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 }