--- /dev/null
+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