GNU Classpath (0.19) | ||
Frames | No Frames |
1: /* BasicMenuUI.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: 39: package javax.swing.plaf.basic; 40: 41: import java.awt.Component; 42: import java.awt.Dimension; 43: import java.awt.event.MouseEvent; 44: import java.beans.PropertyChangeEvent; 45: import java.beans.PropertyChangeListener; 46: 47: import javax.swing.JComponent; 48: import javax.swing.JMenu; 49: import javax.swing.JMenuBar; 50: import javax.swing.JPopupMenu; 51: import javax.swing.LookAndFeel; 52: import javax.swing.MenuSelectionManager; 53: import javax.swing.UIDefaults; 54: import javax.swing.UIManager; 55: import javax.swing.event.ChangeEvent; 56: import javax.swing.event.ChangeListener; 57: import javax.swing.event.MenuDragMouseEvent; 58: import javax.swing.event.MenuDragMouseListener; 59: import javax.swing.event.MenuEvent; 60: import javax.swing.event.MenuKeyEvent; 61: import javax.swing.event.MenuKeyListener; 62: import javax.swing.event.MenuListener; 63: import javax.swing.event.MouseInputListener; 64: import javax.swing.plaf.ComponentUI; 65: 66: /** 67: * UI Delegate for JMenu 68: */ 69: public class BasicMenuUI extends BasicMenuItemUI 70: { 71: protected ChangeListener changeListener; 72: 73: /* MenuListener listens to MenuEvents fired by JMenu */ 74: protected MenuListener menuListener; 75: 76: /* PropertyChangeListner that listens to propertyChangeEvents occuring in JMenu*/ 77: protected PropertyChangeListener propertyChangeListener; 78: 79: /** 80: * Creates a new BasicMenuUI object. 81: */ 82: public BasicMenuUI() 83: { 84: mouseInputListener = createMouseInputListener((JMenu) menuItem); 85: menuListener = createMenuListener((JMenu) menuItem); 86: propertyChangeListener = createPropertyChangeListener((JMenu) menuItem); 87: } 88: 89: /** 90: * This method creates a new ChangeListener. 91: * 92: * @return A new ChangeListener. 93: */ 94: protected ChangeListener createChangeListener(JComponent c) 95: { 96: return new ChangeHandler((JMenu) c, this); 97: } 98: 99: /** 100: * This method creates new MenuDragMouseListener to listen to mouse dragged events 101: * occuring in the Menu 102: * 103: * @param c the menu to listen to 104: * 105: * @return The MenuDrageMouseListener 106: */ 107: protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) 108: { 109: return new MenuDragMouseHandler(); 110: } 111: 112: /** 113: * This method creates new MenuDragKeyListener to listen to key events 114: * 115: * @param c the menu to listen to 116: * 117: * @return The MenuKeyListener 118: */ 119: protected MenuKeyListener createMenuKeyListener(JComponent c) 120: { 121: return new MenuKeyHandler(); 122: } 123: 124: /** 125: * This method creates new MenuListener to listen to menu events 126: * occuring in the Menu 127: * 128: * @param c the menu to listen to 129: * 130: * @return The MenuListener 131: */ 132: protected MenuListener createMenuListener(JComponent c) 133: { 134: return new MenuHandler(); 135: } 136: 137: /** 138: * This method creates new MouseInputListener to listen to mouse input events 139: * occuring in the Menu 140: * 141: * @param c the menu to listen to 142: * 143: * @return The MouseInputListener 144: */ 145: protected MouseInputListener createMouseInputListener(JComponent c) 146: { 147: return new MouseInputHandler(); 148: } 149: 150: /** 151: * This method creates newPropertyChangeListener to listen to property changes 152: * occuring in the Menu 153: * 154: * @param c the menu to listen to 155: * 156: * @return The PropertyChangeListener 157: */ 158: protected PropertyChangeListener createPropertyChangeListener(JComponent c) 159: { 160: return new PropertyChangeHandler(); 161: } 162: 163: /** 164: * This method creates a new BasicMenuUI. 165: * 166: * @param c The JComponent to create a UI for. 167: * 168: * @return A new BasicMenuUI. 169: */ 170: public static ComponentUI createUI(JComponent c) 171: { 172: return new BasicMenuUI(); 173: } 174: 175: /** 176: * Get the component's maximum size. 177: * 178: * @param c The JComponent for which to get maximum size 179: * 180: * @return The maximum size of the component 181: */ 182: public Dimension getMaximumSize(JComponent c) 183: { 184: return c.getPreferredSize(); 185: } 186: 187: /** 188: * Returns the prefix for entries in the {@link UIDefaults} table. 189: * 190: * @return "Menu" 191: */ 192: protected String getPropertyPrefix() 193: { 194: return "Menu"; 195: } 196: 197: /** 198: * Initializes any default properties that this UI has from the defaults for 199: * the Basic look and feel. 200: */ 201: protected void installDefaults() 202: { 203: LookAndFeel.installBorder(menuItem, "Menu.border"); 204: LookAndFeel.installColorsAndFont(menuItem, "Menu.background", 205: "Menu.foreground", "Menu.font"); 206: menuItem.setMargin(UIManager.getInsets("Menu.margin")); 207: acceleratorFont = UIManager.getFont("Menu.acceleratorFont"); 208: acceleratorForeground = UIManager.getColor("Menu.acceleratorForeground"); 209: acceleratorSelectionForeground = UIManager.getColor("Menu.acceleratorSelectionForeground"); 210: selectionBackground = UIManager.getColor("Menu.selectionBackground"); 211: selectionForeground = UIManager.getColor("Menu.selectionForeground"); 212: arrowIcon = UIManager.getIcon("Menu.arrowIcon"); 213: oldBorderPainted = UIManager.getBoolean("Menu.borderPainted"); 214: menuItem.setOpaque(true); 215: } 216: 217: /** 218: * Installs any keyboard actions. The list of keys that need to be bound are 219: * listed in Basic look and feel's defaults. 220: * 221: */ 222: protected void installKeyboardActions() 223: { 224: // FIXME: Need to implement 225: } 226: 227: /** 228: * Creates and registers all the listeners for this UI delegate. 229: */ 230: protected void installListeners() 231: { 232: ((JMenu) menuItem).addMouseListener(mouseInputListener); 233: ((JMenu) menuItem).addMouseMotionListener(mouseInputListener); 234: ((JMenu) menuItem).addMenuListener(menuListener); 235: ((JMenu) menuItem).addMenuDragMouseListener(menuDragMouseListener); 236: } 237: 238: protected void setupPostTimer(JMenu menu) 239: { 240: // TODO: Implement this properly. 241: } 242: 243: /** 244: * This method uninstalls the defaults and sets any objects created during 245: * install to null 246: */ 247: protected void uninstallDefaults() 248: { 249: menuItem.setBackground(null); 250: menuItem.setBorder(null); 251: menuItem.setFont(null); 252: menuItem.setForeground(null); 253: menuItem.setMargin(null); 254: acceleratorFont = null; 255: acceleratorForeground = null; 256: acceleratorSelectionForeground = null; 257: selectionBackground = null; 258: selectionForeground = null; 259: arrowIcon = null; 260: } 261: 262: /** 263: * Uninstalls any keyboard actions. The list of keys used are listed in 264: * Basic look and feel's defaults. 265: */ 266: protected void uninstallKeyboardActions() 267: { 268: // FIXME: Need to implement 269: } 270: 271: /** 272: * Unregisters all the listeners that this UI delegate was using. In 273: * addition, it will also null any listeners that it was using. 274: */ 275: protected void uninstallListeners() 276: { 277: ((JMenu) menuItem).removeMouseListener(mouseInputListener); 278: ((JMenu) menuItem).removeMenuListener(menuListener); 279: ((JMenu) menuItem).removePropertyChangeListener(propertyChangeListener); 280: } 281: 282: /** 283: * This class is used by menus to handle mouse events occuring in the 284: * menu. 285: */ 286: protected class MouseInputHandler implements MouseInputListener 287: { 288: public void mouseClicked(MouseEvent e) 289: { 290: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 291: manager.processMouseEvent(e); 292: } 293: 294: public void mouseDragged(MouseEvent e) 295: { 296: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 297: manager.processMouseEvent(e); 298: } 299: 300: private boolean popupVisible() 301: { 302: JMenuBar mb = (JMenuBar) ((JMenu) menuItem).getParent(); 303: // check if mb.isSelected because if no menus are selected 304: // we don't have to look through the list for popup menus 305: if (!mb.isSelected()) 306: return false; 307: for (int i = 0; i < mb.getMenuCount(); i++) 308: { 309: JMenu m = mb.getMenu(i); 310: if (m != null && m.isPopupMenuVisible()) 311: return true; 312: } 313: return false; 314: } 315: 316: public void mouseEntered(MouseEvent e) 317: { 318: /* When mouse enters menu item, it should be considered selected 319: 320: if (i) if this menu is a submenu in some other menu 321: (ii) or if this menu is in a menu bar and some other menu in a 322: menu bar was just selected and has its popup menu visible. 323: (If nothing was selected, menu should be pressed before 324: it will be selected) 325: */ 326: JMenu menu = (JMenu) menuItem; 327: 328: // NOTE: the following if used to require !menu.isArmed but I could find 329: // no reason for this and it was preventing some JDK-compatible behaviour. 330: // Specifically, if a menu is selected but its popup menu not visible, 331: // and then another menu is selected whose popup menu IS visible, when 332: // the mouse is moved over the first menu, its popup menu should become 333: // visible. 334: 335: if (! menu.isTopLevelMenu() || popupVisible()) 336: { 337: // set new selection and forward this event to MenuSelectionManager 338: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 339: manager.setSelectedPath(getPath()); 340: manager.processMouseEvent(e); 341: } 342: } 343: 344: public void mouseExited(MouseEvent e) 345: { 346: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 347: manager.processMouseEvent(e); 348: } 349: 350: public void mouseMoved(MouseEvent e) 351: { 352: // TODO: What should be done here, if anything? 353: } 354: 355: public void mousePressed(MouseEvent e) 356: { 357: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 358: JMenu menu = (JMenu) menuItem; 359: manager.processMouseEvent(e); 360: 361: // Menu should be displayed when the menu is pressed only if 362: // it is top-level menu 363: if (menu.isTopLevelMenu()) 364: { 365: if (menu.getPopupMenu().isVisible()) 366: // If menu is visible and menu button was pressed.. 367: // then need to cancel the menu 368: manager.clearSelectedPath(); 369: else 370: { 371: // Display the menu 372: int x = 0; 373: int y = menu.getHeight(); 374: 375: manager.setSelectedPath(getPath()); 376: 377: JMenuBar mb = (JMenuBar) menu.getParent(); 378: 379: // set selectedIndex of the selectionModel of a menuBar 380: mb.getSelectionModel().setSelectedIndex(mb.getComponentIndex(menu)); 381: } 382: } 383: } 384: 385: public void mouseReleased(MouseEvent e) 386: { 387: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 388: manager.processMouseEvent(e); 389: } 390: } 391: 392: /** 393: * This class handles MenuEvents fired by the JMenu 394: */ 395: protected class MenuHandler implements MenuListener 396: { 397: /** 398: * This method is called when menu is cancelled. The menu is cancelled 399: * when its popup menu is closed without selection. It clears selected index 400: * in the selectionModel of the menu parent. 401: * 402: * @param e The MenuEvent. 403: */ 404: public void menuCanceled(MenuEvent e) 405: { 406: menuDeselected(e); 407: } 408: 409: /** 410: * This method is called when menu is deselected. It clears selected index 411: * in the selectionModel of the menu parent. 412: * 413: * @param e The MenuEvent. 414: */ 415: public void menuDeselected(MenuEvent e) 416: { 417: JMenu menu = (JMenu) menuItem; 418: if (menu.getParent() != null) 419: { 420: if (menu.isTopLevelMenu()) 421: ((JMenuBar) menu.getParent()).getSelectionModel().clearSelection(); 422: else 423: ((JPopupMenu) menu.getParent()).getSelectionModel().clearSelection(); 424: } 425: } 426: 427: /** 428: * This method is called when menu is selected. It sets selected index 429: * in the selectionModel of the menu parent. 430: * 431: * @param e The MenuEvent. 432: */ 433: public void menuSelected(MenuEvent e) 434: { 435: JMenu menu = (JMenu) menuItem; 436: if (menu.isTopLevelMenu()) 437: ((JMenuBar) menu.getParent()).setSelected(menu); 438: else 439: ((JPopupMenu) menu.getParent()).setSelected(menu); 440: } 441: } 442: 443: /** 444: * This class handles PropertyChangeEvents fired from the JMenu 445: */ 446: protected class PropertyChangeHandler implements PropertyChangeListener 447: { 448: /** 449: * This method is called whenever one of the properties of the menu item 450: * changes. 451: * 452: * @param e The PropertyChangeEvent. 453: */ 454: public void propertyChange(PropertyChangeEvent e) 455: { 456: // TODO: Implement this properly. 457: } 458: } 459: 460: /** 461: * @deprecated 462: */ 463: public class ChangeHandler implements ChangeListener 464: { 465: /** 466: * Not used. 467: */ 468: public boolean isSelected; 469: 470: /** 471: * Not used. 472: */ 473: public JMenu menu; 474: 475: /** 476: * Not used. 477: */ 478: public BasicMenuUI ui; 479: 480: /** 481: * Not used. 482: */ 483: public Component wasFocused; 484: 485: /** 486: * Not used. 487: */ 488: public ChangeHandler(JMenu m, BasicMenuUI ui) 489: { 490: // Not used. 491: } 492: 493: /** 494: * Not used. 495: */ 496: public void stateChanged(ChangeEvent e) 497: { 498: // Not used. 499: } 500: } 501: 502: /** 503: * This class handles mouse dragged events occuring in the menu. 504: */ 505: protected class MenuDragMouseHandler implements MenuDragMouseListener 506: { 507: /** 508: * This method is invoked when mouse is dragged over the menu item. 509: * 510: * @param e The MenuDragMouseEvent 511: */ 512: public void menuDragMouseDragged(MenuDragMouseEvent e) 513: { 514: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 515: manager.setSelectedPath(e.getPath()); 516: } 517: 518: /** 519: * This method is invoked when mouse enters the menu item while it is 520: * being dragged. 521: * 522: * @param e The MenuDragMouseEvent 523: */ 524: public void menuDragMouseEntered(MenuDragMouseEvent e) 525: { 526: MenuSelectionManager manager = MenuSelectionManager.defaultManager(); 527: manager.setSelectedPath(e.getPath()); 528: } 529: 530: /** 531: * This method is invoked when mouse exits the menu item while 532: * it is being dragged 533: * 534: * @param e The MenuDragMouseEvent 535: */ 536: public void menuDragMouseExited(MenuDragMouseEvent e) 537: { 538: // TODO: What should be done here, if anything? 539: } 540: 541: /** 542: * This method is invoked when mouse was dragged and released 543: * inside the menu item. 544: * 545: * @param e The MenuDragMouseEvent 546: */ 547: public void menuDragMouseReleased(MenuDragMouseEvent e) 548: { 549: // TODO: What should be done here, if anything? 550: } 551: } 552: 553: /** 554: * This class handles key events occuring when menu item is visible on the 555: * screen. 556: */ 557: protected class MenuKeyHandler implements MenuKeyListener 558: { 559: /** 560: * This method is invoked when key has been pressed 561: * 562: * @param e A {@link MenuKeyEvent}. 563: */ 564: public void menuKeyPressed(MenuKeyEvent e) 565: { 566: // TODO: What should be done here, if anything? 567: } 568: 569: /** 570: * This method is invoked when key has been pressed 571: * 572: * @param e A {@link MenuKeyEvent}. 573: */ 574: public void menuKeyReleased(MenuKeyEvent e) 575: { 576: // TODO: What should be done here, if anything? 577: } 578: 579: /** 580: * This method is invoked when key has been typed 581: * It handles the mnemonic key for the menu item. 582: * 583: * @param e A {@link MenuKeyEvent}. 584: */ 585: public void menuKeyTyped(MenuKeyEvent e) 586: { 587: // TODO: What should be done here, if anything? 588: } 589: } 590: }
GNU Classpath (0.19) |