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$ */ package de.dal33t.powerfolder.ui; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.TimerTask; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.SwingUtilities; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.factories.Borders; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import de.dal33t.powerfolder.*; import de.dal33t.powerfolder.clientserver.ServerClientEvent; import de.dal33t.powerfolder.clientserver.ServerClientListener; import de.dal33t.powerfolder.disk.Folder; import de.dal33t.powerfolder.event.*; import de.dal33t.powerfolder.net.ConnectionHandlerFactory; import de.dal33t.powerfolder.net.ConnectionListener; import de.dal33t.powerfolder.net.ConnectionQuality; import de.dal33t.powerfolder.net.IOProvider; import de.dal33t.powerfolder.ui.model.NoticesModel; import de.dal33t.powerfolder.ui.notices.AskForFriendshipEventNotice; import de.dal33t.powerfolder.ui.notices.InvitationNotice; import de.dal33t.powerfolder.ui.notices.Notice; import de.dal33t.powerfolder.ui.notices.NoticeSeverity; import de.dal33t.powerfolder.ui.notices.RunnableNotice; import de.dal33t.powerfolder.ui.notices.WarningNotice; import de.dal33t.powerfolder.ui.widget.JButtonMini; import de.dal33t.powerfolder.util.TransferCounter; import de.dal33t.powerfolder.util.Translation; import de.dal33t.powerfolder.ui.util.*; import de.dal33t.powerfolder.ui.util.LimitedConnectivityChecker.CheckTask; import de.dal33t.powerfolder.ui.dialog.DialogFactory; import de.dal33t.powerfolder.ui.dialog.GenericDialogType; /** * The status bar on the lower side of the main window. * * @author <a href="mailto:totmacher@powerfolder.com">Christian Sprajc</a> * @version $Revision: 1.5 $ */ public class StatusBar extends PFUIComponent { private JComponent comp; private JButton compactModeButton; private SyncIconButtonMini syncButton; private JLabel portLabel; private JLabel networkModeLabel; private JButton newNoticesButton; //private JButton openAboutBoxButton; private JButton openPreferencesButton; //private JButton openStatsChartButton; private JButton openDebugButton; private JButton pendingMessagesButton; private boolean shownQualityWarningToday; private boolean shownLimitedConnectivityToday; private DelayedUpdater syncUpdater; private DelayedUpdater checkQualityUpdater; private NoticesModel noticeModel; protected StatusBar(Controller controller) { super(controller); noticeModel = getApplicationModel().getNoticesModel(); noticeModel.getAllNoticesCountVM().addValueChangeListener(new MyNoticesListener()); noticeModel.getUnreadNoticesCountVM().addValueChangeListener(new MyNoticesListener()); } public Component getUIComponent() { if (comp == null) { boolean showPort = getController().getConnectionListener().getPort() != ConnectionListener.DEFAULT_PORT; initComponents(); String debugArea = ""; if (getController().isVerbose()) { debugArea = "pref, 3dlu, "; } String portArea = ""; if (showPort) { portArea = "pref, 3dlu, "; } FormLayout mainLayout = new FormLayout("1dlu, pref, 3dlu, pref, center:pref:grow, pref, 3dlu, " + portArea + debugArea + " pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu", "pref"); DefaultFormBuilder mainBuilder = new DefaultFormBuilder(mainLayout); mainBuilder.setBorder(Borders.createEmptyBorder("3dlu, 0, 0, 0")); CellConstraints cc = new CellConstraints(); int col = 2; mainBuilder.add(syncButton, cc.xy(col, 1)); col += 2; mainBuilder.add(newNoticesButton, cc.xy(col, 1)); col += 1; mainBuilder.add(networkModeLabel, cc.xy(col, 1)); col += 1; mainBuilder.add(pendingMessagesButton, cc.xy(col, 1)); col += 2; if (portArea.length() > 0) { mainBuilder.add(portLabel, cc.xy(col, 1)); col += 2; } if (debugArea.length() > 0) { mainBuilder.add(openDebugButton, cc.xy(col, 1)); col += 2; } // mainBuilder.add(openStatsChartButton, cc.xy(col, 1)); // col += 2; mainBuilder.add(openPreferencesButton, cc.xy(col, 1)); // col += 2; // mainBuilder.add(openAboutBoxButton, cc.xy(col, 1)); if (Feature.COMPACT_MODE.isEnabled()) { col += 2; mainBuilder.add(compactModeButton, cc.xy(col, 1)); } comp = mainBuilder.getPanel(); comp.setOpaque(false); } return comp; } public void showPendingMessages(boolean show) { pendingMessagesButton.setVisible(show); } private void initComponents() { syncUpdater = new DelayedUpdater(getController(), 1000L); checkQualityUpdater = new DelayedUpdater(getController()); MyActionListener listener = new MyActionListener(); compactModeButton = new JButtonMini(Icons.getIconById(Icons.COMPACT), Translation.getTranslation("status_bar.compact.tips")); compactModeButton.addActionListener(listener); configureConnectionLabels(); // Behavior when the limited connecvitiy gets checked getController().addLimitedConnectivityListener(new MyLimitedConnectivityListener()); syncButton = new SyncIconButtonMini(getController()); syncButton.addActionListener(listener); updateSyncButton(); getController().getFolderRepository().addFolderRepositoryListener(new MyFolderRepositoryListener()); getController().getTransferManager().addListener(new MyTransferManagerListener()); portLabel = new JLabel(Translation.getTranslation("status.port.text", String.valueOf(getController().getConnectionListener().getPort()))); portLabel.setToolTipText(Translation.getTranslation("status.port.tip")); newNoticesButton = new JButtonMini(getApplicationModel().getActionModel().getViewNoticesAction()); newNoticesButton.setText(null); networkModeLabel = new JLabel("nwm"); // openStatsChartButton = new JButtonMini(getApplicationModel() // .getActionModel().getOpenStatsChartsAction()); // openStatsChartButton.setVisible(getController().isVerbose()); openPreferencesButton = new JButtonMini(getApplicationModel().getActionModel().getOpenPreferencesAction()); // openAboutBoxButton = new JButtonMini(getApplicationModel() // .getActionModel().getOpenAboutBoxAction()); openDebugButton = new JButtonMini(getApplicationModel().getActionModel().getOpenDebugInformationAction()); pendingMessagesButton = new JButtonMini(Icons.getIconById(Icons.CHAT_PENDING), Translation.getTranslation("status.chat_pending")); pendingMessagesButton.addActionListener(listener); showPendingMessages(false); updateNewNoticesText(); } private void updateNewNoticesText() { int unread = (Integer) noticeModel.getUnreadNoticesCountVM().getValue(); newNoticesButton.setVisible(unread != 0); if (unread != 0) { // If there are any warnings, set icon as warning, else information. Icon noticesIcon = Icons.getIconById(Icons.INFORMATION); for (Notice notice : getUIController().getApplicationModel().getNoticesModel().getAllNotices()) { if (notice.getNoticeSeverity() == NoticeSeverity.WARINING) { noticesIcon = Icons.getIconById(Icons.WARNING); break; } } newNoticesButton.setIcon(noticesIcon); // See if they are all one type Class clazz = null; boolean variety = false; for (Notice notice : noticeModel.getAllNotices()) { if (notice.isRead()) { // Skip alread read notices. continue; } if (clazz == null) { clazz = notice.getClass(); } else if (clazz != notice.getClass()) { variety = true; break; } } // Adjust status text if they are all one variety. String noticesText; if (clazz != null && !variety) { if (clazz == AskForFriendshipEventNotice.class) { noticesText = Translation.getTranslation("status_tab.new_friendship_notices"); } else if (clazz == WarningNotice.class) { noticesText = Translation.getTranslation("status_tab.new_warning_notices"); } else if (clazz == InvitationNotice.class) { noticesText = Translation.getTranslation("status_tab.new_invitation_notices"); } else { // Default noticesText = Translation.getTranslation("status_tab.unread_notices"); } } else { noticesText = Translation.getTranslation("status_tab.unread_notices"); } newNoticesButton.setToolTipText(noticesText); } } private void configureConnectionLabels() { // Add behavior getController().getNodeManager().addNodeManagerListener(new MyNodeListener()); getController().getOSClient().addListener(new MyServerClientListener()); checkQuality(); } private void updateLimitedConnectivityLabel() { if (getController().isLimitedConnectivity() && !shownLimitedConnectivityToday) { shownLimitedConnectivityToday = true; showLimitedConnectivityWarning(getController()); } } private static void showLimitedConnectivityWarning(final Controller controller) { Boolean warn = PreferencesEntry.TEST_CONNECTIVITY.getValueBoolean(controller); if (warn) { // Advise user of limited connectivity. Runnable runnable = new Runnable() { public void run() { controller.getThreadPool().execute(new CheckTask(controller)); LimitedConnectivityChecker.showConnectivityWarning(controller); } }; RunnableNotice notice = new RunnableNotice(Translation.getTranslation("warning_notice.title"), Translation.getTranslation("warning_notice.limited_connectivity"), runnable, NoticeSeverity.WARINING); controller.getUIController().getApplicationModel().getNoticesModel().handleNotice(notice); } } private void checkQuality() { checkQualityUpdater.schedule(new Runnable() { public void run() { checkQuality0(); } }); } private void checkQuality0() { Controller controller = getController(); IOProvider ioProvider = controller.getIOProvider(); if (ioProvider != null) { ConnectionHandlerFactory factory = ioProvider.getConnectionHandlerFactory(); if (factory != null) { ConnectionQuality quality = factory.getConnectionQuality(); if (quality != null) { if (quality == ConnectionQuality.POOR) { // Only show warning once! if (!shownQualityWarningToday) { shownQualityWarningToday = true; showQualityWarning(controller); } } } } } } private static void showQualityWarning(final Controller controller) { Boolean warn = PreferencesEntry.WARN_POOR_QUALITY.getValueBoolean(controller); if (warn) { // Advise user of quality issue. Runnable runnable = new Runnable() { public void run() { String wikiLink = Help.getWikiArticleURL(controller, WikiLinks.LIMITED_CONNECTIVITY); String infoText = Translation.getTranslation("status_bar.poor_quality_warning.text", wikiLink); NeverAskAgainResponse response = DialogFactory.genericDialog(controller, Translation.getTranslation("status_bar.poor_quality_warning.title"), infoText, new String[] { Translation.getTranslation("general.ok") }, 0, GenericDialogType.INFO, Translation.getTranslation("general.neverAskAgain")); if (response.isNeverAskAgain()) { PreferencesEntry.WARN_POOR_QUALITY.setValue(controller, false); } } }; RunnableNotice notice = new RunnableNotice(Translation.getTranslation("warning_notice.title"), Translation.getTranslation("warning_notice.poor_quality"), runnable, NoticeSeverity.WARINING); controller.getUIController().getApplicationModel().getNoticesModel().handleNotice(notice); } } public static JLabel createTransferCounterLabel(Controller controller, final Icon icon, final String format, final TransferCounter tc, final String toolTip) { final JLabel label = new JLabel(); // Create task which updates the counter each second controller.scheduleAndRepeat(new TimerTask() { @Override public void run() { SwingUtilities.invokeLater(new Runnable() { public void run() { label.setIcon(icon); label.setText(String.format(format, tc.calculateCurrentKBS())); label.setToolTipText(toolTip); } }); } }, 0, 1000); return label; } public void setNetworkingModeStatus(NetworkingMode networkingMode) { if (networkingMode == NetworkingMode.LANONLYMODE) { networkModeLabel.setText(Translation.getTranslation("general.network_mode.lan_only")); } else if (networkingMode == NetworkingMode.SERVERONLYMODE && !getController().isBackupOnly()) { networkModeLabel.setText(Translation.getTranslation("general.network_mode.server_only")); } else { networkModeLabel.setText(""); } } private void updateSyncButton() { syncUpdater.schedule(new Runnable() { public void run() { boolean anySynchronizing = false; for (Folder folder : getController().getFolderRepository().getFolders(true)) { if (folder.isSyncing()) { anySynchronizing = true; break; } } syncButton.setVisible(anySynchronizing); syncButton.spin(anySynchronizing); } }); } // //////////////// // Inner Classes // // //////////////// private class MyNodeListener extends NodeManagerAdapter { public void nodeConnected(NodeManagerEvent e) { checkQuality(); } public void nodeDisconnected(NodeManagerEvent e) { checkQuality(); } public void startStop(NodeManagerEvent e) { checkQuality(); } public boolean fireInEventDispatchThread() { return true; } } private class MyServerClientListener implements ServerClientListener { public boolean fireInEventDispatchThread() { return true; } public void serverDisconnected(ServerClientEvent event) { } public void serverConnected(ServerClientEvent event) { } public void nodeServerStatusChanged(ServerClientEvent event) { } public void login(ServerClientEvent event) { checkQuality(); } public void accountUpdated(ServerClientEvent event) { checkQuality(); } } private class MyFolderRepositoryListener implements FolderRepositoryListener { public void folderCreated(FolderRepositoryEvent e) { } public void folderRemoved(FolderRepositoryEvent e) { } public void maintenanceFinished(FolderRepositoryEvent e) { updateSyncButton(); } public void maintenanceStarted(FolderRepositoryEvent e) { updateSyncButton(); } public boolean fireInEventDispatchThread() { return true; } } private class MyTransferManagerListener extends TransferManagerAdapter { private void updateIfRequired(TransferManagerEvent event) { updateSyncButton(); } @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; } } private class MyActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getSource() == pendingMessagesButton) { getUIController().openChat(null); } else if (e.getSource() == syncButton) { syncAllFolders(); } else if (e.getSource() == compactModeButton) { getUIController().reconfigureForCompactMode(true); } } } private void syncAllFolders() { for (Folder folder : getController().getFolderRepository().getFolders(true)) { if (folder.isPreviewOnly()) { continue; } getApplicationModel().syncFolder(folder); } } private class MyNoticesListener implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent evt) { updateNewNoticesText(); } } private class MyLimitedConnectivityListener implements LimitedConnectivityListener { public void setLimitedConnectivity(LimitedConnectivityEvent event) { updateLimitedConnectivityLabel(); } public boolean fireInEventDispatchThread() { return true; } } }