Bug 396975 - Provide find action for [ToolBar|Trim|Menu] contribution
elements

Change-Id: I52152edf92937c0c473a386f756eb8a7f36c2506
Signed-off-by: Marco Descher <marco@descher.at>

Bug 396975 - Provide find action for [ToolBar|Trim|Menu] contribution
elements

Change-Id: I52152edf92937c0c473a386f756eb8a7f36c2506
Signed-off-by: Marco Descher <marco@descher.at>
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.java
index e27edb7..8a78ad1 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.java
@@ -7,7 +7,7 @@
  *
  * Contributors:
  *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
- *     Marco Descher <marco@descher.at> - Bug 395982
+ *     Marco Descher <marco@descher.at> - Bug 395982, Bug 396975
  ******************************************************************************/
 package org.eclipse.e4.tools.emf.ui.internal;
 
@@ -585,6 +585,11 @@
 	public String ExpressionIdDialog_DialogMessage;
 	public String ExpressionIdDialog_Id;
 
+	public String MenuIdDialog_ShellTitle;
+	public String MenuIdDialog_DialogTitle;
+	public String MenuIdDialog_DialogMessage;
+	public String MenuIdDialog_Id;
+
 	public String CommandToStringConverter_None;
 
 	public String VRootBindingContexts_AddContext;
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.properties b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.properties
index 402fef0..2395d43 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.properties
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/Messages.properties
@@ -8,7 +8,7 @@
 # * Contributors:
 # *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
 # *		Sopot Cela <sopotcela@gmail.com> - enhancements
-# *     Marco Descher <marco@descher.at> - Bug 395982
+# *     Marco Descher <marco@descher.at> - Bug 395982, Bug 396975
 # ******************************************************************************
 ModelTooling_Common_Up=Up
 ModelTooling_Common_Down=Down
@@ -588,6 +588,11 @@
 ExpressionIdDialog_Id=ID
 CommandToStringConverter_None=<None>
 
+MenuIdDialog_ShellTitle=Find Parent Menu Id
+MenuIdDialog_DialogTitle=Find Parent Menu Id
+MenuIdDialog_DialogMessage=Find the menu id to be used as parent (in fragment finds the imported menus only)
+MenuIdDialog_Id=Parent Id 
+
 VRootBindingContexts_AddContext=Binding Context
 VRootBindingContexts_TreeLabel=Binding Context
 VRootBindingContexts_TreeLabelDescription=Binding Context Bla Bla Bla
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/MenuContributionEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/MenuContributionEditor.java
index 506f3f0..98dabb4 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/MenuContributionEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/MenuContributionEditor.java
@@ -7,7 +7,7 @@
  *
  * Contributors:
  *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
- *     Marco Descher <marco@descher.at> - Bug 397650, Bug 395982
+ *     Marco Descher <marco@descher.at> - Bug 397650, Bug 395982, Bug 396975
  ******************************************************************************/
 package org.eclipse.e4.tools.emf.ui.internal.common.component;
 
@@ -19,16 +19,21 @@
 import org.eclipse.core.databinding.observable.value.WritableValue;
 import org.eclipse.core.databinding.property.list.IListProperty;
 import org.eclipse.e4.tools.emf.ui.common.EStackLayout;
+import org.eclipse.e4.tools.emf.ui.common.IModelResource;
 import org.eclipse.e4.tools.emf.ui.common.Util;
 import org.eclipse.e4.tools.emf.ui.common.component.AbstractComponentEditor;
 import org.eclipse.e4.tools.emf.ui.internal.ResourceProvider;
 import org.eclipse.e4.tools.emf.ui.internal.common.ComponentLabelProvider;
+import org.eclipse.e4.tools.emf.ui.internal.common.component.ControlFactory.TextPasteHandler;
+import org.eclipse.e4.tools.emf.ui.internal.common.component.dialogs.MenuIdDialog;
 import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl;
 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.impl.UiPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution;
 import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
 import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuPackageImpl;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
 import org.eclipse.emf.common.command.Command;
 import org.eclipse.emf.databinding.EMFDataBindingContext;
 import org.eclipse.emf.databinding.EMFProperties;
@@ -63,6 +68,7 @@
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
 
 public class MenuContributionEditor extends AbstractComponentEditor {
 	private Composite composite;
@@ -72,6 +78,12 @@
 	private EStackLayout stackLayout;
 	private List<Action> actions = new ArrayList<Action>();
 
+	@Inject
+	private IModelResource resource;
+
+	@Inject
+	private EModelService modelService;
+
 	private static class Struct {
 		private final String label;
 		private final EClass eClass;
@@ -207,7 +219,31 @@
 
 		ControlFactory.createTextField(parent, Messages.ModelTooling_Common_Id, master, context, textProp, EMFEditProperties.value(getEditingDomain(), ApplicationPackageImpl.Literals.APPLICATION_ELEMENT__ELEMENT_ID));
 		ControlFactory.createTextField(parent, Messages.ModelTooling_UIElement_AccessibilityPhrase, getMaster(), context, textProp, EMFEditProperties.value(getEditingDomain(), UiPackageImpl.Literals.UI_ELEMENT__ACCESSIBILITY_PHRASE));
-		ControlFactory.createTextField(parent, Messages.MenuContributionEditor_ParentId, master, context, textProp, EMFEditProperties.value(getEditingDomain(), MenuPackageImpl.Literals.MENU_CONTRIBUTION__PARENT_ID));
+
+		{
+			Label l = new Label(parent, SWT.NONE);
+			l.setText(Messages.MenuContributionEditor_ParentId);
+			l.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
+
+			final Text t = new Text(parent, SWT.BORDER);
+			TextPasteHandler.createFor(t);
+			GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+			t.setLayoutData(gd);
+			context.bindValue(textProp.observeDelayed(200, t), EMFEditProperties.value(getEditingDomain(), MenuPackageImpl.Literals.MENU_CONTRIBUTION__PARENT_ID).observeDetail(getMaster()));
+
+			Button b = new Button(parent, SWT.PUSH | SWT.FLAT);
+			b.setText(Messages.ModelTooling_Common_FindEllipsis);
+			b.setImage(createImage(ResourceProvider.IMG_Obj16_zoom));
+			b.addSelectionListener(new SelectionAdapter() {
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					MenuIdDialog dialog = new MenuIdDialog(t.getShell(), resource, (MMenuContribution) getMaster().getValue(), getEditingDomain(), modelService, Messages);
+					dialog.open();
+				}
+			});
+
+		}
+
 		ControlFactory.createTextField(parent, Messages.MenuContributionEditor_Position, master, context, textProp, EMFEditProperties.value(getEditingDomain(), MenuPackageImpl.Literals.MENU_CONTRIBUTION__POSITION_IN_PARENT));
 
 		// ------------------------------------------------------------
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/dialogs/MenuIdDialog.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/dialogs/MenuIdDialog.java
new file mode 100644
index 0000000..d5b1226
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/dialogs/MenuIdDialog.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (c) 2013 MEDEVIT, FHV 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:
+ *     Marco Descher <marco@descher.at> - initial implementation (Bug 396975)
+ *******************************************************************************/
+package org.eclipse.e4.tools.emf.ui.internal.common.component.dialogs;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.e4.tools.emf.ui.common.IModelResource;
+import org.eclipse.e4.tools.emf.ui.internal.Messages;
+import org.eclipse.e4.tools.emf.ui.internal.PatternFilter;
+import org.eclipse.e4.tools.emf.ui.internal.common.component.ControlFactory;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.MApplicationElement;
+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.MMenu;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolItem;
+import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuPackageImpl;
+import org.eclipse.e4.ui.model.fragment.MModelFragments;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.edit.command.SetCommand;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StyledCellLabelProvider;
+import org.eclipse.jface.viewers.StyledString;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerCell;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+public class MenuIdDialog extends TitleAreaDialog {
+
+	private EModelService modelService;
+	private TableViewer viewer;
+	private EditingDomain domain;
+	private IModelResource resource;
+	private MMenuContribution menuContribution;
+	private Messages messages;
+
+	public MenuIdDialog(Shell parentShell, IModelResource resource, MMenuContribution menuContribution, EditingDomain domain, EModelService modelService, Messages Messages) {
+		super(parentShell);
+		this.resource = resource;
+		this.modelService = modelService;
+		this.messages = Messages;
+		this.domain = domain;
+		this.menuContribution = menuContribution;
+	}
+
+	@Override
+	protected Control createDialogArea(Composite parent) {
+		getShell().setText(messages.MenuIdDialog_ShellTitle);
+		setTitle(messages.MenuIdDialog_DialogTitle);
+		setMessage(messages.MenuIdDialog_DialogMessage);
+		Composite comp = (Composite) super.createDialogArea(parent);
+		Composite container = new Composite(comp, SWT.NONE);
+		container.setLayoutData(new GridData(GridData.FILL_BOTH));
+		container.setLayout(new GridLayout(2, false));
+
+		Label l = new Label(container, SWT.NONE);
+		l.setText(messages.MenuIdDialog_Id);
+
+		Text idField = new Text(container, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH);
+		idField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		final PatternFilter filter = new PatternFilter() {
+			@Override
+			protected boolean isParentMatch(Viewer viewer, Object element) {
+				return viewer instanceof AbstractTreeViewer && super.isParentMatch(viewer, element);
+			}
+		};
+
+		l = new Label(container, SWT.NONE);
+		viewer = new TableViewer(container);
+		viewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
+		viewer.setContentProvider(new ArrayContentProvider());
+		viewer.setLabelProvider(new LabelProviderImpl());
+		viewer.addFilter(filter);
+		viewer.addDoubleClickListener(new IDoubleClickListener() {
+
+			public void doubleClick(DoubleClickEvent event) {
+				okPressed();
+			}
+		});
+
+		ControlFactory.attachFiltering(idField, viewer, filter);
+
+		if (resource.getRoot().get(0) instanceof MApplication) {
+			List<MMenu> list = new ArrayList<MMenu>();
+			// include Window main-menu instances
+			MApplication ma = ((MApplication) resource.getRoot().get(0));
+			for (MWindow m : ma.getChildren()) {
+				list.add(m.getMainMenu());
+			}
+			// include menu elements located within parts
+			List<MPart> mp = modelService.findElements(ma, null, MPart.class, null);
+			for (MPart mPart : mp) {
+				list.addAll(mPart.getMenus());
+			}
+			// include menu elements carried by tool items
+			List<MToolItem> mt = modelService.findElements(ma, null, MToolItem.class, null);
+			for (MToolItem mToolItem : mt) {
+				if (mToolItem.getMenu() != null)
+					list.add(mToolItem.getMenu());
+			}
+
+			for (MMenu mMenuEntry : list.toArray(new MMenu[] {})) {
+				performRecursiveCheck(mMenuEntry, list);
+			}
+
+			viewer.setInput(list);
+
+		} else if (resource.getRoot().get(0) instanceof MModelFragments) {
+			List<MApplicationElement> list = new ArrayList<MApplicationElement>();
+			for (MApplicationElement f : ((MModelFragments) resource.getRoot().get(0)).getImports()) {
+				if (f instanceof MMenu) {
+					list.add(f);
+				}
+			}
+			viewer.setInput(list);
+
+		}
+
+		return comp;
+	}
+
+	/**
+	 * A menu may contain another {@link MMenu} as a child; we want them to be
+	 * shown as an additional entry, so we recursively dive into these elements
+	 * 
+	 * @param mMenu
+	 * @param list
+	 */
+	private void performRecursiveCheck(MMenu mMenu, List<MMenu> list) {
+		List<MMenuElement> children = mMenu.getChildren();
+		for (MMenuElement child : children) {
+			if (child instanceof MMenu) {
+				MMenu mMenuChild = (MMenu) child;
+				list.add(mMenuChild);
+				performRecursiveCheck(mMenuChild, list);
+			}
+		}
+	}
+
+	@Override
+	protected void okPressed() {
+		if (!viewer.getSelection().isEmpty()) {
+			MMenu el = (MMenu) ((IStructuredSelection) viewer.getSelection()).getFirstElement();
+			Command cmd = SetCommand.create(domain, menuContribution, MenuPackageImpl.Literals.MENU_CONTRIBUTION__PARENT_ID, el.getElementId());
+			if (cmd.canExecute()) {
+				domain.getCommandStack().execute(cmd);
+				super.okPressed();
+			}
+		}
+	}
+
+	static class LabelProviderImpl extends StyledCellLabelProvider {
+		@Override
+		public void update(ViewerCell cell) {
+			MMenu el = (MMenu) cell.getElement();
+			String elementId = (el.getElementId() != null) ? el.getElementId() : "(Id missing)";
+			StyledString str = new StyledString(elementId);
+			str.append(" - " + el.getLabel(), StyledString.DECORATIONS_STYLER); //$NON-NLS-1$
+			cell.setText(str.getString());
+			cell.setStyleRanges(str.getStyleRanges());
+		}
+	}
+}
\ No newline at end of file