/* * org.openmicroscopy.shoola.env.ui.TopWindowGroup * *------------------------------------------------------------------------------ * Copyright (C) 2006 University of Dundee. All rights reserved. * * * This program 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; either version 2 of the License, or * (at your option) any later version. * This program 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 this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.env.ui; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.HashMap; import java.util.Map; import javax.swing.AbstractButton; import javax.swing.Icon; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuItem; /** * Links a group of windows to the {@link TaskBar} and manages their display * on screen. * <p>Rather than adding an entry in the * {@link TaskBar#WINDOW_MENU} for each window in the group}. * These menus contain an entry * for each window in the group and are populated/depopulated via the * {@link #add(TopWindow, String, Icon) add}/{@link #remove(JFrame) remove} * methods.</p> * <p>All those menu entries are display-trigger buttons that cause the * corresponding window to be shown on screen. This class uses the * {@link TopWindowManager} to control mouse clicks on these buttons as well as * to manage the display state of the windows in the group.</p> * * @see org.openmicroscopy.shoola.env.ui.TopWindowManager * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author <br>Andrea Falconi      * <a href="mailto:a.falconi@dundee.ac.uk"> * a.falconi@dundee.ac.uk</a> * @version 2.2 * @since OME2.2 */ public class TopWindowGroup { /** * Just a record to hold the display buttons of a window and its manager. */ private static class WindowConfig { /** The windows sub menu item. */ JMenuItem winSubMenuEntry; /** Reference to the manager. */ TopWindowManager manager; } /** Cached reference to the {@link TaskBar}. */ private TaskBar taskBar; /** The sub-menu in the {@link TaskBar#WINDOW_MENU}. */ private JMenu winSubMenu; /** Maps each window in the group to its configuration object. */ private Map windows; /** The close all item in the {@link #winSubMenu}.*/ private JMenuItem closeAllWinSubMenuEntry; /** The close all item in the {@link #dropDownButton}. */ private JMenuItem closeAllDropDownButtonEntry; /** * Helper method to create the display buttons and the manager for the * specified window. * * @param window The window. * @return A record-like class containing the display buttons and the * manager for <code>window</code>. */ private WindowConfig makeConfigFor(TopWindow window) { WindowConfig cfg = new WindowConfig(); cfg.winSubMenuEntry = new JMenuItem(); cfg.manager = new TopWindowManager(window, new AbstractButton[] {cfg.winSubMenuEntry}); return cfg; } /** * Creates the close all buttons and attaches the needed listeners. */ private void makeCloseAllButtons() { String closeAll = "Close All"; closeAllWinSubMenuEntry = new JMenuItem(closeAll); closeAllDropDownButtonEntry = new JMenuItem(closeAll); ActionListener al = new ActionListener() { public void actionPerformed(ActionEvent ae) { removeAll(true); } }; closeAllWinSubMenuEntry.addActionListener(al); closeAllDropDownButtonEntry.addActionListener(al); } /** * Helper method to add the close all items to the {@link #winSubMenu} and * to the {@link #dropDownButton}. */ private void addCloseAllButtons() { winSubMenu.add(closeAllWinSubMenuEntry); winSubMenu.addSeparator(); } /** * Helper method to remove all items from the {@link #winSubMenu}. * This method is called after the last window has been removed from this * group so as to get rid of the close all buttons and separators. */ private void clearMenus() { winSubMenu.removeAll(); winSubMenu.setEnabled(false); } /** * Creates a new window group. * This constructor adds a sub-menu to the * {@link TaskBar#WINDOW_MENU}. These menus can then be populated/ * depopulated via the {@link #add(TopWindow, String, Icon) add}/ * {@link #remove(JFrame) remove} methods. * * @param name The name of this window group. This will also be the * text displayed by the sub-menu entry in the * {@link TaskBar#WINDOW_MENU}. * @param icon The icon of this window group. This icon will be displayed * both by the the sub-menu entry in the * {@link TaskBar#WINDOW_MENU}. * @param tb A reference to the task bar. */ public TopWindowGroup(String name, Icon icon, TaskBar tb) { if (tb == null) throw new NullPointerException("No reference to the TaskBar."); if (name == null || name.length() == 0) throw new IllegalArgumentException("Must provide a name."); taskBar = tb; winSubMenu = new JMenu(name); winSubMenu.setIcon(icon); winSubMenu.setEnabled(false); taskBar.addToMenu(TaskBar.WINDOW_MENU, winSubMenu); windows = new HashMap(); makeCloseAllButtons(); } /** * Returns the window sub-menu entry. * * @return See above. */ public JMenu getWinMenuEntry() { return winSubMenu; } /** * Adds the specified window to this group. * This method also creates the display buttons for the window. This means * an entry will be added to the sub-menu in the * {@link TaskBar#WINDOW_MENU}. * * @param window The window to add. * @param name The text label for the display buttons. * @param icon The icon for the display buttons. */ public void add(TopWindow window, String name, Icon icon) { if (window == null) return; if (name == null || name.length() == 0) throw new IllegalArgumentException("Must provide a name."); WindowConfig cfg = (WindowConfig) windows.get(window); if (cfg == null) { cfg = makeConfigFor(window); windows.put(window, cfg); } cfg.winSubMenuEntry.setText(name); cfg.winSubMenuEntry.setIcon(icon); //NOTE: If window has already a cfg, then we simply overwrite the //previous text and icon of the display buttons. if (windows.size() == 1) addCloseAllButtons(); winSubMenu.setEnabled(true); winSubMenu.add(cfg.winSubMenuEntry); } /** * Removes the specified window from this group. * This method also removes the display buttons for the window. However, * this method doesn't affect the current state of the window — so * if the window is showing on screen, it won't be hidden or disposed. * * @param window The window to remove. */ public void remove(JFrame window) { WindowConfig cfg = (WindowConfig) windows.get(window); if (cfg == null) return; windows.remove(window); if (windows.size() == 0) clearMenus(); winSubMenu.remove(cfg.winSubMenuEntry); } /** * Removes the specified window from this group. * This method also removes the display buttons for the window. * If <code>dispose</code> is <code>true</code>, then the window is also * disposed, oterwise this method doesn't affect the current state of the * window — so if the window is showing on screen, it won't be hidden * or disposed. * * @param window The window to remove. * @param dispose Tells whether to dispose of the window. */ public void remove(JFrame window, boolean dispose) { if (window == null) return; remove(window); if (dispose) window.dispose(); } /** * Removes all windows currently in this group. * This method also removes the display buttons for each window. However, * this method doesn't affect the current state of the windows — so * if a window is showing on screen, it won't be hidden or disposed. */ public void removeAll() { removeAll(false); } /** * Calls {@link #remove(JFrame, boolean) remove(window, dispose)} for each * <code>window</code> currently in this group. * * @param dispose Tells whether to dispose of the windows. */ public void removeAll(boolean dispose) { int k = windows.size(); if (k == 0) return; JFrame[] wIterator = new JFrame[k]; windows.keySet().toArray(wIterator); //NOTE: Using Iterator would cause a ConcurrentModificationException. for (k = 0; k < wIterator.length; ++k) remove(wIterator[k], dispose); } //NOTE: we may want to add methods hideAll, removeAndHideAll, and so on. }