comparison org.eclipse.jface/src/org/eclipse/jface/action/ToolBarContributionItem.d @ 12:bc29606a740c

Added dwt-addons in original directory structure of eclipse.org
author Frank Benoit <benoit@tionex.de>
date Sat, 14 Mar 2009 18:23:29 +0100
parents
children 735224fcc45f
comparison
equal deleted inserted replaced
11:43904fec5dca 12:bc29606a740c
1 /*******************************************************************************
2 * Copyright (c) 2000, 2008 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 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13
14 module org.eclipse.jface.action.ToolBarContributionItem;
15
16 import org.eclipse.jface.action.IContributionItem;
17 import org.eclipse.jface.action.ContributionItem;
18 import org.eclipse.jface.action.MenuManager;
19 import org.eclipse.jface.action.IToolBarManager;
20 import org.eclipse.jface.action.ToolBarManager;
21 import org.eclipse.jface.action.ActionContributionItem;
22 import org.eclipse.jface.action.SubContributionItem;
23 import org.eclipse.jface.action.ICoolBarManager;
24 import org.eclipse.jface.action.Separator;
25 import org.eclipse.jface.action.IContributionManager;
26
27 // import java.util.Iterator;
28
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.events.DisposeEvent;
31 import org.eclipse.swt.events.DisposeListener;
32 import org.eclipse.swt.events.SelectionAdapter;
33 import org.eclipse.swt.events.SelectionEvent;
34 import org.eclipse.swt.graphics.Point;
35 import org.eclipse.swt.graphics.Rectangle;
36 import org.eclipse.swt.widgets.Control;
37 import org.eclipse.swt.widgets.CoolBar;
38 import org.eclipse.swt.widgets.CoolItem;
39 import org.eclipse.swt.widgets.Event;
40 import org.eclipse.swt.widgets.Listener;
41 import org.eclipse.swt.widgets.Menu;
42 import org.eclipse.swt.widgets.ToolBar;
43 import org.eclipse.swt.widgets.ToolItem;
44 import org.eclipse.core.runtime.Assert;
45 import org.eclipse.jface.internal.provisional.action.IToolBarContributionItem;
46 import org.eclipse.jface.util.Policy;
47
48 import java.lang.all;
49 import java.util.ArrayList;
50 import java.util.Iterator;
51 import java.util.Set;
52 import tango.io.Stdout;
53
54 /**
55 * The <code>ToolBarContributionItem</code> class provides a wrapper for tool
56 * bar managers when used in cool bar managers. It extends <code>ContributionItem</code>
57 * but and provides some additional methods to customize the size of the cool
58 * item and to retrieve the underlying tool bar manager.
59 * <p>
60 * This class may be instantiated; it is not intended to be subclassed.
61 * </p>
62 *
63 * @since 3.0
64 * @noextend This class is not intended to be subclassed by clients.
65 */
66 public class ToolBarContributionItem : ContributionItem, IToolBarContributionItem {
67 alias ContributionItem.fill fill;
68 alias ContributionItem.update update;
69
70 public IContributionManager getParent() {
71 return super.getParent();
72 }
73
74 /**
75 * A constant used by <code>setMinimumItemsToShow</code> and <code>getMinimumItemsToShow</code>
76 * to indicate that all tool items should be shown in the cool item.
77 */
78 public static const int SHOW_ALL_ITEMS = -1;
79
80 /**
81 * The pull down menu used to list all hidden tool items if the current
82 * size is less than the preffered size.
83 */
84 private MenuManager chevronMenuManager = null;
85
86 /**
87 * The widget created for this item; <code>null</code> before creation
88 * and after disposal.
89 */
90 private CoolItem coolItem = null;
91
92 /**
93 * Current height of cool item
94 */
95 private int currentHeight = -1;
96
97 /**
98 * Current width of cool item.
99 */
100 private int currentWidth = -1;
101
102 /**
103 * A flag indicating that this item has been disposed. This prevents future
104 * method invocations from doing things they shouldn't.
105 */
106 private bool disposed = false;
107
108 /**
109 * Mininum number of tool items to show in the cool item widget.
110 */
111 private int minimumItemsToShow = SHOW_ALL_ITEMS;
112
113 /**
114 * The tool bar manager used to manage the tool items contained in the cool
115 * item widget.
116 */
117 private ToolBarManager toolBarManager = null;
118
119 /**
120 * Enable/disable chevron support.
121 */
122 private bool useChevron = true;
123
124 /**
125 * Convenience method equivalent to <code>ToolBarContributionItem(new ToolBarManager(), null)</code>.
126 */
127 public this() {
128 this(new ToolBarManager(), null);
129 }
130
131 /**
132 * Convenience method equivalent to <code>ToolBarContributionItem(toolBarManager, null)</code>.
133 *
134 * @param toolBarManager
135 * the tool bar manager
136 */
137 public this(IToolBarManager toolBarManager) {
138 this(toolBarManager, null);
139 }
140
141 /**
142 * Creates a tool bar contribution item.
143 *
144 * @param toolBarManager
145 * the tool bar manager to wrap
146 * @param id
147 * the contribution item id, or <code>null</code> if none
148 */
149 public this(IToolBarManager toolBarManager, String id) {
150 super(id);
151 Assert.isTrue( null !is cast(ToolBarManager)toolBarManager );
152 this.toolBarManager = cast(ToolBarManager) toolBarManager;
153 }
154
155 /**
156 * Checks whether this contribution item has been disposed. If it has, and
157 * the tracing options are active, then it prints some debugging
158 * information.
159 *
160 * @return <code>true</code> if the item is disposed; <code>false</code>
161 * otherwise.
162 *
163 */
164 private final bool checkDisposed() {
165 if (disposed) {
166 if (Policy.TRACE_TOOLBAR) {
167 Stdout.formatln("Method invocation on a disposed tool bar contribution item."); //$NON-NLS-1$
168 ExceptionPrintStackTrace( new Exception(null), Stdout );
169 }
170
171 return true;
172 }
173
174 return false;
175 }
176
177 /*
178 * (non-Javadoc)
179 *
180 * @see org.eclipse.jface.action.IContributionItem#dispose()
181 */
182 public override void dispose() {
183 // Dispose of the ToolBar and all its contributions
184 if (toolBarManager !is null) {
185 toolBarManager.dispose();
186 toolBarManager = null;
187 }
188
189 /*
190 * We need to dispose the cool item or we might be left holding a cool
191 * item with a disposed control.
192 */
193 if ((coolItem !is null) && (!coolItem.isDisposed())) {
194 coolItem.dispose();
195 coolItem = null;
196 }
197
198 // Mark this item as disposed.
199 disposed = true;
200 }
201
202 /*
203 * (non-Javadoc)
204 *
205 * @see org.eclipse.jface.action.IContributionItem#fill(org.eclipse.swt.widgets.CoolBar,
206 * int)
207 */
208 public override void fill(CoolBar coolBar, int index) {
209 if (checkDisposed()) {
210 return;
211 }
212
213 if (coolItem is null && coolBar !is null) {
214 ToolBar oldToolBar = toolBarManager.getControl();
215 ToolBar toolBar = toolBarManager.createControl(coolBar);
216 if ((oldToolBar !is null) && (oldToolBar.opEquals(toolBar))) {
217 // We are using an old tool bar, so we need to update.
218 toolBarManager.update(true);
219 }
220
221 // Do not create a coolItem if the toolbar is empty
222 if (toolBar.getItemCount() < 1) {
223 return;
224 }
225 int flags = SWT.DROP_DOWN;
226 if (index >= 0) {
227 coolItem = new CoolItem(coolBar, flags, index);
228 } else {
229 coolItem = new CoolItem(coolBar, flags);
230 }
231 // sets the back reference
232 coolItem.setData(this);
233 // Add the toolbar to the CoolItem widget
234 coolItem.setControl(toolBar);
235
236 // Handle Context Menu
237 // ToolBarManager.createControl can actually return a pre-existing control.
238 // Only add the listener if the toolbar was newly created (bug 62097).
239 if (oldToolBar !is toolBar) {
240 toolBar.addListener(SWT.MenuDetect, new class Listener {
241
242 public void handleEvent(Event event) {
243 // if the toolbar does not have its own context menu then
244 // handle the event
245 if (toolBarManager.getContextMenuManager() is null) {
246 handleContextMenu(event);
247 }
248 }
249 });
250 }
251
252 // Handle for chevron clicking
253 if (getUseChevron()) {
254 // Chevron Support
255 coolItem.addSelectionListener(new class SelectionAdapter {
256
257 public void widgetSelected(SelectionEvent event) {
258 if (event.detail is SWT.ARROW) {
259 handleChevron(event);
260 }
261 }
262 });
263 }
264
265 // Handle for disposal
266 coolItem.addDisposeListener(new class DisposeListener {
267
268 public void widgetDisposed(DisposeEvent event) {
269 handleWidgetDispose(event);
270 }
271 });
272
273 // Sets the size of the coolItem
274 updateSize(true);
275 }
276 }
277
278 /**
279 * Returns a consistent set of wrap indices. The return value will always
280 * include at least one entry and the first entry will always be zero.
281 * CoolBar.getWrapIndices() is inconsistent in whether or not it returns an
282 * index for the first row.
283 */
284 private int[] getAdjustedWrapIndices(int[] wraps) {
285 int[] adjustedWrapIndices;
286 if (wraps.length is 0) {
287 adjustedWrapIndices = [ 0 ];
288 } else {
289 if (wraps[0] !is 0) {
290 adjustedWrapIndices = new int[wraps.length + 1];
291 adjustedWrapIndices[0] = 0;
292 for (int i = 0; i < wraps.length; i++) {
293 adjustedWrapIndices[i + 1] = wraps[i];
294 }
295 } else {
296 adjustedWrapIndices = wraps;
297 }
298 }
299 return adjustedWrapIndices;
300 }
301
302 /**
303 * Returns the current height of the corresponding cool item.
304 *
305 * @return the current height
306 */
307 public int getCurrentHeight() {
308 if (checkDisposed()) {
309 return -1;
310 }
311 return currentHeight;
312 }
313
314 /**
315 * Returns the current width of the corresponding cool item.
316 *
317 * @return the current size
318 */
319 public int getCurrentWidth() {
320 if (checkDisposed()) {
321 return -1;
322 }
323 return currentWidth;
324 }
325
326 /**
327 * Returns the minimum number of tool items to show in the cool item.
328 *
329 * @return the minimum number of tool items to show, or <code>SHOW_ALL_ITEMS</code>
330 * if a value was not set
331 * @see #setMinimumItemsToShow(int)
332 */
333 public int getMinimumItemsToShow() {
334 if (checkDisposed()) {
335 return -1;
336 }
337 return minimumItemsToShow;
338 }
339
340 /**
341 * Returns the internal tool bar manager of the contribution item.
342 *
343 * @return the tool bar manager, or <code>null</code> if one is not
344 * defined.
345 * @see IToolBarManager
346 */
347 public IToolBarManager getToolBarManager() {
348 if (checkDisposed()) {
349 return null;
350 }
351 return toolBarManager;
352 }
353
354 /**
355 * Returns whether chevron support is enabled.
356 *
357 * @return <code>true</code> if chevron support is enabled, <code>false</code>
358 * otherwise
359 */
360 public bool getUseChevron() {
361 if (checkDisposed()) {
362 return false;
363 }
364 return useChevron;
365 }
366
367 /**
368 * Create and display the chevron menu.
369 */
370 private void handleChevron(SelectionEvent event) {
371 CoolItem item = cast(CoolItem) event.widget;
372 Control control = item.getControl();
373 if (!(cast(ToolBar)control ) ) {
374 return;
375 }
376 CoolBar coolBar = item.getParent();
377 ToolBar toolBar = cast(ToolBar) control;
378 Rectangle toolBarBounds = toolBar.getBounds();
379 ToolItem[] items = toolBar.getItems();
380 ArrayList hidden = new ArrayList();
381 for (int i = 0; i < items.length; ++i) {
382 Rectangle itemBounds = items[i].getBounds();
383 if (!((itemBounds.x + itemBounds.width <= toolBarBounds.width) && (itemBounds.y
384 + itemBounds.height <= toolBarBounds.height))) {
385 hidden.add(items[i]);
386 }
387 }
388
389 // Create a pop-up menu with items for each of the hidden buttons.
390 if (chevronMenuManager !is null) {
391 chevronMenuManager.dispose();
392 }
393 chevronMenuManager = new MenuManager();
394 for (Iterator i = hidden.iterator(); i.hasNext();) {
395 ToolItem toolItem = cast(ToolItem) i.next();
396 IContributionItem data = cast(IContributionItem) toolItem.getData();
397 if (cast(ActionContributionItem)data ) {
398 ActionContributionItem contribution = new ActionContributionItem(
399 (cast(ActionContributionItem) data).getAction());
400 chevronMenuManager.add(contribution);
401 } else if (cast(SubContributionItem)data ) {
402 IContributionItem innerData = (cast(SubContributionItem) data)
403 .getInnerItem();
404 if (cast(ActionContributionItem)innerData ) {
405 ActionContributionItem contribution = new ActionContributionItem(
406 (cast(ActionContributionItem) innerData).getAction());
407 chevronMenuManager.add(contribution);
408 }
409 } else if (data.isSeparator()) {
410 chevronMenuManager.add(new Separator());
411 }
412 }
413 Menu popup = chevronMenuManager.createContextMenu(coolBar);
414 Point chevronPosition = coolBar.toDisplay(event.x, event.y);
415 popup.setLocation(chevronPosition.x, chevronPosition.y);
416 popup.setVisible(true);
417 }
418
419 /**
420 * Handles the event when the toobar item does not have its own context
421 * menu.
422 *
423 * @param event
424 * the event object
425 */
426 private void handleContextMenu(Event event) {
427 ToolBar toolBar = toolBarManager.getControl();
428 // If parent has a menu then use that one
429 Menu parentMenu = toolBar.getParent().getMenu();
430 if ((parentMenu !is null) && (!parentMenu.isDisposed())) {
431 toolBar.setMenu(parentMenu);
432 // Hook listener to remove menu once it has disapeared
433 parentMenu.addListener(SWT.Hide, new class Listener {
434
435 public void handleEvent(Event innerEvent) {
436 ToolBar innerToolBar = toolBarManager.getControl();
437 if (innerToolBar !is null) {
438 innerToolBar.setMenu(null);
439 Menu innerParentMenu = innerToolBar.getParent()
440 .getMenu();
441 if (innerParentMenu !is null) {
442 innerParentMenu.removeListener(SWT.Hide, this);
443 }
444 }
445 }
446 });
447 }
448 }
449
450 /**
451 * Handles the disposal of the widget.
452 *
453 * @param event
454 * the event object
455 */
456 private void handleWidgetDispose(DisposeEvent event) {
457 coolItem = null;
458 }
459
460 /**
461 * A contribution item is visible iff its internal state is visible <em>or</em>
462 * the tool bar manager contains something other than group markers and
463 * separators.
464 *
465 * @return <code>true</code> if the tool bar manager contains something
466 * other than group marks and separators, and the internal state is
467 * set to be visible.
468 */
469 public override bool isVisible() {
470 if (checkDisposed()) {
471 return false;
472 }
473
474 bool visibleItem = false;
475 if (toolBarManager !is null) {
476 IContributionItem[] contributionItems = toolBarManager.getItems();
477 for (int i = 0; i < contributionItems.length; i++) {
478 IContributionItem contributionItem = contributionItems[i];
479 if ((!contributionItem.isGroupMarker())
480 && (!contributionItem.isSeparator())) {
481 visibleItem = true;
482 break;
483 }
484 }
485 }
486
487 return (visibleItem || super.isVisible());
488 }
489
490 /*
491 * (non-Javadoc)
492 *
493 * @see org.eclipse.jface.action.IContributionItem#saveWidgetState()
494 */
495 public override void saveWidgetState() {
496 if (checkDisposed()) {
497 return;
498 }
499 if (coolItem is null) {
500 return;
501 }
502
503 //1. Save current size
504 CoolBar coolBar = coolItem.getParent();
505 bool isLastOnRow = false;
506 int lastIndex = coolBar.getItemCount() - 1;
507 int coolItemIndex = coolBar.indexOf(coolItem);
508 int[] wrapIndicies = getAdjustedWrapIndices(coolBar.getWrapIndices());
509 // Traverse through all wrap indicies backwards
510 for (int row = wrapIndicies.length - 1; row >= 0; row--) {
511 if (wrapIndicies[row] <= coolItemIndex) {
512
513 int nextRow = row + 1;
514 int nextRowStartIndex;
515 if (nextRow > (wrapIndicies.length - 1)) {
516 nextRowStartIndex = lastIndex + 1;
517 } else {
518 nextRowStartIndex = wrapIndicies[nextRow];
519 }
520
521 // Check to see if its the last item on the row
522 if (coolItemIndex is (nextRowStartIndex - 1)) {
523 isLastOnRow = true;
524 }
525 break;
526 }
527 }
528
529 // Save the preferred size as actual size for the last item on a row
530 int nCurrentWidth;
531 if (isLastOnRow) {
532 nCurrentWidth = coolItem.getPreferredSize().x;
533 } else {
534 nCurrentWidth = coolItem.getSize().x;
535 }
536 setCurrentWidth(nCurrentWidth);
537 setCurrentHeight(coolItem.getSize().y);
538 }
539
540 /**
541 * Sets the current height of the cool item. Update(SIZE) should be called
542 * to adjust the widget.
543 *
544 * @param currentHeight
545 * the current height to set
546 */
547 public void setCurrentHeight(int currentHeight) {
548 if (checkDisposed()) {
549 return;
550 }
551 this.currentHeight = currentHeight;
552 }
553
554 /**
555 * Sets the current width of the cool item. Update(SIZE) should be called
556 * to adjust the widget.
557 *
558 * @param currentWidth
559 * the current width to set
560 */
561 public void setCurrentWidth(int currentWidth) {
562 if (checkDisposed()) {
563 return;
564 }
565 this.currentWidth = currentWidth;
566 }
567
568 /**
569 * Sets the minimum number of tool items to show in the cool item. If this
570 * number is less than the total tool items, a chevron will appear and the
571 * hidden tool items appear in a drop down menu. By default, all the tool
572 * items are shown in the cool item.
573 *
574 * @param minimumItemsToShow
575 * the minimum number of tool items to show.
576 * @see #getMinimumItemsToShow()
577 * @see #setUseChevron(bool)
578 */
579 public void setMinimumItemsToShow(int minimumItemsToShow) {
580 if (checkDisposed()) {
581 return;
582 }
583 this.minimumItemsToShow = minimumItemsToShow;
584 }
585
586 /**
587 * Enables or disables chevron support for the cool item. By default,
588 * chevron support is enabled.
589 *
590 * @param value
591 * <code>true</code> to enable chevron support, <code>false</code>
592 * otherwise.
593 */
594 public void setUseChevron(bool value) {
595 if (checkDisposed()) {
596 return;
597 }
598 useChevron = value;
599 }
600
601 /*
602 * (non-Javadoc)
603 *
604 * @see org.eclipse.jface.action.IContributionItem#update(java.lang.String)
605 */
606 public override void update(String propertyName) {
607 if (checkDisposed()) {
608 return;
609 }
610 if (coolItem !is null) {
611 IToolBarManager manager = getToolBarManager();
612 if (manager !is null) {
613 manager.update(true);
614 }
615
616 if ((propertyName is null)
617 || propertyName.equals(ICoolBarManager.SIZE)) {
618 updateSize(true);
619 }
620 }
621 }
622
623 /**
624 * Updates the cool items' preferred, minimum, and current size. The
625 * preferred size is calculated based on the tool bar size and extra trim.
626 *
627 * @param changeCurrentSize
628 * <code>true</code> if the current size should be changed to
629 * the preferred size, <code>false</code> to not change the
630 * current size
631 */
632 private void updateSize(bool changeCurrentSize) {
633 if (checkDisposed()) {
634 return;
635 }
636 // cannot set size if coolItem is null
637 if (coolItem is null || coolItem.isDisposed()) {
638 return;
639 }
640 bool locked = false;
641 CoolBar coolBar = coolItem.getParent();
642 try {
643 // Fix odd behaviour with locked tool bars
644 if (coolBar !is null) {
645 if (coolBar.getLocked()) {
646 coolBar.setLocked(false);
647 locked = true;
648 }
649 }
650 ToolBar toolBar = cast(ToolBar) coolItem.getControl();
651 if ((toolBar is null) || (toolBar.isDisposed())
652 || (toolBar.getItemCount() <= 0)) {
653 // if the toolbar does not contain any items then dispose of
654 // coolItem
655 coolItem.setData(null);
656 Control control = coolItem.getControl();
657 if ((control !is null) && !control.isDisposed()) {
658 control.dispose();
659 coolItem.setControl(null);
660 }
661 if (!coolItem.isDisposed()) {
662 coolItem.dispose();
663 }
664 } else {
665 // If the toolbar item exists then adjust the size of the cool
666 // item
667 Point toolBarSize = toolBar.computeSize(SWT.DEFAULT,
668 SWT.DEFAULT);
669 // Set the preffered size to the size of the toolbar plus trim
670 Point preferredSize = coolItem.computeSize(toolBarSize.x,
671 toolBarSize.y);
672 coolItem.setPreferredSize(preferredSize);
673 // note setMinimumSize must be called before setSize, see PR
674 // 15565
675 // Set minimum size
676 if (getMinimumItemsToShow() !is SHOW_ALL_ITEMS) {
677 int toolItemWidth = toolBar.getItems()[0].getWidth();
678 int minimumWidth = toolItemWidth * getMinimumItemsToShow();
679 coolItem.setMinimumSize(minimumWidth, toolBarSize.y);
680 } else {
681 coolItem.setMinimumSize(toolBarSize.x, toolBarSize.y);
682 }
683 if (changeCurrentSize) {
684 // Set current size to preferred size
685 coolItem.setSize(preferredSize);
686 }
687 }
688 } finally {
689 // If the cool bar was locked, then set it back to locked
690 if ((locked) && (coolBar !is null)) {
691 coolBar.setLocked(true);
692 }
693 }
694 }
695
696 }