| 1 7 8 package javax.swing; 9 10 import java.awt.*; 11 import java.awt.event.*; 12 import java.io.IOException ; 13 import java.io.ObjectInputStream ; 14 import java.io.ObjectOutputStream ; 15 import java.io.Serializable ; 16 import java.beans.*; 17 18 import java.util.Locale ; 19 import java.util.Vector ; 20 import java.util.Hashtable ; 21 import javax.accessibility.*; 22 import javax.swing.plaf.PopupMenuUI ; 23 import javax.swing.plaf.ComponentUI ; 24 import javax.swing.plaf.basic.BasicComboPopup ; 25 import javax.swing.event.*; 26 27 import java.applet.Applet ; 28 29 61 public class JPopupMenu extends JComponent implements Accessible,MenuElement { 62 63 67 private static final String uiClassID = "PopupMenuUI"; 68 69 72 private static final Object defaultLWPopupEnabledKey = 73 new StringBuffer ("JPopupMenu.defaultLWPopupEnabledKey"); 74 75 76 static boolean popupPostionFixDisabled = false; 77 78 static { 79 popupPostionFixDisabled = java.security.AccessController.doPrivileged( 80 new sun.security.action.GetPropertyAction( 81 "javax.swing.adjustPopupLocationToFit","")).equals("false"); 82 83 } 84 85 transient Component invoker; 86 transient Popup popup; 87 transient Frame frame; 88 private int desiredLocationX,desiredLocationY; 89 90 private String label = null; 91 private boolean paintBorder = true; 92 private Insets margin = null; 93 94 97 private boolean lightWeightPopup = true; 98 99 102 private SingleSelectionModel selectionModel; 103 104 107 private static final Object classLock = new Object (); 108 109 110 private static final boolean TRACE = false; private static final boolean VERBOSE = false; private static final boolean DEBUG = false; 114 123 public static void setDefaultLightWeightPopupEnabled(boolean aFlag) { 124 SwingUtilities.appContextPut(defaultLWPopupEnabledKey, 125 Boolean.valueOf(aFlag)); 126 } 127 128 137 public static boolean getDefaultLightWeightPopupEnabled() { 138 Boolean b = (Boolean ) 139 SwingUtilities.appContextGet(defaultLWPopupEnabledKey); 140 if (b == null) { 141 SwingUtilities.appContextPut(defaultLWPopupEnabledKey, 142 Boolean.TRUE); 143 return true; 144 } 145 return b.booleanValue(); 146 } 147 148 151 public JPopupMenu() { 152 this(null); 153 } 154 155 161 public JPopupMenu(String label) { 162 this.label = label; 163 lightWeightPopup = getDefaultLightWeightPopupEnabled(); 164 setSelectionModel(new DefaultSingleSelectionModel ()); 165 enableEvents(AWTEvent.MOUSE_EVENT_MASK); 166 setFocusTraversalKeysEnabled(false); 167 updateUI(); 168 } 169 170 171 172 177 public PopupMenuUI getUI() { 178 return (PopupMenuUI )ui; 179 } 180 181 192 public void setUI(PopupMenuUI ui) { 193 super.setUI(ui); 194 } 195 196 201 public void updateUI() { 202 setUI((PopupMenuUI )UIManager.getUI(this)); 203 } 204 205 206 213 public String getUIClassID() { 214 return uiClassID; 215 } 216 217 protected void processFocusEvent(FocusEvent evt) { 218 super.processFocusEvent(evt); 219 } 220 221 226 protected void processKeyEvent(KeyEvent evt) { 227 MenuSelectionManager.defaultManager().processKeyEvent(evt); 228 if (evt.isConsumed()) { 229 return; 230 } 231 super.processKeyEvent(evt); 232 } 233 234 235 241 public SingleSelectionModel getSelectionModel() { 242 return selectionModel; 243 } 244 245 254 public void setSelectionModel(SingleSelectionModel model) { 255 selectionModel = model; 256 } 257 258 264 public JMenuItem add(JMenuItem menuItem) { 265 super.add(menuItem); 266 return menuItem; 267 } 268 269 275 public JMenuItem add(String s) { 276 return add(new JMenuItem (s)); 277 } 278 279 293 public JMenuItem add(Action a) { 294 JMenuItem mi = createActionComponent(a); 295 mi.setAction(a); 296 add(mi); 297 return mi; 298 } 299 300 307 Point adjustPopupLocationToFitScreen(int xposition, int yposition) { 308 Point p = new Point(xposition, yposition); 309 310 if(popupPostionFixDisabled == true || GraphicsEnvironment.isHeadless()) 311 return p; 312 313 Toolkit toolkit = Toolkit.getDefaultToolkit(); 314 Rectangle screenBounds; 315 Insets screenInsets; 316 GraphicsConfiguration gc = null; 317 GraphicsEnvironment ge = 320 GraphicsEnvironment.getLocalGraphicsEnvironment(); 321 GraphicsDevice[] gd = ge.getScreenDevices(); 322 for(int i = 0; i < gd.length; i++) { 323 if(gd[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) { 324 GraphicsConfiguration dgc = 325 gd[i].getDefaultConfiguration(); 326 if(dgc.getBounds().contains(p)) { 327 gc = dgc; 328 break; 329 } 330 } 331 } 332 333 if(gc == null && getInvoker() != null) { 335 gc = getInvoker().getGraphicsConfiguration(); 336 } 337 338 if(gc != null) { 339 screenInsets = toolkit.getScreenInsets(gc); 342 screenBounds = gc.getBounds(); 343 } else { 344 screenInsets = new Insets(0, 0, 0, 0); 347 screenBounds = new Rectangle(toolkit.getScreenSize()); 348 } 349 350 int scrWidth = screenBounds.width - 351 Math.abs(screenInsets.left+screenInsets.right); 352 int scrHeight = screenBounds.height - 353 Math.abs(screenInsets.top+screenInsets.bottom); 354 355 Dimension size; 356 357 size = JPopupMenu.this.getPreferredSize(); 358 359 if( (p.x + size.width) > screenBounds.x + scrWidth ) 360 p.x = screenBounds.x + scrWidth - size.width; 361 362 if( (p.y + size.height) > screenBounds.y + scrHeight) 363 p.y = screenBounds.y + scrHeight - size.height; 364 365 368 if( p.x < screenBounds.x ) 369 p.x = screenBounds.x ; 370 if( p.y < screenBounds.y ) 371 p.y = screenBounds.y; 372 373 return p; 374 } 375 376 377 392 protected JMenuItem createActionComponent(Action a) { 393 JMenuItem mi = new JMenuItem ((String )a.getValue(Action.NAME), 394 (Icon )a.getValue(Action.SMALL_ICON)){ 395 protected PropertyChangeListener createActionPropertyChangeListener(Action a) { 396 PropertyChangeListener pcl = createActionChangeListener(this); 397 if (pcl == null) { 398 pcl = super.createActionPropertyChangeListener(a); 399 } 400 return pcl; 401 } 402 }; 403 mi.setHorizontalTextPosition(JButton.TRAILING); 404 mi.setVerticalTextPosition(JButton.CENTER); 405 mi.setEnabled(a.isEnabled()); 406 return mi; 407 } 408 409 418 protected PropertyChangeListener createActionChangeListener(JMenuItem b) { 419 return new ActionChangedListener(b); 420 } 421 422 private class ActionChangedListener implements PropertyChangeListener, Serializable { 423 private JMenuItem menuItem; 424 425 public ActionChangedListener(JMenuItem mi) { 426 super(); 427 setTarget(mi); 428 } 429 public void propertyChange(PropertyChangeEvent e) { 430 String propertyName = e.getPropertyName(); 431 if (e.getPropertyName().equals(Action.NAME)) { 432 String text = (String ) e.getNewValue(); 433 menuItem.setText(text); 434 } else if (propertyName.equals("enabled")) { 435 Boolean enabledState = (Boolean ) e.getNewValue(); 436 menuItem.setEnabled(enabledState.booleanValue()); 437 } else if (e.getPropertyName().equals(Action.SMALL_ICON)) { 438 Icon icon = (Icon ) e.getNewValue(); 439 menuItem.setIcon(icon); 440 menuItem.invalidate(); 441 menuItem.repaint(); 442 } 443 } 444 public void setTarget(JMenuItem b) { 445 this.menuItem = b; 446 } 447 } 448 449 458 public void remove(int pos) { 459 if (pos < 0) { 460 throw new IllegalArgumentException ("index less than zero."); 461 } 462 if (pos > getComponentCount() -1) { 463 throw new IllegalArgumentException ("index greater than the number of items."); 464 } 465 super.remove(pos); 466 } 467 468 489 public void setLightWeightPopupEnabled(boolean aFlag) { 490 lightWeightPopup = aFlag; 493 } 494 495 501 public boolean isLightWeightPopupEnabled() { 502 return lightWeightPopup; 503 } 504 505 511 public String getLabel() { 512 return label; 513 } 514 515 526 public void setLabel(String label) { 527 String oldValue = this.label; 528 this.label = label; 529 firePropertyChange("label", oldValue, label); 530 if (accessibleContext != null) { 531 accessibleContext.firePropertyChange( 532 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, 533 oldValue, label); 534 } 535 invalidate(); 536 repaint(); 537 } 538 539 542 public void addSeparator() { 543 add( new JPopupMenu.Separator () ); 544 } 545 546 556 public void insert(Action a, int index) { 557 JMenuItem mi = createActionComponent(a); 558 mi.setAction(a); 559 insert(mi, index); 560 } 561 562 571 public void insert(Component component, int index) { 572 if (index < 0) { 573 throw new IllegalArgumentException ("index less than zero."); 574 } 575 576 int nitems = getComponentCount(); 577 Vector tempItems = new Vector (); 579 580 584 for (int i = index ; i < nitems; i++) { 585 tempItems.addElement(getComponent(index)); 586 remove(index); 587 } 588 589 add(component); 590 591 594 for (int i = 0; i < tempItems.size() ; i++) { 595 add((Component)tempItems.elementAt(i)); 596 } 597 } 598 599 604 public void addPopupMenuListener(PopupMenuListener l) { 605 listenerList.add(PopupMenuListener.class,l); 606 } 607 608 613 public void removePopupMenuListener(PopupMenuListener l) { 614 listenerList.remove(PopupMenuListener.class,l); 615 } 616 617 625 public PopupMenuListener[] getPopupMenuListeners() { 626 return (PopupMenuListener[])listenerList.getListeners( 627 PopupMenuListener.class); 628 } 629 630 636 public void addMenuKeyListener(MenuKeyListener l) { 637 listenerList.add(MenuKeyListener.class, l); 638 } 639 640 646 public void removeMenuKeyListener(MenuKeyListener l) { 647 listenerList.remove(MenuKeyListener.class, l); 648 } 649 650 658 public MenuKeyListener[] getMenuKeyListeners() { 659 return (MenuKeyListener[])listenerList.getListeners( 660 MenuKeyListener.class); 661 } 662 663 667 protected void firePopupMenuWillBecomeVisible() { 668 Object [] listeners = listenerList.getListenerList(); 669 PopupMenuEvent e=null; 670 for (int i = listeners.length-2; i>=0; i-=2) { 671 if (listeners[i]==PopupMenuListener.class) { 672 if (e == null) 673 e = new PopupMenuEvent(this); 674 ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeVisible(e); 675 } 676 } 677 } 678 679 683 protected void firePopupMenuWillBecomeInvisible() { 684 Object [] listeners = listenerList.getListenerList(); 685 PopupMenuEvent e=null; 686 for (int i = listeners.length-2; i>=0; i-=2) { 687 if (listeners[i]==PopupMenuListener.class) { 688 if (e == null) 689 e = new PopupMenuEvent(this); 690 ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeInvisible(e); 691 } 692 } 693 } 694 695 699 protected void firePopupMenuCanceled() { 700 Object [] listeners = listenerList.getListenerList(); 701 PopupMenuEvent e=null; 702 for (int i = listeners.length-2; i>=0; i-=2) { 703 if (listeners[i]==PopupMenuListener.class) { 704 if (e == null) 705 e = new PopupMenuEvent(this); 706 ((PopupMenuListener)listeners[i+1]).popupMenuCanceled(e); 707 } 708 } 709 } 710 711 716 boolean alwaysOnTop() { 718 return true; 719 } 720 721 725 public void pack() { 726 if(popup != null) { 727 Dimension pref = getPreferredSize(); 728 729 if (pref == null || pref.width != getWidth() || 730 pref.height != getHeight()) { 731 popup = getPopup(); 732 } else { 733 validate(); 734 } 735 } 736 } 737 738 747 public void setVisible(boolean b) { 748 if (DEBUG) { 749 System.out.println("JPopupMenu.setVisible " + b); 750 } 751 752 if (b == isVisible()) 754 return; 755 756 if (b == false) { 758 759 Boolean doCanceled = (Boolean )getClientProperty("JPopupMenu.firePopupMenuCanceled"); 764 if (doCanceled != null && doCanceled == Boolean.TRUE) { 765 putClientProperty("JPopupMenu.firePopupMenuCanceled", Boolean.FALSE); 766 firePopupMenuCanceled(); 767 } 768 getSelectionModel().clearSelection(); 769 770 } else { 771 if (isPopupMenu()) { 774 if (getSubElements().length > 0) { 775 MenuElement me[] = new MenuElement [2]; 776 me[0]=(MenuElement )this; 777 me[1]=getSubElements()[0]; 778 MenuSelectionManager.defaultManager().setSelectedPath(me); 779 } else { 780 MenuElement me[] = new MenuElement [1]; 781 me[0]=(MenuElement )this; 782 MenuSelectionManager.defaultManager().setSelectedPath(me); 783 } 784 } 785 } 786 787 if(b) { 788 firePopupMenuWillBecomeVisible(); 789 popup = getPopup(); 790 firePropertyChange("visible", Boolean.FALSE, Boolean.TRUE); 791 792 793 } else if(popup != null) { 794 firePopupMenuWillBecomeInvisible(); 795 popup.hide(); 796 popup = null; 797 firePropertyChange("visible", Boolean.TRUE, Boolean.FALSE); 798 if (isPopupMenu()) { 801 MenuSelectionManager.defaultManager().clearSelectedPath(); 802 } 803 } 804 } 805 806 816 private Popup getPopup() { 817 Popup oldPopup = popup; 818 819 if (oldPopup != null) { 820 oldPopup.hide(); 821 } 822 PopupFactory popupFactory = PopupFactory.getSharedInstance(); 823 824 if (isLightWeightPopupEnabled()) { 825 popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP); 826 } 827 else { 828 popupFactory.setPopupType(PopupFactory.MEDIUM_WEIGHT_POPUP); 829 } 830 831 Point p = adjustPopupLocationToFitScreen(desiredLocationX,desiredLocationY); 833 desiredLocationX = p.x; 834 desiredLocationY = p.y; 835 836 Popup newPopup = getUI().getPopup(this, desiredLocationX, 837 desiredLocationY); 838 839 popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP); 840 newPopup.show(); 841 return newPopup; 842 } 843 844 848 public boolean isVisible() { 849 if(popup != null) 850 return true; 851 else 852 return false; 853 } 854 855 866 public void setLocation(int x, int y) { 867 int oldX = desiredLocationX; 868 int oldY = desiredLocationY; 869 870 desiredLocationX = x; 871 desiredLocationY = y; 872 if(popup != null && (x != oldX || y != oldY)) { 873 popup = getPopup(); 874 } 875 } 876 877 883 private boolean isPopupMenu() { 884 return ((invoker != null) && !(invoker instanceof JMenu )); 885 } 886 887 893 public Component getInvoker() { 894 return this.invoker; 895 } 896 897 907 public void setInvoker(Component invoker) { 908 Component oldInvoker = this.invoker; 909 this.invoker = invoker; 910 if ((oldInvoker != this.invoker) && (ui != null)) { 911 ui.uninstallUI(this); 912 ui.installUI(this); 913 } 914 invalidate(); 915 } 916 917 927 public void show(Component invoker, int x, int y) { 928 if (DEBUG) { 929 System.out.println("in JPopupMenu.show " ); 930 } 931 setInvoker(invoker); 932 Frame newFrame = getFrame(invoker); 933 if (newFrame != frame) { 934 if (newFrame!=null) { 937 this.frame = newFrame; 938 if(popup != null) { 939 setVisible(false); 940 } 941 } 942 } 943 |