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 gnu.java.lang.CPStringBuilder; 42: 43: import java.awt.Component; 44: import java.awt.Dimension; 45: import java.awt.Insets; 46: import java.awt.Point; 47: import java.awt.event.KeyEvent; 48: import java.awt.event.MouseEvent; 49: import java.beans.PropertyChangeEvent; 50: import java.beans.PropertyChangeListener; 51: import java.util.ArrayList; 52: import java.util.EventListener; 53: 54: import javax.accessibility.Accessible; 55: import javax.accessibility.AccessibleContext; 56: import javax.accessibility.AccessibleRole; 57: import javax.swing.event.MenuKeyListener; 58: import javax.swing.event.PopupMenuEvent; 59: import javax.swing.event.PopupMenuListener; 60: import javax.swing.plaf.PopupMenuUI; 61: 62: /** 63: * JPopupMenu is a container that is used to display popup menu's menu 64: * items. By default JPopupMenu is a lightweight container, however if it 65: * is the case that JPopupMenu's bounds are outside of main window, then 66: * heawyweight container will be used to display menu items. It is also 67: * possible to change JPopupMenu's default behavior and set JPopupMenu 68: * to always use heavyweight container. 69: * 70: * JPopupMenu can be displayed anywhere; it is a floating free popup menu. 71: * However before JPopupMenu is diplayed, its invoker property should be set. 72: * JPopupMenu's invoker is a component relative to which popup menu is 73: * displayed. 74: * 75: * JPopupMenu fires PopupMenuEvents to its registered listeners. Whenever 76: * JPopupMenu becomes visible on the screen then PopupMenuEvent indicating 77: * that popup menu became visible will be fired. In the case when 78: * JPopupMenu becomes invisible or cancelled without selection, then 79: * popupMenuBecomeInvisible() or popupMenuCancelled() methods of 80: * PopupMenuListeners will be invoked. 81: * 82: * JPopupMenu also fires PropertyChangeEvents when its bound properties 83: * change.In addittion to inheritted bound properties, JPopupMenu has 84: * 'visible' bound property. When JPopupMenu becomes visible/invisible on 85: * the screen it fires PropertyChangeEvents to its registered 86: * PropertyChangeListeners. 87: */ 88: public class JPopupMenu extends JComponent implements Accessible, MenuElement 89: { 90: private static final long serialVersionUID = -8336996630009646009L; 91: 92: /* indicates if popup's menu border should be painted*/ 93: private boolean borderPainted = true; 94: 95: /** Flag indicating whether lightweight, mediumweight or heavyweight popup 96: is used to display menu items. 97: 98: These are the possible cases: 99: 100: 1. if DefaultLightWeightPopupEnabled true 101: (i) use lightweight container if popup feets inside top-level window 102: (ii) only use heavyweight container (JDialog) if popup doesn't fit. 103: 104: 2. if DefaultLightWeightPopupEnabled false 105: (i) if popup fits, use awt.Panel (mediumWeight) 106: (ii) if popup doesn't fit, use JDialog (heavyWeight) 107: */ 108: private static boolean DefaultLightWeightPopupEnabled = true; 109: 110: /* Component that invokes popup menu. */ 111: transient Component invoker; 112: 113: /* Label for this popup menu. It is not used in most of the look and feel themes. */ 114: private String label; 115: 116: /*Amount of space between menuItem's in JPopupMenu and JPopupMenu's border */ 117: private Insets margin; 118: 119: /** Indicates whether ligthWeight container can be used to display popup 120: menu. This flag is the same as DefaultLightWeightPopupEnabled, but setting 121: this flag can change popup menu after creation of the object */ 122: private boolean lightWeightPopupEnabled; 123: 124: /** SelectionModel that keeps track of menu selection. */ 125: protected SingleSelectionModel selectionModel; 126: 127: /* Popup that is used to display JPopupMenu */ 128: private transient Popup popup; 129: 130: /** 131: * Location of the popup, X coordinate. 132: */ 133: private int popupLocationX; 134: 135: /** 136: * Location of the popup, Y coordinate. 137: */ 138: private int popupLocationY; 139: 140: /* Field indicating if popup menu is visible or not */ 141: private boolean visible = false; 142: 143: /** 144: * Creates a new JPopupMenu object. 145: */ 146: public JPopupMenu() 147: { 148: this(null); 149: } 150: 151: /** 152: * Creates a new JPopupMenu with specified label 153: * 154: * @param label Label for popup menu. 155: */ 156: public JPopupMenu(String label) 157: { 158: lightWeightPopupEnabled = getDefaultLightWeightPopupEnabled(); 159: setLabel(label); 160: setSelectionModel(new DefaultSingleSelectionModel()); 161: super.setVisible(false); 162: updateUI(); 163: } 164: 165: /** 166: * Adds given menu item to the popup menu 167: * 168: * @param item menu item to add to the popup menu 169: * 170: * @return menu item that was added to the popup menu 171: */ 172: public JMenuItem add(JMenuItem item) 173: { 174: this.insert(item, -1); 175: return item; 176: } 177: 178: /** 179: * Constructs menu item with a specified label and adds it to 180: * popup menu 181: * 182: * @param text label for the menu item to be added 183: * 184: * @return constructed menu item that was added to the popup menu 185: */ 186: public JMenuItem add(String text) 187: { 188: JMenuItem item = new JMenuItem(text); 189: return add(item); 190: } 191: 192: /** 193: * Constructs menu item associated with the specified action 194: * and adds it to the popup menu 195: * 196: * @param action Action for the new menu item 197: * 198: * @return menu item that was added to the menu 199: */ 200: public JMenuItem add(Action action) 201: { 202: JMenuItem item = createActionComponent(action); 203: 204: if (action != null) 205: action.addPropertyChangeListener(createActionChangeListener(item)); 206: 207: return add(item); 208: } 209: 210: /** 211: * Revomes component at the given index from the menu. 212: * 213: * @param index index of the component that will be removed in the menu 214: */ 215: public void remove(int index) 216: { 217: super.remove(index); 218: revalidate(); 219: } 220: 221: /** 222: * Create menu item associated with the given action 223: * and inserts it into the popup menu at the specified index 224: * 225: * @param action Action for the new menu item 226: * @param index index in the popup menu at which to insert new menu item. 227: */ 228: public void insert(Action action, int index) 229: { 230: JMenuItem item = new JMenuItem(action); 231: this.insert(item, index); 232: } 233: 234: /** 235: * Insert given component to the popup menu at the 236: * specified index 237: * 238: * @param component Component to insert 239: * @param index Index at which to insert given component 240: */ 241: public void insert(Component component, int index) 242: { 243: super.add(component, index); 244: } 245: 246: /** 247: * Returns flag indicating if newly created JPopupMenu will use 248: * heavyweight or lightweight container to display its menu items 249: * 250: * @return true if JPopupMenu will use lightweight container to display 251: * menu items by default, and false otherwise. 252: */ 253: public static boolean getDefaultLightWeightPopupEnabled() 254: { 255: return DefaultLightWeightPopupEnabled; 256: } 257: 258: /** 259: * Sets whether JPopupMenu should use ligthWeight container to 260: * display it menu items by default 261: * 262: * @param enabled true if JPopupMenu should use lightweight container 263: * for displaying its menu items, and false otherwise. 264: */ 265: public static void setDefaultLightWeightPopupEnabled(boolean enabled) 266: { 267: DefaultLightWeightPopupEnabled = enabled; 268: } 269: 270: /** 271: * This method returns the UI used to display the JPopupMenu. 272: * 273: * @return The UI used to display the JPopupMenu. 274: */ 275: public PopupMenuUI getUI() 276: { 277: return (PopupMenuUI) ui; 278: } 279: 280: /** 281: * Set the "UI" property of the menu item, which is a look and feel class 282: * responsible for handling popupMenu's input events and painting it. 283: * 284: * @param ui The new "UI" property 285: */ 286: public void setUI(PopupMenuUI ui) 287: { 288: super.setUI(ui); 289: } 290: 291: /** 292: * This method sets this menuItem's UI to the UIManager's default for the 293: * current look and feel. 294: */ 295: public void updateUI() 296: { 297: setUI((PopupMenuUI) UIManager.getUI(this)); 298: } 299: 300: /** 301: * This method returns a name to identify which look and feel class will be 302: * the UI delegate for the menuItem. 303: * 304: * @return The Look and Feel classID. "PopupMenuUI" 305: */ 306: public String getUIClassID() 307: { 308: return "PopupMenuUI"; 309: } 310: 311: /** 312: * Returns selectionModel used by this popup menu to keep 313: * track of the selection. 314: * 315: * @return popup menu's selection model 316: */ 317: public SingleSelectionModel getSelectionModel() 318: { 319: return selectionModel; 320: } 321: 322: /** 323: * Sets selection model for this popup menu 324: * 325: * @param model new selection model of this popup menu 326: */ 327: public void setSelectionModel(SingleSelectionModel model) 328: { 329: selectionModel = model; 330: } 331: 332: /** 333: * Creates new menu item associated with a given action. 334: * 335: * @param action Action used to create new menu item 336: * 337: * @return new created menu item associated with a given action. 338: */ 339: protected JMenuItem createActionComponent(Action action) 340: { 341: return new JMenuItem(action); 342: } 343: 344: /** 345: * Creates PropertyChangeListener that listens to PropertyChangeEvents 346: * occuring in the Action associated with given menu item in this popup menu. 347: * 348: * @param item MenuItem 349: * 350: * @return The PropertyChangeListener 351: */ 352: protected PropertyChangeListener createActionChangeListener(JMenuItem item) 353: { 354: return new ActionChangeListener(); 355: } 356: 357: /** 358: * Returns true if this popup menu will display its menu item in 359: * a lightweight container and false otherwise. 360: * 361: * @return true if this popup menu will display its menu items 362: * in a lightweight container and false otherwise. 363: */ 364: public boolean isLightWeightPopupEnabled() 365: { 366: return lightWeightPopupEnabled; 367: } 368: 369: /** 370: * DOCUMENT ME! 371: * 372: * @param enabled DOCUMENT ME! 373: */ 374: public void setLightWeightPopupEnabled(boolean enabled) 375: { 376: lightWeightPopupEnabled = enabled; 377: } 378: 379: /** 380: * Returns label for this popup menu 381: * 382: * @return label for this popup menu 383: */ 384: public String getLabel() 385: { 386: return label; 387: } 388: 389: /** 390: * Sets label for this popup menu. This method fires PropertyChangeEvent 391: * when the label property is changed. Please note that most 392: * of the Look & Feel will ignore this property. 393: * 394: * @param label label for this popup menu 395: */ 396: public void setLabel(String label) 397: { 398: if (label != this.label) 399: { 400: String oldLabel = this.label; 401: this.label = label; 402: firePropertyChange("label", oldLabel, label); 403: } 404: } 405: 406: /** 407: * Adds separator to this popup menu 408: */ 409: public void addSeparator() 410: { 411: // insert separator at the end of the list of menu items 412: this.insert(new Separator(), -1); 413: } 414: 415: /** 416: * Adds a MenuKeyListener to the popup. 417: * 418: * @param l - the listener to add. 419: */ 420: public void addMenuKeyListener(MenuKeyListener l) 421: { 422: listenerList.add(MenuKeyListener.class, l); 423: } 424: 425: /** 426: * Removes a MenuKeyListener from the popup. 427: * 428: * @param l - the listener to remove. 429: */ 430: public void removeMenuKeyListener(MenuKeyListener l) 431: { 432: listenerList.remove(MenuKeyListener.class, l); 433: } 434: 435: /** 436: * Returns array of getMenuKeyListeners that are listening to JPopupMenu. 437: * 438: * @return array of getMenuKeyListeners that are listening to JPopupMenu 439: */ 440: public MenuKeyListener[] getMenuKeyListeners() 441: { 442: return ((MenuKeyListener[]) listenerList.getListeners(MenuKeyListener.class)); 443: } 444: 445: /** 446: * Adds popupMenuListener to listen for PopupMenuEvents fired 447: * by the JPopupMenu 448: * 449: * @param listener PopupMenuListener to add to JPopupMenu 450: */ 451: public void addPopupMenuListener(PopupMenuListener listener) 452: { 453: listenerList.add(PopupMenuListener.class, listener); 454: } 455: 456: /** 457: * Removes PopupMenuListener from JPopupMenu's list of listeners 458: * 459: * @param listener PopupMenuListener which needs to be removed 460: */ 461: public void removePopupMenuListener(PopupMenuListener listener) 462: { 463: listenerList.remove(PopupMenuListener.class, listener); 464: } 465: 466: /** 467: * Returns array of PopupMenuListeners that are listening to JPopupMenu 468: * 469: * @return Array of PopupMenuListeners that are listening to JPopupMenu 470: */ 471: public PopupMenuListener[] getPopupMenuListeners() 472: { 473: return ((PopupMenuListener[]) listenerList.getListeners(PopupMenuListener.class)); 474: } 475: 476: /** 477: * This method calls popupMenuWillBecomeVisible() of popup menu's 478: * PopupMenuListeners. This method is invoked just before popup menu 479: * will appear on the screen. 480: */ 481: protected void firePopupMenuWillBecomeVisible() 482: { 483: EventListener[] ll = listenerList.getListeners(PopupMenuListener.class); 484: 485: for (int i = 0; i < ll.length; i++) 486: ((PopupMenuListener) ll[i]).popupMenuWillBecomeVisible(new PopupMenuEvent(this)); 487: } 488: 489: /** 490: * This method calls popupMenuWillBecomeInvisible() of popup 491: * menu's PopupMenuListeners. This method is invoked just before popup 492: * menu will disappear from the screen 493: */ 494: protected void firePopupMenuWillBecomeInvisible() 495: { 496: EventListener[] ll = listenerList.getListeners(PopupMenuListener.class); 497: 498: for (int i = 0; i < ll.length; i++) 499: ((PopupMenuListener) ll[i]).popupMenuWillBecomeInvisible(new PopupMenuEvent(this)); 500: } 501: 502: /** 503: * This method calls popupMenuCanceled() of popup menu's PopupMenuListeners. 504: * This method is invoked just before popup menu is cancelled. This happens 505: * when popup menu is closed without selecting any of its menu items. This 506: * usually happens when the top-level window is resized or moved. 507: */ 508: protected void firePopupMenuCanceled() 509: { 510: EventListener[] ll = listenerList.getListeners(PopupMenuListener.class); 511: 512: for (int i = 0; i < ll.length; i++) 513: ((PopupMenuListener) ll[i]).popupMenuCanceled(new PopupMenuEvent(this)); 514: } 515: 516: /** 517: * This methods sets popup menu's size to its' preferred size. If the 518: * popup menu's size is previously set it will be ignored. 519: */ 520: public void pack() 521: { 522: // Hook up this call so that it gets executed on the event thread in order 523: // to avoid synchronization problems when calling the layout manager. 524: if (! SwingUtilities.isEventDispatchThread()) 525: { 526: SwingUtilities.invokeLater(new Runnable() 527: { 528: public void run() 529: { 530: show(); 531: } 532: }); 533: } 534: 535: setSize(getPreferredSize()); 536: } 537: 538: /** 539: * Return visibility of the popup menu 540: * 541: * @return true if popup menu is visible on the screen and false otherwise. 542: */ 543: public boolean isVisible() 544: { 545: return visible; 546: } 547: 548: /** 549: * Sets visibility property of this popup menu. If the property is 550: * set to true then popup menu will be dispayed and popup menu will 551: * hide itself if visible property is set to false. 552: * 553: * @param visible true if popup menu will become visible and false otherwise. 554: */ 555: public void setVisible(final boolean visible) 556: { 557: // Hook up this call so that it gets executed on the event thread in order 558: // to avoid synchronization problems when calling the layout manager. 559: if (! SwingUtilities.isEventDispatchThread()) 560: { 561: SwingUtilities.invokeLater(new Runnable() 562: { 563: public void run() 564: { 565: setVisible(visible); 566: } 567: }); 568: } 569: 570: if (visible == isVisible()) 571: return; 572: 573: boolean old = isVisible(); 574: this.visible = visible; 575: if (old != isVisible()) 576: { 577: if (visible) 578: { 579: if (invoker != null && !(invoker instanceof JMenu)) 580: { 581: MenuElement[] menuEls; 582: if (getSubElements().length > 0) 583: { 584: menuEls = new MenuElement[2]; 585: menuEls[0] = this; 586: menuEls[1] = getSubElements()[0]; 587: } 588: else 589: { 590: menuEls = new MenuElement[1]; 591: menuEls[0] = this; 592: } 593: MenuSelectionManager.defaultManager().setSelectedPath(menuEls); 594: } 595: firePopupMenuWillBecomeVisible(); 596: PopupFactory pf = PopupFactory.getSharedInstance(); 597: pack(); 598: popup = pf.getPopup(invoker, this, popupLocationX, popupLocationY); 599: popup.show(); 600: } 601: else 602: { 603: getSelectionModel().clearSelection(); 604: firePopupMenuWillBecomeInvisible(); 605: popup.hide(); 606: } 607: firePropertyChange("visible", old, isVisible()); 608: } 609: } 610: 611: /** 612: * Sets location of the popup menu. 613: * 614: * @param x X coordinate of the popup menu's location 615: * @param y Y coordinate of the popup menu's location 616: */ 617: public void setLocation(int x, int y) 618: { 619: popupLocationX = x; 620: popupLocationY = y; 621: // Handle the case when the popup is already showing. In this case we need 622: // to fetch a new popup from PopupFactory and use this. See the general 623: // contract of the PopupFactory. 624: } 625: 626: /** 627: * Returns popup menu's invoker. 628: * 629: * @return popup menu's invoker 630: */ 631: public Component getInvoker() 632: { 633: return invoker; 634: } 635: 636: /** 637: * Sets popup menu's invoker. 638: * 639: * @param component The new invoker of this popup menu 640: */ 641: public void setInvoker(Component component) 642: { 643: invoker = component; 644: } 645: 646: /** 647: * This method displays JPopupMenu on the screen at the specified 648: * location. Note that x and y coordinates given to this method 649: * should be expressed in terms of the popup menus' invoker. 650: * 651: * @param component Invoker for this popup menu 652: * @param x x-coordinate of the popup menu relative to the specified invoker 653: * @param y y-coordiate of the popup menu relative to the specified invoker 654: */ 655: public void show(Component component, int x, int y) 656: { 657: if (component.isShowing()) 658: { 659: setInvoker(component); 660: Point p = new Point(x, y); 661: SwingUtilities.convertPointToScreen(p, component); 662: setLocation(p.x, p.y); 663: setVisible(true); 664: } 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: CPStringBuilder sb = new CPStringBuilder(); 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 (invoker instanceof JMenu) 826: { 827: // We need to special case this since the JMenu calculates the 828: // position etc of the popup. 829: JMenu menu = (JMenu) invoker; 830: menu.setPopupMenuVisible(changed); 831: } 832: else if (! changed) 833: setVisible(false); 834: } 835: 836: /** 837: * Return subcomonents of this popup menu. This method returns only 838: * components that implement the <code>MenuElement</code> interface. 839: * 840: * @return array of menu items belonging to this popup menu 841: */ 842: public MenuElement[] getSubElements() 843: { 844: Component[] items = getComponents(); 845: ArrayList subElements = new ArrayList(); 846: 847: for (int i = 0; i < items.length; i++) 848: if (items[i] instanceof MenuElement) 849: subElements.add(items[i]); 850: 851: return (MenuElement[]) 852: subElements.toArray(new MenuElement[subElements.size()]); 853: } 854: 855: /** 856: * Method of the MenuElement interface. Returns reference to itself. 857: * 858: * @return Returns reference to itself 859: */ 860: public Component getComponent() 861: { 862: return this; 863: } 864: 865: /** 866: * Checks if observing mouse event should trigger popup 867: * menu to show on the screen. 868: * 869: * @param event MouseEvent to check 870: * 871: * @return true if the observing mouse event is popup trigger and false otherwise 872: */ 873: public boolean isPopupTrigger(MouseEvent event) 874: { 875: return ((PopupMenuUI) getUI()).isPopupTrigger(event); 876: } 877: 878: /** 879: * DOCUMENT ME! 880: * 881: * @return DOCUMENT ME! 882: */ 883: public AccessibleContext getAccessibleContext() 884: { 885: if (accessibleContext == null) 886: accessibleContext = new AccessibleJPopupMenu(); 887: 888: return accessibleContext; 889: } 890: 891: /** 892: * This is the separator that can be used in popup menu. 893: */ 894: public static class Separator extends JSeparator 895: { 896: public Separator() 897: { 898: super(); 899: } 900: 901: public String getUIClassID() 902: { 903: return "PopupMenuSeparatorUI"; 904: } 905: } 906: 907: /** 908: * Returns <code>true</code> if the component is guaranteed to be painted 909: * on top of others. This returns false by default and is overridden by 910: * components like JMenuItem, JPopupMenu and JToolTip to return true for 911: * added efficiency. 912: * 913: * @return <code>true</code> if the component is guaranteed to be painted 914: * on top of others 915: */ 916: boolean onTop() 917: { 918: return true; 919: } 920: 921: protected class AccessibleJPopupMenu extends AccessibleJComponent 922: { 923: private static final long serialVersionUID = 7423261328879849768L; 924: 925: protected AccessibleJPopupMenu() 926: { 927: // Nothing to do here. 928: } 929: 930: public AccessibleRole getAccessibleRole() 931: { 932: return AccessibleRole.POPUP_MENU; 933: } 934: } 935: 936: /* This class resizes popup menu and repaints popup menu appropriately if one 937: of item's action has changed */ 938: private class ActionChangeListener implements PropertyChangeListener 939: { 940: public void propertyChange(PropertyChangeEvent evt) 941: { 942: // We used to have a revalidate() and repaint() call here. However I think 943: // this is not needed. Instead, a new Popup has to be fetched from the 944: // PopupFactory and used here. 945: } 946: } 947: }