aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRené Brandstetter2014-03-27 18:54:41 (EDT)
committerPaul Webster2014-04-23 16:38:42 (EDT)
commitd230c401f95d8b6f87e3dcf22ae116177b54e7dc (patch)
tree7b10f71b22f0bf8cb542354bea3d9a3f4a96e788
parentbda3bad1a25085e05301e9c9dc2386872012c088 (diff)
downloadeclipse.platform.ui-d230c401f95d8b6f87e3dcf22ae116177b54e7dc.zip
eclipse.platform.ui-d230c401f95d8b6f87e3dcf22ae116177b54e7dc.tar.gz
eclipse.platform.ui-d230c401f95d8b6f87e3dcf22ae116177b54e7dc.tar.bz2
Bug 391430 - Dynamically creating / deleting menu items in Menu and MPopupMenu doesn't workrefs/changes/26/24126/10
Reactivate the fix of Sopot and modify it so it can handle the remove and add of many elements. Additionally the determination of the insert index changes so it can handle the differences between MenuManager and E4 model. Change-Id: I800574190347c0f94e4a2d951bb7611ab73cc9e3 Signed-off-by: René Brandstetter <Rene.Brandstetter@gmx.net>
-rw-r--r--bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerRenderer.java387
-rw-r--r--bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java12
2 files changed, 275 insertions, 124 deletions
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerRenderer.java
index aed3c56..1f820b9 100644
--- a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerRenderer.java
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/MenuManagerRenderer.java
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Marco Descher <marco@descher.at> - Bug 389063, Bug 398865, Bug 398866, Bug 405471
* Sopot Cela <sopotcela@gmail.com>
+ * René Brandstetter <Rene.Brandstetter@gmx.net> - Bug 391430 - Dynamically creating / deleting menu items in Menu and MPopupMenu doesn't work
*******************************************************************************/
package org.eclipse.e4.ui.workbench.renderers.swt;
@@ -61,6 +62,7 @@ import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.action.SubContributionItem;
import org.eclipse.jface.internal.MenuManagerEventHelper;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
@@ -254,6 +256,54 @@ public class MenuManagerRenderer extends SWTPartRenderer {
}
};
+ /**
+ * Flag for skipping the {@link #childrenUpdater}, which indicates a call
+ * from the {@link #reconcileManagerToModel(MenuManager, MMenu)} method.
+ */
+ private boolean isReconcileManagerToModel = false;
+ /**
+ * Flag for skipping the {@link #childrenUpdater}, which indicates a call
+ * from the {@link #processContributions(MMenu, String, boolean, boolean)}
+ * method.
+ */
+ private boolean isProcessContributions = false;
+
+ /**
+ * EventHanlder which handles the adding and disappearing of menu entries.
+ */
+ private EventHandler childrenUpdater = new EventHandler() {
+ public void handleEvent(Event event) {
+ // skip the event handling, because it is called from methods of
+ // this class which try to synchronize a MenuManager with the model
+ if (isReconcileManagerToModel || isProcessContributions)
+ return;
+
+ Object changedObj = event.getProperty(UIEvents.EventTags.ELEMENT);
+ if (changedObj instanceof MMenu) {
+ MMenu menuModel = (MMenu) changedObj;
+ MenuManager manager = getManager(menuModel);
+ if (manager == null)
+ return;
+ if (UIEvents.isREMOVE(event)) {
+ // remove can be one or many --> always use a list of
+ // entries
+ @SuppressWarnings("unchecked")
+ Iterable<MMenuElement> toRemove = (Iterable<MMenuElement>) UIEvents
+ .asIterable(event, UIEvents.EventTags.OLD_VALUE);
+
+ handleMenuElementRemove(manager, toRemove);
+ } else if (UIEvents.isADD(event)) {
+ // add can also be one or many --> always use a list of
+ // entries
+ @SuppressWarnings("unchecked")
+ Iterable<MMenuElement> toAdd = (Iterable<MMenuElement>) UIEvents
+ .asIterable(event, UIEvents.EventTags.NEW_VALUE);
+ handleMenuElementAdd(manager, toAdd);
+ }
+ }
+ }
+ };
+
private MenuManagerRendererFilter rendererFilter;
@PostConstruct
@@ -264,6 +314,8 @@ public class MenuManagerRenderer extends SWTPartRenderer {
eventBroker.subscribe(UIEvents.Item.TOPIC_ENABLED, enabledUpdater);
eventBroker
.subscribe(UIEvents.UIElement.TOPIC_ALL, toBeRenderedUpdater);
+ eventBroker.subscribe(UIEvents.ElementContainer.TOPIC_CHILDREN,
+ childrenUpdater);
context.set(MenuManagerRenderer.class, this);
Display display = context.get(Display.class);
@@ -289,6 +341,7 @@ public class MenuManagerRenderer extends SWTPartRenderer {
eventBroker.unsubscribe(selectionUpdater);
eventBroker.unsubscribe(enabledUpdater);
eventBroker.unsubscribe(toBeRenderedUpdater);
+ eventBroker.unsubscribe(childrenUpdater);
ContextInjectionFactory.uninject(MenuManagerEventHelper.getInstance()
.getShowHelper(),
@@ -453,16 +506,23 @@ MenuManagerEventHelper.getInstance()
if (elementId == null) {
return;
}
- final ArrayList<MMenuContribution> toContribute = new ArrayList<MMenuContribution>();
- ContributionsAnalyzer.XXXgatherMenuContributions(menuModel,
- application.getMenuContributions(), elementId, toContribute,
- null, isPopup);
- generateContributions(menuModel, toContribute, isMenuBar);
- for (MMenuElement element : menuModel.getChildren()) {
- if (element instanceof MMenu) {
- processContributions((MMenu) element, element.getElementId(),
- false, isPopup);
+
+ boolean prevProcessContributions = isProcessContributions;
+ isProcessContributions = true;
+ try {
+ final ArrayList<MMenuContribution> toContribute = new ArrayList<MMenuContribution>();
+ ContributionsAnalyzer.XXXgatherMenuContributions(menuModel,
+ application.getMenuContributions(), elementId,
+ toContribute, null, isPopup);
+ generateContributions(menuModel, toContribute, isMenuBar);
+ for (MMenuElement element : menuModel.getChildren()) {
+ if (element instanceof MMenu) {
+ processContributions((MMenu) element,
+ element.getElementId(), false, isPopup);
+ }
}
+ } finally {
+ isProcessContributions = prevProcessContributions;
}
}
@@ -908,139 +968,156 @@ MenuManagerEventHelper.getInstance()
* @param menuModel
*/
public void reconcileManagerToModel(MenuManager menuManager, MMenu menuModel) {
- List<MMenuElement> modelChildren = menuModel.getChildren();
-
- HashSet<MMenuItem> oldModelItems = new HashSet<MMenuItem>();
- HashSet<MMenu> oldMenus = new HashSet<MMenu>();
- HashSet<MMenuSeparator> oldSeps = new HashSet<MMenuSeparator>();
- for (MMenuElement itemModel : modelChildren) {
- if (OpaqueElementUtil.isOpaqueMenuSeparator(itemModel)) {
- oldSeps.add((MMenuSeparator) itemModel);
- } else if (OpaqueElementUtil.isOpaqueMenuItem(itemModel)) {
- oldModelItems.add((MMenuItem) itemModel);
- } else if (OpaqueElementUtil.isOpaqueMenu(itemModel)) {
- oldMenus.add((MMenu) itemModel);
+ boolean prevReconcileManagerToModel = isReconcileManagerToModel;
+ isReconcileManagerToModel = true;
+ try {
+ List<MMenuElement> modelChildren = menuModel.getChildren();
+
+ HashSet<MMenuItem> oldModelItems = new HashSet<MMenuItem>();
+ HashSet<MMenu> oldMenus = new HashSet<MMenu>();
+ HashSet<MMenuSeparator> oldSeps = new HashSet<MMenuSeparator>();
+ for (MMenuElement itemModel : modelChildren) {
+ if (OpaqueElementUtil.isOpaqueMenuSeparator(itemModel)) {
+ oldSeps.add((MMenuSeparator) itemModel);
+ } else if (OpaqueElementUtil.isOpaqueMenuItem(itemModel)) {
+ oldModelItems.add((MMenuItem) itemModel);
+ } else if (OpaqueElementUtil.isOpaqueMenu(itemModel)) {
+ oldMenus.add((MMenu) itemModel);
+ }
}
- }
- IContributionItem[] items = menuManager.getItems();
- for (int src = 0, dest = 0; src < items.length; src++, dest++) {
- IContributionItem item = items[src];
- if (item instanceof MenuManager) {
- MenuManager childManager = (MenuManager) item;
- MMenu childModel = getMenuModel(childManager);
- if (childModel == null) {
- MMenu legacyModel = OpaqueElementUtil.createOpaqueMenu();
- legacyModel.setElementId(childManager.getId());
- legacyModel.setVisible(childManager.isVisible());
- linkModelToManager(legacyModel, childManager);
- OpaqueElementUtil.setOpaqueItem(legacyModel, childManager);
- if (modelChildren.size() > dest) {
- modelChildren.add(dest, legacyModel);
- } else {
- modelChildren.add(legacyModel);
- }
- reconcileManagerToModel(childManager, legacyModel);
- } else {
- if (OpaqueElementUtil.isOpaqueMenu(childModel)) {
- oldMenus.remove(childModel);
- }
- if (modelChildren.size() > dest) {
- if (modelChildren.get(dest) != childModel) {
- modelChildren.remove(childModel);
- modelChildren.add(dest, childModel);
+ IContributionItem[] items = menuManager.getItems();
+ for (int src = 0, dest = 0; src < items.length; src++, dest++) {
+ IContributionItem item = items[src];
+
+ if (item instanceof SubContributionItem) {
+ // get the wrapped contribution item
+ item = ((SubContributionItem) item).getInnerItem();
+ }
+
+ if (item instanceof MenuManager) {
+ MenuManager childManager = (MenuManager) item;
+ MMenu childModel = getMenuModel(childManager);
+ if (childModel == null) {
+ MMenu legacyModel = OpaqueElementUtil
+ .createOpaqueMenu();
+ legacyModel.setElementId(childManager.getId());
+ legacyModel.setVisible(childManager.isVisible());
+ legacyModel.setLabel(childManager.getMenuText());
+
+ linkModelToManager(legacyModel, childManager);
+ OpaqueElementUtil.setOpaqueItem(legacyModel,
+ childManager);
+ if (modelChildren.size() > dest) {
+ modelChildren.add(dest, legacyModel);
+ } else {
+ modelChildren.add(legacyModel);
}
+ reconcileManagerToModel(childManager, legacyModel);
} else {
- modelChildren.add(childModel);
- }
- if (childModel instanceof MPopupMenu) {
- if (((MPopupMenu) childModel).getContext() == null) {
- IEclipseContext lclContext = getContext(menuModel);
- if (lclContext != null) {
- ((MPopupMenu) childModel)
- .setContext(lclContext
- .createChild(childModel
- .getElementId()));
+ if (OpaqueElementUtil.isOpaqueMenu(childModel)) {
+ oldMenus.remove(childModel);
+ }
+ if (modelChildren.size() > dest) {
+ if (modelChildren.get(dest) != childModel) {
+ modelChildren.remove(childModel);
+ modelChildren.add(dest, childModel);
+ }
+ } else {
+ modelChildren.add(childModel);
+ }
+ if (childModel instanceof MPopupMenu) {
+ if (((MPopupMenu) childModel).getContext() == null) {
+ IEclipseContext lclContext = getContext(menuModel);
+ if (lclContext != null) {
+ ((MPopupMenu) childModel)
+ .setContext(lclContext
+ .createChild(childModel
+ .getElementId()));
+ }
}
}
}
- }
- } else if (item.isSeparator() || item.isGroupMarker()) {
- MMenuElement menuElement = getMenuElement(item);
- if (menuElement == null) {
- MMenuSeparator legacySep = OpaqueElementUtil
- .createOpaqueMenuSeparator();
- legacySep.setElementId(item.getId());
- legacySep.setVisible(item.isVisible());
- OpaqueElementUtil.setOpaqueItem(legacySep, item);
- linkModelToContribution(legacySep, item);
- if (modelChildren.size() > dest) {
- modelChildren.add(dest, legacySep);
- } else {
- modelChildren.add(legacySep);
- }
- } else if (OpaqueElementUtil.isOpaqueMenuSeparator(menuElement)) {
- MMenuSeparator legacySep = (MMenuSeparator) menuElement;
- oldSeps.remove(legacySep);
- if (modelChildren.size() > dest) {
- if (modelChildren.get(dest) != legacySep) {
- modelChildren.remove(legacySep);
+ } else if (item.isSeparator() || item.isGroupMarker()) {
+ MMenuElement menuElement = getMenuElement(item);
+ if (menuElement == null) {
+ MMenuSeparator legacySep = OpaqueElementUtil
+ .createOpaqueMenuSeparator();
+ legacySep.setElementId(item.getId());
+ legacySep.setVisible(item.isVisible());
+ OpaqueElementUtil.setOpaqueItem(legacySep, item);
+ linkModelToContribution(legacySep, item);
+ if (modelChildren.size() > dest) {
modelChildren.add(dest, legacySep);
+ } else {
+ modelChildren.add(legacySep);
+ }
+ } else if (OpaqueElementUtil
+ .isOpaqueMenuSeparator(menuElement)) {
+ MMenuSeparator legacySep = (MMenuSeparator) menuElement;
+ oldSeps.remove(legacySep);
+ if (modelChildren.size() > dest) {
+ if (modelChildren.get(dest) != legacySep) {
+ modelChildren.remove(legacySep);
+ modelChildren.add(dest, legacySep);
+ }
+ } else {
+ modelChildren.add(legacySep);
}
- } else {
- modelChildren.add(legacySep);
- }
- }
- } else {
- MMenuElement menuElement = getMenuElement(item);
- if (menuElement == null) {
- MMenuItem legacyItem = OpaqueElementUtil
- .createOpaqueMenuItem();
- legacyItem.setElementId(item.getId());
- legacyItem.setVisible(item.isVisible());
- OpaqueElementUtil.setOpaqueItem(legacyItem, item);
- linkModelToContribution(legacyItem, item);
- if (modelChildren.size() > dest) {
- modelChildren.add(dest, legacyItem);
- } else {
- modelChildren.add(legacyItem);
}
- } else if (OpaqueElementUtil.isOpaqueMenuItem(menuElement)) {
- MMenuItem legacyItem = (MMenuItem) menuElement;
- oldModelItems.remove(legacyItem);
- if (modelChildren.size() > dest) {
- if (modelChildren.get(dest) != legacyItem) {
- modelChildren.remove(legacyItem);
+ } else {
+ MMenuElement menuElement = getMenuElement(item);
+ if (menuElement == null) {
+ MMenuItem legacyItem = OpaqueElementUtil
+ .createOpaqueMenuItem();
+ legacyItem.setElementId(item.getId());
+ legacyItem.setVisible(item.isVisible());
+ OpaqueElementUtil.setOpaqueItem(legacyItem, item);
+ linkModelToContribution(legacyItem, item);
+ if (modelChildren.size() > dest) {
modelChildren.add(dest, legacyItem);
+ } else {
+ modelChildren.add(legacyItem);
+ }
+ } else if (OpaqueElementUtil.isOpaqueMenuItem(menuElement)) {
+ MMenuItem legacyItem = (MMenuItem) menuElement;
+ oldModelItems.remove(legacyItem);
+ if (modelChildren.size() > dest) {
+ if (modelChildren.get(dest) != legacyItem) {
+ modelChildren.remove(legacyItem);
+ modelChildren.add(dest, legacyItem);
+ }
+ } else {
+ modelChildren.add(legacyItem);
}
- } else {
- modelChildren.add(legacyItem);
}
}
}
- }
- if (!oldModelItems.isEmpty()) {
- modelChildren.removeAll(oldModelItems);
- for (MMenuItem model : oldModelItems) {
- IContributionItem ici = (IContributionItem) OpaqueElementUtil
- .getOpaqueItem(model);
- clearModelToContribution(model, ici);
+ if (!oldModelItems.isEmpty()) {
+ modelChildren.removeAll(oldModelItems);
+ for (MMenuItem model : oldModelItems) {
+ IContributionItem ici = (IContributionItem) OpaqueElementUtil
+ .getOpaqueItem(model);
+ clearModelToContribution(model, ici);
+ }
}
- }
- if (!oldMenus.isEmpty()) {
- modelChildren.removeAll(oldMenus);
- for (MMenu oldMenu : oldMenus) {
- MenuManager oldManager = getManager(oldMenu);
- clearModelToManager(oldMenu, oldManager);
+ if (!oldMenus.isEmpty()) {
+ modelChildren.removeAll(oldMenus);
+ for (MMenu oldMenu : oldMenus) {
+ MenuManager oldManager = getManager(oldMenu);
+ clearModelToManager(oldMenu, oldManager);
+ }
}
- }
- if (!oldSeps.isEmpty()) {
- modelChildren.removeAll(oldSeps);
- for (MMenuSeparator model : oldSeps) {
- IContributionItem item = (IContributionItem) OpaqueElementUtil
- .getOpaqueItem(model);
- clearModelToContribution(model, item);
+ if (!oldSeps.isEmpty()) {
+ modelChildren.removeAll(oldSeps);
+ for (MMenuSeparator model : oldSeps) {
+ IContributionItem item = (IContributionItem) OpaqueElementUtil
+ .getOpaqueItem(model);
+ clearModelToContribution(model, item);
+ }
}
+ } finally {
+ isReconcileManagerToModel = prevReconcileManagerToModel;
}
}
@@ -1112,4 +1189,66 @@ MenuManagerEventHelper.getInstance()
MenuManager mm = getManager(menu);
clearModelToManager(menu, mm);
}
+
+ /**
+ * Handles the create of menu entries.
+ *
+ * @param manager
+ * the {@link MenuManager} to add the new entries too
+ * @param menuElements
+ * the new entries to add
+ */
+ private void handleMenuElementAdd(MenuManager manager,
+ Iterable<MMenuElement> menuElements) {
+ Iterator<MMenuElement> iterMenuElements = menuElements.iterator();
+
+ if (!iterMenuElements.hasNext())
+ return;
+
+ while (iterMenuElements.hasNext()) {
+ modelProcessSwitch(manager, iterMenuElements.next());
+ }
+
+ manager.updateAll(false);
+ }
+
+ /**
+ * Handles the remove of menu entries.
+ *
+ * @param manager
+ * the {@link MenuManager} to remove the entries from
+ * @param menuElements
+ * the elements to remove
+ */
+ private void handleMenuElementRemove(MenuManager manager,
+ Iterable<MMenuElement> menuElements) {
+ Iterator<MMenuElement> iterMenuElements = menuElements.iterator();
+
+ if (!iterMenuElements.hasNext())
+ return;
+
+ while (iterMenuElements.hasNext()) {
+ MMenuElement menuElement = iterMenuElements.next();
+ if (menuElement instanceof MMenu) {
+ MMenu menuModel = (MMenu) menuElement;
+ MenuManager mi = getManager(menuModel);
+ manager.remove(mi);
+
+ // clean up (children also)
+ clearModelToManager(menuModel, mi);
+ handleMenuElementRemove(mi, menuModel.getChildren());
+ mi.dispose();
+ } else {
+ IContributionItem ci = getContribution(menuElement);
+ manager.remove(ci);
+
+ // clean up
+ clearModelToContribution(menuElement, ci);
+ ci.dispose();
+ }
+
+ }
+
+ manager.updateAll(false);
+ }
}
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java
index 99d305b..4d80abc 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java
@@ -730,6 +730,18 @@ public class WorkbenchWindow implements IWorkbenchWindow {
}
updateActionSets();
+ // synchronize the main menu with the e4 model
+ IMenuManager menuBarManager = getMenuBarManager();
+ if (menuBarManager instanceof MenuManager) {
+ // TODO: remove this hack to retrieve the MenuManagerRenderer
+ MenuManagerRenderer mr = (MenuManagerRenderer) rendererFactory.getRenderer(
+ modelService.createModelElement(MMenu.class), null);
+ MMenu parent = mr.getMenuModel((MenuManager) menuBarManager);
+ if (parent != null) {
+ mr.reconcileManagerToModel((MenuManager) menuBarManager, parent);
+ }
+ }
+
IPreferenceStore preferenceStore = PrefUtil.getAPIPreferenceStore();
boolean enableAnimations = preferenceStore
.getBoolean(IWorkbenchPreferenceConstants.ENABLE_ANIMATIONS);