Frames | No Frames |
1: /* BasicPopupMenuUI.java 2: Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package javax.swing.plaf.basic; 39: 40: import gnu.classpath.NotImplementedException; 41: 42: import java.awt.Component; 43: import java.awt.Dimension; 44: import java.awt.event.ComponentEvent; 45: import java.awt.event.ComponentListener; 46: import java.awt.event.MouseEvent; 47: 48: import javax.swing.BoxLayout; 49: import javax.swing.JComponent; 50: import javax.swing.JMenuItem; 51: import javax.swing.JPopupMenu; 52: import javax.swing.LookAndFeel; 53: import javax.swing.MenuElement; 54: import javax.swing.MenuSelectionManager; 55: import javax.swing.SwingUtilities; 56: import javax.swing.event.PopupMenuEvent; 57: import javax.swing.event.PopupMenuListener; 58: import javax.swing.plaf.ComponentUI; 59: import javax.swing.plaf.PopupMenuUI; 60: 61: 62: /** 63: * UI Delegate for JPopupMenu 64: */ 65: public class BasicPopupMenuUI extends PopupMenuUI 66: { 67: /* popupMenu for which this UI delegate is for*/ 68: protected JPopupMenu popupMenu; 69: 70: /* PopupMenuListener listens to popup menu events fired by JPopupMenu*/ 71: private transient PopupMenuListener popupMenuListener; 72: 73: /* ComponentListener listening to popupMenu's invoker. 74: * This is package-private to avoid an accessor method. */ 75: TopWindowListener topWindowListener; 76: 77: /** 78: * Creates a new BasicPopupMenuUI object. 79: */ 80: public BasicPopupMenuUI() 81: { 82: popupMenuListener = new PopupMenuHandler(); 83: topWindowListener = new TopWindowListener(); 84: } 85: 86: /** 87: * Factory method to create a BasicPopupMenuUI for the given {@link 88: * JComponent}, which should be a {@link JMenuItem}. 89: * 90: * @param x The {@link JComponent} a UI is being created for. 91: * 92: * @return A BasicPopupMenuUI for the {@link JComponent}. 93: */ 94: public static ComponentUI createUI(JComponent x) 95: { 96: return new BasicPopupMenuUI(); 97: } 98: 99: /** 100: * Installs and initializes all fields for this UI delegate. Any properties 101: * of the UI that need to be initialized and/or set to defaults will be 102: * done now. It will also install any listeners necessary. 103: * 104: * @param c The {@link JComponent} that is having this UI installed. 105: */ 106: public void installUI(JComponent c) 107: { 108: super.installUI(c); 109: popupMenu = (JPopupMenu) c; 110: popupMenu.setLayout(new DefaultMenuLayout(popupMenu, BoxLayout.Y_AXIS)); 111: popupMenu.setBorderPainted(true); 112: JPopupMenu.setDefaultLightWeightPopupEnabled(true); 113: 114: installDefaults(); 115: installListeners(); 116: } 117: 118: /** 119: * This method installs the defaults that are defined in the Basic look 120: * and feel for this {@link JPopupMenu}. 121: */ 122: public void installDefaults() 123: { 124: LookAndFeel.installColorsAndFont(popupMenu, "PopupMenu.background", 125: "PopupMenu.foreground", "PopupMenu.font"); 126: LookAndFeel.installBorder(popupMenu, "PopupMenu.border"); 127: popupMenu.setOpaque(true); 128: } 129: 130: /** 131: * This method installs the listeners for the {@link JMenuItem}. 132: */ 133: protected void installListeners() 134: { 135: popupMenu.addPopupMenuListener(popupMenuListener); 136: } 137: 138: /** 139: * This method installs the keyboard actions for this {@link JPopupMenu}. 140: */ 141: protected void installKeyboardActions() 142: throws NotImplementedException 143: { 144: // FIXME: Need to implement 145: } 146: 147: /** 148: * Performs the opposite of installUI. Any properties or resources that need 149: * to be cleaned up will be done now. It will also uninstall any listeners 150: * it has. In addition, any properties of this UI will be nulled. 151: * 152: * @param c The {@link JComponent} that is having this UI uninstalled. 153: */ 154: public void uninstallUI(JComponent c) 155: { 156: uninstallListeners(); 157: uninstallDefaults(); 158: popupMenu = null; 159: } 160: 161: /** 162: * This method uninstalls the defaults and sets any objects created during 163: * install to null 164: */ 165: protected void uninstallDefaults() 166: { 167: popupMenu.setBackground(null); 168: popupMenu.setBorder(null); 169: popupMenu.setFont(null); 170: popupMenu.setForeground(null); 171: } 172: 173: /** 174: * Unregisters all the listeners that this UI delegate was using. 175: */ 176: protected void uninstallListeners() 177: { 178: popupMenu.removePopupMenuListener(popupMenuListener); 179: } 180: 181: /** 182: * Uninstalls any keyboard actions. 183: */ 184: protected void uninstallKeyboardActions() 185: throws NotImplementedException 186: { 187: // FIXME: Need to implement 188: } 189: 190: /** 191: * This method returns the minimum size of the JPopupMenu. 192: * 193: * @param c The JComponent to find a size for. 194: * 195: * @return The minimum size. 196: */ 197: public Dimension getMinimumSize(JComponent c) 198: { 199: return null; 200: } 201: 202: /** 203: * This method returns the preferred size of the JPopupMenu. 204: * 205: * @param c The JComponent to find a size for. 206: * 207: * @return The preferred size. 208: */ 209: public Dimension getPreferredSize(JComponent c) 210: { 211: return null; 212: } 213: 214: /** 215: * This method returns the minimum size of the JPopupMenu. 216: * 217: * @param c The JComponent to find a size for. 218: * 219: * @return The minimum size. 220: */ 221: public Dimension getMaximumSize(JComponent c) 222: { 223: return null; 224: } 225: 226: /** 227: * Return true if given mouse event is a platform popup trigger, and false 228: * otherwise 229: * 230: * @param e MouseEvent that is to be checked for popup trigger event 231: * 232: * @return true if given mouse event is a platform popup trigger, and false 233: * otherwise 234: */ 235: public boolean isPopupTrigger(MouseEvent e) 236: { 237: return false; 238: } 239: 240: /** 241: * This listener handles PopupMenuEvents fired by JPopupMenu 242: */ 243: private class PopupMenuHandler implements PopupMenuListener 244: { 245: /** 246: * This method is invoked when JPopupMenu is cancelled. 247: * 248: * @param event the PopupMenuEvent 249: */ 250: public void popupMenuCanceled(PopupMenuEvent event) 251: { 252: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 253: manager.clearSelectedPath(); 254: } 255: 256: /** 257: * This method is invoked when JPopupMenu becomes invisible 258: * 259: * @param event the PopupMenuEvent 260: */ 261: public void popupMenuWillBecomeInvisible(PopupMenuEvent event) 262: { 263: // remove listener that listens to component events fired 264: // by the top - level window that this popup belongs to. 265: Component invoker = popupMenu.getInvoker(); 266: Component rootContainer = SwingUtilities.getRoot(invoker); 267: if (rootContainer != null) 268: rootContainer.removeComponentListener(topWindowListener); 269: } 270: 271: /** 272: * This method is invoked when JPopupMenu becomes visible 273: * 274: * @param event the PopupMenuEvent 275: */ 276: public void popupMenuWillBecomeVisible(PopupMenuEvent event) 277: { 278: // Adds topWindowListener to top-level window to listener to 279: // ComponentEvents fired by it. We need to cancel this popup menu 280: // if topWindow to which this popup belongs was resized or moved. 281: Component invoker = popupMenu.getInvoker(); 282: Component rootContainer = SwingUtilities.getRoot(invoker); 283: rootContainer.addComponentListener(topWindowListener); 284: 285: // if this popup menu is a free floating popup menu, 286: // then by default its first element should be always selected when 287: // this popup menu becomes visible. 288: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 289: 290: if (manager.getSelectedPath().length == 0) 291: { 292: // Set selected path to point to the first item in the popup menu 293: MenuElement[] path = new MenuElement[2]; 294: path[0] = popupMenu; 295: Component[] comps = popupMenu.getComponents(); 296: if (comps.length != 0 && comps[0] instanceof MenuElement) 297: { 298: path[1] = (MenuElement) comps[0]; 299: manager.setSelectedPath(path); 300: } 301: } 302: } 303: } 304: 305: /** 306: * ComponentListener that listens to Component Events fired by the top - 307: * level window to which popup menu belongs. If top-level window was 308: * resized, moved or hidded then popup menu will be hidded and selected 309: * path of current menu hierarchy will be set to null. 310: */ 311: private class TopWindowListener implements ComponentListener 312: { 313: /** 314: * This method is invoked when top-level window is resized. This method 315: * closes current menu hierarchy. 316: * 317: * @param e The ComponentEvent 318: */ 319: public void componentResized(ComponentEvent e) 320: { 321: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 322: manager.clearSelectedPath(); 323: } 324: 325: /** 326: * This method is invoked when top-level window is moved. This method 327: * closes current menu hierarchy. 328: * 329: * @param e The ComponentEvent 330: */ 331: public void componentMoved(ComponentEvent e) 332: { 333: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 334: manager.clearSelectedPath(); 335: } 336: 337: /** 338: * This method is invoked when top-level window is shown This method 339: * does nothing by default. 340: * 341: * @param e The ComponentEvent 342: */ 343: public void componentShown(ComponentEvent e) 344: { 345: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 346: manager.clearSelectedPath(); 347: } 348: 349: /** 350: * This method is invoked when top-level window is hidden This method 351: * closes current menu hierarchy. 352: * 353: * @param e The ComponentEvent 354: */ 355: public void componentHidden(ComponentEvent e) 356: { 357: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 358: manager.clearSelectedPath(); 359: } 360: } 361: 362: }