KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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
12 package org.eclipse.jface.action;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Iterator JavaDoc;
16
17 import org.eclipse.jface.internal.provisional.action.IToolBarContributionItem;
18 import org.eclipse.core.runtime.Assert;
19 import org.eclipse.jface.util.Policy;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.events.DisposeEvent;
22 import org.eclipse.swt.events.DisposeListener;
23 import org.eclipse.swt.events.SelectionAdapter;
24 import org.eclipse.swt.events.SelectionEvent;
25 import org.eclipse.swt.graphics.Point;
26 import org.eclipse.swt.graphics.Rectangle;
27 import org.eclipse.swt.widgets.Control;
28 import org.eclipse.swt.widgets.CoolBar;
29 import org.eclipse.swt.widgets.CoolItem;
30 import org.eclipse.swt.widgets.Event;
31 import org.eclipse.swt.widgets.Listener;
32 import org.eclipse.swt.widgets.Menu;
33 import org.eclipse.swt.widgets.ToolBar;
34 import org.eclipse.swt.widgets.ToolItem;
35
36 /**
37  * The <code>ToolBarContributionItem</code> class provides a wrapper for tool
38  * bar managers when used in cool bar managers. It extends <code>ContributionItem</code>
39  * but and provides some additional methods to customize the size of the cool
40  * item and to retrieve the underlying tool bar manager.
41  * <p>
42  * This class may be instantiated; it is not intended to be subclassed.
43  * </p>
44  *
45  * @since 3.0
46  */

47 public class ToolBarContributionItem extends ContributionItem implements IToolBarContributionItem {
48
49     /**
50      * A constant used by <code>setMinimumItemsToShow</code> and <code>getMinimumItemsToShow</code>
51      * to indicate that all tool items should be shown in the cool item.
52      */

53     public static final int SHOW_ALL_ITEMS = -1;
54
55     /**
56      * The pull down menu used to list all hidden tool items if the current
57      * size is less than the preffered size.
58      */

59     private MenuManager chevronMenuManager = null;
60
61     /**
62      * The widget created for this item; <code>null</code> before creation
63      * and after disposal.
64      */

65     private CoolItem coolItem = null;
66
67     /**
68      * Current height of cool item
69      */

70     private int currentHeight = -1;
71
72     /**
73      * Current width of cool item.
74      */

75     private int currentWidth = -1;
76
77     /**
78      * A flag indicating that this item has been disposed. This prevents future
79      * method invocations from doing things they shouldn't.
80      */

81     private boolean disposed = false;
82
83     /**
84      * Mininum number of tool items to show in the cool item widget.
85      */

86     private int minimumItemsToShow = SHOW_ALL_ITEMS;
87
88     /**
89      * The tool bar manager used to manage the tool items contained in the cool
90      * item widget.
91      */

92     private ToolBarManager toolBarManager = null;
93
94     /**
95      * Enable/disable chevron support.
96      */

97     private boolean useChevron = true;
98
99     /**
100      * Convenience method equivalent to <code>ToolBarContributionItem(new ToolBarManager(), null)</code>.
101      */

102     public ToolBarContributionItem() {
103         this(new ToolBarManager(), null);
104     }
105
106     /**
107      * Convenience method equivalent to <code>ToolBarContributionItem(toolBarManager, null)</code>.
108      *
109      * @param toolBarManager
110      * the tool bar manager
111      */

112     public ToolBarContributionItem(IToolBarManager toolBarManager) {
113         this(toolBarManager, null);
114     }
115
116     /**
117      * Creates a tool bar contribution item.
118      *
119      * @param toolBarManager
120      * the tool bar manager to wrap
121      * @param id
122      * the contribution item id, or <code>null</code> if none
123      */

124     public ToolBarContributionItem(IToolBarManager toolBarManager, String JavaDoc id) {
125         super(id);
126         Assert.isTrue(toolBarManager instanceof ToolBarManager);
127         this.toolBarManager = (ToolBarManager) toolBarManager;
128     }
129
130     /**
131      * Checks whether this contribution item has been disposed. If it has, and
132      * the tracing options are active, then it prints some debugging
133      * information.
134      *
135      * @return <code>true</code> if the item is disposed; <code>false</code>
136      * otherwise.
137      *
138      */

139     private final boolean checkDisposed() {
140         if (disposed) {
141             if (Policy.TRACE_TOOLBAR) {
142                 System.out
143                         .println("Method invocation on a disposed tool bar contribution item."); //$NON-NLS-1$
144
new Exception JavaDoc().printStackTrace(System.out);
145             }
146
147             return true;
148         }
149
150         return false;
151     }
152
153     /*
154      * (non-Javadoc)
155      *
156      * @see org.eclipse.jface.action.IContributionItem#dispose()
157      */

158     public void dispose() {
159         // Dispose of the ToolBar and all its contributions
160
if (toolBarManager != null) {
161             toolBarManager.dispose();
162             toolBarManager = null;
163         }
164
165         /*
166          * We need to dispose the cool item or we might be left holding a cool
167          * item with a disposed control.
168          */

169         if ((coolItem != null) && (!coolItem.isDisposed())) {
170             coolItem.dispose();
171             coolItem = null;
172         }
173
174         // Mark this item as disposed.
175
disposed = true;
176     }
177
178     /*
179      * (non-Javadoc)
180      *
181      * @see org.eclipse.jface.action.IContributionItem#fill(org.eclipse.swt.widgets.CoolBar,
182      * int)
183      */

184     public void fill(CoolBar coolBar, int index) {
185         if (checkDisposed()) {
186             return;
187         }
188
189         if (coolItem == null && coolBar != null) {
190             ToolBar oldToolBar = toolBarManager.getControl();
191             ToolBar toolBar = toolBarManager.createControl(coolBar);
192             if ((oldToolBar != null) && (oldToolBar.equals(toolBar))) {
193                 // We are using an old tool bar, so we need to update.
194
toolBarManager.update(true);
195             }
196
197             // Do not create a coolItem if the toolbar is empty
198
if (toolBar.getItemCount() < 1) {
199                 return;
200             }
201             int flags = SWT.DROP_DOWN;
202             if (index >= 0) {
203                 coolItem = new CoolItem(coolBar, flags, index);
204             } else {
205                 coolItem = new CoolItem(coolBar, flags);
206             }
207             // sets the back reference
208
coolItem.setData(this);
209             // Add the toolbar to the CoolItem widget
210
coolItem.setControl(toolBar);
211
212             // Handle Context Menu
213
// ToolBarManager.createControl can actually return a pre-existing control.
214
// Only add the listener if the toolbar was newly created (bug 62097).
215
if (oldToolBar != toolBar) {
216                 toolBar.addListener(SWT.MenuDetect, new Listener() {
217     
218                     public void handleEvent(Event event) {
219                         // if the toolbar does not have its own context menu then
220
// handle the event
221
if (toolBarManager.getContextMenuManager() == null) {
222                             handleContextMenu(event);
223                         }
224                     }
225                 });
226             }
227
228             // Handle for chevron clicking
229
if (getUseChevron()) {
230                 // Chevron Support
231
coolItem.addSelectionListener(new SelectionAdapter() {
232
233                     public void widgetSelected(SelectionEvent event) {
234                         if (event.detail == SWT.ARROW) {
235                             handleChevron(event);
236                         }
237                     }
238                 });
239             }
240
241             // Handle for disposal
242
coolItem.addDisposeListener(new DisposeListener() {
243
244                 public void widgetDisposed(DisposeEvent event) {
245                     handleWidgetDispose(event);
246                 }
247             });
248
249             // Sets the size of the coolItem
250
updateSize(true);
251         }
252     }
253
254     /**
255      * Returns a consistent set of wrap indices. The return value will always
256      * include at least one entry and the first entry will always be zero.
257      * CoolBar.getWrapIndices() is inconsistent in whether or not it returns an
258      * index for the first row.
259      */

260     private int[] getAdjustedWrapIndices(int[] wraps) {
261         int[] adjustedWrapIndices;
262         if (wraps.length == 0) {
263             adjustedWrapIndices = new int[] { 0 };
264         } else {
265             if (wraps[0] != 0) {
266                 adjustedWrapIndices = new int[wraps.length + 1];
267                 adjustedWrapIndices[0] = 0;
268                 for (int i = 0; i < wraps.length; i++) {
269                     adjustedWrapIndices[i + 1] = wraps[i];
270                 }
271             } else {
272                 adjustedWrapIndices = wraps;
273             }
274         }
275         return adjustedWrapIndices;
276     }
277
278     /**
279      * Returns the current height of the corresponding cool item.
280      *
281      * @return the current height
282      */

283     public int getCurrentHeight() {
284         if (checkDisposed()) {
285             return -1;
286         }
287         return currentHeight;
288     }
289
290     /**
291      * Returns the current width of the corresponding cool item.
292      *
293      * @return the current size
294      */

295     public int getCurrentWidth() {
296         if (checkDisposed()) {
297             return -1;
298         }
299         return currentWidth;
300     }
301
302     /**
303      * Returns the minimum number of tool items to show in the cool item.
304      *
305      * @return the minimum number of tool items to show, or <code>SHOW_ALL_ITEMS</code>
306      * if a value was not set
307      * @see #setMinimumItemsToShow(int)
308      */

309     public int getMinimumItemsToShow() {
310         if (checkDisposed()) {
311             return -1;
312         }
313         return minimumItemsToShow;
314     }
315
316     /**
317      * Returns the internal tool bar manager of the contribution item.
318      *
319      * @return the tool bar manager, or <code>null</code> if one is not
320      * defined.
321      * @see IToolBarManager
322      */

323     public IToolBarManager getToolBarManager() {
324         if (checkDisposed()) {
325             return null;
326         }
327         return toolBarManager;
328     }
329
330     /**
331      * Returns whether chevron support is enabled.
332      *
333      * @return <code>true</code> if chevron support is enabled, <code>false</code>
334      * otherwise
335      */

336     public boolean getUseChevron() {
337         if (checkDisposed()) {
338             return false;
339         }
340         return useChevron;
341     }
342
343     /**
344      * Create and display the chevron menu.
345      */

346     private void handleChevron(SelectionEvent event) {
347         CoolItem item = (CoolItem) event.widget;
348         Control control = item.getControl();
349         if ((control instanceof ToolBar) == false) {
350             return;
351         }
352         CoolBar coolBar = item.getParent();
353         ToolBar toolBar = (ToolBar) control;
354         Rectangle toolBarBounds = toolBar.getBounds();
355         ToolItem[] items = toolBar.getItems();
356         ArrayList JavaDoc hidden = new ArrayList JavaDoc();
357         for (int i = 0; i < items.length; ++i) {
358             Rectangle itemBounds = items[i].getBounds();
359             if (!((itemBounds.x + itemBounds.width <= toolBarBounds.width) && (itemBounds.y
360                     + itemBounds.height <= toolBarBounds.height))) {
361                 hidden.add(items[i]);
362             }
363         }
364
365         // Create a pop-up menu with items for each of the hidden buttons.
366
if (chevronMenuManager != null) {
367             chevronMenuManager.dispose();
368         }
369         chevronMenuManager = new MenuManager();
370         for (Iterator JavaDoc i = hidden.iterator(); i.hasNext();) {
371             ToolItem toolItem = (ToolItem) i.next();
372             IContributionItem data = (IContributionItem) toolItem.getData();
373             if (data instanceof ActionContributionItem) {
374                 ActionContributionItem contribution = new ActionContributionItem(
375                         ((ActionContributionItem) data).getAction());
376                 chevronMenuManager.add(contribution);
377             } else if (data instanceof SubContributionItem) {
378                 IContributionItem innerData = ((SubContributionItem) data)
379                         .getInnerItem();
380                 if (innerData instanceof ActionContributionItem) {
381                     ActionContributionItem contribution = new ActionContributionItem(
382                             ((ActionContributionItem) innerData).getAction());
383                     chevronMenuManager.add(contribution);
384                 }
385             } else if (data.isSeparator()) {
386                 chevronMenuManager.add(new Separator());
387             }
388         }
389         Menu popup = chevronMenuManager.createContextMenu(coolBar);
390         Point chevronPosition = coolBar.toDisplay(event.x, event.y);
391         popup.setLocation(chevronPosition.x, chevronPosition.y);
392         popup.setVisible(true);
393     }
394
395     /**
396      * Handles the event when the toobar item does not have its own context
397      * menu.
398      *
399      * @param event
400      * the event object
401      */

402     private void handleContextMenu(Event event) {
403         ToolBar toolBar = toolBarManager.getControl();
404         // If parent has a menu then use that one
405
Menu parentMenu = toolBar.getParent().getMenu();
406         if ((parentMenu != null) && (!parentMenu.isDisposed())) {
407             toolBar.setMenu(parentMenu);
408             // Hook listener to remove menu once it has disapeared
409
parentMenu.addListener(SWT.Hide, new Listener() {
410
411                 public void handleEvent(Event innerEvent) {
412                     ToolBar innerToolBar = toolBarManager.getControl();
413                     if (innerToolBar != null) {
414                         innerToolBar.setMenu(null);
415                         Menu innerParentMenu = innerToolBar.getParent()
416                                 .getMenu();
417                         if (innerParentMenu != null) {
418                             innerParentMenu.removeListener(SWT.Hide, this);
419                         }
420                     }
421                 }
422             });
423         }
424     }
425
426     /**
427      * Handles the disposal of the widget.
428      *
429      * @param event
430      * the event object
431      */

432     private void handleWidgetDispose(DisposeEvent event) {
433         coolItem = null;
434     }
435
436     /**
437      * A contribution item is visible iff its internal state is visible <em>or</em>
438      * the tool bar manager contains something other than group markers and
439      * separators.
440      *
441      * @return <code>true</code> if the tool bar manager contains something
442      * other than group marks and separators, and the internal state is
443      * set to be visible.
444      */

445     public boolean isVisible() {
446         if (checkDisposed()) {
447             return false;
448         }
449
450         boolean visibleItem = false;
451         if (toolBarManager != null) {
452             IContributionItem[] contributionItems = toolBarManager.getItems();
453             for (int i = 0; i < contributionItems.length; i++) {
454                 IContributionItem contributionItem = contributionItems[i];
455                 if ((!contributionItem.isGroupMarker())
456                         && (!contributionItem.isSeparator())) {
457                     visibleItem = true;
458                     break;
459                 }
460             }
461         }
462
463         return (visibleItem || super.isVisible());
464     }
465
466     /*
467      * (non-Javadoc)
468      *
469      * @see org.eclipse.jface.action.IContributionItem#saveWidgetState()
470      */

471     public void saveWidgetState() {
472         if (checkDisposed()) {
473             return;
474         }
475         if (coolItem == null) {
476             return;
477         }
478
479         //1. Save current size
480
CoolBar coolBar = coolItem.getParent();
481         boolean isLastOnRow = false;
482         int lastIndex = coolBar.getItemCount() - 1;
483         int coolItemIndex = coolBar.indexOf(coolItem);
484         int[] wrapIndicies = getAdjustedWrapIndices(coolBar.getWrapIndices());
485         // Traverse through all wrap indicies backwards
486
for (int row = wrapIndicies.length - 1; row >= 0; row--) {
487             if (wrapIndicies[row] <= coolItemIndex) {
488
489                 int nextRow = row + 1;
490                 int nextRowStartIndex;
491                 if (nextRow > (wrapIndicies.length - 1)) {
492                     nextRowStartIndex = lastIndex + 1;
493                 } else {
494                     nextRowStartIndex = wrapIndicies[nextRow];
495                 }
496
497                 // Check to see if its the last item on the row
498
if (coolItemIndex == (nextRowStartIndex - 1)) {
499                     isLastOnRow = true;
500                 }
501                 break;
502             }
503         }
504
505         // Save the preferred size as actual size for the last item on a row
506
int nCurrentWidth;
507         if (isLastOnRow) {
508             nCurrentWidth = coolItem.getPreferredSize().x;
509         } else {
510             nCurrentWidth = coolItem.getSize().x;
511         }
512         setCurrentWidth(nCurrentWidth);
513         setCurrentHeight(coolItem.getSize().y);
514     }
515
516     /**
517      * Sets the current height of the cool item. Update(SIZE) should be called
518      * to adjust the widget.
519      *
520      * @param currentHeight
521      * the current height to set
522      */

523     public void setCurrentHeight(int currentHeight) {
524         if (checkDisposed()) {
525             return;
526         }
527         this.currentHeight = currentHeight;
528     }
529
530     /**
531      * Sets the current width of the cool item. Update(SIZE) should be called
532      * to adjust the widget.
533      *
534      * @param currentWidth
535      * the current width to set
536      */

537     public void setCurrentWidth(int currentWidth) {
538         if (checkDisposed()) {
539             return;
540         }
541         this.currentWidth = currentWidth;
542     }
543
544     /**
545      * Sets the minimum number of tool items to show in the cool item. If this
546      * number is less than the total tool items, a chevron will appear and the
547      * hidden tool items appear in a drop down menu. By default, all the tool
548      * items are shown in the cool item.
549      *
550      * @param minimumItemsToShow
551      * the minimum number of tool items to show.
552      * @see #getMinimumItemsToShow()
553      * @see #setUseChevron(boolean)
554      */

555     public void setMinimumItemsToShow(int minimumItemsToShow) {
556         if (checkDisposed()) {
557             return;
558         }
559         this.minimumItemsToShow = minimumItemsToShow;
560     }
561
562     /**
563      * Enables or disables chevron support for the cool item. By default,
564      * chevron support is enabled.
565      *
566      * @param value
567      * <code>true</code> to enable chevron support, <code>false</code>
568      * otherwise.
569      */

570     public void setUseChevron(boolean value) {
571         if (checkDisposed()) {
572             return;
573         }
574         useChevron = value;
575     }
576
577     /*
578      * (non-Javadoc)
579      *
580      * @see org.eclipse.jface.action.IContributionItem#update(java.lang.String)
581      */

582     public void update(String JavaDoc propertyName) {
583         if (checkDisposed()) {
584             return;
585         }
586         if (coolItem != null) {
587             IToolBarManager manager = getToolBarManager();
588             if (manager != null) {
589                 manager.update(true);
590             }
591
592             if ((propertyName == null)
593                     || propertyName.equals(ICoolBarManager.SIZE)) {
594                 updateSize(true);
595             }
596         }
597     }
598
599     /**
600      * Updates the cool items' preferred, minimum, and current size. The
601      * preferred size is calculated based on the tool bar size and extra trim.
602      *
603      * @param changeCurrentSize
604      * <code>true</code> if the current size should be changed to
605      * the preferred size, <code>false</code> to not change the
606      * current size
607      */

608     private void updateSize(boolean changeCurrentSize) {
609         if (checkDisposed()) {
610             return;
611         }
612         // cannot set size if coolItem is null
613
if (coolItem == null || coolItem.isDisposed()) {
614             return;
615         }
616         boolean locked = false;
617         CoolBar coolBar = coolItem.getParent();
618         try {
619             // Fix odd behaviour with locked tool bars
620
if (coolBar != null) {
621                 if (coolBar.getLocked()) {
622                     coolBar.setLocked(false);
623                     locked = true;
624                 }
625             }
626             ToolBar toolBar = (ToolBar) coolItem.getControl();
627             if ((toolBar == null) || (toolBar.isDisposed())
628                     || (toolBar.getItemCount() <= 0)) {
629                 // if the toolbar does not contain any items then dispose of
630
// coolItem
631
coolItem.setData(null);
632                 Control control = coolItem.getControl();
633                 if ((control != null) && !control.isDisposed()) {
634                     control.dispose();
635                     coolItem.setControl(null);
636                 }
637                 if (!coolItem.isDisposed()) {
638                     coolItem.dispose();
639                 }
640             } else {
641                 // If the toolbar item exists then adjust the size of the cool
642
// item
643
Point toolBarSize = toolBar.computeSize(SWT.DEFAULT,
644                         SWT.DEFAULT);
645                 // Set the preffered size to the size of the toolbar plus trim
646
Point preferredSize = coolItem.computeSize(toolBarSize.x,
647                         toolBarSize.y);
648                 coolItem.setPreferredSize(preferredSize);
649                 // note setMinimumSize must be called before setSize, see PR
650
// 15565
651
// Set minimum size
652
if (getMinimumItemsToShow() != SHOW_ALL_ITEMS) {
653                     int toolItemWidth = toolBar.getItems()[0].getWidth();
654                     int minimumWidth = toolItemWidth * getMinimumItemsToShow();
655                     coolItem.setMinimumSize(minimumWidth, toolBarSize.y);
656                 } else {
657                     coolItem.setMinimumSize(toolBarSize.x, toolBarSize.y);
658                 }
659                 if (changeCurrentSize) {
660                     // Set current size to preferred size
661
coolItem.setSize(preferredSize);
662                 }
663             }
664         } finally {
665             // If the cool bar was locked, then set it back to locked
666
if ((locked) && (coolBar != null)) {
667                 coolBar.setLocked(true);
668             }
669         }
670     }
671
672 }
673
Popular Tags