1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
|
/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jface.action;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.CoolBar;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ToolBar;
/**
* A <code>SubMenuManager</code> is used to define a set of contribution
* items within a parent manager. Once defined, the visibility of the entire set can
* be changed as a unit.
* <p>
* A client may ask for and make additions to a submenu. The visibility of these items
* is also controlled by the visibility of the <code>SubMenuManager</code>.
* </p>
*/
public class SubMenuManager extends SubContributionManager implements
IMenuManager {
/**
* Maps each submenu in the manager to a wrapper. The wrapper is used to
* monitor additions and removals. If the visibility of the manager is modified
* the visibility of the submenus is also modified.
*/
private Map mapMenuToWrapper;
/**
* List of registered menu listeners (element type: <code>IMenuListener</code>).
*/
private ListenerList menuListeners = new ListenerList();
/**
* The menu listener added to the parent. Lazily initialized
* in addMenuListener.
*/
private IMenuListener menuListener;
/**
* Constructs a new manager.
*
* @param mgr the parent manager. All contributions made to the
* <code>SubMenuManager</code> are forwarded and appear in the
* parent manager.
*/
public SubMenuManager(IMenuManager mgr) {
super(mgr);
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IMenuManager#addMenuListener(org.eclipse.jface.action.IMenuListener)
*/
public void addMenuListener(IMenuListener listener) {
menuListeners.add(listener);
if (menuListener == null) {
menuListener = new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
Object[] listeners = menuListeners.getListeners();
for (int i = 0; i < listeners.length; ++i) {
((IMenuListener) listeners[i])
.menuAboutToShow(SubMenuManager.this);
}
}
};
}
getParentMenuManager().addMenuListener(menuListener);
}
/**
* The default implementation of this <code>IContributionItem</code>
* method does nothing. Subclasses may override.
*/
public void dispose() {
// do nothing
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.SubContributionManager#disposeManager()
*/
@Override
public void disposeManager() {
if (menuListener != null) {
getParentMenuManager().removeMenuListener(menuListener);
menuListener = null;
menuListeners.clear();
}
// Dispose wrapped menus in addition to removing them.
// See bugs 64024 and 73715 for details.
// important to dispose menu wrappers before call to super,
// otherwise super's call to removeAll will remove them
// before they can be disposed
if (mapMenuToWrapper != null) {
Iterator iter = mapMenuToWrapper.values().iterator();
while (iter.hasNext()) {
SubMenuManager wrapper = (SubMenuManager) iter.next();
wrapper.disposeManager();
}
mapMenuToWrapper.clear();
mapMenuToWrapper = null;
}
super.disposeManager();
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#fill(org.eclipse.swt.widgets.Composite)
*/
public void fill(Composite parent) {
if (isVisible()) {
getParentMenuManager().fill(parent);
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#fill(org.eclipse.swt.widgets.CoolBar, int)
*/
public void fill(CoolBar parent, int index) {
// do nothing
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#fill(org.eclipse.swt.widgets.Menu, int)
*/
public void fill(Menu parent, int index) {
if (isVisible()) {
getParentMenuManager().fill(parent, index);
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#fill(org.eclipse.swt.widgets.ToolBar, int)
*/
public void fill(ToolBar parent, int index) {
if (isVisible()) {
getParentMenuManager().fill(parent, index);
}
}
/* (non-Javadoc)
* Method declared on IContributionManager.
*
* Returns the item passed to us, not the wrapper.
* In the case of menu's not added by this manager,
* ensure that we return a wrapper for the menu.
*/
@Override
public IContributionItem find(String id) {
IContributionItem item = getParentMenuManager().find(id);
if (item instanceof SubContributionItem) {
// Return the item passed to us, not the wrapper.
item = unwrap(item);
}
if (item instanceof IMenuManager) {
// if it is a menu manager wrap it before returning
IMenuManager menu = (IMenuManager) item;
item = getWrapper(menu);
}
return item;
}
/**
* <p>
* The menu returned is wrapped within a <code>SubMenuManager</code> to
* monitor additions and removals. If the visibility of this menu is modified
* the visibility of the submenus is also modified.
* </p>
*/
public IMenuManager findMenuUsingPath(String path) {
IContributionItem item = findUsingPath(path);
if (item instanceof IMenuManager) {
return (IMenuManager) item;
}
return null;
}
/* (non-Javadoc)
* Method declared on IMenuManager.
*
* Returns the item passed to us, not the wrapper.
*
* We use use the same algorithm as MenuManager.findUsingPath, but unwrap
* submenus along so that SubMenuManagers are visible.
*/
public IContributionItem findUsingPath(String path) {
String id = path;
String rest = null;
int separator = path.indexOf('/');
if (separator != -1) {
id = path.substring(0, separator);
rest = path.substring(separator + 1);
}
IContributionItem item = find(id); // unwraps item
if (rest != null && item instanceof IMenuManager) {
IMenuManager menu = (IMenuManager) item;
item = menu.findUsingPath(rest);
}
return item;
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#getId()
*/
public String getId() {
return getParentMenuManager().getId();
}
/**
* @return the parent menu manager that this sub-manager contributes to.
*/
protected final IMenuManager getParentMenuManager() {
// Cast is ok because that's the only
// thing we accept in the construtor.
return (IMenuManager) getParent();
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IMenuManager#getRemoveAllWhenShown()
*/
public boolean getRemoveAllWhenShown() {
return false;
}
/**
* Returns the menu wrapper for a menu manager.
* <p>
* The sub menus within this menu are wrapped within a <code>SubMenuManager</code> to
* monitor additions and removals. If the visibility of this menu is modified
* the visibility of the sub menus is also modified.
* <p>
* @param mgr the menu manager to be wrapped
*
* @return the menu wrapper
*/
protected IMenuManager getWrapper(IMenuManager mgr) {
if (mapMenuToWrapper == null) {
mapMenuToWrapper = new HashMap(4);
}
SubMenuManager wrapper = (SubMenuManager) mapMenuToWrapper.get(mgr);
if (wrapper == null) {
wrapper = wrapMenu(mgr);
mapMenuToWrapper.put(mgr, wrapper);
}
return wrapper;
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#isDynamic()
*/
public boolean isDynamic() {
return getParentMenuManager().isDynamic();
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#isEnabled()
*/
public boolean isEnabled() {
return isVisible() && getParentMenuManager().isEnabled();
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#isGroupMarker()
*/
public boolean isGroupMarker() {
return getParentMenuManager().isGroupMarker();
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#isSeparator()
*/
public boolean isSeparator() {
return getParentMenuManager().isSeparator();
}
/**
* Remove all contribution items.
*/
@Override
public void removeAll() {
super.removeAll();
if (mapMenuToWrapper != null) {
Iterator iter = mapMenuToWrapper.values().iterator();
while (iter.hasNext()) {
SubMenuManager wrapper = (SubMenuManager) iter.next();
wrapper.removeAll();
}
mapMenuToWrapper.clear();
mapMenuToWrapper = null;
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IMenuManager#removeMenuListener(org.eclipse.jface.action.IMenuListener)
*/
public void removeMenuListener(IMenuListener listener) {
menuListeners.remove(listener);
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#saveWidgetState()
*/
public void saveWidgetState() {
// do nothing
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#setParent(org.eclipse.jface.action.IContributionManager)
*/
public void setParent(IContributionManager parent) {
// do nothing, our "parent manager's" parent
// is set when it is added to a manager
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IMenuManager#setRemoveAllWhenShown(boolean)
*/
public void setRemoveAllWhenShown(boolean removeAll) {
Assert.isTrue(false, "Should not be called on submenu manager"); //$NON-NLS-1$
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.SubContributionManager#setVisible(boolean)
*/
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (mapMenuToWrapper != null) {
Iterator iter = mapMenuToWrapper.values().iterator();
while (iter.hasNext()) {
SubMenuManager wrapper = (SubMenuManager) iter.next();
wrapper.setVisible(visible);
}
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#update()
*/
public void update() {
// This method is not governed by visibility. The client may
// call <code>setVisible</code> and then force an update. At that
// point we need to update the parent.
getParentMenuManager().update();
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionManager#update(boolean)
*/
public void update(boolean force) {
// This method is not governed by visibility. The client may
// call <code>setVisible</code> and then force an update. At that
// point we need to update the parent.
getParentMenuManager().update(force);
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IContributionItem#update(java.lang.String)
*/
public void update(String id) {
getParentMenuManager().update(id);
}
/* (non-Javadoc)
* @see org.eclipse.jface.action.IMenuManager#updateAll(boolean)
*/
public void updateAll(boolean force) {
// This method is not governed by visibility. The client may
// call <code>setVisible</code> and then force an update. At that
// point we need to update the parent.
getParentMenuManager().updateAll(force);
}
/**
* Wraps a menu manager in a sub menu manager, and returns the new wrapper.
* @param menu the menu manager to wrap
* @return the new wrapped menu manager
*/
protected SubMenuManager wrapMenu(IMenuManager menu) {
SubMenuManager mgr = new SubMenuManager(menu);
mgr.setVisible(isVisible());
return mgr;
}
}
|