Java tutorial
/* * Copyright 2004 - 2008 Christian Sprajc. All rights reserved. * * This file is part of PowerFolder. * * PowerFolder 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. * * PowerFolder 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. * * You should have received a copy of the GNU General Public License * along with PowerFolder. If not, see <http://www.gnu.org/licenses/>. * * $Id: ExpandableFolderView.java 5495 2008-10-24 04:59:13Z harry $ */ package de.dal33t.powerfolder.ui.folders; import static de.dal33t.powerfolder.disk.FolderStatistic.UNKNOWN_SYNC_STATUS; import java.awt.Cursor; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.nio.file.Paths; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.TimerTask; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.factories.Borders; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import de.dal33t.powerfolder.ConfigurationEntry; import de.dal33t.powerfolder.Controller; import de.dal33t.powerfolder.PreferencesEntry; import de.dal33t.powerfolder.clientserver.RemoteCallException; import de.dal33t.powerfolder.clientserver.ServerClient; import de.dal33t.powerfolder.disk.Folder; import de.dal33t.powerfolder.disk.FolderStatistic; import de.dal33t.powerfolder.disk.problem.ResolvableProblem; import de.dal33t.powerfolder.event.FolderEvent; import de.dal33t.powerfolder.event.FolderListener; import de.dal33t.powerfolder.event.FolderMembershipEvent; import de.dal33t.powerfolder.event.FolderMembershipListener; import de.dal33t.powerfolder.event.FolderRepositoryEvent; import de.dal33t.powerfolder.event.FolderRepositoryListener; import de.dal33t.powerfolder.event.ListenerSupportFactory; import de.dal33t.powerfolder.event.NodeManagerAdapter; import de.dal33t.powerfolder.event.NodeManagerEvent; import de.dal33t.powerfolder.event.TransferManagerAdapter; import de.dal33t.powerfolder.event.TransferManagerEvent; import de.dal33t.powerfolder.light.FileInfo; import de.dal33t.powerfolder.light.FolderInfo; import de.dal33t.powerfolder.security.FolderPermission; import de.dal33t.powerfolder.security.FolderRemovePermission; import de.dal33t.powerfolder.security.Permission; import de.dal33t.powerfolder.transfer.DownloadManager; import de.dal33t.powerfolder.transfer.TransferManager; import de.dal33t.powerfolder.ui.ExpandableView; import de.dal33t.powerfolder.ui.PFUIComponent; import de.dal33t.powerfolder.ui.WikiLinks; import de.dal33t.powerfolder.ui.action.BaseAction; import de.dal33t.powerfolder.ui.dialog.DialogFactory; import de.dal33t.powerfolder.ui.dialog.FolderRemoveDialog; import de.dal33t.powerfolder.ui.dialog.GenericDialogType; import de.dal33t.powerfolder.ui.dialog.PreviewToJoinDialog; import de.dal33t.powerfolder.ui.event.ExpansionEvent; import de.dal33t.powerfolder.ui.event.ExpansionListener; import de.dal33t.powerfolder.ui.folders.ExpandableFolderModel.Type; import de.dal33t.powerfolder.ui.information.folder.settings.SettingsTab; import de.dal33t.powerfolder.ui.util.CursorUtils; import de.dal33t.powerfolder.ui.util.DelayedUpdater; import de.dal33t.powerfolder.ui.util.Help; import de.dal33t.powerfolder.ui.util.Icons; import de.dal33t.powerfolder.ui.util.SyncIconButtonMini; import de.dal33t.powerfolder.ui.widget.ActionLabel; import de.dal33t.powerfolder.ui.widget.ActivityVisualizationWorker; import de.dal33t.powerfolder.ui.widget.JButtonMini; import de.dal33t.powerfolder.ui.widget.ResizingJLabel; import de.dal33t.powerfolder.ui.wizard.PFWizard; import de.dal33t.powerfolder.util.BrowserLauncher; import de.dal33t.powerfolder.util.BrowserLauncher.URLProducer; import de.dal33t.powerfolder.util.DateUtil; import de.dal33t.powerfolder.util.Format; import de.dal33t.powerfolder.util.PathUtils; import de.dal33t.powerfolder.util.StringUtils; import de.dal33t.powerfolder.util.Translation; import de.dal33t.powerfolder.util.WebDAV; import de.dal33t.powerfolder.util.os.OSUtil; /** * Class to render expandable view of a folder. */ public class ExpandableFolderView extends PFUIComponent implements ExpandableView { private FolderInfo folderInfo; private Folder folder; private Type type; private boolean online; private boolean admin; private final AtomicBoolean focus = new AtomicBoolean(); private final AtomicBoolean showing100Sync = new AtomicBoolean(); private ResizingJLabel nameLabel; private JButtonMini openSettingsInformationButton; private JButtonMini openFilesInformationButton; private JButtonMini inviteButton; private ActionLabel membersLabel; private ActionLabel upperSyncPercentageLabel; private JPanel uiComponent; private JPanel borderPanel; private JPanel lowerOuterPanel; private AtomicBoolean expanded; private AtomicBoolean mouseOver; private ActionLabel filesLabel; private ActionLabel deletedFilesLabel; private ActionLabel transferModeLabel; private ActionLabel localDirectoryLabel; private JLabel syncPercentLabel; private ActionLabel syncDateLabel; private JLabel localSizeLabel; private JLabel totalSizeLabel; // private ActionLabel filesAvailableLabel; private JPanel upperPanel; private JButtonMini primaryButton; private SyncIconButtonMini upperSyncFolderButton; private JButtonMini lowerSyncFolderButton; private MyFolderListener myFolderListener; private MyFolderMembershipListener myFolderMembershipListener; // private MyServerClientListener myServerClientListener; private MyTransferManagerListener myTransferManagerListener; private MyFolderRepositoryListener myFolderRepositoryListener; private MyNodeManagerListener myNodeManagerListener; private ExpansionListener listenerSupport; private OnlineStorageComponent osComponent; private ServerClient serverClient; private MySyncFolderAction syncFolderAction; private MyOpenFilesInformationAction openFilesInformationAction; private MyOpenSettingsInformationAction openSettingsInformationAction; private MyInviteAction inviteAction; private MyOpenMembersInformationAction openMembersInformationAction; private MyMostRecentChangesAction mostRecentChangesAction; private MyClearCompletedDownloadsAction clearCompletedDownloadsAction; private MyOpenExplorerAction openExplorerAction; private FolderRemoveAction removeFolderLocalAction; private FolderOnlineRemoveAction removeFolderOnlineAction; private BackupOnlineStorageAction backupOnlineStorageAction; private StopOnlineStorageAction stopOnlineStorageAction; private WebdavAction webdavAction; private WebViewAction webViewAction; // Performance stuff private DelayedUpdater syncUpdater; private DelayedUpdater folderUpdater; private DelayedUpdater folderDetailsUpdater; private String webDAVURL; private String ownerDisplayname; private String removeLabel; /** * Constructor * * @param controller * @param folderInfo */ public ExpandableFolderView(Controller controller, FolderInfo folderInfo) { super(controller); serverClient = controller.getOSClient(); this.folderInfo = folderInfo; listenerSupport = ListenerSupportFactory.createListenerSupport(ExpansionListener.class); admin = getController().getOSClient().getAccount().hasAdminPermission(folderInfo); initComponent(); buildUI(); } /** * Set the folder for this view. May be null if online storage only, so * update visual components if null --> folder or folder --> null * * @param folderModel */ public void configure(ExpandableFolderModel folderModel) { boolean changed = false; Folder beanFolder = folderModel.getFolder(); FolderInfo beanFolderInfo = folderModel.getFolderInfo().intern(); Type beanType = folderModel.getType(); boolean beanOnline = folderModel.isOnline(); if (beanFolder != null && folder == null) { changed = true; } else if (beanFolder == null && folder != null) { changed = true; } else if (beanFolder != null && !folder.equals(beanFolder)) { changed = true; } else if (!folderInfo.getName().equals(beanFolderInfo.getName())) { changed = true; } else if (beanType != type) { changed = true; } else if (beanOnline ^ online) { changed = true; } if (!changed) { return; } // Something changed - change details. unregisterFolderListeners(); type = beanType; folder = beanFolder; folderInfo = beanFolderInfo; online = beanOnline; osComponent.setFolder(beanFolder); updateStatsDetails(); updateNumberOfFiles(); updateTransferMode(); updateFolderMembershipDetails(); updateIconAndOS(); updateLocalButtons(); updateNameLabel(); updatePermissions(); updateDeletedFiles(); registerFolderListeners(); } /** * Expand this view if collapsed. */ public void expand() { // Only actually expand local folders in advanced mode, // but we still need to fire the reset to clear others' focus. if (PreferencesEntry.EXPERT_MODE.getValueBoolean(getController()) && type == Type.Local) { expanded.set(true); if (PreferencesEntry.BEGINNER_MODE.getValueBoolean(getController()) && !PreferencesEntry.EXPERT_MODE.getValueBoolean(getController())) { upperPanel.setToolTipText(Translation.getTranslation("exp_folder_view.remove")); } else { upperPanel.setToolTipText(Translation.getTranslation("exp_folder_view.collapse")); } updateNameLabel(); lowerOuterPanel.setVisible(true); } listenerSupport.resetAllButSource(new ExpansionEvent(this)); } /** * Collapse this view if expanded. */ public void collapse() { expanded.set(false); if (PreferencesEntry.BEGINNER_MODE.getValueBoolean(getController()) && !PreferencesEntry.EXPERT_MODE.getValueBoolean(getController())) { upperPanel.setToolTipText(Translation.getTranslation("exp_folder_view.create")); } else { upperPanel.setToolTipText(Translation.getTranslation("exp_folder_view.expand")); } updateNameLabel(); lowerOuterPanel.setVisible(false); } public void setFocus(boolean focus) { this.focus.set(focus); updateBorderPanel(); } public boolean hasFocus() { return focus.get(); } private void updateBorderPanel() { if (focus.get()) { borderPanel.setBorder(BorderFactory.createEtchedBorder()); } else { borderPanel.setBorder(BorderFactory.createEmptyBorder()); } } private void retrieveAdditionalInfosFromServer() { SwingWorker worker = new SwingWorker() { protected Object doInBackground() throws Exception { createWebDAVURL(); retrieveOwnerDisplayname(); return null; } }; worker.execute(); } private synchronized String createWebDAVURL() { if (!serverClient.isConnected() || !serverClient.isLoggedIn()) { return null; } if (webDAVURL == null) { webDAVURL = serverClient.getFolderService().getWebDAVURL(folderInfo); if (webDAVURL == null) { // Don't fetch again. It's simply not available. webDAVURL = ""; } } return webDAVURL; } private String retrieveOwnerDisplayname() { if (!serverClient.isConnected() || !serverClient.isLoggedIn()) { return null; } if (serverClient.getAccount().hasOwnerPermission(folderInfo)) { return null; } if (ownerDisplayname == null) { try { ownerDisplayname = serverClient.getFolderService().getOwnerDisplayname(folderInfo); } catch (RemoteCallException e) { logFine("Unsupported/Old server. Not able to retrieve owner name of " + folderInfo.getName() + ". " + e); } if (ownerDisplayname == null) { // Don't fetch again. It's simply not available. ownerDisplayname = ""; } else { if (isFine()) { logFine("Owner of " + folderInfo.getName() + ": " + ownerDisplayname); } updateNameLabel(); } } return ownerDisplayname; } /** * Gets the ui component, building if required. * * @return */ public JPanel getUIComponent() { return uiComponent; } /** * Builds the ui component. */ private void buildUI() { // Build ui // icon name #-files webdav open FormLayout upperLayout = new FormLayout( // "pref, 3dlu, pref:grow, 3dlu, pref, 3dlu, pref, 3dlu", "pref"); "pref, 3dlu, pref:grow, 3dlu, pref, 3dlu", "pref"); PanelBuilder upperBuilder = new PanelBuilder(upperLayout); CellConstraints cc = new CellConstraints(); updateIconAndOS(); // Primary and upperSyncFolder buttons share the same slot. upperBuilder.add(primaryButton, cc.xy(1, 1)); upperBuilder.add(upperSyncFolderButton, cc.xy(1, 1)); MouseAdapter mca = new MyMouseClickAdapter(); MouseAdapter moa = new MyMouseOverAdapter(); nameLabel = new ResizingJLabel(); upperBuilder.add(nameLabel, cc.xy(3, 1)); nameLabel.addMouseListener(moa); nameLabel.addMouseListener(mca); // Because this is the biggest blank // area where the user might click. upperBuilder.add(upperSyncPercentageLabel.getUIComponent(), cc.xy(5, 1)); // upperBuilder.add(filesAvailableLabel.getUIComponent(), cc.xy(7, 1)); // filesAvailableLabel.getUIComponent().addMouseListener(moa); upperPanel = upperBuilder.getPanel(); upperPanel.setOpaque(false); if (type == Type.Local) { upperPanel.setToolTipText(Translation.getTranslation("exp_folder_view.expand")); } CursorUtils.setHandCursor(upperPanel); upperPanel.addMouseListener(moa); upperPanel.addMouseListener(mca); // Build lower detials with line border. FormLayout lowerLayout; if (getController().isBackupOnly()) { // Skip computers stuff lowerLayout = new FormLayout("3dlu, pref, pref:grow, 3dlu, pref, 3dlu", "pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, pref"); } else { lowerLayout = new FormLayout("3dlu, pref, pref:grow, 3dlu, pref, 3dlu", "pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, pref"); } PanelBuilder lowerBuilder = new PanelBuilder(lowerLayout); int row = 1; lowerBuilder.addSeparator(null, cc.xywh(1, row, 6, 1)); row += 2; lowerBuilder.add(syncDateLabel.getUIComponent(), cc.xy(2, row)); lowerBuilder.add(lowerSyncFolderButton, cc.xy(5, row)); row += 2; lowerBuilder.add(syncPercentLabel, cc.xy(2, row)); lowerBuilder.add(openFilesInformationButton, cc.xy(5, row)); row += 2; lowerBuilder.add(filesLabel.getUIComponent(), cc.xy(2, row)); row += 2; lowerBuilder.add(localSizeLabel, cc.xy(2, row)); row += 2; lowerBuilder.add(totalSizeLabel, cc.xy(2, row)); row += 2; lowerBuilder.add(deletedFilesLabel.getUIComponent(), cc.xy(2, row)); row += 2; lowerBuilder.addSeparator(null, cc.xywh(2, row, 4, 1)); row += 2; // No computers stuff if backup mode. if (getController().isBackupOnly()) { lowerBuilder.add(transferModeLabel.getUIComponent(), cc.xy(2, row)); lowerBuilder.add(openSettingsInformationButton, cc.xy(5, row)); row += 2; lowerBuilder.add(localDirectoryLabel.getUIComponent(), cc.xy(2, row)); } else { if (ConfigurationEntry.MEMBERS_ENABLED.getValueBoolean(getController())) { lowerBuilder.add(membersLabel.getUIComponent(), cc.xy(2, row)); } if (ConfigurationEntry.SERVER_INVITE_ENABLED.getValueBoolean(getController())) { lowerBuilder.add(inviteButton, cc.xy(5, row)); } if (ConfigurationEntry.MEMBERS_ENABLED.getValueBoolean(getController()) || ConfigurationEntry.SERVER_INVITE_ENABLED.getValueBoolean(getController())) { row += 2; lowerBuilder.addSeparator(null, cc.xywh(2, row, 4, 1)); } if (PreferencesEntry.BEGINNER_MODE.getValueBoolean(getController()) && !PreferencesEntry.EXPERT_MODE.getValueBoolean(getController())) { row += 2; lowerBuilder.add(transferModeLabel.getUIComponent(), cc.xy(2, row)); lowerBuilder.add(openSettingsInformationButton, cc.xy(5, row)); row += 2; lowerBuilder.add(localDirectoryLabel.getUIComponent(), cc.xy(2, row)); } } row++; // Just add one. lowerBuilder.add(osComponent.getUIComponent(), cc.xywh(2, row, 4, 1)); JPanel lowerPanel = lowerBuilder.getPanel(); lowerPanel.setOpaque(false); // Build spacer then lower outer with lower panel FormLayout lowerOuterLayout = new FormLayout("pref:grow", "3dlu, pref"); PanelBuilder lowerOuterBuilder = new PanelBuilder(lowerOuterLayout); lowerOuterPanel = lowerOuterBuilder.getPanel(); lowerOuterPanel.setVisible(false); lowerOuterBuilder.add(lowerPanel, cc.xy(1, 2)); // Build border around upper and lower FormLayout borderLayout = new FormLayout("3dlu, pref:grow, 3dlu", "3dlu, pref, pref, 3dlu"); PanelBuilder borderBuilder = new PanelBuilder(borderLayout); borderBuilder.add(upperPanel, cc.xy(2, 2)); JPanel panel = lowerOuterBuilder.getPanel(); panel.setOpaque(false); borderBuilder.add(panel, cc.xy(2, 3)); borderPanel = borderBuilder.getPanel(); borderPanel.setOpaque(false); // Build ui with vertical space before the next one FormLayout outerLayout = new FormLayout("3dlu, pref:grow, 3dlu", "pref, 3dlu"); PanelBuilder outerBuilder = new PanelBuilder(outerLayout); outerBuilder.add(borderPanel, cc.xy(2, 1)); uiComponent = outerBuilder.getPanel(); uiComponent.setOpaque(false); } /** * Initializes the components. */ private void initComponent() { syncUpdater = new DelayedUpdater(getController(), 1000L); folderDetailsUpdater = new DelayedUpdater(getController()); folderUpdater = new DelayedUpdater(getController()); openFilesInformationAction = new MyOpenFilesInformationAction(getController()); inviteAction = new MyInviteAction(getController()); inviteAction.allowWith(FolderPermission.admin(folderInfo)); openSettingsInformationAction = new MyOpenSettingsInformationAction(getController()); openSettingsInformationAction.setEnabled(!getController().isBackupOnly()); MyMoveLocalFolderAction moveLocalFolderAction = new MyMoveLocalFolderAction(getController()); moveLocalFolderAction.setEnabled(!getController().isBackupOnly()); openMembersInformationAction = new MyOpenMembersInformationAction(getController()); mostRecentChangesAction = new MyMostRecentChangesAction(getController()); clearCompletedDownloadsAction = new MyClearCompletedDownloadsAction(getController()); openExplorerAction = new MyOpenExplorerAction(getController()); // Allow to stop local sync even if no folder remove permissions was // given. removeFolderLocalAction = new FolderRemoveAction(getController()); if (admin) { removeLabel = "action_remove_online_folder_admin"; } else { removeLabel = "action_remove_online_folder"; } ; // Don't allow to choose action at all if online folder only. removeFolderOnlineAction = new FolderOnlineRemoveAction(getController()); removeFolderOnlineAction.allowWith(FolderRemovePermission.INSTANCE); backupOnlineStorageAction = new BackupOnlineStorageAction(getController()); stopOnlineStorageAction = new StopOnlineStorageAction(getController()); syncFolderAction = new MySyncFolderAction(getController()); webdavAction = new WebdavAction(getController()); webViewAction = new WebViewAction(getController()); expanded = new AtomicBoolean(); mouseOver = new AtomicBoolean(); osComponent = new OnlineStorageComponent(getController(), folder); primaryButton = new JButtonMini(Icons.getIconById(Icons.BLANK), ""); primaryButton.addActionListener(new PrimaryButtonActionListener()); openSettingsInformationButton = new JButtonMini(openSettingsInformationAction); upperSyncPercentageLabel = new ActionLabel(getController(), new MyOpenFilesUnsyncedAction(getController())); if (!ConfigurationEntry.FILES_ENABLED.getValueBoolean(getController())) { upperSyncPercentageLabel.setNeverUnderline(true); } openFilesInformationButton = new JButtonMini(openFilesInformationAction); openFilesInformationButton.setVisible(ConfigurationEntry.FILES_ENABLED.getValueBoolean(getController())); inviteButton = new JButtonMini(inviteAction); upperSyncFolderButton = new SyncIconButtonMini(getController()); upperSyncFolderButton.addActionListener(new PrimaryButtonActionListener()); upperSyncFolderButton.setVisible(false); Icon pIcon = Icons.getIconById(Icons.SYNC_COMPLETE); Icon sIcon = Icons.getIconById(Icons.SYNC_ANIMATION[0]); if (pIcon.getIconHeight() > sIcon.getIconHeight()) { // HACK(tm) when mixing 16x16 sync icon with 24x24 icons upperSyncFolderButton.setBorder(Borders.createEmptyBorder("6, 6, 6, 6")); } lowerSyncFolderButton = new JButtonMini(syncFolderAction); filesLabel = new ActionLabel(getController(), openFilesInformationAction); transferModeLabel = new ActionLabel(getController(), openSettingsInformationAction); localDirectoryLabel = new ActionLabel(getController(), moveLocalFolderAction); syncPercentLabel = new JLabel(); syncDateLabel = new ActionLabel(getController(), mostRecentChangesAction); localSizeLabel = new JLabel(); totalSizeLabel = new JLabel(); membersLabel = new ActionLabel(getController(), openMembersInformationAction); // filesAvailableLabel = new ActionLabel(getController(), // new MyFilesAvailableAction()); deletedFilesLabel = new ActionLabel(getController(), new MyDeletedFilesAction()); updateNumberOfFiles(); updateStatsDetails(); updateFolderMembershipDetails(); updateTransferMode(); updateLocalButtons(); updateIconAndOS(); updatePermissions(); registerListeners(); } private void updatePermissions() { if (getController().isBackupOnly()) { backupOnlineStorageAction.setEnabled(false); stopOnlineStorageAction.setEnabled(false); inviteAction.setEnabled(false); return; } // Update permissions Permission folderAdmin = FolderPermission.admin(folderInfo); backupOnlineStorageAction.allowWith(folderAdmin); stopOnlineStorageAction.allowWith(folderAdmin); inviteAction.allowWith(folderAdmin); admin = getController().getOSClient().getAccount().hasAdminPermission(folderInfo); } private void updateLocalButtons() { boolean enabled = type == Type.Local; openSettingsInformationButton.setEnabled(enabled && !getController().isBackupOnly()); transferModeLabel.setEnabled(enabled && !getController().isBackupOnly()); localDirectoryLabel.setEnabled(enabled && !getController().isBackupOnly()); openSettingsInformationAction.setEnabled(enabled && !getController().isBackupOnly()); openFilesInformationButton.setEnabled(enabled); openFilesInformationAction.setEnabled(enabled); inviteButton.setEnabled(enabled && !getController().isBackupOnly()); inviteAction.setEnabled(enabled && !getController().isBackupOnly()); syncDateLabel.setEnabled(enabled); mostRecentChangesAction.setEnabled(enabled); membersLabel.setEnabled(enabled); openMembersInformationAction.setEnabled(enabled && !getController().isBackupOnly()); openExplorerAction.setEnabled(enabled); // Controlled by permission system. // removeFolderAction.setEnabled(true); updateSyncButton(); } private void updateSyncButton() { if (type != Type.Local) { upperSyncFolderButton.setVisible(false); upperSyncFolderButton.spin(false); primaryButton.setVisible(true); return; } // Do Local updates later. syncUpdater.schedule(new Runnable() { public void run() { if (folder == null) { return; } if (folder.isSyncing()) { primaryButton.setVisible(false); upperSyncFolderButton.setVisible(true); upperSyncFolderButton.spin(true); } else { primaryButton.setVisible(true); upperSyncFolderButton.setVisible(false); upperSyncFolderButton.spin(false); } } }); } private void registerListeners() { // myServerClientListener = new MyServerClientListener(); // getController().getOSClient().addListener(myServerClientListener); // myNodeManagerListener = new MyNodeManagerListener(); getController().getNodeManager().addNodeManagerListener(myNodeManagerListener); myTransferManagerListener = new MyTransferManagerListener(); getController().getTransferManager().addListener(myTransferManagerListener); myFolderRepositoryListener = new MyFolderRepositoryListener(); getController().getFolderRepository().addFolderRepositoryListener(myFolderRepositoryListener); } /** * Call if this object is being discarded, so that listeners are not * orphaned. */ public void unregisterListeners() { if (myNodeManagerListener != null) { getController().getNodeManager().removeNodeManagerListener(myNodeManagerListener); myNodeManagerListener = null; } if (myTransferManagerListener != null) { getController().getTransferManager().removeListener(myTransferManagerListener); myTransferManagerListener = null; } if (myFolderRepositoryListener != null) { getController().getFolderRepository().removeFolderRepositoryListener(myFolderRepositoryListener); myFolderRepositoryListener = null; } unregisterFolderListeners(); } /** * Register listeners of the folder. */ private void registerFolderListeners() { if (folder != null) { myFolderListener = new MyFolderListener(); folder.addFolderListener(myFolderListener); myFolderMembershipListener = new MyFolderMembershipListener(); folder.addMembershipListener(myFolderMembershipListener); } } /** * Unregister listeners of the folder. */ private void unregisterFolderListeners() { if (folder != null) { if (myFolderListener != null) { folder.removeFolderListener(myFolderListener); myFolderListener = null; } if (myFolderMembershipListener != null) { folder.removeMembershipListener(myFolderMembershipListener); myFolderMembershipListener = null; } } } /** * @return the Info of the associated folder. */ public FolderInfo getFolderInfo() { return folderInfo; } /** * Updates the statistics details of the folder. */ private void updateStatsDetails() { String syncPercentText; String syncPercentTip = null; String syncDateText; String localSizeString; String totalSizeString; if (type == Type.Local) { Date lastSyncDate = folder.getLastSyncDate(); if (lastSyncDate == null) { syncDateText = Translation.getTranslation("exp_folder_view.never_synchronized"); } else { String formattedDate = Format.formatDateShort(lastSyncDate); syncDateText = Translation.getTranslation("exp_folder_view.last_synchronized", formattedDate); } if (folder.hasOwnDatabase()) { FolderStatistic statistic = folder.getStatistic(); double sync = statistic.getHarmonizedSyncPercentage(); if (sync < UNKNOWN_SYNC_STATUS) { sync = UNKNOWN_SYNC_STATUS; } if (sync > 100) { sync = 100; } // Sync in progress? Rewrite date as estimate. if (Double.compare(sync, 100.0) < 0 && Double.compare(sync, UNKNOWN_SYNC_STATUS) > 0) { Date date = folder.getStatistic().getEstimatedSyncDate(); if (date != null) { // If ETA sync > 2 days show text: // "Estimated sync: Unknown" // If ETA sync > 20 hours show text: // "Estimated sync: in X days" // If ETA sync > 45 minutes show text: // "Estimated sync: in X hours" // If ETA sync < 45 minutes show text: // "Estimated sync: in X minutes" if (DateUtil.isDateMoreThanNDaysInFuture(date, 2)) { syncDateText = Translation.getTranslation("main_frame.sync_eta_unknown"); } else if (DateUtil.isDateMoreThanNHoursInFuture(date, 20)) { int days = DateUtil.getDaysInFuture(date); if (days <= 1) { syncDateText = Translation.getTranslation("exp_folder_view.sync_eta_one_day"); } else { syncDateText = Translation.getTranslation("exp_folder_view.sync_eta_days", String.valueOf(days)); } } else if (DateUtil.isDateMoreThanNMinutesInFuture(date, 45)) { int hours = DateUtil.getDaysInFuture(date); if (hours <= 1) { syncDateText = Translation.getTranslation("exp_folder_view.sync_eta_one_hour"); } else { syncDateText = Translation.getTranslation("exp_folder_view.sync_eta_hours", String.valueOf(hours)); } } else { int minutes = DateUtil.getHoursInFuture(date); if (minutes <= 1) { syncDateText = Translation.getTranslation("exp_folder_view.sync_eta_one_minute"); } else { syncDateText = Translation.getTranslation("exp_folder_view.sync_eta_minutes", String.valueOf(minutes)); } } } } if (lastSyncDate == null && (Double.compare(sync, 100.0) == 0 || Double.compare(sync, UNKNOWN_SYNC_STATUS) == 0)) { // Never synced with others. syncPercentText = Translation.getTranslation("exp_folder_view.unsynchronized"); showing100Sync.set(false); } else { showing100Sync.set(Double.compare(sync, 100) == 0); if (Double.compare(sync, UNKNOWN_SYNC_STATUS) == 0) { if (folder.getConnectedMembersCount() >= 1) { syncPercentText = Translation.getTranslation("exp_folder_view.unsynchronized"); syncPercentTip = Translation.getTranslation("exp_folder_view.unsynchronized.tip"); } else { syncPercentText = ""; syncPercentTip = ""; } } else { syncPercentText = Translation.getTranslation("exp_folder_view.synchronized", Format.formatPercent(sync)); // Workaround: Prevent double %% syncPercentText = syncPercentText.replace("%%", "%"); } } if (lastSyncDate != null && Double.compare(sync, 100.0) == 0) { // 100% sync - remove any sync problem. folder.checkSync(); } long localSize = statistic.getLocalSize(); localSizeString = Format.formatBytesShort(localSize); long totalSize = statistic.getTotalSize(); totalSizeString = Format.formatBytesShort(totalSize); if (sync >= 0 && sync < 100) { upperSyncPercentageLabel.setText(Format.formatPercent(sync)); } else { upperSyncPercentageLabel.setText(""); } } else { upperSyncPercentageLabel.setText(""); showing100Sync.set(false); syncPercentText = Translation.getTranslation("exp_folder_view.not_yet_scanned"); localSizeString = "?"; totalSizeString = "?"; } } else { upperSyncPercentageLabel.setText(""); syncPercentText = Translation.getTranslation("exp_folder_view.synchronized", "?"); syncDateText = Translation.getTranslation("exp_folder_view.last_synchronized", "?"); localSizeString = "?"; totalSizeString = "?"; } syncPercentLabel.setText(syncPercentText); syncPercentLabel.setToolTipText(syncPercentTip); syncDateLabel.setText(syncDateText); localSizeLabel.setText(Translation.getTranslation("exp_folder_view.local", localSizeString)); totalSizeLabel.setText(Translation.getTranslation("exp_folder_view.total", totalSizeString)); // Maybe change visibility of upperSyncLink. retrieveAdditionalInfosFromServer(); } /** * Updates the number of files details of the folder. */ private void updateNumberOfFiles() { String filesText; if (type == Type.Local) { // FIXME: Returns # of files + # of directories filesText = Translation.getTranslation("exp_folder_view.files", String.valueOf(folder.getStatistic().getLocalFilesCount())); } else { filesText = Translation.getTranslation("exp_folder_view.files", "?"); } filesLabel.setText(filesText); } private void updateDeletedFiles() { String deletedFileText; if (type == Type.Local) { Collection<FileInfo> allFiles = folder.getDAO().findAllFiles(getController().getMySelf().getId()); int deletedCount = 0; for (FileInfo file : allFiles) { if (file.isDeleted()) { deletedCount++; } } deletedFileText = Translation.getTranslation("exp_folder_view.deleted_files", String.valueOf(deletedCount)); } else { deletedFileText = Translation.getTranslation("exp_folder_view.deleted_files", "?"); } deletedFilesLabel.setText(deletedFileText); } /** * Updates transfer mode of the folder. */ private void updateTransferMode() { String transferMode; if (type == Type.Local) { transferMode = Translation.getTranslation("exp_folder_view.transfer_mode", folder.getSyncProfile().getName()); String path = folder.getCommitOrLocalDir().toAbsolutePath().toString(); if (path.length() >= 35) { path = path.substring(0, 15) + "..." + path.substring(path.length() - 15, path.length()); } localDirectoryLabel.setVisible(true); localDirectoryLabel.setText(path); } else { transferMode = Translation.getTranslation("exp_folder_view.transfer_mode", "?"); localDirectoryLabel.setVisible(false); } transferModeLabel.setText(transferMode); } /** * Updates the folder member details. */ private void updateFolderMembershipDetails() { folderDetailsUpdater.schedule(new Runnable() { public void run() { updateFolderMembershipDetails0(); } }); } /** * Updates the folder member details. */ private void updateFolderMembershipDetails0() { String countText; String connectedCountText; if (type == Type.Local) { countText = String.valueOf(folder.getMembersCount()); // And me! connectedCountText = String.valueOf(folder.getConnectedMembersCount() + 1); } else { countText = "?"; connectedCountText = "?"; } membersLabel.setText(Translation.getTranslation("exp_folder_view.members", countText, connectedCountText)); } /** * Gets called externally to update the display of problems. */ public void updateIconAndOS() { boolean osComponentVisible = getController().getOSClient().isBackupByDefault() && !getController().isBackupOnly(); if (type == Type.Local) { double sync = folder.getStatistic().getHarmonizedSyncPercentage(); if (folder != null && folder.countProblems() > 0) { // Got a problem. primaryButton.setIcon(Icons.getIconById(Icons.PROBLEMS)); primaryButton.setToolTipText(Translation.getTranslation("exp_folder_view.folder_problem_text")); } else if (folder != null && folder.isPreviewOnly()) { // It's a preview. primaryButton.setIcon(Icons.getIconById(Icons.PREVIEW_FOLDER)); primaryButton.setToolTipText(Translation.getTranslation("exp_folder_view.folder_preview_text")); } else if (getController().isPaused() && Double.compare(sync, 100.0d) < 0 && sync != FolderStatistic.UNKNOWN_SYNC_STATUS) { // Sync is in pause primaryButton.setIcon(Icons.getIconById(Icons.PAUSE)); primaryButton.setToolTipText(Translation.getTranslation("exp_folder_view.folder_sync_paused")); } else if (Double.compare(sync, 100.0d) < 0) { // Not synced and not syncing. primaryButton.setIcon(Icons.getIconById(Icons.SYNC_INCOMPLETE)); primaryButton.setToolTipText(Translation.getTranslation("exp_folder_view.folder_sync_incomplete")); } else { // We are in sync. primaryButton.setIcon(Icons.getIconById(Icons.LOCAL_FOLDER)); if (PreferencesEntry.BEGINNER_MODE.getValueBoolean(getController()) && !PreferencesEntry.EXPERT_MODE.getValueBoolean(getController())) { primaryButton.setToolTipText(Translation.getTranslation("exp_folder_view.explore")); } else { primaryButton .setToolTipText(Translation.getTranslation("exp_folder_view.folder_sync_complete")); } } } else if (type == Type.Typical) { primaryButton.setIcon(Icons.getIconById(Icons.TYPICAL_FOLDER)); primaryButton.setToolTipText(Translation.getTranslation("exp_folder_view.folder_typical_text")); osComponent.getUIComponent().setVisible(false); } else { // CloudOnly primaryButton.setIcon(Icons.getIconById(Icons.ONLINE_FOLDER)); primaryButton.setToolTipText(Translation.getTranslation("exp_folder_view.folder_online_text")); osComponent.getUIComponent().setVisible(osComponentVisible); } if (folder != null && folder.isPreviewOnly()) { osComponent.getUIComponent().setVisible(false); } else { osComponent.getUIComponent().setVisible(osComponentVisible); if (osComponentVisible) { double sync = 0; if (folder != null) { sync = folder.getStatistic().getServerSyncPercentage(); } boolean warned = serverClient.getAccountDetails().getAccount().getOSSubscription() .isDisabledUsage(); boolean joined = folder != null && serverClient.joinedByCloud(folder); osComponent.setSyncPercentage(sync, warned, joined); } } } public void addExpansionListener(ExpansionListener listener) { ListenerSupportFactory.addListener(listenerSupport, listener); } public void removeExpansionListener(ExpansionListener listener) { ListenerSupportFactory.removeListener(listenerSupport, listener); } /** * Is the view expanded? * * @return */ public boolean isExpanded() { return expanded.get(); } public JPopupMenu createPopupMenu() { JPopupMenu contextMenu = new JPopupMenu(); if (type == Type.CloudOnly) { // Cloud-only folder popup createWebDAVURL(); if (StringUtils.isNotBlank(webDAVURL)) { if (serverClient.supportsWebDAV() && OSUtil.isWindowsSystem()) { contextMenu.add(webdavAction).setIcon(null); } if (serverClient.supportsWebLogin()) { contextMenu.add(webViewAction).setIcon(null); } } contextMenu.add(removeFolderOnlineAction).setIcon(null); } else { // Local folder popup contextMenu.add(openExplorerAction).setIcon(null); contextMenu.addSeparator(); boolean expert = PreferencesEntry.EXPERT_MODE.getValueBoolean(getController()); if (expert) { contextMenu.add(syncFolderAction).setIcon(null); contextMenu.add(openFilesInformationAction).setIcon(null); contextMenu.add(mostRecentChangesAction).setIcon(null); contextMenu.add(clearCompletedDownloadsAction).setIcon(null); } if (!getController().isBackupOnly()) { boolean addedSeparator = false; if (ConfigurationEntry.SERVER_INVITE_ENABLED.getValueBoolean(getController()) && admin) { contextMenu.addSeparator(); addedSeparator = true; contextMenu.add(inviteAction).setIcon(null); } if (expert) { if (!addedSeparator) { contextMenu.addSeparator(); } contextMenu.add(openMembersInformationAction).setIcon(null); } } contextMenu.addSeparator(); if (ConfigurationEntry.SETTINGS_ENABLED.getValueBoolean(getController())) { contextMenu.add(openSettingsInformationAction).setIcon(null); } contextMenu.add(removeFolderLocalAction).setIcon(null); if (expert && serverClient.isConnected() && serverClient.isLoggedIn()) { boolean osConfigured = serverClient.joinedByCloud(folder); if (osConfigured) { contextMenu.add(stopOnlineStorageAction).setIcon(null); } else { contextMenu.add(backupOnlineStorageAction).setIcon(null); } } } return contextMenu; } private void openExplorer() { // PFC-2349 : Don't freeze UI getController().getIOProvider().startIO(new Runnable() { public void run() { PathUtils.openFile(folder.getCommitOrLocalDir()); } }); } /** * Downloads added or removed for this folder. Recalculate new files status. * Or if expanded / collapsed - might need to change tool tip. */ public void updateNameLabel() { boolean newFiles = false; String newCountString = ""; String ownerAddition = ""; if (folder != null) { int newCount = getController().getTransferManager().countCompletedDownloads(folder); // #PFC-2497 Do not show new Files in Beginnger mode if (!PreferencesEntry.BEGINNER_MODE.getValueBoolean(getController())) { newFiles = newCount > 0; } if (newFiles) { newCountString = " (" + newCount + ')'; nameLabel.setToolTipText( Translation.getTranslation("exp_folder_view.new_files_tip_text", String.valueOf(newCount))); } } if (!newFiles && folder != null) { if (expanded.get()) { nameLabel.setToolTipText(Translation.getTranslation("exp_folder_view.collapse")); } else { if (PreferencesEntry.BEGINNER_MODE.getValueBoolean(getController()) && !PreferencesEntry.EXPERT_MODE.getValueBoolean(getController())) { nameLabel.setToolTipText(Translation.getTranslation("exp_folder_view.remove")); } else { nameLabel.setToolTipText(Translation.getTranslation("exp_folder_view.expand")); } } } if (folder == null) { nameLabel.setToolTipText(Translation.getTranslation("exp_folder_view.folder_online_text")); } String folderName = folderInfo.getLocalizedName(); if (StringUtils.isNotBlank(ownerDisplayname)) { ownerAddition += " (" + ownerDisplayname + ")"; } nameLabel.setText(folderName + newCountString + ownerAddition); nameLabel.setFont(new Font(nameLabel.getFont().getName(), newFiles ? Font.BOLD : Font.PLAIN, nameLabel.getFont().getSize())); clearCompletedDownloadsAction.setEnabled(newFiles); } /** * Create a WebDAV connection to this folder. Should be something like 'net * use * "https://my.powerfolder.com/webdav/afolder" * /User:bob@powerfolder.com pazzword' */ private void createWebdavConnection() { ActivityVisualizationWorker worker = new ActivityVisualizationWorker(getUIController()) { protected String getTitle() { return Translation.getTranslation("exp_folder_view.webdav_title"); } protected String getWorkingText() { return Translation.getTranslation("exp_folder_view.webdav_working_text"); } public Object construct() throws Throwable { try { return WebDAV.createConnection(serverClient, createWebDAVURL()); } catch (Exception e) { // Looks like the link failed, badly :-( logSevere(e.getMessage(), e); return 'N' + e.getMessage(); } } public void finished() { // See what happened. String result = (String) get(); if (result != null) { if (result.startsWith("Y")) { String[] parts = result.substring(1).split("\\s"); for (final String part : parts) { if (part.length() == 2 && part.charAt(1) == ':') { // Probably the new drive name, so open it. getController().getIOProvider().startIO(new Runnable() { public void run() { PathUtils.openFile(Paths.get(part)); } }); break; } } } else if (result.startsWith("N")) { String[] ops; if (Help.hasWiki(getController())) { ops = new String[] { Translation.getTranslation("general.ok"), Translation.getTranslation("general.help") }; } else { ops = new String[] { Translation.getTranslation("general.ok") }; } int op = DialogFactory.genericDialog(getController(), Translation.getTranslation("exp_folder_view.webdav_failure_title"), Translation .getTranslation("exp_folder_view.webdav_failure_text", result.substring(1)), ops, 0, GenericDialogType.ERROR); if (op == 1) { Help.openWikiArticle(getController(), WikiLinks.WEBDAV); } } } } }; worker.start(); } /** * See if user wants to create this typical folder. */ private void askToCreateFolder() { if (type != Type.Typical) { logSevere("Folder " + folderInfo.getName() + " is not Typical"); return; } PFWizard.openTypicalFolderJoinWizard(getController(), folderInfo); } // //////////////// // Inner Classes // // //////////////// private class MyNodeManagerListener extends NodeManagerAdapter { private void updateIfRequired(NodeManagerEvent e) { if (folder != null && folder.hasMember(e.getNode())) { updateFolderMembershipDetails(); doFolderChanges(folder); } } public void nodeConnected(NodeManagerEvent e) { updateIfRequired(e); } public void nodeDisconnected(NodeManagerEvent e) { updateIfRequired(e); } public void friendAdded(NodeManagerEvent e) { updateIfRequired(e); } public void friendRemoved(NodeManagerEvent e) { updateIfRequired(e); } @Override public void settingsChanged(NodeManagerEvent e) { updateIfRequired(e); } public boolean fireInEventDispatchThread() { return true; } } private synchronized void doFolderChanges(Folder eventFolder) { if (folder == null || folder.equals(eventFolder)) { folderUpdater.schedule(new Runnable() { public void run() { updateNumberOfFiles(); updateDeletedFiles(); updateStatsDetails(); updateIconAndOS(); updateLocalButtons(); updateTransferMode(); updatePermissions(); } }); } } /** * Class to respond to folder events. */ private class MyFolderListener implements FolderListener { public void statisticsCalculated(FolderEvent folderEvent) { doFolderChanges(folderEvent.getFolder()); } public void fileChanged(FolderEvent folderEvent) { doFolderChanges(folderEvent.getFolder()); } public void filesDeleted(FolderEvent folderEvent) { doFolderChanges(folderEvent.getFolder()); } public void remoteContentsChanged(FolderEvent folderEvent) { if (folderEvent.getMember().hasCompleteFileListFor(folderEvent.getFolder().getInfo())) { doFolderChanges(folderEvent.getFolder()); } } public void scanResultCommited(FolderEvent folderEvent) { if (folderEvent.getScanResult().isChangeDetected()) { doFolderChanges(folderEvent.getFolder()); } } public void syncProfileChanged(FolderEvent folderEvent) { doFolderChanges(folderEvent.getFolder()); } public void archiveSettingsChanged(FolderEvent folderEvent) { doFolderChanges(folderEvent.getFolder()); } public boolean fireInEventDispatchThread() { return true; } } /** * Class to respond to folder membership events. */ private class MyFolderMembershipListener implements FolderMembershipListener { public void memberJoined(FolderMembershipEvent folderEvent) { updateFolderMembershipDetails(); doFolderChanges(folder); } public void memberLeft(FolderMembershipEvent folderEvent) { updateFolderMembershipDetails(); doFolderChanges(folder); } public boolean fireInEventDispatchThread() { return true; } } private class MyFolderRepositoryListener implements FolderRepositoryListener { private void updateIfRequired(FolderRepositoryEvent e) { if (folder == null || !folder.equals(e.getFolder())) { return; } updateSyncButton(); updateIconAndOS(); } public void folderCreated(FolderRepositoryEvent e) { } public void folderRemoved(FolderRepositoryEvent e) { } public void maintenanceFinished(FolderRepositoryEvent e) { updateIfRequired(e); } public void maintenanceStarted(FolderRepositoryEvent e) { updateIfRequired(e); } public boolean fireInEventDispatchThread() { return true; } } private class MyTransferManagerListener extends TransferManagerAdapter { private void updateIfRequired(TransferManagerEvent event) { if (folder == null || !folderInfo.equals(event.getFile().getFolderInfo())) { return; } updateSyncButton(); updateIconAndOS(); } @Override public void downloadAborted(TransferManagerEvent event) { updateIfRequired(event); } @Override public void downloadBroken(TransferManagerEvent event) { updateIfRequired(event); } @Override public void downloadCompleted(TransferManagerEvent event) { updateIfRequired(event); } @Override public void downloadQueued(TransferManagerEvent event) { updateIfRequired(event); } @Override public void downloadRequested(TransferManagerEvent event) { updateIfRequired(event); } @Override public void downloadStarted(TransferManagerEvent event) { updateIfRequired(event); } @Override public void uploadAborted(TransferManagerEvent event) { updateIfRequired(event); } @Override public void uploadBroken(TransferManagerEvent event) { updateIfRequired(event); } @Override public void uploadCompleted(TransferManagerEvent event) { updateIfRequired(event); } @Override public void uploadRequested(TransferManagerEvent event) { updateIfRequired(event); } @Override public void uploadStarted(TransferManagerEvent event) { updateIfRequired(event); } public boolean fireInEventDispatchThread() { return true; } } /** Hover over any component in the upper panel should expand / collapse. */ private class MyMouseOverAdapter extends MouseAdapter { // Auto expand if user hovers for two seconds. public void mouseEntered(MouseEvent e) { mouseOver.set(true); if (PreferencesEntry.AUTO_EXPAND.getValueBoolean(getController())) { if (!expanded.get()) { getController().schedule(new TimerTask() { public void run() { if (mouseOver.get()) { if (!expanded.get()) { expand(); PreferencesEntry.AUTO_EXPAND.setValue(getController(), Boolean.FALSE); } } } }, 2000); } } } public void mouseExited(MouseEvent e) { mouseOver.set(false); } } /** Click on the upper panel should expand or display context menu */ private class MyMouseClickAdapter extends MouseAdapter { public void mousePressed(MouseEvent e) { if (e.isPopupTrigger()) { showContextMenu(e); } } public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger()) { showContextMenu(e); } } private void showContextMenu(MouseEvent evt) { Cursor c = CursorUtils.setWaitCursor(upperPanel); try { createPopupMenu().show(evt.getComponent(), evt.getX(), evt.getY()); } finally { CursorUtils.returnToOriginal(upperPanel, c); } } public void mouseClicked(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1) { setFocus(true); if (expanded.get()) { collapse(); } else { expand(); if (type == Type.Local) { boolean openedTab = getController().getUIController().openFilesInformation(folderInfo); if (!openedTab) { FolderRemoveDialog panel = new FolderRemoveDialog(getController(), folderInfo); panel.open(); } } if (type == Type.CloudOnly && folderInfo != null) { PFWizard.openOnlineStorageJoinWizard(getController(), Collections.singletonList(folderInfo)); } if (type == Type.Typical) { askToCreateFolder(); } } } } } // Action to invite friend. private class MyInviteAction extends BaseAction { private MyInviteAction(Controller controller) { super("action_invite_friend", controller); } public void actionPerformed(ActionEvent e) { PFWizard.openSendInvitationWizard(getController(), folderInfo); } } private class MyOpenSettingsInformationAction extends BaseAction { private MyOpenSettingsInformationAction(Controller controller) { super("action_open_settings_information", controller); } public void actionPerformed(ActionEvent e) { getController().getUIController().openSettingsInformation(folderInfo); } } private class MyMoveLocalFolderAction extends BaseAction { private MyMoveLocalFolderAction(Controller controller) { super("action_move_local_folder", controller); } public void actionPerformed(ActionEvent e) { getController().getUIController().moveLocalFolder(folderInfo); } } private class MyOpenFilesInformationAction extends BaseAction { MyOpenFilesInformationAction(Controller controller) { super("action_open_files_information", controller); } public void actionPerformed(ActionEvent e) { getController().getUIController().openFilesInformation(folderInfo); } } private class MyOpenFilesUnsyncedAction extends BaseAction { MyOpenFilesUnsyncedAction(Controller controller) { super("action_open_files_unsynced", controller); } public void actionPerformed(ActionEvent e) { getController().getUIController().openFilesInformationUnsynced(folderInfo); } } private class MyOpenMembersInformationAction extends BaseAction { MyOpenMembersInformationAction(Controller controller) { super("action_open_members_information", controller); } public void actionPerformed(ActionEvent e) { getController().getUIController().openMembersInformation(folderInfo); } } private class MySyncFolderAction extends BaseAction { private MySyncFolderAction(Controller controller) { super("action_sync_folder", controller); } public void actionPerformed(ActionEvent e) { if (folder.isPreviewOnly()) { SwingUtilities.invokeLater(new Runnable() { public void run() { PreviewToJoinDialog panel = new PreviewToJoinDialog(getController(), folder); panel.open(); } }); } else { getApplicationModel().syncFolder(folder); } } } private class FolderRemoveAction extends BaseAction { private FolderRemoveAction(Controller controller) { super("action_remove_folder", controller); } public void actionPerformed(ActionEvent e) { FolderRemoveDialog panel = new FolderRemoveDialog(getController(), folderInfo); panel.open(); } } private class FolderOnlineRemoveAction extends BaseAction { private FolderOnlineRemoveAction(Controller controller) { super(removeLabel, controller); } public void actionPerformed(ActionEvent e) { FolderRemoveDialog panel = new FolderRemoveDialog(getController(), folderInfo); panel.open(); } } // private class MyProblemAction extends BaseAction { // // private MyProblemAction(Controller controller) { // super("action_folder_problem", controller); // } // // public void actionPerformed(ActionEvent e) { // getController().getUIController().openProblemsInformation( // folderInfo); // } // } // private class MyClearCompletedDownloadsAction extends BaseAction { private MyClearCompletedDownloadsAction(Controller controller) { super("exp.action_clear_completed_downloads", controller); } public void actionPerformed(ActionEvent e) { TransferManager transferManager = getController().getTransferManager(); for (DownloadManager dlMan : transferManager.getCompletedDownloadsCollection()) { if (dlMan.getFileInfo().getFolderInfo().equals(folder.getInfo())) { transferManager.clearCompletedDownload(dlMan); } } } } private class MyMostRecentChangesAction extends BaseAction { private MyMostRecentChangesAction(Controller controller) { super("action_most_recent_changes", controller); } public void actionPerformed(ActionEvent e) { getController().getUIController().openFilesInformationLatest(folderInfo); } } // private class MyFilesAvailableAction extends AbstractAction { // // public void actionPerformed(ActionEvent e) { // getController().getUIController().openFilesInformationIncoming( // folderInfo); // } // } private class MyDeletedFilesAction extends AbstractAction { public void actionPerformed(ActionEvent e) { getController().getUIController().openFilesInformationDeleted(folderInfo); } } private class MyOpenExplorerAction extends BaseAction { private MyOpenExplorerAction(Controller controller) { super("action_open_explorer", controller); } public void actionPerformed(ActionEvent e) { openExplorer(); } } @SuppressWarnings("serial") private class BackupOnlineStorageAction extends BaseAction { private BackupOnlineStorageAction(Controller controller) { super("exp.action_backup_online_storage", controller); } public void actionPerformed(ActionEvent e) { // FolderOnlineStoragePanel knows if folder already joined :-) getUIController().getApplicationModel().getServerClientModel().checkAndSetupAccount(); PFWizard.openMirrorFolderWizard(getController(), folder); } } @SuppressWarnings("serial") private class StopOnlineStorageAction extends BaseAction { private StopOnlineStorageAction(Controller controller) { super("exp.action_stop_online_storage", controller); } public void actionPerformed(ActionEvent e) { // FolderOnlineStoragePanel knows if folder already joined :-) getUIController().getApplicationModel().getServerClientModel().checkAndSetupAccount(); PFWizard.openMirrorFolderWizard(getController(), folder); } } private class PrimaryButtonActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { if (type == Type.Local && folder != null && folder.countProblems() > 0) { if (!ConfigurationEntry.PROBLEMS_ENABLED.getValueBoolean(getController())) { ResolvableProblem prob = (ResolvableProblem) folder.getProblems().get(0); DialogFactory.genericDialog(getController(), prob.getDescription(), prob.getDescription(), GenericDialogType.WARN); SwingUtilities.invokeLater(prob.resolution(getController())); folder.removeProblem(prob); } else { // Display the problem. getController().getUIController().openProblemsInformation(folderInfo); } } else if (type == Type.CloudOnly) { // Join the folder locally. PFWizard.openOnlineStorageJoinWizard(getController(), Collections.singletonList(folderInfo)); } else if (type == Type.Local && folder != null && folder.isPreviewOnly()) { // Local Preview - want to change? SettingsTab.doPreviewChange(getController(), folder); } else if (type == Type.Local) { // Local - open it openExplorer(); } else { // Typical - ask to create. askToCreateFolder(); } } } @SuppressWarnings("serial") private class WebdavAction extends BaseAction { private WebdavAction(Controller controller) { super("action_webdav", controller); } public void actionPerformed(ActionEvent e) { createWebdavConnection(); } } @SuppressWarnings("serial") private class WebViewAction extends BaseAction { private WebViewAction(Controller controller) { super("action_webview", controller); } public void actionPerformed(ActionEvent e) { final ServerClient client = getController().getOSClient(); if (client.supportsWebLogin()) { BrowserLauncher.open(getController(), new URLProducer() { public String url() { return client.getFolderURLWithCredentials(folder.getInfo()); } }); } } } void dispose() { removeFolderLocalAction.dispose(); removeFolderOnlineAction.dispose(); backupOnlineStorageAction.dispose(); stopOnlineStorageAction.dispose(); inviteAction.dispose(); } }