Java tutorial
package ch.cyberduck.ui.cocoa.controller; /* * Copyright (c) 2002-2016 iterate GmbH. All rights reserved. * https://cyberduck.io/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ import ch.cyberduck.binding.AbstractTableDelegate; import ch.cyberduck.binding.Action; import ch.cyberduck.binding.Delegate; import ch.cyberduck.binding.HyperlinkAttributedStringFactory; import ch.cyberduck.binding.Outlet; import ch.cyberduck.binding.WindowController; import ch.cyberduck.binding.application.*; import ch.cyberduck.binding.foundation.NSArray; import ch.cyberduck.binding.foundation.NSIndexSet; import ch.cyberduck.binding.foundation.NSNotification; import ch.cyberduck.binding.foundation.NSNotificationCenter; import ch.cyberduck.binding.foundation.NSRange; import ch.cyberduck.core.AbstractCollectionListener; import ch.cyberduck.core.Collection; import ch.cyberduck.core.Host; import ch.cyberduck.core.LocalFactory; import ch.cyberduck.core.LocaleFactory; import ch.cyberduck.core.Path; import ch.cyberduck.core.PathCache; import ch.cyberduck.core.SessionPoolFactory; import ch.cyberduck.core.TransferCollection; import ch.cyberduck.core.exception.AccessDeniedException; import ch.cyberduck.core.io.BandwidthThrottle; import ch.cyberduck.core.local.ApplicationLauncherFactory; import ch.cyberduck.core.local.LocalTrashFactory; import ch.cyberduck.core.local.RevealService; import ch.cyberduck.core.local.RevealServiceFactory; import ch.cyberduck.core.pasteboard.PathPasteboard; import ch.cyberduck.core.pasteboard.PathPasteboardFactory; import ch.cyberduck.core.pool.SessionPool; import ch.cyberduck.core.preferences.Preferences; import ch.cyberduck.core.preferences.PreferencesFactory; import ch.cyberduck.core.resources.IconCacheFactory; import ch.cyberduck.core.threading.BackgroundAction; import ch.cyberduck.core.threading.ControllerMainAction; import ch.cyberduck.core.threading.DefaultMainAction; import ch.cyberduck.core.threading.TransferBackgroundAction; import ch.cyberduck.core.threading.TransferCollectionBackgroundAction; import ch.cyberduck.core.threading.WindowMainAction; import ch.cyberduck.core.transfer.DownloadTransfer; import ch.cyberduck.core.transfer.Transfer; import ch.cyberduck.core.transfer.TransferCallback; import ch.cyberduck.core.transfer.TransferItem; import ch.cyberduck.core.transfer.TransferListener; import ch.cyberduck.core.transfer.TransferOptions; import ch.cyberduck.core.transfer.TransferProgress; import ch.cyberduck.core.transfer.TransferSpeedometer; import ch.cyberduck.ui.browser.DownloadDirectoryFinder; import ch.cyberduck.ui.cocoa.datasource.TransferTableDataSource; import ch.cyberduck.ui.cocoa.delegate.AbstractMenuDelegate; import ch.cyberduck.ui.cocoa.toolbar.TransferToolbarFactory; import ch.cyberduck.ui.cocoa.toolbar.TransferToolbarValidator; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.rococoa.Foundation; import org.rococoa.ID; import org.rococoa.Rococoa; import org.rococoa.Selector; import org.rococoa.cocoa.CGFloat; import org.rococoa.cocoa.foundation.NSInteger; import org.rococoa.cocoa.foundation.NSSize; import org.rococoa.cocoa.foundation.NSUInteger; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; public final class TransferController extends WindowController implements TransferListener, NSToolbar.Delegate, NSMenu.Validation { private static final Logger log = Logger.getLogger(TransferController.class); private final TransferToolbarValidator toolbarValidator = new TransferToolbarValidator(this); private final TransferToolbarFactory toolbarFactory = new TransferToolbarFactory(this); private final NSNotificationCenter notificationCenter = NSNotificationCenter.defaultCenter(); private final Preferences preferences = PreferencesFactory.get(); private final TransferCollection collection = TransferCollection.defaultCollection(); private final TableColumnFactory tableColumnsFactory = new TableColumnFactory(); private TranscriptController transcript; private final BandwidthMenuDelegate bandwidthMenuDelegate = new BandwidthMenuDelegate(); @Outlet private NSProgressIndicator transferSpinner; @Outlet private NSToolbar toolbar; @Outlet private NSTextField urlField; @Outlet private NSTextField localField; @Outlet private NSTextField localLabel; @Outlet private NSImageView iconView; @Outlet private NSTextField filterField; @Outlet private NSDrawer logDrawer; @Outlet private NSTableView transferTable; @Delegate private TransferTableDataSource transferTableModel; @Delegate private AbstractTableDelegate<Transfer> transferTableDelegate; public TransferController() { collection.addListener(new AbstractCollectionListener<Transfer>() { @Override public void collectionLoaded() { invoke(new ControllerMainAction(TransferController.this) { @Override public void run() { reload(); } }); } @Override public void collectionItemAdded(final Transfer item) { invoke(new ControllerMainAction(TransferController.this) { @Override public void run() { reload(); } }); } @Override public void collectionItemRemoved(final Transfer item) { invoke(new ControllerMainAction(TransferController.this) { @Override public void run() { reload(); } }); } }); } @Override public void awakeFromNib() { this.toolbar = NSToolbar.toolbarWithIdentifier("Transfer Toolbar"); this.toolbar.setDelegate(this.id()); this.toolbar.setAllowsUserCustomization(true); this.toolbar.setAutosavesConfiguration(true); this.toolbar.setDisplayMode(NSToolbar.NSToolbarDisplayModeLabelOnly); this.window.setToolbar(toolbar); if (!collection.isLoaded()) { transferSpinner.startAnimation(null); } collection.addListener(new AbstractCollectionListener<Transfer>() { @Override public void collectionLoaded() { invoke(new WindowMainAction(TransferController.this) { @Override public void run() { transferSpinner.stopAnimation(null); transferTable.setGridStyleMask(NSTableView.NSTableViewSolidHorizontalGridLineMask); } }); } }); if (collection.isLoaded()) { transferSpinner.stopAnimation(null); transferTable.setGridStyleMask(NSTableView.NSTableViewSolidHorizontalGridLineMask); } super.awakeFromNib(); } @Override public void setWindow(NSWindow window) { window.setFrameAutosaveName("Transfers"); window.setContentMinSize(new NSSize(400d, 150d)); window.setMovableByWindowBackground(true); window.setTitle(LocaleFactory.localizedString("Transfers")); if (window.respondsToSelector(Foundation.selector("setTabbingIdentifier:"))) { window.setTabbingIdentifier(preferences.getProperty("queue.window.tabbing.identifier")); } super.setWindow(window); } @Override public boolean isSingleton() { return true; } @Override public void windowDidBecomeKey(NSNotification notification) { this.updateHighlight(); } @Override public void windowDidResignKey(NSNotification notification) { this.updateHighlight(); } @Override public void windowDidBecomeMain(NSNotification notification) { this.updateHighlight(); } @Override public void windowDidResignMain(NSNotification notification) { this.updateHighlight(); } public void setUrlField(NSTextField urlField) { this.urlField = urlField; this.urlField.setAllowsEditingTextAttributes(true); this.urlField.setSelectable(true); } public void setLocalField(NSTextField localField) { this.localField = localField; this.localField.setAllowsEditingTextAttributes(true); this.localField.setSelectable(true); } public void setLocalLabel(NSTextField localLabel) { this.localLabel = localLabel; this.localLabel.setStringValue(LocaleFactory.localizedString("Local File:", "Transfer")); } public void setIconView(final NSImageView iconView) { this.iconView = iconView; } @Action public void connectionsPopupChanged(final NSMenuItem sender) { final Integer connections = Integer.valueOf(sender.representedObject()); preferences.setProperty("queue.connections.limit", connections); } public NSTextField getFilterField() { return filterField; } public void setFilterField(NSTextField filterField) { this.filterField = filterField; notificationCenter.addObserver(this.id(), Foundation.selector("filterFieldTextDidChange:"), NSControl.NSControlTextDidChangeNotification, this.filterField); } public void filterFieldTextDidChange(NSNotification notification) { transferTableModel.setFilter(filterField.stringValue()); this.reload(); } public void setTransferSpinner(NSProgressIndicator transferSpinner) { this.transferSpinner = transferSpinner; } /** * Change focus to filter field * * @param sender Search field */ @Action public void searchButtonClicked(final ID sender) { window.makeFirstResponder(this.filterField); } @Action public void drawerDidOpen(final NSNotification notification) { preferences.setProperty("queue.transcript.open", true); } @Action public void drawerDidClose(final NSNotification notification) { preferences.setProperty("queue.transcript.open", false); transcript.clear(); } public NSSize drawerWillResizeContents_toSize(final NSDrawer sender, final NSSize contentSize) { return contentSize; } public void setLogDrawer(NSDrawer drawer) { this.logDrawer = drawer; this.transcript = new TranscriptController() { @Override public boolean isOpen() { return logDrawer.state() == NSDrawer.OpenState; } }; this.logDrawer.setContentView(this.transcript.getLogView()); this.logDrawer.setDelegate(this.id()); } public void toggleLogDrawer(final ID sender) { this.logDrawer.toggle(sender); } @Action public void bandwidthPopupChanged(NSMenuItem sender) { final NSIndexSet selected = transferTable.selectedRowIndexes(); final float bandwidth = Float.valueOf(sender.representedObject()); for (NSUInteger index = selected.firstIndex(); !index.equals(NSIndexSet.NSNotFound); index = selected .indexGreaterThanIndex(index)) { final Transfer transfer = collection.get(index.intValue()); transfer.setBandwidth(bandwidth); if (transfer.isRunning()) { // Find matching background task for (BackgroundAction action : registry.toArray(new BackgroundAction[registry.size()])) { if (action instanceof TransferBackgroundAction) { final TransferBackgroundAction t = (TransferBackgroundAction) action; if (t.getTransfer().equals(transfer)) { final TransferSpeedometer meter = t.getMeter(); meter.reset(); } } } } } } @Override protected String getBundleName() { return "Transfer"; } @Override public void invalidate() { toolbar.setDelegate(null); transferTableModel.invalidate(); super.invalidate(); } public void setQueueTable(NSTableView view) { this.transferTable = view; this.transferTable.setRowHeight(new CGFloat(82)); { NSTableColumn c = tableColumnsFactory.create(TransferTableDataSource.Column.progress.name()); c.setMinWidth(80f); c.setWidth(300f); c.setResizingMask(NSTableColumn.NSTableColumnAutoresizingMask); this.transferTable.addTableColumn(c); } this.transferTable.setDataSource((transferTableModel = new TransferTableDataSource()).id()); this.transferTable.setDelegate((transferTableDelegate = new AbstractTableDelegate<Transfer>( transferTable.tableColumnWithIdentifier(TransferTableDataSource.Column.progress.name())) { @Override public String tooltip(final Transfer t) { return t.getName(); } @Override public void enterKeyPressed(final ID sender) { this.tableRowDoubleClicked(sender); } @Override public void deleteKeyPressed(final ID sender) { deleteButtonClicked(sender); } @Override public void tableColumnClicked(NSTableView view, NSTableColumn tableColumn) { // } @Override public void tableRowDoubleClicked(final ID sender) { reloadButtonClicked(sender); } @Override public void selectionIsChanging(final NSNotification notification) { updateHighlight(); } @Override public void selectionDidChange(final NSNotification notification) { updateHighlight(); updateSelection(); transferTable.noteHeightOfRowsWithIndexesChanged(NSIndexSet.indexSetWithIndexesInRange( NSRange.NSMakeRange(new NSUInteger(0), new NSUInteger(transferTable.numberOfRows())))); } public NSView tableView_viewForTableColumn_row(final NSTableView view, final NSTableColumn column, final NSInteger row) { final ProgressController controller = transferTableModel.getController(row.intValue()); return controller.view(); } @Override public boolean isTypeSelectSupported() { return true; } public String tableView_typeSelectStringForTableColumn_row(final NSTableView view, final NSTableColumn column, final NSInteger row) { return transferTableModel.getSource().get(row.intValue()).getName(); } }).id()); // receive drag events from types // in fact we are not interested in file promises, but because the browser model can only initiate // a drag with tableView.dragPromisedFilesOfTypes(), we listens for those events // and then use the private pasteboard instead. this.transferTable.registerForDraggedTypes(NSArray.arrayWithObjects(NSPasteboard.StringPboardType, // Accept file promises made myself NSPasteboard.FilesPromisePboardType)); // No grid lines until list is loaded this.transferTable.setGridStyleMask(NSTableView.NSTableViewGridNone); // Set sselection properties this.transferTable.setAllowsMultipleSelection(true); this.transferTable.setAllowsEmptySelection(true); this.transferTable.setAllowsColumnReordering(false); this.transferTable.sizeToFit(); } public NSTableView getTransferTable() { return transferTable; } public TransferTableDataSource getTransferTableModel() { return transferTableModel; } /** * Update highlighted rows */ private void updateHighlight() { final boolean main = window().isMainWindow(); final NSIndexSet set = transferTable.selectedRowIndexes(); for (int i = 0; i < transferTableModel.numberOfRowsInTableView(transferTable).intValue(); i++) { boolean highlighted = set.containsIndex(new NSUInteger(i)) && main; if (transferTableModel.isHighlighted(i) == highlighted) { continue; } transferTableModel.setHighlighted(i, highlighted); } } /** * Update labels from selection */ private void updateSelection() { this.updateLabels(); this.updateIcon(); toolbar.validateVisibleItems(); } private void updateLabels() { final int selected = transferTable.numberOfSelectedRows().intValue(); if (1 == selected) { final Transfer transfer = transferTableModel.getSource().get(transferTable.selectedRow().intValue()); // Draw text fields at the bottom final String remote = transfer.getRemote().getUrl(); urlField.setAttributedStringValue(HyperlinkAttributedStringFactory.create(remote)); final String local = transfer.getLocal(); if (local != null) { localField.setAttributedStringValue( HyperlinkAttributedStringFactory.create(local, LocalFactory.get(local))); } else { localField.setStringValue(StringUtils.EMPTY); } } else { urlField.setStringValue(StringUtils.EMPTY); localField.setStringValue(StringUtils.EMPTY); } } private void updateIcon() { final int selected = transferTable.numberOfSelectedRows().intValue(); if (1 == selected) { final Transfer transfer = transferTableModel.getSource().get(transferTable.selectedRow().intValue()); // Draw file type icon if (transfer.getRoots().size() == 1) { if (transfer.getLocal() != null) { iconView.setImage(IconCacheFactory.<NSImage>get().fileIcon(transfer.getRoot().local, 32)); } else { iconView.setImage(IconCacheFactory.<NSImage>get().fileIcon(transfer.getRoot().remote, 32)); } } else { iconView.setImage(IconCacheFactory.<NSImage>get().iconNamed("NSMultipleDocuments", 32)); } } else { iconView.setImage(null); } } private void reload() { while (transferTable.subviews().count().intValue() > 0) { (Rococoa.cast(transferTable.subviews().lastObject(), NSView.class)) .removeFromSuperviewWithoutNeedingDisplay(); } transferTable.reloadData(); this.updateHighlight(); this.updateSelection(); } /** * Add this item to the list; select it and scroll the view to make it visible * * @param transfer Transfer */ public void add(final Transfer transfer, final TransferBackgroundAction action) { if (collection.size() > preferences.getInteger("queue.size.warn")) { final NSAlert alert = NSAlert.alert(TransferToolbarFactory.TransferToolbarItem.cleanup.label(), //title LocaleFactory.localizedString("Remove completed transfers from list."), // message TransferToolbarFactory.TransferToolbarItem.cleanup.label(), // defaultbutton LocaleFactory.localizedString("Cancel"), // alternate button null //other button ); alert.setShowsSuppressionButton(true); alert.suppressionButton().setTitle(LocaleFactory.localizedString("Don't ask again", "Configuration")); this.alert(alert, new SheetCallback() { @Override public void callback(int returncode) { if (alert.suppressionButton().state() == NSCell.NSOnState) { // Never show again. preferences.setProperty("queue.size.warn", Integer.MAX_VALUE); } if (returncode == DEFAULT_OPTION) { clearButtonClicked(null); } add(transfer); background(action); } }); } else { this.add(transfer); this.background(action); } } private void add(final Transfer transfer) { collection.add(transfer); final int row = collection.size() - 1; final NSInteger index = new NSInteger(row); transferTable.selectRowIndexes(NSIndexSet.indexSetWithIndex(index), false); transferTable.scrollRowToVisible(index); } /** * @param transfer Transfer */ public void transferDidStart(final Transfer transfer) { final ProgressController progress = transferTableModel.getController(transfer); progress.transferDidStart(transfer); this.invoke(new DefaultMainAction() { @Override public void run() { toolbar.validateVisibleItems(); } }); } @Override public void transferDidStop(final Transfer transfer) { final ProgressController progress = transferTableModel.getController(transfer); progress.transferDidStop(transfer); this.invoke(new DefaultMainAction() { @Override public void run() { toolbar.validateVisibleItems(); } }); } @Override public void transferDidProgress(final Transfer transfer, final TransferProgress status) { final ProgressController progress = transferTableModel.getController(transfer); progress.transferDidProgress(transfer, status); } /** * @param transfer Transfer */ public void start(final Transfer transfer, final TransferOptions options) { this.start(transfer, options, new TransferCallback() { @Override public void complete(final Transfer transfer) { // } }); } /** * @param transfer Transfer */ public void start(final Transfer transfer, final TransferOptions options, final TransferCallback callback) { final ProgressController progress = transferTableModel.getController(transfer); final PathCache cache = new PathCache(preferences.getInteger("transfer.cache.size")); final Host source = transfer.getSource(); final Host destination = transfer.getDestination(); final TransferBackgroundAction action = new TransferCollectionBackgroundAction(this, null == source ? SessionPool.DISCONNECTED : SessionPoolFactory.create(this, cache, source), null == destination ? SessionPool.DISCONNECTED : SessionPoolFactory.create(this, cache, destination), this, progress, transfer.withCache(cache), options) { @Override public void init() { super.init(); if (preferences.getBoolean("queue.window.open.transfer.start")) { window.makeKeyAndOrderFront(null); } } @Override public void finish() { super.finish(); if (transfer.isComplete()) { callback.complete(transfer); } } @Override public void cleanup() { super.cleanup(); if (transfer.isReset() && transfer.isComplete()) { if (preferences.getBoolean("queue.window.open.transfer.stop")) { if (!(collection.numberOfRunningTransfers() > 0)) { window.orderOut(null); } } } } }; if (!collection.contains(transfer)) { this.add(transfer, action); } else { this.background(action); } } @Override public void log(final Type request, final String message) { transcript.log(request, message); } @Override public NSToolbarItem toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar(final NSToolbar toolbar, final String identifier, final boolean flag) { return toolbarFactory.create(identifier); } @Action public void paste(final ID sender) { for (PathPasteboard pasteboard : PathPasteboardFactory.allPasteboards()) { if (pasteboard.isEmpty()) { continue; } if (log.isDebugEnabled()) { log.debug("Paste download transfer from pasteboard"); } final List<TransferItem> downloads = new ArrayList<TransferItem>(); for (Path download : pasteboard) { downloads.add(new TransferItem(download, LocalFactory .get(new DownloadDirectoryFinder().find(pasteboard.getBookmark()), download.getName()))); } this.add(new DownloadTransfer(pasteboard.getBookmark(), downloads)); pasteboard.clear(); } } @Action public void stopButtonClicked(final ID sender) { final NSIndexSet selected = transferTable.selectedRowIndexes(); for (NSUInteger index = selected.firstIndex(); !index.equals(NSIndexSet.NSNotFound); index = selected .indexGreaterThanIndex(index)) { final Transfer transfer = transferTableModel.getSource().get(index.intValue()); if (transfer.isRunning()) { // Find matching background task for (BackgroundAction action : registry.toArray(new BackgroundAction[registry.size()])) { if (action instanceof TransferBackgroundAction) { final TransferBackgroundAction t = (TransferBackgroundAction) action; if (t.getTransfer().equals(transfer)) { t.cancel(); } } } } } } @Action public void stopAllButtonClicked(final ID sender) { final Collection<Transfer> transfers = transferTableModel.getSource(); for (final Transfer transfer : transfers) { if (transfer.isRunning()) { // Find matching background task for (BackgroundAction action : registry.toArray(new BackgroundAction[registry.size()])) { if (action instanceof TransferBackgroundAction) { final TransferBackgroundAction t = (TransferBackgroundAction) action; if (t.getTransfer().equals(transfer)) { t.cancel(); } } } } } } @Action public void resumeButtonClicked(final ID sender) { final NSIndexSet selected = transferTable.selectedRowIndexes(); for (NSUInteger index = selected.firstIndex(); !index.equals(NSIndexSet.NSNotFound); index = selected .indexGreaterThanIndex(index)) { final Collection<Transfer> transfers = transferTableModel.getSource(); final Transfer transfer = transfers.get(index.intValue()); if (!transfer.isRunning()) { final TransferOptions options = new TransferOptions(); options.resumeRequested = true; options.reloadRequested = false; this.start(transfer, options); } } } @Action public void reloadButtonClicked(final ID sender) { final NSIndexSet selected = transferTable.selectedRowIndexes(); for (NSUInteger index = selected.firstIndex(); !index.equals(NSIndexSet.NSNotFound); index = selected .indexGreaterThanIndex(index)) { final Collection<Transfer> transfers = transferTableModel.getSource(); final Transfer transfer = transfers.get(index.intValue()); if (!transfer.isRunning()) { final TransferOptions options = new TransferOptions(); options.resumeRequested = false; options.reloadRequested = true; this.start(transfer, options); } } } @Action public void openButtonClicked(final ID sender) { if (transferTable.numberOfSelectedRows().intValue() == 1) { final Transfer transfer = transferTableModel.getSource().get(transferTable.selectedRow().intValue()); for (TransferItem l : transfer.getRoots()) { ApplicationLauncherFactory.get().open(l.local); } } } @Action public void revealButtonClicked(final ID sender) { final NSIndexSet selected = transferTable.selectedRowIndexes(); final Collection<Transfer> transfers = transferTableModel.getSource(); final RevealService reveal = RevealServiceFactory.get(); for (NSUInteger index = selected.firstIndex(); !index.equals(NSIndexSet.NSNotFound); index = selected .indexGreaterThanIndex(index)) { final Transfer transfer = transfers.get(index.intValue()); for (TransferItem l : transfer.getRoots()) { reveal.reveal(l.local); } } } @Action public void deleteButtonClicked(final ID sender) { final NSIndexSet selected = transferTable.selectedRowIndexes(); final Collection<Transfer> transfers = transferTableModel.getSource(); int i = 0; final List<Transfer> remove = new ArrayList<Transfer>(); for (NSUInteger index = selected.firstIndex(); !index.equals(NSIndexSet.NSNotFound); index = selected .indexGreaterThanIndex(index)) { final Transfer t = transfers.get(index.intValue() - i); if (!t.isRunning()) { remove.add(t); } } collection.removeAll(remove); collection.save(); } @Action public void clearButtonClicked(final ID sender) { collection.removeIf(Transfer::isComplete); collection.save(); } @Action public void trashButtonClicked(final ID sender) { final NSIndexSet selected = transferTable.selectedRowIndexes(); final Collection<Transfer> transfers = transferTableModel.getSource(); for (NSUInteger index = selected.firstIndex(); !index.equals(NSIndexSet.NSNotFound); index = selected .indexGreaterThanIndex(index)) { final Transfer transfer = transfers.get(index.intValue()); if (!transfer.isRunning()) { for (TransferItem l : transfer.getRoots()) { try { LocalTrashFactory.get().trash(l.local); } catch (AccessDeniedException e) { log.warn(String.format("Failure trashing file %s %s", l.local, e.getMessage())); } } } } this.updateIcon(); } @Action public void printDocument(final ID sender) { this.print(transferTable); } /** * NSToolbar.Delegate * * @param toolbar Window toolbar */ @Override public NSArray toolbarDefaultItemIdentifiers(final NSToolbar toolbar) { return toolbarFactory.getDefault(); } /** * NSToolbar.Delegate * * @param toolbar Window toolbar */ @Override public NSArray toolbarAllowedItemIdentifiers(final NSToolbar toolbar) { return toolbarFactory.getAllowed(); } @Override public NSArray toolbarSelectableItemIdentifiers(final NSToolbar toolbar) { return NSArray.array(); } /** * @param item Menu item * @return True if enabled */ @Override public boolean validateMenuItem(final NSMenuItem item) { final Selector action = item.action(); if (action.equals(Foundation.selector("paste:"))) { final List<PathPasteboard> pasteboards = PathPasteboardFactory.allPasteboards(); if (pasteboards.size() == 1) { for (PathPasteboard pasteboard : pasteboards) { if (pasteboard.size() == 1) { item.setTitle(MessageFormat.format(LocaleFactory.localizedString("Paste {0}"), pasteboard.get(0).getName())); } else { item.setTitle(MessageFormat.format(LocaleFactory.localizedString("Paste {0}"), MessageFormat.format(LocaleFactory.localizedString("{0} Files"), String.valueOf(pasteboard.size())) + ")")); } } } else { item.setTitle(LocaleFactory.localizedString("Paste")); } } return toolbarValidator.validate(action); } /** * @param item Toolbar item */ @Override @Action public boolean validateToolbarItem(final NSToolbarItem item) { return toolbarValidator.validate(item); } public AbstractMenuDelegate getBandwidthMenuDelegate() { return bandwidthMenuDelegate; } private class BandwidthMenuDelegate extends AbstractMenuDelegate { @Override public NSInteger numberOfItemsInMenu(final NSMenu menu) { return new NSInteger( new StringTokenizer(preferences.getProperty("queue.bandwidth.options"), ",").countTokens() + 2); } @Override public boolean menuUpdateItemAtIndex(final NSMenu menu, final NSMenuItem item, final NSInteger i, final boolean cancel) { if (item.representedObject() != null) { final int selected = transferTable.numberOfSelectedRows().intValue(); final int bytes = Integer.valueOf(item.representedObject()); final NSIndexSet iterator = transferTable.selectedRowIndexes(); for (NSUInteger index = iterator.firstIndex(); !index .equals(NSIndexSet.NSNotFound); index = iterator.indexGreaterThanIndex(index)) { final Transfer transfer = collection.get(index.intValue()); if (BandwidthThrottle.UNLIMITED == transfer.getBandwidth().getRate()) { if (BandwidthThrottle.UNLIMITED == bytes) { item.setState(selected > 1 ? NSCell.NSMixedState : NSCell.NSOnState); break; } else { item.setState(NSCell.NSOffState); } } else { final int bandwidth = (int) transfer.getBandwidth().getRate(); if (bytes == bandwidth) { item.setState(selected > 1 ? NSCell.NSMixedState : NSCell.NSOnState); break; } else { item.setState(NSCell.NSOffState); } } } } return super.menuUpdateItemAtIndex(menu, item, i, cancel); } @Override public Selector getDefaultAction() { return Foundation.selector("bandwidthPopupChanged:"); } } }