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