KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > awt > Actions


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.openide.awt;
20
21 import java.awt.Component JavaDoc;
22 import java.awt.Container JavaDoc;
23 import java.awt.Dimension JavaDoc;
24 import java.awt.EventQueue JavaDoc;
25 import java.awt.Image JavaDoc;
26 import java.awt.Toolkit JavaDoc;
27 import java.awt.event.ActionEvent JavaDoc;
28 import java.awt.event.ActionListener JavaDoc;
29 import java.awt.event.KeyEvent JavaDoc;
30 import java.awt.image.FilteredImageSource JavaDoc;
31 import java.awt.image.ImageProducer JavaDoc;
32 import java.awt.image.RGBImageFilter JavaDoc;
33 import java.beans.PropertyChangeEvent JavaDoc;
34 import java.beans.PropertyChangeListener JavaDoc;
35 import java.lang.ref.Reference JavaDoc;
36 import java.util.List JavaDoc;
37 import java.util.logging.Level JavaDoc;
38 import java.util.logging.LogRecord JavaDoc;
39 import java.util.logging.Logger JavaDoc;
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 JavaDoc;
45 import java.util.ArrayList JavaDoc;
46 import java.util.Collection JavaDoc;
47 import java.util.Hashtable JavaDoc;
48 import java.util.Iterator JavaDoc;
49 import java.util.Map JavaDoc;
50 import java.util.Observable JavaDoc;
51 import java.util.Observer JavaDoc;
52 import java.util.WeakHashMap JavaDoc;
53 import javax.swing.AbstractButton JavaDoc;
54 import javax.swing.Action JavaDoc;
55 import javax.swing.Icon JavaDoc;
56 import javax.swing.ImageIcon JavaDoc;
57 import javax.swing.JCheckBoxMenuItem JavaDoc;
58 import javax.swing.JComponent JavaDoc;
59 import javax.swing.JMenu JavaDoc;
60 import javax.swing.JMenuItem JavaDoc;
61 import javax.swing.KeyStroke JavaDoc;
62 import javax.swing.event.ChangeEvent JavaDoc;
63 import javax.swing.event.ChangeListener JavaDoc;
64 import javax.swing.text.Keymap JavaDoc;
65 import org.openide.util.actions.BooleanStateAction;
66 import org.openide.util.actions.SystemAction;
67
68
69 /** Supporting class for manipulation with menu and toolbar presenters.
70 *
71 * @author Jaroslav Tulach
72 */

73 public class Actions extends Object JavaDoc {
74     private static Map JavaDoc<Action JavaDoc, Reference JavaDoc<JMenuItem JavaDoc>> menuActionCache;
75     private static Object JavaDoc menuActionLock = new Object JavaDoc();
76
77     /** Shared instance of filter for disabled icons */
78     private static RGBImageFilter JavaDoc DISABLED_BUTTON_FILTER;
79
80     /**
81      * Make sure an icon is not null, so that e.g. menu items for javax.swing.Action's
82      * with no specified icon are correctly aligned. SystemAction already does this so
83      * that is not affected.
84      */

85     private static Icon JavaDoc nonNullIcon(Icon JavaDoc i) {
86         return null;
87
88         /*if (i != null) {
89             return i;
90         } else {
91             if (BLANK_ICON == null) {
92                 BLANK_ICON = new ImageIcon(Utilities.loadImage("org/openide/resources/actions/empty.gif", true)); // NOI18N
93             }
94             return BLANK_ICON;
95         }*/

96     }
97
98     /** Method that finds the keydescription assigned to this action.
99     * @param action action to find key for
100     * @return the text representing the key or null if there is no text assigned
101     */

102     public static String JavaDoc findKey(SystemAction action) {
103         return findKey((Action JavaDoc) action);
104     }
105
106     /** Same method as above, but works just with plain actions.
107      */

108     private static String JavaDoc findKey(Action JavaDoc action) {
109         if (action == null) {
110             return null;
111         }
112
113         KeyStroke JavaDoc accelerator = (KeyStroke JavaDoc) action.getValue(Action.ACCELERATOR_KEY);
114
115         if (accelerator == null) {
116             return null;
117         }
118
119         int modifiers = accelerator.getModifiers();
120         String JavaDoc acceleratorText = ""; // NOI18N
121

122         if (modifiers > 0) {
123             acceleratorText = KeyEvent.getKeyModifiersText(modifiers);
124             acceleratorText += "+"; // NOI18N
125
} else if (accelerator.getKeyCode() == KeyEvent.VK_UNDEFINED) {
126             return ""; // NOI18N
127
}
128
129         acceleratorText += KeyEvent.getKeyText(accelerator.getKeyCode());
130
131         return acceleratorText;
132     }
133
134     /** Attaches menu item to an action.
135     * @param item menu item
136     * @param action action
137     * @param popup create popup or menu item
138      * @deprecated Use {@link #connect(JMenuItem, Action, boolean)} instead.
139     */

140     public static void connect(JMenuItem JavaDoc item, SystemAction action, boolean popup) {
141         connect(item, (Action JavaDoc) action, popup);
142     }
143
144     /** Attaches menu item to an action.
145      * You can supply an alternative implementation
146      * for this method by implementing method
147      * {@link ButtonActionConnector#connect(JMenuItem, Action, boolean)} and
148      * registering an instance of {@link ButtonActionConnector} in the
149      * default lookup.
150      * @param item menu item
151      * @param action action
152      * @param popup create popup or menu item
153      * @since 3.29
154      */

155     public static void connect(JMenuItem JavaDoc item, Action JavaDoc 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             // #39508 fix.
169
setMenuActionConnection(item, action);
170         }
171     }
172
173     /**
174      * #39508 fix. the MenuItems have the accelerator set by the Bridge, however that is not removed when the Menu is invisible.
175      * it's because of the AddNotify/removeNotify method calls and the Bridge.VisL listener.
176      * that conflicts with the changes done in the global keymap (NbKeymap) that are not propagated to the menu items when such change occurs.
177      * Fixed by having one global observer on the NbKeyMap (or any other Keymap impl which is Observable) and always synchronizing the menus with the current
178      * global Keymap
179      */

180     private static void setMenuActionConnection(JMenuItem JavaDoc menu, Action JavaDoc action) {
181         synchronized (menuActionLock) {
182             if (menuActionCache == null) {
183                 menuActionCache = new WeakHashMap JavaDoc<Action JavaDoc, Reference JavaDoc<JMenuItem JavaDoc>>();
184
185                 Keymap JavaDoc map = (Keymap JavaDoc) Lookup.getDefault().lookup(Keymap JavaDoc.class);
186
187                 if (map instanceof Observable JavaDoc) {
188                     //HACK MAJOR - assuming we have the NbKeymap which is observable
189
((Observable JavaDoc) map).addObserver(
190                         new Observer JavaDoc() {
191                             public void update(Observable JavaDoc o, Object JavaDoc arg) {
192                                 synchronized (menuActionLock) {
193                                     Iterator JavaDoc<Map.Entry JavaDoc<Action JavaDoc, Reference JavaDoc<JMenuItem JavaDoc>>> it = menuActionCache.entrySet().iterator();
194
195                                     while (it.hasNext()) {
196                                         Map.Entry JavaDoc<Action JavaDoc, Reference JavaDoc<JMenuItem JavaDoc>> entry = it.next();
197                                         Action JavaDoc act = entry.getKey();
198                                         Reference JavaDoc<JMenuItem JavaDoc> ref = entry.getValue();
199                                         JMenuItem JavaDoc mn = ref.get();
200
201                                         if ((act != null) && (mn != null)) {
202                                             KeyStroke JavaDoc actKey = (KeyStroke JavaDoc) act.getValue(Action.ACCELERATOR_KEY);
203                                             KeyStroke JavaDoc 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 JavaDoc<JMenuItem JavaDoc>(menu));
226         }
227     }
228
229     /** Attaches checkbox menu item to boolean state action.
230     * @param item menu item
231     * @param action action
232     * @param popup create popup or menu item
233     */

234     public static void connect(JCheckBoxMenuItem JavaDoc item, BooleanStateAction action, boolean popup) {
235         Bridge b = new CheckMenuBridge(item, action, popup);
236         b.updateState(null);
237     }
238
239     /** Connects buttons to action.
240     * @param button the button
241     * @param action the action
242      * @deprecated Use {@link #connect(AbstractButton, Action)} instead.
243     */

244     public static void connect(AbstractButton JavaDoc button, SystemAction action) {
245         connect(button, (Action JavaDoc) action);
246     }
247
248     /** Connects buttons to action. If the action supplies value for "iconBase"
249      * key from getValue(String) with a path to icons the methods setIcon,
250      * setPressedIcon, setDisabledIcon and setRolloverIcon will be called on the
251      * button with loaded icons using the iconBase. E.g. if the value for "iconBase"
252      * will be "com/mycompany/myIcon.gif" following images will be tried "com/mycompany/myIcon.gif"
253      * for setIcon, "com/mycompany/myIcon_pressed.gif" for setPressedIcon,
254      * "com/mycompany/myIcon_disabled.gif" for setDisabledIcon and
255      * "com/mycompany/myIcon_rollover.gif" for setRolloverIcon. SystemAction has
256      * special support for iconBase - please check {@link SystemAction#iconResource}
257      * for more details.
258      * You can supply an alternative implementation
259      * for this method by implementing method
260      * {@link ButtonActionConnector#connect(AbstractButton, Action)} and
261      * registering an instance of {@link ButtonActionConnector} in the
262      * default lookup.
263      * @param button the button
264      * @param action the action
265      * @since 3.29
266      */

267     public static void connect(AbstractButton JavaDoc button, Action JavaDoc 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     /** Connects buttons to action.
278     * @param button the button
279     * @param action the action
280     */

281     public static void connect(AbstractButton JavaDoc button, BooleanStateAction action) {
282         Bridge b = new BooleanButtonBridge(button, action);
283         b.updateState(null);
284     }
285
286     /** Sets the text for the menu item or other subclass of AbstractButton.
287     * Cut from the name '&' char.
288     * @param item AbstractButton
289     * @param text new label
290     * @param useMnemonic if true and '&' char found in new text, next char is used
291     * as Mnemonic.
292     * @deprecated Use either {@link AbstractButton#setText} or {@link Mnemonics#setLocalizedText(AbstractButton, String)} as appropriate.
293     */

294     public static void setMenuText(AbstractButton JavaDoc item, String JavaDoc text, boolean useMnemonic) {
295         if (useMnemonic) {
296             Mnemonics.setLocalizedText(item, text);
297         } else {
298             item.setText(cutAmpersand(text));
299         }
300     }
301
302     /**
303      * Removes an ampersand from a text string; commonly used to strip out unneeded mnemonics.
304      * Replaces the first occurence of <samp>&amp;?</samp> by <samp>?</samp> or <samp>(&amp;??</samp> by the empty string
305      * where <samp>?</samp> is a wildcard for any character.
306      * <samp>&amp;?</samp> is a shortcut in English locale.
307      * <samp>(&amp;?)</samp> is a shortcut in Japanese locale.
308      * Used to remove shortcuts from workspace names (or similar) when shortcuts are not supported.
309      * <p>The current implementation behaves in the same way regardless of locale.
310      * In case of a conflict it would be necessary to change the
311      * behavior based on the current locale.
312      * @param text a localized label that may have mnemonic information in it
313      * @return string without first <samp>&amp;</samp> if there was any
314      */

315     public static String JavaDoc cutAmpersand(String JavaDoc text) {
316         // XXX should this also be deprecated by something in Mnemonics?
317
int i;
318         String JavaDoc result = text;
319
320         /* First check of occurence of '(&'. If not found check
321           * for '&' itself.
322           * If '(&' is found then remove '(&??'.
323           */

324         i = text.indexOf("(&"); // NOI18N
325

326         if ((i >= 0) && ((i + 3) < text.length()) && /* #31093 */
327                 (text.charAt(i + 3) == ')')) { // NOI18N
328
result = text.substring(0, i) + text.substring(i + 4);
329         } else {
330             //Sequence '(&?)' not found look for '&' itself
331
i = text.indexOf('&');
332
333             if (i < 0) {
334                 //No ampersand
335
result = text;
336             } else if (i == (text.length() - 1)) {
337                 //Ampersand is last character, wrong shortcut but we remove it anyway
338
result = text.substring(0, i);
339             } else {
340                 //Remove ampersand from middle of string
341
//Is ampersand followed by space? If yes do not remove it.
342
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     /** Extracts help from action.
354      */

355     private static HelpCtx findHelp(Action JavaDoc a) {
356         if (a instanceof HelpCtx.Provider) {
357             return ((HelpCtx.Provider) a).getHelpCtx();
358         } else {
359             return HelpCtx.DEFAULT_HELP;
360         }
361     }
362
363     // #40824 - when the text changes, it's too late to update in JmenuPlus.popup.show() (which triggers the updateState() in the MenuBridge).
364
// check JmenuPlus.setPopupMenuVisible()
365
static void prepareMenuBridgeItemsInContainer(Container JavaDoc c) {
366         Component JavaDoc[] comps = c.getComponents();
367
368         for (int i = 0; i < comps.length; i++) {
369             if (comps[i] instanceof JComponent JavaDoc) {
370                 JComponent JavaDoc cop = (JComponent JavaDoc) comps[i];
371                 MenuBridge bridge = (MenuBridge) cop.getClientProperty("menubridgeresizehack");
372
373                 if (bridge != null) {
374                     bridge.updateState(null);
375                 }
376             }
377         }
378     }
379
380     //
381
// Methods for configuration of MenuItems
382
//
383

384     /** Method to prepare the margins and text positions.
385     */

386     static void prepareMargins(JMenuItem JavaDoc item, Action JavaDoc action) {
387         item.setHorizontalTextPosition(JMenuItem.RIGHT);
388         item.setHorizontalAlignment(JMenuItem.LEFT);
389     }
390
391     /** Updates value of the key
392     * @param item item to update
393     * @param action the action to update
394     */

395     static void updateKey(JMenuItem JavaDoc item, Action JavaDoc action) {
396         if (!(item instanceof JMenu JavaDoc)) {
397             item.setAccelerator((KeyStroke JavaDoc) action.getValue(Action.ACCELERATOR_KEY));
398         }
399     }
400
401     private static Icon JavaDoc createDisabledIcon(Image JavaDoc img) {
402         ImageProducer JavaDoc prod = new FilteredImageSource JavaDoc(img.getSource(), disabledButtonFilter());
403
404         return new ImageIcon JavaDoc(Toolkit.getDefaultToolkit().createImage(prod), "");
405     }
406
407     private static RGBImageFilter JavaDoc disabledButtonFilter() {
408         if (DISABLED_BUTTON_FILTER == null) {
409             DISABLED_BUTTON_FILTER = new DisabledButtonFilter();
410         }
411
412         return DISABLED_BUTTON_FILTER;
413     }
414
415     /** Interface for the creating Actions.SubMenu. It provides the methods for
416     * all items in submenu: name shortcut and perform method. Also has methods
417     * for notification of changes of the model.
418     */

419     public static interface SubMenuModel {
420         /** @return count of the submenu items. */
421         public int getCount();
422
423         /** Gets label for specific index
424         * @param index of the submenu item
425         * @return label for this menu item (or <code>null</code> for a separator)
426         */

427         public String JavaDoc getLabel(int index);
428
429         /** Gets shortcut for specific index
430         * @index of the submenu item
431         * @return menushortcut for this menu item
432         */

433
434         // public MenuShortcut getMenuShortcut(int index);
435

436         /** Get context help for the specified item.
437         * This can be used to associate help with individual items.
438         * You may return <code>null</code> to just use the context help for
439         * the associated system action (if any).
440         * Note that only help IDs will work, not URLs.
441         * @return the context help, or <code>null</code>
442         */

443         public HelpCtx getHelpCtx(int index);
444
445         /** Perform the action on the specific index
446         * @param index of the submenu item which should be performed
447         */

448         public void performActionAt(int index);
449
450         /** Adds change listener for changes of the model.
451         */

452         public void addChangeListener(ChangeListener JavaDoc l);
453
454         /** Removes change listener for changes of the model.
455         */

456         public void removeChangeListener(ChangeListener JavaDoc l);
457     }
458
459     /** Listener on showing/hiding state of the component.
460     * Is attached to menu or toolbar item in prepareXXX methods and
461     * method addNotify is called when the item is showing and
462     * the method removeNotify is called when the item is hidding.
463     * <P>
464     * There is a special support listening on changes in the action and
465     * if such change occures, updateState method is called to
466     * reflect it.
467     */

468     private static abstract class Bridge extends Object JavaDoc implements PropertyChangeListener JavaDoc {
469         /** component to work with */
470         protected JComponent JavaDoc comp;
471
472         /** action to associate */
473         protected Action JavaDoc action;
474         
475         protected PropertyChangeListener JavaDoc listener;
476         /** @param comp component
477         * @param action the action
478         */

479         public Bridge(JComponent JavaDoc comp, Action JavaDoc action) {
480             if(comp == null || action == null) {
481                 throw new IllegalArgumentException JavaDoc(
482                     "None of the arguments can be null: comp=" + comp + //NOI18N
483
", action=" + action); // NOI18N
484
}
485             this.comp = comp;
486             this.action = action;
487
488             // visibility listener
489
listener = new VisL();
490             Bridge.this.comp.addPropertyChangeListener(listener);
491
492             if (Bridge.this.comp.isShowing()) {
493                 addNotify();
494             }
495
496             // associate context help, if applicable
497
// [PENDING] probably belongs in ButtonBridge.updateState to make it dynamic
498
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         /** Attaches listener to given action */
506         public void addNotify() {
507             action.addPropertyChangeListener(this);
508             updateState(null);
509         }
510
511         /** Remove the listener */
512         public void removeNotify() {
513             action.removePropertyChangeListener(this);
514         }
515
516         /** @param changedProperty the name of property that has changed
517         * or null if it is not known
518         */

519         public abstract void updateState(String JavaDoc changedProperty);
520
521         /** Listener to changes of some properties.
522         * Multicast - reacts to keymap changes and ancestor changes
523         * together.
524         */

525         public void propertyChange(final PropertyChangeEvent JavaDoc ev) {
526             //assert EventQueue.isDispatchThread();
527
if (!EventQueue.isDispatchThread()) {
528                 new IllegalStateException JavaDoc("This must happen in the event thread!").printStackTrace();
529             }
530
531             updateState(ev.getPropertyName());
532         }
533
534         // Must be separate from general PCL, because otherwise
535
// SystemAction.PROP_ENABLED -> updateState("enabled") ->
536
// button.setEnabled(...) -> JButton.PROP_ENABLED ->
537
// updateState("enabled") -> button.setEnabled(same)
538
private class VisL implements PropertyChangeListener JavaDoc {
539             VisL() {
540             }
541
542             public void propertyChange(final PropertyChangeEvent JavaDoc ev) {
543                 if ("ancestor".equals(ev.getPropertyName())) {
544                     // ancestor change - decide if parent is null or not
545
if (ev.getNewValue() != null) {
546                         addNotify();
547                     } else {
548                         removeNotify();
549                     }
550                 }
551             }
552         }
553     }
554
555     /** Bridge between an action and button.
556     */

557     private static class ButtonBridge extends Bridge
558     implements ActionListener JavaDoc {
559         /** UI logger to notify about invocation of an action */
560         private static Logger JavaDoc UILOG = Logger.getLogger("org.netbeans.ui.actions"); // NOI18N
561

562         /** the button */
563         protected AbstractButton JavaDoc button;
564
565         public ButtonBridge(AbstractButton JavaDoc button, Action JavaDoc action) {
566             super(button, action);
567             button.addActionListener(action);
568             this.button = button;
569             button.addActionListener(this);
570         }
571         
572         public void actionPerformed(ActionEvent JavaDoc ev) {
573             LogRecord JavaDoc rec = new LogRecord JavaDoc(Level.FINER, "UI_ACTION_BUTTON_PRESS"); // NOI18N
574
rec.setParameters(new Object JavaDoc[] { 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"); // NOI18N
577
rec.setLoggerName(UILOG.getName());
578             UILOG.log(rec);
579         }
580
581         protected void updateButtonIcon() {
582             Object JavaDoc i = null;
583             Object JavaDoc base = action.getValue("iconBase"); // NOI18N
584
boolean useSmallIcon = true;
585             Object JavaDoc prop = button.getClientProperty("PreferredIconSize"); //NOI18N
586

587             if (prop instanceof Integer JavaDoc) {
588                 if (((Integer JavaDoc) prop).intValue() == 24) {
589                     useSmallIcon = false;
590                 }
591             }
592
593             if (action instanceof SystemAction) {
594                 if (base instanceof String JavaDoc) {
595                     String JavaDoc b = (String JavaDoc) base;
596                     Image JavaDoc img = null;
597
598                     if (!useSmallIcon) {
599                         img = Utilities.loadImage(insertBeforeSuffix(b, "24"), true); // NOI18N
600

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 JavaDoc(img);
610                         button.setIcon((Icon JavaDoc) i);
611                         button.setDisabledIcon(createDisabledIcon(img));
612                     } else {
613                         SystemAction sa = (SystemAction) action;
614                         i = sa.getIcon(useTextIcons());
615                         button.setIcon((Icon JavaDoc) i);
616
617                         if (i instanceof ImageIcon JavaDoc) {
618                             button.setDisabledIcon(createDisabledIcon(((ImageIcon JavaDoc) i).getImage()));
619                         }
620                     }
621                 } else {
622                     SystemAction sa = (SystemAction) action;
623                     i = sa.getIcon(useTextIcons());
624                     button.setIcon((Icon JavaDoc) i);
625
626                     if (i instanceof ImageIcon JavaDoc) {
627                         button.setDisabledIcon(createDisabledIcon(((ImageIcon JavaDoc) i).getImage()));
628                     }
629                 }
630             } else {
631                 //Try to get icon from iconBase for non SystemAction action
632
if (base instanceof String JavaDoc) {
633                     String JavaDoc b = (String JavaDoc) base;
634                     Image JavaDoc img = null;
635
636                     if (!useSmallIcon) {
637                         img = Utilities.loadImage(insertBeforeSuffix(b, "24"), true); // NOI18N
638

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 JavaDoc(img);
648                         button.setIcon((Icon JavaDoc) i);
649                         button.setDisabledIcon(createDisabledIcon(img));
650                     } else {
651                         i = action.getValue(Action.SMALL_ICON);
652
653                         if (i instanceof Icon JavaDoc) {
654                             button.setIcon((Icon JavaDoc) i);
655
656                             if (i instanceof ImageIcon JavaDoc) {
657                                 button.setDisabledIcon(createDisabledIcon(((ImageIcon JavaDoc) 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 JavaDoc) {
667                         button.setIcon((Icon JavaDoc) i);
668
669                         if (i instanceof ImageIcon JavaDoc) {
670                             button.setDisabledIcon(createDisabledIcon(((ImageIcon JavaDoc) i).getImage()));
671                         }
672                     } else {
673                         button.setIcon(nonNullIcon(null));
674                     }
675                 }
676             }
677
678             if (base instanceof String JavaDoc) {
679                 String JavaDoc b = (String JavaDoc) base;
680
681                 if (!useSmallIcon) {
682                     b = insertBeforeSuffix(b, "24"); //NOI18N
683
}
684
685                 Image JavaDoc img = null;
686
687                 if (i == null) {
688                     // even for regular icon
689
img = Utilities.loadImage(b, true);
690
691                     if (img != null) {
692                         button.setIcon(new ImageIcon JavaDoc(img));
693                     }
694
695                     i = img;
696                 }
697
698                 Image JavaDoc pImg = Utilities.loadImage(insertBeforeSuffix(b, "_pressed"), true); // NOI18N
699

700                 if (pImg != null) {
701                     button.setPressedIcon(new ImageIcon JavaDoc(pImg));
702                 }
703
704                 Image JavaDoc rImg = Utilities.loadImage(insertBeforeSuffix(b, "_rollover"), true); // NOI18N
705

706                 if (rImg != null) {
707                     button.setRolloverIcon(new ImageIcon JavaDoc(rImg));
708                 }
709
710                 Image JavaDoc dImg = Utilities.loadImage(insertBeforeSuffix(b, "_disabled"), true); // NOI18N
711

712                 if (dImg != null) {
713                     button.setDisabledIcon(new ImageIcon JavaDoc(dImg));
714                 } else if (img != null) {
715                     button.setDisabledIcon(createDisabledIcon(img));
716                 }
717             }
718         }
719
720         static String JavaDoc insertBeforeSuffix(String JavaDoc path, String JavaDoc toInsert) {
721             String JavaDoc withoutSuffix = path;
722             String JavaDoc suffix = ""; // NOI18N
723

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         /** @param changedProperty the name of property that has changed
733         * or null if it is not known
734         */

735         public void updateState(String JavaDoc changedProperty) {
736             // note: "enabled" (== SA.PROP_ENABLED) hardcoded in AbstractAction
737
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             ) { // NOI18N
745
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 JavaDoc tip = findKey(action);
754                 String JavaDoc toolTip = (String JavaDoc) action.getValue(Action.SHORT_DESCRIPTION);
755
756                 if (toolTip == null) {
757                     toolTip = (String JavaDoc) action.getValue(Action.NAME);
758                     toolTip = (toolTip == null) ? "" : cutAmpersand(toolTip);
759                 }
760
761                 if ((tip == null) || tip.equals("")) { // NOI18N
762
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 JavaDoc &&
772                     ((changedProperty == null) || changedProperty.equals(Action.NAME))
773             ) {
774                 button.getAccessibleContext().setAccessibleName((String JavaDoc) action.getValue(Action.NAME));
775             }
776         }
777
778         /** Should textual icons be used when lacking a real icon?
779         * In the default implementation, <code>true</code>.
780         * @return <code>true</code> if so
781         */

782         protected boolean useTextIcons() {
783             return true;
784         }
785     }
786
787     /** Bridge for button and boolean action.
788     */

789     private static class BooleanButtonBridge extends ButtonBridge {
790         public BooleanButtonBridge(AbstractButton JavaDoc button, BooleanStateAction action) {
791             super(button, action);
792         }
793
794         /** @param changedProperty the name of property that has changed
795         * or null if it is not known
796         */

797         public void updateState(String JavaDoc 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     /** Menu item bridge.
807     */

808     private static class MenuBridge extends ButtonBridge {
809         /** behave like menu or popup */
810         private boolean popup;
811
812         /** Constructor.
813         * @param popup pop-up menu
814         */

815         public MenuBridge(JMenuItem JavaDoc item, Action JavaDoc action, boolean popup) {
816             super(item, action);
817             this.popup = popup;
818             
819             if (item instanceof Actions.MenuItem) {
820                 // addnotify/remove notify doens't make sense for menus and
821
// popups.
822
MenuBridge.this.comp.removePropertyChangeListener(listener);
823             }
824             
825             if (popup) {
826                 prepareMargins(item, action);
827             } else {
828                 // #40824 hack
829
item.putClientProperty("menubridgeresizehack", this);
830
831                 // #40824 hack end.
832
}
833         }
834
835         /** @param changedProperty the name of property that has changed
836         * or null if it is not known
837         */

838         public void updateState(String JavaDoc 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 JavaDoc) 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                 ) { // NOI18N
852
updateButtonIcon();
853                 }
854             }
855
856             if ((changedProperty == null) || changedProperty.equals(Action.NAME)) {
857                 Object JavaDoc s = action.getValue(Action.NAME);
858
859                 if (s instanceof String JavaDoc) {
860                     setMenuText(((JMenuItem JavaDoc) comp), (String JavaDoc) s, true);
861
862                     //System.out.println("Menu item: " + s);
863
//System.out.println("Action class: " + action.getClass());
864
}
865             }
866         }
867
868         protected void updateButtonIcon() {
869             Object JavaDoc i = null;
870             Object JavaDoc obj = action.getValue("noIconInMenu"); //NOI18N
871

872             if (Boolean.TRUE.equals(obj)) {
873                 //button.setIcon(nonNullIcon(null));
874
return;
875             }
876
877             if (action instanceof SystemAction) {
878                 SystemAction sa = (SystemAction) action;
879                 i = sa.getIcon(useTextIcons());
880                 button.setIcon((Icon JavaDoc) i);
881
882                 if (i instanceof ImageIcon JavaDoc) {
883                     button.setDisabledIcon(createDisabledIcon(((ImageIcon JavaDoc) i).getImage()));
884                 }
885             } else {
886                 i = action.getValue(Action.SMALL_ICON);
887
888                 if (i instanceof Icon JavaDoc) {
889                     button.setIcon((Icon JavaDoc) i);
890
891                     if (i instanceof ImageIcon JavaDoc) {
892                         button.setDisabledIcon(createDisabledIcon(((ImageIcon JavaDoc) i).getImage()));
893                     }
894                 } else {
895                     //button.setIcon(nonNullIcon(null));
896
}
897             }
898
899             Object JavaDoc base = action.getValue("iconBase"); // NOI18N
900

901             if (base instanceof String JavaDoc) {
902                 String JavaDoc b = (String JavaDoc) base;
903                 Image JavaDoc img = null;
904
905                 if (i == null) {
906                     // even for regular icon
907
img = Utilities.loadImage(b, true);
908
909                     if (img != null) {
910                         button.setIcon(new ImageIcon JavaDoc(img));
911                         button.setDisabledIcon(createDisabledIcon(img));
912                     }
913                 }
914
915                 Image JavaDoc pImg = Utilities.loadImage(insertBeforeSuffix(b, "_pressed"), true); // NOI18N
916

917                 if (pImg != null) {
918                     button.setPressedIcon(new ImageIcon JavaDoc(pImg));
919                 }
920
921                 Image JavaDoc rImg = Utilities.loadImage(insertBeforeSuffix(b, "_rollover"), true); // NOI18N
922

923                 if (rImg != null) {
924                     button.setRolloverIcon(new ImageIcon JavaDoc(rImg));
925                 }
926
927                 Image JavaDoc dImg = Utilities.loadImage(insertBeforeSuffix(b, "_disabled"), true); // NOI18N
928

929                 if (dImg != null) {
930                     button.setDisabledIcon(new ImageIcon JavaDoc(dImg));
931                 } else if (img != null) {
932                     button.setDisabledIcon(createDisabledIcon(img));
933                 }
934             }
935         }
936
937         // Not actually used:
938
protected boolean useTextIcons() {
939             return false;
940         }
941     }
942
943     /** Check menu item bridge.
944     */

945     private static final class CheckMenuBridge extends BooleanButtonBridge {
946         /** is popup or menu */
947         private boolean popup;
948         private boolean hasOwnIcon = false;
949
950         /** Popup menu */
951         public CheckMenuBridge(JCheckBoxMenuItem JavaDoc 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 JavaDoc base = action.getValue("iconBase"); //NOI18N
960
Object JavaDoc 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         /** @param changedProperty the name of property that has changed
972         * or null if it is not known
973         */

974         public void updateState(String JavaDoc changedProperty) {
975             super.updateState(changedProperty);
976
977             if ((changedProperty == null) || !changedProperty.equals(Action.ACCELERATOR_KEY)) {
978                 updateKey((JMenuItem JavaDoc) comp, action);
979             }
980
981             if ((changedProperty == null) || changedProperty.equals(Action.NAME)) {
982                 Object JavaDoc s = action.getValue(Action.NAME);
983
984                 if (s instanceof String JavaDoc) {
985                     setMenuText(((JMenuItem JavaDoc) comp), (String JavaDoc) 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 JavaDoc(Utilities.loadImage("org/openide/resources/actions/gap.gif", true))); // NOI18N
999
}
1000        }
1001
1002        protected boolean useTextIcons() {
1003            return false;
1004        }
1005    }
1006
1007
1008    /** The class that listens to the menu item selections and forwards it to the
1009     * action class via the performAction() method.
1010     */

1011    private static class ISubActionListener implements java.awt.event.ActionListener JavaDoc {
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        /** called when a user clicks on this menu item */
1021        public void actionPerformed(ActionEvent JavaDoc e) {
1022            support.performActionAt(index);
1023        }
1024    }
1025
1026    /** Sub menu bridge 2.
1027    */

1028    private static final class SubMenuBridge extends MenuBridge implements ChangeListener JavaDoc, DynamicMenuContent {
1029        /** model to obtain subitems from */
1030        private SubMenuModel model;
1031        private List JavaDoc<JMenuItem JavaDoc> currentOnes;
1032        private JMenuItem JavaDoc single;
1033        private JMenu JavaDoc multi;
1034        /** Constructor.
1035        */

1036        public SubMenuBridge(JMenuItem JavaDoc one, JMenu JavaDoc more, Action JavaDoc action, SubMenuModel model, boolean popup) {
1037            super(one, action, popup);
1038            single = one;
1039            multi = more;
1040            setMenuText(multi, (String JavaDoc)action.getValue(Action.NAME), popup);
1041            prepareMargins(one, action);
1042            prepareMargins(more, action);
1043            currentOnes = new ArrayList JavaDoc<JMenuItem JavaDoc>();
1044            this.model = model;
1045        }
1046
1047        /** Called when model changes. Regenerates the model.
1048        */

1049        public void stateChanged(ChangeEvent JavaDoc ev) {
1050            //assert EventQueue.isDispatchThread();
1051
if (!EventQueue.isDispatchThread()) {
1052                new IllegalStateException JavaDoc("This must happen in the event thread!").printStackTrace();
1053            }
1054            // change in keys or in submenu model
1055
// checkVisibility();
1056
}
1057        
1058        public void updateState(String JavaDoc changedProperty) {
1059            super.updateState(changedProperty);
1060// checkVisibility();
1061
}
1062
1063        
1064        
1065        public JComponent JavaDoc[] getMenuPresenters() {
1066            return synchMenuPresenters(null);
1067        }
1068        
1069        public JComponent JavaDoc[] synchMenuPresenters(JComponent JavaDoc[] items) {
1070            currentOnes.clear();
1071            int cnt = model.getCount();
1072            
1073            if (cnt == 0) {
1074                updateState(null);
1075                currentOnes.add(single);
1076                // menu disabled
1077
single.setEnabled(false);
1078            } else if (cnt == 1) {
1079                updateState(null);
1080                currentOnes.add(single);
1081                single.setEnabled(action.isEnabled());
1082                // generate without submenu
1083
HelpCtx help = model.getHelpCtx(0);
1084                associateHelp(single, (help == null) ? findHelp(action) : help);
1085            } else {
1086                currentOnes.add(multi);
1087                multi.removeAll();
1088                //TODO
1089
Mnemonics.setLocalizedText(multi, (String JavaDoc)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 JavaDoc label = model.getLabel(i);
1096                
1097                    // MenuShortcut shortcut = support.getMenuShortcut(i);
1098
if (label == null) {
1099                        addSeparator = multi.getItemCount() > 0;
1100                    } else {
1101                        if (addSeparator) {
1102                            multi.addSeparator();
1103                            addSeparator = false;
1104                        }
1105                    
1106                        // if (shortcut == null)
1107
// (Dafe) changed to support mnemonics in item labels
1108
JMenuItem JavaDoc item = new JMenuItem JavaDoc();
1109                        Mnemonics.setLocalizedText(item, label);
1110                    
1111                        // attach the shortcut to the first item
1112
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 JavaDoc[currentOnes.size()]);
1128            
1129        }
1130
1131        private void associateHelp(JComponent JavaDoc 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    //
1140
//
1141
// The presenter classes
1142
//
1143
//
1144

1145    /**
1146     * Extension of Swing menu item with connection to
1147     * system actions.
1148     */

1149    public static class MenuItem extends javax.swing.JMenuItem JavaDoc implements DynamicMenuContent {
1150        static final long serialVersionUID = -21757335363267194L;
1151        private Actions.Bridge bridge;
1152        /** Constructs a new menu item with the specified label
1153        * and no keyboard shortcut and connects it to the given SystemAction.
1154        * @param aAction the action to which this menu item should be connected
1155        * @param useMnemonic if true, the menu try to find mnemonic in action label
1156        */

1157        public MenuItem(SystemAction aAction, boolean useMnemonic) {
1158            Actions.connect(this, aAction, !useMnemonic);
1159        }
1160
1161        /** Constructs a new menu item with the specified label
1162        * and no keyboard shortcut and connects it to the given SystemAction.
1163        * @param aAction the action to which this menu item should be connected
1164        * @param useMnemonic if true, the menu try to find mnemonic in action label
1165        */

1166        public MenuItem(Action JavaDoc 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 JavaDoc[] synchMenuPresenters(JComponent JavaDoc[] items) {
1175            if (bridge != null) {
1176                bridge.updateState(null);
1177            }
1178            return getMenuPresenters();
1179        }
1180
1181        public JComponent JavaDoc[] getMenuPresenters() {
1182            return new JComponent JavaDoc[] {this};
1183        }
1184        
1185    }
1186
1187    /** CheckboxMenuItem extends the java.awt.CheckboxMenuItem and adds
1188    * a connection to boolean state actions. The ActCheckboxMenuItem
1189    * processes the ItemEvents itself and calls the action.seBooleanState() method.
1190    * It also tracks the enabled and boolean state of the action and reflects it
1191    * as its visual enabled/check state.
1192    *
1193    * @author Ian Formanek, Jan Jancura
1194    */

1195    public static class CheckboxMenuItem extends javax.swing.JCheckBoxMenuItem JavaDoc {
1196        static final long serialVersionUID = 6190621106981774043L;
1197
1198        /** Constructs a new ActCheckboxMenuItem with the specified label
1199        * and connects it to the given BooleanStateAction.
1200        * @param aAction the action to which this menu item should be connected
1201        * @param useMnemonic if true, the menu try to find mnemonic in action label
1202        */

1203        public CheckboxMenuItem(BooleanStateAction aAction, boolean useMnemonic) {
1204            Actions.connect(this, aAction, !useMnemonic);
1205        }
1206    }
1207
1208    /** Component shown in toolbar, representing an action.
1209    * @deprecated extends deprecated ToolbarButton
1210    */

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 JavaDoc aAction) {
1220            super(null);
1221            Actions.connect(this, aAction);
1222        }
1223
1224        /**
1225         * Gets the maximum size of this component.
1226         * @return A dimension object indicating this component's maximum size.
1227         * @see #getMinimumSize
1228         * @see #getPreferredSize
1229         * @see java.awt.LayoutManager
1230         */

1231        public Dimension JavaDoc getMaximumSize() {
1232            return this.getPreferredSize();
1233        }
1234
1235        public Dimension JavaDoc getMinimumSize() {
1236            return this.getPreferredSize();
1237        }
1238    }
1239
1240    /** The Component for BooleeanState action that is to be shown
1241    * in a toolbar.
1242    *
1243    * @deprecated extends deprecated ToolbarToggleButton
1244    */

1245    public static class ToolbarToggleButton extends org.openide.awt.ToolbarToggleButton {
1246        static final long serialVersionUID = -4783163952526348942L;
1247
1248        /** Constructs a new ActToolbarToggleButton for specified action */
1249        public ToolbarToggleButton(BooleanStateAction aAction) {
1250            super(null, false);
1251            Actions.connect(this, aAction);
1252        }
1253
1254        /**
1255         * Gets the maximum size of this component.
1256         * @return A dimension object indicating this component's maximum size.
1257         * @see #getMinimumSize
1258         * @see #getPreferredSize
1259         * @see java.awt.LayoutManager
1260         */

1261        public Dimension JavaDoc getMaximumSize() {
1262            return this.getPreferredSize();
1263        }
1264
1265        public Dimension JavaDoc getMinimumSize() {
1266            return this.getPreferredSize();
1267        }
1268    }
1269    
1270
1271    /** SubMenu provides easy way of displaying submenu items based on
1272    * SubMenuModel.
1273    */

1274    public static class SubMenu extends JMenuPlus implements DynamicMenuContent {
1275        static final long serialVersionUID = -4446966671302959091L;
1276
1277        private SubMenuBridge bridge;
1278
1279        /** Constructs a new ActMenuItem with the specified label
1280        * and no keyboard shortcut and connects it to the given SystemAction.
1281        * No icon is used by default.
1282        * @param aAction the action to which this menu item should be connected
1283        * @param model the support for the menu items
1284        */

1285        public SubMenu(SystemAction aAction, SubMenuModel model) {
1286            this(aAction, model, true);
1287        }
1288
1289        /** Constructs a new ActMenuItem with the specified label
1290        * and no keyboard shortcut and connects it to the given SystemAction.
1291        * No icon is used by default.
1292        * @param aAction the action to which this menu item should be connected
1293        * @param model the support for the menu items
1294        * @param popup whether this is a popup menu
1295        */

1296        public SubMenu(SystemAction aAction, SubMenuModel model, boolean popup) {
1297            this((Action JavaDoc) aAction, model, popup);
1298        }
1299
1300        /** Constructs a new ActMenuItem with the specified label
1301        * and no keyboard shortcut and connects it to the given SystemAction.
1302        * No icon is used by default.
1303        * @param aAction the action to which this menu item should be connected
1304        * @param model the support for the menu items
1305        * @param popup whether this is a popup menu
1306        */

1307        public SubMenu(Action JavaDoc aAction, SubMenuModel model, boolean popup) {
1308            bridge = new SubMenuBridge(new JMenuItem JavaDoc(), this, aAction, model, popup);
1309
1310            // set at least the name to have reasonable bounds
1311
bridge.updateState(Action.NAME);
1312        }
1313        
1314        public JComponent JavaDoc[] getMenuPresenters() {
1315            return bridge.getMenuPresenters();
1316        }
1317        
1318        public JComponent JavaDoc[] synchMenuPresenters(JComponent JavaDoc[] items) {
1319            return bridge.synchMenuPresenters(items);
1320        }
1321        
1322    }
1323
1324    /**
1325     * SPI for supplying alternative implementation of connection between actions and presenters.
1326     * The implementations
1327     * of this interface are being looked up in the default lookup.
1328     * If there is no implemenation in the lookup the default implementation
1329     * is used.
1330     * @see Lookup#getDefault()
1331     * @since org.openide.awt 6.9
1332     */

1333    public interface ButtonActionConnector {
1334        /**
1335         * Connects the action to the supplied button.
1336         * @return true if the connection was successful and no
1337         * further actions are needed. If false is returned the
1338         * default connect implementation is called
1339         */

1340        boolean connect(AbstractButton JavaDoc button, Action JavaDoc action);
1341        /**
1342         * Connects the action to the supplied JMenuItem.
1343         * @return true if the connection was successful and no
1344         * further actions are needed. If false is returned the
1345         * default connect implementation is called
1346         */

1347        boolean connect(JMenuItem JavaDoc item, Action JavaDoc action, boolean popup);
1348    }
1349
1350    private static class DisabledButtonFilter extends RGBImageFilter JavaDoc {
1351        DisabledButtonFilter() {
1352            canFilterIndexColorModel = true;
1353        }
1354
1355        public int filterRGB(int x, int y, int rgb) {
1356            // Reduce the color bandwidth in quarter (>> 2) and Shift 0x88.
1357
return (rgb & 0xff000000) + 0x888888 + ((((rgb >> 16) & 0xff) >> 2) << 16) +
1358            ((((rgb >> 8) & 0xff) >> 2) << 8) + (((rgb) & 0xff) >> 2);
1359        }
1360
1361        // override the superclass behaviour to not pollute
1362
// the heap with useless properties strings. Saves tens of KBs
1363
public void setProperties(Hashtable JavaDoc props) {
1364            props = (Hashtable JavaDoc) props.clone();
1365            consumer.setProperties(props);
1366        }
1367    }
1368}
1369
Popular Tags