|
Link Here
|
| 10 |
*******************************************************************************/ |
10 |
*******************************************************************************/ |
| 11 |
package org.eclipse.e4.ui.workbench.renderers.swt; |
11 |
package org.eclipse.e4.ui.workbench.renderers.swt; |
| 12 |
|
12 |
|
|
|
13 |
import java.util.ArrayList; |
| 14 |
import java.util.HashMap; |
| 15 |
import java.util.HashSet; |
| 13 |
import org.eclipse.e4.core.contexts.IEclipseContext; |
16 |
import org.eclipse.e4.core.contexts.IEclipseContext; |
|
|
17 |
import org.eclipse.e4.core.contexts.RunAndTrack; |
| 18 |
import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer; |
| 19 |
import org.eclipse.e4.ui.model.application.MApplication; |
| 14 |
import org.eclipse.e4.ui.model.application.ui.MElementContainer; |
20 |
import org.eclipse.e4.ui.model.application.ui.MElementContainer; |
| 15 |
import org.eclipse.e4.ui.model.application.ui.MUIElement; |
21 |
import org.eclipse.e4.ui.model.application.ui.MUIElement; |
| 16 |
import org.eclipse.e4.ui.model.application.ui.basic.MWindow; |
22 |
import org.eclipse.e4.ui.model.application.ui.basic.MWindow; |
| 17 |
import org.eclipse.e4.ui.model.application.ui.menu.MMenu; |
23 |
import org.eclipse.e4.ui.model.application.ui.menu.MMenu; |
|
|
24 |
import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution; |
| 18 |
import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement; |
25 |
import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement; |
| 19 |
import org.eclipse.e4.ui.model.application.ui.menu.MMenuSeparator; |
26 |
import org.eclipse.e4.ui.model.application.ui.menu.MMenuSeparator; |
| 20 |
import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuFactoryImpl; |
27 |
import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuFactoryImpl; |
| 21 |
import org.eclipse.e4.ui.workbench.swt.modeling.MenuServiceFilter; |
28 |
import org.eclipse.e4.ui.workbench.modeling.ExpressionContext; |
| 22 |
import org.eclipse.emf.ecore.EObject; |
29 |
import org.eclipse.emf.ecore.EObject; |
| 23 |
import org.eclipse.swt.SWT; |
30 |
import org.eclipse.swt.SWT; |
|
|
31 |
import org.eclipse.swt.events.DisposeEvent; |
| 32 |
import org.eclipse.swt.events.DisposeListener; |
| 24 |
import org.eclipse.swt.widgets.Control; |
33 |
import org.eclipse.swt.widgets.Control; |
| 25 |
import org.eclipse.swt.widgets.Decorations; |
34 |
import org.eclipse.swt.widgets.Decorations; |
| 26 |
import org.eclipse.swt.widgets.Menu; |
35 |
import org.eclipse.swt.widgets.Menu; |
|
Link Here
|
| 31 |
* Create a contribute part. |
40 |
* Create a contribute part. |
| 32 |
*/ |
41 |
*/ |
| 33 |
public class MenuRenderer extends SWTPartRenderer { |
42 |
public class MenuRenderer extends SWTPartRenderer { |
|
|
43 |
private MApplication application; |
| 44 |
private HashMap<MMenu, ArrayList<ArrayList<MMenuElement>>> pendingCleanup = new HashMap<MMenu, ArrayList<ArrayList<MMenuElement>>>(); |
| 45 |
|
| 46 |
@Override |
| 47 |
public void init(IEclipseContext context) { |
| 48 |
super.init(context); |
| 49 |
application = context.get(MApplication.class); |
| 50 |
} |
| 34 |
|
51 |
|
| 35 |
public Object createWidget(final MUIElement element, Object parent) { |
52 |
public Object createWidget(final MUIElement element, Object parent) { |
| 36 |
if (!(element instanceof MMenu)) |
53 |
if (!(element instanceof MMenu)) |
| 37 |
return null; |
54 |
return null; |
| 38 |
|
55 |
|
| 39 |
MMenu menuModel = (MMenu) element; |
56 |
final MMenu menuModel = (MMenu) element; |
| 40 |
|
57 |
|
| 41 |
Menu newMenu = null; |
58 |
Menu newMenu = null; |
| 42 |
if (parent instanceof Decorations) { |
59 |
if (parent instanceof Decorations) { |
| 43 |
MUIElement container = (MUIElement) ((EObject) element) |
60 |
MUIElement container = (MUIElement) ((EObject) element) |
| 44 |
.eContainer(); |
61 |
.eContainer(); |
| 45 |
if (container instanceof MWindow) |
62 |
if (container instanceof MWindow) { |
| 46 |
newMenu = new Menu((Decorations) parent, SWT.BAR); |
63 |
newMenu = new Menu((Decorations) parent, SWT.BAR); |
| 47 |
else { |
64 |
newMenu.addDisposeListener(new DisposeListener() { |
|
|
65 |
public void widgetDisposed(DisposeEvent e) { |
| 66 |
cleanUp(menuModel); |
| 67 |
} |
| 68 |
}); |
| 69 |
} else { |
| 48 |
newMenu = new Menu((Decorations) parent, SWT.POP_UP); |
70 |
newMenu = new Menu((Decorations) parent, SWT.POP_UP); |
| 49 |
} |
71 |
} |
| 50 |
} else if (parent instanceof Menu) { |
72 |
} else if (parent instanceof Menu) { |
|
Link Here
|
| 71 |
*/ |
93 |
*/ |
| 72 |
@Override |
94 |
@Override |
| 73 |
public void processContents(MElementContainer<MUIElement> container) { |
95 |
public void processContents(MElementContainer<MUIElement> container) { |
| 74 |
Object obj = container.getWidget(); |
|
|
| 75 |
Object menuModel = container; |
| 76 |
if ((obj instanceof Menu) && (((Menu) obj).getStyle() & SWT.BAR) != 0 |
| 77 |
&& (menuModel instanceof MMenu)) { |
| 78 |
if (container.getChildren().isEmpty()) { |
| 79 |
return; |
| 80 |
} |
| 81 |
// this is a crazy fill and run |
| 82 |
IEclipseContext ctx = getContext(container); |
| 83 |
MenuServiceFilter filter = ctx.get(MenuServiceFilter.class); |
| 84 |
filter.showMenu(null, (Menu) obj, (MMenu) menuModel); |
| 85 |
return; |
| 86 |
} |
| 87 |
if (container.getChildren().size() == 0) { |
96 |
if (container.getChildren().size() == 0) { |
| 88 |
MMenuSeparator sep = MenuFactoryImpl.eINSTANCE |
97 |
MMenuSeparator sep = MenuFactoryImpl.eINSTANCE |
| 89 |
.createMenuSeparator(); |
98 |
.createMenuSeparator(); |
| 90 |
sep.setElementId("placeholder"); //$NON-NLS-1$ |
99 |
sep.setElementId("menu.placeholder"); //$NON-NLS-1$ |
| 91 |
container.getChildren().add(sep); |
100 |
container.getChildren().add(sep); |
| 92 |
} |
101 |
} |
| 93 |
|
102 |
|
| 94 |
super.processContents(container); |
103 |
super.processContents(container); |
|
|
104 |
|
| 105 |
Object obj = container.getWidget(); |
| 106 |
Object menuObj = container; |
| 107 |
if ((obj instanceof Menu) && (((Menu) obj).getStyle() & SWT.BAR) != 0 |
| 108 |
&& (menuObj instanceof MMenu)) { |
| 109 |
MMenu menuModel = (MMenu) menuObj; |
| 110 |
IEclipseContext ctx = getContext(container); |
| 111 |
ExpressionContext eContext = new ExpressionContext(ctx); |
| 112 |
ArrayList<MMenuContribution> toContribute = new ArrayList<MMenuContribution>(); |
| 113 |
ContributionsAnalyzer.gatherMenuContributions(menuModel, |
| 114 |
application.getMenuContributions(), |
| 115 |
menuModel.getElementId(), toContribute, eContext, false); |
| 116 |
addMenuBarContributions(menuModel, toContribute, ctx, eContext); |
| 117 |
} |
| 118 |
} |
| 119 |
|
| 120 |
// this is similar in nature to: |
| 121 |
// org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer.addMenuContributions(MMenu, |
| 122 |
// ArrayList<MMenuContribution>, ArrayList<MMenuElement>) |
| 123 |
// the difference is it needs to add all the contributions and manage their |
| 124 |
// visiblility through a RAT |
| 125 |
private void addMenuBarContributions(final MMenu menuModel, |
| 126 |
ArrayList<MMenuContribution> toContribute, |
| 127 |
final IEclipseContext ctx, final ExpressionContext eContext) { |
| 128 |
HashSet<String> existingMenuIds = new HashSet<String>(); |
| 129 |
HashSet<String> existingSeparatorNames = new HashSet<String>(); |
| 130 |
for (MMenuElement child : menuModel.getChildren()) { |
| 131 |
String elementId = child.getElementId(); |
| 132 |
if (child instanceof MMenu && elementId != null) { |
| 133 |
existingMenuIds.add(elementId); |
| 134 |
} else if (child instanceof MMenuSeparator && elementId != null) { |
| 135 |
existingSeparatorNames.add(elementId); |
| 136 |
} |
| 137 |
} |
| 138 |
|
| 139 |
boolean done = toContribute.size() == 0; |
| 140 |
while (!done) { |
| 141 |
ArrayList<MMenuContribution> curList = new ArrayList<MMenuContribution>( |
| 142 |
toContribute); |
| 143 |
int retryCount = toContribute.size(); |
| 144 |
toContribute.clear(); |
| 145 |
|
| 146 |
for (final MMenuContribution menuContribution : curList) { |
| 147 |
final ArrayList<MMenuElement> menuContributionsToRemove = new ArrayList<MMenuElement>(); |
| 148 |
if (!ContributionsAnalyzer.processAddition(menuModel, |
| 149 |
menuContributionsToRemove, menuContribution, |
| 150 |
existingMenuIds, existingSeparatorNames)) { |
| 151 |
toContribute.add(menuContribution); |
| 152 |
} else { |
| 153 |
ctx.runAndTrack(new RunAndTrack() { |
| 154 |
@Override |
| 155 |
public boolean changed(IEclipseContext context) { |
| 156 |
if (!menuModel.isToBeRendered() |
| 157 |
|| !menuModel.isVisible() |
| 158 |
|| menuModel.getWidget() == null) { |
| 159 |
return false; |
| 160 |
} |
| 161 |
boolean rc = ContributionsAnalyzer.isVisible( |
| 162 |
menuContribution, eContext); |
| 163 |
for (MMenuElement element : menuContributionsToRemove) { |
| 164 |
element.setToBeRendered(rc); |
| 165 |
} |
| 166 |
return true; |
| 167 |
} |
| 168 |
}); |
| 169 |
ArrayList<ArrayList<MMenuElement>> lists = pendingCleanup |
| 170 |
.get(menuModel); |
| 171 |
if (lists == null) { |
| 172 |
lists = new ArrayList<ArrayList<MMenuElement>>(); |
| 173 |
pendingCleanup.put(menuModel, lists); |
| 174 |
} |
| 175 |
} |
| 176 |
} |
| 177 |
// We're done if the retryList is now empty (everything done) or |
| 178 |
// if the list hasn't changed at all (no hope) |
| 179 |
done = (toContribute.size() == 0) |
| 180 |
|| (toContribute.size() == retryCount); |
| 181 |
} |
| 95 |
} |
182 |
} |
| 96 |
|
183 |
|
| 97 |
private void setItemText(MMenu model, MenuItem item) { |
184 |
private void setItemText(MMenu model, MenuItem item) { |
|
Link Here
|
| 145 |
return super.getUIContainer(element); |
232 |
return super.getUIContainer(element); |
| 146 |
} |
233 |
} |
| 147 |
|
234 |
|
|
|
235 |
void cleanUp(MMenu menuModel) { |
| 236 |
ArrayList<ArrayList<MMenuElement>> lists = pendingCleanup |
| 237 |
.remove(menuModel); |
| 238 |
if (lists == null) { |
| 239 |
return; |
| 240 |
} |
| 241 |
for (ArrayList<MMenuElement> list : lists) { |
| 242 |
for (MMenuElement item : list) { |
| 243 |
menuModel.getChildren().remove(item); |
| 244 |
} |
| 245 |
} |
| 246 |
} |
| 148 |
} |
247 |
} |