diff options
author | Remy Suen | 2012-02-13 18:03:03 +0000 |
---|---|---|
committer | Remy Suen | 2012-02-13 18:03:03 +0000 |
commit | 5185d9e93948557023700a3cfd8d3ff2480223ee (patch) | |
tree | d76f5b82404fdecf333bc85aba93c9e3cc8358c2 | |
parent | f2a8ce2a9c2725653391ee3326262a984a9fa896 (diff) | |
download | eclipse.platform.ui-5185d9e93948557023700a3cfd8d3ff2480223ee.tar.gz eclipse.platform.ui-5185d9e93948557023700a3cfd8d3ff2480223ee.tar.xz eclipse.platform.ui-5185d9e93948557023700a3cfd8d3ff2480223ee.zip |
Bug 319621 [Compatibility] All views now have view menusv20120213-1803
A part's menu is a dynamic item in that when the part is first
constructed, it may not have a menu but a menu may become
necessary at a later point in time when other variables become
satisfied. Likewise, a part may start of needing a menu but this
requirement may be lifted later.
To properly react to this, a RunAndTrack is needed to determine
when a part's menu should be rendered or not.
5 files changed, 259 insertions, 21 deletions
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ContributionRecord.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ContributionRecord.java index 2d7c7e60ec3..c9ccfde24c0 100644 --- a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ContributionRecord.java +++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/ContributionRecord.java @@ -110,7 +110,10 @@ public class ContributionRecord { } if (changed) { - getManagerForModel().markDirty(); + MenuManager manager = getManagerForModel(); + if (manager != null) { + manager.markDirty(); + } } } 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 a5ab9bf26b2..ac990eff679 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2010 IBM Corporation and others. + * Copyright (c) 2009, 2012 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 @@ -31,6 +31,7 @@ import org.eclipse.e4.ui.model.application.ui.MCoreExpression; import org.eclipse.e4.ui.model.application.ui.MElementContainer; import org.eclipse.e4.ui.model.application.ui.MUIElement; import org.eclipse.e4.ui.model.application.ui.MUILabel; +import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.e4.ui.model.application.ui.basic.MWindow; import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem; import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem; @@ -437,7 +438,7 @@ public class MenuManagerRenderer extends SWTPartRenderer { if (!record.mergeIntoModel()) { return false; } - if (menuBar) { + if (menuBar || isPartMenu(menuModel)) { final IEclipseContext parentContext = modelService .getContainingContext(menuModel); parentContext.runAndTrack(new RunAndTrack() { @@ -452,6 +453,13 @@ public class MenuManagerRenderer extends SWTPartRenderer { return true; } + private boolean isPartMenu(MMenu menuModel) { + // don't want popup menus as their visibility does not need to be + // tracked by a separate RunAndTrack + return !(menuModel instanceof MPopupMenu) + && ((EObject) menuModel).eContainer() instanceof MPart; + } + public ArrayList<ContributionRecord> getList(MMenuElement item) { ArrayList<ContributionRecord> tmp = sharedElementToRecord.get(item); if (tmp == null) { diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRenderer.java index d429220a61f..c36b4d27b8d 100644 --- a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRenderer.java +++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/StackRenderer.java @@ -32,6 +32,9 @@ import org.eclipse.e4.ui.model.application.ui.basic.MPartStack; import org.eclipse.e4.ui.model.application.ui.basic.MStackElement; import org.eclipse.e4.ui.model.application.ui.basic.MWindow; import org.eclipse.e4.ui.model.application.ui.menu.MMenu; +import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement; +import org.eclipse.e4.ui.model.application.ui.menu.MOpaqueMenuItem; +import org.eclipse.e4.ui.model.application.ui.menu.MOpaqueMenuSeparator; import org.eclipse.e4.ui.model.application.ui.menu.MToolBar; import org.eclipse.e4.ui.services.IStylingEngine; import org.eclipse.e4.ui.widgets.CTabFolder; @@ -45,6 +48,7 @@ import org.eclipse.e4.ui.workbench.modeling.EModelService; import org.eclipse.e4.ui.workbench.modeling.EPartService; import org.eclipse.e4.ui.workbench.swt.util.ISWTResourceUtilities; import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.MenuManager; import org.eclipse.swt.SWT; import org.eclipse.swt.accessibility.ACC; @@ -114,6 +118,13 @@ public class StackRenderer extends LazyStackRenderer { private EventHandler dirtyUpdater; + /** + * An event handler for listening to changes to the state of view menus and + * its child menu items. Depending on what state these items are in, the + * view menu should or should not be rendered in the tab folder. + */ + private EventHandler viewMenuUpdater; + private boolean ignoreTabSelChanges = false; private ActivationJob activationJob = null; @@ -329,6 +340,92 @@ public class StackRenderer extends LazyStackRenderer { eventBroker.subscribe(UIEvents.buildTopic(UIEvents.Dirtyable.TOPIC, UIEvents.Dirtyable.DIRTY), dirtyUpdater); + + viewMenuUpdater = new EventHandler() { + public void handleEvent(Event event) { + Object objElement = event + .getProperty(UIEvents.EventTags.ELEMENT); + + // Ensure that this event is for a MMenuItem + if (!(objElement instanceof MMenuElement)) { + return; + } + + EObject parent = ((EObject) objElement).eContainer(); + while (parent instanceof MMenuElement) { + MUIElement element = (MUIElement) parent; + if (!element.isToBeRendered() || !element.isVisible()) { + return; + } + + objElement = parent; + parent = parent.eContainer(); + } + + // if we're a view menu, the parent element is a part + if (!(parent instanceof MPart)) { + return; + } + + MPart element = (MPart) parent; + MUIElement parentElement = element.getParent(); + if (parentElement == null) { + MPlaceholder placeholder = element.getCurSharedRef(); + if (placeholder == null) { + return; + } + + parentElement = placeholder.getParent(); + if (parentElement == null) { + return; + } + } + + Object widget = parentElement.getWidget(); + if (widget instanceof CTabFolder) { + Boolean newValue = (Boolean) event + .getProperty(UIEvents.EventTags.NEW_VALUE); + CTabFolder folder = (CTabFolder) widget; + if (newValue.booleanValue()) { + if (getViewMenuTB(folder) == null) { + disposeViewMenu(folder); + setupMenuButton(element, folder); + layoutTopRight(folder); + } + } else if (!isMenuVisible((MMenu) objElement)) { + disposeViewMenu(folder); + } + } + } + }; + eventBroker + .subscribe(UIEvents.UIElement.TOPIC_VISIBLE, viewMenuUpdater); + eventBroker.subscribe(UIEvents.UIElement.TOPIC_TOBERENDERED, + viewMenuUpdater); + } + + /** + * Determines if the menu provided or any one of its children should be + * rendered. + * + * @param menu + * the menu to determine if it should be displayed in the tab + * folder + * @return <tt>true</tt> if the menu should be drawn in the tab folder, + * <tt>false</tt> otherwise + */ + private boolean isMenuVisible(MMenu menu) { + if (menu.isToBeRendered() && menu.isVisible()) { + for (MMenuElement element : menu.getChildren()) { + if (element.isToBeRendered() && element.isVisible()) { + return true; + } else if (element instanceof MMenu + && isMenuVisible((MMenu) element)) { + return true; + } + } + } + return false; } protected void updateTab(CTabItem cti, MPart part, String attName, @@ -361,6 +458,7 @@ public class StackRenderer extends LazyStackRenderer { eventBroker.unsubscribe(itemUpdater); eventBroker.unsubscribe(dirtyUpdater); + eventBroker.unsubscribe(viewMenuUpdater); } private String getLabel(MUILabel itemPart, String newName) { @@ -497,7 +595,20 @@ public class StackRenderer extends LazyStackRenderer { return (Composite) ctf.getData(TOP_RIGHT); } + /** + * Disposes of the view menu associated with the given tab folder. + * + * @param ctf + * the tab folder to clear of its view menu + */ + public void disposeViewMenu(CTabFolder ctf) { + ToolBar vmTB = getViewMenuTB(ctf); + if (vmTB != null && !vmTB.isDisposed()) + vmTB.dispose(); + } + public void clearTR(CTabFolder ctf) { + disposeViewMenu(ctf); ToolBar vmTB = getViewMenuTB(ctf); if (vmTB != null && !vmTB.isDisposed()) vmTB.dispose(); @@ -525,7 +636,16 @@ public class StackRenderer extends LazyStackRenderer { } setupMenuButton(part, ctf); + layoutTopRight(ctf); + } + /** + * Asks the specified tab folder to layout its top right control. + * + * @param ctf + * the tab folder that should be laid out + */ + public void layoutTopRight(CTabFolder ctf) { Composite trComp = getTRComposite(ctf); if (trComp.getChildren().length > 0) { trComp.setVisible(true); @@ -535,8 +655,8 @@ public class StackRenderer extends LazyStackRenderer { trComp.setVisible(false); } - trComp.layout(); - ctf.layout(); + trComp.pack(); + ctf.layout(true, true); } private MToolBar getViewTB(CTabFolder ctf) { @@ -874,11 +994,19 @@ public class StackRenderer extends LazyStackRenderer { adjustTR(ctf, part); } - private void setupMenuButton(MPart part, CTabFolder ctf) { + /** + * Creates a view menu for the given part in the contained tab folder. + * + * @param part + * the part that should have its view menu created + * @param ctf + * the containing tab folder + */ + public void setupMenuButton(MPart part, CTabFolder ctf) { MMenu viewMenu = getViewMenu(part); // View menu (if any) - if (viewMenu != null) { + if (viewMenu != null && hasVisibleMenuItems(viewMenu, part)) { showMenuButton(part, ctf, viewMenu); } else { // hide the menu's TB @@ -1170,10 +1298,73 @@ public class StackRenderer extends LazyStackRenderer { return null; } for (MMenu menu : part.getMenus()) { - if (menu.getTags().contains(TAG_VIEW_MENU) && menu.isToBeRendered()) { + if (menu.getTags().contains(TAG_VIEW_MENU)) { return menu; } } return null; } + + /** + * Determine whether the given view menu has any visible menu items. + * + * @param viewMenu + * the view menu to check + * @param part + * the view menu's parent part + * @return <tt>true</tt> if the specified view menu has visible children, + * <tt>false</tt> otherwise + */ + private boolean hasVisibleMenuItems(MMenu viewMenu, MPart part) { + if (!viewMenu.isToBeRendered() || !viewMenu.isVisible()) { + return false; + } + + for (MMenuElement menuElement : viewMenu.getChildren()) { + if (menuElement.isToBeRendered() && menuElement.isVisible()) { + if (menuElement instanceof MOpaqueMenuItem) { + IContributionItem item = (IContributionItem) ((MOpaqueMenuItem) menuElement) + .getOpaqueItem(); + if (item != null && item.isVisible()) { + return true; + } + } else if (menuElement instanceof MOpaqueMenuSeparator) { + IContributionItem item = (IContributionItem) ((MOpaqueMenuSeparator) menuElement) + .getOpaqueItem(); + if (item != null && item.isVisible()) { + return true; + } + } else { + return true; + } + } + } + + Object menuRenderer = viewMenu.getRenderer(); + if (menuRenderer instanceof MenuManagerRenderer) { + MenuManager manager = ((MenuManagerRenderer) menuRenderer) + .getManager(viewMenu); + if (manager != null && manager.isVisible()) { + return true; + } + } + + Control control = (Control) part.getWidget(); + Menu menu = (Menu) renderer.createGui(viewMenu, control.getShell(), + part.getContext()); + if (menu != null) { + menuRenderer = viewMenu.getRenderer(); + if (menuRenderer instanceof MenuManagerRenderer) { + MenuManagerRenderer menuManagerRenderer = (MenuManagerRenderer) menuRenderer; + MenuManager manager = menuManagerRenderer.getManager(viewMenu); + if (manager != null) { + // remark ourselves as dirty so that the menu will be + // reconstructed + manager.markDirty(); + } + } + return menu.getItemCount() != 0; + } + return false; + } } diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ActionBars.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ActionBars.java index 55dc3433325..999f5b62eb4 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ActionBars.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ActionBars.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2011 IBM Corporation and others. + * Copyright (c) 2010, 2012 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 @@ -13,10 +13,12 @@ package org.eclipse.ui.internal.e4.compatibility; import org.eclipse.e4.ui.model.application.ui.MElementContainer; import org.eclipse.e4.ui.model.application.ui.MGenericStack; +import org.eclipse.e4.ui.model.application.ui.MUIElement; import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder; import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.e4.ui.model.application.ui.menu.MToolBar; import org.eclipse.e4.ui.widgets.CTabFolder; +import org.eclipse.e4.ui.workbench.renderers.swt.StackRenderer; import org.eclipse.e4.ui.workbench.renderers.swt.ToolBarManagerRenderer; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; @@ -110,9 +112,31 @@ public class ActionBars extends SubActionBars { } } } + + MUIElement parent = getParentModel(); + if (parent != null) { + Object renderer = parent.getRenderer(); + if (renderer instanceof StackRenderer) { + StackRenderer stackRenderer = (StackRenderer) renderer; + CTabFolder folder = (CTabFolder) parent.getWidget(); + stackRenderer.disposeViewMenu(folder); + stackRenderer.setupMenuButton(part, folder); + stackRenderer.layoutTopRight(folder); + } + } + super.updateActionBars(); } + private MUIElement getParentModel() { + MElementContainer<MUIElement> parent = part.getParent(); + if (parent == null) { + MPlaceholder placeholder = part.getCurSharedRef(); + return placeholder == null ? null : placeholder.getParent(); + } + return parent; + } + private Control getPackParent(Control control) { Composite parent = control.getParent(); while (parent != null) { diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/CompatibilityView.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/CompatibilityView.java index 5ca44fac98e..1b9f8f8b6ed 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/CompatibilityView.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/CompatibilityView.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2011 IBM Corporation and others. + * Copyright (c) 2009, 2012 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 @@ -83,6 +83,15 @@ public class CompatibilityView extends CompatibilityPart { return reference; } + private MMenu getViewMenu() { + for (MMenu menu : part.getMenus()) { + if (menu.getTags().contains(StackRenderer.TAG_VIEW_MENU)) { + return menu; + } + } + return null; + } + /* * (non-Javadoc) * @@ -94,6 +103,9 @@ public class CompatibilityView extends CompatibilityPart { protected boolean createPartControl(IWorkbenchPart legacyPart, Composite parent) { part.getContext().set(IViewPart.class, (IViewPart) legacyPart); + IEclipseContext context = getModel().getContext(); + IRendererFactory rendererFactory = context.get(IRendererFactory.class); + // Some views (i.e. Console) require that the actual ToolBar be // instantiated before they are IActionBars actionBars = ((IViewPart) legacyPart).getViewSite().getActionBars(); @@ -101,22 +113,22 @@ public class CompatibilityView extends CompatibilityPart { Composite toolBarParent = new Composite(parent, SWT.NONE); tbm.createControl(toolBarParent); + MenuManager mm = (MenuManager) actionBars.getMenuManager(); + MMenu menu = getViewMenu(); + if (menu != null) { + AbstractPartRenderer apr = rendererFactory.getRenderer(menu, parent); + if (apr instanceof MenuManagerRenderer) { + MenuManagerRenderer renderer = (MenuManagerRenderer) apr; + renderer.linkModelToManager(menu, mm); + } + } + super.createPartControl(legacyPart, parent); // dispose the tb, it will be re-created when the tab is shown toolBarParent.dispose(); - IEclipseContext context = getModel().getContext(); - IRendererFactory rendererFactory = context.get(IRendererFactory.class); - - MenuManager mm = (MenuManager) actionBars.getMenuManager(); - MMenu menu = null; - for (MMenu me : part.getMenus()) { - if (me.getTags().contains(StackRenderer.TAG_VIEW_MENU)) { - menu = me; - break; - } - } + menu = getViewMenu(); if (menu == null) { menu = MenuFactoryImpl.eINSTANCE.createMenu(); menu.setElementId(part.getElementId()); |