Difference between revisions of "Mediator"
(→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
Contents
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()); } } }