]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.document.linking.ui/src/org/simantics/document/linking/wizard/EvaluatorConfigurationWidget.java
Sync git svn branch with SVN repository r33144.
[simantics/platform.git] / bundles / org.simantics.document.linking.ui / src / org / simantics / document / linking / wizard / EvaluatorConfigurationWidget.java
1 package org.simantics.document.linking.wizard;\r
2 \r
3 import java.util.HashMap;\r
4 import java.util.Map;\r
5 \r
6 import org.eclipse.jface.layout.GridDataFactory;\r
7 import org.eclipse.jface.resource.ImageDescriptor;\r
8 import org.eclipse.jface.resource.LocalResourceManager;\r
9 import org.eclipse.jface.viewers.CellEditor;\r
10 import org.eclipse.jface.viewers.ColumnViewer;\r
11 import org.eclipse.jface.viewers.ColumnViewerEditor;\r
12 import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;\r
13 import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;\r
14 import org.eclipse.jface.viewers.ICellModifier;\r
15 import org.eclipse.jface.viewers.ISelection;\r
16 import org.eclipse.jface.viewers.IStructuredSelection;\r
17 import org.eclipse.jface.viewers.ITreeContentProvider;\r
18 import org.eclipse.jface.viewers.LabelProvider;\r
19 import org.eclipse.jface.viewers.StructuredSelection;\r
20 import org.eclipse.jface.viewers.TextCellEditor;\r
21 import org.eclipse.jface.viewers.TreeSelection;\r
22 import org.eclipse.jface.viewers.TreeViewer;\r
23 import org.eclipse.jface.viewers.TreeViewerEditor;\r
24 import org.eclipse.jface.viewers.Viewer;\r
25 import org.eclipse.jface.viewers.ViewerDropAdapter;\r
26 import org.eclipse.swt.SWT;\r
27 import org.eclipse.swt.dnd.DND;\r
28 import org.eclipse.swt.dnd.DragSourceEvent;\r
29 import org.eclipse.swt.dnd.DragSourceListener;\r
30 import org.eclipse.swt.dnd.Transfer;\r
31 import org.eclipse.swt.dnd.TransferData;\r
32 import org.eclipse.swt.events.MenuDetectEvent;\r
33 import org.eclipse.swt.events.MenuDetectListener;\r
34 import org.eclipse.swt.events.MouseEvent;\r
35 import org.eclipse.swt.events.SelectionAdapter;\r
36 import org.eclipse.swt.events.SelectionEvent;\r
37 import org.eclipse.swt.graphics.Image;\r
38 import org.eclipse.swt.layout.GridLayout;\r
39 import org.eclipse.swt.widgets.Composite;\r
40 import org.eclipse.swt.widgets.Control;\r
41 import org.eclipse.swt.widgets.Menu;\r
42 import org.eclipse.swt.widgets.MenuItem;\r
43 import org.eclipse.swt.widgets.TreeItem;\r
44 import org.eclipse.ui.plugin.AbstractUIPlugin;\r
45 import org.simantics.browsing.ui.swt.ComboBoxCellEditor2;\r
46 import org.simantics.document.linking.report.evaluator.EnumEditableNode;\r
47 import org.simantics.document.linking.report.evaluator.EvaluatorItem;\r
48 import org.simantics.document.linking.report.evaluator.EvaluatorNode;\r
49 import org.simantics.document.linking.report.evaluator.EvaluatorRoot;\r
50 import org.simantics.document.linking.report.evaluator.StringEditableNode;\r
51 import org.simantics.document.linking.report.templates.custom.EvaluatorCustomizableContent;\r
52 import org.simantics.ui.dnd.LocalObjectTransfer;\r
53 \r
54 \r
55 /**\r
56  * UI component for configuring evaluator trees.\r
57  * \r
58  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
59  *\r
60  */\r
61 public class EvaluatorConfigurationWidget extends Composite {\r
62         \r
63         \r
64         EvaluatorCustomizableContent input;\r
65         LocalResourceManager manager;\r
66         \r
67         EvaluatorRoot root;\r
68 \r
69         TreeViewer viewer;\r
70 \r
71         \r
72         public EvaluatorConfigurationWidget(Composite parent, LocalResourceManager manager, int style) {\r
73                 super(parent, style);\r
74                 this.manager = manager;\r
75                 root = new EvaluatorRoot();\r
76                 \r
77                 setLayout(new GridLayout(1,false));\r
78                 viewer = new TreeViewer(this);\r
79                 \r
80                 TreeViewerEditor.create(viewer, null, new DoubleClickEditorActivationStrategy(viewer), ColumnViewerEditor.DEFAULT);\r
81                 viewer.setContentProvider(new EvaluatorNodeContentProvider());\r
82                 \r
83                 viewer.setLabelProvider(new EvaluatorLabelProvider());\r
84                 viewer.setCellEditors(new CellEditor[]{new EvaluatorNodeCellEditor(viewer.getTree())});\r
85                 viewer.setCellModifier(new EvaluatorNodeCellModifier());\r
86                 viewer.setColumnProperties(new String[]{"value"});\r
87                 viewer.setInput(root);\r
88                 viewer.getTree().addMenuDetectListener(new MenuDetectListener() {\r
89                         \r
90                         @Override\r
91                         public void menuDetected(MenuDetectEvent e) {\r
92                                 StructuredSelection sel = (StructuredSelection)viewer.getSelection();\r
93                                 createPopupMenu(e, sel);\r
94                                 \r
95                         }\r
96                 });\r
97                 int operations = DND.DROP_COPY| DND.DROP_MOVE;\r
98                 viewer.addDragSupport(operations, new Transfer[]{LocalObjectTransfer.getTransfer()}, new DragSourceListener() {\r
99                         \r
100                         @Override\r
101                         public void dragStart(DragSourceEvent event) {\r
102                                 ISelection sel = viewer.getSelection();\r
103                                 \r
104                                 event.doit = !sel.isEmpty();\r
105                                         \r
106                                 \r
107                         }\r
108                         \r
109                         @Override\r
110                         public void dragSetData(DragSourceEvent event) {\r
111                                 if (LocalObjectTransfer.getTransfer().isSupportedType(event.dataType)) {\r
112                                         event.data = viewer.getSelection();\r
113                                 }\r
114                                 \r
115                         }\r
116                         \r
117                         @Override\r
118                         public void dragFinished(DragSourceEvent event) {\r
119                                 // TODO Auto-generated method stub\r
120                                 \r
121                         }\r
122                 });\r
123                 \r
124                 viewer.addDropSupport(operations, new Transfer[]{LocalObjectTransfer.getTransfer()}, new ViewerDropAdapter(viewer) {\r
125                         \r
126                         @Override\r
127                         public boolean validateDrop(Object target, int operation,\r
128                                         TransferData transferType) {\r
129                                 if ((operation & DND.DROP_COPY) > 0) {\r
130                                         return true;\r
131                                 } else if ((operation & DND.DROP_MOVE) > 0) {\r
132                                         return true;\r
133                                 }  else {\r
134                                         return false;\r
135                                 }\r
136                                 \r
137                         }\r
138                         \r
139                         \r
140                         \r
141                         @Override\r
142                         public boolean performDrop(Object data) {\r
143                                 EvaluatorItem item = (EvaluatorItem)determineTarget(getCurrentEvent());\r
144                                 EvaluatorNode parent = item.getParent();\r
145                                 EvaluatorItem toProcess = (EvaluatorItem)((TreeSelection)data).getFirstElement();\r
146                                 if (toProcess == null)\r
147                                         return false;\r
148                                 EvaluatorNode toProcessParent = toProcess.getParent();\r
149                                 int index = parent.indexOf(item);\r
150                                 boolean copy = false;\r
151                                 if ((getCurrentOperation() & DND.DROP_COPY) > 0) {\r
152                                         copy = true;\r
153                                         toProcess = toProcess.copy();\r
154                                 }\r
155                                 switch (getCurrentLocation()) {\r
156                                         case LOCATION_BEFORE: {\r
157                                                 if (!dropValid(parent, toProcessParent, toProcess, index, copy))\r
158                                                         return false;\r
159                                                         \r
160                                                 if (!copy && toProcessParent != null) {\r
161                                                         toProcessParent.removeChild(toProcess);\r
162                                                         viewer.refresh(toProcessParent);\r
163                                                 }\r
164                                                 parent.addChild(index, toProcess);\r
165                                                 viewer.refresh(parent);\r
166                                                 return true;\r
167                                         }\r
168                                         case LOCATION_AFTER: {\r
169                                                 if (!dropValid(parent, toProcessParent, toProcess, index, copy))\r
170                                                         return false;\r
171                                                 \r
172                                                 if (!copy && toProcessParent != null) {\r
173                                                         toProcessParent.removeChild(toProcess);\r
174                                                         viewer.refresh(toProcessParent);\r
175                                                 }\r
176                                                 parent.addChild(index+1, toProcess);\r
177                                                 viewer.refresh(parent);\r
178                                                 return true;\r
179                                         }\r
180                                         \r
181                                         case LOCATION_ON: {\r
182                                                 if (item instanceof EvaluatorNode) {\r
183                                                         EvaluatorNode node = ((EvaluatorNode)item);\r
184                                                         if (!dropValid(node, toProcessParent, toProcess, index, copy))\r
185                                                                 return false;\r
186                                                         \r
187                                                         if (!copy && toProcessParent != null) {\r
188                                                                 toProcessParent.removeChild(toProcess);\r
189                                                                 viewer.refresh(toProcessParent);\r
190                                                         }\r
191                                                         node.addChild(toProcess);\r
192                                                         viewer.refresh(item);\r
193                                                         if (!copy)\r
194                                                                 \r
195                                                         return true;\r
196                                                 } \r
197                                                 return false;\r
198                                         }\r
199                                 }\r
200                                 return false;\r
201                         }\r
202                 });\r
203                 \r
204                 GridDataFactory.fillDefaults().span(1, 1).grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(viewer.getTree());\r
205 \r
206         }\r
207         \r
208         private boolean dropValid(EvaluatorNode parent, EvaluatorNode toProcessParent, EvaluatorItem toProcess, int index, boolean copy) {\r
209                 if (parent.equals(toProcessParent)) {\r
210                         if (copy && !parent.acceptChild(index,toProcess))\r
211                                 return false;\r
212                 } else {\r
213                         if (!parent.acceptChild(index,toProcess))\r
214                                 return false;\r
215                 }\r
216                 return true;\r
217         }\r
218         \r
219         public void setInput(EvaluatorCustomizableContent content) {\r
220                 input = content;\r
221         }\r
222         \r
223         public void updateContent() {\r
224 \r
225                 if (input != null) {\r
226                         \r
227                         \r
228                         viewer.getTree().setEnabled(true);\r
229                         root.getChildren().clear();\r
230                         root.addChild(input.getItem());\r
231                         root.setSupportStyles(input.isSupportStyles());\r
232                         root.setSupportMultiline(input.isSupportMultiline());\r
233                         viewer.setInput(root);\r
234                 } else {\r
235                         root.getChildren().clear();\r
236                         viewer.setInput(root);\r
237                         viewer.getTree().setEnabled(false);\r
238                 }\r
239         }\r
240         \r
241         private Map<Class<? extends EvaluatorItem>, Image> imageMap = new HashMap<Class<? extends EvaluatorItem>, Image>();\r
242         \r
243         private Image getImage(Class<? extends EvaluatorItem> cls) {\r
244                 Image image = imageMap.get(cls);\r
245                 if (image == null) {\r
246                         try {\r
247                                 EvaluatorItem tempItem = (EvaluatorItem)cls.newInstance();\r
248                                 ImageDescriptor imageDescriptor = tempItem.getImage();\r
249                                 if (imageDescriptor != null) {\r
250                                         image = manager.createImage(imageDescriptor);\r
251                                         imageMap.put(cls, image);\r
252                                 }\r
253                         } catch (Exception e1) {\r
254                                 imageMap.put(cls, null);\r
255                         }\r
256                 }\r
257                 return image;\r
258         }\r
259         \r
260         private void createPopupMenu(MenuDetectEvent event, StructuredSelection sel) {\r
261                 EvaluatorItem i = null;\r
262                 if (sel.isEmpty()) {\r
263                         i = root;\r
264                 } else {\r
265                         i = (EvaluatorItem) sel.getFirstElement();\r
266                 }\r
267                 final EvaluatorItem item = i;\r
268                 Menu menu = new Menu(viewer.getControl());\r
269                 MenuItem add = new MenuItem(menu, SWT.CASCADE);\r
270                 add.setText("Add");\r
271                 Menu addMenu = new Menu(menu);\r
272                 add.setMenu(addMenu);\r
273                 add.setImage(manager.createImage(AbstractUIPlugin.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_right.png")));\r
274                 \r
275                 MenuItem insert = new MenuItem(menu, SWT.CASCADE);\r
276                 insert.setText("Insert");\r
277                 Menu insertMenu = new Menu(menu);\r
278                 insert.setMenu(insertMenu);\r
279                 insert.setImage(manager.createImage(AbstractUIPlugin.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_left.png")));\r
280                 \r
281                 // add menu\r
282                 if (item instanceof EvaluatorNode) {\r
283                         final EvaluatorNode node = (EvaluatorNode)item;\r
284                         for (final Class<? extends EvaluatorItem> cls : node.getPossibleChildren(true)) {\r
285                                 MenuItem menuItem = new MenuItem(addMenu, SWT.PUSH);\r
286                                 menuItem.setText(cls.getSimpleName());\r
287                                 menuItem.addSelectionListener(new SelectionAdapter() {\r
288                                         public void widgetSelected(SelectionEvent e) {\r
289                                                 node.createChild(cls);\r
290                                                 update(node);\r
291                                         };\r
292                                 });\r
293                                 \r
294                                 \r
295                                 menuItem.setImage(getImage(cls));\r
296                         }\r
297                 }\r
298                 if (addMenu.getItemCount() == 0)\r
299                         add.setEnabled(false);\r
300                 if (item.getParent() != null) {\r
301                         final EvaluatorNode node = item.getParent();\r
302                         for (final Class<? extends EvaluatorItem> cls : node.getPossibleChildren(false)) {\r
303                                 if (EvaluatorNode.class.isAssignableFrom(cls)) {\r
304                                         MenuItem menuItem = new MenuItem(insertMenu, SWT.PUSH);\r
305                                         menuItem.setText(cls.getSimpleName());\r
306                                         menuItem.addSelectionListener(new SelectionAdapter() {\r
307                                                 public void widgetSelected(SelectionEvent e) {\r
308                                                         int index = node.indexOf(item);\r
309                                                         node.removeChild(item);\r
310                                                         EvaluatorNode inserted = (EvaluatorNode)node.createChild(index,cls);\r
311                                                         inserted.addChild(item);\r
312                                                         update(node);\r
313                                                 };\r
314                                         });\r
315                                         \r
316                                         menuItem.setImage(getImage(cls));\r
317                                 }\r
318                         }\r
319                 }\r
320                 if (insertMenu.getItemCount() == 0)\r
321                         insert.setEnabled(false);\r
322                 \r
323                 MenuItem menuItem = new MenuItem(menu, SWT.PUSH);\r
324                 menuItem.setText("Remove");\r
325                 menuItem.addSelectionListener(new SelectionAdapter() {\r
326                         public void widgetSelected(SelectionEvent e) {\r
327                                 EvaluatorNode parent = item.getParent();\r
328                                 if (parent != null) {\r
329                                         parent.removeChild(item);\r
330                                         update(parent);\r
331                                 }\r
332                         };\r
333                 });\r
334                 menuItem.setEnabled(item != root);\r
335                 menuItem.setImage(manager.createImage(AbstractUIPlugin.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/delete.png")));\r
336                 menu.setLocation(event.x,event.y);\r
337                 menu.setVisible(true);\r
338                 \r
339                 \r
340         }\r
341         \r
342         private void update(EvaluatorItem item) {\r
343                 viewer.refresh(item);\r
344                 if (item == root) {\r
345                         if (root.getChildren().size() > 0) {\r
346                                 input.setItem(root.getChildren().get(0));\r
347                         } else {\r
348                                 //input.setItem(null);\r
349                         }\r
350                 }\r
351         }\r
352         \r
353         private class EvaluatorLabelProvider extends LabelProvider {\r
354                 \r
355                 @Override\r
356                 public Image getImage(Object element) {\r
357                         EvaluatorItem item = (EvaluatorItem)element;\r
358                         ImageDescriptor descriptor = item.getImage();\r
359                         if (descriptor == null)\r
360                                 return null;\r
361                         \r
362                         return manager.createImage(descriptor);\r
363                 }\r
364                 \r
365         }\r
366         \r
367         private class EvaluatorNodeContentProvider implements ITreeContentProvider {\r
368                 \r
369                 @Override\r
370                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
371                         \r
372                 }\r
373                 \r
374                 @Override\r
375                 public void dispose() {\r
376                         \r
377                 }\r
378                 \r
379                 @Override\r
380                 public boolean hasChildren(Object element) {\r
381                         if (element instanceof EvaluatorNode) {\r
382                                 return true;\r
383                         }\r
384                         return false;\r
385                 }\r
386                 \r
387                 @Override\r
388                 public Object getParent(Object element) {\r
389                         if (element instanceof EvaluatorItem) {\r
390                                 return ((EvaluatorItem)element).getParent();\r
391                         }\r
392                         return null;\r
393                 }\r
394                 \r
395                 @Override\r
396                 public Object[] getElements(Object inputElement) {\r
397                         if (inputElement instanceof EvaluatorNode) {\r
398                                 EvaluatorNode node = (EvaluatorNode)inputElement;\r
399                                 return node.getChildren().toArray();\r
400                         }\r
401                         return new Object[0];\r
402                 }\r
403                 \r
404                 @Override\r
405                 public Object[] getChildren(Object parentElement) {\r
406                         if (parentElement instanceof EvaluatorNode) {\r
407                                 EvaluatorNode node = (EvaluatorNode)parentElement;\r
408                                 return node.getChildren().toArray();\r
409                         }\r
410                         return new Object[0];\r
411                 }\r
412         }\r
413         \r
414         private class EvaluatorNodeCellEditor extends CellEditor {\r
415 \r
416                 TextCellEditor textEditor;\r
417                 ComboBoxCellEditor2 enumEditor;\r
418                 \r
419                 CellEditor current;\r
420                 \r
421                 public EvaluatorNodeCellEditor(Composite parent) {\r
422                         super(parent);\r
423                         \r
424                 }\r
425                 \r
426                 Object getSelected() {\r
427                         StructuredSelection sel = (StructuredSelection)viewer.getSelection();\r
428                         return sel.getFirstElement();\r
429                 }\r
430                 \r
431                 @Override\r
432                 protected Control createControl(Composite parent) {\r
433                         textEditor = new TextCellEditor(parent);\r
434                         enumEditor = new ComboBoxCellEditor2(parent, new String[0]);\r
435                         current = textEditor;\r
436                         return null;\r
437                 }\r
438                 \r
439                 @Override\r
440                 protected Object doGetValue() {\r
441                         return current.getValue();\r
442                 }\r
443                 \r
444                 @Override\r
445                 protected void doSetValue(Object value) {\r
446                         Object selected = getSelected();\r
447                         if (selected instanceof StringEditableNode) {\r
448                                 if (current != textEditor)\r
449                                         current = textEditor;\r
450                                 \r
451                         } else if (selected instanceof EnumEditableNode) {\r
452                                 if (current != enumEditor)\r
453                                         current = enumEditor;\r
454                                 enumEditor.setItems(((EnumEditableNode)selected).getEnumearation());\r
455                         }\r
456                         current.setValue(value);\r
457                 }\r
458                 \r
459                 @Override\r
460                 protected void doSetFocus() {\r
461                         current.setFocus();\r
462                         \r
463                 }\r
464                 \r
465                 @Override\r
466                 public void activate(ColumnViewerEditorActivationEvent activationEvent) {\r
467                         // TODO Auto-generated method stub\r
468                         current.activate(activationEvent);\r
469                 }\r
470                 \r
471                 @Override\r
472                 public void activate() {\r
473                         current.activate();\r
474                 }\r
475                 \r
476                 @Override\r
477                 public void deactivate() {\r
478                         current.deactivate();\r
479                 }\r
480                 \r
481                 @Override\r
482                 public Control getControl() {\r
483                         return current.getControl();\r
484                 }\r
485                 \r
486         }\r
487         \r
488         private class EvaluatorNodeCellModifier implements ICellModifier {\r
489                 \r
490                 \r
491                 @Override\r
492                 public boolean canModify(Object element, String property) {\r
493                         return (element instanceof StringEditableNode || element instanceof EnumEditableNode);\r
494                 }\r
495                 \r
496                 @Override\r
497                 public Object getValue(Object element, String property) {\r
498                         if (element instanceof StringEditableNode)\r
499                                 return ((StringEditableNode)element).getValue();\r
500                         else if (element instanceof EnumEditableNode) {\r
501                                 String values[] = ((EnumEditableNode)element).getEnumearation();\r
502                                 String value = ((EnumEditableNode)element).getValue();\r
503                                 for (int i = 0; i < values.length; i++) {\r
504                                         if (value.equals(values[i]))\r
505                                                 return i;\r
506                                 }\r
507                                 return 0;\r
508                         }\r
509                         return "";\r
510                 }\r
511                 @Override\r
512                 public void modify(Object element, String property, Object value) {\r
513                         StringEditableNode node = null;\r
514                         EnumEditableNode node2 = null;\r
515                         if (element instanceof TreeItem) {\r
516                                 Object data = ((TreeItem)element).getData();\r
517                                 if (data instanceof StringEditableNode)\r
518                                         node = (StringEditableNode)data;\r
519                                 else if (data instanceof EnumEditableNode) {\r
520                                         node2 = (EnumEditableNode)data;\r
521                                 }\r
522                         } else if (element instanceof StringEditableNode){\r
523                                 node = (StringEditableNode)element;\r
524                         } else if (element instanceof EnumEditableNode) {\r
525                                 node2 = (EnumEditableNode)element;\r
526                         }\r
527                         if (node != null) {\r
528                                 node.setValue((String)value);\r
529                                 update(node);\r
530                         } else if (node2 != null) {\r
531                                 node2.setValue(node2.getEnumearation()[(Integer)value]);\r
532                                 update(node2);\r
533                         }\r
534                         \r
535                 }\r
536         }\r
537         \r
538         \r
539         private class DoubleClickEditorActivationStrategy extends ColumnViewerEditorActivationStrategy {\r
540 \r
541                 public DoubleClickEditorActivationStrategy(ColumnViewer viewer) {\r
542                         super(viewer);\r
543                 }\r
544                 \r
545                 @Override\r
546                 protected boolean isEditorActivationEvent(\r
547                                 ColumnViewerEditorActivationEvent event) {\r
548                         boolean singleSelect = ((IStructuredSelection)viewer.getSelection()).size() == 1;\r
549                         boolean isLeftMouseSelect = event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION && ((MouseEvent)event.sourceEvent).button == 1;\r
550 \r
551                         return singleSelect && (isLeftMouseSelect\r
552                                         || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC\r
553                                         || event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL);\r
554                 }\r
555                 \r
556         }\r
557         \r
558 \r
559 }\r