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