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