comparison org.eclipse.jface/src/org/eclipse/jface/action/CoolBarManager.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) 2003, 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 module org.eclipse.jface.action.CoolBarManager;
14
15 import org.eclipse.jface.action.ToolBarContributionItem;
16 import org.eclipse.jface.action.Separator;
17
18 import org.eclipse.jface.action.ContributionManager;
19 import org.eclipse.jface.action.IContributionManager;
20 import org.eclipse.jface.action.IContributionItem;
21 import org.eclipse.jface.action.ICoolBarManager;
22 import org.eclipse.jface.action.IToolBarManager;
23 import org.eclipse.jface.action.IMenuManager;
24 import org.eclipse.jface.action.MenuManager;
25
26 import org.eclipse.swt.SWT;
27 import org.eclipse.swt.widgets.Composite;
28 import org.eclipse.swt.widgets.Control;
29 import org.eclipse.swt.widgets.CoolBar;
30 import org.eclipse.swt.widgets.CoolItem;
31 import org.eclipse.swt.widgets.Menu;
32 import org.eclipse.core.runtime.Assert;
33 import org.eclipse.jface.util.Policy;
34
35 import java.lang.all;
36 import java.util.ListIterator;
37 import java.util.List;
38 import java.util.ArrayList;
39 import java.util.Iterator;
40 import java.util.HashMap;
41 import java.util.Set;
42 import tango.io.Stdout;
43
44 /**
45 * A cool bar manager is a contribution manager which realizes itself and its
46 * items in a cool bar control.
47 * <p>
48 * This class may be instantiated; it may also be subclassed.
49 * </p>
50 *
51 * @since 3.0
52 */
53 public class CoolBarManager : ContributionManager,
54 ICoolBarManager {
55 alias ContributionManager.add add;
56
57 /**
58 * A separator created by the end user.
59 */
60 public final static String USER_SEPARATOR = "UserSeparator"; //$NON-NLS-1$
61
62 /**
63 * The original creation order of the contribution items.
64 */
65 private ArrayList cbItemsCreationOrder;
66
67 /**
68 * MenuManager for cool bar pop-up menu, or null if none.
69 */
70 private MenuManager contextMenuManager = null;
71
72 /**
73 * The cool bar control; <code>null</code> before creation and after
74 * disposal.
75 */
76 private CoolBar coolBar = null;
77
78 /**
79 * The cool bar items style; <code>SWT.NONE</code> by default.
80 */
81 private int itemStyle = SWT.NONE;
82
83 /**
84 * Creates a new cool bar manager with the default style. Equivalent to
85 * <code>CoolBarManager(SWT.NONE)</code>.
86 */
87 public this() {
88 cbItemsCreationOrder = new ArrayList();
89 // do nothing
90 }
91
92 /**
93 * Creates a cool bar manager for an existing cool bar control. This
94 * manager becomes responsible for the control, and will dispose of it when
95 * the manager is disposed.
96 *
97 * @param coolBar
98 * the cool bar control
99 */
100 public this(CoolBar coolBar) {
101 this();
102 Assert.isNotNull(coolBar);
103 this.coolBar = coolBar;
104 itemStyle = coolBar.getStyle();
105 }
106
107 /**
108 * Creates a cool bar manager with the given SWT style. Calling <code>createControl</code>
109 * will create the cool bar control.
110 *
111 * @param style
112 * the cool bar item style; see
113 * {@link org.eclipse.swt.widgets.CoolBar CoolBar}for for valid
114 * style bits
115 */
116 public this(int style) {
117 cbItemsCreationOrder = new ArrayList();
118 itemStyle = style;
119 }
120
121 /*
122 * (non-Javadoc)
123 *
124 * @see org.eclipse.jface.action.ICoolBarManager#add(org.eclipse.jface.action.IToolBarManager)
125 */
126 public void add(IToolBarManager toolBarManager) {
127 Assert.isNotNull(cast(Object)toolBarManager);
128 super.add(new ToolBarContributionItem(toolBarManager));
129 }
130
131 /**
132 * Collapses consecutive separators and removes a separator from the
133 * beginning and end of the list.
134 *
135 * @param contributionList
136 * the list of contributions; must not be <code>null</code>.
137 * @return The contribution list provided with extraneous separators
138 * removed; this value is never <code>null</code>, but may be
139 * empty.
140 */
141 private ArrayList adjustContributionList(ArrayList contributionList) {
142 IContributionItem item;
143 // Fist remove a separator if it is the first element of the list
144 if (contributionList.size() !is 0) {
145 item = cast(IContributionItem) contributionList.get(0);
146 if (item.isSeparator()) {
147 contributionList.remove(0);
148 }
149
150 auto iterator = contributionList.listIterator();
151 // collapse consecutive separators
152 while (iterator.hasNext()) {
153 item = cast(IContributionItem) iterator.next();
154 if (item.isSeparator()) {
155 while (iterator.hasNext()) {
156 item = cast(IContributionItem) iterator.next();
157 if (item.isSeparator()) {
158 iterator.remove();
159 } else {
160 break;
161 }
162 }
163
164 }
165 }
166 // Now check last element to see if there is a separator
167 item = cast(IContributionItem) contributionList.get(contributionList
168 .size() - 1);
169 if (item.isSeparator()) {
170 contributionList.remove(contributionList.size() - 1);
171 }
172 }
173 return contributionList;
174
175 }
176
177 /* (non-Javadoc)
178 * @see org.eclipse.jface.action.ContributionManager#checkDuplication(org.eclipse.jface.action.IContributionItem)
179 */
180 protected override bool allowItem(IContributionItem itemToAdd) {
181 /* We will allow as many null entries as they like, though there should
182 * be none.
183 */
184 if (itemToAdd is null) {
185 return true;
186 }
187
188 /* Null identifiers can be expected in generic contribution items.
189 */
190 String firstId = itemToAdd.getId();
191 if (firstId is null) {
192 return true;
193 }
194
195 // Cycle through the current list looking for duplicates.
196 IContributionItem[] currentItems = getItems();
197 for (int i = 0; i < currentItems.length; i++) {
198 IContributionItem currentItem = currentItems[i];
199
200 // We ignore null entries.
201 if (currentItem is null) {
202 continue;
203 }
204
205 String secondId = currentItem.getId();
206 if (firstId.equals(secondId)) {
207 if (Policy.TRACE_TOOLBAR) {
208 Stdout.formatln("Trying to add a duplicate item."); //$NON-NLS-1$
209 ExceptionPrintStackTrace(new Exception(null), Stdout );
210 Stdout.formatln("DONE --------------------------"); //$NON-NLS-1$
211 }
212 return false;
213 }
214 }
215
216 return true;
217 }
218
219 /**
220 * Positions the list iterator to the end of all the separators. Calling
221 * <code>next()</code> the iterator should return the immediate object
222 * following the last separator.
223 *
224 * @param iterator
225 * the list iterator.
226 */
227 private void collapseSeparators(ListIterator iterator) {
228
229 while (iterator.hasNext()) {
230 IContributionItem item = cast(IContributionItem) iterator.next();
231 if (!item.isSeparator()) {
232 iterator.previous();
233 return;
234 }
235 }
236 }
237
238 /**
239 * Returns whether the cool bar control has been created and not yet
240 * disposed.
241 *
242 * @return <code>true</code> if the control has been created and not yet
243 * disposed, <code>false</code> otherwise
244 */
245 private bool coolBarExist() {
246 return coolBar !is null && !coolBar.isDisposed();
247 }
248
249 /**
250 * Creates and returns this manager's cool bar control. Does not create a
251 * new control if one already exists.
252 *
253 * @param parent
254 * the parent control
255 * @return the cool bar control
256 */
257 public CoolBar createControl(Composite parent) {
258 Assert.isNotNull(parent);
259 if (!coolBarExist()) {
260 coolBar = new CoolBar(parent, itemStyle);
261 coolBar.setMenu(getContextMenuControl());
262 coolBar.setLocked(false);
263 update(false);
264 }
265 return coolBar;
266 }
267
268 /**
269 * Disposes of this cool bar manager and frees all allocated SWT resources.
270 * Notifies all contribution items of the dispose. Note that this method
271 * does not clean up references between this cool bar manager and its
272 * associated contribution items. Use <code>removeAll</code> for that
273 * purpose.
274 */
275 public void dispose() {
276 if (coolBarExist()) {
277 coolBar.dispose();
278 coolBar = null;
279 }
280 IContributionItem[] items = getItems();
281 for (int i = 0; i < items.length; i++) {
282 // Disposes of the contribution item.
283 // If Contribution Item is a toolbar then it will dispose of
284 // all the nested
285 // contribution items.
286 items[i].dispose();
287 }
288 // If a context menu existed then dispose of it.
289 if (contextMenuManager !is null) {
290 contextMenuManager.dispose();
291 contextMenuManager = null;
292 }
293
294 }
295
296 /**
297 * Disposes the given cool item.
298 *
299 * @param item
300 * the cool item to dispose
301 */
302 private void dispose(CoolItem item) {
303 if ((item !is null) && !item.isDisposed()) {
304
305 item.setData(null);
306 Control control = item.getControl();
307 // if the control is already disposed, setting the coolitem
308 // control to null will cause an SWT exception, workaround
309 // for 19630
310 if ((control !is null) && !control.isDisposed()) {
311 item.setControl(null);
312 }
313 item.dispose();
314 }
315 }
316
317 /**
318 * Finds the cool item associated with the given contribution item.
319 *
320 * @param item
321 * the contribution item
322 * @return the associated cool item, or <code>null</code> if not found
323 */
324 private CoolItem findCoolItem(IContributionItem item) {
325 CoolItem[] coolItems = (coolBar is null) ? null : coolBar.getItems();
326 return findCoolItem(coolItems, item);
327 }
328
329 private CoolItem findCoolItem(CoolItem[] items, IContributionItem item) {
330 if (items is null) {
331 return null;
332 }
333
334 for (int i = 0; i < items.length; i++) {
335 CoolItem coolItem = items[i];
336 IContributionItem data = cast(IContributionItem) coolItem.getData();
337 if (data !is null && (cast(Object)data).opEquals(cast(Object)item)) {
338 return coolItem;
339 }
340 }
341 return null;
342 }
343
344 /**
345 * Return a consistent set of wrap indices. The return value will always
346 * include at least one entry and the first entry will always be zero.
347 * CoolBar.getWrapIndices() is inconsistent in whether or not it returns an
348 * index for the first row.
349 *
350 * @param wraps
351 * the wrap indicies from the cool bar widget
352 * @return the adjusted wrap indicies.
353 */
354 private int[] getAdjustedWrapIndices(int[] wraps) {
355 int[] adjustedWrapIndices;
356 if (wraps.length is 0) {
357 adjustedWrapIndices = [ 0 ];
358 } else {
359 if (wraps[0] !is 0) {
360 adjustedWrapIndices = new int[wraps.length + 1];
361 adjustedWrapIndices[0] = 0;
362 for (int i = 0; i < wraps.length; i++) {
363 adjustedWrapIndices[i + 1] = wraps[i];
364 }
365 } else {
366 adjustedWrapIndices = wraps;
367 }
368 }
369 return adjustedWrapIndices;
370 }
371
372 /**
373 * Returns the control of the Menu Manager. If the menu manager does not
374 * have a control then one is created.
375 *
376 * @return menu control associated with manager, or null if none
377 */
378 private Menu getContextMenuControl() {
379 if ((contextMenuManager !is null) && (coolBar !is null)) {
380 Menu menuWidget = contextMenuManager.getMenu();
381 if ((menuWidget is null) || (menuWidget.isDisposed())) {
382 menuWidget = contextMenuManager.createContextMenu(coolBar);
383 }
384 return menuWidget;
385 }
386 return null;
387 }
388
389 /*
390 * (non-Javadoc)
391 *
392 * @see org.eclipse.jface.action.ICoolBarManager#isLayoutLocked()
393 */
394 public IMenuManager getContextMenuManager() {
395 return contextMenuManager;
396 }
397
398 /**
399 * Returns the cool bar control for this manager.
400 *
401 * @return the cool bar control, or <code>null</code> if none
402 */
403 public CoolBar getControl() {
404 return coolBar;
405 }
406
407 /**
408 * Returns an array list of all the contribution items in the manager.
409 *
410 * @return an array list of contribution items.
411 */
412 private ArrayList getItemList() {
413 IContributionItem[] cbItems = getItems();
414 ArrayList list = new ArrayList(cbItems.length);
415 for (int i = 0; i < cbItems.length; i++) {
416 list.add( cast(Object) cbItems[i]);
417 }
418 return list;
419 }
420
421 /*
422 * (non-Javadoc)
423 *
424 * @see org.eclipse.jface.action.ICoolBarManager#isLayoutLocked()
425 */
426 public bool getLockLayout() {
427 if (!coolBarExist()) {
428 return false;
429 }
430 return coolBar.getLocked();
431 }
432
433 /**
434 * Returns the number of rows that should be displayed visually.
435 *
436 * @param items
437 * the array of contributin items
438 * @return the number of rows
439 */
440 private int getNumRows(IContributionItem[] items) {
441 int numRows = 1;
442 bool separatorFound = false;
443 for (int i = 0; i < items.length; i++) {
444 if (items[i].isSeparator()) {
445 separatorFound = true;
446 }
447 if ((separatorFound) && (items[i].isVisible())
448 && (!items[i].isGroupMarker()) && (!items[i].isSeparator())) {
449 numRows++;
450 separatorFound = false;
451 }
452 }
453 return numRows;
454 }
455
456 /*
457 * (non-Javadoc)
458 *
459 * @see org.eclipse.jface.action.ICoolBarManager#getStyle()
460 */
461 public int getStyle() {
462 return itemStyle;
463 }
464
465 /**
466 * Subclasses may extend this <code>ContributionManager</code> method,
467 * but must call <code>super.itemAdded</code>.
468 *
469 * @see org.eclipse.jface.action.ContributionManager#itemAdded(org.eclipse.jface.action.IContributionItem)
470 */
471 protected override void itemAdded(IContributionItem item) {
472 Assert.isNotNull(cast(Object)item);
473 super.itemAdded(item);
474 int insertedAt = indexOf(item);
475 bool replaced = false;
476 final int size = cbItemsCreationOrder.size();
477 for (int i = 0; i < size; i++) {
478 IContributionItem created = cast(IContributionItem) cbItemsCreationOrder
479 .get(i);
480 if (created.getId() !is null && created.getId().equals(item.getId())) {
481 cbItemsCreationOrder.set(i, cast(Object) item);
482 replaced = true;
483 break;
484 }
485 }
486
487 if (!replaced) {
488 cbItemsCreationOrder.add(Math.min(Math.max(insertedAt, 0),
489 cbItemsCreationOrder.size()), cast(Object) item);
490 }
491 }
492
493 /**
494 * Subclasses may extend this <code>ContributionManager</code> method,
495 * but must call <code>super.itemRemoved</code>.
496 *
497 * @see org.eclipse.jface.action.ContributionManager#itemRemoved(org.eclipse.jface.action.IContributionItem)
498 */
499 protected override void itemRemoved(IContributionItem item) {
500 Assert.isNotNull(cast(Object)item);
501 super.itemRemoved(item);
502 CoolItem coolItem = findCoolItem(item);
503 if (coolItem !is null) {
504 coolItem.setData(null);
505 }
506 }
507
508 /**
509 * Positions the list iterator to the starting of the next row. By calling
510 * next on the returned iterator, it will return the first element of the
511 * next row.
512 *
513 * @param iterator
514 * the list iterator of contribution items
515 * @param ignoreCurrentItem
516 * Whether the current item in the iterator should be considered
517 * (as well as subsequent items).
518 */
519 private void nextRow(ListIterator iterator, bool ignoreCurrentItem) {
520
521 IContributionItem currentElement = null;
522 if (!ignoreCurrentItem && iterator.hasPrevious()) {
523 currentElement = cast(IContributionItem) iterator.previous();
524 iterator.next();
525 }
526
527 if ((currentElement !is null) && (currentElement.isSeparator())) {
528 collapseSeparators(iterator);
529 return;
530 }
531
532 //Find next separator
533 while (iterator.hasNext()) {
534 IContributionItem item = cast(IContributionItem) iterator.next();
535 if (item.isSeparator()) {
536 // we we find a separator, collapse any consecutive
537 // separators
538 // and return
539 collapseSeparators(iterator);
540 return;
541 }
542 }
543 }
544
545 /*
546 * Used for debuging. Prints all the items in the internal structures.
547 */
548 // private void printContributions(ArrayList contributionList) {
549 // int index = 0;
550 // System.out.println("----------------------------------\n"); //$NON-NLS-1$
551 // for (Iterator i = contributionList.iterator(); i.hasNext(); index++) {
552 // IContributionItem item = (IContributionItem) i.next();
553 // if (item.isSeparator()) {
554 // System.out.println("Separator"); //$NON-NLS-1$
555 // } else {
556 // System.out.println(index + ". Item id: " + item.getId() //$NON-NLS-1$
557 // + " - is Visible: " //$NON-NLS-1$
558 // + item.isVisible());
559 // }
560 // }
561 // }
562 /**
563 * Synchronizes the visual order of the cool items in the control with this
564 * manager's internal data structures. This method should be called before
565 * requesting the order of the contribution items to ensure that the order
566 * is accurate.
567 * <p>
568 * Note that <code>update()</code> and <code>refresh()</code> are
569 * converses: <code>update()</code> changes the visual order to match the
570 * internal structures, and <code>refresh</code> changes the internal
571 * structures to match the visual order.
572 * </p>
573 */
574 public void refresh() {
575 if (!coolBarExist()) {
576 return;
577 }
578
579 // Retreives the list of contribution items as an array list
580 auto contributionList = getItemList();
581
582 // Check the size of the list
583 if (contributionList.size() is 0) {
584 return;
585 }
586
587 // The list of all the cool items in their visual order
588 CoolItem[] coolItems = coolBar.getItems();
589 // The wrap indicies of the coolbar
590 int[] wrapIndicies = getAdjustedWrapIndices(coolBar.getWrapIndices());
591
592 int row = 0;
593 int coolItemIndex = 0;
594
595 // Traverse through all cool items in the coolbar add them to a new
596 // data structure
597 // in the correct order
598 auto displayedItems = new ArrayList(coolBar.getItemCount());
599 for (int i = 0; i < coolItems.length; i++) {
600 CoolItem coolItem = coolItems[i];
601 if ( auto cbItem = cast(IContributionItem) coolItem.getData() ) {
602 displayedItems.add(Math.min(i, displayedItems.size()), cast(Object) cbItem);
603 }
604 }
605
606 // Add separators to the displayed Items data structure
607 int offset = 0;
608 for (int i = 1; i < wrapIndicies.length; i++) {
609 int insertAt = wrapIndicies[i] + offset;
610 displayedItems.add(insertAt, new Separator(USER_SEPARATOR));
611 offset++;
612 }
613
614 // Determine which rows are invisible
615 auto existingVisibleRows = new ArrayList(4);
616 ListIterator rowIterator = contributionList.listIterator();
617 collapseSeparators(rowIterator);
618 int numRow = 0;
619 while (rowIterator.hasNext()) {
620 // Scan row
621 while (rowIterator.hasNext()) {
622 IContributionItem cbItem = cast(IContributionItem) rowIterator
623 .next();
624 if (displayedItems.contains(cast(Object) cbItem)) {
625 existingVisibleRows.add(new Integer(numRow));
626 break;
627 }
628 if (cbItem.isSeparator()) {
629 break;
630 }
631 }
632 nextRow(rowIterator, false);
633 numRow++;
634 }
635
636 auto existingRows = existingVisibleRows.iterator();
637 // Adjust row number to the first visible
638 if (existingRows.hasNext()) {
639 row = (cast(Integer) existingRows.next()).intValue();
640 }
641
642 auto itemLocation = new HashMap();
643 for (ListIterator locationIterator = displayedItems.listIterator(); locationIterator
644 .hasNext();) {
645 IContributionItem item = cast(IContributionItem) locationIterator
646 .next();
647 if (item.isSeparator()) {
648 if (existingRows.hasNext()) {
649 Integer value = cast(Integer) existingRows.next();
650 row = value.intValue();
651 } else {
652 row++;
653 }
654 } else {
655 itemLocation.put(cast(Object)item, new Integer(row));
656 }
657
658 }
659
660 // Insert the contribution items in their correct location
661 for (ListIterator iterator = displayedItems.listIterator(); iterator
662 .hasNext();) {
663 IContributionItem cbItem = cast(IContributionItem) iterator.next();
664 if (cbItem.isSeparator()) {
665 coolItemIndex = 0;
666 } else {
667 relocate(cbItem, coolItemIndex, contributionList, itemLocation);
668 cbItem.saveWidgetState();
669 coolItemIndex++;
670 }
671 }
672
673 if (contributionList.size() !is 0) {
674 contributionList = adjustContributionList(contributionList);
675 IContributionItem[] array = arraycast!(IContributionItem)( contributionList.toArray());
676 internalSetItems(array);
677 }
678
679 }
680
681 /**
682 * Relocates the given contribution item to the specified index.
683 *
684 * @param cbItem
685 * the conribution item to relocate
686 * @param index
687 * the index to locate this item
688 * @param contributionList
689 * the current list of conrtributions
690 * @param itemLocation
691 */
692 private void relocate(IContributionItem cbItem, int index,
693 ArrayList contributionList, HashMap itemLocation) {
694
695 if (!(cast(Integer)itemLocation.get(cast(Object)cbItem) )) {
696 return;
697 }
698 int targetRow = (cast(Integer) itemLocation.get(cast(Object)cbItem)).intValue();
699
700 int cbInternalIndex = contributionList.indexOf(cast(Object)cbItem);
701
702 // by default add to end of list
703 int insertAt = contributionList.size();
704 // Find the row to place this item in.
705 ListIterator iterator = contributionList.listIterator();
706 // bypass any separators at the begining
707 collapseSeparators(iterator);
708 int currentRow = -1;
709 while (iterator.hasNext()) {
710
711 currentRow++;
712 if (currentRow is targetRow) {
713 // We found the row to insert the item
714 int virtualIndex = 0;
715 insertAt = iterator.nextIndex();
716 // first check the position of the current element (item)
717 // then get the next element
718 while (iterator.hasNext()) {
719 IContributionItem item = cast(IContributionItem) iterator
720 .next();
721 Integer itemRow = cast(Integer) itemLocation.get( cast(Object) item);
722 if (item.isSeparator()) {
723 break;
724 }
725 // if the item has an associate widget
726 if ((itemRow !is null) && (itemRow.intValue() is targetRow)) {
727 // if the next element is the index we are looking for
728 // then break
729 if (virtualIndex >= index) {
730 break;
731 }
732 virtualIndex++;
733
734 }
735 insertAt++;
736 }
737 // If we don't need to move it then we return
738 if (cbInternalIndex is insertAt) {
739 return;
740 }
741 break;
742 }
743 nextRow(iterator, true);
744 }
745 contributionList.remove(cast(Object) cbItem);
746
747 // Adjust insertAt index
748 if (cbInternalIndex < insertAt) {
749 insertAt--;
750 }
751
752 // if we didn't find the row then add a new row
753 if (currentRow !is targetRow) {
754 contributionList.add(new Separator(USER_SEPARATOR));
755 insertAt = contributionList.size();
756 }
757 insertAt = Math.min(insertAt, contributionList.size());
758 contributionList.add(insertAt, cast(Object) cbItem);
759
760 }
761
762 /**
763 * Restores the canonical order of this cool bar manager. The canonical
764 * order is the order in which the contribution items where added.
765 */
766 public void resetItemOrder() {
767 for (ListIterator iterator = cbItemsCreationOrder.listIterator(); iterator
768 .hasNext();) {
769 IContributionItem item = cast(IContributionItem) iterator.next();
770 // if its a user separator then do not include in original order.
771 if ((item.getId() !is null) && (item.getId().equals(USER_SEPARATOR))) {
772 iterator.remove();
773 }
774 }
775 IContributionItem[] itemsToSet = arraycast!(IContributionItem)(cbItemsCreationOrder.toArray());
776 setItems(itemsToSet);
777 }
778
779 /*
780 * (non-Javadoc)
781 *
782 * @see org.eclipse.jface.action.ICoolBarManager#setContextMenuManager(org.eclipse.jface.action.IMenuManager)
783 */
784 public void setContextMenuManager(IMenuManager contextMenuManager) {
785 this.contextMenuManager = cast(MenuManager) contextMenuManager;
786 if (coolBar !is null) {
787 coolBar.setMenu(getContextMenuControl());
788 }
789 }
790
791 /**
792 * Replaces the current items with the given items.
793 * Forces an update.
794 *
795 * @param newItems the items with which to replace the current items
796 */
797 public void setItems(IContributionItem[] newItems) {
798 // dispose of all the cool items on the cool bar manager
799 if (coolBar !is null) {
800 CoolItem[] coolItems = coolBar.getItems();
801 for (int i = 0; i < coolItems.length; i++) {
802 dispose(coolItems[i]);
803 }
804 }
805 // Set the internal structure to this order
806 internalSetItems(newItems);
807 // Force and update
808 update(true);
809 }
810
811 /*
812 * (non-Javadoc)
813 *
814 * @see org.eclipse.jface.action.ICoolBarManager#lockLayout(bool)
815 */
816 public void setLockLayout(bool value) {
817 if (!coolBarExist()) {
818 return;
819 }
820 coolBar.setLocked(value);
821 }
822
823 /**
824 * Subclasses may extend this <code>IContributionManager</code> method,
825 * but must call <code>super.update</code>.
826 *
827 * @see org.eclipse.jface.action.IContributionManager#update(bool)
828 */
829 public void update(bool force) {
830 if ((!isDirty() && !force) || (!coolBarExist())) {
831 return;
832 }
833
834 bool relock = false;
835 bool changed = false;
836
837 try {
838 coolBar.setRedraw(false);
839
840 // Refresh the widget data with the internal data structure.
841 refresh();
842
843 if (coolBar.getLocked()) {
844 coolBar.setLocked(false);
845 relock = true;
846 }
847
848 /*
849 * Make a list of items including only those items that are
850 * visible. Separators should stay because they mark line breaks in
851 * a cool bar.
852 */
853 IContributionItem[] items = getItems();
854 List visibleItems = new ArrayList(items.length);
855 for (int i = 0; i < items.length; i++) {
856 IContributionItem item = items[i];
857 if (item.isVisible()) {
858 visibleItems.add(cast(Object)item);
859 }
860 }
861
862 /*
863 * Make a list of CoolItem widgets in the cool bar for which there
864 * is no current visible contribution item. These are the widgets
865 * to be disposed. Dynamic items are also removed.
866 */
867 CoolItem[] coolItems = coolBar.getItems();
868 ArrayList coolItemsToRemove = new ArrayList(coolItems.length);
869 for (int i = 0; i < coolItems.length; i++) {
870 Object data = coolItems[i].getData();
871 if ((data is null)
872 || (!visibleItems.contains(data))
873 || ((cast(IContributionItem)data ) && (cast(IContributionItem) data)
874 .isDynamic())) {
875 coolItemsToRemove.add(coolItems[i]);
876 }
877 }
878
879 // Dispose of any items in the list to be removed.
880 for (int i = coolItemsToRemove.size() - 1; i >= 0; i--) {
881 CoolItem coolItem = cast(CoolItem) coolItemsToRemove.get(i);
882 if (!coolItem.isDisposed()) {
883 Control control = coolItem.getControl();
884 if (control !is null) {
885 coolItem.setControl(null);
886 control.dispose();
887 }
888 coolItem.dispose();
889 }
890 }
891
892 // Add any new items by telling them to fill.
893 coolItems = coolBar.getItems();
894 IContributionItem sourceItem;
895 IContributionItem destinationItem;
896 int sourceIndex = 0;
897 int destinationIndex = 0;
898 Iterator visibleItemItr = visibleItems.iterator();
899 while (visibleItemItr.hasNext()) {
900 sourceItem = cast(IContributionItem) visibleItemItr.next();
901
902 // Retrieve the corresponding contribution item from SWT's
903 // data.
904 if (sourceIndex < coolItems.length) {
905 destinationItem = cast(IContributionItem) coolItems[sourceIndex]
906 .getData();
907 } else {
908 destinationItem = null;
909 }
910
911 // The items match is they are equal or both separators.
912 if (destinationItem !is null) {
913 if ((cast(Object)sourceItem).opEquals(cast(Object)destinationItem)) {
914 sourceIndex++;
915 destinationIndex++;
916 sourceItem.update();
917 continue;
918
919 } else if ((destinationItem.isSeparator())
920 && (sourceItem.isSeparator())) {
921 coolItems[sourceIndex].setData(cast(Object)sourceItem);
922 sourceIndex++;
923 destinationIndex++;
924 sourceItem.update();
925 continue;
926
927 }
928 }
929
930 // Otherwise, a new item has to be added.
931 int start = coolBar.getItemCount();
932 sourceItem.fill(coolBar, destinationIndex);
933 int newItems = coolBar.getItemCount() - start;
934 for (int i = 0; i < newItems; i++) {
935 coolBar.getItem(destinationIndex++).setData(cast(Object)sourceItem);
936 }
937 changed = true;
938 }
939
940 // Remove any old widgets not accounted for.
941 for (int i = coolItems.length - 1; i >= sourceIndex; i--) {
942 final CoolItem item = coolItems[i];
943 if (!item.isDisposed()) {
944 Control control = item.getControl();
945 if (control !is null) {
946 item.setControl(null);
947 control.dispose();
948 }
949 item.dispose();
950 changed = true;
951 }
952 }
953
954 // Update wrap indices.
955 updateWrapIndices();
956
957 // Update the sizes.
958 for (int i = 0; i < items.length; i++) {
959 IContributionItem item = items[i];
960 item.update(SIZE);
961 }
962
963 // if the coolBar was previously locked then lock it
964 if (relock) {
965 coolBar.setLocked(true);
966 }
967
968 if (changed) {
969 updateTabOrder();
970 }
971
972 // We are no longer dirty.
973 setDirty(false);
974 } finally {
975 coolBar.setRedraw(true);
976 }
977 }
978
979 /**
980 * Sets the tab order of the coolbar to the visual order of its items.
981 */
982 /* package */void updateTabOrder() {
983 if (coolBar !is null) {
984 CoolItem[] items = coolBar.getItems();
985 if (items !is null) {
986 ArrayList children = new ArrayList(items.length);
987 for (int i = 0; i < items.length; i++) {
988 if ((items[i].getControl() !is null)
989 && (!items[i].getControl().isDisposed())) {
990 children.add(items[i].getControl());
991 }
992 }
993 // Convert array
994 Control[] childrenArray;
995 childrenArray = arraycast!(Control)(children.toArray());
996
997 if (childrenArray !is null) {
998 coolBar.setTabList(childrenArray);
999 }
1000
1001 }
1002 }
1003 }
1004
1005 /**
1006 * Updates the indices at which the cool bar should wrap.
1007 */
1008 private void updateWrapIndices() {
1009 final IContributionItem[] items = getItems();
1010 final int numRows = getNumRows(items) - 1;
1011
1012 // Generate the list of wrap indices.
1013 final int[] wrapIndices = new int[numRows];
1014 bool foundSeparator = false;
1015 int j = 0;
1016 CoolItem[] coolItems = (coolBar is null) ? null : coolBar.getItems();
1017
1018 for (int i = 0; i < items.length; i++) {
1019 IContributionItem item = items[i];
1020 CoolItem coolItem = findCoolItem(coolItems, item);
1021 if (item.isSeparator()) {
1022 foundSeparator = true;
1023 }
1024 if ((!item.isSeparator()) && (!item.isGroupMarker())
1025 && (item.isVisible()) && (coolItem !is null)
1026 && (foundSeparator)) {
1027 wrapIndices[j] = coolBar.indexOf(coolItem);
1028 j++;
1029 foundSeparator = false;
1030 }
1031 }
1032
1033 /*
1034 * Check to see if these new wrap indices are different than the old
1035 * ones.
1036 */
1037 final int[] oldIndices = coolBar.getWrapIndices();
1038 bool shouldUpdate = false;
1039 if (oldIndices.length is wrapIndices.length) {
1040 for (int i = 0; i < oldIndices.length; i++) {
1041 if (oldIndices[i] !is wrapIndices[i]) {
1042 shouldUpdate = true;
1043 break;
1044 }
1045 }
1046 } else {
1047 shouldUpdate = true;
1048 }
1049
1050 if (shouldUpdate) {
1051 coolBar.setWrapIndices(wrapIndices);
1052 }
1053 }
1054 }