de.dal33t.powerfolder.ui.StatusBar.java Source code

Java tutorial

Introduction

Here is the source code for de.dal33t.powerfolder.ui.StatusBar.java

Source

/*
 * 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;
        }
    }

}