KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > action > ActionContributionItem


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jface.action;
12
13 import org.eclipse.jface.action.ExternalActionManager.IBindingManagerCallback;
14 import org.eclipse.jface.bindings.Trigger;
15 import org.eclipse.jface.bindings.TriggerSequence;
16 import org.eclipse.jface.bindings.keys.IKeyLookup;
17 import org.eclipse.jface.bindings.keys.KeyLookupFactory;
18 import org.eclipse.jface.bindings.keys.KeyStroke;
19 import org.eclipse.jface.resource.ImageDescriptor;
20 import org.eclipse.jface.resource.JFaceResources;
21 import org.eclipse.jface.resource.LocalResourceManager;
22 import org.eclipse.jface.resource.ResourceManager;
23 import org.eclipse.jface.util.IPropertyChangeListener;
24 import org.eclipse.jface.util.Policy;
25 import org.eclipse.jface.util.PropertyChangeEvent;
26 import org.eclipse.swt.SWT;
27 import org.eclipse.swt.graphics.GC;
28 import org.eclipse.swt.graphics.Point;
29 import org.eclipse.swt.graphics.Rectangle;
30 import org.eclipse.swt.widgets.Button;
31 import org.eclipse.swt.widgets.Composite;
32 import org.eclipse.swt.widgets.Display;
33 import org.eclipse.swt.widgets.Event;
34 import org.eclipse.swt.widgets.Item;
35 import org.eclipse.swt.widgets.Listener;
36 import org.eclipse.swt.widgets.Menu;
37 import org.eclipse.swt.widgets.MenuItem;
38 import org.eclipse.swt.widgets.ToolBar;
39 import org.eclipse.swt.widgets.ToolItem;
40 import org.eclipse.swt.widgets.Widget;
41
42 /**
43  * A contribution item which delegates to an action.
44  * <p>
45  * This class may be instantiated; it is not intended to be subclassed.
46  * </p>
47  */

48 public class ActionContributionItem extends ContributionItem {
49
50     /**
51      * Mode bit: Show text on tool items, even if an image is present. If this
52      * mode bit is not set, text is only shown on tool items if there is no
53      * image present.
54      *
55      * @since 3.0
56      */

57     public static int MODE_FORCE_TEXT = 1;
58
59     /** a string inserted in the middle of text that has been shortened */
60     private static final String JavaDoc ellipsis = "..."; //$NON-NLS-1$
61

62     private static boolean USE_COLOR_ICONS = true;
63
64     /**
65      * Returns whether color icons should be used in toolbars.
66      *
67      * @return <code>true</code> if color icons should be used in toolbars,
68      * <code>false</code> otherwise
69      */

70     public static boolean getUseColorIconsInToolbars() {
71         return USE_COLOR_ICONS;
72     }
73
74     /**
75      * Sets whether color icons should be used in toolbars.
76      *
77      * @param useColorIcons
78      * <code>true</code> if color icons should be used in toolbars,
79      * <code>false</code> otherwise
80      */

81     public static void setUseColorIconsInToolbars(boolean useColorIcons) {
82         USE_COLOR_ICONS = useColorIcons;
83     }
84
85     /**
86      * The presentation mode.
87      */

88     private int mode = 0;
89
90     /**
91      * The action.
92      */

93     private IAction action;
94
95     /**
96      * The listener for changes to the text of the action contributed by an
97      * external source.
98      */

99     private final IPropertyChangeListener actionTextListener = new IPropertyChangeListener() {
100
101         /**
102          * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
103          */

104         public void propertyChange(PropertyChangeEvent event) {
105             update(event.getProperty());
106         }
107     };
108
109     /**
110      * Remembers all images in use by this contribution item
111      */

112     private LocalResourceManager imageManager;
113
114     /**
115      * Listener for SWT button widget events.
116      */

117     private Listener buttonListener;
118
119     /**
120      * Listener for SWT menu item widget events.
121      */

122     private Listener menuItemListener;
123
124     /**
125      * Listener for action property change notifications.
126      */

127     private final IPropertyChangeListener propertyListener = new IPropertyChangeListener() {
128         public void propertyChange(PropertyChangeEvent event) {
129             actionPropertyChange(event);
130         }
131     };
132
133     /**
134      * Listener for SWT tool item widget events.
135      */

136     private Listener toolItemListener;
137
138     /**
139      * The widget created for this item; <code>null</code> before creation and
140      * after disposal.
141      */

142     private Widget widget = null;
143
144     /**
145      * Creates a new contribution item from the given action. The id of the
146      * action is used as the id of the item.
147      *
148      * @param action
149      * the action
150      */

151     public ActionContributionItem(IAction action) {
152         super(action.getId());
153         this.action = action;
154     }
155
156     /**
157      * Handles a property change event on the action (forwarded by nested
158      * listener).
159      */

160     private void actionPropertyChange(final PropertyChangeEvent e) {
161         // This code should be removed. Avoid using free asyncExec
162

163         if (isVisible() && widget != null) {
164             Display display = widget.getDisplay();
165             if (display.getThread() == Thread.currentThread()) {
166                 update(e.getProperty());
167             } else {
168                 display.asyncExec(new Runnable JavaDoc() {
169                     public void run() {
170                         update(e.getProperty());
171                     }
172                 });
173             }
174
175         }
176     }
177
178     /**
179      * Compares this action contribution item with another object. Two action
180      * contribution items are equal if they refer to the identical Action.
181      */

182     public boolean equals(Object JavaDoc o) {
183         if (!(o instanceof ActionContributionItem)) {
184             return false;
185         }
186         return action.equals(((ActionContributionItem) o).action);
187     }
188
189     /**
190      * The <code>ActionContributionItem</code> implementation of this
191      * <code>IContributionItem</code> method creates an SWT
192      * <code>Button</code> for the action using the action's style. If the
193      * action's checked property has been set, the button is created and primed
194      * to the value of the checked property.
195      */

196     public void fill(Composite parent) {
197         if (widget == null && parent != null) {
198             int flags = SWT.PUSH;
199             if (action != null) {
200                 if (action.getStyle() == IAction.AS_CHECK_BOX) {
201                     flags = SWT.TOGGLE;
202                 }
203                 if (action.getStyle() == IAction.AS_RADIO_BUTTON) {
204                     flags = SWT.RADIO;
205                 }
206             }
207
208             Button b = new Button(parent, flags);
209             b.setData(this);
210             b.addListener(SWT.Dispose, getButtonListener());
211             // Don't hook a dispose listener on the parent
212
b.addListener(SWT.Selection, getButtonListener());
213             if (action.getHelpListener() != null) {
214                 b.addHelpListener(action.getHelpListener());
215             }
216             widget = b;
217
218             update(null);
219
220             // Attach some extra listeners.
221
action.addPropertyChangeListener(propertyListener);
222             if (action != null) {
223                 String JavaDoc commandId = action.getActionDefinitionId();
224                 ExternalActionManager.ICallback callback = ExternalActionManager
225                         .getInstance().getCallback();
226
227                 if ((callback != null) && (commandId != null)) {
228                     callback.addPropertyChangeListener(commandId,
229                             actionTextListener);
230                 }
231             }
232         }
233     }
234
235     /**
236      * The <code>ActionContributionItem</code> implementation of this
237      * <code>IContributionItem</code> method creates an SWT
238      * <code>MenuItem</code> for the action using the action's style. If the
239      * action's checked property has been set, a button is created and primed to
240      * the value of the checked property. If the action's menu creator property
241      * has been set, a cascading submenu is created.
242      */

243     public void fill(Menu parent, int index) {
244         if (widget == null && parent != null) {
245             Menu subMenu = null;
246             int flags = SWT.PUSH;
247             if (action != null) {
248                 int style = action.getStyle();
249                 if (style == IAction.AS_CHECK_BOX) {
250                     flags = SWT.CHECK;
251                 } else if (style == IAction.AS_RADIO_BUTTON) {
252                     flags = SWT.RADIO;
253                 } else if (style == IAction.AS_DROP_DOWN_MENU) {
254                     IMenuCreator mc = action.getMenuCreator();
255                     if (mc != null) {
256                         subMenu = mc.getMenu(parent);
257                         flags = SWT.CASCADE;
258                     }
259                 }
260             }
261
262             MenuItem mi = null;
263             if (index >= 0) {
264                 mi = new MenuItem(parent, flags, index);
265             } else {
266                 mi = new MenuItem(parent, flags);
267             }
268             widget = mi;
269
270             mi.setData(this);
271             mi.addListener(SWT.Dispose, getMenuItemListener());
272             mi.addListener(SWT.Selection, getMenuItemListener());
273             if (action.getHelpListener() != null) {
274                 mi.addHelpListener(action.getHelpListener());
275             }
276
277             if (subMenu != null) {
278                 mi.setMenu(subMenu);
279             }
280
281             update(null);
282
283             // Attach some extra listeners.
284
action.addPropertyChangeListener(propertyListener);
285             if (action != null) {
286                 String JavaDoc commandId = action.getActionDefinitionId();
287                 ExternalActionManager.ICallback callback = ExternalActionManager
288                         .getInstance().getCallback();
289
290                 if ((callback != null) && (commandId != null)) {
291                     callback.addPropertyChangeListener(commandId,
292                             actionTextListener);
293                 }
294             }
295         }
296     }
297
298     /**
299      * The <code>ActionContributionItem</code> implementation of this ,
300      * <code>IContributionItem</code> method creates an SWT
301      * <code>ToolItem</code> for the action using the action's style. If the
302      * action's checked property has been set, a button is created and primed to
303      * the value of the checked property. If the action's menu creator property
304      * has been set, a drop-down tool item is created.
305      */

306     public void fill(ToolBar parent, int index) {
307         if (widget == null && parent != null) {
308             int flags = SWT.PUSH;
309             if (action != null) {
310                 int style = action.getStyle();
311                 if (style == IAction.AS_CHECK_BOX) {
312                     flags = SWT.CHECK;
313                 } else if (style == IAction.AS_RADIO_BUTTON) {
314                     flags = SWT.RADIO;
315                 } else if (style == IAction.AS_DROP_DOWN_MENU) {
316                     flags = SWT.DROP_DOWN;
317                 }
318             }
319
320             ToolItem ti = null;
321             if (index >= 0) {
322                 ti = new ToolItem(parent, flags, index);
323             } else {
324                 ti = new ToolItem(parent, flags);
325             }
326             ti.setData(this);
327             ti.addListener(SWT.Selection, getToolItemListener());
328             ti.addListener(SWT.Dispose, getToolItemListener());
329
330             widget = ti;
331
332             update(null);
333
334             // Attach some extra listeners.
335
action.addPropertyChangeListener(propertyListener);
336             if (action != null) {
337                 String JavaDoc commandId = action.getActionDefinitionId();
338                 ExternalActionManager.ICallback callback = ExternalActionManager
339                         .getInstance().getCallback();
340
341                 if ((callback != null) && (commandId != null)) {
342                     callback.addPropertyChangeListener(commandId,
343                             actionTextListener);
344                 }
345             }
346         }
347     }
348
349     /**
350      * Returns the action associated with this contribution item.
351      *
352      * @return the action
353      */

354     public IAction getAction() {
355         return action;
356     }
357
358     /**
359      * Returns the listener for SWT button widget events.
360      *
361      * @return a listener for button events
362      */

363     private Listener getButtonListener() {
364         if (buttonListener == null) {
365             buttonListener = new Listener() {
366                 public void handleEvent(Event event) {
367                     switch (event.type) {
368                     case SWT.Dispose:
369                         handleWidgetDispose(event);
370                         break;
371                     case SWT.Selection:
372                         Widget ew = event.widget;
373                         if (ew != null) {
374                             handleWidgetSelection(event, ((Button) ew)
375                                     .getSelection());
376                         }
377                         break;
378                     }
379                 }
380             };
381         }
382         return buttonListener;
383     }
384
385     /**
386      * Returns the listener for SWT menu item widget events.
387      *
388      * @return a listener for menu item events
389      */

390     private Listener getMenuItemListener() {
391         if (menuItemListener == null) {
392             menuItemListener = new Listener() {
393                 public void handleEvent(Event event) {
394                     switch (event.type) {
395                     case SWT.Dispose:
396                         handleWidgetDispose(event);
397                         break;
398                     case SWT.Selection:
399                         Widget ew = event.widget;
400                         if (ew != null) {
401                             handleWidgetSelection(event, ((MenuItem) ew)
402                                     .getSelection());
403                         }
404                         break;
405                     }
406                 }
407             };
408         }
409         return menuItemListener;
410     }
411
412     /**
413      * Returns the presentation mode, which is the bitwise-or of the
414      * <code>MODE_*</code> constants. The default mode setting is 0, meaning
415      * that for menu items, both text and image are shown (if present), but for
416      * tool items, the text is shown only if there is no image.
417      *
418      * @return the presentation mode settings
419      *
420      * @since 3.0
421      */

422     public int getMode() {
423         return mode;
424     }
425
426     /**
427      * Returns the listener for SWT tool item widget events.
428      *
429      * @return a listener for tool item events
430      */

431     private Listener getToolItemListener() {
432         if (toolItemListener == null) {
433             toolItemListener = new Listener() {
434                 public void handleEvent(Event event) {
435                     switch (event.type) {
436                     case SWT.Dispose:
437                         handleWidgetDispose(event);
438                         break;
439                     case SWT.Selection:
440                         Widget ew = event.widget;
441                         if (ew != null) {
442                             handleWidgetSelection(event, ((ToolItem) ew)
443                                     .getSelection());
444                         }
445                         break;
446                     }
447                 }
448             };
449         }
450         return toolItemListener;
451     }
452
453     /**
454      * Handles a widget dispose event for the widget corresponding to this item.
455      */

456     private void handleWidgetDispose(Event e) {
457         // Check if our widget is the one being disposed.
458
if (e.widget == widget) {
459             // Dispose of the menu creator.
460
if (action.getStyle() == IAction.AS_DROP_DOWN_MENU) {
461                 IMenuCreator mc = action.getMenuCreator();
462                 if (mc != null) {
463                     mc.dispose();
464                 }
465             }
466
467             // Unhook all of the listeners.
468
action.removePropertyChangeListener(propertyListener);
469             if (action != null) {
470                 String JavaDoc commandId = action.getActionDefinitionId();
471                 ExternalActionManager.ICallback callback = ExternalActionManager
472                         .getInstance().getCallback();
473
474                 if ((callback != null) && (commandId != null)) {
475                     callback.removePropertyChangeListener(commandId,
476                             actionTextListener);
477                 }
478             }
479
480             // Clear the widget field.
481
widget = null;
482
483             disposeOldImages();
484         }
485     }
486
487     /**
488      * Handles a widget selection event.
489      */

490     private void handleWidgetSelection(Event e, boolean selection) {
491
492         Widget item = e.widget;
493         if (item != null) {
494             int style = item.getStyle();
495
496             if ((style & (SWT.TOGGLE | SWT.CHECK)) != 0) {
497                 if (action.getStyle() == IAction.AS_CHECK_BOX) {
498                     action.setChecked(selection);
499                 }
500             } else if ((style & SWT.RADIO) != 0) {
501                 if (action.getStyle() == IAction.AS_RADIO_BUTTON) {
502                     action.setChecked(selection);
503                 }
504             } else if ((style & SWT.DROP_DOWN) != 0) {
505                 if (e.detail == 4) { // on drop-down button
506
if (action.getStyle() == IAction.AS_DROP_DOWN_MENU) {
507                         IMenuCreator mc = action.getMenuCreator();
508                         ToolItem ti = (ToolItem) item;
509                         // we create the menu as a sub-menu of "dummy" so that
510
// we can use
511
// it in a cascading menu too.
512
// If created on a SWT control we would get an SWT
513
// error...
514
// Menu dummy= new Menu(ti.getParent());
515
// Menu m= mc.getMenu(dummy);
516
// dummy.dispose();
517
if (mc != null) {
518                             Menu m = mc.getMenu(ti.getParent());
519                             if (m != null) {
520                                 // position the menu below the drop down item
521
Rectangle b = ti.getBounds();
522                                 Point p = ti.getParent().toDisplay(
523                                         new Point(b.x, b.y + b.height));
524                                 m.setLocation(p.x, p.y); // waiting for SWT
525
// 0.42
526
m.setVisible(true);
527                                 return; // we don't fire the action
528
}
529                         }
530                     }
531                 }
532             }
533
534             // Ensure action is enabled first.
535
// See 1GAN3M6: ITPUI:WINNT - Any IAction in the workbench can be
536
// executed while disabled.
537
if (action.isEnabled()) {
538                 boolean trace = Policy.TRACE_ACTIONS;
539
540                 long ms = 0L;
541                 if (trace) {
542                     ms = System.currentTimeMillis();
543                     System.out.println("Running action: " + action.getText()); //$NON-NLS-1$
544
}
545
546                 action.runWithEvent(e);
547
548                 if (trace) {
549                     System.out.println((System.currentTimeMillis() - ms)
550                             + " ms to run action: " + action.getText()); //$NON-NLS-1$
551
}
552             }
553         }
554     }
555
556     /*
557      * (non-Javadoc) Method declared on Object.
558      */

559     public int hashCode() {
560         return action.hashCode();
561     }
562
563     /**
564      * Returns whether the given action has any images.
565      *
566      * @param actionToCheck
567      * the action
568      * @return <code>true</code> if the action has any images,
569      * <code>false</code> if not
570      */

571     private boolean hasImages(IAction actionToCheck) {
572         return actionToCheck.getImageDescriptor() != null
573                 || actionToCheck.getHoverImageDescriptor() != null
574                 || actionToCheck.getDisabledImageDescriptor() != null;
575     }
576
577     /**
578      * Returns whether the command corresponding to this action is active.
579      */

580     private boolean isCommandActive() {
581         IAction actionToCheck = getAction();
582
583         if (actionToCheck != null) {
584             String JavaDoc commandId = actionToCheck.getActionDefinitionId();
585             ExternalActionManager.ICallback callback = ExternalActionManager
586                     .getInstance().getCallback();
587
588             if (callback != null) {
589                 return callback.isActive(commandId);
590             }
591         }
592         return true;
593     }
594
595     /**
596      * The action item implementation of this <code>IContributionItem</code>
597      * method returns <code>true</code> for menu items and <code>false</code>
598      * for everything else.
599      */

600     public boolean isDynamic() {
601         if (widget instanceof MenuItem) {
602             // Optimization. Only recreate the item is the check or radio style
603
// has changed.
604
boolean itemIsCheck = (widget.getStyle() & SWT.CHECK) != 0;
605             boolean actionIsCheck = getAction() != null
606                     && getAction().getStyle() == IAction.AS_CHECK_BOX;
607             boolean itemIsRadio = (widget.getStyle() & SWT.RADIO) != 0;
608             boolean actionIsRadio = getAction() != null
609                     && getAction().getStyle() == IAction.AS_RADIO_BUTTON;
610             return (itemIsCheck != actionIsCheck)
611                     || (itemIsRadio != actionIsRadio);
612         }
613         return false;
614     }
615
616     /*
617      * (non-Javadoc) Method declared on IContributionItem.
618      */

619     public boolean isEnabled() {
620         return action != null && action.isEnabled();
621     }
622
623     /**
624      * Returns <code>true</code> if this item is allowed to enable,
625      * <code>false</code> otherwise.
626      *
627      * @return if this item is allowed to be enabled
628      * @since 2.0
629      */

630     protected boolean isEnabledAllowed() {
631         if (getParent() == null) {
632             return true;
633         }
634         Boolean JavaDoc value = getParent().getOverrides().getEnabled(this);
635         return (value == null) ? true : value.booleanValue();
636     }
637
638     /**
639      * The <code>ActionContributionItem</code> implementation of this
640      * <code>ContributionItem</code> method extends the super implementation
641      * by also checking whether the command corresponding to this action is
642      * active.
643      */

644     public boolean isVisible() {
645         return super.isVisible() && isCommandActive();
646     }
647
648     /**
649      * Sets the presentation mode, which is the bitwise-or of the
650      * <code>MODE_*</code> constants.
651      *
652      * @param mode
653      * the presentation mode settings
654      *
655      * @since 3.0
656      */

657     public void setMode(int mode) {
658         this.mode = mode;
659         update();
660     }
661
662     /**
663      * The action item implementation of this <code>IContributionItem</code>
664      * method calls <code>update(null)</code>.
665      */

666     public final void update() {
667         update(null);
668     }
669
670     /**
671      * Synchronizes the UI with the given property.
672      *
673      * @param propertyName
674      * the name of the property, or <code>null</code> meaning all
675      * applicable properties
676      */

677     public void update(String JavaDoc propertyName) {
678         if (widget != null) {
679             // determine what to do
680
boolean textChanged = propertyName == null
681                     || propertyName.equals(IAction.TEXT);
682             boolean imageChanged = propertyName == null
683                     || propertyName.equals(IAction.IMAGE);
684             boolean tooltipTextChanged = propertyName == null
685                     || propertyName.equals(IAction.TOOL_TIP_TEXT);
686             boolean enableStateChanged = propertyName == null
687                     || propertyName.equals(IAction.ENABLED)
688                     || propertyName
689                             .equals(IContributionManagerOverrides.P_ENABLED);
690             boolean checkChanged = (action.getStyle() == IAction.AS_CHECK_BOX || action
691                     .getStyle() == IAction.AS_RADIO_BUTTON)
692                     && (propertyName == null || propertyName
693                             .equals(IAction.CHECKED));
694
695             if (widget instanceof ToolItem) {
696                 ToolItem ti = (ToolItem) widget;
697                 String JavaDoc text = action.getText();
698                 // the set text is shown only if there is no image or if forced
699
// by MODE_FORCE_TEXT
700
boolean showText = text != null
701                         && ((getMode() & MODE_FORCE_TEXT) != 0 || !hasImages(action));
702
703                 // only do the trimming if the text will be used
704
if (showText && text != null) {
705                     text = Action.removeAcceleratorText(text);
706                     text = Action.removeMnemonics(text);
707                 }
708
709                 if (textChanged) {
710                     String JavaDoc textToSet = showText ? text : ""; //$NON-NLS-1$
711
boolean rightStyle = (ti.getParent().getStyle() & SWT.RIGHT) != 0;
712                     if (rightStyle || !ti.getText().equals(textToSet)) {
713                         // In addition to being required to update the text if
714
// it
715
// gets nulled out in the action, this is also a
716
// workaround
717
// for bug 50151: Using SWT.RIGHT on a ToolBar leaves
718
// blank space
719
ti.setText(textToSet);
720                     }
721                 }
722
723                 if (imageChanged) {
724                     // only substitute a missing image if it has no text
725
updateImages(!showText);
726                 }
727
728                 if (tooltipTextChanged || textChanged) {
729                     String JavaDoc toolTip = action.getToolTipText();
730                     if ((toolTip == null) || (toolTip.length() == 0)) {
731                         toolTip = text;
732                     }
733                     
734                     ExternalActionManager.ICallback callback = ExternalActionManager
735                             .getInstance().getCallback();
736                     String JavaDoc commandId = action.getActionDefinitionId();
737                     if ((callback != null) && (commandId != null) && (toolTip != null)) {
738                         String JavaDoc acceleratorText = callback.getAcceleratorText(commandId);
739                         if (acceleratorText != null && acceleratorText.length() != 0) {
740                             toolTip = JFaceResources.format(
741                                     "Toolbar_Tooltip_Accelerator", //$NON-NLS-1$
742
new Object JavaDoc[] { toolTip, acceleratorText });
743                         }
744                     }
745
746                     // if the text is showing, then only set the tooltip if
747
// different
748
if (!showText || toolTip != null && !toolTip.equals(text)) {
749                         ti.setToolTipText(toolTip);
750                     } else {
751                         ti.setToolTipText(null);
752                     }
753                 }
754
755                 if (enableStateChanged) {
756                     boolean shouldBeEnabled = action.isEnabled()
757                             && isEnabledAllowed();
758
759                     if (ti.getEnabled() != shouldBeEnabled) {
760                         ti.setEnabled(shouldBeEnabled);
761                     }
762                 }
763
764                 if (checkChanged) {
765                     boolean bv = action.isChecked();
766
767                     if (ti.getSelection() != bv) {
768                         ti.setSelection(bv);
769                     }
770                 }
771                 return;
772             }
773
774             if (widget instanceof MenuItem) {
775                 MenuItem mi = (MenuItem) widget;
776
777                 if (textChanged) {
778                     int accelerator = 0;
779                     String JavaDoc acceleratorText = null;
780                     IAction updatedAction = getAction();
781                     String JavaDoc text = null;
782                     accelerator = updatedAction.getAccelerator();
783                     ExternalActionManager.ICallback callback = ExternalActionManager
784                             .getInstance().getCallback();
785
786                     // Block accelerators that are already in use.
787
if ((accelerator != 0) && (callback != null)
788                             && (callback.isAcceleratorInUse(accelerator))) {
789                         accelerator = 0;
790                     }
791
792                     /*
793                      * Process accelerators on GTK in a special way to avoid Bug
794                      * 42009. We will override the native input method by
795                      * allowing these reserved accelerators to be placed on the
796                      * menu. We will only do this for "Ctrl+Shift+[0-9A-FU]".
797                      */

798                     final String JavaDoc commandId = updatedAction
799                             .getActionDefinitionId();
800                     if (("gtk".equals(SWT.getPlatform())) && (callback instanceof IBindingManagerCallback) //$NON-NLS-1$
801
&& (commandId != null)) {
802                         final IBindingManagerCallback bindingManagerCallback = (IBindingManagerCallback) callback;
803                         final IKeyLookup lookup = KeyLookupFactory.getDefault();
804                         final TriggerSequence[] triggerSequences = bindingManagerCallback
805                                 .getActiveBindingsFor(commandId);
806                         for (int i = 0; i < triggerSequences.length; i++) {
807                             final TriggerSequence triggerSequence = triggerSequences[i];
808                             final Trigger[] triggers = triggerSequence
809                                     .getTriggers();
810                             if (triggers.length == 1) {
811                                 final Trigger trigger = triggers[0];
812                                 if (trigger instanceof KeyStroke) {
813                                     final KeyStroke currentKeyStroke = (KeyStroke) trigger;
814                                     final int currentNaturalKey = currentKeyStroke
815                                             .getNaturalKey();
816                                     if ((currentKeyStroke.getModifierKeys() == (lookup
817                                             .getCtrl() | lookup.getShift()))
818                                             && ((currentNaturalKey >= '0' && currentNaturalKey <= '9')
819                                                     || (currentNaturalKey >= 'A' && currentNaturalKey <= 'F') || (currentNaturalKey == 'U'))) {
820                                         accelerator = currentKeyStroke
821                                                 .getModifierKeys()
822                                                 | currentNaturalKey;
823                                         acceleratorText = triggerSequence
824                                                 .format();
825                                         break;
826                                     }
827                                 }
828                             }
829                         }
830                     }
831
832                     if (accelerator == 0) {
833                         if ((callback != null) && (commandId != null)) {
834                             acceleratorText = callback
835                                     .getAcceleratorText(commandId);
836                         }
837                     }
838
839                     IContributionManagerOverrides overrides = null;
840
841                     if (getParent() != null) {
842                         overrides = getParent().getOverrides();
843                     }
844
845                     if (overrides != null) {
846                         text = getParent().getOverrides().getText(this);
847                     }
848
849                     mi.setAccelerator(accelerator);
850
851                     if (text == null) {
852                         text = updatedAction.getText();
853                     }
854
855                     if (text != null && acceleratorText == null) {
856                         // use extracted accelerator text in case accelerator cannot be fully represented in one int (e.g. multi-stroke keys)
857
acceleratorText = LegacyActionTools.extractAcceleratorText(text);
858                         if (acceleratorText == null && accelerator != 0) {
859                             acceleratorText= Action.convertAccelerator(accelerator);
860                         }
861                     }
862
863                     if (text == null) {
864                         text = ""; //$NON-NLS-1$
865
} else {
866                         text = Action.removeAcceleratorText(text);
867                     }
868
869                     if (acceleratorText == null) {
870                         mi.setText(text);
871                     } else {
872                         mi.setText(text + '\t' + acceleratorText);
873                     }
874                 }
875
876                 if (imageChanged) {
877                     updateImages(false);
878                 }
879
880                 if (enableStateChanged) {
881                     boolean shouldBeEnabled = action.isEnabled()
882                             && isEnabledAllowed();
883
884                     if (mi.getEnabled() != shouldBeEnabled) {
885                         mi.setEnabled(shouldBeEnabled);
886                     }
887                 }
888
889                 if (checkChanged) {
890                     boolean bv = action.isChecked();
891
892                     if (mi.getSelection() != bv) {
893                         mi.setSelection(bv);
894                     }
895                 }
896
897                 return;
898             }
899
900             if (widget instanceof Button) {
901                 Button button = (Button) widget;
902
903                 if (imageChanged && updateImages(false)) {
904                     textChanged = false; // don't update text if it has an
905
// image
906
}
907
908                 if (textChanged) {
909                     String JavaDoc text = action.getText();
910                     if (text == null) {
911                         text = ""; //$NON-NLS-1$
912
} else {
913                         text = Action.removeAcceleratorText(text);
914                     }
915                     button.setText(text);
916                 }
917
918                 if (tooltipTextChanged) {
919                     button.setToolTipText(action.getToolTipText());
920                 }
921
922                 if (enableStateChanged) {
923                     boolean shouldBeEnabled = action.isEnabled()
924                             && isEnabledAllowed();
925
926                     if (button.getEnabled() != shouldBeEnabled) {
927                         button.setEnabled(shouldBeEnabled);
928                     }
929                 }
930
931                 if (checkChanged) {
932                     boolean bv = action.isChecked();
933
934                     if (button.getSelection() != bv) {
935                         button.setSelection(bv);
936                     }
937                 }
938                 return;
939             }
940         }
941     }
942
943     /**
944      * Updates the images for this action.
945      *
946      * @param forceImage
947      * <code>true</code> if some form of image is compulsory, and
948      * <code>false</code> if it is acceptable for this item to have
949      * no image
950      * @return <code>true</code> if there are images for this action,
951      * <code>false</code> if not
952      */

953     private boolean updateImages(boolean forceImage) {
954
955         ResourceManager parentResourceManager = JFaceResources.getResources();
956
957         if (widget instanceof ToolItem) {
958             if (USE_COLOR_ICONS) {
959                 ImageDescriptor image = action.getHoverImageDescriptor();
960                 if (image == null) {
961                     image = action.getImageDescriptor();
962                 }
963                 ImageDescriptor disabledImage = action
964                         .getDisabledImageDescriptor();
965
966                 // Make sure there is a valid image.
967
if (image == null && forceImage) {
968                     image = ImageDescriptor.getMissingImageDescriptor();
969                 }
970
971                 LocalResourceManager localManager = new LocalResourceManager(
972                         parentResourceManager);
973
974                 // performance: more efficient in SWT to set disabled and hot
975
// image before regular image
976
((ToolItem) widget)
977                         .setDisabledImage(disabledImage == null ? null
978                                 : localManager
979                                         .createImageWithDefault(disabledImage));
980                 ((ToolItem) widget).setImage(image == null ? null
981                         : localManager.createImageWithDefault(image));
982
983                 disposeOldImages();
984                 imageManager = localManager;
985
986                 return image != null;
987             }
988             ImageDescriptor image = action.getImageDescriptor();
989             ImageDescriptor hoverImage = action.getHoverImageDescriptor();
990             ImageDescriptor disabledImage = action.getDisabledImageDescriptor();
991
992             // If there is no regular image, but there is a hover image,
993
// convert the hover image to gray and use it as the regular image.
994
if (image == null && hoverImage != null) {
995                 image = ImageDescriptor.createWithFlags(action
996                         .getHoverImageDescriptor(), SWT.IMAGE_GRAY);
997             } else {
998                 // If there is no hover image, use the regular image as the
999
// hover image,
1000
// and convert the regular image to gray
1001
if (hoverImage == null && image != null) {
1002                    hoverImage = image;
1003                    image = ImageDescriptor.createWithFlags(action
1004                            .getImageDescriptor(), SWT.IMAGE_GRAY);
1005                }
1006            }
1007
1008            // Make sure there is a valid image.
1009
if (hoverImage == null && image == null && forceImage) {
1010                image = ImageDescriptor.getMissingImageDescriptor();
1011            }
1012
1013            // Create a local resource manager to remember the images we've
1014
// allocated for this tool item
1015
LocalResourceManager localManager = new LocalResourceManager(
1016                    parentResourceManager);
1017
1018            // performance: more efficient in SWT to set disabled and hot image
1019
// before regular image
1020
((ToolItem) widget).setDisabledImage(disabledImage == null ? null
1021                    : localManager.createImageWithDefault(disabledImage));
1022            ((ToolItem) widget).setHotImage(hoverImage == null ? null
1023                    : localManager.createImageWithDefault(hoverImage));
1024            ((ToolItem) widget).setImage(image == null ? null : localManager
1025                    .createImageWithDefault(image));
1026
1027            // Now that we're no longer referencing the old images, clear them
1028
// out.
1029
disposeOldImages();
1030            imageManager = localManager;
1031
1032            return image != null;
1033        } else if (widget instanceof Item || widget instanceof Button) {
1034
1035            // Use hover image if there is one, otherwise use regular image.
1036
ImageDescriptor image = action.getHoverImageDescriptor();
1037            if (image == null) {
1038                image = action.getImageDescriptor();
1039            }
1040            // Make sure there is a valid image.
1041
if (image == null && forceImage) {
1042                image = ImageDescriptor.getMissingImageDescriptor();
1043            }
1044
1045            // Create a local resource manager to remember the images we've
1046
// allocated for this widget
1047
LocalResourceManager localManager = new LocalResourceManager(
1048                    parentResourceManager);
1049
1050            if (widget instanceof Item) {
1051                ((Item) widget).setImage(image == null ? null : localManager
1052                        .createImageWithDefault(image));
1053            } else if (widget instanceof Button) {
1054                ((Button) widget).setImage(image == null ? null : localManager
1055                        .createImageWithDefault(image));
1056            }
1057
1058            // Now that we're no longer referencing the old images, clear them
1059
// out.
1060
disposeOldImages();
1061            imageManager = localManager;
1062
1063            return image != null;
1064        }
1065        return false;
1066    }
1067
1068    /**
1069     * Dispose any images allocated for this contribution item
1070     */

1071    private void disposeOldImages() {
1072        if (imageManager != null) {
1073            imageManager.dispose();
1074            imageManager = null;
1075        }
1076    }
1077
1078    /**
1079     * Shorten the given text <code>t</code> so that its length doesn't exceed
1080     * the width of the given ToolItem.The default implementation replaces
1081     * characters in the center of the original string with an ellipsis ("...").
1082     * Override if you need a different strategy.
1083     *
1084     * @param textValue
1085     * the text to shorten
1086     * @param item
1087     * the tool item the text belongs to
1088     * @return the shortened string
1089     *
1090     */

1091    protected String JavaDoc shortenText(String JavaDoc textValue, ToolItem item) {
1092        if (textValue == null) {
1093            return null;
1094        }
1095
1096        GC gc = new GC(item.getParent());
1097
1098        int maxWidth = item.getImage().getBounds().width * 4;
1099
1100        if (gc.textExtent(textValue).x < maxWidth) {
1101            gc.dispose();
1102            return textValue;
1103        }
1104
1105        for (int i = textValue.length(); i > 0; i--) {
1106            String JavaDoc test = textValue.substring(0, i);
1107            test = test + ellipsis;
1108            if (gc.textExtent(test).x < maxWidth) {
1109                gc.dispose();
1110                return test;
1111            }
1112
1113        }
1114        gc.dispose();
1115        // If for some reason we fall through abort
1116
return textValue;
1117    }
1118}
1119
Popular Tags