1 19 package org.openide.awt; 20 21 import java.awt.Component ; 22 import java.awt.Container ; 23 import java.awt.Dimension ; 24 import java.awt.EventQueue ; 25 import java.awt.Image ; 26 import java.awt.Toolkit ; 27 import java.awt.event.ActionEvent ; 28 import java.awt.event.ActionListener ; 29 import java.awt.event.KeyEvent ; 30 import java.awt.image.FilteredImageSource ; 31 import java.awt.image.ImageProducer ; 32 import java.awt.image.RGBImageFilter ; 33 import java.beans.PropertyChangeEvent ; 34 import java.beans.PropertyChangeListener ; 35 import java.lang.ref.Reference ; 36 import java.util.List ; 37 import java.util.logging.Level ; 38 import java.util.logging.LogRecord ; 39 import java.util.logging.Logger ; 40 import org.openide.util.HelpCtx; 41 import org.openide.util.Lookup; 42 import org.openide.util.NbBundle; 43 import org.openide.util.Utilities; 44 import java.lang.ref.WeakReference ; 45 import java.util.ArrayList ; 46 import java.util.Collection ; 47 import java.util.Hashtable ; 48 import java.util.Iterator ; 49 import java.util.Map ; 50 import java.util.Observable ; 51 import java.util.Observer ; 52 import java.util.WeakHashMap ; 53 import javax.swing.AbstractButton ; 54 import javax.swing.Action ; 55 import javax.swing.Icon ; 56 import javax.swing.ImageIcon ; 57 import javax.swing.JCheckBoxMenuItem ; 58 import javax.swing.JComponent ; 59 import javax.swing.JMenu ; 60 import javax.swing.JMenuItem ; 61 import javax.swing.KeyStroke ; 62 import javax.swing.event.ChangeEvent ; 63 import javax.swing.event.ChangeListener ; 64 import javax.swing.text.Keymap ; 65 import org.openide.util.actions.BooleanStateAction; 66 import org.openide.util.actions.SystemAction; 67 68 69 73 public class Actions extends Object { 74 private static Map <Action , Reference <JMenuItem >> menuActionCache; 75 private static Object menuActionLock = new Object (); 76 77 78 private static RGBImageFilter DISABLED_BUTTON_FILTER; 79 80 85 private static Icon nonNullIcon(Icon i) { 86 return null; 87 88 96 } 97 98 102 public static String findKey(SystemAction action) { 103 return findKey((Action ) action); 104 } 105 106 108 private static String findKey(Action action) { 109 if (action == null) { 110 return null; 111 } 112 113 KeyStroke accelerator = (KeyStroke ) action.getValue(Action.ACCELERATOR_KEY); 114 115 if (accelerator == null) { 116 return null; 117 } 118 119 int modifiers = accelerator.getModifiers(); 120 String acceleratorText = ""; 122 if (modifiers > 0) { 123 acceleratorText = KeyEvent.getKeyModifiersText(modifiers); 124 acceleratorText += "+"; } else if (accelerator.getKeyCode() == KeyEvent.VK_UNDEFINED) { 126 return ""; } 128 129 acceleratorText += KeyEvent.getKeyText(accelerator.getKeyCode()); 130 131 return acceleratorText; 132 } 133 134 140 public static void connect(JMenuItem item, SystemAction action, boolean popup) { 141 connect(item, (Action ) action, popup); 142 } 143 144 155 public static void connect(JMenuItem item, Action action, boolean popup) { 156 for (ButtonActionConnector bac : Lookup.getDefault().lookupAll(ButtonActionConnector.class)) { 157 if (bac.connect(item, action, popup)) { 158 return; 159 } 160 } 161 Bridge b = new MenuBridge(item, action, popup); 162 163 if (item instanceof Actions.MenuItem) { 164 ((Actions.MenuItem)item).setBridge(b); 165 } 166 b.updateState(null); 167 if (!popup) { 168 setMenuActionConnection(item, action); 170 } 171 } 172 173 180 private static void setMenuActionConnection(JMenuItem menu, Action action) { 181 synchronized (menuActionLock) { 182 if (menuActionCache == null) { 183 menuActionCache = new WeakHashMap <Action , Reference <JMenuItem >>(); 184 185 Keymap map = (Keymap ) Lookup.getDefault().lookup(Keymap .class); 186 187 if (map instanceof Observable ) { 188 ((Observable ) map).addObserver( 190 new Observer () { 191 public void update(Observable o, Object arg) { 192 synchronized (menuActionLock) { 193 Iterator <Map.Entry <Action , Reference <JMenuItem >>> it = menuActionCache.entrySet().iterator(); 194 195 while (it.hasNext()) { 196 Map.Entry <Action , Reference <JMenuItem >> entry = it.next(); 197 Action act = entry.getKey(); 198 Reference <JMenuItem > ref = entry.getValue(); 199 JMenuItem mn = ref.get(); 200 201 if ((act != null) && (mn != null)) { 202 KeyStroke actKey = (KeyStroke ) act.getValue(Action.ACCELERATOR_KEY); 203 KeyStroke mnKey = mn.getAccelerator(); 204 205 if ( 206 ((mnKey == null) && (actKey != null)) || 207 ((mnKey != null) && (actKey == null)) || 208 ((mnKey != null) && (actKey != null) && !actKey.equals(mnKey)) 209 ) { 210 mn.setAccelerator(actKey); 211 } 212 } 213 } 214 } 215 } 216 } 217 ); 218 } else { 219 Logger.getLogger(Actions.class.getName()).warning( 220 "Keymap is not observable, behaviour described in bug #39508 can reappear." 221 ); 222 } 223 } 224 225 menuActionCache.put(action, new WeakReference <JMenuItem >(menu)); 226 } 227 } 228 229 234 public static void connect(JCheckBoxMenuItem item, BooleanStateAction action, boolean popup) { 235 Bridge b = new CheckMenuBridge(item, action, popup); 236 b.updateState(null); 237 } 238 239 244 public static void connect(AbstractButton button, SystemAction action) { 245 connect(button, (Action ) action); 246 } 247 248 267 public static void connect(AbstractButton button, Action action) { 268 for (ButtonActionConnector bac : Lookup.getDefault().lookupAll(ButtonActionConnector.class)) { 269 if (bac.connect(button, action)) { 270 return; 271 } 272 } 273 Bridge b = new ButtonBridge(button, action); 274 b.updateState(null); 275 } 276 277 281 public static void connect(AbstractButton button, BooleanStateAction action) { 282 Bridge b = new BooleanButtonBridge(button, action); 283 b.updateState(null); 284 } 285 286 294 public static void setMenuText(AbstractButton item, String text, boolean useMnemonic) { 295 if (useMnemonic) { 296 Mnemonics.setLocalizedText(item, text); 297 } else { 298 item.setText(cutAmpersand(text)); 299 } 300 } 301 302 315 public static String cutAmpersand(String text) { 316 int i; 318 String result = text; 319 320 324 i = text.indexOf("(&"); 326 if ((i >= 0) && ((i + 3) < text.length()) && 327 (text.charAt(i + 3) == ')')) { result = text.substring(0, i) + text.substring(i + 4); 329 } else { 330 i = text.indexOf('&'); 332 333 if (i < 0) { 334 result = text; 336 } else if (i == (text.length() - 1)) { 337 result = text.substring(0, i); 339 } else { 340 if (" ".equals(text.substring(i + 1, i + 2))) { 343 result = text; 344 } else { 345 result = text.substring(0, i) + text.substring(i + 1); 346 } 347 } 348 } 349 350 return result; 351 } 352 353 355 private static HelpCtx findHelp(Action a) { 356 if (a instanceof HelpCtx.Provider) { 357 return ((HelpCtx.Provider) a).getHelpCtx(); 358 } else { 359 return HelpCtx.DEFAULT_HELP; 360 } 361 } 362 363 static void prepareMenuBridgeItemsInContainer(Container c) { 366 Component [] comps = c.getComponents(); 367 368 for (int i = 0; i < comps.length; i++) { 369 if (comps[i] instanceof JComponent ) { 370 JComponent cop = (JComponent ) comps[i]; 371 MenuBridge bridge = (MenuBridge) cop.getClientProperty("menubridgeresizehack"); 372 373 if (bridge != null) { 374 bridge.updateState(null); 375 } 376 } 377 } 378 } 379 380 384 386 static void prepareMargins(JMenuItem item, Action action) { 387 item.setHorizontalTextPosition(JMenuItem.RIGHT); 388 item.setHorizontalAlignment(JMenuItem.LEFT); 389 } 390 391 395 static void updateKey(JMenuItem item, Action action) { 396 if (!(item instanceof JMenu )) { 397 item.setAccelerator((KeyStroke ) action.getValue(Action.ACCELERATOR_KEY)); 398 } 399 } 400 401 private static Icon createDisabledIcon(Image img) { 402 ImageProducer prod = new FilteredImageSource (img.getSource(), disabledButtonFilter()); 403 404 return new ImageIcon (Toolkit.getDefaultToolkit().createImage(prod), ""); 405 } 406 407 private static RGBImageFilter disabledButtonFilter() { 408 if (DISABLED_BUTTON_FILTER == null) { 409 DISABLED_BUTTON_FILTER = new DisabledButtonFilter(); 410 } 411 412 return DISABLED_BUTTON_FILTER; 413 } 414 415 419 public static interface SubMenuModel { 420 421 public int getCount(); 422 423 427 public String getLabel(int index); 428 429 433 434 436 443 public HelpCtx getHelpCtx(int index); 444 445 448 public void performActionAt(int index); 449 450 452 public void addChangeListener(ChangeListener l); 453 454 456 public void removeChangeListener(ChangeListener l); 457 } 458 459 468 private static abstract class Bridge extends Object implements PropertyChangeListener { 469 470 protected JComponent comp; 471 472 473 protected Action action; 474 475 protected PropertyChangeListener listener; 476 479 public Bridge(JComponent comp, Action action) { 480 if(comp == null || action == null) { 481 throw new IllegalArgumentException ( 482 "None of the arguments can be null: comp=" + comp + ", action=" + action); } 485 this.comp = comp; 486 this.action = action; 487 488 listener = new VisL(); 490 Bridge.this.comp.addPropertyChangeListener(listener); 491 492 if (Bridge.this.comp.isShowing()) { 493 addNotify(); 494 } 495 496 HelpCtx help = findHelp(action); 499 500 if ((help != null) && !help.equals(HelpCtx.DEFAULT_HELP) && (help.getHelpID() != null)) { 501 HelpCtx.setHelpIDString(comp, help.getHelpID()); 502 } 503 } 504 505 506 public void addNotify() { 507 action.addPropertyChangeListener(this); 508 updateState(null); 509 } 510 511 512 public void removeNotify() { 513 action.removePropertyChangeListener(this); 514 } 515 516 519 public abstract void updateState(String changedProperty); 520 521 525 public void propertyChange(final PropertyChangeEvent ev) { 526 if (!EventQueue.isDispatchThread()) { 528 new IllegalStateException ("This must happen in the event thread!").printStackTrace(); 529 } 530 531 updateState(ev.getPropertyName()); 532 } 533 534 private class VisL implements PropertyChangeListener { 539 VisL() { 540 } 541 542 public void propertyChange(final PropertyChangeEvent ev) { 543 if ("ancestor".equals(ev.getPropertyName())) { 544 if (ev.getNewValue() != null) { 546 addNotify(); 547 } else { 548 removeNotify(); 549 } 550 } 551 } 552 } 553 } 554 555 557 private static class ButtonBridge extends Bridge 558 implements ActionListener { 559 560 private static Logger UILOG = Logger.getLogger("org.netbeans.ui.actions"); 562 563 protected AbstractButton button; 564 565 public ButtonBridge(AbstractButton button, Action action) { 566 super(button, action); 567 button.addActionListener(action); 568 this.button = button; 569 button.addActionListener(this); 570 } 571 572 public void actionPerformed(ActionEvent ev) { 573 LogRecord rec = new LogRecord (Level.FINER, "UI_ACTION_BUTTON_PRESS"); rec.setParameters(new Object [] { button, button.getClass().getName(), action, action.getClass().getName(), action.getValue(Action.NAME) }); 575 rec.setResourceBundle(NbBundle.getBundle(Actions.class)); 576 rec.setResourceBundleName(Actions.class.getPackage().getName() + ".Bundle"); rec.setLoggerName(UILOG.getName()); 578 UILOG.log(rec); 579 } 580 581 protected void updateButtonIcon() { 582 Object i = null; 583 Object base = action.getValue("iconBase"); boolean useSmallIcon = true; 585 Object prop = button.getClientProperty("PreferredIconSize"); 587 if (prop instanceof Integer ) { 588 if (((Integer ) prop).intValue() == 24) { 589 useSmallIcon = false; 590 } 591 } 592 593 if (action instanceof SystemAction) { 594 if (base instanceof String ) { 595 String b = (String ) base; 596 Image img = null; 597 598 if (!useSmallIcon) { 599 img = Utilities.loadImage(insertBeforeSuffix(b, "24"), true); 601 if (img == null) { 602 img = Utilities.loadImage(b, true); 603 } 604 } else { 605 img = Utilities.loadImage(b, true); 606 } 607 608 if (img != null) { 609 i = new ImageIcon (img); 610 button.setIcon((Icon ) i); 611 button.setDisabledIcon(createDisabledIcon(img)); 612 } else { 613 SystemAction sa = (SystemAction) action; 614 i = sa.getIcon(useTextIcons()); 615 button.setIcon((Icon ) i); 616 617 if (i instanceof ImageIcon ) { 618 button.setDisabledIcon(createDisabledIcon(((ImageIcon ) i).getImage())); 619 } 620 } 621 } else { 622 SystemAction sa = (SystemAction) action; 623 i = sa.getIcon(useTextIcons()); 624 button.setIcon((Icon ) i); 625 626 if (i instanceof ImageIcon ) { 627 button.setDisabledIcon(createDisabledIcon(((ImageIcon ) i).getImage())); 628 } 629 } 630 } else { 631 if (base instanceof String ) { 633 String b = (String ) base; 634 Image img = null; 635 636 if (!useSmallIcon) { 637 img = Utilities.loadImage(insertBeforeSuffix(b, "24"), true); 639 if (img == null) { 640 img = Utilities.loadImage(b, true); 641 } 642 } else { 643 img = Utilities.loadImage(b, true); 644 } 645 646 if (img != null) { 647 i = new ImageIcon (img); 648 button.setIcon((Icon ) i); 649 button.setDisabledIcon(createDisabledIcon(img)); 650 } else { 651 i = action.getValue(Action.SMALL_ICON); 652 653 if (i instanceof Icon ) { 654 button.setIcon((Icon ) i); 655 656 if (i instanceof ImageIcon ) { 657 button.setDisabledIcon(createDisabledIcon(((ImageIcon ) i).getImage())); 658 } 659 } else { 660 button.setIcon(nonNullIcon(null)); 661 } 662 } 663 } else { 664 i = action.getValue(Action.SMALL_ICON); 665 666 if (i instanceof Icon ) { 667 button.setIcon((Icon ) i); 668 669 if (i instanceof ImageIcon ) { 670 button.setDisabledIcon(createDisabledIcon(((ImageIcon ) i).getImage())); 671 } 672 } else { 673 button.setIcon(nonNullIcon(null)); 674 } 675 } 676 } 677 678 if (base instanceof String ) { 679 String b = (String ) base; 680 681 if (!useSmallIcon) { 682 b = insertBeforeSuffix(b, "24"); } 684 685 Image img = null; 686 687 if (i == null) { 688 img = Utilities.loadImage(b, true); 690 691 if (img != null) { 692 button.setIcon(new ImageIcon (img)); 693 } 694 695 i = img; 696 } 697 698 Image pImg = Utilities.loadImage(insertBeforeSuffix(b, "_pressed"), true); 700 if (pImg != null) { 701 button.setPressedIcon(new ImageIcon (pImg)); 702 } 703 704 Image rImg = Utilities.loadImage(insertBeforeSuffix(b, "_rollover"), true); 706 if (rImg != null) { 707 button.setRolloverIcon(new ImageIcon (rImg)); 708 } 709 710 Image dImg = Utilities.loadImage(insertBeforeSuffix(b, "_disabled"), true); 712 if (dImg != null) { 713 button.setDisabledIcon(new ImageIcon (dImg)); 714 } else if (img != null) { 715 button.setDisabledIcon(createDisabledIcon(img)); 716 } 717 } 718 } 719 720 static String insertBeforeSuffix(String path, String toInsert) { 721 String withoutSuffix = path; 722 String suffix = ""; 724 if (path.lastIndexOf('.') >= 0) { 725 withoutSuffix = path.substring(0, path.lastIndexOf('.')); 726 suffix = path.substring(path.lastIndexOf('.'), path.length()); 727 } 728 729 return withoutSuffix + toInsert + suffix; 730 } 731 732 735 public void updateState(String changedProperty) { 736 if ((changedProperty == null) || changedProperty.equals(SystemAction.PROP_ENABLED)) { 738 button.setEnabled(action.isEnabled()); 739 } 740 741 if ( 742 (changedProperty == null) || changedProperty.equals(SystemAction.PROP_ICON) || 743 changedProperty.equals(Action.SMALL_ICON) || changedProperty.equals("iconBase") 744 ) { updateButtonIcon(); 746 } 747 748 if ( 749 (changedProperty == null) || changedProperty.equals(Action.ACCELERATOR_KEY) || 750 (changedProperty.equals(Action.NAME) && (action.getValue(Action.SHORT_DESCRIPTION) == null)) || 751 changedProperty.equals(Action.SHORT_DESCRIPTION) 752 ) { 753 String tip = findKey(action); 754 String toolTip = (String ) action.getValue(Action.SHORT_DESCRIPTION); 755 756 if (toolTip == null) { 757 toolTip = (String ) action.getValue(Action.NAME); 758 toolTip = (toolTip == null) ? "" : cutAmpersand(toolTip); 759 } 760 761 if ((tip == null) || tip.equals("")) { button.setToolTipText(toolTip); 763 } else { 764 button.setToolTipText( 765 org.openide.util.NbBundle.getMessage(Actions.class, "FMT_ButtonHint", toolTip, tip) 766 ); 767 } 768 } 769 770 if ( 771 button instanceof javax.accessibility.Accessible && 772 ((changedProperty == null) || changedProperty.equals(Action.NAME)) 773 ) { 774 button.getAccessibleContext().setAccessibleName((String ) action.getValue(Action.NAME)); 775 } 776 } 777 778 782 protected boolean useTextIcons() { 783 return true; 784 } 785 } 786 787 789 private static class BooleanButtonBridge extends ButtonBridge { 790 public BooleanButtonBridge(AbstractButton button, BooleanStateAction action) { 791 super(button, action); 792 } 793 794 797 public void updateState(String changedProperty) { 798 super.updateState(changedProperty); 799 800 if ((changedProperty == null) || changedProperty.equals(BooleanStateAction.PROP_BOOLEAN_STATE)) { 801 button.setSelected(((BooleanStateAction) action).getBooleanState()); 802 } 803 } 804 } 805 806 808 private static class MenuBridge extends ButtonBridge { 809 810 private boolean popup; 811 812 815 public MenuBridge(JMenuItem item, Action action, boolean popup) { 816 super(item, action); 817 this.popup = popup; 818 819 if (item instanceof Actions.MenuItem) { 820 MenuBridge.this.comp.removePropertyChangeListener(listener); 823 } 824 825 if (popup) { 826 prepareMargins(item, action); 827 } else { 828 item.putClientProperty("menubridgeresizehack", this); 830 831 } 833 } 834 835 838 public void updateState(String changedProperty) { 839 if ((changedProperty == null) || changedProperty.equals(SystemAction.PROP_ENABLED)) { 840 button.setEnabled(action.isEnabled()); 841 } 842 843 if ((changedProperty == null) || !changedProperty.equals(Action.ACCELERATOR_KEY)) { 844 updateKey((JMenuItem ) comp, action); 845 } 846 847 if (!popup) { 848 if ( 849 (changedProperty == null) || changedProperty.equals(SystemAction.PROP_ICON) || 850 changedProperty.equals(Action.SMALL_ICON) || changedProperty.equals("iconBase") 851 ) { updateButtonIcon(); 853 } 854 } 855 856 if ((changedProperty == null) || changedProperty.equals(Action.NAME)) { 857 Object s = action.getValue(Action.NAME); 858 859 if (s instanceof String ) { 860 setMenuText(((JMenuItem ) comp), (String ) s, true); 861 862 } 865 } 866 } 867 868 protected void updateButtonIcon() { 869 Object i = null; 870 Object obj = action.getValue("noIconInMenu"); 872 if (Boolean.TRUE.equals(obj)) { 873 return; 875 } 876 877 if (action instanceof SystemAction) { 878 SystemAction sa = (SystemAction) action; 879 i = sa.getIcon(useTextIcons()); 880 button.setIcon((Icon ) i); 881 882 if (i instanceof ImageIcon ) { 883 button.setDisabledIcon(createDisabledIcon(((ImageIcon ) i).getImage())); 884 } 885 } else { 886 i = action.getValue(Action.SMALL_ICON); 887 888 if (i instanceof Icon ) { 889 button.setIcon((Icon ) i); 890 891 if (i instanceof ImageIcon ) { 892 button.setDisabledIcon(createDisabledIcon(((ImageIcon ) i).getImage())); 893 } 894 } else { 895 } 897 } 898 899 Object base = action.getValue("iconBase"); 901 if (base instanceof String ) { 902 String b = (String ) base; 903 Image img = null; 904 905 if (i == null) { 906 img = Utilities.loadImage(b, true); 908 909 if (img != null) { 910 button.setIcon(new ImageIcon (img)); 911 button.setDisabledIcon(createDisabledIcon(img)); 912 } 913 } 914 915 Image pImg = Utilities.loadImage(insertBeforeSuffix(b, "_pressed"), true); 917 if (pImg != null) { 918 button.setPressedIcon(new ImageIcon (pImg)); 919 } 920 921 Image rImg = Utilities.loadImage(insertBeforeSuffix(b, "_rollover"), true); 923 if (rImg != null) { 924 button.setRolloverIcon(new ImageIcon (rImg)); 925 } 926 927 Image dImg = Utilities.loadImage(insertBeforeSuffix(b, "_disabled"), true); 929 if (dImg != null) { 930 button.setDisabledIcon(new ImageIcon (dImg)); 931 } else if (img != null) { 932 button.setDisabledIcon(createDisabledIcon(img)); 933 } 934 } 935 } 936 937 protected boolean useTextIcons() { 939 return false; 940 } 941 } 942 943 945 private static final class CheckMenuBridge extends BooleanButtonBridge { 946 947 private boolean popup; 948 private boolean hasOwnIcon = false; 949 950 951 public CheckMenuBridge(JCheckBoxMenuItem item, BooleanStateAction action, boolean popup) { 952 super(item, action); 953 this.popup = popup; 954 955 if (popup) { 956 prepareMargins(item, action); 957 } 958 959 Object base = action.getValue("iconBase"); Object i = null; 961 962 if (action instanceof SystemAction) { 963 i = action.getValue(SystemAction.PROP_ICON); 964 } else { 965 i = action.getValue(Action.SMALL_ICON); 966 } 967 968 hasOwnIcon = (base != null) || (i != null); 969 } 970 971 974 public void updateState(String changedProperty) { 975 super.updateState(changedProperty); 976 977 if ((changedProperty == null) || !changedProperty.equals(Action.ACCELERATOR_KEY)) { 978 updateKey((JMenuItem ) comp, action); 979 } 980 981 if ((changedProperty == null) || changedProperty.equals(Action.NAME)) { 982 Object s = action.getValue(Action.NAME); 983 984 if (s instanceof String ) { 985 setMenuText(((JMenuItem ) comp), (String ) s, true); 986 } 987 } 988 } 989 990 protected void updateButtonIcon() { 991 if (hasOwnIcon) { 992 super.updateButtonIcon(); 993 994 return; 995 } 996 997 if (!popup) { 998 button.setIcon(new ImageIcon (Utilities.loadImage("org/openide/resources/actions/gap.gif", true))); } 1000 } 1001 1002 protected boolean useTextIcons() { 1003 return false; 1004 } 1005 } 1006 1007 1008 1011 private static class ISubActionListener implements java.awt.event.ActionListener { 1012 int index; 1013 SubMenuModel support; 1014 1015 public ISubActionListener(int index, SubMenuModel support) { 1016 this.index = index; 1017 this.support = support; 1018 } 1019 1020 1021 public void actionPerformed(ActionEvent e) { 1022 support.performActionAt(index); 1023 } 1024 } 1025 1026 1028 private static final class SubMenuBridge extends MenuBridge implements ChangeListener , DynamicMenuContent { 1029 1030 private SubMenuModel model; 1031 private List <JMenuItem > currentOnes; 1032 private JMenuItem single; 1033 private JMenu multi; 1034 1036 public SubMenuBridge(JMenuItem one, JMenu more, Action action, SubMenuModel model, boolean popup) { 1037 super(one, action, popup); 1038 single = one; 1039 multi = more; 1040 setMenuText(multi, (String )action.getValue(Action.NAME), popup); 1041 prepareMargins(one, action); 1042 prepareMargins(more, action); 1043 currentOnes = new ArrayList <JMenuItem >(); 1044 this.model = model; 1045 } 1046 1047 1049 public void stateChanged(ChangeEvent ev) { 1050 if (!EventQueue.isDispatchThread()) { 1052 new IllegalStateException ("This must happen in the event thread!").printStackTrace(); 1053 } 1054 } 1057 1058 public void updateState(String changedProperty) { 1059 super.updateState(changedProperty); 1060 } 1062 1063 1064 1065 public JComponent [] getMenuPresenters() { 1066 return synchMenuPresenters(null); 1067 } 1068 1069 public JComponent [] synchMenuPresenters(JComponent [] items) { 1070 currentOnes.clear(); 1071 int cnt = model.getCount(); 1072 1073 if (cnt == 0) { 1074 updateState(null); 1075 currentOnes.add(single); 1076 single.setEnabled(false); 1078 } else if (cnt == 1) { 1079 updateState(null); 1080 currentOnes.add(single); 1081 single.setEnabled(action.isEnabled()); 1082 HelpCtx help = model.getHelpCtx(0); 1084 associateHelp(single, (help == null) ? findHelp(action) : help); 1085 } else { 1086 currentOnes.add(multi); 1087 multi.removeAll(); 1088 Mnemonics.setLocalizedText(multi, (String )action.getValue(Action.NAME)); 1090 1091 boolean addSeparator = false; 1092 int count = model.getCount(); 1093 1094 for (int i = 0; i < count; i++) { 1095 String label = model.getLabel(i); 1096 1097 if (label == null) { 1099 addSeparator = multi.getItemCount() > 0; 1100 } else { 1101 if (addSeparator) { 1102 multi.addSeparator(); 1103 addSeparator = false; 1104 } 1105 1106 JMenuItem item = new JMenuItem (); 1109 Mnemonics.setLocalizedText(item, label); 1110 1111 if (i == 0) { 1113 updateKey(item, action); 1114 } 1115 1116 item.addActionListener(new ISubActionListener(i, model)); 1117 1118 HelpCtx help = model.getHelpCtx(i); 1119 associateHelp(item, (help == null) ? findHelp(action) : help); 1120 multi.add(item); 1121 } 1122 1123 associateHelp(multi, findHelp(action)); 1124 } 1125 multi.setEnabled(true); 1126 } 1127 return currentOnes.toArray(new JMenuItem [currentOnes.size()]); 1128 1129 } 1130 1131 private void associateHelp(JComponent comp, HelpCtx help) { 1132 if ((help != null) && !help.equals(HelpCtx.DEFAULT_HELP) && (help.getHelpID() != null)) { 1133 HelpCtx.setHelpIDString(comp, help.getHelpID()); 1134 } else { 1135 HelpCtx.setHelpIDString(comp, null); 1136 } 1137 } 1138 } 1139 1145 1149 public static class MenuItem extends javax.swing.JMenuItem implements DynamicMenuContent { 1150 static final long serialVersionUID = -21757335363267194L; 1151 private Actions.Bridge bridge; 1152 1157 public MenuItem(SystemAction aAction, boolean useMnemonic) { 1158 Actions.connect(this, aAction, !useMnemonic); 1159 } 1160 1161 1166 public MenuItem(Action aAction, boolean useMnemonic) { 1167 Actions.connect(this, aAction, !useMnemonic); 1168 } 1169 1170 void setBridge(Actions.Bridge br) { 1171 bridge = br; 1172 } 1173 1174 public JComponent [] synchMenuPresenters(JComponent [] items) { 1175 if (bridge != null) { 1176 bridge.updateState(null); 1177 } 1178 return getMenuPresenters(); 1179 } 1180 1181 public JComponent [] getMenuPresenters() { 1182 return new JComponent [] {this}; 1183 } 1184 1185 } 1186 1187 1195 public static class CheckboxMenuItem extends javax.swing.JCheckBoxMenuItem { 1196 static final long serialVersionUID = 6190621106981774043L; 1197 1198 1203 public CheckboxMenuItem(BooleanStateAction aAction, boolean useMnemonic) { 1204 Actions.connect(this, aAction, !useMnemonic); 1205 } 1206 } 1207 1208 1211 public static class ToolbarButton extends org.openide.awt.ToolbarButton { 1212 static final long serialVersionUID = 6564434578524381134L; 1213 1214 public ToolbarButton(SystemAction aAction) { 1215 super(null); 1216 Actions.connect(this, aAction); 1217 } 1218 1219 public ToolbarButton(Action aAction) { 1220 super(null); 1221 Actions.connect(this, aAction); 1222 } 1223 1224 1231 public Dimension getMaximumSize() { 1232 return this.getPreferredSize(); 1233 } 1234 1235 public Dimension getMinimumSize() { 1236 return this.getPreferredSize(); 1237 } 1238 } 1239 1240 1245 public static class ToolbarToggleButton extends org.openide.awt.ToolbarToggleButton { 1246 static final long serialVersionUID = -4783163952526348942L; 1247 1248 1249 public ToolbarToggleButton(BooleanStateAction aAction) { 1250 super(null, false); 1251 Actions.connect(this, aAction); 1252 } 1253 1254 1261 public Dimension getMaximumSize() { 1262 return this.getPreferredSize(); 1263 } 1264 1265 public Dimension getMinimumSize() { 1266 return this.getPreferredSize(); 1267 } 1268 } 1269 1270 1271 1274 public static class SubMenu extends JMenuPlus implements DynamicMenuContent { 1275 static final long serialVersionUID = -4446966671302959091L; 1276 1277 private SubMenuBridge bridge; 1278 1279 1285 public SubMenu(SystemAction aAction, SubMenuModel model) { 1286 this(aAction, model, true); 1287 } 1288 1289 1296 public SubMenu(SystemAction aAction, SubMenuModel model, boolean popup) { 1297 this((Action ) aAction, model, popup); 1298 } 1299 1300 1307 public SubMenu(Action aAction, SubMenuModel model, boolean popup) { 1308 bridge = new SubMenuBridge(new JMenuItem (), this, aAction, model, popup); 1309 1310 bridge.updateState(Action.NAME); 1312 } 1313 1314 public JComponent [] getMenuPresenters() { 1315 return bridge.getMenuPresenters(); 1316 } 1317 1318 public JComponent [] synchMenuPresenters(JComponent [] items) { 1319 return bridge.synchMenuPresenters(items); 1320 } 1321 1322 } 1323 1324 1333 public interface ButtonActionConnector { 1334 1340 boolean connect(AbstractButton button, Action action); 1341 1347 boolean connect(JMenuItem item, Action action, boolean popup); 1348 } 1349 1350 private static class DisabledButtonFilter extends RGBImageFilter { 1351 DisabledButtonFilter() { 1352 canFilterIndexColorModel = true; 1353 } 1354 1355 public int filterRGB(int x, int y, int rgb) { 1356 return (rgb & 0xff000000) + 0x888888 + ((((rgb >> 16) & 0xff) >> 2) << 16) + 1358 ((((rgb >> 8) & 0xff) >> 2) << 8) + (((rgb) & 0xff) >> 2); 1359 } 1360 1361 public void setProperties(Hashtable props) { 1364 props = (Hashtable ) props.clone(); 1365 consumer.setProperties(props); 1366 } 1367 } 1368} 1369 | Popular Tags |