commit 4cab94052be0feaa7ae3e08681d1d0f120442b44
Author: Patrick Plitzner <p.plitzner@bgbm.org>
Date:   Mon Jun 19 10:59:52 2017 +0200

    ref #6694 Extract composite and Listeners from FeatureTreeEditor
    # Conflicts:
    #       eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureTreeEditor.java

diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureNodeDragListener.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureNodeDragListener.java
new file mode 100644
index 000000000..10ddd7fc8
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureNodeDragListener.java
@@ -0,0 +1,68 @@
+/**
+* Copyright (C) 2017 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.taxeditor.featuretree.e4;
+
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSourceAdapter;
+import org.eclipse.swt.dnd.DragSourceEvent;
+
+import eu.etaxonomy.cdm.model.description.FeatureNode;
+import eu.etaxonomy.taxeditor.featuretree.FeatureNodeTransfer;
+
+class FeatureNodeDragListener extends DragSourceAdapter {
+
+	private final TreeViewer viewer;
+
+	public FeatureNodeDragListener(TreeViewer viewer) {
+		this.viewer = viewer;
+	}
+
+	/**
+	 * Method declared on DragSourceListener
+	 */
+	@Override
+	public void dragFinished(DragSourceEvent event) {
+		if (!event.doit) {
+            return;
+        }
+		// if the featureNode was moved, remove it from the source viewer
+		if (event.detail == DND.DROP_MOVE) {
+			IStructuredSelection selection = (IStructuredSelection) viewer
+					.getSelection();
+			viewer.remove(selection);
+			viewer.refresh();
+		}
+	}
+
+	/**
+	 * Method declared on DragSourceListener
+	 */
+	@Override
+	public void dragSetData(DragSourceEvent event) {
+		IStructuredSelection selection = (IStructuredSelection) viewer
+				.getSelection();
+		FeatureNode[] featureNodes = (FeatureNode[]) selection.toList()
+				.toArray(new FeatureNode[selection.size()]);
+		if (FeatureNodeTransfer.getInstance().isSupportedType(
+				event.dataType)) {
+			event.data = featureNodes;
+		}
+	}
+
+	/**
+	 * Method declared on DragSourceListener
+	 */
+	@Override
+	public void dragStart(DragSourceEvent event) {
+		event.doit = !viewer.getSelection().isEmpty();
+	}
+
+}
\ No newline at end of file
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureNodeDropAdapter.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureNodeDropAdapter.java
new file mode 100644
index 000000000..1c6e8da4e
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureNodeDropAdapter.java
@@ -0,0 +1,92 @@
+/**
+* Copyright (C) 2017 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.taxeditor.featuretree.e4;
+
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerDropAdapter;
+import org.eclipse.swt.dnd.TransferData;
+
+import eu.etaxonomy.cdm.model.description.FeatureNode;
+import eu.etaxonomy.cdm.model.description.FeatureTree;
+import eu.etaxonomy.taxeditor.featuretree.FeatureNodeTransfer;
+import eu.etaxonomy.taxeditor.model.MessagingUtils;
+
+class FeatureNodeDropAdapter extends ViewerDropAdapter {
+
+	/**
+     *
+     */
+    private final FeatureTreeEditor featureTreeEditor;
+
+    protected FeatureNodeDropAdapter(FeatureTreeEditor featureTreeEditor, Viewer viewer) {
+		super(viewer);
+        this.featureTreeEditor = featureTreeEditor;
+	}
+
+	@Override
+	public boolean performDrop(Object data) {
+		FeatureNode target = (FeatureNode) getCurrentTarget();
+		int position = 0;
+
+		if (target != null) {
+			int location = getCurrentLocation();
+			FeatureNode parent = target.getParent();
+			if (location == LOCATION_BEFORE) {
+				position = Math.max(0, parent.getIndex(target) - 1);
+				target = parent;
+			}
+
+			if (location == LOCATION_AFTER) {
+				position = parent.getIndex(target);
+				target = parent;
+			}
+		}
+
+		// set target to root node if there is no target specified
+		if (target == null) {
+			FeatureTree featureTree = (FeatureTree) getViewer().getInput();
+			target = featureTree.getRoot();
+		}
+
+		Object[] droppedObjects = (Object[]) data;
+		TreeViewer viewer = (TreeViewer) getViewer();
+
+		// cannot drop a feature node onto itself
+		for (Object droppedObject : droppedObjects) {
+			if (droppedObject == null) {
+				MessagingUtils.warningDialog(
+								"Operation not supported yet",
+								this,
+								"We are currently unable to change the order of freshly created "
+										+ "feature trees nodes. Please close and reopen the dialog to change the order of features.");
+				return false;
+			}
+			if (droppedObject.equals(target)) {
+				return false;
+			}
+		}
+		for (Object droppedObject : droppedObjects) {
+			FeatureNode droppedNode = (FeatureNode) droppedObject;
+			target.addChild(droppedNode, position);
+			viewer.add(target, droppedNode);
+			viewer.reveal(droppedNode);
+		}
+        this.featureTreeEditor.setDirty(true);
+		return true;
+	}
+
+	@Override
+	public boolean validateDrop(Object target, int operation,
+			TransferData transferData) {
+		return FeatureNodeTransfer.getInstance().isSupportedType(
+				transferData);
+	}
+
+}
\ No newline at end of file
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureTreeEditor.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureTreeEditor.java
index ec1d61bf7..331d5c72c 100644
--- a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureTreeEditor.java
+++ b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureTreeEditor.java
@@ -24,29 +24,14 @@ import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
 import org.eclipse.jface.viewers.ISelectionChangedListener;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerDropAdapter;
 import org.eclipse.jface.wizard.WizardDialog;
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.dnd.DND;
-import org.eclipse.swt.dnd.DragSourceAdapter;
-import org.eclipse.swt.dnd.DragSourceEvent;
-import org.eclipse.swt.dnd.Transfer;
-import org.eclipse.swt.dnd.TransferData;
 import org.eclipse.swt.events.ModifyEvent;
 import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-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.Label;
 import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.swt.widgets.Tree;
 
 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
 import eu.etaxonomy.cdm.api.service.IFeatureNodeService;
@@ -57,11 +42,6 @@ import eu.etaxonomy.cdm.model.description.Feature;
 import eu.etaxonomy.cdm.model.description.FeatureNode;
 import eu.etaxonomy.cdm.model.description.FeatureTree;
 import eu.etaxonomy.taxeditor.featuretree.AvailableFeaturesWizard;
-import eu.etaxonomy.taxeditor.featuretree.FeatureNodeTransfer;
-import eu.etaxonomy.taxeditor.featuretree.FeatureTreeContentProvider;
-import eu.etaxonomy.taxeditor.featuretree.FeatureTreeLabelProvider;
-import eu.etaxonomy.taxeditor.model.ImageResources;
-import eu.etaxonomy.taxeditor.model.MessagingUtils;
 import eu.etaxonomy.taxeditor.store.CdmStore;
 import eu.etaxonomy.taxeditor.ui.dialog.selection.FeatureTreeSelectionDialog;
 
@@ -74,14 +54,6 @@ import eu.etaxonomy.taxeditor.ui.dialog.selection.FeatureTreeSelectionDialog;
 public class FeatureTreeEditor implements
 		ModifyListener, ISelectionChangedListener {
 
-	private TreeViewer viewer;
-	private Label label_title;
-	private Button button_add;
-	private Button button_remove;
-	private FeatureTree featureTree;
-	private Text text_title;
-    private Button btnOpenFeatureTree;
-
     private ConversationHolder conversation;
 
     @Inject
@@ -92,6 +64,10 @@ public class FeatureTreeEditor implements
 
     private Shell shell;
 
+    private FeatureTree featureTree;
+
+    private FeatureTreeEditorComposite composite;
+
     @Inject
     public FeatureTreeEditor(@Named(IServiceConstants.ACTIVE_SHELL)Shell shell) {
         this.shell = shell;
@@ -103,75 +79,8 @@ public class FeatureTreeEditor implements
 	/** {@inheritDoc} */
 	@PostConstruct
 	public void createControl(Composite parent, @Named(IServiceConstants.ACTIVE_SHELL)Shell shell) {
-	    parent.setLayout(new GridLayout(2, false));
-
-		Composite composite_treeTitle = new Composite(parent, SWT.NULL);
-		composite_treeTitle.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true,
-				false));
-		GridLayout gl_composite_treeTitle = new GridLayout(2, false);
-		gl_composite_treeTitle.marginWidth = 0;
-		composite_treeTitle.setLayout(gl_composite_treeTitle);
-
-		label_title = new Label(composite_treeTitle, SWT.NULL);
-		label_title.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
-		label_title.setText("Feature Tree");
-
-		text_title = new Text(composite_treeTitle, SWT.BORDER);
-		text_title.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
-		text_title.setEditable(false);
-
-		btnOpenFeatureTree = new Button(parent, SWT.NONE);
-		btnOpenFeatureTree.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
-		btnOpenFeatureTree.setToolTipText("Open Tree");
-		btnOpenFeatureTree.setImage(ImageResources.getImage(ImageResources.BROWSE_ICON));
-
-		viewer = new TreeViewer(parent);
-		Tree tree = viewer.getTree();
-		tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
-		viewer.getControl().setLayoutData(
-				new GridData(SWT.FILL, SWT.FILL, true, true));
-
-		Composite composite_buttons = new Composite(parent,
-				SWT.NULL);
-		composite_buttons.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false,
-				false));
-		composite_buttons.setLayout(new GridLayout());
-
-		button_add = new Button(composite_buttons, SWT.PUSH);
-		button_add.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
-		button_add.setToolTipText("Add a feature to this feature tree.");
-		button_add.setImage(ImageResources.getImage(ImageResources.ADD_EDIT));
-		button_remove = new Button(composite_buttons, SWT.PUSH);
-		button_remove.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
-		button_remove.setToolTipText("Remove a feature from this feature tree.");
-		button_remove.setImage(ImageResources.getImage(ImageResources.TRASH_ICON));
-
-		init(shell);
-	}
-
-	private void setDirty(boolean isDirty){
-	    this.dirty.setDirty(isDirty);
-	}
-
-    private void init(Shell shell) {
-        viewer.setContentProvider(new FeatureTreeContentProvider());
-        viewer.setLabelProvider(new FeatureTreeLabelProvider());
-
-        int ops = DND.DROP_COPY | DND.DROP_MOVE;
-        Transfer[] transfers = new Transfer[] { FeatureNodeTransfer
-                .getInstance() };
-        viewer.addDragSupport(ops, transfers, new FeatureNodeDragListener(
-                viewer));
-        viewer.addDropSupport(ops, transfers,
-                new FeatureNodeDropAdapter(viewer));
-
-        viewer.addSelectionChangedListener(this);
-
-        button_add.addSelectionListener(new AddButtonListener());
-        button_remove.addSelectionListener(new RemoveSelectionListener());
-
-        btnOpenFeatureTree.addSelectionListener(new SelectionListener() {
-
+	    composite = new FeatureTreeEditorComposite(parent, SWT.NULL);
+		composite.init(new FeatureNodeDragListener(composite.getViewer()), new FeatureNodeDropAdapter(this, composite.getViewer()), this, new SelectionAdapter() {
             @Override
             public void widgetSelected(SelectionEvent e) {
                 FeatureTree tree = FeatureTreeSelectionDialog.select(shell, conversation, null);
@@ -179,28 +88,27 @@ public class FeatureTreeEditor implements
                     setSelectedTree(tree);
                 }
             }
+        }, new AddButtonListener(), new RemoveSelectionListener());
+	}
 
-            @Override
-            public void widgetDefaultSelected(SelectionEvent e) {
-            }
-        });
-    }
+	public void setDirty(boolean isDirty){
+	    this.dirty.setDirty(isDirty);
+	}
 
     public void setSelectedTree(FeatureTree featureTree) {
 		this.featureTree = HibernateProxyHelper.deproxy(featureTree, FeatureTree.class);
 		this.featureTree.setRoot(HibernateProxyHelper.deproxy(featureTree.getRoot(), FeatureNode.class));
-		viewer.setInput(featureTree);
+		composite.getViewer().setInput(featureTree);
 
-		text_title.removeModifyListener(this);
-		text_title.setText(featureTree.getTitleCache());
-		text_title.addModifyListener(this);
-		text_title.setEditable(true);
+		composite.getText_title().removeModifyListener(this);
+		composite.getText_title().setText(featureTree.getTitleCache());
+		composite.getText_title().addModifyListener(this);
 	}
 
 	/** {@inheritDoc} */
 	@Override
 	public void modifyText(ModifyEvent e) {
-		featureTree.setTitleCache(text_title.getText(), true);
+		featureTree.setTitleCache(composite.getText_title().getText(), true);
 		setDirty(true);
 	}
 
@@ -210,8 +118,8 @@ public class FeatureTreeEditor implements
 		IStructuredSelection selection = (IStructuredSelection) event
 				.getSelection();
 
-		button_add.setEnabled(selection.size() <= 1);
-		button_remove.setEnabled(selection.size() > 0);
+		composite.getButton_add().setEnabled(selection.size() <= 1);
+		composite.getButton_remove().setEnabled(selection.size() > 0);
 		//propagate selection
 		IStructuredSelection isel = (IStructuredSelection) event.getSelection();
 		selService.setSelection((isel.size() == 1 ? isel.getFirstElement() : isel.toArray()));
@@ -219,7 +127,7 @@ public class FeatureTreeEditor implements
 
 	@Focus
 	public void focus(){
-	    viewer.getControl().setFocus();
+	    composite.getViewer().getControl().setFocus();
         if(conversation!=null && !conversation.isBound()){
             conversation.bind();
         }
@@ -239,10 +147,10 @@ public class FeatureTreeEditor implements
 			WizardDialog dialog = new WizardDialog(shell, wizard);
 
 			if (dialog.open() == IStatus.OK) {
-				IStructuredSelection selection = (IStructuredSelection) viewer
+				IStructuredSelection selection = (IStructuredSelection) composite.getViewer()
 						.getSelection();
 				FeatureNode parent = (FeatureNode) (selection.getFirstElement() != null ? selection
-						.getFirstElement() : ((FeatureTree) viewer.getInput())
+						.getFirstElement() : ((FeatureTree) composite.getViewer().getInput())
 						.getRoot());
 				Collection<Feature> additionalFeatures = wizard
 						.getAdditionalFeatures();
@@ -253,7 +161,7 @@ public class FeatureTreeEditor implements
 					parent.addChild(child);
 				}
 				setDirty(true);
-				viewer.refresh();
+				composite.getViewer().refresh();
 			}
 		}
 
@@ -262,7 +170,7 @@ public class FeatureTreeEditor implements
 	private class RemoveSelectionListener extends SelectionAdapter {
 		@Override
 		public void widgetSelected(SelectionEvent e) {
-			IStructuredSelection selection = (IStructuredSelection) viewer
+			IStructuredSelection selection = (IStructuredSelection) composite.getViewer()
 					.getSelection();
 
 			for (Object selectedObject : selection.toArray()) {
@@ -274,124 +182,7 @@ public class FeatureTreeEditor implements
 
 			}
 			setDirty(true);
-			viewer.refresh();
+			composite.getViewer().refresh();
 		}
 	}
-
-	private class FeatureNodeDragListener extends DragSourceAdapter {
-
-		private final TreeViewer viewer;
-
-		public FeatureNodeDragListener(TreeViewer viewer) {
-			this.viewer = viewer;
-		}
-
-		/**
-		 * Method declared on DragSourceListener
-		 */
-		@Override
-		public void dragFinished(DragSourceEvent event) {
-			if (!event.doit) {
-                return;
-            }
-			// if the featureNode was moved, remove it from the source viewer
-			if (event.detail == DND.DROP_MOVE) {
-				IStructuredSelection selection = (IStructuredSelection) viewer
-						.getSelection();
-				viewer.remove(selection);
-				viewer.refresh();
-			}
-		}
-
-		/**
-		 * Method declared on DragSourceListener
-		 */
-		@Override
-		public void dragSetData(DragSourceEvent event) {
-			IStructuredSelection selection = (IStructuredSelection) viewer
-					.getSelection();
-			FeatureNode[] featureNodes = (FeatureNode[]) selection.toList()
-					.toArray(new FeatureNode[selection.size()]);
-			if (FeatureNodeTransfer.getInstance().isSupportedType(
-					event.dataType)) {
-				event.data = featureNodes;
-			}
-		}
-
-		/**
-		 * Method declared on DragSourceListener
-		 */
-		@Override
-		public void dragStart(DragSourceEvent event) {
-			event.doit = !viewer.getSelection().isEmpty();
-		}
-
-	}
-
-	private class FeatureNodeDropAdapter extends ViewerDropAdapter {
-
-		protected FeatureNodeDropAdapter(Viewer viewer) {
-			super(viewer);
-		}
-
-		@Override
-		public boolean performDrop(Object data) {
-			FeatureNode target = (FeatureNode) getCurrentTarget();
-			int position = 0;
-
-			if (target != null) {
-				int location = getCurrentLocation();
-				FeatureNode parent = target.getParent();
-				if (location == LOCATION_BEFORE) {
-					position = Math.max(0, parent.getIndex(target) - 1);
-					target = parent;
-				}
-
-				if (location == LOCATION_AFTER) {
-					position = parent.getIndex(target);
-					target = parent;
-				}
-			}
-
-			// set target to root node if there is no target specified
-			if (target == null) {
-				FeatureTree featureTree = (FeatureTree) getViewer().getInput();
-				target = featureTree.getRoot();
-			}
-
-			Object[] droppedObjects = (Object[]) data;
-			TreeViewer viewer = (TreeViewer) getViewer();
-
-			// cannot drop a feature node onto itself
-			for (Object droppedObject : droppedObjects) {
-				if (droppedObject == null) {
-					MessagingUtils.warningDialog(
-									"Operation not supported yet",
-									this,
-									"We are currently unable to change the order of freshly created "
-											+ "feature trees nodes. Please close and reopen the dialog to change the order of features.");
-					return false;
-				}
-				if (droppedObject.equals(target)) {
-					return false;
-				}
-			}
-			for (Object droppedObject : droppedObjects) {
-				FeatureNode droppedNode = (FeatureNode) droppedObject;
-				target.addChild(droppedNode, position);
-				viewer.add(target, droppedNode);
-				viewer.reveal(droppedNode);
-			}
-            setDirty(true);
-			return true;
-		}
-
-		@Override
-		public boolean validateDrop(Object target, int operation,
-				TransferData transferData) {
-			return FeatureNodeTransfer.getInstance().isSupportedType(
-					transferData);
-		}
-
-	}
 }
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureTreeEditorComposite.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureTreeEditorComposite.java
new file mode 100644
index 000000000..a59898f7d
--- /dev/null
+++ b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/featuretree/e4/FeatureTreeEditorComposite.java
@@ -0,0 +1,153 @@
+/**
+* Copyright (C) 2017 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.taxeditor.featuretree.e4;
+
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.SelectionListener;
+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.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+
+import eu.etaxonomy.taxeditor.featuretree.FeatureNodeTransfer;
+import eu.etaxonomy.taxeditor.featuretree.FeatureTreeContentProvider;
+import eu.etaxonomy.taxeditor.featuretree.FeatureTreeLabelProvider;
+import eu.etaxonomy.taxeditor.model.ImageResources;
+
+/**
+ * @author pplitzner
+ * @since Jun 19, 2017
+ *
+ */
+public class FeatureTreeEditorComposite extends Composite{
+
+    private Label label_title;
+    private Text text_title;
+    private Button btnOpenFeatureTree;
+    private TreeViewer viewer;
+    private Button button_add;
+    private Button button_remove;
+
+    public FeatureTreeEditorComposite(Composite parent, int style) {
+        super(parent, style);
+        setLayout(new GridLayout(2, false));
+
+        Composite composite_treeTitle = new Composite(this, SWT.NULL);
+        composite_treeTitle.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true,
+                false));
+        GridLayout gl_composite_treeTitle = new GridLayout(2, false);
+        gl_composite_treeTitle.marginWidth = 0;
+        composite_treeTitle.setLayout(gl_composite_treeTitle);
+
+        label_title = new Label(composite_treeTitle, SWT.NULL);
+        label_title.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+        label_title.setText("Feature Tree");
+
+        text_title = new Text(composite_treeTitle, SWT.BORDER);
+        text_title.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+
+        btnOpenFeatureTree = new Button(this, SWT.NONE);
+        btnOpenFeatureTree.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
+        btnOpenFeatureTree.setToolTipText("Open Tree");
+        btnOpenFeatureTree.setImage(ImageResources.getImage(ImageResources.BROWSE_ICON));
+
+        viewer = new TreeViewer(this);
+        Tree tree = viewer.getTree();
+        tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+        viewer.getControl().setLayoutData(
+                new GridData(SWT.FILL, SWT.FILL, true, true));
+
+        Composite composite_buttons = new Composite(this,
+                SWT.NULL);
+        composite_buttons.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false,
+                false));
+        composite_buttons.setLayout(new GridLayout());
+
+        button_add = new Button(composite_buttons, SWT.PUSH);
+        button_add.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
+        button_add.setToolTipText("Add a feature to this feature tree.");
+        button_add.setImage(ImageResources.getImage(ImageResources.ADD_EDIT));
+        button_remove = new Button(composite_buttons, SWT.PUSH);
+        button_remove.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
+        button_remove.setToolTipText("Remove a feature from this feature tree.");
+        button_remove.setImage(ImageResources.getImage(ImageResources.TRASH_ICON));
+    }
+
+    public void init(DragSourceListener dragSourceListener,
+            DropTargetListener dropTargetListener, ISelectionChangedListener viewerSelectionChangedListener,
+            SelectionListener selectionListener, SelectionListener addButtonSelectionListener, SelectionListener removeButtonSelectionListener) {
+        viewer.setContentProvider(new FeatureTreeContentProvider());
+        viewer.setLabelProvider(new FeatureTreeLabelProvider());
+
+        int ops = DND.DROP_COPY | DND.DROP_MOVE;
+        Transfer[] transfers = new Transfer[] { FeatureNodeTransfer
+                .getInstance() };
+        viewer.addDragSupport(ops, transfers, dragSourceListener);
+        viewer.addDropSupport(ops, transfers, dropTargetListener);
+
+        viewer.addSelectionChangedListener(viewerSelectionChangedListener);
+
+        button_add.addSelectionListener(addButtonSelectionListener);
+        button_remove.addSelectionListener(removeButtonSelectionListener);
+
+        btnOpenFeatureTree.addSelectionListener(selectionListener);
+    }
+
+    /**
+     * @return the label_title
+     */
+    public Label getLabel_title() {
+        return label_title;
+    }
+
+    /**
+     * @return the text_title
+     */
+    public Text getText_title() {
+        return text_title;
+    }
+
+    /**
+     * @return the btnOpenFeatureTree
+     */
+    public Button getBtnOpenFeatureTree() {
+        return btnOpenFeatureTree;
+    }
+
+    /**
+     * @return the viewer
+     */
+    public TreeViewer getViewer() {
+        return viewer;
+    }
+
+    /**
+     * @return the button_add
+     */
+    public Button getButton_add() {
+        return button_add;
+    }
+
+    /**
+     * @return the button_remove
+     */
+    public Button getButton_remove() {
+        return button_remove;
+    }
+
+}
