Mercurial > projects > dwt2
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 } |