]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.document.linking.ui/src/org/simantics/document/linking/wizard/EvaluatorConfigurationWidget.java
Externalize org.simantics.document.linking.ui
[simantics/platform.git] / bundles / org.simantics.document.linking.ui / src / org / simantics / document / linking / wizard / EvaluatorConfigurationWidget.java
index 3fd2aa0fc89e6e27a6385710a14039ff92c24392..6f53d1f3580992ae787f127111e4473aac82b0c2 100644 (file)
-package org.simantics.document.linking.wizard;\r
-\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-\r
-import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.resource.ImageDescriptor;\r
-import org.eclipse.jface.resource.LocalResourceManager;\r
-import org.eclipse.jface.viewers.CellEditor;\r
-import org.eclipse.jface.viewers.ColumnViewer;\r
-import org.eclipse.jface.viewers.ColumnViewerEditor;\r
-import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;\r
-import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;\r
-import org.eclipse.jface.viewers.ICellModifier;\r
-import org.eclipse.jface.viewers.ISelection;\r
-import org.eclipse.jface.viewers.IStructuredSelection;\r
-import org.eclipse.jface.viewers.ITreeContentProvider;\r
-import org.eclipse.jface.viewers.LabelProvider;\r
-import org.eclipse.jface.viewers.StructuredSelection;\r
-import org.eclipse.jface.viewers.TextCellEditor;\r
-import org.eclipse.jface.viewers.TreeSelection;\r
-import org.eclipse.jface.viewers.TreeViewer;\r
-import org.eclipse.jface.viewers.TreeViewerEditor;\r
-import org.eclipse.jface.viewers.Viewer;\r
-import org.eclipse.jface.viewers.ViewerDropAdapter;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.dnd.DND;\r
-import org.eclipse.swt.dnd.DragSourceEvent;\r
-import org.eclipse.swt.dnd.DragSourceListener;\r
-import org.eclipse.swt.dnd.Transfer;\r
-import org.eclipse.swt.dnd.TransferData;\r
-import org.eclipse.swt.events.MenuDetectEvent;\r
-import org.eclipse.swt.events.MenuDetectListener;\r
-import org.eclipse.swt.events.MouseEvent;\r
-import org.eclipse.swt.events.SelectionAdapter;\r
-import org.eclipse.swt.events.SelectionEvent;\r
-import org.eclipse.swt.graphics.Image;\r
-import org.eclipse.swt.layout.GridLayout;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Control;\r
-import org.eclipse.swt.widgets.Menu;\r
-import org.eclipse.swt.widgets.MenuItem;\r
-import org.eclipse.swt.widgets.TreeItem;\r
-import org.eclipse.ui.plugin.AbstractUIPlugin;\r
-import org.simantics.browsing.ui.swt.ComboBoxCellEditor2;\r
-import org.simantics.document.linking.report.evaluator.EnumEditableNode;\r
-import org.simantics.document.linking.report.evaluator.EvaluatorItem;\r
-import org.simantics.document.linking.report.evaluator.EvaluatorNode;\r
-import org.simantics.document.linking.report.evaluator.EvaluatorRoot;\r
-import org.simantics.document.linking.report.evaluator.StringEditableNode;\r
-import org.simantics.document.linking.report.templates.custom.EvaluatorCustomizableContent;\r
-import org.simantics.ui.dnd.LocalObjectTransfer;\r
-\r
-\r
-/**\r
- * UI component for configuring evaluator trees.\r
- * \r
- * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
- *\r
- */\r
-public class EvaluatorConfigurationWidget extends Composite {\r
-       \r
-       \r
-       EvaluatorCustomizableContent input;\r
-       LocalResourceManager manager;\r
-       \r
-       EvaluatorRoot root;\r
-\r
-       TreeViewer viewer;\r
-\r
-       \r
-       public EvaluatorConfigurationWidget(Composite parent, LocalResourceManager manager, int style) {\r
-               super(parent, style);\r
-               this.manager = manager;\r
-               root = new EvaluatorRoot();\r
-               \r
-               setLayout(new GridLayout(1,false));\r
-               viewer = new TreeViewer(this);\r
-               \r
-               TreeViewerEditor.create(viewer, null, new DoubleClickEditorActivationStrategy(viewer), ColumnViewerEditor.DEFAULT);\r
-               viewer.setContentProvider(new EvaluatorNodeContentProvider());\r
-               \r
-               viewer.setLabelProvider(new EvaluatorLabelProvider());\r
-               viewer.setCellEditors(new CellEditor[]{new EvaluatorNodeCellEditor(viewer.getTree())});\r
-               viewer.setCellModifier(new EvaluatorNodeCellModifier());\r
-               viewer.setColumnProperties(new String[]{"value"});\r
-               viewer.setInput(root);\r
-               viewer.getTree().addMenuDetectListener(new MenuDetectListener() {\r
-                       \r
-                       @Override\r
-                       public void menuDetected(MenuDetectEvent e) {\r
-                               StructuredSelection sel = (StructuredSelection)viewer.getSelection();\r
-                               createPopupMenu(e, sel);\r
-                               \r
-                       }\r
-               });\r
-               int operations = DND.DROP_COPY| DND.DROP_MOVE;\r
-               viewer.addDragSupport(operations, new Transfer[]{LocalObjectTransfer.getTransfer()}, new DragSourceListener() {\r
-                       \r
-                       @Override\r
-                       public void dragStart(DragSourceEvent event) {\r
-                               ISelection sel = viewer.getSelection();\r
-                               \r
-                               event.doit = !sel.isEmpty();\r
-                                       \r
-                               \r
-                       }\r
-                       \r
-                       @Override\r
-                       public void dragSetData(DragSourceEvent event) {\r
-                               if (LocalObjectTransfer.getTransfer().isSupportedType(event.dataType)) {\r
-                                       event.data = viewer.getSelection();\r
-                               }\r
-                               \r
-                       }\r
-                       \r
-                       @Override\r
-                       public void dragFinished(DragSourceEvent event) {\r
-                               // TODO Auto-generated method stub\r
-                               \r
-                       }\r
-               });\r
-               \r
-               viewer.addDropSupport(operations, new Transfer[]{LocalObjectTransfer.getTransfer()}, new ViewerDropAdapter(viewer) {\r
-                       \r
-                       @Override\r
-                       public boolean validateDrop(Object target, int operation,\r
-                                       TransferData transferType) {\r
-                               if ((operation & DND.DROP_COPY) > 0) {\r
-                                       return true;\r
-                               } else if ((operation & DND.DROP_MOVE) > 0) {\r
-                                       return true;\r
-                               }  else {\r
-                                       return false;\r
-                               }\r
-                               \r
-                       }\r
-                       \r
-                       \r
-                       \r
-                       @Override\r
-                       public boolean performDrop(Object data) {\r
-                               EvaluatorItem item = (EvaluatorItem)determineTarget(getCurrentEvent());\r
-                               EvaluatorNode parent = item.getParent();\r
-                               EvaluatorItem toProcess = (EvaluatorItem)((TreeSelection)data).getFirstElement();\r
-                               if (toProcess == null)\r
-                                       return false;\r
-                               EvaluatorNode toProcessParent = toProcess.getParent();\r
-                               int index = parent.indexOf(item);\r
-                               boolean copy = false;\r
-                               if ((getCurrentOperation() & DND.DROP_COPY) > 0) {\r
-                                       copy = true;\r
-                                       toProcess = toProcess.copy();\r
-                               }\r
-                               switch (getCurrentLocation()) {\r
-                                       case LOCATION_BEFORE: {\r
-                                               if (!dropValid(parent, toProcessParent, toProcess, index, copy))\r
-                                                       return false;\r
-                                                       \r
-                                               if (!copy && toProcessParent != null) {\r
-                                                       toProcessParent.removeChild(toProcess);\r
-                                                       viewer.refresh(toProcessParent);\r
-                                               }\r
-                                               parent.addChild(index, toProcess);\r
-                                               viewer.refresh(parent);\r
-                                               return true;\r
-                                       }\r
-                                       case LOCATION_AFTER: {\r
-                                               if (!dropValid(parent, toProcessParent, toProcess, index, copy))\r
-                                                       return false;\r
-                                               \r
-                                               if (!copy && toProcessParent != null) {\r
-                                                       toProcessParent.removeChild(toProcess);\r
-                                                       viewer.refresh(toProcessParent);\r
-                                               }\r
-                                               parent.addChild(index+1, toProcess);\r
-                                               viewer.refresh(parent);\r
-                                               return true;\r
-                                       }\r
-                                       \r
-                                       case LOCATION_ON: {\r
-                                               if (item instanceof EvaluatorNode) {\r
-                                                       EvaluatorNode node = ((EvaluatorNode)item);\r
-                                                       if (!dropValid(node, toProcessParent, toProcess, index, copy))\r
-                                                               return false;\r
-                                                       \r
-                                                       if (!copy && toProcessParent != null) {\r
-                                                               toProcessParent.removeChild(toProcess);\r
-                                                               viewer.refresh(toProcessParent);\r
-                                                       }\r
-                                                       node.addChild(toProcess);\r
-                                                       viewer.refresh(item);\r
-                                                       if (!copy)\r
-                                                               \r
-                                                       return true;\r
-                                               } \r
-                                               return false;\r
-                                       }\r
-                               }\r
-                               return false;\r
-                       }\r
-               });\r
-               \r
-               GridDataFactory.fillDefaults().span(1, 1).grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(viewer.getTree());\r
-\r
-       }\r
-       \r
-       private boolean dropValid(EvaluatorNode parent, EvaluatorNode toProcessParent, EvaluatorItem toProcess, int index, boolean copy) {\r
-               if (parent.equals(toProcessParent)) {\r
-                       if (copy && !parent.acceptChild(index,toProcess))\r
-                               return false;\r
-               } else {\r
-                       if (!parent.acceptChild(index,toProcess))\r
-                               return false;\r
-               }\r
-               return true;\r
-       }\r
-       \r
-       public void setInput(EvaluatorCustomizableContent content) {\r
-               input = content;\r
-       }\r
-       \r
-       public void updateContent() {\r
-\r
-               if (input != null) {\r
-                       \r
-                       \r
-                       viewer.getTree().setEnabled(true);\r
-                       root.getChildren().clear();\r
-                       root.addChild(input.getItem());\r
-                       root.setSupportStyles(input.isSupportStyles());\r
-                       root.setSupportMultiline(input.isSupportMultiline());\r
-                       viewer.setInput(root);\r
-               } else {\r
-                       root.getChildren().clear();\r
-                       viewer.setInput(root);\r
-                       viewer.getTree().setEnabled(false);\r
-               }\r
-       }\r
-       \r
-       private Map<Class<? extends EvaluatorItem>, Image> imageMap = new HashMap<Class<? extends EvaluatorItem>, Image>();\r
-       \r
-       private Image getImage(Class<? extends EvaluatorItem> cls) {\r
-               Image image = imageMap.get(cls);\r
-               if (image == null) {\r
-                       try {\r
-                               EvaluatorItem tempItem = (EvaluatorItem)cls.newInstance();\r
-                               ImageDescriptor imageDescriptor = tempItem.getImage();\r
-                               if (imageDescriptor != null) {\r
-                                       image = manager.createImage(imageDescriptor);\r
-                                       imageMap.put(cls, image);\r
-                               }\r
-                       } catch (Exception e1) {\r
-                               imageMap.put(cls, null);\r
-                       }\r
-               }\r
-               return image;\r
-       }\r
-       \r
-       private void createPopupMenu(MenuDetectEvent event, StructuredSelection sel) {\r
-               EvaluatorItem i = null;\r
-               if (sel.isEmpty()) {\r
-                       i = root;\r
-               } else {\r
-                       i = (EvaluatorItem) sel.getFirstElement();\r
-               }\r
-               final EvaluatorItem item = i;\r
-               Menu menu = new Menu(viewer.getControl());\r
-               MenuItem add = new MenuItem(menu, SWT.CASCADE);\r
-               add.setText("Add");\r
-               Menu addMenu = new Menu(menu);\r
-               add.setMenu(addMenu);\r
-               add.setImage(manager.createImage(AbstractUIPlugin.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_right.png")));\r
-               \r
-               MenuItem insert = new MenuItem(menu, SWT.CASCADE);\r
-               insert.setText("Insert");\r
-               Menu insertMenu = new Menu(menu);\r
-               insert.setMenu(insertMenu);\r
-               insert.setImage(manager.createImage(AbstractUIPlugin.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_left.png")));\r
-               \r
-               // add menu\r
-               if (item instanceof EvaluatorNode) {\r
-                       final EvaluatorNode node = (EvaluatorNode)item;\r
-                       for (final Class<? extends EvaluatorItem> cls : node.getPossibleChildren(true)) {\r
-                               MenuItem menuItem = new MenuItem(addMenu, SWT.PUSH);\r
-                               menuItem.setText(cls.getSimpleName());\r
-                               menuItem.addSelectionListener(new SelectionAdapter() {\r
-                                       public void widgetSelected(SelectionEvent e) {\r
-                                               node.createChild(cls);\r
-                                               update(node);\r
-                                       };\r
-                               });\r
-                               \r
-                               \r
-                               menuItem.setImage(getImage(cls));\r
-                       }\r
-               }\r
-               if (addMenu.getItemCount() == 0)\r
-                       add.setEnabled(false);\r
-               if (item.getParent() != null) {\r
-                       final EvaluatorNode node = item.getParent();\r
-                       for (final Class<? extends EvaluatorItem> cls : node.getPossibleChildren(false)) {\r
-                               if (EvaluatorNode.class.isAssignableFrom(cls)) {\r
-                                       MenuItem menuItem = new MenuItem(insertMenu, SWT.PUSH);\r
-                                       menuItem.setText(cls.getSimpleName());\r
-                                       menuItem.addSelectionListener(new SelectionAdapter() {\r
-                                               public void widgetSelected(SelectionEvent e) {\r
-                                                       int index = node.indexOf(item);\r
-                                                       node.removeChild(item);\r
-                                                       EvaluatorNode inserted = (EvaluatorNode)node.createChild(index,cls);\r
-                                                       inserted.addChild(item);\r
-                                                       update(node);\r
-                                               };\r
-                                       });\r
-                                       \r
-                                       menuItem.setImage(getImage(cls));\r
-                               }\r
-                       }\r
-               }\r
-               if (insertMenu.getItemCount() == 0)\r
-                       insert.setEnabled(false);\r
-               \r
-               MenuItem menuItem = new MenuItem(menu, SWT.PUSH);\r
-               menuItem.setText("Remove");\r
-               menuItem.addSelectionListener(new SelectionAdapter() {\r
-                       public void widgetSelected(SelectionEvent e) {\r
-                               EvaluatorNode parent = item.getParent();\r
-                               if (parent != null) {\r
-                                       parent.removeChild(item);\r
-                                       update(parent);\r
-                               }\r
-                       };\r
-               });\r
-               menuItem.setEnabled(item != root);\r
-               menuItem.setImage(manager.createImage(AbstractUIPlugin.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/delete.png")));\r
-               menu.setLocation(event.x,event.y);\r
-               menu.setVisible(true);\r
-               \r
-               \r
-       }\r
-       \r
-       private void update(EvaluatorItem item) {\r
-               viewer.refresh(item);\r
-               if (item == root) {\r
-                       if (root.getChildren().size() > 0) {\r
-                               input.setItem(root.getChildren().get(0));\r
-                       } else {\r
-                               //input.setItem(null);\r
-                       }\r
-               }\r
-       }\r
-       \r
-       private class EvaluatorLabelProvider extends LabelProvider {\r
-               \r
-               @Override\r
-               public Image getImage(Object element) {\r
-                       EvaluatorItem item = (EvaluatorItem)element;\r
-                       ImageDescriptor descriptor = item.getImage();\r
-                       if (descriptor == null)\r
-                               return null;\r
-                       \r
-                       return manager.createImage(descriptor);\r
-               }\r
-               \r
-       }\r
-       \r
-       private class EvaluatorNodeContentProvider implements ITreeContentProvider {\r
-               \r
-               @Override\r
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public void dispose() {\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public boolean hasChildren(Object element) {\r
-                       if (element instanceof EvaluatorNode) {\r
-                               return true;\r
-                       }\r
-                       return false;\r
-               }\r
-               \r
-               @Override\r
-               public Object getParent(Object element) {\r
-                       if (element instanceof EvaluatorItem) {\r
-                               return ((EvaluatorItem)element).getParent();\r
-                       }\r
-                       return null;\r
-               }\r
-               \r
-               @Override\r
-               public Object[] getElements(Object inputElement) {\r
-                       if (inputElement instanceof EvaluatorNode) {\r
-                               EvaluatorNode node = (EvaluatorNode)inputElement;\r
-                               return node.getChildren().toArray();\r
-                       }\r
-                       return new Object[0];\r
-               }\r
-               \r
-               @Override\r
-               public Object[] getChildren(Object parentElement) {\r
-                       if (parentElement instanceof EvaluatorNode) {\r
-                               EvaluatorNode node = (EvaluatorNode)parentElement;\r
-                               return node.getChildren().toArray();\r
-                       }\r
-                       return new Object[0];\r
-               }\r
-       }\r
-       \r
-       private class EvaluatorNodeCellEditor extends CellEditor {\r
-\r
-               TextCellEditor textEditor;\r
-               ComboBoxCellEditor2 enumEditor;\r
-               \r
-               CellEditor current;\r
-               \r
-               public EvaluatorNodeCellEditor(Composite parent) {\r
-                       super(parent);\r
-                       \r
-               }\r
-               \r
-               Object getSelected() {\r
-                       StructuredSelection sel = (StructuredSelection)viewer.getSelection();\r
-                       return sel.getFirstElement();\r
-               }\r
-               \r
-               @Override\r
-               protected Control createControl(Composite parent) {\r
-                       textEditor = new TextCellEditor(parent);\r
-                       enumEditor = new ComboBoxCellEditor2(parent, new String[0]);\r
-                       current = textEditor;\r
-                       return null;\r
-               }\r
-               \r
-               @Override\r
-               protected Object doGetValue() {\r
-                       return current.getValue();\r
-               }\r
-               \r
-               @Override\r
-               protected void doSetValue(Object value) {\r
-                       Object selected = getSelected();\r
-                       if (selected instanceof StringEditableNode) {\r
-                               if (current != textEditor)\r
-                                       current = textEditor;\r
-                               \r
-                       } else if (selected instanceof EnumEditableNode) {\r
-                               if (current != enumEditor)\r
-                                       current = enumEditor;\r
-                               enumEditor.setItems(((EnumEditableNode)selected).getEnumearation());\r
-                       }\r
-                       current.setValue(value);\r
-               }\r
-               \r
-               @Override\r
-               protected void doSetFocus() {\r
-                       current.setFocus();\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public void activate(ColumnViewerEditorActivationEvent activationEvent) {\r
-                       // TODO Auto-generated method stub\r
-                       current.activate(activationEvent);\r
-               }\r
-               \r
-               @Override\r
-               public void activate() {\r
-                       current.activate();\r
-               }\r
-               \r
-               @Override\r
-               public void deactivate() {\r
-                       current.deactivate();\r
-               }\r
-               \r
-               @Override\r
-               public Control getControl() {\r
-                       return current.getControl();\r
-               }\r
-               \r
-       }\r
-       \r
-       private class EvaluatorNodeCellModifier implements ICellModifier {\r
-               \r
-               \r
-               @Override\r
-               public boolean canModify(Object element, String property) {\r
-                       return (element instanceof StringEditableNode || element instanceof EnumEditableNode);\r
-               }\r
-               \r
-               @Override\r
-               public Object getValue(Object element, String property) {\r
-                       if (element instanceof StringEditableNode)\r
-                               return ((StringEditableNode)element).getValue();\r
-                       else if (element instanceof EnumEditableNode) {\r
-                               String values[] = ((EnumEditableNode)element).getEnumearation();\r
-                               String value = ((EnumEditableNode)element).getValue();\r
-                               for (int i = 0; i < values.length; i++) {\r
-                                       if (value.equals(values[i]))\r
-                                               return i;\r
-                               }\r
-                               return 0;\r
-                       }\r
-                       return "";\r
-               }\r
-               @Override\r
-               public void modify(Object element, String property, Object value) {\r
-                       StringEditableNode node = null;\r
-                       EnumEditableNode node2 = null;\r
-                       if (element instanceof TreeItem) {\r
-                               Object data = ((TreeItem)element).getData();\r
-                               if (data instanceof StringEditableNode)\r
-                                       node = (StringEditableNode)data;\r
-                               else if (data instanceof EnumEditableNode) {\r
-                                       node2 = (EnumEditableNode)data;\r
-                               }\r
-                       } else if (element instanceof StringEditableNode){\r
-                               node = (StringEditableNode)element;\r
-                       } else if (element instanceof EnumEditableNode) {\r
-                               node2 = (EnumEditableNode)element;\r
-                       }\r
-                       if (node != null) {\r
-                               node.setValue((String)value);\r
-                               update(node);\r
-                       } else if (node2 != null) {\r
-                               node2.setValue(node2.getEnumearation()[(Integer)value]);\r
-                               update(node2);\r
-                       }\r
-                       \r
-               }\r
-       }\r
-       \r
-       \r
-       private class DoubleClickEditorActivationStrategy extends ColumnViewerEditorActivationStrategy {\r
-\r
-               public DoubleClickEditorActivationStrategy(ColumnViewer viewer) {\r
-                       super(viewer);\r
-               }\r
-               \r
-               @Override\r
-               protected boolean isEditorActivationEvent(\r
-                               ColumnViewerEditorActivationEvent event) {\r
-                       boolean singleSelect = ((IStructuredSelection)viewer.getSelection()).size() == 1;\r
-                       boolean isLeftMouseSelect = event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION && ((MouseEvent)event.sourceEvent).button == 1;\r
-\r
-                       return singleSelect && (isLeftMouseSelect\r
-                                       || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC\r
-                                       || event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL);\r
-               }\r
-               \r
-       }\r
-       \r
-\r
-}\r
+package org.simantics.document.linking.wizard;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ColumnViewer;
+import org.eclipse.jface.viewers.ColumnViewerEditor;
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.TreeViewerEditor;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerDropAdapter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.events.MenuDetectEvent;
+import org.eclipse.swt.events.MenuDetectListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.simantics.browsing.ui.swt.ComboBoxCellEditor2;
+import org.simantics.document.linking.report.evaluator.EnumEditableNode;
+import org.simantics.document.linking.report.evaluator.EvaluatorItem;
+import org.simantics.document.linking.report.evaluator.EvaluatorNode;
+import org.simantics.document.linking.report.evaluator.EvaluatorRoot;
+import org.simantics.document.linking.report.evaluator.StringEditableNode;
+import org.simantics.document.linking.report.templates.custom.EvaluatorCustomizableContent;
+import org.simantics.ui.dnd.LocalObjectTransfer;
+
+
+/**
+ * UI component for configuring evaluator trees.
+ * 
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
+ *
+ */
+public class EvaluatorConfigurationWidget extends Composite {
+       
+       
+       EvaluatorCustomizableContent input;
+       LocalResourceManager manager;
+       
+       EvaluatorRoot root;
+
+       TreeViewer viewer;
+
+       
+       public EvaluatorConfigurationWidget(Composite parent, LocalResourceManager manager, int style) {
+               super(parent, style);
+               this.manager = manager;
+               root = new EvaluatorRoot();
+               
+               setLayout(new GridLayout(1,false));
+               viewer = new TreeViewer(this);
+               
+               TreeViewerEditor.create(viewer, null, new DoubleClickEditorActivationStrategy(viewer), ColumnViewerEditor.DEFAULT);
+               viewer.setContentProvider(new EvaluatorNodeContentProvider());
+               
+               viewer.setLabelProvider(new EvaluatorLabelProvider());
+               viewer.setCellEditors(new CellEditor[]{new EvaluatorNodeCellEditor(viewer.getTree())});
+               viewer.setCellModifier(new EvaluatorNodeCellModifier());
+               viewer.setColumnProperties(new String[]{"value"}); //$NON-NLS-1$
+               viewer.setInput(root);
+               viewer.getTree().addMenuDetectListener(new MenuDetectListener() {
+                       
+                       @Override
+                       public void menuDetected(MenuDetectEvent e) {
+                               StructuredSelection sel = (StructuredSelection)viewer.getSelection();
+                               createPopupMenu(e, sel);
+                               
+                       }
+               });
+               int operations = DND.DROP_COPY| DND.DROP_MOVE;
+               viewer.addDragSupport(operations, new Transfer[]{LocalObjectTransfer.getTransfer()}, new DragSourceListener() {
+                       
+                       @Override
+                       public void dragStart(DragSourceEvent event) {
+                               ISelection sel = viewer.getSelection();
+                               
+                               event.doit = !sel.isEmpty();
+                                       
+                               
+                       }
+                       
+                       @Override
+                       public void dragSetData(DragSourceEvent event) {
+                               if (LocalObjectTransfer.getTransfer().isSupportedType(event.dataType)) {
+                                       event.data = viewer.getSelection();
+                               }
+                               
+                       }
+                       
+                       @Override
+                       public void dragFinished(DragSourceEvent event) {
+                               // TODO Auto-generated method stub
+                               
+                       }
+               });
+               
+               viewer.addDropSupport(operations, new Transfer[]{LocalObjectTransfer.getTransfer()}, new ViewerDropAdapter(viewer) {
+                       
+                       @Override
+                       public boolean validateDrop(Object target, int operation,
+                                       TransferData transferType) {
+                               if ((operation & DND.DROP_COPY) > 0) {
+                                       return true;
+                               } else if ((operation & DND.DROP_MOVE) > 0) {
+                                       return true;
+                               }  else {
+                                       return false;
+                               }
+                               
+                       }
+                       
+                       
+                       
+                       @Override
+                       public boolean performDrop(Object data) {
+                               EvaluatorItem item = (EvaluatorItem)determineTarget(getCurrentEvent());
+                               EvaluatorNode parent = item.getParent();
+                               EvaluatorItem toProcess = (EvaluatorItem)((TreeSelection)data).getFirstElement();
+                               if (toProcess == null)
+                                       return false;
+                               EvaluatorNode toProcessParent = toProcess.getParent();
+                               int index = parent.indexOf(item);
+                               boolean copy = false;
+                               if ((getCurrentOperation() & DND.DROP_COPY) > 0) {
+                                       copy = true;
+                                       toProcess = toProcess.copy();
+                               }
+                               switch (getCurrentLocation()) {
+                                       case LOCATION_BEFORE: {
+                                               if (!dropValid(parent, toProcessParent, toProcess, index, copy))
+                                                       return false;
+                                                       
+                                               if (!copy && toProcessParent != null) {
+                                                       toProcessParent.removeChild(toProcess);
+                                                       viewer.refresh(toProcessParent);
+                                               }
+                                               parent.addChild(index, toProcess);
+                                               viewer.refresh(parent);
+                                               return true;
+                                       }
+                                       case LOCATION_AFTER: {
+                                               if (!dropValid(parent, toProcessParent, toProcess, index, copy))
+                                                       return false;
+                                               
+                                               if (!copy && toProcessParent != null) {
+                                                       toProcessParent.removeChild(toProcess);
+                                                       viewer.refresh(toProcessParent);
+                                               }
+                                               parent.addChild(index+1, toProcess);
+                                               viewer.refresh(parent);
+                                               return true;
+                                       }
+                                       
+                                       case LOCATION_ON: {
+                                               if (item instanceof EvaluatorNode) {
+                                                       EvaluatorNode node = ((EvaluatorNode)item);
+                                                       if (!dropValid(node, toProcessParent, toProcess, index, copy))
+                                                               return false;
+                                                       
+                                                       if (!copy && toProcessParent != null) {
+                                                               toProcessParent.removeChild(toProcess);
+                                                               viewer.refresh(toProcessParent);
+                                                       }
+                                                       node.addChild(toProcess);
+                                                       viewer.refresh(item);
+                                                       if (!copy)
+                                                               
+                                                       return true;
+                                               } 
+                                               return false;
+                                       }
+                               }
+                               return false;
+                       }
+               });
+               
+               GridDataFactory.fillDefaults().span(1, 1).grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(viewer.getTree());
+
+       }
+       
+       private boolean dropValid(EvaluatorNode parent, EvaluatorNode toProcessParent, EvaluatorItem toProcess, int index, boolean copy) {
+               if (parent.equals(toProcessParent)) {
+                       if (copy && !parent.acceptChild(index,toProcess))
+                               return false;
+               } else {
+                       if (!parent.acceptChild(index,toProcess))
+                               return false;
+               }
+               return true;
+       }
+       
+       public void setInput(EvaluatorCustomizableContent content) {
+               input = content;
+       }
+       
+       public void updateContent() {
+
+               if (input != null) {
+                       
+                       
+                       viewer.getTree().setEnabled(true);
+                       root.getChildren().clear();
+                       root.addChild(input.getItem());
+                       root.setSupportStyles(input.isSupportStyles());
+                       root.setSupportMultiline(input.isSupportMultiline());
+                       viewer.setInput(root);
+               } else {
+                       root.getChildren().clear();
+                       viewer.setInput(root);
+                       viewer.getTree().setEnabled(false);
+               }
+       }
+       
+       private Map<Class<? extends EvaluatorItem>, Image> imageMap = new HashMap<Class<? extends EvaluatorItem>, Image>();
+       
+       private Image getImage(Class<? extends EvaluatorItem> cls) {
+               Image image = imageMap.get(cls);
+               if (image == null) {
+                       try {
+                               EvaluatorItem tempItem = (EvaluatorItem)cls.newInstance();
+                               ImageDescriptor imageDescriptor = tempItem.getImage();
+                               if (imageDescriptor != null) {
+                                       image = manager.createImage(imageDescriptor);
+                                       imageMap.put(cls, image);
+                               }
+                       } catch (Exception e1) {
+                               imageMap.put(cls, null);
+                       }
+               }
+               return image;
+       }
+       
+       private void createPopupMenu(MenuDetectEvent event, StructuredSelection sel) {
+               EvaluatorItem i = null;
+               if (sel.isEmpty()) {
+                       i = root;
+               } else {
+                       i = (EvaluatorItem) sel.getFirstElement();
+               }
+               final EvaluatorItem item = i;
+               Menu menu = new Menu(viewer.getControl());
+               MenuItem add = new MenuItem(menu, SWT.CASCADE);
+               add.setText(Messages.EvaluatorConfigurationWidget_Add);
+               Menu addMenu = new Menu(menu);
+               add.setMenu(addMenu);
+               add.setImage(manager.createImage(AbstractUIPlugin.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_right.png"))); //$NON-NLS-1$ //$NON-NLS-2$
+               
+               MenuItem insert = new MenuItem(menu, SWT.CASCADE);
+               insert.setText("Insert"); //$NON-NLS-1$
+               Menu insertMenu = new Menu(menu);
+               insert.setMenu(insertMenu);
+               insert.setImage(manager.createImage(AbstractUIPlugin.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_left.png"))); //$NON-NLS-1$ //$NON-NLS-2$
+               
+               // add menu
+               if (item instanceof EvaluatorNode) {
+                       final EvaluatorNode node = (EvaluatorNode)item;
+                       for (final Class<? extends EvaluatorItem> cls : node.getPossibleChildren(true)) {
+                               MenuItem menuItem = new MenuItem(addMenu, SWT.PUSH);
+                               menuItem.setText(cls.getSimpleName());
+                               menuItem.addSelectionListener(new SelectionAdapter() {
+                                       public void widgetSelected(SelectionEvent e) {
+                                               node.createChild(cls);
+                                               update(node);
+                                       };
+                               });
+                               
+                               
+                               menuItem.setImage(getImage(cls));
+                       }
+               }
+               if (addMenu.getItemCount() == 0)
+                       add.setEnabled(false);
+               if (item.getParent() != null) {
+                       final EvaluatorNode node = item.getParent();
+                       for (final Class<? extends EvaluatorItem> cls : node.getPossibleChildren(false)) {
+                               if (EvaluatorNode.class.isAssignableFrom(cls)) {
+                                       MenuItem menuItem = new MenuItem(insertMenu, SWT.PUSH);
+                                       menuItem.setText(cls.getSimpleName());
+                                       menuItem.addSelectionListener(new SelectionAdapter() {
+                                               public void widgetSelected(SelectionEvent e) {
+                                                       int index = node.indexOf(item);
+                                                       node.removeChild(item);
+                                                       EvaluatorNode inserted = (EvaluatorNode)node.createChild(index,cls);
+                                                       inserted.addChild(item);
+                                                       update(node);
+                                               };
+                                       });
+                                       
+                                       menuItem.setImage(getImage(cls));
+                               }
+                       }
+               }
+               if (insertMenu.getItemCount() == 0)
+                       insert.setEnabled(false);
+               
+               MenuItem menuItem = new MenuItem(menu, SWT.PUSH);
+               menuItem.setText(Messages.EvaluatorConfigurationWidget_Remove);
+               menuItem.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent e) {
+                               EvaluatorNode parent = item.getParent();
+                               if (parent != null) {
+                                       parent.removeChild(item);
+                                       update(parent);
+                               }
+                       };
+               });
+               menuItem.setEnabled(item != root);
+               menuItem.setImage(manager.createImage(AbstractUIPlugin.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/delete.png"))); //$NON-NLS-1$ //$NON-NLS-2$
+               menu.setLocation(event.x,event.y);
+               menu.setVisible(true);
+               
+               
+       }
+       
+       private void update(EvaluatorItem item) {
+               viewer.refresh(item);
+               if (item == root) {
+                       if (root.getChildren().size() > 0) {
+                               input.setItem(root.getChildren().get(0));
+                       } else {
+                               //input.setItem(null);
+                       }
+               }
+       }
+       
+       private class EvaluatorLabelProvider extends LabelProvider {
+               
+               @Override
+               public Image getImage(Object element) {
+                       EvaluatorItem item = (EvaluatorItem)element;
+                       ImageDescriptor descriptor = item.getImage();
+                       if (descriptor == null)
+                               return null;
+                       
+                       return manager.createImage(descriptor);
+               }
+               
+       }
+       
+       private class EvaluatorNodeContentProvider implements ITreeContentProvider {
+               
+               @Override
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+                       
+               }
+               
+               @Override
+               public void dispose() {
+                       
+               }
+               
+               @Override
+               public boolean hasChildren(Object element) {
+                       if (element instanceof EvaluatorNode) {
+                               return true;
+                       }
+                       return false;
+               }
+               
+               @Override
+               public Object getParent(Object element) {
+                       if (element instanceof EvaluatorItem) {
+                               return ((EvaluatorItem)element).getParent();
+                       }
+                       return null;
+               }
+               
+               @Override
+               public Object[] getElements(Object inputElement) {
+                       if (inputElement instanceof EvaluatorNode) {
+                               EvaluatorNode node = (EvaluatorNode)inputElement;
+                               return node.getChildren().toArray();
+                       }
+                       return new Object[0];
+               }
+               
+               @Override
+               public Object[] getChildren(Object parentElement) {
+                       if (parentElement instanceof EvaluatorNode) {
+                               EvaluatorNode node = (EvaluatorNode)parentElement;
+                               return node.getChildren().toArray();
+                       }
+                       return new Object[0];
+               }
+       }
+       
+       private class EvaluatorNodeCellEditor extends CellEditor {
+
+               TextCellEditor textEditor;
+               ComboBoxCellEditor2 enumEditor;
+               
+               CellEditor current;
+               
+               public EvaluatorNodeCellEditor(Composite parent) {
+                       super(parent);
+                       
+               }
+               
+               Object getSelected() {
+                       StructuredSelection sel = (StructuredSelection)viewer.getSelection();
+                       return sel.getFirstElement();
+               }
+               
+               @Override
+               protected Control createControl(Composite parent) {
+                       textEditor = new TextCellEditor(parent);
+                       enumEditor = new ComboBoxCellEditor2(parent, new String[0]);
+                       current = textEditor;
+                       return null;
+               }
+               
+               @Override
+               protected Object doGetValue() {
+                       return current.getValue();
+               }
+               
+               @Override
+               protected void doSetValue(Object value) {
+                       Object selected = getSelected();
+                       if (selected instanceof StringEditableNode) {
+                               if (current != textEditor)
+                                       current = textEditor;
+                               
+                       } else if (selected instanceof EnumEditableNode) {
+                               if (current != enumEditor)
+                                       current = enumEditor;
+                               enumEditor.setItems(((EnumEditableNode)selected).getEnumearation());
+                       }
+                       current.setValue(value);
+               }
+               
+               @Override
+               protected void doSetFocus() {
+                       current.setFocus();
+                       
+               }
+               
+               @Override
+               public void activate(ColumnViewerEditorActivationEvent activationEvent) {
+                       // TODO Auto-generated method stub
+                       current.activate(activationEvent);
+               }
+               
+               @Override
+               public void activate() {
+                       current.activate();
+               }
+               
+               @Override
+               public void deactivate() {
+                       current.deactivate();
+               }
+               
+               @Override
+               public Control getControl() {
+                       return current.getControl();
+               }
+               
+       }
+       
+       private class EvaluatorNodeCellModifier implements ICellModifier {
+               
+               
+               @Override
+               public boolean canModify(Object element, String property) {
+                       return (element instanceof StringEditableNode || element instanceof EnumEditableNode);
+               }
+               
+               @Override
+               public Object getValue(Object element, String property) {
+                       if (element instanceof StringEditableNode)
+                               return ((StringEditableNode)element).getValue();
+                       else if (element instanceof EnumEditableNode) {
+                               String values[] = ((EnumEditableNode)element).getEnumearation();
+                               String value = ((EnumEditableNode)element).getValue();
+                               for (int i = 0; i < values.length; i++) {
+                                       if (value.equals(values[i]))
+                                               return i;
+                               }
+                               return 0;
+                       }
+                       return ""; //$NON-NLS-1$
+               }
+               @Override
+               public void modify(Object element, String property, Object value) {
+                       StringEditableNode node = null;
+                       EnumEditableNode node2 = null;
+                       if (element instanceof TreeItem) {
+                               Object data = ((TreeItem)element).getData();
+                               if (data instanceof StringEditableNode)
+                                       node = (StringEditableNode)data;
+                               else if (data instanceof EnumEditableNode) {
+                                       node2 = (EnumEditableNode)data;
+                               }
+                       } else if (element instanceof StringEditableNode){
+                               node = (StringEditableNode)element;
+                       } else if (element instanceof EnumEditableNode) {
+                               node2 = (EnumEditableNode)element;
+                       }
+                       if (node != null) {
+                               node.setValue((String)value);
+                               update(node);
+                       } else if (node2 != null) {
+                               node2.setValue(node2.getEnumearation()[(Integer)value]);
+                               update(node2);
+                       }
+                       
+               }
+       }
+       
+       
+       private class DoubleClickEditorActivationStrategy extends ColumnViewerEditorActivationStrategy {
+
+               public DoubleClickEditorActivationStrategy(ColumnViewer viewer) {
+                       super(viewer);
+               }
+               
+               @Override
+               protected boolean isEditorActivationEvent(
+                               ColumnViewerEditorActivationEvent event) {
+                       boolean singleSelect = ((IStructuredSelection)viewer.getSelection()).size() == 1;
+                       boolean isLeftMouseSelect = event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION && ((MouseEvent)event.sourceEvent).button == 1;
+
+                       return singleSelect && (isLeftMouseSelect
+                                       || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC
+                                       || event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL);
+               }
+               
+       }
+       
+
+}