Bug 501597 - [Model] Support new trimbars for Part and Perspective in e4
model editor

Add virtual editor tree elements for Part(Descriptor)Editor and
PerspectiveEditor. Add an abstract superclass for VWindowTrimEditor and
add inheriting classes for MPart's, MPartDescriptor's and MPerspective's
TrimBars

Change-Id: I71ca4708a70e56ce06bae2c2fc9c4083812ac271
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/E4Properties.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/E4Properties.java
index f412a60..3392380 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/E4Properties.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/E4Properties.java
@@ -424,12 +424,28 @@
 	}
 
 	@SuppressWarnings("unchecked")
-	public static IListProperty<MTrimmedWindow, MTrimBar> trimBars() {
+	public static IListProperty<MTrimmedWindow, MTrimBar> windowTrimBars() {
 		return EMFProperties.list(
 				org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl.Literals.TRIMMED_WINDOW__TRIM_BARS);
 	}
 
 	@SuppressWarnings("unchecked")
+	public static IListProperty<MPart, MTrimBar> partTrimBars() {
+		return EMFProperties
+				.list(org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl.Literals.PART__TRIM_BARS);
+	}
+
+	@SuppressWarnings("unchecked")
+	public static IListProperty<MPartDescriptor, MTrimBar> partDescriptorTrimBars() {
+		return EMFProperties.list(BasicPackageImpl.Literals.PART_DESCRIPTOR__TRIM_BARS);
+	}
+
+	@SuppressWarnings("unchecked")
+	public static IListProperty<MPerspective, MTrimBar> perspectiveTrimBars() {
+		return EMFProperties.list(AdvancedPackageImpl.Literals.PERSPECTIVE__TRIM_BARS);
+	}
+
+	@SuppressWarnings("unchecked")
 	public static IListProperty<MWindow, MWindow> windowWindows() {
 		return EMFProperties
 				.list(org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl.Literals.WINDOW__WINDOWS);
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 33ff515..35e94fb 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
@@ -262,6 +262,7 @@
 	public String PartDescriptorEditor_Menus;
 	public String PartDescriptorEditor_Handlers;
 	public String PartDescriptorEditor_ContainerData;
+	public String PartDescriptorEditor_TrimBars;
 
 	public String PartEditor_Label;
 	public String PartEditor_Description;
@@ -278,6 +279,7 @@
 	public String PartEditor_ToolBar;
 	public String PartEditor_BindingContexts;
 	public String PartEditor_Controls;
+	public String PartEditor_TrimBars;
 
 	public String PartSashContainerEditor_Label;
 	public String PartSashContainerEditor_Description;
@@ -309,6 +311,7 @@
 	public String PerspectiveEditor_Tooltip;
 	public String PerspectiveEditor_IconURI;
 	public String PerspectiveEditor_Controls;
+	public String PerspectiveEditor_TrimBars;
 	public String PerspectiveEditor_AddPartSashContainer;
 	public String PerspectiveEditor_AddPartStack;
 	public String PerspectiveEditor_AddPart;
@@ -574,8 +577,19 @@
 
 	public String VWindowTrimEditor_TreeLabel;
 	public String VWindowTrimEditor_TreeLabelDescription;
-	public String VWindowTrimEditor_Controls;
-	public String VWindowTrimEditor_AddWindowTrim;
+	public String VWindowTrimEditor_AddTrim;
+
+	public String VPartTrimEditor_TreeLabel;
+	public String VPartTrimEditor_TreeLabelDescription;
+	public String VPartTrimEditor_AddTrim;
+
+	public String VPartDescriptorTrimEditor_TreeLabel;
+	public String VPartDescriptorTrimEditor_TreeLabelDescription;
+	public String VPartDescriptorTrimEditor_AddTrim;
+
+	public String VPerspectiveTrimEditor_TreeLabel;
+	public String VPerspectiveTrimEditor_TreeLabelDescription;
+	public String VPerspectiveTrimEditor_AddTrim;
 
 	public String AbstractIconDialog_IconName;
 	public String AbstractIconDialog_all_workspace_bundles;
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 6ea3761..d3b235a 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
@@ -223,6 +223,7 @@
 PartDescriptorEditor_Menus=Menus
 PartDescriptorEditor_Handlers=Handlers
 PartDescriptorEditor_ContainerData=Container &Data\:
+PartDescriptorEditor_TrimBars=Trim Bars
 
 PartEditor_Label=Part
 PartEditor_Description=Part 
@@ -239,6 +240,7 @@
 PartEditor_ToolBar=ToolBar
 PartEditor_BindingContexts=Binding Contexts
 PartEditor_Controls=Controls
+PartEditor_TrimBars=Trim Bars
 
 PartSashContainerEditor_Label=Part Sash Container
 PartSashContainerEditor_Description=Sash
@@ -275,6 +277,7 @@
 PerspectiveEditor_Tooltip=T&ooltip\:
 PerspectiveEditor_IconURI=&Icon URI\:
 PerspectiveEditor_Controls=Controls
+PerspectiveEditor_TrimBars=Trim Bars
 PerspectiveEditor_AddPartSashContainer=Part Sash Container
 PerspectiveEditor_AddPartStack=Part Stack
 PerspectiveEditor_AddPart=Part
@@ -433,8 +436,8 @@
 ToolItemEditor_NoExpression=<None>
 ToolItemEditor_Menu=Menu
 
-TrimBarEditor_TreeLabel=Window Trim
-TrimBarEditor_TreeLabelDescription=Window Trim
+TrimBarEditor_TreeLabel=Trim Bar
+TrimBarEditor_TreeLabelDescription=Trim Bar
 TrimBarEditor_Side=Side
 TrimBarEditor_Controls=Controls
 TrimBarEditor_AddToolBar=Toolbar
@@ -446,7 +449,7 @@
 TrimContributionEditor_Position=&Position\:
 TrimContributionEditor_Controls=Controls
 
-TrimmedWindowEditor_TrimBars=TrimBars
+TrimmedWindowEditor_TrimBars=Trim Bars
 TrimmedWindowEditor_TreeLabel=Trimmed Window
 
 WindowEditor_AddMainMenu=Main Menu
@@ -550,8 +553,20 @@
 
 VWindowTrimEditor_TreeLabel=Window Trims
 VWindowTrimEditor_TreeLabelDescription=Window Trims
-VWindowTrimEditor_Controls=Controls
-VWindowTrimEditor_AddWindowTrim=Window Trim
+VWindowTrimEditor_AddTrim=Window Trim
+
+VPartTrimEditor_TreeLabel=Part Trims
+VPartTrimEditor_TreeLabelDescription=Part Trims
+VPartTrimEditor_AddTrim=Part Trim
+
+VPartDescriptorTrimEditor_TreeLabel=Part Trims
+VPartDescriptorTrimEditor_TreeLabelDescription=Part Trims
+VPartDescriptorTrimEditor_AddTrim=Part Trim
+
+VPerspectiveTrimEditor_TreeLabel=Perspective Trims
+VPerspectiveTrimEditor_TreeLabelDescription=Perspective Trims
+VPerspectiveTrimEditor_Controls=Controls
+VPerspectiveTrimEditor_AddTrim=Perspective Trim
 
 AbstractIconDialog_IconName=IconName
 AbstractIconDialog_Type_To_Start_Search=Type to start search
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 bdea5b4..d969144 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
@@ -133,8 +133,11 @@
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VModelImportsEditor;
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPartDescriptor;
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPartDescriptorMenuEditor;
+import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPartDescriptorTrimEditor;
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPartMenuEditor;
+import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPartTrimEditor;
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPerspectiveControlEditor;
+import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPerspectiveTrimEditor;
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPerspectiveWindowsEditor;
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VRootBindingContexts;
 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VSnippetsEditor;
@@ -260,8 +263,10 @@
 	public static final String VIRTUAL_PERSPECTIVE_WINDOWS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PERSPECTIVE_WINDOWS"; //$NON-NLS-1$
 	public static final String VIRTUAL_WINDOW_WINDOWS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_WINDOW_WINDOWS"; //$NON-NLS-1$
 	public static final String VIRTUAL_WINDOW_CONTROLS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_WINDOW_CONTROLS"; //$NON-NLS-1$
+	public static final String VIRTUAL_PART_TRIMS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PART_TRIMS"; //$NON-NLS-1$
 	public static final String VIRTUAL_PART_DESCRIPTORS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PART_DESCRIPTORS"; //$NON-NLS-1$
 	public static final String VIRTUAL_PARTDESCRIPTOR_MENU = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PARTDESCRIPTOR_MENU"; //$NON-NLS-1$
+	public static final String VIRTUAL_PARTDESCRIPTOR_TRIMS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PART_DESCRIPTOR_TRIMS"; //$NON-NLS-1$
 	public static final String VIRTUAL_TRIMMED_WINDOW_TRIMS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_TRIMMED_WINDOW_TRIMS"; //$NON-NLS-1$
 	public static final String VIRTUAL_ADDONS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_ADDONS"; //$NON-NLS-1$
 	public static final String VIRTUAL_MENU_CONTRIBUTIONS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_MENU_CONTRIBUTIONS"; //$NON-NLS-1$
@@ -277,6 +282,7 @@
 	public static final String VIRTUAL_MENUELEMENTS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_MENUELEMENTS"; //$NON-NLS-1$
 	public static final String VIRTUAL_ROOT_CONTEXTS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_ROOT_CONTEXTS"; //$NON-NLS-1$
 	public static final String VIRTUAL_PERSPECTIVE_CONTROLS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PERSPECTIVE_CONTROLS"; //$NON-NLS-1$
+	public static final String VIRTUAL_PERSPECTIVE_TRIMS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PERSPECTIVE_TRIMS"; //$NON-NLS-1$
 	public static final String VIRTUAL_SNIPPETS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_SNIPPETS"; //$NON-NLS-1$
 
 	public static final int TAB_FORM = 0;
@@ -284,6 +290,7 @@
 	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
@@ -1143,6 +1150,7 @@
 
 	private void registerVirtualEditors() {
 		registerEditor(VIRTUAL_PART_MENU, VPartMenuEditor.class);
+		registerEditor(VIRTUAL_PART_TRIMS, VPartTrimEditor.class);
 		registerEditor(VIRTUAL_HANDLER, VHandlerEditor.class);
 		registerEditor(VIRTUAL_CONTROLS, VControlsEditor.class);
 		registerEditor(VIRTUAL_BINDING_TABLE, VBindingTableEditor.class);
@@ -1154,6 +1162,7 @@
 		registerEditor(VIRTUAL_WINDOW_SNIPPETS, VSnippetsEditor.class);
 		registerEditor(VIRTUAL_PART_DESCRIPTORS, VPartDescriptor.class);
 		registerEditor(VIRTUAL_PARTDESCRIPTOR_MENU, VPartDescriptorMenuEditor.class);
+		registerEditor(VIRTUAL_PARTDESCRIPTOR_TRIMS, VPartDescriptorTrimEditor.class);
 		registerEditor(VIRTUAL_TRIMMED_WINDOW_TRIMS, VWindowTrimEditor.class);
 		registerEditor(VIRTUAL_ADDONS, VApplicationAddons.class);
 		registerEditor(VIRTUAL_MENU_CONTRIBUTIONS, VMenuContributionsEditor.class);
@@ -1166,6 +1175,7 @@
 		registerEditor(VIRTUAL_PARAMETERS, VItemParametersEditor.class);
 		registerEditor(VIRTUAL_ROOT_CONTEXTS, VRootBindingContexts.class);
 		registerEditor(VIRTUAL_PERSPECTIVE_CONTROLS, VPerspectiveControlEditor.class);
+		registerEditor(VIRTUAL_PERSPECTIVE_TRIMS, VPerspectiveTrimEditor.class);
 		registerEditor(VIRTUAL_SNIPPETS, VSnippetsEditor.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
index 67e42cc..810f62c 100644
--- 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
@@ -319,6 +319,8 @@
 				Messages.PartEditor_Menus));
 		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_HANDLER, E4Properties.handlers(), part,
 				Messages.PartEditor_Handlers));
+		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_PART_TRIMS, E4Properties.partTrimBars(), part,
+				Messages.PartEditor_TrimBars));
 
 		if (part.getToolbar() != null) {
 			list.add(0, part.getToolbar());
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartDescriptorEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartDescriptorEditor.java
index f63f1b6..5087884 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartDescriptorEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PartDescriptorEditor.java
@@ -341,22 +341,24 @@
 	@Override
 	public IObservableList<?> getChildList(final Object element) {
 		final WritableList<Object> list = new WritableList<>();
-		final MPartDescriptor window = (MPartDescriptor) element;
+		final MPartDescriptor partDescriptor = (MPartDescriptor) element;
 
 		if (getEditor().isModelFragment() && Util.isImport((EObject) element)) {
 			return list;
 		}
 
-		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_PARTDESCRIPTOR_MENU, E4Properties.partDescriptorMenus(), window,
+		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_PARTDESCRIPTOR_MENU, E4Properties.partDescriptorMenus(), partDescriptor,
 				Messages.PartDescriptorEditor_Menus));
-		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_HANDLER, E4Properties.handlers(), window,
+		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_HANDLER, E4Properties.handlers(), partDescriptor,
 				Messages.PartDescriptorEditor_Handlers));
+		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_PARTDESCRIPTOR_TRIMS, E4Properties.partDescriptorTrimBars(),
+				partDescriptor, Messages.PartDescriptorEditor_TrimBars));
 
-		if (window.getToolbar() != null) {
-			list.add(0, window.getToolbar());
+		if (partDescriptor.getToolbar() != null) {
+			list.add(0, partDescriptor.getToolbar());
 		}
 
-		E4Properties.partDescriptorToolbar().observe(window).addValueChangeListener(event -> {
+		E4Properties.partDescriptorToolbar().observe(partDescriptor).addValueChangeListener(event -> {
 			if (event.diff.getOldValue() != null) {
 				list.remove(event.diff.getOldValue());
 				if (getMaster().getValue() == element && !createRemoveToolBar.isDisposed()) {
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PerspectiveEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PerspectiveEditor.java
index b86c2b6..e873730 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PerspectiveEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/PerspectiveEditor.java
@@ -305,6 +305,8 @@
 				Messages.WindowEditor_Windows));
 		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_PERSPECTIVE_CONTROLS, E4Properties.children(), perspective,
 				Messages.PerspectiveEditor_Controls));
+		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_PERSPECTIVE_TRIMS, E4Properties.perspectiveTrimBars(),
+				perspective, Messages.PerspectiveEditor_TrimBars));
 
 		return list;
 	}
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/TrimmedWindowEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/TrimmedWindowEditor.java
index 65b3bb9..29e898f 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/TrimmedWindowEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/TrimmedWindowEditor.java
@@ -37,7 +37,7 @@
 			return list;
 		}
 
-		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_TRIMMED_WINDOW_TRIMS, E4Properties.trimBars(),
+		list.add(new VirtualEntry<>(ModelEditor.VIRTUAL_TRIMMED_WINDOW_TRIMS, E4Properties.windowTrimBars(),
 				(MTrimmedWindow) element, Messages.TrimmedWindowEditor_TrimBars));
 		return list;
 	}
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/AbstractVTrimEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/AbstractVTrimEditor.java
new file mode 100644
index 0000000..e1e63f4
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/AbstractVTrimEditor.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * 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 org.eclipse.core.databinding.observable.list.IObservableList;
+import org.eclipse.core.databinding.observable.value.WritableValue;
+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.VirtualEntry;
+import org.eclipse.e4.ui.model.application.ui.basic.MBasicFactory;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.databinding.EMFDataBindingContext;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.edit.command.AddCommand;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.TableViewer;
+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;
+
+public abstract class AbstractVTrimEditor<M> extends AbstractComponentEditor<M> {
+	private Composite composite;
+	private EMFDataBindingContext context;
+	private TableViewer viewer;
+	private final List<Action> actions = new ArrayList<>();
+
+	protected abstract String getActionLabel();
+
+	protected abstract List<?> getTrimBars(Object master);
+
+	protected abstract EReference getTrimBarFeature();
+
+	@PostConstruct
+	void init() {
+		actions.add(new Action(getActionLabel(), createImageDescriptor(ResourceProvider.IMG_WindowTrim)) {
+			@Override
+			public void run() {
+				handleAdd();
+			}
+		});
+	}
+
+	@Override
+	public Composite doGetEditor(Composite parent, Object object) {
+		if (composite == null) {
+			context = new EMFDataBindingContext();
+			composite = createForm(parent, context, getMaster());
+		}
+		@SuppressWarnings("unchecked")
+		final VirtualEntry<M, ?> o = (VirtualEntry<M, ?>) object;
+		viewer.setInput(o.getList());
+		getMaster().setValue(o.getOriginalParent());
+		return composite;
+	}
+
+	private Composite createForm(Composite parent, EMFDataBindingContext context,
+			WritableValue<M> 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_PICKER, PickListFeatures.NO_GROUP), this,
+					getTrimBarFeature()) {
+				@Override
+				protected void addPressed() {
+					handleAdd();
+				}
+
+				@Override
+				protected List<?> getContainerChildren(Object master) {
+					return getTrimBars(master);
+				}
+			};
+			pickList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
+			viewer = pickList.getList();
+		}
+
+		folder.setSelection(0);
+
+		return folder;
+	}
+
+	@Override
+	public IObservableList<?> getChildList(Object element) {
+		return null;
+	}
+
+	protected void handleAdd() {
+		final MTrimBar handler = MBasicFactory.INSTANCE.createTrimBar();
+		setElementId(handler);
+
+		final Command cmd = AddCommand.create(getEditingDomain(), getMaster().getValue(),
+				getTrimBarFeature(), handler);
+
+		if (cmd.canExecute()) {
+			getEditingDomain().getCommandStack().execute(cmd);
+			getEditor().setSelection(handler);
+		}
+	}
+
+	@Override
+	public List<Action> getActions(Object element) {
+		final ArrayList<Action> l = new ArrayList<>(super.getActions(element));
+		l.addAll(actions);
+		return l;
+	}
+}
\ 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/VPartDescriptorTrimEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VPartDescriptorTrimEditor.java
new file mode 100644
index 0000000..d2b42e3
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VPartDescriptorTrimEditor.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.List;
+
+import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor;
+import org.eclipse.e4.ui.model.application.descriptor.basic.impl.BasicPackageImpl.Literals;
+import org.eclipse.emf.ecore.EReference;
+
+public class VPartDescriptorTrimEditor extends AbstractVTrimEditor<MPartDescriptor> {
+
+	@Override
+	protected String getActionLabel() {
+		return Messages.VPartDescriptorTrimEditor_AddTrim;
+	}
+
+	@Override
+	protected List<?> getTrimBars(Object master) {
+		if (master instanceof MPartDescriptor) {
+			return ((MPartDescriptor) master).getTrimBars();
+		}
+		return null;
+	}
+
+	@Override
+	protected EReference getTrimBarFeature() {
+		return Literals.PART_DESCRIPTOR__TRIM_BARS;
+	}
+
+	@Override
+	public String getLabel(Object element) {
+		return Messages.VPartDescriptorTrimEditor_TreeLabel;
+	}
+
+	@Override
+	public String getDetailLabel(Object element) {
+		return null;
+	}
+
+	@Override
+	public String getDescription(Object element) {
+		return Messages.VPartDescriptorTrimEditor_TreeLabelDescription;
+	}
+
+}
\ 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/VPartTrimEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VPartTrimEditor.java
new file mode 100644
index 0000000..8dc6f2d
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VPartTrimEditor.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.List;
+
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
+import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl.Literals;
+import org.eclipse.emf.ecore.EReference;
+
+public class VPartTrimEditor extends AbstractVTrimEditor<MPart> {
+
+	@Override
+	protected String getActionLabel() {
+		return Messages.VPartTrimEditor_AddTrim;
+	}
+
+	@Override
+	protected List<?> getTrimBars(Object master) {
+		if (master instanceof MPart) {
+			return ((MPart) master).getTrimBars();
+		}
+		return null;
+	}
+
+	@Override
+	protected EReference getTrimBarFeature() {
+		return Literals.PART__TRIM_BARS;
+	}
+
+	@Override
+	public String getLabel(Object element) {
+		return Messages.VPartTrimEditor_TreeLabel;
+	}
+
+	@Override
+	public String getDetailLabel(Object element) {
+		return null;
+	}
+
+	@Override
+	public String getDescription(Object element) {
+		return Messages.VPartTrimEditor_TreeLabelDescription;
+	}
+
+}
\ 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/VPerspectiveTrimEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VPerspectiveTrimEditor.java
new file mode 100644
index 0000000..4d32c29
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VPerspectiveTrimEditor.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.List;
+
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.impl.AdvancedPackageImpl.Literals;
+import org.eclipse.emf.ecore.EReference;
+
+public class VPerspectiveTrimEditor extends AbstractVTrimEditor<MPerspective> {
+
+	@Override
+	protected String getActionLabel() {
+		return Messages.VPerspectiveTrimEditor_AddTrim;
+	}
+
+	@Override
+	protected List<?> getTrimBars(Object master) {
+		if (master instanceof MPerspective) {
+			return ((MPerspective) master).getTrimBars();
+		}
+		return null;
+	}
+
+	@Override
+	protected EReference getTrimBarFeature() {
+		return Literals.PERSPECTIVE__TRIM_BARS;
+	}
+
+	@Override
+	public String getLabel(Object element) {
+		return Messages.VPerspectiveTrimEditor_TreeLabel;
+	}
+
+	@Override
+	public String getDetailLabel(Object element) {
+		return null;
+	}
+
+	@Override
+	public String getDescription(Object element) {
+		return Messages.VPerspectiveTrimEditor_TreeLabelDescription;
+	}
+
+}
\ 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/VSnippetsEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VSnippetsEditor.java
index eb5b43b..bead050 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VSnippetsEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VSnippetsEditor.java
@@ -142,8 +142,8 @@
 				handleAdd(BasicPackageImpl.Literals.WINDOW);
 			}
 		});
-		actions.add(new Action(Messages.VWindowTrimEditor_AddWindowTrim,
-				createImageDescriptor(ResourceProvider.IMG_WindowTrim)) {
+		actions.add(new Action(Messages.VWindowTrimEditor_AddTrim,
+		    createImageDescriptor(ResourceProvider.IMG_WindowTrim)) {
 			@Override
 			public void run() {
 				handleAdd(BasicPackageImpl.Literals.TRIM_BAR);
diff --git a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VWindowTrimEditor.java b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VWindowTrimEditor.java
index 2b1994b..0435f1f 100644
--- a/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VWindowTrimEditor.java
+++ b/bundles/org.eclipse.e4.tools.emf.ui/src/org/eclipse/e4/tools/emf/ui/internal/common/component/virtual/VWindowTrimEditor.java
@@ -14,56 +14,30 @@
  ******************************************************************************/
 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.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.VirtualEntry;
-import org.eclipse.e4.ui.model.application.ui.basic.MBasicFactory;
-import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
 import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
 import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl;
-import org.eclipse.emf.common.command.Command;
-import org.eclipse.emf.databinding.EMFDataBindingContext;
-import org.eclipse.emf.edit.command.AddCommand;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.viewers.TableViewer;
-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.emf.ecore.EReference;
 
-public class VWindowTrimEditor extends AbstractComponentEditor<MTrimmedWindow> {
-	private Composite composite;
-	private EMFDataBindingContext context;
-	private TableViewer viewer;
-	private final List<Action> actions = new ArrayList<>();
+public class VWindowTrimEditor extends AbstractVTrimEditor<MTrimmedWindow> {
 
-	@Inject
-	public VWindowTrimEditor() {
-		super();
+	@Override
+	protected String getActionLabel() {
+		return Messages.VWindowTrimEditor_AddTrim;
 	}
 
-	@PostConstruct
-	void init() {
-		actions.add(new Action(Messages.VWindowTrimEditor_AddWindowTrim,
-				createImageDescriptor(ResourceProvider.IMG_WindowTrim)) {
-			@Override
-			public void run() {
-				handleAdd();
-			}
-		});
+	@Override
+	protected List<?> getTrimBars(Object master) {
+		if (master instanceof MTrimmedWindow) {
+			return ((MTrimmedWindow) master).getTrimBars();
+		}
+		return null;
+	}
+
+	@Override
+	protected EReference getTrimBarFeature() {
+		return BasicPackageImpl.Literals.TRIMMED_WINDOW__TRIM_BARS;
 	}
 
 	@Override
@@ -81,77 +55,4 @@
 		return Messages.VWindowTrimEditor_TreeLabelDescription;
 	}
 
-	@Override
-	public Composite doGetEditor(Composite parent, Object object) {
-		if (composite == null) {
-			context = new EMFDataBindingContext();
-			composite = createForm(parent, context, getMaster());
-		}
-		@SuppressWarnings("unchecked")
-		final VirtualEntry<MTrimmedWindow, ?> o = (VirtualEntry<MTrimmedWindow, ?>) object;
-		viewer.setInput(o.getList());
-		getMaster().setValue(o.getOriginalParent());
-		return composite;
-	}
-
-	private Composite createForm(Composite parent, EMFDataBindingContext context,
-			WritableValue<MTrimmedWindow> 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_PICKER, PickListFeatures.NO_GROUP), this,
-					BasicPackageImpl.Literals.TRIMMED_WINDOW__TRIM_BARS) {
-				@Override
-				protected void addPressed() {
-					handleAdd();
-				}
-
-				@Override
-				protected List<?> getContainerChildren(Object master) {
-					if (master instanceof MTrimmedWindow) {
-						return ((MTrimmedWindow) master).getTrimBars();
-					}
-					return null;
-				}
-			};
-			pickList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
-			viewer = pickList.getList();
-		}
-
-		folder.setSelection(0);
-
-		return folder;
-	}
-
-	@Override
-	public IObservableList<?> getChildList(Object element) {
-		return null;
-	}
-
-	protected void handleAdd() {
-		final MTrimBar handler = MBasicFactory.INSTANCE.createTrimBar();
-		setElementId(handler);
-
-		final Command cmd = AddCommand.create(getEditingDomain(), getMaster().getValue(),
-				BasicPackageImpl.Literals.TRIMMED_WINDOW__TRIM_BARS, handler);
-
-		if (cmd.canExecute()) {
-			getEditingDomain().getCommandStack().execute(cmd);
-			getEditor().setSelection(handler);
-		}
-	}
-
-	@Override
-	public List<Action> getActions(Object element) {
-		final ArrayList<Action> l = new ArrayList<>(super.getActions(element));
-		l.addAll(actions);
-		return l;
-	}
 }
\ No newline at end of file