GNU Classpath (0.18) | ||
Frames | No Frames |
1: /* JPopupMenu.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; 40: 41: import java.awt.Component; 42: import java.awt.Container; 43: import java.awt.Dimension; 44: import java.awt.GridBagConstraints; 45: import java.awt.Insets; 46: import java.awt.Panel; 47: import java.awt.Point; 48: import java.awt.event.KeyEvent; 49: import java.awt.event.MouseEvent; 50: import java.beans.PropertyChangeEvent; 51: import java.beans.PropertyChangeListener; 52: import java.io.IOException; 53: import java.io.ObjectInputStream; 54: import java.io.ObjectOutputStream; 55: import java.util.ArrayList; 56: import java.util.EventListener; 57: 58: import javax.accessibility.Accessible; 59: import javax.accessibility.AccessibleContext; 60: import javax.accessibility.AccessibleRole; 61: import javax.swing.event.PopupMenuEvent; 62: import javax.swing.event.PopupMenuListener; 63: import javax.swing.plaf.PopupMenuUI; 64: 65: /** 66: * JPopupMenu is a container that is used to display popup menu's menu 67: * items. By default JPopupMenu is a lightweight container, however if it 68: * is the case that JPopupMenu's bounds are outside of main window, then 69: * heawyweight container will be used to display menu items. It is also 70: * possible to change JPopupMenu's default behavior and set JPopupMenu 71: * to always use heavyweight container. 72: * 73: * JPopupMenu can be displayed anywhere; it is a floating free popup menu. 74: * However before JPopupMenu is diplayed, its invoker property should be set. 75: * JPopupMenu's invoker is a component relative to which popup menu is 76: * displayed. 77: * 78: * JPopupMenu fires PopupMenuEvents to its registered listeners. Whenever 79: * JPopupMenu becomes visible on the screen then PopupMenuEvent indicating 80: * that popup menu became visible will be fired. In the case when 81: * JPopupMenu becomes invisible or cancelled without selection, then 82: * popupMenuBecomeInvisible() or popupMenuCancelled() methods of 83: * PopupMenuListeners will be invoked. 84: * 85: * JPopupMenu also fires PropertyChangeEvents when its bound properties 86: * change.In addittion to inheritted bound properties, JPopupMenu has 87: * 'visible' bound property. When JPopupMenu becomes visible/invisible on 88: * the screen it fires PropertyChangeEvents to its registered 89: * PropertyChangeListeners. 90: */ 91: public class JPopupMenu extends JComponent implements Accessible, MenuElement 92: { 93: private static final long serialVersionUID = -8336996630009646009L; 94: 95: /* indicates if popup's menu border should be painted*/ 96: private boolean borderPainted = true; 97: 98: /** Flag indicating whether lightweight, mediumweight or heavyweight popup 99: is used to display menu items. 100: 101: These are the possible cases: 102: 103: 1. if DefaultLightWeightPopupEnabled true 104: (i) use lightweight container if popup feets inside top-level window 105: (ii) only use heavyweight container (JWindow) if popup doesn't fit. 106: 107: 2. if DefaultLightWeightPopupEnabled false 108: (i) if popup fits, use awt.Panel (mediumWeight) 109: (ii) if popup doesn't fit, use JWindow (heavyWeight) 110: */ 111: private static boolean DefaultLightWeightPopupEnabled = true; 112: 113: /* Component that invokes popup menu. */ 114: transient Component invoker; 115: 116: /* Label for this popup menu. It is not used in most of the look and feel themes. */ 117: private String label; 118: 119: /*Amount of space between menuItem's in JPopupMenu and JPopupMenu's border */ 120: private Insets margin; 121: 122: /** Indicates whether ligthWeight container can be used to display popup 123: menu. This flag is the same as DefaultLightWeightPopupEnabled, but setting 124: this flag can change popup menu after creation of the object */ 125: private boolean lightWeightPopupEnabled; 126: 127: /** SelectionModel that keeps track of menu selection. */ 128: private SingleSelectionModel selectionModel; 129: 130: /* Popup that is used to display JPopupMenu */ 131: private transient Popup popup; 132: 133: /* Location of the popup */ 134: private Point popupLocation; 135: 136: /* Field indicating if popup menu is visible or not */ 137: private boolean visible = false; 138: 139: /** 140: * Creates a new JPopupMenu object. 141: */ 142: public JPopupMenu() 143: { 144: this(null); 145: } 146: 147: /** 148: * Creates a new JPopupMenu with specified label 149: * 150: * @param label Label for popup menu. 151: */ 152: public JPopupMenu(String label) 153: { 154: lightWeightPopupEnabled = getDefaultLightWeightPopupEnabled(); 155: setLabel(label); 156: setSelectionModel(new DefaultSingleSelectionModel()); 157: super.setVisible(false); 158: updateUI(); 159: } 160: 161: private void readObject(ObjectInputStream stream) 162: throws IOException, ClassNotFoundException 163: { 164: } 165: 166: private void writeObject(ObjectOutputStream stream) throws IOException 167: { 168: } 169: 170: /** 171: * Adds given menu item to the popup menu 172: * 173: * @param item menu item to add to the popup menu 174: * 175: * @return menu item that was added to the popup menu 176: */ 177: public JMenuItem add(JMenuItem item) 178: { 179: this.insert(item, -1); 180: return item; 181: } 182: 183: /** 184: * Constructs menu item with a specified label and adds it to 185: * popup menu 186: * 187: * @param text label for the menu item to be added 188: * 189: * @return constructed menu item that was added to the popup menu 190: */ 191: public JMenuItem add(String text) 192: { 193: JMenuItem item = new JMenuItem(text); 194: return add(item); 195: } 196: 197: /** 198: * Constructs menu item associated with the specified action 199: * and adds it to the popup menu 200: * 201: * @param action Action for the new menu item 202: * 203: * @return menu item that was added to the menu 204: */ 205: public JMenuItem add(Action action) 206: { 207: JMenuItem item = createActionComponent(action); 208: 209: if (action != null) 210: action.addPropertyChangeListener(createActionChangeListener(item)); 211: 212: return add(item); 213: } 214: 215: /** 216: * Revomes component at the given index from the menu. 217: * 218: * @param index index of the component that will be removed in the menu 219: */ 220: public void remove(int index) 221: { 222: super.remove(index); 223: 224: GridBagConstraints constraints = new GridBagConstraints(); 225: constraints.fill = GridBagConstraints.BOTH; 226: constraints.weightx = 100.0; 227: constraints.weighty = 100.0; 228: 229: Component[] items = getComponents(); 230: for (int i = index; i < items.length; i++) 231: { 232: constraints.gridy = i; 233: super.add(items[i], constraints, i); 234: } 235: this.setSize(this.getPreferredSize()); 236: } 237: 238: /** 239: * Create menu item associated with the given action 240: * and inserts it into the popup menu at the specified index 241: * 242: * @param action Action for the new menu item 243: * @param index index in the popup menu at which to insert new menu item. 244: */ 245: public void insert(Action action, int index) 246: { 247: JMenuItem item = new JMenuItem(action); 248: this.insert(item, index); 249: } 250: 251: /** 252: * Insert given component to the popup menu at the 253: * specified index 254: * 255: * @param component Component to insert 256: * @param index Index at which to insert given component 257: */ 258: public void insert(Component component, int index) 259: { 260: GridBagConstraints constraints = new GridBagConstraints(); 261: constraints.fill = GridBagConstraints.BOTH; 262: constraints.weightx = 100.0; 263: constraints.weighty = 100.0; 264: 265: constraints.gridy = index; 266: super.add(component, constraints, index); 267: 268: // need to change constraints for the components that were moved by 1 269: // due to the insertion 270: if (index != -1) 271: { 272: Component[] items = getComponents(); 273: 274: for (int i = index + 1; i < items.length; i++) 275: { 276: constraints.gridy = i; 277: super.add(items[i], constraints, i); 278: } 279: } 280: this.setSize(this.getPreferredSize()); 281: } 282: 283: /** 284: * Returns flag indicating if newly created JPopupMenu will use 285: * heavyweight or lightweight container to display its menu items 286: * 287: * @return true if JPopupMenu will use lightweight container to display 288: * menu items by default, and false otherwise. 289: */ 290: public static boolean getDefaultLightWeightPopupEnabled() 291: { 292: return DefaultLightWeightPopupEnabled; 293: } 294: 295: /** 296: * Sets whether JPopupMenu should use ligthWeight container to 297: * display it menu items by default 298: * 299: * @param enabled true if JPopupMenu should use lightweight container 300: * for displaying its menu items, and false otherwise. 301: */ 302: public static void setDefaultLightWeightPopupEnabled(boolean enabled) 303: { 304: DefaultLightWeightPopupEnabled = enabled; 305: } 306: 307: /** 308: * This method returns the UI used to display the JPopupMenu. 309: * 310: * @return The UI used to display the JPopupMenu. 311: */ 312: public PopupMenuUI getUI() 313: { 314: return (PopupMenuUI) ui; 315: } 316: 317: /** 318: * Set the "UI" property of the menu item, which is a look and feel class 319: * responsible for handling popupMenu's input events and painting it. 320: * 321: * @param ui The new "UI" property 322: */ 323: public void setUI(PopupMenuUI ui) 324: { 325: super.setUI(ui); 326: } 327: 328: /** 329: * This method sets this menuItem's UI to the UIManager's default for the 330: * current look and feel. 331: */ 332: public void updateUI() 333: { 334: setUI((PopupMenuUI) UIManager.getUI(this)); 335: invalidate(); 336: } 337: 338: /** 339: * This method returns a name to identify which look and feel class will be 340: * the UI delegate for the menuItem. 341: * 342: * @return The Look and Feel classID. "PopupMenuUI" 343: */ 344: public String getUIClassID() 345: { 346: return "PopupMenuUI"; 347: } 348: 349: /** 350: * Returns selectionModel used by this popup menu to keep 351: * track of the selection. 352: * 353: * @return popup menu's selection model 354: */ 355: public SingleSelectionModel getSelectionModel() 356: { 357: return selectionModel; 358: } 359: 360: /** 361: * Sets selection model for this popup menu 362: * 363: * @param model new selection model of this popup menu 364: */ 365: public void setSelectionModel(SingleSelectionModel model) 366: { 367: selectionModel = model; 368: } 369: 370: /** 371: * Creates new menu item associated with a given action. 372: * 373: * @param action Action used to create new menu item 374: * 375: * @return new created menu item associated with a given action. 376: */ 377: protected JMenuItem createActionComponent(Action action) 378: { 379: return new JMenuItem(action); 380: } 381: 382: /** 383: * Creates PropertyChangeListener that listens to PropertyChangeEvents 384: * occuring in the Action associated with given menu item in this popup menu. 385: * 386: * @param item MenuItem 387: * 388: * @return The PropertyChangeListener 389: */ 390: protected PropertyChangeListener createActionChangeListener(JMenuItem item) 391: { 392: return new ActionChangeListener(); 393: } 394: 395: /** 396: * Returns true if this popup menu will display its menu item in 397: * a lightweight container and false otherwise. 398: * 399: * @return true if this popup menu will display its menu items 400: * in a lightweight container and false otherwise. 401: */ 402: public boolean isLightWeightPopupEnabled() 403: { 404: return lightWeightPopupEnabled; 405: } 406: 407: /** 408: * DOCUMENT ME! 409: * 410: * @param enabled DOCUMENT ME! 411: */ 412: public void setLightWeightPopupEnabled(boolean enabled) 413: { 414: lightWeightPopupEnabled = enabled; 415: } 416: 417: /** 418: * Returns label for this popup menu 419: * 420: * @return label for this popup menu 421: */ 422: public String getLabel() 423: { 424: return label; 425: } 426: 427: /** 428: * Sets label for this popup menu. This method fires PropertyChangeEvent 429: * when the label property is changed. Please note that most 430: * of the Look & Feel will ignore this property. 431: * 432: * @param label label for this popup menu 433: */ 434: public void setLabel(String label) 435: { 436: if (label != this.label) 437: { 438: String oldLabel = this.label; 439: this.label = label; 440: firePropertyChange("label", oldLabel, label); 441: } 442: } 443: 444: /** 445: * Adds separator to this popup menu 446: */ 447: public void addSeparator() 448: { 449: // insert separator at the end of the list of menu items 450: this.insert(new Separator(), -1); 451: } 452: 453: /** 454: * Adds popupMenuListener to listen for PopupMenuEvents fired 455: * by the JPopupMenu 456: * 457: * @param listener PopupMenuListener to add to JPopupMenu 458: */ 459: public void addPopupMenuListener(PopupMenuListener listener) 460: { 461: listenerList.add(PopupMenuListener.class, listener); 462: } 463: 464: /** 465: * Removes PopupMenuListener from JPopupMenu's list of listeners 466: * 467: * @param listener PopupMenuListener which needs to be removed 468: */ 469: public void removePopupMenuListener(PopupMenuListener listener) 470: { 471: listenerList.remove(PopupMenuListener.class, listener); 472: } 473: 474: /** 475: * Returns array of PopupMenuListeners that are listening to JPopupMenu 476: * 477: * @return Array of PopupMenuListeners that are listening to JPopupMenu 478: */ 479: public PopupMenuListener[] getPopupMenuListeners() 480: { 481: return ((PopupMenuListener[]) listenerList.getListeners(PopupMenuListener.class)); 482: } 483: 484: /** 485: * This method calls popupMenuWillBecomeVisible() of popup menu's 486: * PopupMenuListeners. This method is invoked just before popup menu 487: * will appear on the screen. 488: */ 489: protected void firePopupMenuWillBecomeVisible() 490: { 491: EventListener[] ll = listenerList.getListeners(PopupMenuListener.class); 492: 493: for (int i = 0; i < ll.length; i++) 494: ((PopupMenuListener) ll[i]).popupMenuWillBecomeVisible(new PopupMenuEvent(this)); 495: } 496: 497: /** 498: * This method calls popupMenuWillBecomeInvisible() of popup 499: * menu's PopupMenuListeners. This method is invoked just before popup 500: * menu will disappear from the screen 501: */ 502: protected void firePopupMenuWillBecomeInvisible() 503: { 504: EventListener[] ll = listenerList.getListeners(PopupMenuListener.class); 505: 506: for (int i = 0; i < ll.length; i++) 507: ((PopupMenuListener) ll[i]).popupMenuWillBecomeInvisible(new PopupMenuEvent(this)); 508: } 509: 510: /** 511: * This method calls popupMenuCanceled() of popup menu's PopupMenuListeners. 512: * This method is invoked just before popup menu is cancelled. This happens 513: * when popup menu is closed without selecting any of its menu items. This 514: * usually happens when the top-level window is resized or moved. 515: */ 516: protected void firePopupMenuCanceled() 517: { 518: EventListener[] ll = listenerList.getListeners(PopupMenuListener.class); 519: 520: for (int i = 0; i < ll.length; i++) 521: ((PopupMenuListener) ll[i]).popupMenuCanceled(new PopupMenuEvent(this)); 522: } 523: 524: /** 525: * This methods sets popup menu's size to its' preferred size. If the 526: * popup menu's size is previously set it will be ignored. 527: */ 528: public void pack() 529: { 530: super.setSize(null); 531: } 532: 533: /** 534: * Return visibility of the popup menu 535: * 536: * @return true if popup menu is visible on the screen and false otherwise. 537: */ 538: public boolean isVisible() 539: { 540: return visible; 541: } 542: 543: /** 544: * Sets visibility property of this popup menu. If the property is 545: * set to true then popup menu will be dispayed and popup menu will 546: * hide itself if visible property is set to false. 547: * 548: * @param visible true if popup menu will become visible and false otherwise. 549: */ 550: public void setVisible(boolean visible) 551: { 552: if (visible == isVisible()) 553: return; 554: 555: boolean old = isVisible(); 556: this.visible = visible; 557: if (old != isVisible()) 558: { 559: firePropertyChange("visible", old, isVisible()); 560: if (visible) 561: { 562: firePopupMenuWillBecomeVisible(); 563: Container rootContainer = (Container) SwingUtilities.getRoot(invoker); 564: 565: boolean fit = true; 566: Dimension size; 567: 568: // Determine the size of the popup menu 569: if (this.getSize().width == 0 && this.getSize().width == 0) 570: size = this.getPreferredSize(); 571: else 572: size = this.getSize(); 573: 574: if ((size.width > (rootContainer.getWidth() - popupLocation.x)) 575: || (size.height > (rootContainer.getHeight() - popupLocation.y))) 576: fit = false; 577: if (lightWeightPopupEnabled && fit) 578: popup = new LightWeightPopup(this); 579: else 580: { 581: if (fit) 582: popup = new MediumWeightPopup(this); 583: else 584: popup = new HeavyWeightPopup(this); 585: } 586: if (popup instanceof LightWeightPopup 587: || popup instanceof MediumWeightPopup) 588: { 589: JLayeredPane layeredPane; 590: layeredPane = SwingUtilities.getRootPane(invoker) 591: .getLayeredPane(); 592: Point p = new Point(popupLocation.x, popupLocation.y); 593: SwingUtilities.convertPointFromScreen(p, layeredPane); 594: popup.show(p.x, p.y, size.width, size.height); 595: } 596: else 597: { 598: // Subtract insets of the top-level container if popup menu's 599: // top-left corner is inside it. 600: Insets insets = rootContainer.getInsets(); 601: popup.show(popupLocation.x - insets.left, 602: popupLocation.y - insets.top, size.width, 603: size.height); 604: } 605: } 606: else 607: { 608: firePopupMenuWillBecomeInvisible(); 609: popup.hide(); 610: } 611: } 612: } 613: 614: /** 615: * Sets location of the popup menu. 616: * 617: * @param x X coordinate of the popup menu's location 618: * @param y Y coordinate of the popup menu's location 619: */ 620: public void setLocation(int x, int y) 621: { 622: if (popupLocation == null) 623: popupLocation = new Point(); 624: 625: popupLocation.x = x; 626: popupLocation.y = y; 627: } 628: 629: /** 630: * Returns popup menu's invoker. 631: * 632: * @return popup menu's invoker 633: */ 634: public Component getInvoker() 635: { 636: return invoker; 637: } 638: 639: /** 640: * Sets popup menu's invoker. 641: * 642: * @param component The new invoker of this popup menu 643: */ 644: public void setInvoker(Component component) 645: { 646: invoker = component; 647: } 648: 649: /** 650: * This method displays JPopupMenu on the screen at the specified 651: * location. Note that x and y coordinates given to this method 652: * should be expressed in terms of the popup menus' invoker. 653: * 654: * @param component Invoker for this popup menu 655: * @param x x-coordinate of the popup menu relative to the specified invoker 656: * @param y y-coordiate of the popup menu relative to the specified invoker 657: */ 658: public void show(Component component, int x, int y) 659: { 660: setInvoker(component); 661: Point p = new Point(x, y); 662: SwingUtilities.convertPointToScreen(p, component); 663: setLocation(p.x, p.y); 664: setVisible(true); 665: } 666: 667: /** 668: * Returns component located at the specified index in the popup menu 669: * 670: * @param index index of the component to return 671: * 672: * @return component located at the specified index in the popup menu 673: * 674: * @deprecated Replaced by getComponent(int) 675: */ 676: public Component getComponentAtIndex(int index) 677: { 678: return getComponent(index); 679: } 680: 681: /** 682: * Returns index of the specified component in the popup menu 683: * 684: * @param component Component to look for 685: * 686: * @return index of the specified component in the popup menu 687: */ 688: public int getComponentIndex(Component component) 689: { 690: Component[] items = getComponents(); 691: 692: for (int i = 0; i < items.length; i++) 693: { 694: if (items[i].equals(component)) 695: return i; 696: } 697: 698: return -1; 699: } 700: 701: /** 702: * Sets size of the popup 703: * 704: * @param size Dimensions representing new size of the popup menu 705: */ 706: public void setPopupSize(Dimension size) 707: { 708: super.setSize(size); 709: } 710: 711: /** 712: * Sets size of the popup menu 713: * 714: * @param width width for the new size 715: * @param height height for the new size 716: */ 717: public void setPopupSize(int width, int height) 718: { 719: super.setSize(width, height); 720: } 721: 722: /** 723: * Selects specified component in this popup menu. 724: * 725: * @param selected component to select 726: */ 727: public void setSelected(Component selected) 728: { 729: int index = getComponentIndex(selected); 730: selectionModel.setSelectedIndex(index); 731: } 732: 733: /** 734: * Checks if this popup menu paints its border. 735: * 736: * @return true if this popup menu paints its border and false otherwise. 737: */ 738: public boolean isBorderPainted() 739: { 740: return borderPainted; 741: } 742: 743: /** 744: * Sets if the border of the popup menu should be 745: * painter or not. 746: * 747: * @param painted true if the border should be painted and false otherwise 748: */ 749: public void setBorderPainted(boolean painted) 750: { 751: borderPainted = painted; 752: } 753: 754: /** 755: * Returns margin for this popup menu. 756: * 757: * @return margin for this popup menu. 758: */ 759: public Insets getMargin() 760: { 761: return margin; 762: } 763: 764: /** 765: * A string that describes this JPopupMenu. Normally only used 766: * for debugging. 767: * 768: * @return A string describing this JMenuItem 769: */ 770: protected String paramString() 771: { 772: StringBuffer sb = new StringBuffer(); 773: sb.append(super.paramString()); 774: sb.append(",label="); 775: if (getLabel() != null) 776: sb.append(getLabel()); 777: sb.append(",lightWeightPopupEnabled=").append(isLightWeightPopupEnabled()); 778: sb.append(",margin="); 779: if (getMargin() != null) 780: sb.append(margin); 781: sb.append(",paintBorder=").append(isBorderPainted()); 782: return sb.toString(); 783: } 784: 785: /** 786: * Process mouse events forwarded from MenuSelectionManager. This method 787: * doesn't do anything. It is here to conform to the MenuElement interface. 788: * 789: * @param event event forwarded from MenuSelectionManager 790: * @param path path to the menu element from which event was generated 791: * @param manager MenuSelectionManager for the current menu hierarchy 792: */ 793: public void processMouseEvent(MouseEvent event, MenuElement[] path, 794: MenuSelectionManager manager) 795: { 796: // Empty Implementation. This method is needed for the implementation 797: // of MenuElement interface 798: } 799: 800: /** 801: * Process key events forwarded from MenuSelectionManager. This method 802: * doesn't do anything. It is here to conform to the MenuElement interface. 803: * 804: * @param event event forwarded from MenuSelectionManager 805: * @param path path to the menu element from which event was generated 806: * @param manager MenuSelectionManager for the current menu hierarchy 807: * 808: */ 809: public void processKeyEvent(KeyEvent event, MenuElement[] path, 810: MenuSelectionManager manager) 811: { 812: // Empty Implementation. This method is needed for the implementation 813: // of MenuElement interface 814: } 815: 816: /** 817: * Method of MenuElement Interface. It is invoked when 818: * popupMenu's selection has changed 819: * 820: * @param changed true if this popupMenu is part of current menu 821: * hierarchy and false otherwise. 822: */ 823: public void menuSelectionChanged(boolean changed) 824: { 825: if (! changed) 826: setVisible(false); 827: } 828: 829: /** 830: * Return subcomonents of this popup menu. This method returns only 831: * components that implement the <code>MenuElement</code> interface. 832: * 833: * @return array of menu items belonging to this popup menu 834: */ 835: public MenuElement[] getSubElements() 836: { 837: Component[] items = getComponents(); 838: ArrayList subElements = new ArrayList(); 839: 840: for (int i = 0; i < items.length; i++) 841: if (items[i] instanceof MenuElement) 842: subElements.add(items[i]); 843: 844: return (MenuElement[]) 845: subElements.toArray(new MenuElement[subElements.size()]); 846: } 847: 848: /** 849: * Method of the MenuElement interface. Returns reference to itself. 850: * 851: * @return Returns reference to itself 852: */ 853: public Component getComponent() 854: { 855: return this; 856: } 857: 858: /** 859: * Checks if observing mouse event should trigger popup 860: * menu to show on the screen. 861: * 862: * @param event MouseEvent to check 863: * 864: * @return true if the observing mouse event is popup trigger and false otherwise 865: */ 866: public boolean isPopupTrigger(MouseEvent event) 867: { 868: return ((PopupMenuUI) getUI()).isPopupTrigger(event); 869: } 870: 871: /** 872: * DOCUMENT ME! 873: * 874: * @return DOCUMENT ME! 875: */ 876: public AccessibleContext getAccessibleContext() 877: { 878: if (accessibleContext == null) 879: accessibleContext = new AccessibleJPopupMenu(); 880: 881: return accessibleContext; 882: } 883: 884: /** 885: * This interface is used to display menu items of the JPopupMenu 886: */ 887: private interface Popup 888: { 889: /** 890: * Displays container on the screen 891: * 892: * @param x x-coordinate of popup menu's location on the screen 893: * @param y y-coordinate of popup menu's location on the screen 894: * @param width width of the container that is used to display menu 895: * item's for popup menu 896: * @param height height of the container that is used to display menu 897: * item's for popup menu 898: */ 899: void show(int x, int y, int width, int height); 900: 901: /** 902: * Hides container used to display popup menu item's from the screen 903: */ 904: void hide(); 905: } 906: 907: /** 908: * This class represents Popup menu that uses light weight container 909: * to display its contents. 910: */ 911: private class LightWeightPopup extends Container implements Popup 912: { 913: private Component c; 914: 915: /** 916: * Creates a new LightWeightPopup menu 917: * 918: * @param c Container containing menu items 919: */ 920: public LightWeightPopup(Container c) 921: { 922: this.c = c; 923: } 924: 925: /** 926: * Displayes lightweight container with menu items to the screen 927: * 928: * @param x x-coordinate of lightweight container on the screen 929: * @param y y-coordinate of lightweight container on the screen 930: * @param width width of the lightweight container 931: * @param height height of the lightweight container 932: */ 933: public void show(int x, int y, int width, int height) 934: { 935: JLayeredPane layeredPane; 936: layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); 937: c.setBounds(x, y, width, height); 938: layeredPane.add(c, JLayeredPane.POPUP_LAYER, 0); 939: } 940: 941: /** 942: * Hides lightweight container from the screen 943: */ 944: public void hide() 945: { 946: // FIXME: Right now the lightweight container is removed from JLayered 947: // pane. It is probably would be better in order to improve performance 948: // to make the container invisible instead of removing it everytime. 949: JLayeredPane layeredPane; 950: layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); 951: int index = layeredPane.getIndexOf(c); 952: layeredPane.remove(index); 953: } 954: } 955: 956: /** 957: * MediumWeightPopup is an AWT Panel with JPopupMenu's menu items. 958: * It is used to display JPopupMenu's menu items on the screen 959: */ 960: private class MediumWeightPopup extends Panel implements Popup 961: { 962: /** 963: * Creates a new MediumWeightPopup object. 964: * 965: * @param c Container with JPopupMenu's menu items 966: */ 967: public MediumWeightPopup(Container c) 968: { 969: this.add(c); 970: } 971: 972: /** 973: * Displays AWT Panel with its components on the screen 974: * 975: * @param x x-coordinate of the upper-left corner of the panel's 976: * @param y y-coordinate of the upper-left corner of the panel's 977: * @param width width of the panel 978: * @param height height of the panel 979: */ 980: public void show(int x, int y, int width, int height) 981: { 982: JLayeredPane layeredPane; 983: layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); 984: layeredPane.add(this, JLayeredPane.POPUP_LAYER, 0); 985: this.setBounds(x, y, width, height); 986: } 987: 988: /** 989: * Hides This panel from the screen 990: */ 991: public void hide() 992: { 993: // FIXME: Right now the lightweight container is removed from JLayered 994: // pane. It is probably would be better in order to improve performance 995: // to make the container invisible instead of removing it everytime. 996: JLayeredPane layeredPane; 997: layeredPane = SwingUtilities.getRootPane(invoker).getLayeredPane(); 998: int index = layeredPane.getIndexOf(this); 999: layeredPane.remove(index); 1000: } 1001: } 1002: 1003: /** 1004: * HeavyWeightPopup is JWindow that is used to display JPopupMenu menu item's 1005: * on the screen 1006: */ 1007: private class HeavyWeightPopup extends JWindow implements Popup 1008: { 1009: /** 1010: * Creates a new HeavyWeightPopup object. 1011: * 1012: * @param c Container containing menu items 1013: */ 1014: public HeavyWeightPopup(Container c) 1015: { 1016: this.setContentPane(c); 1017: } 1018: 1019: /** 1020: * Displays JWindow container JPopupMenu's menu items to the screen 1021: * 1022: * @param x x-coordinate of JWindow containing menu items 1023: * @param y y-coordinate of JWindow containing menu items 1024: * @param width width of the JWindow 1025: * @param height height of the JWindow 1026: */ 1027: public void show(int x, int y, int width, int height) 1028: { 1029: this.setBounds(x, y, width, height); 1030: this.show(); 1031: } 1032: } 1033: 1034: /** 1035: * This is the separator that can be used in popup menu. 1036: */ 1037: public static class Separator extends JSeparator 1038: { 1039: public Separator() 1040: { 1041: } 1042: 1043: public String getUIClassID() 1044: { 1045: return "PopupMenuSeparatorUI"; 1046: } 1047: } 1048: 1049: protected class AccessibleJPopupMenu extends AccessibleJComponent 1050: { 1051: private static final long serialVersionUID = 7423261328879849768L; 1052: 1053: protected AccessibleJPopupMenu() 1054: { 1055: } 1056: 1057: public AccessibleRole getAccessibleRole() 1058: { 1059: return AccessibleRole.POPUP_MENU; 1060: } 1061: } 1062: 1063: /* This class resizes popup menu and repaints popup menu appropriately if one 1064: of item's action has changed */ 1065: protected class ActionChangeListener implements PropertyChangeListener 1066: { 1067: public void propertyChange(PropertyChangeEvent evt) 1068: { 1069: JPopupMenu.this.revalidate(); 1070: JPopupMenu.this.repaint(); 1071: } 1072: } 1073: }
GNU Classpath (0.18) |