Difference between revisions of "Mediator"

From CDOT Wiki
Jump to: navigation, search
(References)
(References)
Line 482: Line 482:
  
 
[http://www.dofactory.com/Patterns/PatternMediator.aspx www.dofactory.com]
 
[http://www.dofactory.com/Patterns/PatternMediator.aspx www.dofactory.com]
 +
 
[http://my.execpc.com/~gopalan/design/behavioral/mediator/mediator.html my.execpc.com]
 
[http://my.execpc.com/~gopalan/design/behavioral/mediator/mediator.html my.execpc.com]

Revision as of 16:02, 27 March 2007

Example.png

Explain

Example

LimeWire uses several mediators in their coding. This Mediator is used to control the tip of the day window in limewire.

    	
package com.limegroup.gnutella.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.ResourceBundle;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

import com.limegroup.gnutella.gui.themes.ThemeFileHandler;
import com.limegroup.gnutella.gui.themes.ThemeMediator;
import com.limegroup.gnutella.gui.themes.ThemeObserver;
import com.limegroup.gnutella.settings.StartupSettings;
import com.limegroup.gnutella.util.CommonUtils;


public final class TipOfTheDayMediator implements ThemeObserver {

    /**
     * The instance of this class.
     */
    private static TipOfTheDayMediator _instance;

    /**
     * The title for the TOTD window.
     */
    private static final String TOTD_TITLE =
        GUIMediator.getStringResource("TOTD_TITLE");

    /**
     * The 'Did You Know' intro.
     */
    private static final String TOTD_INTRO =
        GUIMediator.getStringResource("TOTD_INTRODUCTION");

    /**
     * The 'Show Tips At Startup' string
     */
    private static final String TOTD_STARTUP =
        GUIMediator.getStringResource("TOTD_SHOW_AT_STARTUP");

    /**
     * 'Next'.
     */
    private static final String TOTD_NEXT =
        GUIMediator.getStringResource("TOTD_NEXT");

    /**
     * 'Previous'.
     */
    private static final String TOTD_PREVIOUS =
        GUIMediator.getStringResource("TOTD_PREVIOUS");

    /**
     * 'Close'.
     */
    private static final String TOTD_CLOSE =
        GUIMediator.getStringResource("TOTD_CLOSE");

    /**
     * The actual TOTD JDialog.
     */
    private final JDialog _dialog = new JDialog();

    /**
     * The JTextComponent that displays the tip.
     */
    private final JEditorPane _tipPane = new JEditorPane();

    /**
     * The 'Previous' JButton.  Global so it can be
     * enabled/disabled.
     */
    private final JButton _previous;

    /**
     * The prefix to use for general tips.
     */
    private static final String GENERAL = "GENERAL_";

    /**
     * The prefix to use for OSX tips.
     */
    private static final String OSX = "OSX_";

    /**
     * The prefix to use for Windows tips.
     */
    private static final String WINDOWS = "WINDOWS_";

    /**
     * The prefix to use for Linux tips.
     */
    private static final String LINUX = "LINUX_";

    /**
     * The prefix to use for other all other OS' tips.
     */
    private static final String OTHER = "OTHER_";

    /**
     * The prefix to use for non OSX tips.
     */
    private static final String NOT_OSX = "NOT_OSX_";

    /**
     * The prefix to use for Pro tips.
     */
    private static final String PRO = "PRO_";

    /**
     * The prefix to use for Free tips.
     */
    private static final String FREE = "FREE_";

    /**
     * The list of keys that are valid in the resource bundle.
     */
    private static final List<String> KEYS = new ArrayList<String>();

    /**
     * The index of the current tip.
     */
    private static int _currentTip;

    /**
     * The foreground color to use for text.
     */
    private static Color _foreground;

    /**
     * Whether or not we can display the TOTD dialog.
     */
    private boolean _canDisplay = true;


    /**
     * Private constructor that initiates the appropriate things for the TOTD.
     */
    private TipOfTheDayMediator() {
        retrieveKeys();

        _dialog.setModal(false);
        _dialog.setResizable(false);
        _dialog.setTitle(TOTD_TITLE);
        GUIUtils.addHideAction((JComponent)_dialog.getContentPane());

        // Previous' listener must be added here instead of
        // in constructDialog because otherwise multiple
        // listeners will be added when the theme changes.
        _previous = new JButton(TOTD_PREVIOUS);
        _previous.addActionListener(new PreviousTipListener());
        constructDialog();
        ThemeMediator.addThemeObserver(this);
    }

    /**
     * Returns the sole instance of this class.
     */
    public static synchronized TipOfTheDayMediator instance() {
        if  (_instance == null)
            _instance = new TipOfTheDayMediator();
        return _instance;
    }

    /**
     * Redraws the whole dialog upon theme change.
     */
    public void updateComponentTreeUI() {
        SwingUtilities.updateComponentTreeUI(_dialog);
    }

    /**
     * Causes the TOTD window to become visible.
     */
    public void displayTipWindow() {
        GUIMediator.safeInvokeLater(new Runnable() {
            public void run() {
                if (!_canDisplay)
                    return;

                if (_dialog.isShowing()) {
                    _dialog.setVisible(false);
                    _dialog.setVisible(true);
                    _dialog.toFront();
                    return;
                }

                if (GUIMediator.isAppVisible())
                    _dialog.setLocationRelativeTo(GUIMediator.getAppFrame());
                else
                    _dialog.setLocation(GUIMediator.getScreenCenterPoint(_dialog));

                _dialog.setVisible(true);

                if (!"text/html".equals(_tipPane.getContentType())) {
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            _tipPane.setContentType("text/html");
                            setText(getRandomTip());
                        }
                    });
                }

                _dialog.toFront();
            }
        });
    }

    /**
     * Hides the TOTD dialogue window.
     */
    public void hide() {
        _dialog.setVisible(false);
    }

    /**
     * Sets the text of the tip to a new tip.
     */
    private void setText(String tip) {
        int r = _foreground.getRed();
        int g = _foreground.getGreen();
        int b = _foreground.getBlue();
        String foreHex = toHex(r) + toHex(g) + toHex(b);
        _tipPane.setText("<html><body text='#" + foreHex + "'>" + tip + "</html>");
        _tipPane.setCaretPosition(0);
    }

    /**
     * Returns the int as a hex string.
     */
    private String toHex(int i) {
        String hex = Integer.toHexString(i).toUpperCase();
        if(hex.length() == 1)
            return "0" + hex;
        else
            return hex;
    }

    /**
     * Iterates through all the tips' keys and stores the ones
     * that are valid for this OS.
     */
    private void retrieveKeys() {
        ResourceBundle bundle = ResourceManager.getTOTDResourceBundle();
        Enumeration<String> e = bundle.getKeys();
        while(e.hasMoreElements()) {
            final String k = e.nextElement();
            if(k.startsWith(GENERAL))
                KEYS.add(k);
            else if(CommonUtils.isWindows() && k.startsWith(WINDOWS))
                KEYS.add(k);
            else if(CommonUtils.isMacOSX() && k.startsWith(OSX))
                KEYS.add(k);
            else if(CommonUtils.isLinux() && k.startsWith(LINUX))
                KEYS.add(k);
            else if(!CommonUtils.isWindows() &&
                    !CommonUtils.isMacOSX() &&
                    !CommonUtils.isLinux() &&
                    k.startsWith(OTHER))
                KEYS.add(k);
            else if(!CommonUtils.isMacOSX() && k.startsWith(NOT_OSX))
                KEYS.add(k);
            else if(CommonUtils.isPro() && k.startsWith(PRO))
                KEYS.add(k);
            else if(!CommonUtils.isPro() && k.startsWith(FREE))
                KEYS.add(k);
        }

        // randomize the list.
        Collections.shuffle(KEYS);
        _currentTip = -1;
    }

    /**
     * Retrieves a random tip and updates the _currentTip
     * index to that tip.
     */
    private String getRandomTip() {
        // If this is our last key, reshuffle them.
        if(_currentTip == KEYS.size() - 1) {
            Collections.shuffle(KEYS);
            _currentTip = -1;
        } else if(_currentTip < -1)
            _currentTip = -1;

        String k = KEYS.get(++_currentTip);

        if(_currentTip == 0)
            _previous.setEnabled(false);
        else
            _previous.setEnabled(true);

        ResourceBundle bundle = ResourceManager.getTOTDResourceBundle();
        return bundle.getString(k);
    }

    /**
     * Recreates the dialog box to update the theme.
     */
    public void updateTheme() {
        boolean wasShowing = _dialog.isShowing();

        _dialog.setVisible(false);
        _dialog.getContentPane().removeAll();
        // Lower the size of the font in the TIP because
        // it's going to get larger again.
        Font tipFont = new Font(
            _tipPane.getFont().getName(),
            _tipPane.getFont().getStyle(),
            _tipPane.getFont().getSize()-2);
        _tipPane.setFont(tipFont);
        constructDialog();
        _tipPane.setContentType("text/html");
        setText(getRandomTip());


        if (wasShowing) {
            _dialog.setVisible(true);
            _dialog.toFront();
        }
    }

    /**
     * Builds the TOTD dialog.
     */
    private void constructDialog() {
        JPanel imagePanel = new JPanel();
        imagePanel.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1,
                         ThemeFileHandler.TABLE_BACKGROUND_COLOR.getValue()));
        JLabel img = new JLabel(GUIMediator.getThemeImage("question"));
        imagePanel.add(img);

        JPanel didYouKnowPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JLabel didYouKnow = new JLabel(TOTD_INTRO);
        Font didYouKnowFont = new Font(
            "Dialog",
            didYouKnow.getFont().getStyle(),
            didYouKnow.getFont().getSize()+5);
        didYouKnow.setFont(didYouKnowFont);
        didYouKnowPanel.add(Box.createHorizontalStrut(3));
        didYouKnowPanel.add(didYouKnow);

        JPanel tipPanel = new JPanel();
        _foreground = didYouKnow.getForeground();
        tipPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0,
                       ThemeFileHandler.TABLE_BACKGROUND_COLOR.getValue()));
        // THE HTML ENGINE TAKES TOO LONG TO LOAD, SO WE MUST LOAD AS TEXT.
        _tipPane.setContentType("text");
        _tipPane.setEditable(false);
        _tipPane.setBackground(tipPanel.getBackground());
        Font tipFont = new Font(
            "Dialog",
            _tipPane.getFont().getStyle(),
            _tipPane.getFont().getSize()+2);
        _tipPane.setFont(tipFont);
        _tipPane.addHyperlinkListener(GUIUtils.getHyperlinkListener());
        _tipPane.setText(GUIMediator.getStringResource("TOTD_LOADING_TIPS"));
        JScrollPane tipScroller = new JScrollPane(_tipPane);
        tipScroller.setPreferredSize(new Dimension(400, 100));
        tipScroller.setHorizontalScrollBarPolicy(
            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        tipScroller.setVerticalScrollBarPolicy(
            JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        tipScroller.setBorder(null);
        tipPanel.add(tipScroller);

        BoxPanel rightTip = new BoxPanel();
        rightTip.add(Box.createVerticalStrut(10));
        rightTip.add(didYouKnowPanel);
        rightTip.add(tipPanel);

        JPanel wholeTip = new JPanel(new BorderLayout());
        BoxPanel innerTip = new BoxPanel(BoxPanel.X_AXIS);
        innerTip.add(imagePanel);
        innerTip.add(rightTip);
        innerTip.setBorder(BorderFactory.createLoweredBevelBorder());
        wholeTip.add(Box.createHorizontalStrut(5), BorderLayout.WEST);
        wholeTip.add(Box.createHorizontalStrut(5), BorderLayout.EAST);
        wholeTip.add(Box.createVerticalStrut(5), BorderLayout.NORTH);
        wholeTip.add(Box.createVerticalStrut(5), BorderLayout.SOUTH);
        wholeTip.add(innerTip, BorderLayout.CENTER);

        JPanel startupPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JCheckBox showTips = new JCheckBox(TOTD_STARTUP);
        showTips.setSelected(StartupSettings.SHOW_TOTD.getValue());
        startupPanel.add(showTips);

        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        buttonPanel.add(_previous);
        JButton next = new JButton(TOTD_NEXT);
        buttonPanel.add(next);
        JButton close = new JButton(TOTD_CLOSE);
        buttonPanel.add(close);

        JPanel navigation = new JPanel(new BorderLayout());
        navigation.add(startupPanel, BorderLayout.WEST);
        navigation.add(buttonPanel, BorderLayout.EAST);

        showTips.addActionListener(new ShowTipListener());
        next.addActionListener(new NextTipListener());
        close.addActionListener(GUIUtils.getDisposeAction());

        _dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        Container pane = _dialog.getContentPane();
        pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
        pane.add(wholeTip);
        pane.add(Box.createVerticalStrut(5));
        pane.add(navigation);
        try {
            _dialog.pack();
        } catch(OutOfMemoryError oome) {
            // who knows why it happens, but it's an internal error.
            _canDisplay = false;
        }
    }

    /**
     * A listener for changing the state of the 'Show Tips on Startup'.
     */
    private class ShowTipListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            JCheckBox source = (JCheckBox)e.getSource();
            StartupSettings.SHOW_TOTD.setValue(source.isSelected());
        }
    }

    /**
     * A listener for showing the next tip.
     */
    private class NextTipListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            setText(getRandomTip());
        }
    }

    /**
     * A listener for showing the previous tip.
     */
    private class PreviousTipListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            _currentTip = _currentTip - 2;
            setText(getRandomTip());
        }
    }
}


References

sern.ucalgary.ca

www.dofactory.com

my.execpc.com