Bug 496833 - [Tools] Application model editor doesn’t allow to create a
ToolBar for a CompositePart

Create abstract superclass for Part Editors, extend GUI for
CompositePart-Editors. Add VControlsEditor to configure sub-parts of
CompositeParts

Change-Id: Iefae092e39791c4a0cc3050cbbb6d3e8023a6606
Signed-off-by: Benedikt Kuntz <benedikt.kuntz@airbus.com>
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 efdcdbf..5190449 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
@@ -277,6 +277,7 @@
 	public String PartEditor_ContainerData;
 	public String PartEditor_ToolBar;
 	public String PartEditor_BindingContexts;
+	public String PartEditor_Controls;
 
 	public String PartSashContainerEditor_Label;
 	public String PartSashContainerEditor_Description;
@@ -509,6 +510,9 @@
 	public String VHandlerEditor_Handlers;
 	public String VHandlerEditor_AddHandler;
 
+	public String VControlsEditor_TreeLabel;
+	public String VControlsEditor_TreeLabelDescription;
+
 	public String VMenuContributionsEditor_TreeLabel;
 	public String VMenuContributionsEditor_TreeLabelDescription;
 	public String VMenuContributionsEditor_MenuContributions;
@@ -799,11 +803,6 @@
 	public String CompositePartEditor_Horizontal;
 	public String CompositePartEditor_Vertical;
 	public String CompositePartEditor_SelectedElement;
-	public String CompositePartEditor_ContainerData;
 	public String CompositePartEditor_Controls;
-	public String CompositePartEditor_LabelLabel;
-	public String CompositePartEditor_Tooltip;
-	public String CompositePartEditor_IconURI;
-	public String CompositePartEditor_IconURI_Tooltip;
 
 }
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 11afd83..d0c8650 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
@@ -238,6 +238,7 @@
 PartEditor_ContainerData=Container &Data\:
 PartEditor_ToolBar=ToolBar
 PartEditor_BindingContexts=Binding Contexts
+PartEditor_Controls=Controls
 
 PartSashContainerEditor_Label=Part Sash Container
 PartSashContainerEditor_Description=Sash
@@ -484,6 +485,9 @@
 VHandlerEditor_Handlers=Handlers
 VHandlerEditor_AddHandler=Handler
 
+VControlsEditor_TreeLabel=Controls
+VControlsEditor_TreeLabelDescription=Controls
+
 VMenuContributionsEditor_TreeLabel=Menu Contributions
 VMenuContributionsEditor_TreeLabelDescription=Menu Contributions
 VMenuContributionsEditor_MenuContributions=Menu Contributions
@@ -806,9 +810,4 @@
 CompositePartEditor_Horizontal=Horizontal
 CompositePartEditor_Vertical=Vertical
 CompositePartEditor_SelectedElement=&Selected Element\:
-CompositePartEditor_ContainerData=Container &Data\:
-CompositePartEditor_Controls=&Controls\:
-CompositePartEditor_LabelLabel=L&abel\:
-CompositePartEditor_Tooltip=T&ooltip\:
-CompositePartEditor_IconURI=&Icon URI\:
-CompositePartEditor_IconURI_Tooltip=Choose the icon of your part here
\ No newline at end of file
+CompositePartEditor_Controls=&Controls\:
\ No newline at end of file
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java
index cb62542..053c33d 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/ModelEditor.java
@@ -124,6 +124,7 @@
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VApplicationWindowEditor;
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VBindingTableEditor;
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VCommandEditor;
+import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VControlsEditor;
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VHandlerEditor;
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VItemParametersEditor;
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VMenuContributionsEditor;
@@ -251,6 +252,7 @@
 
 	public static final String VIRTUAL_PART_MENU = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PART_MENU"; //$NON-NLS-1$
 	public static final String VIRTUAL_HANDLER = "org.eclipse.e4.tools.emf.ui.VIRTUAL_HANDLER"; //$NON-NLS-1$
+	public static final String VIRTUAL_CONTROLS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_CONTROLS"; //$NON-NLS-1$
 	public static final String VIRTUAL_BINDING_TABLE = "org.eclipse.e4.tools.emf.ui.VIRTUAL_BINDING_TABLE"; //$NON-NLS-1$
 	public static final String VIRTUAL_COMMAND = "org.eclipse.e4.tools.emf.ui.VIRTUAL_COMMAND"; //$NON-NLS-1$
 	public static final String VIRTUAL_APPLICATION_WINDOWS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_APPLICATION_WINDOWS"; //$NON-NLS-1$
@@ -280,6 +282,7 @@
 	public static final int TAB_XMI = 1;
 	public static final int TAB_LIST = 2;
 
+
 	/**
 	 * A map with key = eClass name or virtual key, value is an
 	 * AbstractComponentEditor instance This map is filled on the fly when getting
@@ -1140,6 +1143,7 @@
 	private void registerVirtualEditors() {
 		registerEditor(VIRTUAL_PART_MENU, VPartMenuEditor.class);
 		registerEditor(VIRTUAL_HANDLER, VHandlerEditor.class);
+		registerEditor(VIRTUAL_CONTROLS, VControlsEditor.class);
 		registerEditor(VIRTUAL_BINDING_TABLE, VBindingTableEditor.class);
 		registerEditor(VIRTUAL_COMMAND, VCommandEditor.class);
 		registerEditor(VIRTUAL_APPLICATION_WINDOWS, VApplicationWindowEditor.class);
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/AbstractPartEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/AbstractPartEditor.java
new file mode 100644
index 0000000..67e42cc
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/AbstractPartEditor.java
@@ -0,0 +1,363 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Airbus Defence and Space GmbH and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Benedikt Kuntz <benedikt.kuntz@airbus.com> - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.tools.emf.ui.internal.common.component;
+
+import javax.inject.Inject;
+
+import org.eclipse.core.databinding.observable.list.IObservableList;
+import org.eclipse.core.databinding.observable.list.WritableList;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
+import org.eclipse.core.databinding.observable.value.WritableValue;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.tools.emf.ui.common.ImageTooltip;
+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.E4Properties;
+import org.eclipse.e4.tools.emf.ui.internal.common.ModelEditor;
+import org.eclipse.e4.tools.emf.ui.internal.common.VirtualEntry;
+import org.eclipse.e4.tools.emf.ui.internal.common.component.ControlFactory.TextPasteHandler;
+import org.eclipse.e4.tools.emf.ui.internal.common.component.dialogs.PartIconDialogEditor;
+import org.eclipse.e4.tools.emf.ui.internal.common.objectdata.ObjectViewer;
+import org.eclipse.e4.tools.emf.ui.internal.common.uistructure.UIViewer;
+import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.impl.UiPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.databinding.EMFDataBindingContext;
+import org.eclipse.emf.databinding.FeaturePath;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.edit.command.SetCommand;
+import org.eclipse.jface.databinding.swt.IWidgetValueProperty;
+import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+public abstract class AbstractPartEditor<M extends MPart> extends AbstractComponentEditor<M> {
+	private Composite composite;
+	private EMFDataBindingContext context;
+	private Button createRemoveToolBarButton;
+	private StackLayout stackLayout;
+
+	@Inject
+	@Optional
+	private IProject project;
+
+	@Inject
+	private IEclipseContext eclipseContext;
+
+	@Inject
+	public AbstractPartEditor() {
+		super();
+	}
+
+	@Override
+	public FeaturePath[] getLabelProperties() {
+		return new FeaturePath[] { FeaturePath.fromList(UiPackageImpl.Literals.GENERIC_TILE__HORIZONTAL),
+				FeaturePath.fromList(UiPackageImpl.Literals.UI_ELEMENT__TO_BE_RENDERED) };
+	}
+
+	@Override
+	public String getDetailLabel(Object element) {
+		return null;
+	}
+
+	@Override
+	public Composite doGetEditor(Composite parent, Object object) {
+		if (composite == null) {
+			context = new EMFDataBindingContext();
+			if (getEditor().isModelFragment()) {
+				composite = new Composite(parent, SWT.NONE);
+				stackLayout = new StackLayout();
+				composite.setLayout(stackLayout);
+				createForm(composite, context, getMaster(), false);
+				createForm(composite, context, getMaster(), true);
+			} else {
+				composite = createForm(parent, context, getMaster(), false);
+			}
+		}
+
+		if (getEditor().isModelFragment()) {
+			Control topControl;
+			if (Util.isImport((EObject) object)) {
+				topControl = composite.getChildren()[1];
+			} else {
+				topControl = composite.getChildren()[0];
+			}
+
+			if (stackLayout.topControl != topControl) {
+				stackLayout.topControl = topControl;
+				composite.layout(true, true);
+			}
+		}
+
+		if (createRemoveToolBarButton != null) {
+			createRemoveToolBarButton.setSelection(((MPart) object).getToolbar() != null);
+		}
+
+		return composite;
+	}
+
+	protected Composite createForm(Composite parent, final EMFDataBindingContext context,
+			WritableValue<M> master, boolean isImport) {
+
+		final CTabFolder folder = new CTabFolder(parent, SWT.BOTTOM);
+
+		CTabItem item = new CTabItem(folder, SWT.BORDER);
+		item.setText(Messages.ModelTooling_Common_TabDefault);
+
+		parent = createScrollableContainer(folder);
+		item.setControl(parent.getParent());
+
+		if (getEditor().isShowXMIId() || getEditor().isLiveModel()) {
+			ControlFactory.createXMIId(parent, this);
+		}
+
+		final IWidgetValueProperty<Text, String> textProp = WidgetProperties.text(SWT.Modify);
+
+		if (isImport) {
+			ControlFactory.createFindImport(parent, Messages, this, context);
+			folder.setSelection(0);
+			return folder;
+		}
+
+		ControlFactory.createTextField(parent, Messages.ModelTooling_Common_Id, master, context, textProp,
+				E4Properties.elementId(getEditingDomain()));
+		ControlFactory.createTextField(parent, Messages.PartEditor_LabelLabel, master, context, textProp,
+				E4Properties.label(getEditingDomain()));
+		ControlFactory.createTextField(parent, Messages.ModelTooling_UIElement_AccessibilityPhrase, master, context,
+				textProp, E4Properties.accessibilityPhrase(getEditingDomain()));
+		ControlFactory.createTextField(parent, Messages.PartEditor_Tooltip, master, context, textProp,
+				E4Properties.tooltip(getEditingDomain()));
+
+		// ------------------------------------------------------------
+		{
+			final Label l = new Label(parent, SWT.NONE);
+			l.setText(Messages.PartEditor_IconURI);
+			l.setLayoutData(new GridData());
+			l.setToolTipText(Messages.PartEditor_IconURI_Tooltip);
+
+			final Text t = new Text(parent, SWT.BORDER);
+			TextPasteHandler.createFor(t);
+			t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+			context.bindValue(
+					textProp.observeDelayed(200, t),
+					E4Properties.iconUri(getEditingDomain()).observeDetail(master));
+
+			new ImageTooltip(t, Messages, this);
+
+			Button b = ControlFactory.createFindButton(parent, resourcePool);
+			b.addSelectionListener(new SelectionAdapter() {
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					final PartIconDialogEditor dialog = new PartIconDialogEditor(b.getShell(), eclipseContext, project,
+							getEditingDomain(), getMaster().getValue(), Messages);
+					dialog.open();
+				}
+			});
+		}
+
+
+		ControlFactory.createClassURIField(parent, Messages, this, Messages.PartEditor_ClassURI,
+				ApplicationPackageImpl.Literals.CONTRIBUTION__CONTRIBUTION_URI,
+				getEditor().getContributionCreator(BasicPackageImpl.Literals.PART), project, context, eclipseContext);
+
+		// ------------------------------------------------------------
+		ControlFactory.createTextField(parent, Messages.PartEditor_ContainerData, master, context, textProp,
+				E4Properties.containerData(getEditingDomain()));
+
+		createSubformElements(parent, context, master);
+
+		{
+			final Label l = new Label(parent, SWT.NONE);
+			l.setText(Messages.PartEditor_ToolBar);
+			l.setLayoutData(new GridData());
+
+			createRemoveToolBarButton = new Button(parent, SWT.CHECK);
+			createRemoveToolBarButton.addSelectionListener(new SelectionAdapter() {
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					final MPart window = getMaster().getValue();
+					if (window.getToolbar() == null) {
+						addToolBar();
+					} else {
+						removeToolBar();
+					}
+				}
+			});
+			createRemoveToolBarButton
+			.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false, 2, 1));
+		}
+
+		ControlFactory.createCheckBox(parent, Messages.PartEditor_Closeable, Messages.PartEditor_Closeable_Tooltip,
+				getMaster(), context, WidgetProperties.buttonSelection(),
+				E4Properties.partClosable(getEditingDomain()));
+
+		// ------------------------------------------------------------
+		ControlFactory.createCheckBox(parent, Messages.ModelTooling_UIElement_ToBeRendered, getMaster(), context,
+				WidgetProperties.buttonSelection(), E4Properties.toBeRendered(getEditingDomain()));
+		ControlFactory.createCheckBox(parent, Messages.ModelTooling_UIElement_Visible, getMaster(), context,
+				WidgetProperties.buttonSelection(), E4Properties.visible(getEditingDomain()));
+
+		ControlFactory.createBindingContextWiget(parent, Messages, this, Messages.PartEditor_BindingContexts);
+		ControlFactory.createMapProperties(parent, Messages, this, Messages.ModelTooling_Contribution_PersistedState,
+				ApplicationPackageImpl.Literals.APPLICATION_ELEMENT__PERSISTED_STATE, VERTICAL_LIST_WIDGET_INDENT);
+		ControlFactory.createMapProperties(parent, Messages, this, Messages.ModelTooling_Context_Properties,
+				UiPackageImpl.Literals.CONTEXT__PROPERTIES, VERTICAL_LIST_WIDGET_INDENT);
+
+		item = new CTabItem(folder, SWT.NONE);
+		item.setText(Messages.ModelTooling_Common_TabSupplementary);
+
+		parent = createScrollableContainer(folder);
+		item.setControl(parent.getParent());
+
+		ControlFactory.createStringListWidget(parent, Messages, this, Messages.ModelTooling_Context_Variables,
+				Messages.ModelTooling_Context_Variables_Tooltip, UiPackageImpl.Literals.CONTEXT__VARIABLES,
+				VERTICAL_LIST_WIDGET_INDENT);
+		ControlFactory.createStringListWidget(parent, Messages, this, Messages.CategoryEditor_Tags,
+				ApplicationPackageImpl.Literals.APPLICATION_ELEMENT__TAGS, VERTICAL_LIST_WIDGET_INDENT);
+
+		if (project == null) {
+			createInstanceInspection(folder);
+			createUITreeInspection(folder);
+		}
+
+		createContributedEditorTabs(folder, context, getMaster(), MPart.class);
+
+		folder.setSelection(0);
+
+		return folder;
+	}
+
+	protected void createSubformElements(Composite parent, EMFDataBindingContext context,
+			IObservableValue<M> master) {
+		// add nothing as default, allow to be overwritten
+	}
+
+	protected void addToolBar() {
+		final MToolBar menu = MMenuFactory.INSTANCE.createToolBar();
+		setElementId(menu);
+
+		final Command cmd = SetCommand.create(getEditingDomain(), getMaster().getValue(),
+				BasicPackageImpl.Literals.PART__TOOLBAR, menu);
+		if (cmd.canExecute()) {
+			getEditingDomain().getCommandStack().execute(cmd);
+		}
+	}
+
+	protected void removeToolBar() {
+		final Command cmd = SetCommand.create(getEditingDomain(), getMaster().getValue(),
+				BasicPackageImpl.Literals.PART__TOOLBAR, null);
+		if (cmd.canExecute()) {
+			getEditingDomain().getCommandStack().execute(cmd);
+		}
+	}
+
+	private void createInstanceInspection(CTabFolder folder) {
+		final CTabItem item = new CTabItem(folder, SWT.NONE);
+		item.setText(Messages.ModelTooling_Common_RuntimeContributionInstance);
+		final Composite container = new Composite(folder, SWT.NONE);
+		container.setLayout(new GridLayout());
+		item.setControl(container);
+
+		final ObjectViewer objectViewer = new ObjectViewer();
+		final TreeViewer viewer = objectViewer.createViewer(container,
+				ApplicationPackageImpl.Literals.CONTRIBUTION__OBJECT, getMaster(), resourcePool, Messages);
+		viewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
+	}
+
+	private void createUITreeInspection(CTabFolder folder) {
+		final CTabItem item = new CTabItem(folder, SWT.NONE);
+		item.setText(Messages.ModelTooling_Common_RuntimeWidgetTree);
+		final Composite container = new Composite(folder, SWT.NONE);
+		container.setLayout(new GridLayout());
+		item.setControl(container);
+
+		final UIViewer objectViewer = new UIViewer();
+		final TreeViewer viewer = objectViewer.createViewer(container, UiPackageImpl.Literals.UI_ELEMENT__WIDGET,
+				getMaster(), resourcePool, Messages);
+		viewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
+	}
+
+	@Override
+	public IObservableList<?> getChildList(Object element) {
+		final WritableList<Object> list = new WritableList<>();
+		final MPart part = (MPart) element;
+
+		if (getEditor().isModelFragment() && Util.isImport((EObject) element)) {
+			return list;
+		}
+
+		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_PART_MENU, E4Properties.partMenus(), part,
+				Messages.PartEditor_Menus));
+		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_HANDLER, E4Properties.handlers(), part,
+				Messages.PartEditor_Handlers));
+
+		if (part.getToolbar() != null) {
+			list.add(0, part.getToolbar());
+		}
+
+		E4Properties.partToolbar().observe(part).addValueChangeListener(event -> {
+			if (event.diff.getOldValue() != null) {
+				list.remove(event.diff.getOldValue());
+				if (getMaster().getValue() == element && !createRemoveToolBarButton.isDisposed()) {
+					createRemoveToolBarButton.setSelection(false);
+				}
+
+			}
+
+			if (event.diff.getNewValue() != null) {
+				list.add(0, event.diff.getNewValue());
+				if (getMaster().getValue() == element && !createRemoveToolBarButton.isDisposed()) {
+					createRemoveToolBarButton.setSelection(true);
+				}
+			}
+		});
+
+		addChildListEntries(part, list);
+
+		return list;
+	}
+
+
+	protected void addChildListEntries(MPart part, IObservableList<Object> list) {
+		// add nothing by default, allow to be overwritten
+	}
+
+
+	@Override
+	public void dispose() {
+		super.dispose();
+		if (context != null) {
+			context.dispose();
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/CompositePartEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/CompositePartEditor.java
index 97595e7..bf583e3 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/CompositePartEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/CompositePartEditor.java
@@ -7,25 +7,18 @@
 import javax.inject.Inject;
 
 import org.eclipse.core.databinding.observable.list.IObservableList;
-import org.eclipse.core.databinding.observable.value.WritableValue;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.e4.core.contexts.IEclipseContext;
-import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.core.databinding.observable.value.IObservableValue;
 import org.eclipse.e4.tools.emf.ui.common.IEditorFeature.FeatureClass;
-import org.eclipse.e4.tools.emf.ui.common.ImageTooltip;
 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.E4Properties;
 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.FeatureClassLabelProvider;
 import org.eclipse.e4.tools.emf.ui.internal.common.ModelEditor;
-import org.eclipse.e4.tools.emf.ui.internal.common.component.ControlFactory.TextPasteHandler;
-import org.eclipse.e4.tools.emf.ui.internal.common.component.dialogs.PartIconDialogEditor;
-import org.eclipse.e4.tools.emf.ui.internal.common.uistructure.UIViewer;
+import org.eclipse.e4.tools.emf.ui.internal.common.VirtualEntry;
 import org.eclipse.e4.tools.emf.ui.internal.imp.ModelImportWizard;
 import org.eclipse.e4.tools.emf.ui.internal.imp.RegistryUtil;
-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.advanced.impl.AdvancedPackageImpl;
 import org.eclipse.e4.ui.model.application.ui.basic.MCompositePart;
@@ -42,12 +35,10 @@
 import org.eclipse.emf.edit.command.AddCommand;
 import org.eclipse.emf.edit.command.RemoveCommand;
 import org.eclipse.jface.action.Action;
-import org.eclipse.jface.databinding.swt.IWidgetValueProperty;
-import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
 import org.eclipse.jface.databinding.viewers.IViewerValueProperty;
 import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
 import org.eclipse.jface.databinding.viewers.typed.ViewerProperties;
-import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
 import org.eclipse.jface.resource.FontDescriptor;
 import org.eclipse.jface.viewers.ArrayContentProvider;
 import org.eclipse.jface.viewers.ComboViewer;
@@ -56,50 +47,28 @@
 import org.eclipse.jface.viewers.LabelProvider;
 import org.eclipse.jface.viewers.StructuredSelection;
 import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.jface.window.Window;
 import org.eclipse.jface.wizard.WizardDialog;
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.CTabFolder;
-import org.eclipse.swt.custom.CTabItem;
-import org.eclipse.swt.custom.StackLayout;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Button;
 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 CompositePartEditor extends AbstractComponentEditor<MCompositePart> {
-	private Composite composite;
-	private EMFDataBindingContext context;
-	private StackLayout stackLayout;
+public class CompositePartEditor extends AbstractPartEditor<MCompositePart> {
 	private final List<Action> actions = new ArrayList<>();
 	private final List<Action> actionsImport = new ArrayList<>();
 
 	@Inject
-	@Optional
-	private IProject project;
-
-	@Inject
 	private Shell shell;
 
-	@Inject
-	IEclipseContext eclipseContext;
-
-	@Inject
-	public CompositePartEditor() {
-		super();
-	}
-
 	@PostConstruct
-	void init() {
+	protected void init() {
 		actions.add(new Action(Messages.CompositePartEditor_AddPartSashContainer,
 				createImageDescriptor(ResourceProvider.IMG_PartSashContainer)) {
 			@Override
@@ -167,7 +136,6 @@
 
 		return horizontal ? getImage(element, ResourceProvider.IMG_PartSashContainer)
 				: getImage(element, ResourceProvider.IMG_PartSashContainer_vertical);
-
 	}
 
 	@Override
@@ -176,101 +144,27 @@
 	}
 
 	@Override
+	public FeaturePath[] getLabelProperties() {
+		return new FeaturePath[] { FeaturePath.fromList(UiPackageImpl.Literals.GENERIC_TILE__HORIZONTAL),
+				FeaturePath.fromList(UiPackageImpl.Literals.UI_ELEMENT__TO_BE_RENDERED) };
+	}
+
+	@Override
 	public String getDescription(Object element) {
 		return Messages.CompositePartEditor_Description;
 	}
 
 	@Override
 	public Composite doGetEditor(Composite parent, Object object) {
-		if (composite == null) {
-			context = new EMFDataBindingContext();
-			if (getEditor().isModelFragment()) {
-				composite = new Composite(parent, SWT.NONE);
-				stackLayout = new StackLayout();
-				composite.setLayout(stackLayout);
-				createForm(composite, context, getMaster(), false);
-				createForm(composite, context, getMaster(), true);
-			} else {
-				composite = createForm(parent, context, getMaster(), false);
-			}
-		}
-
-		if (getEditor().isModelFragment()) {
-			Control topControl;
-			if (Util.isImport((EObject) object)) {
-				topControl = composite.getChildren()[1];
-			} else {
-				topControl = composite.getChildren()[0];
-			}
-
-			if (stackLayout.topControl != topControl) {
-				stackLayout.topControl = topControl;
-				composite.layout(true, true);
-			}
-		}
-
+		Composite composite = super.doGetEditor(parent, object);
 		getMaster().setValue((MCompositePart) object);
 		return composite;
 	}
 
-	private Composite createForm(Composite parent, final EMFDataBindingContext context,
-			WritableValue<MCompositePart> master, boolean isImport) {
-		final CTabFolder folder = new CTabFolder(parent, SWT.BOTTOM);
+	@Override
+	protected void createSubformElements(Composite parent, EMFDataBindingContext context,
+			IObservableValue<MCompositePart> master) {
 
-		CTabItem item = new CTabItem(folder, SWT.NONE);
-		item.setText(Messages.ModelTooling_Common_TabDefault);
-
-		parent = createScrollableContainer(folder);
-		item.setControl(parent.getParent());
-
-		if (getEditor().isShowXMIId() || getEditor().isLiveModel()) {
-			ControlFactory.createXMIId(parent, this);
-		}
-
-		final IWidgetValueProperty<Text, String> textProp = WidgetProperties.text(SWT.Modify);
-
-		if (isImport) {
-			ControlFactory.createFindImport(parent, Messages, this, context);
-			folder.setSelection(0);
-			return folder;
-		}
-
-		ControlFactory.createTextField(parent, Messages.ModelTooling_Common_Id, master, context, textProp,
-				E4Properties.elementId(getEditingDomain()));
-		ControlFactory.createTextField(parent, Messages.ModelTooling_UIElement_AccessibilityPhrase, getMaster(),
-				context, textProp, E4Properties.accessibilityPhrase(getEditingDomain()));
-		ControlFactory.createTextField(parent, Messages.CompositePartEditor_LabelLabel, master, context, textProp,
-				E4Properties.label(getEditingDomain()));
-		ControlFactory.createTextField(parent, Messages.CompositePartEditor_Tooltip, master, context, textProp,
-				E4Properties.tooltip(getEditingDomain()));
-
-		// ------------------------------------------------------------
-		{
-			final Label l = new Label(parent, SWT.NONE);
-			l.setText(Messages.CompositePartEditor_IconURI);
-			l.setLayoutData(new GridData());
-			l.setToolTipText(Messages.CompositePartEditor_IconURI_Tooltip);
-
-			final Text t = new Text(parent, SWT.BORDER);
-			TextPasteHandler.createFor(t);
-			t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-			context.bindValue(textProp.observeDelayed(200, t),
-					E4Properties.iconUri(getEditingDomain()).observeDetail(master));
-
-			new ImageTooltip(t, Messages, this);
-
-			Button b = ControlFactory.createFindButton(parent, resourcePool);
-			b.addSelectionListener(new SelectionAdapter() {
-				@Override
-				public void widgetSelected(SelectionEvent e) {
-					final PartIconDialogEditor dialog = new PartIconDialogEditor(b.getShell(), eclipseContext, project,
-							getEditingDomain(), getMaster().getValue(), Messages);
-					dialog.open();
-				}
-			});
-		}
-
-		// ------------------------------------------------------------
 		{
 			final Label l = new Label(parent, SWT.NONE);
 			l.setText(Messages.CompositePartEditor_Orientation);
@@ -295,214 +189,146 @@
 		}
 
 		ControlFactory.createSelectedElement(parent, this, context, Messages.CompositePartEditor_SelectedElement);
-		ControlFactory.createTextField(parent, Messages.CompositePartEditor_ContainerData, master, context, textProp,
-				E4Properties.containerData(getEditingDomain()));
 
-		{
+		final Label l = new Label(parent, SWT.NONE);
+		l.setText(Messages.CompositePartEditor_Controls);
+		l.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false));
 
-			final Label l = new Label(parent, SWT.NONE);
-			l.setText(Messages.CompositePartEditor_Controls);
-			l.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING, false, false));
+		final Composite buttonCompTop = new Composite(parent, SWT.NONE);
+		final GridData span2 = new GridData(GridData.FILL, GridData.BEGINNING, false, false, 2, 1);
+		buttonCompTop.setLayoutData(span2);
+		buttonCompTop.setLayout(GridLayoutFactory.fillDefaults().numColumns(2).create());
 
-			final Composite buttonCompTop = new Composite(parent, SWT.NONE);
-			final GridData span2 = new GridData(GridData.FILL, GridData.BEGINNING, false, false, 2, 1);
-			buttonCompTop.setLayoutData(span2);
-			final GridLayout gl = new GridLayout(2, false);
-			gl.marginLeft = 0;
-			gl.marginRight = 0;
-			gl.marginWidth = 0;
-			gl.marginHeight = 0;
-			buttonCompTop.setLayout(gl);
+		final ComboViewer childrenDropDown = new ComboViewer(buttonCompTop);
+		childrenDropDown.setLabelProvider(new FeatureClassLabelProvider(getEditor()));
+		childrenDropDown.setContentProvider(ArrayContentProvider.getInstance());
 
-			final ComboViewer childrenDropDown = new ComboViewer(buttonCompTop);
-			childrenDropDown.setLabelProvider(new FeatureClassLabelProvider(getEditor()));
-			childrenDropDown.setContentProvider(ArrayContentProvider.getInstance());
+		final List<FeatureClass> eClassList = new ArrayList<>();
+		eClassList.add(new FeatureClass("PartSashContainer", BasicPackageImpl.Literals.PART_SASH_CONTAINER)); //$NON-NLS-1$
+		eClassList.add(new FeatureClass("PartStack", BasicPackageImpl.Literals.PART_STACK)); //$NON-NLS-1$
+		eClassList.add(new FeatureClass("Part", BasicPackageImpl.Literals.PART)); //$NON-NLS-1$
+		eClassList.add(new FeatureClass("Area", AdvancedPackageImpl.Literals.AREA)); //$NON-NLS-1$
+		eClassList.add(new FeatureClass("Placeholder", AdvancedPackageImpl.Literals.PLACEHOLDER)); //$NON-NLS-1$
+		eClassList.addAll(getEditor().getFeatureClasses(BasicPackageImpl.Literals.COMPOSITE_PART,
+				UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN));
+		childrenDropDown.setInput(eClassList);
+		childrenDropDown.setSelection(new StructuredSelection(eClassList.get(0)));
 
-			final List<FeatureClass> eClassList = new ArrayList<>();
-			eClassList.add(new FeatureClass("PartSashContainer", BasicPackageImpl.Literals.PART_SASH_CONTAINER)); //$NON-NLS-1$
-			eClassList.add(new FeatureClass("PartStack", BasicPackageImpl.Literals.PART_STACK)); //$NON-NLS-1$
-			eClassList.add(new FeatureClass("Part", BasicPackageImpl.Literals.PART)); //$NON-NLS-1$
-			eClassList.add(new FeatureClass("Area", AdvancedPackageImpl.Literals.AREA)); //$NON-NLS-1$
-			eClassList.add(new FeatureClass("Placeholder", AdvancedPackageImpl.Literals.PLACEHOLDER)); //$NON-NLS-1$
-			eClassList.addAll(getEditor().getFeatureClasses(BasicPackageImpl.Literals.COMPOSITE_PART,
-					UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN));
-			childrenDropDown.setInput(eClassList);
-			childrenDropDown.setSelection(new StructuredSelection(eClassList.get(0)));
-
-			Button b = new Button(buttonCompTop, SWT.PUSH | SWT.FLAT);
-			b.setText(org.eclipse.e4.tools.emf.ui.internal.Messages.ModelTooling_Common_AddEllipsis);
-			b.setImage(createImage(ResourceProvider.IMG_Obj16_table_add));
-			b.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false));
-			b.addSelectionListener(new SelectionAdapter() {
-				@Override
-				public void widgetSelected(SelectionEvent e) {
-					if (!childrenDropDown.getSelection().isEmpty()) {
-						final EClass eClass = ((FeatureClass) ((IStructuredSelection) childrenDropDown.getSelection())
-								.getFirstElement()).eClass;
-						handleAddChild(eClass);
-					}
+		Button b = new Button(buttonCompTop, SWT.PUSH | SWT.FLAT);
+		b.setText(org.eclipse.e4.tools.emf.ui.internal.Messages.ModelTooling_Common_AddEllipsis);
+		b.setImage(createImage(ResourceProvider.IMG_Obj16_table_add));
+		b.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false));
+		b.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				if (!childrenDropDown.getSelection().isEmpty()) {
+					final EClass eClass = ((FeatureClass) ((IStructuredSelection) childrenDropDown.getSelection())
+							.getFirstElement()).eClass;
+					handleAddChild(eClass);
 				}
-			});
+			}
+		});
 
-			new Label(parent, SWT.NONE);
+		new Label(parent, SWT.NONE);
 
-			final TableViewer viewer = new TableViewer(parent);
-			final GridData gd = new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1);
-			viewer.getControl().setLayoutData(gd);
-			viewer.setContentProvider(new ObservableListContentProvider<>());
+		final TableViewer viewer = new TableViewer(parent);
+		final GridData gd = new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1);
+		viewer.getControl().setLayoutData(gd);
+		viewer.setContentProvider(new ObservableListContentProvider<>());
 
-			final FontDescriptor italicFontDescriptor = FontDescriptor.createFrom(viewer.getControl().getFont())
-					.setStyle(SWT.ITALIC);
-			viewer.setLabelProvider(new DelegatingStyledCellLabelProvider(
-					new ComponentLabelProvider(getEditor(), Messages, italicFontDescriptor)));
+		final FontDescriptor italicFontDescriptor = FontDescriptor.createFrom(viewer.getControl().getFont())
+				.setStyle(SWT.ITALIC);
+		viewer.setLabelProvider(new DelegatingStyledCellLabelProvider(
+				new ComponentLabelProvider(getEditor(), Messages, italicFontDescriptor)));
 
-			viewer.setInput(E4Properties.<MPartSashContainerElement>children().observeDetail(getMaster()));
+		viewer.setInput(E4Properties.<MPartSashContainerElement>children().observeDetail(getMaster()));
 
-			viewer.addOpenListener(event -> {
-				if (event.getSelection() instanceof IStructuredSelection) {
-					IStructuredSelection selection = (IStructuredSelection) event.getSelection();
-					if (selection.getFirstElement() instanceof EObject && getEditor() != null) {
-						EObject selected = (EObject) selection.getFirstElement();
-						getEditor().gotoEObject(ModelEditor.TAB_FORM, selected);
-					}
+		viewer.addOpenListener(event -> {
+			if (event.getSelection() instanceof IStructuredSelection) {
+				IStructuredSelection selection = (IStructuredSelection) event.getSelection();
+				if (selection.getFirstElement() instanceof EObject && getEditor() != null) {
+					EObject selected = (EObject) selection.getFirstElement();
+					getEditor().gotoEObject(ModelEditor.TAB_FORM, selected);
 				}
-			});
+			}
+		});
 
-			new Label(parent, SWT.NONE);
+		new Label(parent, SWT.NONE);
 
-			final Composite buttonCompBot = new Composite(parent, SWT.NONE);
-			buttonCompBot.setLayoutData(new GridData(GridData.FILL, GridData.END, false, false, 2, 1));
-			buttonCompBot.setLayout(new FillLayout());
+		final Composite buttonCompBot = new Composite(parent, SWT.NONE);
+		buttonCompBot.setLayoutData(new GridData(GridData.FILL, GridData.END, false, false, 2, 1));
+		buttonCompBot.setLayout(new FillLayout());
 
-			b = new Button(buttonCompBot, SWT.PUSH | SWT.FLAT);
-			b.setText(org.eclipse.e4.tools.emf.ui.internal.Messages.ModelTooling_Common_Up);
-			b.setImage(createImage(ResourceProvider.IMG_Obj16_arrow_up));
-			b.addSelectionListener(new SelectionAdapter() {
-				@Override
-				public void widgetSelected(SelectionEvent e) {
-					if (!viewer.getSelection().isEmpty()) {
-						final IStructuredSelection s = (IStructuredSelection) viewer.getSelection();
-						if (s.size() == 1) {
-							final Object obj = s.getFirstElement();
-							final int idx = getMaster().getValue().getChildren().indexOf(obj) - 1;
-							if (idx >= 0) {
-								if (Util.moveElementByIndex(getEditingDomain(), (MUIElement) obj, getEditor()
-										.isLiveModel(), idx)) {
-									viewer.setSelection(new StructuredSelection(obj));
-								}
+		b = new Button(buttonCompBot, SWT.PUSH | SWT.FLAT);
+		b.setText(org.eclipse.e4.tools.emf.ui.internal.Messages.ModelTooling_Common_Up);
+		b.setImage(createImage(ResourceProvider.IMG_Obj16_arrow_up));
+		b.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				if (!viewer.getSelection().isEmpty()) {
+					final IStructuredSelection s = (IStructuredSelection) viewer.getSelection();
+					if (s.size() == 1) {
+						final Object obj = s.getFirstElement();
+						final int idx = getMaster().getValue().getChildren().indexOf(obj) - 1;
+						if (idx >= 0) {
+							if (Util.moveElementByIndex(getEditingDomain(), (MUIElement) obj, getEditor().isLiveModel(),
+									idx)) {
+								viewer.setSelection(new StructuredSelection(obj));
 							}
-
 						}
+
 					}
 				}
-			});
+			}
+		});
 
-			b = new Button(buttonCompBot, SWT.PUSH | SWT.FLAT);
-			b.setText(org.eclipse.e4.tools.emf.ui.internal.Messages.ModelTooling_Common_Down);
-			b.setImage(createImage(ResourceProvider.IMG_Obj16_arrow_down));
-			b.addSelectionListener(new SelectionAdapter() {
-				@Override
-				public void widgetSelected(SelectionEvent e) {
-					if (!viewer.getSelection().isEmpty()) {
-						final IStructuredSelection s = (IStructuredSelection) viewer.getSelection();
-						if (s.size() == 1) {
-							final Object obj = s.getFirstElement();
-							final int idx = getMaster().getValue().getChildren().indexOf(obj) + 1;
-							if (idx < getMaster().getValue().getChildren().size()) {
-								if (Util.moveElementByIndex(getEditingDomain(), (MUIElement) obj, getEditor()
-										.isLiveModel(), idx)) {
-									viewer.setSelection(new StructuredSelection(obj));
-								}
+		b = new Button(buttonCompBot, SWT.PUSH | SWT.FLAT);
+		b.setText(org.eclipse.e4.tools.emf.ui.internal.Messages.ModelTooling_Common_Down);
+		b.setImage(createImage(ResourceProvider.IMG_Obj16_arrow_down));
+		b.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				if (!viewer.getSelection().isEmpty()) {
+					final IStructuredSelection s = (IStructuredSelection) viewer.getSelection();
+					if (s.size() == 1) {
+						final Object obj = s.getFirstElement();
+						final int idx = getMaster().getValue().getChildren().indexOf(obj) + 1;
+						if (idx < getMaster().getValue().getChildren().size()) {
+							if (Util.moveElementByIndex(getEditingDomain(), (MUIElement) obj, getEditor().isLiveModel(),
+									idx)) {
+								viewer.setSelection(new StructuredSelection(obj));
 							}
-
 						}
+
 					}
 				}
-			});
+			}
+		});
 
-			b = new Button(buttonCompBot, SWT.PUSH | SWT.FLAT);
-			b.setText(org.eclipse.e4.tools.emf.ui.internal.Messages.ModelTooling_Common_Remove);
-			b.setImage(createImage(ResourceProvider.IMG_Obj16_table_delete));
-			b.addSelectionListener(new SelectionAdapter() {
-				@Override
-				public void widgetSelected(SelectionEvent e) {
-					if (!viewer.getSelection().isEmpty()) {
-						final List<?> elements = ((IStructuredSelection) viewer.getSelection()).toList();
+		b = new Button(buttonCompBot, SWT.PUSH | SWT.FLAT);
+		b.setText(org.eclipse.e4.tools.emf.ui.internal.Messages.ModelTooling_Common_Remove);
+		b.setImage(createImage(ResourceProvider.IMG_Obj16_table_delete));
+		b.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				if (!viewer.getSelection().isEmpty()) {
+					final List<?> elements = ((IStructuredSelection) viewer.getSelection()).toList();
 
-						final Command cmd = RemoveCommand.create(getEditingDomain(), getMaster().getValue(),
-								UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN, elements);
-						if (cmd.canExecute()) {
-							getEditingDomain().getCommandStack().execute(cmd);
-						}
+					final Command cmd = RemoveCommand.create(getEditingDomain(), getMaster().getValue(),
+							UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN, elements);
+					if (cmd.canExecute()) {
+						getEditingDomain().getCommandStack().execute(cmd);
 					}
 				}
-			});
-		}
-
-		ControlFactory.createCheckBox(parent, Messages.ModelTooling_UIElement_ToBeRendered, getMaster(), context,
-				WidgetProperties.buttonSelection(), E4Properties.toBeRendered(getEditingDomain()));
-		ControlFactory.createCheckBox(parent, Messages.ModelTooling_UIElement_Visible, getMaster(), context,
-				WidgetProperties.buttonSelection(), E4Properties.visible(getEditingDomain()));
-
-		Composite propComposite = ControlFactory.createMapProperties(parent, Messages, this,
-				Messages.ModelTooling_Context_Properties, UiPackageImpl.Literals.CONTEXT__PROPERTIES,
-				VERTICAL_LIST_WIDGET_INDENT);
-		propComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).span(3, 1).create());
-
-		Composite variablesComposite = ControlFactory.createStringListWidget(parent, Messages, this,
-				Messages.ModelTooling_Context_Variables, UiPackageImpl.Literals.CONTEXT__VARIABLES,
-				VERTICAL_LIST_WIDGET_INDENT);
-		variablesComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).span(3, 1).create());
-
-		item = new CTabItem(folder, SWT.NONE);
-		item.setText(Messages.ModelTooling_Common_TabSupplementary);
-
-		parent = createScrollableContainer(folder);
-		item.setControl(parent.getParent());
-
-		ControlFactory.createStringListWidget(parent, Messages, this, Messages.CategoryEditor_Tags,
-				ApplicationPackageImpl.Literals.APPLICATION_ELEMENT__TAGS, VERTICAL_LIST_WIDGET_INDENT);
-		ControlFactory.createMapProperties(parent, Messages, this, Messages.ModelTooling_Contribution_PersistedState,
-				ApplicationPackageImpl.Literals.APPLICATION_ELEMENT__PERSISTED_STATE, VERTICAL_LIST_WIDGET_INDENT);
-
-		if (project == null) {
-			createUITreeInspection(folder);
-		}
-
-		createContributedEditorTabs(folder, context, getMaster(), MCompositePart.class);
-
-		folder.setSelection(0);
-
-		return folder;
+			}
+		});
 	}
 
-	private void createUITreeInspection(CTabFolder folder) {
-		final CTabItem item = new CTabItem(folder, SWT.NONE);
-		item.setText(Messages.ModelTooling_Common_RuntimeWidgetTree);
-		final Composite container = new Composite(folder, SWT.NONE);
-		container.setLayout(new GridLayout());
-		item.setControl(container);
-
-		final UIViewer objectViewer = new UIViewer();
-		final TreeViewer viewer = objectViewer.createViewer(container, UiPackageImpl.Literals.UI_ELEMENT__WIDGET,
-				getMaster(), resourcePool, Messages);
-		viewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
-	}
-
+	@SuppressWarnings("unchecked")
 	@Override
-	public IObservableList<?> getChildList(Object element) {
-		return E4Properties.<MPartSashContainerElement>children().observe((MCompositePart) element);
-	}
-
-	@Override
-	public String getDetailLabel(Object element) {
-		return null;
-	}
-
-	@Override
-	public FeaturePath[] getLabelProperties() {
-		return new FeaturePath[] { FeaturePath.fromList(UiPackageImpl.Literals.GENERIC_TILE__HORIZONTAL),
-				FeaturePath.fromList(UiPackageImpl.Literals.UI_ELEMENT__TO_BE_RENDERED) };
+	protected void addChildListEntries(MPart part, IObservableList<Object> list) {
+		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_CONTROLS, E4Properties.<MPartSashContainerElement>children(),
+				(MElementContainer<MPartSashContainerElement>) part, Messages.PartEditor_Controls));
 	}
 
 	protected void handleAddChild(EClass eClass) {
@@ -510,18 +336,6 @@
 		addToModel(eObject);
 	}
 
-	private void addToModel(EObject eObject) {
-		setElementId(eObject);
-
-		final Command cmd = AddCommand.create(getEditingDomain(), getMaster().getValue(),
-				UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN, eObject);
-
-		if (cmd.canExecute()) {
-			getEditingDomain().getCommandStack().execute(cmd);
-			getEditor().setSelection(eObject);
-		}
-	}
-
 	protected void handleImportChild(EClass eClass, String hint) {
 
 		if (eClass == BasicPackageImpl.Literals.PART) {
@@ -536,6 +350,18 @@
 		}
 	}
 
+	private void addToModel(EObject eObject) {
+		setElementId(eObject);
+
+		final Command cmd = AddCommand.create(getEditingDomain(), getMaster().getValue(),
+				UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN, eObject);
+
+		if (cmd.canExecute()) {
+			getEditingDomain().getCommandStack().execute(cmd);
+			getEditor().setSelection(eObject);
+		}
+	}
+
 	@Override
 	public List<Action> getActions(Object element) {
 		final ArrayList<Action> l = new ArrayList<>(super.getActions(element));
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartEditor.java
index 94c9b98..11d7359 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartEditor.java
@@ -15,73 +15,17 @@
  ******************************************************************************/
 package org.eclipse.e4.tools.emf.ui.internal.common.component;
 
-import javax.inject.Inject;
-
-import org.eclipse.core.databinding.observable.list.IObservableList;
-import org.eclipse.core.databinding.observable.list.WritableList;
-import org.eclipse.core.databinding.observable.value.IObservableValue;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.e4.core.contexts.IEclipseContext;
-import org.eclipse.e4.core.di.annotations.Optional;
-import org.eclipse.e4.tools.emf.ui.common.ImageTooltip;
-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.E4Properties;
 import org.eclipse.e4.tools.emf.ui.internal.ResourceProvider;
-import org.eclipse.e4.tools.emf.ui.internal.common.ModelEditor;
-import org.eclipse.e4.tools.emf.ui.internal.common.VirtualEntry;
-import org.eclipse.e4.tools.emf.ui.internal.common.component.ControlFactory.TextPasteHandler;
-import org.eclipse.e4.tools.emf.ui.internal.common.component.dialogs.PartIconDialogEditor;
-import org.eclipse.e4.tools.emf.ui.internal.common.objectdata.ObjectViewer;
-import org.eclipse.e4.tools.emf.ui.internal.common.uistructure.UIViewer;
 import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl;
 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.impl.BasicPackageImpl;
 import org.eclipse.e4.ui.model.application.ui.impl.UiPackageImpl;
-import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory;
-import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
-import org.eclipse.emf.common.command.Command;
-import org.eclipse.emf.databinding.EMFDataBindingContext;
 import org.eclipse.emf.databinding.FeaturePath;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.edit.command.SetCommand;
-import org.eclipse.jface.databinding.swt.IWidgetValueProperty;
-import org.eclipse.jface.databinding.swt.typed.WidgetProperties;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.CTabFolder;
-import org.eclipse.swt.custom.CTabItem;
-import org.eclipse.swt.custom.StackLayout;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Text;
 
-public class PartEditor extends AbstractComponentEditor<MPart> {
-
-	private Composite composite;
-	private EMFDataBindingContext context;
-	private Button createRemoveToolBar;
-	private StackLayout stackLayout;
-
-	@Inject
-	@Optional
-	private IProject project;
-
-	@Inject
-	IEclipseContext eclipseContext;
-
-	@Inject
-	public PartEditor() {
-		super();
-	}
+public class PartEditor extends AbstractPartEditor<MPart> {
 
 	@Override
 	public Image getImage(Object element) {
@@ -103,36 +47,7 @@
 
 	@Override
 	public Composite doGetEditor(Composite parent, Object object) {
-		if (composite == null) {
-			context = new EMFDataBindingContext();
-			if (getEditor().isModelFragment()) {
-				composite = new Composite(parent, SWT.NONE);
-				stackLayout = new StackLayout();
-				composite.setLayout(stackLayout);
-				createForm(composite, context, getMaster(), false);
-				createForm(composite, context, getMaster(), true);
-			} else {
-				composite = createForm(parent, context, getMaster(), false);
-			}
-		}
-
-		if (getEditor().isModelFragment()) {
-			Control topControl;
-			if (Util.isImport((EObject) object)) {
-				topControl = composite.getChildren()[1];
-			} else {
-				topControl = composite.getChildren()[0];
-			}
-
-			if (stackLayout.topControl != topControl) {
-				stackLayout.topControl = topControl;
-				composite.layout(true, true);
-			}
-		}
-
-		if (createRemoveToolBar != null) {
-			createRemoveToolBar.setSelection(((MPart) object).getToolbar() != null);
-		}
+		Composite composite = super.doGetEditor(parent, object);
 
 		getMaster().setValue((MPart) object);
 		enableIdGenerator(UiPackageImpl.Literals.UI_LABEL__LABEL,
@@ -141,223 +56,6 @@
 		return composite;
 	}
 
-	protected Composite createForm(Composite parent, EMFDataBindingContext context, IObservableValue<MPart> master,
-			boolean isImport) {
-		final CTabFolder folder = new CTabFolder(parent, SWT.BOTTOM);
-
-		CTabItem item = new CTabItem(folder, SWT.BORDER);
-		item.setText(Messages.ModelTooling_Common_TabDefault);
-
-		parent = createScrollableContainer(folder);
-		item.setControl(parent.getParent());
-
-		if (getEditor().isShowXMIId() || getEditor().isLiveModel()) {
-			ControlFactory.createXMIId(parent, this);
-		}
-
-		final IWidgetValueProperty<Text, String> textProp = WidgetProperties.text(SWT.Modify);
-
-		if (isImport) {
-			ControlFactory.createFindImport(parent, Messages, this, context);
-			folder.setSelection(0);
-			return folder;
-		}
-
-		ControlFactory.createTextField(parent, Messages.ModelTooling_Common_Id, master, context, textProp,
-				E4Properties.elementId(getEditingDomain()));
-		ControlFactory.createTextField(parent, Messages.PartEditor_LabelLabel, master, context, textProp,
-				E4Properties.label(getEditingDomain()));
-		ControlFactory.createTextField(parent, Messages.ModelTooling_UIElement_AccessibilityPhrase, master, context,
-				textProp, E4Properties.accessibilityPhrase(getEditingDomain()));
-		ControlFactory.createTextField(parent, Messages.PartEditor_Tooltip, master, context, textProp,
-				E4Properties.tooltip(getEditingDomain()));
-
-		// ------------------------------------------------------------
-		{
-			final Label l = new Label(parent, SWT.NONE);
-			l.setText(Messages.PartEditor_IconURI);
-			l.setLayoutData(new GridData());
-			l.setToolTipText(Messages.PartEditor_IconURI_Tooltip);
-
-			final Text t = new Text(parent, SWT.BORDER);
-			TextPasteHandler.createFor(t);
-			t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-			context.bindValue(
-					textProp.observeDelayed(200, t),
-					E4Properties.iconUri(getEditingDomain()).observeDetail(master));
-
-			new ImageTooltip(t, Messages, this);
-
-			Button b = ControlFactory.createFindButton(parent, resourcePool);
-			b.addSelectionListener(new SelectionAdapter() {
-				@Override
-				public void widgetSelected(SelectionEvent e) {
-					final PartIconDialogEditor dialog = new PartIconDialogEditor(b.getShell(), eclipseContext, project,
-							getEditingDomain(), getMaster().getValue(), Messages);
-					dialog.open();
-				}
-			});
-		}
-
-
-		ControlFactory.createClassURIField(parent, Messages, this, Messages.PartEditor_ClassURI,
-				ApplicationPackageImpl.Literals.CONTRIBUTION__CONTRIBUTION_URI,
-				getEditor().getContributionCreator(BasicPackageImpl.Literals.PART), project, context, eclipseContext);
-
-		// ------------------------------------------------------------
-		ControlFactory.createTextField(parent, Messages.PartEditor_ContainerData, master, context, textProp,
-				E4Properties.containerData(getEditingDomain()));
-
-		createSubformElements(parent, context, master);
-
-		{
-			final Label l = new Label(parent, SWT.NONE);
-			l.setText(Messages.PartEditor_ToolBar);
-			l.setLayoutData(new GridData());
-
-			createRemoveToolBar = new Button(parent, SWT.CHECK);
-			createRemoveToolBar.addSelectionListener(new SelectionAdapter() {
-				@Override
-				public void widgetSelected(SelectionEvent e) {
-					final MPart window = getMaster().getValue();
-					if (window.getToolbar() == null) {
-						addToolBar();
-					} else {
-						removeToolBar();
-					}
-				}
-			});
-			createRemoveToolBar.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, false, false, 2, 1));
-		}
-
-		ControlFactory.createCheckBox(parent, Messages.PartEditor_Closeable, Messages.PartEditor_Closeable_Tooltip,
-				getMaster(), context, WidgetProperties.buttonSelection(),
-				E4Properties.partClosable(getEditingDomain()));
-
-		// ------------------------------------------------------------
-		ControlFactory.createCheckBox(parent, Messages.ModelTooling_UIElement_ToBeRendered, getMaster(), context,
-				WidgetProperties.buttonSelection(), E4Properties.toBeRendered(getEditingDomain()));
-		ControlFactory.createCheckBox(parent, Messages.ModelTooling_UIElement_Visible, getMaster(), context,
-				WidgetProperties.buttonSelection(), E4Properties.visible(getEditingDomain()));
-
-		ControlFactory.createBindingContextWiget(parent, Messages, this, Messages.PartEditor_BindingContexts);
-		ControlFactory.createMapProperties(parent, Messages, this, Messages.ModelTooling_Contribution_PersistedState,
-				ApplicationPackageImpl.Literals.APPLICATION_ELEMENT__PERSISTED_STATE, VERTICAL_LIST_WIDGET_INDENT);
-		ControlFactory.createMapProperties(parent, Messages, this, Messages.ModelTooling_Context_Properties,
-				UiPackageImpl.Literals.CONTEXT__PROPERTIES, VERTICAL_LIST_WIDGET_INDENT);
-
-		item = new CTabItem(folder, SWT.NONE);
-		item.setText(Messages.ModelTooling_Common_TabSupplementary);
-
-		parent = createScrollableContainer(folder);
-		item.setControl(parent.getParent());
-
-		ControlFactory.createStringListWidget(parent, Messages, this, Messages.ModelTooling_Context_Variables,
-				Messages.ModelTooling_Context_Variables_Tooltip, UiPackageImpl.Literals.CONTEXT__VARIABLES,
-				VERTICAL_LIST_WIDGET_INDENT);
-		ControlFactory.createStringListWidget(parent, Messages, this, Messages.CategoryEditor_Tags,
-				ApplicationPackageImpl.Literals.APPLICATION_ELEMENT__TAGS, VERTICAL_LIST_WIDGET_INDENT);
-
-		if (project == null) {
-			createInstanceInspection(folder);
-			createUITreeInspection(folder);
-		}
-
-		createContributedEditorTabs(folder, context, getMaster(), MPart.class);
-
-		folder.setSelection(0);
-
-		return folder;
-	}
-
-	private void createInstanceInspection(CTabFolder folder) {
-		final CTabItem item = new CTabItem(folder, SWT.NONE);
-		item.setText(Messages.ModelTooling_Common_RuntimeContributionInstance);
-		final Composite container = new Composite(folder, SWT.NONE);
-		container.setLayout(new GridLayout());
-		item.setControl(container);
-
-		final ObjectViewer objectViewer = new ObjectViewer();
-		final TreeViewer viewer = objectViewer.createViewer(container,
-				ApplicationPackageImpl.Literals.CONTRIBUTION__OBJECT, getMaster(), resourcePool, Messages);
-		viewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
-	}
-
-	private void createUITreeInspection(CTabFolder folder) {
-		final CTabItem item = new CTabItem(folder, SWT.NONE);
-		item.setText(Messages.ModelTooling_Common_RuntimeWidgetTree);
-		final Composite container = new Composite(folder, SWT.NONE);
-		container.setLayout(new GridLayout());
-		item.setControl(container);
-
-		final UIViewer objectViewer = new UIViewer();
-		final TreeViewer viewer = objectViewer.createViewer(container, UiPackageImpl.Literals.UI_ELEMENT__WIDGET,
-				getMaster(), resourcePool, Messages);
-		viewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
-	}
-
-	private void addToolBar() {
-		final MToolBar menu = MMenuFactory.INSTANCE.createToolBar();
-		setElementId(menu);
-
-		final Command cmd = SetCommand.create(getEditingDomain(), getMaster().getValue(),
-				BasicPackageImpl.Literals.PART__TOOLBAR, menu);
-		if (cmd.canExecute()) {
-			getEditingDomain().getCommandStack().execute(cmd);
-		}
-	}
-
-	private void removeToolBar() {
-		final Command cmd = SetCommand.create(getEditingDomain(), getMaster().getValue(),
-				BasicPackageImpl.Literals.PART__TOOLBAR, null);
-		if (cmd.canExecute()) {
-			getEditingDomain().getCommandStack().execute(cmd);
-		}
-	}
-
-	protected void createSubformElements(Composite parent, EMFDataBindingContext context,
-			IObservableValue<MPart> master) {
-
-	}
-
-	@Override
-	public IObservableList<?> getChildList(final Object element) {
-		final WritableList<Object> list = new WritableList<>();
-		final MPart window = (MPart) element;
-
-		if (getEditor().isModelFragment() && Util.isImport((EObject) element)) {
-			return list;
-		}
-
-		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_PART_MENU, E4Properties.partMenus(), window,
-				Messages.PartEditor_Menus));
-		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_HANDLER, E4Properties.handlers(), window,
-				Messages.PartEditor_Handlers));
-
-		if (window.getToolbar() != null) {
-			list.add(0, window.getToolbar());
-		}
-
-		E4Properties.partToolbar().observe(window).addValueChangeListener(event -> {
-			if (event.diff.getOldValue() != null) {
-				list.remove(event.diff.getOldValue());
-				if (getMaster().getValue() == element && !createRemoveToolBar.isDisposed()) {
-					createRemoveToolBar.setSelection(false);
-				}
-
-			}
-
-			if (event.diff.getNewValue() != null) {
-				list.add(0, event.diff.getNewValue());
-				if (getMaster().getValue() == element && !createRemoveToolBar.isDisposed()) {
-					createRemoveToolBar.setSelection(true);
-				}
-			}
-		});
-
-		return list;
-	}
-
 	@Override
 	public String getDetailLabel(Object element) {
 		return getLocalizedLabel((MUILabel) element);
@@ -369,4 +67,4 @@
 				FeaturePath.fromList(UiPackageImpl.Literals.UI_LABEL__ICON_URI),
 				FeaturePath.fromList(UiPackageImpl.Literals.UI_ELEMENT__TO_BE_RENDERED) };
 	}
-}
\ No newline at end of file
+}
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VControlsEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VControlsEditor.java
new file mode 100644
index 0000000..b5253ef
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VControlsEditor.java
@@ -0,0 +1,253 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Airbus Defence and Space GmbH and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Benedikt Kuntz <benedikt.kuntz@airbus.com> - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.e4.tools.emf.ui.internal.common.component.virtual;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+import org.eclipse.core.databinding.observable.list.IObservableList;
+import org.eclipse.core.databinding.observable.value.WritableValue;
+import org.eclipse.e4.tools.emf.ui.common.IEditorFeature.FeatureClass;
+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.AbstractPickList;
+import org.eclipse.e4.tools.emf.ui.internal.common.AbstractPickList.PickListFeatures;
+import org.eclipse.e4.tools.emf.ui.internal.common.E4PickList;
+import org.eclipse.e4.tools.emf.ui.internal.common.EClassLabelProvider;
+import org.eclipse.e4.tools.emf.ui.internal.common.VirtualEntry;
+import org.eclipse.e4.tools.emf.ui.internal.imp.ModelImportWizard;
+import org.eclipse.e4.tools.emf.ui.internal.imp.RegistryUtil;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.advanced.impl.AdvancedPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement;
+import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl;
+import org.eclipse.e4.ui.model.application.ui.impl.UiPackageImpl;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.databinding.EMFDataBindingContext;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.edit.command.AddCommand;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+
+public class VControlsEditor extends AbstractComponentEditor<MElementContainer<MPartSashContainerElement>> {
+	private Composite composite;
+	private EMFDataBindingContext context;
+	private TableViewer viewer;
+	private final List<Action> actions = new ArrayList<>();
+	private final List<Action> actionsImport = new ArrayList<>();
+
+	@Inject
+	private Shell shell;
+
+	@Inject
+	public VControlsEditor() {
+		super();
+	}
+
+	@PostConstruct
+	void init() {
+		actions.add(new Action(Messages.CompositePartEditor_AddPartSashContainer,
+				createImageDescriptor(ResourceProvider.IMG_PartSashContainer)) {
+			@Override
+			public void run() {
+				handleAddChild(BasicPackageImpl.Literals.PART_SASH_CONTAINER);
+			}
+		});
+		actions.add(new Action(Messages.CompositePartEditor_AddPartStack,
+				createImageDescriptor(ResourceProvider.IMG_PartStack)) {
+			@Override
+			public void run() {
+				handleAddChild(BasicPackageImpl.Literals.PART_STACK);
+			}
+		});
+		actions.add(new Action(Messages.CompositePartEditor_AddPart, createImageDescriptor(ResourceProvider.IMG_Part)) {
+			@Override
+			public void run() {
+				handleAddChild(BasicPackageImpl.Literals.PART);
+			}
+		});
+
+		actions.add(new Action(Messages.CompositePartEditor_AddArea, createImageDescriptor(ResourceProvider.IMG_Area)) {
+			@Override
+			public void run() {
+				handleAddChild(AdvancedPackageImpl.Literals.AREA);
+			}
+		});
+		actions.add(new Action(Messages.CompositePartEditor_AddPlaceholder,
+				createImageDescriptor(ResourceProvider.IMG_Placeholder)) {
+			@Override
+			public void run() {
+				handleAddChild(AdvancedPackageImpl.Literals.PLACEHOLDER);
+			}
+		});
+		for (final FeatureClass c : getEditor().getFeatureClasses(BasicPackageImpl.Literals.PART_STACK,
+				UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN)) {
+			final EClass ec = c.eClass;
+			actions.add(new Action(c.label, createImageDescriptor(c.iconId)) {
+				@Override
+				public void run() {
+					handleAddChild(ec);
+				}
+			});
+		}
+
+		// --- Import Actions ---
+		actionsImport.add(new Action("Views", createImageDescriptor(ResourceProvider.IMG_Part)) { //$NON-NLS-1$
+			@Override
+			public void run() {
+				handleImportChild(BasicPackageImpl.Literals.PART, RegistryUtil.HINT_VIEW);
+			}
+		});
+		actionsImport.add(new Action("Editors", createImageDescriptor(ResourceProvider.IMG_Part)) { //$NON-NLS-1$
+			@Override
+			public void run() {
+				handleImportChild(BasicPackageImpl.Literals.PART, RegistryUtil.HINT_EDITOR);
+			}
+		});
+
+	}
+
+	@Override
+	public String getLabel(Object element) {
+		return Messages.VControlsEditor_TreeLabel;
+	}
+
+	@Override
+	public String getDetailLabel(Object element) {
+		return null;
+	}
+
+	@Override
+	public String getDescription(Object element) {
+		return Messages.VControlsEditor_TreeLabelDescription;
+	}
+
+	@Override
+	public Composite doGetEditor(Composite parent, Object object) {
+		if (composite == null) {
+			context = new EMFDataBindingContext();
+			composite = createForm(parent, context, getMaster());
+		}
+		@SuppressWarnings("unchecked")
+		final VirtualEntry<MElementContainer<MPartSashContainerElement>, ?> o = (VirtualEntry<MElementContainer<MPartSashContainerElement>, ?>) object;
+		viewer.setInput(o.getList());
+		getMaster().setValue(o.getOriginalParent());
+		return composite;
+	}
+
+	private Composite createForm(Composite parent, EMFDataBindingContext context,
+			WritableValue<MElementContainer<MPartSashContainerElement>> master) {
+		final CTabFolder folder = new CTabFolder(parent, SWT.BOTTOM);
+
+		final CTabItem item = new CTabItem(folder, SWT.NONE);
+		item.setText(Messages.ModelTooling_Common_TabDefault);
+
+		parent = createScrollableContainer(folder);
+		item.setControl(parent.getParent());
+
+		final AbstractPickList pickList = new E4PickList(parent, SWT.NONE, Arrays.asList(PickListFeatures.NO_GROUP),
+				this, UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN) {
+			@Override
+			protected void addPressed() {
+				final EClass eClass = (EClass) getSelection().getFirstElement();
+				handleAddChild(eClass);
+			}
+
+			@Override
+			protected List<?> getContainerChildren(Object container) {
+				return ((MApplication) container).getChildren();
+			}
+		};
+		pickList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
+		viewer = pickList.getList();
+
+		pickList.setLabelProvider(new EClassLabelProvider(getEditor()));
+		pickList.setInput(
+				new EClass[] { BasicPackageImpl.Literals.PART_SASH_CONTAINER, BasicPackageImpl.Literals.PART_STACK,
+						BasicPackageImpl.Literals.PART, AdvancedPackageImpl.Literals.AREA,
+						AdvancedPackageImpl.Literals.PLACEHOLDER });
+		pickList.setSelection(new StructuredSelection(BasicPackageImpl.Literals.PART));
+
+		folder.setSelection(0);
+
+		return folder;
+	}
+
+	@Override
+	public IObservableList<?> getChildList(Object element) {
+		return null;
+	}
+
+	protected void handleAddChild(EClass eClass) {
+		final EObject eObject = EcoreUtil.create(eClass);
+		addToModel(eObject);
+	}
+
+	private void addToModel(EObject eObject) {
+		setElementId(eObject);
+
+		final Command cmd = AddCommand.create(getEditingDomain(), getMaster().getValue(),
+				UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN, eObject);
+
+		if (cmd.canExecute()) {
+			getEditingDomain().getCommandStack().execute(cmd);
+			getEditor().setSelection(eObject);
+		}
+	}
+
+	protected void handleImportChild(EClass eClass, String hint) {
+
+		if (eClass == BasicPackageImpl.Literals.PART) {
+			final ModelImportWizard wizard = new ModelImportWizard(MPart.class, this, hint, resourcePool);
+			final WizardDialog wizardDialog = new WizardDialog(shell, wizard);
+			if (wizardDialog.open() == Window.OK) {
+				final MPart[] parts = (MPart[]) wizard.getElements(MPart.class);
+				for (final MPart part : parts) {
+					addToModel((EObject) part);
+				}
+			}
+		}
+	}
+
+	@Override
+	public List<Action> getActions(Object element) {
+		final ArrayList<Action> l = new ArrayList<>(super.getActions(element));
+		l.addAll(actions);
+		return l;
+	}
+
+	@Override
+	public List<Action> getActionsImport(Object element) {
+		final ArrayList<Action> l = new ArrayList<>(super.getActionsImport(element));
+		l.addAll(actionsImport);
+		return l;
+	}
+}
\ No newline at end of file