From 2e552b65794281406a82349cb31b7ec22cd95c49 Mon Sep 17 00:00:00 2001
From: Florian Hoelzl <hoelzl@fortiss.org>
Date: Thu, 17 Mar 2011 16:05:52 +0000
Subject: [PATCH] Extended context menu service

---
 org.fortiss.tooling.kernel/trunk/plugin.xml   |  6 +-
 .../interfaces/ICustomMenuContributor.java    | 33 +++++++++++
 .../kernel/internal/ActionService.java        |  9 +--
 .../kernel/internal/ContextMenuService.java   | 58 +++++++++++++++++++
 .../internal/navigator/NavigatorViewPart.java | 42 +++++---------
 .../kernel/services/IActionService.java       |  4 +-
 .../kernel/services/IContextMenuService.java  | 11 ++++
 7 files changed, 127 insertions(+), 36 deletions(-)
 create mode 100644 org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/interfaces/ICustomMenuContributor.java

diff --git a/org.fortiss.tooling.kernel/trunk/plugin.xml b/org.fortiss.tooling.kernel/trunk/plugin.xml
index e6573c42a..f5fb82f82 100644
--- a/org.fortiss.tooling.kernel/trunk/plugin.xml
+++ b/org.fortiss.tooling.kernel/trunk/plugin.xml
@@ -48,7 +48,7 @@
          
       <menuContribution
             allPopups="false"
-            locationURI="popup:org.fortiss.tooling.kernel.model.navigator?before=repository">
+            locationURI="popup:org.fortiss.tooling.kernel.model.navigator?before=custom">
          <menu
                icon="icons/add.png"
                id="org.fortiss.tooling.kernel.model.navigator.newmenu"
@@ -69,6 +69,10 @@
                   id="org.fortiss.tooling.kernel.model.navigator.newmenu.content">
             </dynamic>
          </menu>
+      </menuContribution>
+      <menuContribution
+            allPopups="false"
+            locationURI="popup:org.fortiss.tooling.kernel.model.navigator?after=repository">
          <menu
                icon="icons/server.png"
                id="org.fortiss.tooling.kernel.model.navigator.repositorymenu"
diff --git a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/interfaces/ICustomMenuContributor.java b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/interfaces/ICustomMenuContributor.java
new file mode 100644
index 000000000..9f9704e41
--- /dev/null
+++ b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/interfaces/ICustomMenuContributor.java
@@ -0,0 +1,33 @@
+/*--------------------------------------------------------------------------+
+$Id$
+|                                                                          |
+| Copyright 2011 ForTISS GmbH                     |
+|                                                                          |
+| Licensed under the Apache License, Version 2.0 (the "License");          |
+| you may not use this file except in compliance with the License.         |
+| You may obtain a copy of the License at                                  |
+|                                                                          |
+|    http://www.apache.org/licenses/LICENSE-2.0                            |
+|                                                                          |
+| Unless required by applicable law or agreed to in writing, software      |
+| distributed under the License is distributed on an "AS IS" BASIS,        |
+| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+| See the License for the specific language governing permissions and      |
+| limitations under the License.                                           |
++--------------------------------------------------------------------------*/
+package org.fortiss.tooling.kernel.interfaces;
+
+import org.fortiss.tooling.kernel.services.IContextMenuService;
+
+/**
+ * Classes implementing this interface contribute custom menu entries or
+ * submenus to the context menu provided by the {@link IContextMenuService}.
+ * 
+ * @author hoelzlf
+ * @author $Author$
+ * @version $Rev$
+ * @levd.rating RED Rev:
+ */
+public interface ICustomMenuContributor {
+	// TODO (FH): implement
+}
diff --git a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/ActionService.java b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/ActionService.java
index abcfe4f8d..bcd0fd98a 100644
--- a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/ActionService.java
+++ b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/ActionService.java
@@ -21,8 +21,7 @@ import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.action.MenuManager;
-import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.action.IMenuManager;
 import org.eclipse.ui.IActionBars;
 import org.eclipse.ui.IEditorSite;
 import org.eclipse.ui.ISharedImages;
@@ -109,11 +108,7 @@ public class ActionService implements IActionService {
 
 	/** {@inheritDoc} */
 	@Override
-	public void addGlobalDefaultActionSectionToMenu(MenuManager menuManager) {
-		Separator globalDefaults = new Separator(GROUP_GLOBAL_DEFAULTS);
-		globalDefaults.setVisible(true);
-		menuManager.add(globalDefaults);
-
+	public void addGlobalDefaultActionSectionToMenu(IMenuManager menuManager) {
 		menuManager.appendToGroup(GROUP_GLOBAL_DEFAULTS, globalDeleteAction);
 		menuManager.appendToGroup(GROUP_GLOBAL_DEFAULTS, globalUndoAction);
 	}
diff --git a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/ContextMenuService.java b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/ContextMenuService.java
index d9945d0b0..5114c99b8 100644
--- a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/ContextMenuService.java
+++ b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/ContextMenuService.java
@@ -17,6 +17,13 @@ $Id$
 +--------------------------------------------------------------------------*/
 package org.fortiss.tooling.kernel.internal;
 
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.fortiss.tooling.kernel.interfaces.ICustomMenuContributor;
+import org.fortiss.tooling.kernel.services.IActionService;
 import org.fortiss.tooling.kernel.services.IContextMenuService;
 
 /**
@@ -29,4 +36,55 @@ import org.fortiss.tooling.kernel.services.IContextMenuService;
  */
 public class ContextMenuService implements IContextMenuService {
 
+	/** {@inheritDoc} */
+	@Override
+	public MenuManager createDefaultContextMenu(
+			ICustomMenuContributor menuContributor) {
+		MenuManager menuManager = new MenuManager("#PopupMenu");
+		menuManager.setRemoveAllWhenShown(true);
+		menuManager.addMenuListener(new MenuCreator(menuContributor));
+
+		Separator repositorySection = new Separator("repository");
+		repositorySection.setVisible(true);
+		menuManager.add(repositorySection);
+
+		return menuManager;
+	}
+
+	/** Wrapper class for menu creation. */
+	private static class MenuCreator implements IMenuListener {
+
+		/** Stores the custom menu contributor. */
+		private final ICustomMenuContributor contributor;
+
+		/** Constructor. */
+		public MenuCreator(ICustomMenuContributor contributor) {
+			this.contributor = contributor;
+		}
+
+		/** {@inheritDoc} */
+		@Override
+		public void menuAboutToShow(IMenuManager menu) {
+			if (!menu.isEmpty()) {
+				return;
+			}
+			addVisibleSectionSeparator(menu, CUSTOM_MENU_SEPARATOR_ID);
+			addVisibleSectionSeparator(menu,
+					ActionService.GROUP_GLOBAL_DEFAULTS);
+			addVisibleSectionSeparator(menu, REPOSITORY_MENU_SEPARATOR_ID);
+			addVisibleSectionSeparator(menu,
+					IWorkbenchActionConstants.MB_ADDITIONS);
+
+			// TODO (FH): add custom menu to custom section
+			IActionService.INSTANCE.addGlobalDefaultActionSectionToMenu(menu);
+		}
+	}
+
+	/** Adds a visible section separator. */
+	private static void addVisibleSectionSeparator(IMenuManager menu,
+			String sectionName) {
+		Separator separator = new Separator(sectionName);
+		separator.setVisible(true);
+		menu.add(separator);
+	}
 }
diff --git a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/navigator/NavigatorViewPart.java b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/navigator/NavigatorViewPart.java
index 1319e0c8d..568ca7101 100644
--- a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/navigator/NavigatorViewPart.java
+++ b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/internal/navigator/NavigatorViewPart.java
@@ -25,7 +25,6 @@ import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.common.notify.impl.AdapterImpl;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.jface.action.MenuManager;
-import org.eclipse.jface.action.Separator;
 import org.eclipse.jface.viewers.DecoratingLabelProvider;
 import org.eclipse.jface.viewers.DoubleClickEvent;
 import org.eclipse.jface.viewers.IDoubleClickListener;
@@ -34,11 +33,9 @@ import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.ui.IDecoratorManager;
 import org.eclipse.ui.ISelectionListener;
-import org.eclipse.ui.IWorkbenchActionConstants;
 import org.eclipse.ui.IWorkbenchPart;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.part.ViewPart;
@@ -49,6 +46,7 @@ import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
 import org.fortiss.tooling.kernel.ToolingKernelActivator;
 import org.fortiss.tooling.kernel.internal.NavigatorService;
 import org.fortiss.tooling.kernel.services.IActionService;
+import org.fortiss.tooling.kernel.services.IContextMenuService;
 import org.fortiss.tooling.kernel.services.IEditorService;
 import org.fortiss.tooling.kernel.services.INavigatorService;
 import org.fortiss.tooling.kernel.services.IPropertiesService;
@@ -178,23 +176,27 @@ public final class NavigatorViewPart extends ViewPart implements
 		viewer = new TreeViewer(parent, SWT.MULTI);
 
 		if (workspace != null) {
+			// NOTE that the order of this important. See also JDT package
+			// explorer.
 			IDecoratorManager decoratorManager = PlatformUI.getWorkbench()
 					.getDecoratorManager();
 			viewer.setLabelProvider(new DecoratingLabelProvider(
 					new NavigatorTreeLabelProvider(), decoratorManager
 							.getLabelDecorator()));
 			viewer.setContentProvider(new NavigatorTreeContentProvider());
+
+			createContextMenu();
+			getSite().setSelectionProvider(viewer);
+
 			viewer.setInput(workspace);
-			viewer.addDoubleClickListener(this);
-		}
 
-		createContextMenu();
+			viewer.addDoubleClickListener(this);
 
-		IActionService.INSTANCE.registerGlobalActions(getViewSite());
+			IActionService.INSTANCE.registerGlobalActions(getViewSite());
 
-		PlatformUI.getWorkbench().getActiveWorkbenchWindow()
-				.getSelectionService().addSelectionListener(this);
-		getSite().setSelectionProvider(viewer);
+			PlatformUI.getWorkbench().getActiveWorkbenchWindow()
+					.getSelectionService().addSelectionListener(this);
+		}
 
 		// FIXME: whats that good for?
 		// if (viewer.getTree().getItems().length > 0) {
@@ -205,25 +207,13 @@ public final class NavigatorViewPart extends ViewPart implements
 
 	/** Creates the context menu. */
 	private void createContextMenu() {
-		menuManager = new MenuManager("#PopupMenu");
-
-		Separator repositorySection = new Separator("repository");
-		repositorySection.setVisible(true);
-		menuManager.add(repositorySection);
+		menuManager = IContextMenuService.INSTANCE
+				.createDefaultContextMenu(null);
 
-		IActionService.INSTANCE
-				.addGlobalDefaultActionSectionToMenu(menuManager);
-
-		Separator additions = new Separator(
-				IWorkbenchActionConstants.MB_ADDITIONS);
-		additions.setVisible(true);
-		menuManager.add(additions);
+		Menu contextMenu = menuManager.createContextMenu(viewer.getControl());
+		viewer.getControl().setMenu(contextMenu);
 
 		getSite().registerContextMenu(menuManager, viewer);
-
-		Control control = viewer.getControl();
-		Menu menu = menuManager.createContextMenu(control);
-		control.setMenu(menu);
 	}
 
 	/** Creates the actions. */
diff --git a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/services/IActionService.java b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/services/IActionService.java
index a0c2c8196..d9ad1d071 100644
--- a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/services/IActionService.java
+++ b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/services/IActionService.java
@@ -17,7 +17,7 @@ $Id$
 +--------------------------------------------------------------------------*/
 package org.fortiss.tooling.kernel.services;
 
-import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.IMenuManager;
 import org.eclipse.ui.IEditorSite;
 import org.eclipse.ui.IViewSite;
 import org.fortiss.tooling.kernel.internal.ActionService;
@@ -43,7 +43,7 @@ public interface IActionService {
 	void registerGlobalActions(IEditorSite site);
 
 	/** Adds the global default actions like undo to the given context menu. */
-	void addGlobalDefaultActionSectionToMenu(MenuManager menuManager);
+	void addGlobalDefaultActionSectionToMenu(IMenuManager menuManager);
 
 	/** Updates the enabled state of the global actions. */
 	void update();
diff --git a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/services/IContextMenuService.java b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/services/IContextMenuService.java
index e17bd3f52..65d3712b6 100644
--- a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/services/IContextMenuService.java
+++ b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/services/IContextMenuService.java
@@ -17,6 +17,8 @@ $Id$
 +--------------------------------------------------------------------------*/
 package org.fortiss.tooling.kernel.services;
 
+import org.eclipse.jface.action.MenuManager;
+import org.fortiss.tooling.kernel.interfaces.ICustomMenuContributor;
 import org.fortiss.tooling.kernel.internal.ContextMenuService;
 
 /**
@@ -30,6 +32,15 @@ import org.fortiss.tooling.kernel.internal.ContextMenuService;
  */
 public interface IContextMenuService {
 
+	/** Custom menu section separator id. */
+	public static final String CUSTOM_MENU_SEPARATOR_ID = "custom";
+
+	/** Repository menu section separator id. */
+	public static final String REPOSITORY_MENU_SEPARATOR_ID = "repository";
+
 	/** Returns the singleton instance of the service. */
 	public static final IContextMenuService INSTANCE = new ContextMenuService();
+
+	/** Creates the default context menu provided by the kernel. */
+	MenuManager createDefaultContextMenu(ICustomMenuContributor menuContributor);
 }
-- 
GitLab