KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > menus > MenuAuthority


1 /*******************************************************************************
2  * Copyright (c) 2005, 2006 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  *******************************************************************************/

11
12 package org.eclipse.ui.internal.menus;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.Map JavaDoc;
20 import java.util.Set JavaDoc;
21
22 import org.eclipse.jface.window.Window;
23 import org.eclipse.ui.internal.services.ExpressionAuthority;
24
25 /**
26  * <p>
27  * A central authority for deciding visibility of menu elements. This authority
28  * listens to a variety of incoming sources, and updates the underlying menu
29  * manager if changes occur. It only updates those menu elements that are
30  * showing, and listens to the menu manager to determine which menu elements are
31  * currently visible.
32  * </p>
33  * <p>
34  * This class is not intended for use outside of the
35  * <code>org.eclipse.ui.workbench</code> plug-in.
36  * </p>
37  *
38  * @since 3.2
39  */

40 final class MenuAuthority extends ExpressionAuthority {
41
42     /**
43      * This is a map of menu element contributions (<code>Collection</code>
44      * of <code>IMenuContribution</code>) sorted by identifier (<code>MenuElement</code>).
45      * If there is only one contribution for a menu element, then the
46      * <code>Collection</code> is replaced by a <code>IMenuContribution</code>.
47      * If there is no contribution, the entry should be removed entirely.
48      */

49     private final Map JavaDoc menuContributionsByElement = new HashMap JavaDoc();
50
51     /**
52      * A bucket sort of the contributed menu elements based on source priority.
53      * This only includes the items that are currently showing within the
54      * workbench. Each contribution will appear only once per set, but may
55      * appear in multiple sets. If no contributions are defined for a particular
56      * priority level, then the array at that index will only contain
57      * <code>null</code>.
58      */

59     private final Set JavaDoc[] showingContributionsBySourcePriority = new Set JavaDoc[33];
60
61     /**
62      * The window for which this authority applies. This is used for determining
63      * visibility of particular menu elements.
64      */

65     private final Window window;
66
67     /**
68      * Constructs a new instance of <code>MenuAuthority</code>.
69      *
70      * @param window
71      * The window to use when calling
72      * {@link MenuElement#setVisible(Window, boolean)}; may be
73      * <code>null</code>.
74      */

75     MenuAuthority(final Window window) {
76         this.window = window;
77     }
78
79     /**
80      * Contributes a menu element to the workbench. This will add it to a master
81      * list.
82      *
83      * @param contribution
84      * The contribution; must not be <code>null</code>.
85      */

86     final void contributeMenu(final IMenuContribution contribution) {
87         // First we update the menuContributionsByElement map.
88
final MenuElement element = contribution.getMenuElement();
89         final Object JavaDoc value = menuContributionsByElement.get(element);
90         if (value instanceof Collection JavaDoc) {
91             final Collection JavaDoc menuContributions = (Collection JavaDoc) value;
92             if (!menuContributions.contains(contribution)) {
93                 menuContributions.add(contribution);
94             }
95         } else if (value instanceof IMenuContribution) {
96             if (value != contribution) {
97                 final Collection JavaDoc menuContributions = new ArrayList JavaDoc(2);
98                 menuContributions.add(value);
99                 menuContributions.add(contribution);
100                 menuContributionsByElement.put(element, menuContributions);
101             }
102         } else {
103             menuContributionsByElement.put(element, contribution);
104         }
105
106         // Next we update the source priority bucket sort of activations.
107
if (contribution.getMenuElement().isShowing(window)) {
108             final int sourcePriority = contribution.getSourcePriority();
109             for (int i = 1; i <= 32; i++) {
110                 if ((sourcePriority & (1 << i)) != 0) {
111                     Set JavaDoc contributions = showingContributionsBySourcePriority[i];
112                     if (contributions == null) {
113                         contributions = new HashSet JavaDoc(1);
114                         showingContributionsBySourcePriority[i] = contributions;
115                     }
116                     contributions.add(contribution);
117                 }
118             }
119         }
120     }
121
122     /**
123      * Removes a contribution from the workbench. This will remove it from the
124      * master list, and update as appropriate.
125      *
126      * @param contribution
127      * The contribution; must not be <code>null</code>.
128      */

129     final void removeContribution(final IMenuContribution contribution) {
130         // First we update the menuContributionByElement map.
131
final MenuElement element = contribution.getMenuElement();
132         final Object JavaDoc value = menuContributionsByElement.get(element);
133         if (value instanceof Collection JavaDoc) {
134             final Collection JavaDoc menuContributions = (Collection JavaDoc) value;
135             if (menuContributions.contains(contribution)) {
136                 menuContributions.remove(contribution);
137                 if (menuContributions.isEmpty()) {
138                     menuContributionsByElement.remove(element);
139
140                 } else if (menuContributions.size() == 1) {
141                     final IMenuContribution remainingContribution = (IMenuContribution) menuContributions
142                             .iterator().next();
143                     menuContributionsByElement.put(element,
144                             remainingContribution);
145
146                 }
147             }
148         } else if (value instanceof IMenuContribution) {
149             if (value == contribution) {
150                 menuContributionsByElement.remove(element);
151             }
152         }
153
154         // Next we update the source priority bucket sort of activations.
155
if (element.isShowing(window)) {
156             final int sourcePriority = contribution.getSourcePriority();
157             for (int i = 1; i <= 32; i++) {
158                 if ((sourcePriority & (1 << i)) != 0) {
159                     final Set JavaDoc contributions = showingContributionsBySourcePriority[i];
160                     if (contributions == null) {
161                         continue;
162                     }
163                     contributions.remove(contribution);
164                     if (contributions.isEmpty()) {
165                         showingContributionsBySourcePriority[i] = null;
166                     }
167                 }
168             }
169         }
170     }
171
172     /**
173      * Carries out the actual source change notification. It assumed that by the
174      * time this method is called, <code>getEvaluationContext()</code> is
175      * up-to-date with the current state of the application.
176      *
177      * @param sourcePriority
178      * A bit mask of all the source priorities that have changed.
179      */

180     protected final void sourceChanged(final int sourcePriority) {
181         /*
182          * In this first phase, we cycle through all of the contributions that
183          * could have potentially changed. Each such contribution is added to a
184          * set for future processing. We add it to a set so that we avoid
185          * handling any individual contribution more than once.
186          */

187         final Set JavaDoc contributionsToRecompute = new HashSet JavaDoc();
188         for (int i = 1; i <= 32; i++) {
189             if ((sourcePriority & (1 << i)) != 0) {
190                 final Collection JavaDoc contributions = showingContributionsBySourcePriority[i];
191                 if (contributions != null) {
192                     final Iterator JavaDoc contributionItr = contributions.iterator();
193                     while (contributionItr.hasNext()) {
194                         contributionsToRecompute.add(contributionItr.next());
195                     }
196                 }
197             }
198         }
199
200         /*
201          * For every contribution, we recompute its state, and check whether it
202          * has changed. If it has changed, then we take note of the menu element
203          * so we can update the menu element later.
204          */

205         final Iterator JavaDoc contributionItr = contributionsToRecompute.iterator();
206         while (contributionItr.hasNext()) {
207             final IMenuContribution contribution = (IMenuContribution) contributionItr
208                     .next();
209             final boolean currentlyVisible = evaluate(contribution);
210             contribution.clearResult();
211             final boolean newVisible = evaluate(contribution);
212             if (newVisible != currentlyVisible) {
213                 contribution.getMenuElement().setVisible(window, newVisible);
214             }
215         }
216     }
217 }
218
Popular Tags