Mercurial > projects > dwt2
comparison org.eclipse.jface/src/org/eclipse/jface/action/MenuManager.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 |
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 * Remy Chi Jian Suen <remy.suen@gmail.com> - Bug 12116 [Contributions] widgets: MenuManager.setImageDescriptor() method needed | |
11 * Port to the D programming language: | |
12 * Frank Benoit <benoit@tionex.de> | |
13 *******************************************************************************/ | |
14 module org.eclipse.jface.action.MenuManager; | |
15 | |
16 import org.eclipse.jface.action.ContributionManager; | |
17 import org.eclipse.jface.action.IMenuManager; | |
18 import org.eclipse.jface.action.IContributionManagerOverrides; | |
19 import org.eclipse.jface.action.IContributionManager; | |
20 import org.eclipse.jface.action.IMenuListener; | |
21 import org.eclipse.jface.action.IMenuListener2; | |
22 import org.eclipse.jface.action.IContributionItem; | |
23 import org.eclipse.jface.action.SubContributionItem; | |
24 import org.eclipse.jface.action.IAction; | |
25 import org.eclipse.jface.action.ExternalActionManager; | |
26 | |
27 | |
28 import org.eclipse.swt.SWT; | |
29 import org.eclipse.swt.events.MenuAdapter; | |
30 import org.eclipse.swt.events.MenuEvent; | |
31 import org.eclipse.swt.widgets.Composite; | |
32 import org.eclipse.swt.widgets.Control; | |
33 import org.eclipse.swt.widgets.CoolBar; | |
34 import org.eclipse.swt.widgets.Decorations; | |
35 import org.eclipse.swt.widgets.Item; | |
36 import org.eclipse.swt.widgets.Menu; | |
37 import org.eclipse.swt.widgets.MenuItem; | |
38 import org.eclipse.swt.widgets.Shell; | |
39 import org.eclipse.swt.widgets.ToolBar; | |
40 import org.eclipse.core.runtime.ListenerList; | |
41 import org.eclipse.jface.resource.ImageDescriptor; | |
42 import org.eclipse.jface.resource.JFaceResources; | |
43 import org.eclipse.jface.resource.LocalResourceManager; | |
44 | |
45 import java.lang.all; | |
46 import java.util.List; | |
47 import java.util.ArrayList; | |
48 import java.util.Iterator; | |
49 import java.util.Set; | |
50 | |
51 | |
52 /** | |
53 * A menu manager is a contribution manager which realizes itself and its items | |
54 * in a menu control; either as a menu bar, a sub-menu, or a context menu. | |
55 * <p> | |
56 * This class may be instantiated; it may also be subclassed. | |
57 * </p> | |
58 */ | |
59 public class MenuManager : ContributionManager, IMenuManager { | |
60 | |
61 public bool isDirty(){ | |
62 return super.isDirty(); | |
63 } | |
64 | |
65 /** | |
66 * The menu id. | |
67 */ | |
68 private String id; | |
69 | |
70 /** | |
71 * List of registered menu listeners (element type: <code>IMenuListener</code>). | |
72 */ | |
73 private ListenerList listeners; | |
74 | |
75 /** | |
76 * The menu control; <code>null</code> before | |
77 * creation and after disposal. | |
78 */ | |
79 private Menu menu = null; | |
80 | |
81 /** | |
82 * The menu item widget; <code>null</code> before | |
83 * creation and after disposal. This field is used | |
84 * when this menu manager is a sub-menu. | |
85 */ | |
86 private MenuItem menuItem; | |
87 | |
88 /** | |
89 * The text for a sub-menu. | |
90 */ | |
91 private String menuText; | |
92 | |
93 /** | |
94 * The image for a sub-menu. | |
95 */ | |
96 private ImageDescriptor image; | |
97 | |
98 /** | |
99 * A resource manager to remember all of the images that have been used by this menu. | |
100 */ | |
101 private LocalResourceManager imageManager; | |
102 | |
103 /** | |
104 * The overrides for items of this manager | |
105 */ | |
106 private IContributionManagerOverrides overrides; | |
107 | |
108 /** | |
109 * The parent contribution manager. | |
110 */ | |
111 private IContributionManager parent; | |
112 | |
113 /** | |
114 * Indicates whether <code>removeAll</code> should be | |
115 * called just before the menu is displayed. | |
116 */ | |
117 private bool removeAllWhenShown = false; | |
118 | |
119 /** | |
120 * Indicates this item is visible in its manager; <code>true</code> | |
121 * by default. | |
122 * @since 3.3 | |
123 */ | |
124 protected bool visible = true; | |
125 | |
126 /** | |
127 * allows a submenu to display a shortcut key. This is often used with the | |
128 * QuickMenu command or action which can pop up a menu using the shortcut. | |
129 */ | |
130 private String definitionId = null; | |
131 | |
132 /** | |
133 * Creates a menu manager. The text and id are <code>null</code>. | |
134 * Typically used for creating a context menu, where it doesn't need to be referred to by id. | |
135 */ | |
136 public this() { | |
137 this(null, null, null); | |
138 } | |
139 | |
140 /** | |
141 * Creates a menu manager with the given text. The id of the menu | |
142 * is <code>null</code>. | |
143 * Typically used for creating a sub-menu, where it doesn't need to be referred to by id. | |
144 * | |
145 * @param text the text for the menu, or <code>null</code> if none | |
146 */ | |
147 public this(String text) { | |
148 this(text, null, null); | |
149 } | |
150 | |
151 /** | |
152 * Creates a menu manager with the given text and id. | |
153 * Typically used for creating a sub-menu, where it needs to be referred to by id. | |
154 * | |
155 * @param text the text for the menu, or <code>null</code> if none | |
156 * @param id the menu id, or <code>null</code> if it is to have no id | |
157 */ | |
158 public this(String text, String id) { | |
159 this(text, null, id); | |
160 } | |
161 | |
162 /** | |
163 * Creates a menu manager with the given text, image, and id. | |
164 * Typically used for creating a sub-menu, where it needs to be referred to by id. | |
165 * | |
166 * @param text the text for the menu, or <code>null</code> if none | |
167 * @param image the image for the menu, or <code>null</code> if none | |
168 * @param id the menu id, or <code>null</code> if it is to have no id | |
169 * @since 3.4 | |
170 */ | |
171 public this(String text, ImageDescriptor image, String id) { | |
172 listeners = new ListenerList(); | |
173 this.menuText = text; | |
174 this.image = image; | |
175 this.id = id; | |
176 } | |
177 | |
178 /* (non-Javadoc) | |
179 * @see org.eclipse.jface.action.IMenuManager#addMenuListener(org.eclipse.jface.action.IMenuListener) | |
180 */ | |
181 public void addMenuListener(IMenuListener listener) { | |
182 listeners.add(cast(Object)listener); | |
183 } | |
184 | |
185 /** | |
186 * Creates and returns an SWT context menu control for this menu, | |
187 * and installs all registered contributions. | |
188 * Does not create a new control if one already exists. | |
189 * <p> | |
190 * Note that the menu is not expected to be dynamic. | |
191 * </p> | |
192 * | |
193 * @param parent the parent control | |
194 * @return the menu control | |
195 */ | |
196 public Menu createContextMenu(Control parent) { | |
197 if (!menuExist()) { | |
198 menu = new Menu(parent); | |
199 initializeMenu(); | |
200 } | |
201 return menu; | |
202 } | |
203 | |
204 /** | |
205 * Creates and returns an SWT menu bar control for this menu, | |
206 * for use in the given <code>Decorations</code>, and installs all registered | |
207 * contributions. Does not create a new control if one already exists. | |
208 * | |
209 * @param parent the parent decorations | |
210 * @return the menu control | |
211 * @since 2.1 | |
212 */ | |
213 public Menu createMenuBar(Decorations parent) { | |
214 if (!menuExist()) { | |
215 menu = new Menu(parent, SWT.BAR); | |
216 update(false); | |
217 } | |
218 return menu; | |
219 } | |
220 | |
221 /** | |
222 * Creates and returns an SWT menu bar control for this menu, for use in the | |
223 * given <code>Shell</code>, and installs all registered contributions. Does not | |
224 * create a new control if one already exists. This implementation simply calls | |
225 * the <code>createMenuBar(Decorations)</code> method | |
226 * | |
227 * @param parent the parent decorations | |
228 * @return the menu control | |
229 * @deprecated use <code>createMenuBar(Decorations)</code> instead. | |
230 */ | |
231 public Menu createMenuBar(Shell parent) { | |
232 return createMenuBar(cast(Decorations) parent); | |
233 } | |
234 | |
235 /** | |
236 * Disposes of this menu manager and frees all allocated SWT resources. | |
237 * Notifies all contribution items of the dispose. Note that this method does | |
238 * not clean up references between this menu manager and its associated | |
239 * contribution items. Use <code>removeAll</code> for that purpose. | |
240 */ | |
241 public void dispose() { | |
242 if (menuExist()) { | |
243 menu.dispose(); | |
244 } | |
245 menu = null; | |
246 | |
247 if (menuItem !is null) { | |
248 menuItem.dispose(); | |
249 menuItem = null; | |
250 } | |
251 | |
252 disposeOldImages(); | |
253 | |
254 IContributionItem[] items = getItems(); | |
255 for (int i = 0; i < items.length; i++) { | |
256 items[i].dispose(); | |
257 } | |
258 | |
259 markDirty(); | |
260 } | |
261 | |
262 /* (non-Javadoc) | |
263 * @see org.eclipse.jface.action.IContributionItem#fill(org.eclipse.swt.widgets.Composite) | |
264 */ | |
265 public void fill(Composite parent) { | |
266 } | |
267 | |
268 /* (non-Javadoc) | |
269 * @see org.eclipse.jface.action.IContributionItem#fill(org.eclipse.swt.widgets.CoolBar, int) | |
270 */ | |
271 public void fill(CoolBar parent, int index) { | |
272 } | |
273 | |
274 /* (non-Javadoc) | |
275 * @see org.eclipse.jface.action.IContributionItem#fill(org.eclipse.swt.widgets.Menu, int) | |
276 */ | |
277 public void fill(Menu parent, int index) { | |
278 if (menuItem is null || menuItem.isDisposed()) { | |
279 if (index >= 0) { | |
280 menuItem = new MenuItem(parent, SWT.CASCADE, index); | |
281 } else { | |
282 menuItem = new MenuItem(parent, SWT.CASCADE); | |
283 } | |
284 | |
285 menuItem.setText(getMenuText()); | |
286 | |
287 if (image !is null) { | |
288 LocalResourceManager localManager = new LocalResourceManager( | |
289 JFaceResources.getResources()); | |
290 menuItem.setImage(localManager.createImage(image)); | |
291 disposeOldImages(); | |
292 imageManager = localManager; | |
293 } | |
294 | |
295 if (!menuExist()) { | |
296 menu = new Menu(parent); | |
297 } | |
298 | |
299 menuItem.setMenu(menu); | |
300 | |
301 initializeMenu(); | |
302 | |
303 setDirty(true); | |
304 } | |
305 } | |
306 | |
307 /* (non-Javadoc) | |
308 * @see org.eclipse.jface.action.IContributionItem#fill(org.eclipse.swt.widgets.ToolBar, int) | |
309 */ | |
310 public void fill(ToolBar parent, int index) { | |
311 } | |
312 | |
313 /* (non-Javadoc) | |
314 * @see org.eclipse.jface.action.IMenuManager#findMenuUsingPath(java.lang.String) | |
315 */ | |
316 public IMenuManager findMenuUsingPath(String path) { | |
317 IContributionItem item = findUsingPath(path); | |
318 if (auto mm = cast(IMenuManager)item ) { | |
319 return mm; | |
320 } | |
321 return null; | |
322 } | |
323 | |
324 /* (non-Javadoc) | |
325 * @see org.eclipse.jface.action.IMenuManager#findUsingPath(java.lang.String) | |
326 */ | |
327 public IContributionItem findUsingPath(String path) { | |
328 String id = path; | |
329 String rest = null; | |
330 int separator = java.lang.all.indexOf( path, '/'); | |
331 if (separator !is -1) { | |
332 id = path.substring(0, separator); | |
333 rest = path.substring(separator + 1); | |
334 } else { | |
335 return super.find(path); | |
336 } | |
337 | |
338 IContributionItem item = super.find(id); | |
339 if (auto manager = cast(IMenuManager)item ) { | |
340 return manager.findUsingPath(rest); | |
341 } | |
342 return null; | |
343 } | |
344 | |
345 /** | |
346 * Notifies any menu listeners that a menu is about to show. | |
347 * Only listeners registered at the time this method is called are notified. | |
348 * | |
349 * @param manager the menu manager | |
350 * | |
351 * @see IMenuListener#menuAboutToShow | |
352 */ | |
353 private void fireAboutToShow(IMenuManager manager) { | |
354 Object[] listeners = this.listeners.getListeners(); | |
355 for (int i = 0; i < listeners.length; ++i) { | |
356 (cast(IMenuListener) listeners[i]).menuAboutToShow(manager); | |
357 } | |
358 } | |
359 | |
360 /** | |
361 * Notifies any menu listeners that a menu is about to hide. | |
362 * Only listeners registered at the time this method is called are notified. | |
363 * | |
364 * @param manager the menu manager | |
365 * | |
366 */ | |
367 private void fireAboutToHide(IMenuManager manager) { | |
368 final Object[] listeners = this.listeners.getListeners(); | |
369 for (int i = 0; i < listeners.length; ++i) { | |
370 final Object listener = listeners[i]; | |
371 if (auto listener2 = cast(IMenuListener2)listener) { | |
372 listener2.menuAboutToHide(manager); | |
373 } | |
374 } | |
375 } | |
376 | |
377 /** | |
378 * Returns the menu id. The menu id is used when creating a contribution | |
379 * item for adding this menu as a sub menu of another. | |
380 * | |
381 * @return the menu id | |
382 */ | |
383 public String getId() { | |
384 return id; | |
385 } | |
386 | |
387 /** | |
388 * Returns the SWT menu control for this menu manager. | |
389 * | |
390 * @return the menu control | |
391 */ | |
392 public Menu getMenu() { | |
393 return menu; | |
394 } | |
395 | |
396 /** | |
397 * Returns the text shown in the menu, potentially with a shortcut | |
398 * appended. | |
399 * | |
400 * @return the menu text | |
401 */ | |
402 public String getMenuText() { | |
403 if (definitionId is null) { | |
404 return menuText; | |
405 } | |
406 ExternalActionManager.ICallback callback = ExternalActionManager | |
407 .getInstance().getCallback(); | |
408 if (callback !is null) { | |
409 String shortCut = callback.getAcceleratorText(definitionId); | |
410 if (shortCut is null) { | |
411 return menuText; | |
412 } | |
413 return menuText ~ "\t" ~ shortCut; //$NON-NLS-1$ | |
414 } | |
415 return menuText; | |
416 } | |
417 | |
418 /** | |
419 * Returns the image for this menu as an image descriptor. | |
420 * | |
421 * @return the image, or <code>null</code> if this menu has no image | |
422 * @since 3.4 | |
423 */ | |
424 public ImageDescriptor getImageDescriptor() { | |
425 return image; | |
426 } | |
427 | |
428 /* (non-Javadoc) | |
429 * @see org.eclipse.jface.action.IContributionManager#getOverrides() | |
430 */ | |
431 public override IContributionManagerOverrides getOverrides() { | |
432 if (overrides is null) { | |
433 if (parent is null) { | |
434 overrides = new class IContributionManagerOverrides { | |
435 public Integer getAccelerator(IContributionItem item) { | |
436 return null; | |
437 } | |
438 | |
439 public String getAcceleratorText(IContributionItem item) { | |
440 return null; | |
441 } | |
442 | |
443 public Boolean getEnabled(IContributionItem item) { | |
444 return null; | |
445 } | |
446 | |
447 public String getText(IContributionItem item) { | |
448 return null; | |
449 } | |
450 }; | |
451 } else { | |
452 overrides = parent.getOverrides(); | |
453 } | |
454 super.setOverrides(overrides); | |
455 } | |
456 return overrides; | |
457 } | |
458 | |
459 /** | |
460 * Returns the parent contribution manager of this manger. | |
461 * | |
462 * @return the parent contribution manager | |
463 * @since 2.0 | |
464 */ | |
465 public IContributionManager getParent() { | |
466 return parent; | |
467 } | |
468 | |
469 /* (non-Javadoc) | |
470 * @see org.eclipse.jface.action.IMenuManager#getRemoveAllWhenShown() | |
471 */ | |
472 public bool getRemoveAllWhenShown() { | |
473 return removeAllWhenShown; | |
474 } | |
475 | |
476 /** | |
477 * Notifies all listeners that this menu is about to appear. | |
478 */ | |
479 private void handleAboutToShow() { | |
480 if (removeAllWhenShown) { | |
481 removeAll(); | |
482 } | |
483 fireAboutToShow(this); | |
484 update(false, false); | |
485 } | |
486 | |
487 /** | |
488 * Notifies all listeners that this menu is about to disappear. | |
489 */ | |
490 private void handleAboutToHide() { | |
491 fireAboutToHide(this); | |
492 } | |
493 | |
494 /** | |
495 * Initializes the menu control. | |
496 */ | |
497 private void initializeMenu() { | |
498 menu.addMenuListener(new class MenuAdapter { | |
499 public void menuHidden(MenuEvent e) { | |
500 // ApplicationWindow.resetDescription(e.widget); | |
501 handleAboutToHide(); | |
502 } | |
503 | |
504 public void menuShown(MenuEvent e) { | |
505 handleAboutToShow(); | |
506 } | |
507 }); | |
508 // Don't do an update(true) here, in case menu is never opened. | |
509 // Always do it lazily in handleAboutToShow(). | |
510 } | |
511 | |
512 /* (non-Javadoc) | |
513 * @see org.eclipse.jface.action.IContributionItem#isDynamic() | |
514 */ | |
515 public bool isDynamic() { | |
516 return false; | |
517 } | |
518 | |
519 /** | |
520 * Returns whether this menu should be enabled or not. | |
521 * Used to enable the menu item containing this menu when it is realized as a sub-menu. | |
522 * <p> | |
523 * The default implementation of this framework method | |
524 * returns <code>true</code>. Subclasses may reimplement. | |
525 * </p> | |
526 * | |
527 * @return <code>true</code> if enabled, and | |
528 * <code>false</code> if disabled | |
529 */ | |
530 public bool isEnabled() { | |
531 return true; | |
532 } | |
533 | |
534 /* (non-Javadoc) | |
535 * @see org.eclipse.jface.action.IContributionItem#isGroupMarker() | |
536 */ | |
537 public bool isGroupMarker() { | |
538 return false; | |
539 } | |
540 | |
541 /* (non-Javadoc) | |
542 * @see org.eclipse.jface.action.IContributionItem#isSeparator() | |
543 */ | |
544 public bool isSeparator() { | |
545 return false; | |
546 } | |
547 | |
548 /** | |
549 * Check if the contribution is item is a subsitute for ourselves | |
550 * | |
551 * @param item the contribution item | |
552 * @return <code>true</code> if give item is a substitution for ourselves | |
553 * @deprecated this method is no longer a part of the | |
554 * {@link org.eclipse.jface.action.IContributionItem} API. | |
555 */ | |
556 public bool isSubstituteFor(IContributionItem item) { | |
557 return this.opEquals(cast(Object)item) !is 0; | |
558 } | |
559 | |
560 /* (non-Javadoc) | |
561 * @see org.eclipse.jface.action.IContributionItem#isVisible() | |
562 */ | |
563 public bool isVisible() { | |
564 if (!visible) { | |
565 return false; // short circuit calculations in this case | |
566 } | |
567 | |
568 if (removeAllWhenShown) { | |
569 // we have no way of knowing if the menu has children | |
570 return true; | |
571 } | |
572 | |
573 // menus aren't visible if all of its children are invisible (or only contains visible separators). | |
574 IContributionItem[] childItems = getItems(); | |
575 bool visibleChildren = false; | |
576 for (int j = 0; j < childItems.length; j++) { | |
577 if (childItems[j].isVisible() && !childItems[j].isSeparator()) { | |
578 visibleChildren = true; | |
579 break; | |
580 } | |
581 } | |
582 | |
583 return visibleChildren; | |
584 } | |
585 | |
586 | |
587 /** | |
588 * The <code>MenuManager</code> implementation of this <code>ContributionManager</code> method | |
589 * also propagates the dirty flag up the parent chain. | |
590 * | |
591 * @since 3.1 | |
592 */ | |
593 public override void markDirty() { | |
594 super.markDirty(); | |
595 // Can't optimize by short-circuiting when the first dirty manager is encountered, | |
596 // since non-visible children are not even processed. | |
597 // That is, it's possible to have a dirty sub-menu under a non-dirty parent menu | |
598 // even after the parent menu has been updated. | |
599 // If items are added/removed in the sub-menu, we still need to propagate the dirty flag up, | |
600 // even if the sub-menu is already dirty, since the result of isVisible() may change | |
601 // due to the added/removed items. | |
602 IContributionManager parent = getParent(); | |
603 if (parent !is null) { | |
604 parent.markDirty(); | |
605 } | |
606 } | |
607 | |
608 /** | |
609 * Returns whether the menu control is created | |
610 * and not disposed. | |
611 * | |
612 * @return <code>true</code> if the control is created | |
613 * and not disposed, <code>false</code> otherwise | |
614 * @since 3.4 protected, was added in 3.1 as private method | |
615 */ | |
616 protected bool menuExist() { | |
617 return menu !is null && !menu.isDisposed(); | |
618 } | |
619 | |
620 /* (non-Javadoc) | |
621 * @see org.eclipse.jface.action.IMenuManager#removeMenuListener(org.eclipse.jface.action.IMenuListener) | |
622 */ | |
623 public void removeMenuListener(IMenuListener listener) { | |
624 listeners.remove(cast(Object)listener); | |
625 } | |
626 | |
627 /* (non-Javadoc) | |
628 * @see org.eclipse.jface.action.IContributionItem#saveWidgetState() | |
629 */ | |
630 public void saveWidgetState() { | |
631 } | |
632 | |
633 /** | |
634 * Sets the overrides for this contribution manager | |
635 * | |
636 * @param newOverrides the overrides for the items of this manager | |
637 * @since 2.0 | |
638 */ | |
639 public override void setOverrides(IContributionManagerOverrides newOverrides) { | |
640 overrides = newOverrides; | |
641 super.setOverrides(overrides); | |
642 } | |
643 | |
644 /* (non-Javadoc) | |
645 * @see org.eclipse.jface.action.IContributionItem#setParent(org.eclipse.jface.action.IContributionManager) | |
646 */ | |
647 public void setParent(IContributionManager manager) { | |
648 parent = manager; | |
649 } | |
650 | |
651 /* (non-Javadoc) | |
652 * @see org.eclipse.jface.action.IMenuManager#setRemoveAllWhenShown(bool) | |
653 */ | |
654 public void setRemoveAllWhenShown(bool removeAll) { | |
655 this.removeAllWhenShown = removeAll; | |
656 } | |
657 | |
658 /* (non-Javadoc) | |
659 * @see org.eclipse.jface.action.IContributionItem#setVisible(bool) | |
660 */ | |
661 public void setVisible(bool visible) { | |
662 this.visible = visible; | |
663 } | |
664 | |
665 /** | |
666 * Sets the action definition id of this action. This simply allows the menu | |
667 * item text to include a short cut if available. It can be used to | |
668 * notify a user of a key combination that will open a quick menu. | |
669 * | |
670 * @param definitionId | |
671 * the command definition id | |
672 * @since 3.4 | |
673 */ | |
674 public void setActionDefinitionId(String definitionId) { | |
675 this.definitionId = definitionId; | |
676 } | |
677 | |
678 /* (non-Javadoc) | |
679 * @see org.eclipse.jface.action.IContributionItem#update() | |
680 */ | |
681 public void update() { | |
682 updateMenuItem(); | |
683 } | |
684 | |
685 /** | |
686 * The <code>MenuManager</code> implementation of this <code>IContributionManager</code> | |
687 * updates this menu, but not any of its submenus. | |
688 * | |
689 * @see #updateAll | |
690 */ | |
691 public void update(bool force) { | |
692 update(force, false); | |
693 } | |
694 | |
695 /** | |
696 * Get all the items from the implementation's widget. | |
697 * | |
698 * @return the menu items | |
699 * @since 3.4 | |
700 */ | |
701 protected Item[] getMenuItems() { | |
702 if (menu !is null) { | |
703 return menu.getItems(); | |
704 } | |
705 return null; | |
706 } | |
707 | |
708 /** | |
709 * Get an item from the implementation's widget. | |
710 * | |
711 * @param index | |
712 * of the item | |
713 * @return the menu item | |
714 * @since 3.4 | |
715 */ | |
716 protected Item getMenuItem(int index) { | |
717 if (menu !is null) { | |
718 return menu.getItem(index); | |
719 } | |
720 return null; | |
721 } | |
722 | |
723 /** | |
724 * Get the menu item count for the implementation's widget. | |
725 * | |
726 * @return the number of items | |
727 * @since 3.4 | |
728 */ | |
729 protected int getMenuItemCount() { | |
730 if (menu !is null) { | |
731 return menu.getItemCount(); | |
732 } | |
733 return 0; | |
734 } | |
735 | |
736 /** | |
737 * Call an <code>IContributionItem</code>'s fill method with the | |
738 * implementation's widget. The default is to use the <code>Menu</code> | |
739 * widget.<br> | |
740 * <code>fill(Menu menu, int index)</code> | |
741 * | |
742 * @param ci | |
743 * An <code>IContributionItem</code> whose <code>fill()</code> | |
744 * method should be called. | |
745 * @param index | |
746 * The position the <code>fill()</code> method should start | |
747 * inserting at. | |
748 * @since 3.4 | |
749 */ | |
750 protected void doItemFill(IContributionItem ci, int index) { | |
751 ci.fill(menu, index); | |
752 } | |
753 | |
754 /** | |
755 * Incrementally builds the menu from the contribution items. | |
756 * This method leaves out double separators and separators in the first | |
757 * or last position. | |
758 * | |
759 * @param force <code>true</code> means update even if not dirty, | |
760 * and <code>false</code> for normal incremental updating | |
761 * @param recursive <code>true</code> means recursively update | |
762 * all submenus, and <code>false</code> means just this menu | |
763 */ | |
764 protected void update(bool force, bool recursive) { | |
765 if (isDirty() || force) { | |
766 if (menuExist()) { | |
767 // clean contains all active items without double separators | |
768 IContributionItem[] items = getItems(); | |
769 List clean = new ArrayList(items.length); | |
770 IContributionItem separator = null; | |
771 for (int i = 0; i < items.length; ++i) { | |
772 IContributionItem ci = items[i]; | |
773 if (!ci.isVisible()) { | |
774 continue; | |
775 } | |
776 if (ci.isSeparator()) { | |
777 // delay creation until necessary | |
778 // (handles both adjacent separators, and separator at end) | |
779 separator = ci; | |
780 } else { | |
781 if (separator !is null) { | |
782 if (clean.size() > 0) { | |
783 clean.add(cast(Object)separator); | |
784 } | |
785 separator = null; | |
786 } | |
787 clean.add(cast(Object)ci); | |
788 } | |
789 } | |
790 | |
791 // remove obsolete (removed or non active) | |
792 Item[] mi = getMenuItems(); | |
793 | |
794 for (int i = 0; i < mi.length; i++) { | |
795 Object data = mi[i].getData(); | |
796 | |
797 if (data is null || !clean.contains(data)) { | |
798 mi[i].dispose(); | |
799 } else if (cast(IContributionItem)data | |
800 && (cast(IContributionItem) data).isDynamic() | |
801 && (cast(IContributionItem) data).isDirty()) { | |
802 mi[i].dispose(); | |
803 } | |
804 } | |
805 | |
806 // add new | |
807 mi = getMenuItems(); | |
808 int srcIx = 0; | |
809 int destIx = 0; | |
810 | |
811 for (Iterator e = clean.iterator(); e.hasNext();) { | |
812 IContributionItem src = cast(IContributionItem) e.next(); | |
813 IContributionItem dest; | |
814 | |
815 // get corresponding item in SWT widget | |
816 if (srcIx < mi.length) { | |
817 dest = cast(IContributionItem) mi[srcIx].getData(); | |
818 } else { | |
819 dest = null; | |
820 } | |
821 | |
822 if (dest !is null && (cast(Object)src).opEquals(cast(Object)dest)) { | |
823 srcIx++; | |
824 destIx++; | |
825 } else if (dest !is null && dest.isSeparator() | |
826 && src.isSeparator()) { | |
827 mi[srcIx].setData(cast(Object)src); | |
828 srcIx++; | |
829 destIx++; | |
830 } else { | |
831 int start = getMenuItemCount(); | |
832 doItemFill(src, destIx); | |
833 int newItems = getMenuItemCount() - start; | |
834 for (int i = 0; i < newItems; i++) { | |
835 Item item = getMenuItem(destIx++); | |
836 item.setData(cast(Object)src); | |
837 } | |
838 } | |
839 | |
840 // May be we can optimize this call. If the menu has just | |
841 // been created via the call src.fill(fMenuBar, destIx) then | |
842 // the menu has already been updated with update(true) | |
843 // (see MenuManager). So if force is true we do it again. But | |
844 // we can't set force to false since then information for the | |
845 // sub sub menus is lost. | |
846 if (recursive) { | |
847 IContributionItem item = src; | |
848 if ( auto sub = cast(SubContributionItem)item ) { | |
849 item = sub.getInnerItem(); | |
850 } | |
851 if (auto mm = cast(IMenuManager)item ) { | |
852 mm.updateAll(force); | |
853 } | |
854 } | |
855 | |
856 } | |
857 | |
858 // remove any old menu items not accounted for | |
859 for (; srcIx < mi.length; srcIx++) { | |
860 mi[srcIx].dispose(); | |
861 } | |
862 | |
863 setDirty(false); | |
864 } | |
865 } else { | |
866 // I am not dirty. Check if I must recursivly walk down the hierarchy. | |
867 if (recursive) { | |
868 IContributionItem[] items = getItems(); | |
869 for (int i = 0; i < items.length; ++i) { | |
870 IContributionItem ci = items[i]; | |
871 if ( auto mm = cast(IMenuManager) ci ) { | |
872 if (mm.isVisible()) { | |
873 mm.updateAll(force); | |
874 } | |
875 } | |
876 } | |
877 } | |
878 } | |
879 updateMenuItem(); | |
880 } | |
881 | |
882 /* (non-Javadoc) | |
883 * @see org.eclipse.jface.action.IContributionItem#update(java.lang.String) | |
884 */ | |
885 public void update(String property) { | |
886 IContributionItem items[] = getItems(); | |
887 | |
888 for (int i = 0; i < items.length; i++) { | |
889 items[i].update(property); | |
890 } | |
891 | |
892 if (menu !is null && !menu.isDisposed() && menu.getParentItem() !is null) { | |
893 if (IAction.TEXT.equals(property)) { | |
894 String text = getOverrides().getText(this); | |
895 | |
896 if (text is null) { | |
897 text = getMenuText(); | |
898 } | |
899 | |
900 if (text !is null) { | |
901 ExternalActionManager.ICallback callback = ExternalActionManager | |
902 .getInstance().getCallback(); | |
903 | |
904 if (callback !is null) { | |
905 int index = .indexOf( text, '&' ); // SWT collision with local indexOf | |
906 | |
907 if (index >= 0 && index < text.length - 1) { | |
908 | |
909 dchar character = CharacterToUpper(text | |
910 [index + 1 .. $].firstCodePoint()); | |
911 | |
912 if (callback.isAcceleratorInUse(SWT.ALT | character)) { | |
913 if (index is 0) { | |
914 text = text.substring(1); | |
915 } else { | |
916 text = text.substring(0, index) | |
917 ~ text.substring(index + 1); | |
918 } | |
919 } | |
920 } | |
921 } | |
922 | |
923 menu.getParentItem().setText(text); | |
924 } | |
925 } else if (IAction.IMAGE.equals(property) && image !is null) { | |
926 LocalResourceManager localManager = new LocalResourceManager(JFaceResources | |
927 .getResources()); | |
928 menu.getParentItem().setImage(localManager.createImage(image)); | |
929 disposeOldImages(); | |
930 imageManager = localManager; | |
931 } | |
932 } | |
933 } | |
934 | |
935 /** | |
936 * Dispose any images allocated for this menu | |
937 */ | |
938 private void disposeOldImages() { | |
939 if (imageManager !is null) { | |
940 imageManager.dispose(); | |
941 imageManager = null; | |
942 } | |
943 } | |
944 | |
945 /* (non-Javadoc) | |
946 * @see org.eclipse.jface.action.IMenuManager#updateAll(bool) | |
947 */ | |
948 public void updateAll(bool force) { | |
949 update(force, true); | |
950 } | |
951 | |
952 /** | |
953 * Updates the menu item for this sub menu. | |
954 * The menu item is disabled if this sub menu is empty. | |
955 * Does nothing if this menu is not a submenu. | |
956 */ | |
957 private void updateMenuItem() { | |
958 /* | |
959 * Commented out until proper solution to enablement of | |
960 * menu item for a sub-menu is found. See bug 30833 for | |
961 * more details. | |
962 * | |
963 if (menuItem !is null && !menuItem.isDisposed() && menuExist()) { | |
964 IContributionItem items[] = getItems(); | |
965 bool enabled = false; | |
966 for (int i = 0; i < items.length; i++) { | |
967 IContributionItem item = items[i]; | |
968 enabled = item.isEnabled(); | |
969 if(enabled) break; | |
970 } | |
971 // Workaround for 1GDDCN2: SWT:Linux - MenuItem.setEnabled() always causes a redraw | |
972 if (menuItem.getEnabled() !is enabled) | |
973 menuItem.setEnabled(enabled); | |
974 } | |
975 */ | |
976 // Partial fix for bug #34969 - diable the menu item if no | |
977 // items in sub-menu (for context menus). | |
978 if (menuItem !is null && !menuItem.isDisposed() && menuExist()) { | |
979 bool enabled = removeAllWhenShown || menu.getItemCount() > 0; | |
980 // Workaround for 1GDDCN2: SWT:Linux - MenuItem.setEnabled() always causes a redraw | |
981 if (menuItem.getEnabled() !is enabled) { | |
982 // We only do this for context menus (for bug #34969) | |
983 Menu topMenu = menu; | |
984 while (topMenu.getParentMenu() !is null) { | |
985 topMenu = topMenu.getParentMenu(); | |
986 } | |
987 if ((topMenu.getStyle() & SWT.BAR) is 0) { | |
988 menuItem.setEnabled(enabled); | |
989 } | |
990 } | |
991 } | |
992 } | |
993 } |