]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.interop.update/src/org/simantics/interop/update/editor/ModelUpdateEditor.java
a3b60332ce9e1552bbe68f9e14bdb182f65a86d1
[simantics/interop.git] / org.simantics.interop.update / src / org / simantics / interop / update / editor / ModelUpdateEditor.java
1 package org.simantics.interop.update.editor;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Stack;
8
9 import org.eclipse.jface.resource.ImageDescriptor;
10 import org.eclipse.jface.resource.JFaceResources;
11 import org.eclipse.jface.resource.LocalResourceManager;
12 import org.eclipse.jface.viewers.CellEditor;
13 import org.eclipse.jface.viewers.CheckStateChangedEvent;
14 import org.eclipse.jface.viewers.CheckboxCellEditor;
15 import org.eclipse.jface.viewers.CheckboxTreeViewer;
16 import org.eclipse.jface.viewers.ColumnLabelProvider;
17 import org.eclipse.jface.viewers.ColumnViewer;
18 import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
19 import org.eclipse.jface.viewers.EditingSupport;
20 import org.eclipse.jface.viewers.ICheckStateListener;
21 import org.eclipse.jface.viewers.IStructuredContentProvider;
22 import org.eclipse.jface.viewers.ITreeContentProvider;
23 import org.eclipse.jface.viewers.ITreeViewerListener;
24 import org.eclipse.jface.viewers.TableViewer;
25 import org.eclipse.jface.viewers.TableViewerColumn;
26 import org.eclipse.jface.viewers.TreeExpansionEvent;
27 import org.eclipse.jface.viewers.TreeViewerColumn;
28 import org.eclipse.jface.viewers.Viewer;
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.events.SelectionAdapter;
31 import org.eclipse.swt.events.SelectionEvent;
32 import org.eclipse.swt.graphics.Color;
33 import org.eclipse.swt.graphics.Image;
34 import org.eclipse.swt.graphics.RGB;
35 import org.eclipse.swt.layout.FillLayout;
36 import org.eclipse.swt.layout.GridData;
37 import org.eclipse.swt.layout.GridLayout;
38 import org.eclipse.swt.widgets.Button;
39 import org.eclipse.swt.widgets.Composite;
40 import org.eclipse.swt.widgets.Display;
41 import org.eclipse.swt.widgets.Label;
42 import org.eclipse.swt.widgets.Text;
43 import org.eclipse.ui.IEditorInput;
44 import org.simantics.db.ReadGraph;
45 import org.simantics.db.Resource;
46 import org.simantics.db.Statement;
47 import org.simantics.db.WriteGraph;
48 import org.simantics.db.common.request.WriteRequest;
49 import org.simantics.db.exception.DatabaseException;
50 import org.simantics.db.exception.DoesNotContainValueException;
51 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
52 import org.simantics.db.exception.NoSingleResultException;
53 import org.simantics.db.exception.ServiceException;
54 import org.simantics.db.request.Read;
55 import org.simantics.interop.test.GraphChanges;
56 import org.simantics.interop.test.GraphComparator;
57 import org.simantics.interop.test.NameComparator;
58 import org.simantics.interop.update.Activator;
59 import org.simantics.interop.update.model.UpdateNode;
60 import org.simantics.interop.update.model.UpdateNode.Status;
61 import org.simantics.interop.update.model.UpdateTree;
62 import org.simantics.interop.utils.TableUtils;
63 import org.simantics.layer0.Layer0;
64 import org.simantics.ui.workbench.ResourceEditorPart2;
65 import org.simantics.utils.datastructures.BijectionMap;
66 import org.simantics.utils.datastructures.Callback;
67 import org.simantics.utils.datastructures.Pair;
68 import org.simantics.utils.ui.ExceptionUtils;
69
70
71 /**
72  * Editor for updating models.
73  * 
74  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
75  *
76  */
77 public abstract class ModelUpdateEditor extends ResourceEditorPart2 {
78
79         
80         private Composite composite;
81         private Composite errorComposite;
82         
83         private CheckboxTreeViewer changeBrowser;
84         private TableViewer changeViewer;
85         
86         private GraphChanges changes;
87         private UpdateTree updateTree;
88         
89         private Button updateAllButton;
90         private Button updateSelectedButton;
91         
92         private LocalResourceManager manager = new LocalResourceManager(JFaceResources.getResources());
93         
94         private Image checked;
95         private Image unchecked;
96         private Image warning;
97         
98         private Color containsColor;
99         private Color deletedColor;
100         private Color addedColor;
101         
102         private HashSet<Pair<Statement, Statement>> selected = new HashSet<Pair<Statement,Statement>>();
103         
104         private HashSet<UpdateNode> selectedStructure = new HashSet<UpdateNode>();
105         
106         private List<ChangeFilter> filters = new ArrayList<ChangeFilter>();
107         
108         public ModelUpdateEditor() {
109                 checked = manager.createImage(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/tick.png"));
110                 unchecked = manager.createImage(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/cross.png"));
111                 warning = manager.createImage(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/error.png"));
112         }
113         
114         @Override
115         public void createPartControl(Composite parent) {
116                 
117                 containsColor = new Color(parent.getDisplay(), new RGB(255,255,220));
118                 deletedColor = new Color(parent.getDisplay(), new RGB(255,220,220));
119                 addedColor = new Color(parent.getDisplay(), new RGB(220,255,220));
120                 
121                 composite = new Composite(parent, SWT.NONE);
122                 composite.setLayout(new GridLayout(1,false));
123                 
124                 errorComposite = new Composite(composite, SWT.BORDER);
125                 GridData data = new GridData();
126                 data.grabExcessHorizontalSpace = true;
127                 data.grabExcessVerticalSpace = false;
128                 data.horizontalAlignment = SWT.FILL;
129                 data.verticalAlignment = SWT.TOP;
130                 errorComposite.setLayoutData(data);
131                 errorComposite.setLayout(new GridLayout(2, false));
132                 
133                 errorComposite.setVisible(false);
134
135                 IEditorInput input = getEditorInput();
136                 if (!(input instanceof UpdateEditorInput)) {
137                         Label label = new Label(composite, SWT.NONE);
138                         label.setText("Unknown input.");
139                         return;
140                 }
141                 
142                 Composite fillComposite = new Composite(composite, SWT.NONE);
143                 data = new GridData();
144                 data.grabExcessHorizontalSpace = true;
145                 data.grabExcessVerticalSpace = true;
146                 data.horizontalAlignment = SWT.FILL;
147                 data.verticalAlignment = SWT.FILL;
148                 fillComposite.setLayoutData(data);
149                 fillComposite.setLayout(new FillLayout(SWT.VERTICAL));
150
151                 {
152                         changeBrowser = new CheckboxTreeViewer(fillComposite,SWT.MULTI|SWT.V_SCROLL|SWT.BORDER|SWT.FULL_SELECTION  );
153                         
154                         changeBrowser.setContentProvider(new UpdateTreeContentProvider());
155                         
156                         changeBrowser.getTree().setHeaderVisible(true);
157                         
158                         ColumnViewerToolTipSupport.enableFor(changeBrowser);
159
160                         
161                         TreeViewerColumn dataColumn = TableUtils.addColumn(changeBrowser, "Data", true, 600);
162
163                         dataColumn.setLabelProvider(new UpdateNodeLabelProvicer());
164                         
165                         changeBrowser.addCheckStateListener(new ICheckStateListener() {
166                                 
167                                 @Override
168                                 public void checkStateChanged(CheckStateChangedEvent event) {
169                                         UpdateNode node = (UpdateNode) event.getElement();
170                                         if (node.getOp() != null) {
171                                                 node.getOp().select(Boolean.TRUE.equals(event.getChecked()));
172                                                 
173                                         }
174                                         updateSelection();
175                                         
176                                 }
177                         });
178                         changeBrowser.addTreeListener(new ITreeViewerListener() {
179                                 
180                                 @Override
181                                 public void treeExpanded(TreeExpansionEvent event) {
182                                         event.getTreeViewer().getControl().getDisplay().asyncExec(new Runnable() {
183                                                 
184                                                 @Override
185                                                 public void run() {
186                                                         updateSelection();
187                                                 }
188                                         });
189                                         
190                                 }
191                                 
192                                 @Override
193                                 public void treeCollapsed(TreeExpansionEvent event) {
194                                         
195                                 }
196                         });
197                         changeBrowser.setUseHashlookup(true);
198                         
199                 }
200                 {
201                         changeViewer = new TableViewer(fillComposite,SWT.MULTI|SWT.V_SCROLL|SWT.BORDER|SWT.FULL_SELECTION);
202                         
203                         changeViewer.getTable().setHeaderVisible(true);
204                         changeViewer.getTable().setLinesVisible(true);
205                         
206                         changeViewer.setContentProvider(new ModificationListContentProvider());
207                         
208                         changeViewer.setUseHashlookup(true);
209                         
210                         TableViewerColumn selection = TableUtils.addColumn(changeViewer, getColumntTitle(0), false, false, 20);
211                         TableViewerColumn diagram = TableUtils.addColumn(changeViewer, getColumntTitle(1), true, true, 100);
212                         TableViewerColumn symbol = TableUtils.addColumn(changeViewer, getColumntTitle(2), true, true, 100);
213                         TableViewerColumn property = TableUtils.addColumn(changeViewer, getColumntTitle(3), true, true, 100);
214                         TableViewerColumn oldValue = TableUtils.addColumn(changeViewer, getColumntTitle(4), true, true, 100);
215                         TableViewerColumn newValue = TableUtils.addColumn(changeViewer, getColumntTitle(5), true, true, 100);
216                         
217                         diagram.setLabelProvider(getLabelProvider(1));
218                         symbol.setLabelProvider(getLabelProvider(2));
219                         property.setLabelProvider(getLabelProvider(3));
220                         oldValue.setLabelProvider(getLabelProvider(4));
221                         newValue.setLabelProvider(getLabelProvider(5));
222                         
223                         selection.setLabelProvider(new SelectionLabelProvider(selected));
224                         selection.getColumn().addSelectionListener(new SelectionAdapter() {
225                                 @Override
226                                 public void widgetSelected(SelectionEvent e) {
227                                         if (changes.getModifications().size() > 0) {
228                                                 if (selected.contains(changes.getModifications().get(0))) {
229                                                         for (Pair<Statement, Statement> nr : changes.getModifications())
230                                                                 selected.remove(nr);
231                                                 } else {
232                                                         for (Pair<Statement, Statement> nr : changes.getModifications())
233                                                                 selected.add(nr);
234                                                 }
235                                                 changeViewer.refresh();
236                                         }
237                                 }
238                         });
239                         selection.setEditingSupport(new SelectionEditingSupport(changeViewer, selected));
240                 
241                 }
242                 Composite buttonComposite = new Composite(composite, SWT.NONE);
243                 
244                 data = new GridData();
245                 data.grabExcessHorizontalSpace = true;
246                 data.grabExcessVerticalSpace = false;
247                 data.horizontalAlignment = SWT.FILL;
248                 data.verticalAlignment = SWT.BOTTOM;
249                 
250                 buttonComposite.setLayoutData(data);
251                 
252                 buttonComposite.setLayout(new GridLayout(3, false));
253                 
254                 Label label = new Label(buttonComposite, SWT.NONE);
255                 data = new GridData();
256                 data.grabExcessHorizontalSpace = true;
257                 data.grabExcessVerticalSpace = false;
258                 data.horizontalAlignment = SWT.FILL;
259                 data.verticalAlignment = SWT.CENTER;
260                 label.setLayoutData(data);
261                 
262                 updateAllButton = new Button(buttonComposite, SWT.PUSH);
263                 updateAllButton.setText("Update All");
264                 updateAllButton.addSelectionListener(new SelectionAdapter() {
265                         @Override
266                         public void widgetSelected(SelectionEvent e) {
267                                 updateAll();
268                         }
269                 });
270                 updateSelectedButton = new Button(buttonComposite, SWT.PUSH);
271                 updateSelectedButton.setText("Update Selected");
272                 updateSelectedButton.addSelectionListener(new SelectionAdapter() {
273                         @Override
274                         public void widgetSelected(SelectionEvent e) {
275                                 updateSelected();
276                         }
277                 });
278
279                 load();
280                 
281         }
282         
283         protected String getColumntTitle(int i) {
284                 switch (i) {
285                 case 0:
286                         return "!";
287                 case 1:
288                         return "Diagram";
289                 case 2:
290                         return "Symbol";
291                 case 3:
292                         return "Property";
293                 case 4:
294                         return "Old Value";
295                 case 5:
296                         return "New Value";
297                 default:
298                         throw new RuntimeException("Unknown column index" + i);
299                         
300                 }
301         }
302         
303         protected abstract ColumnLabelProvider getLabelProvider(int i);
304         protected abstract Pair<GraphComparator,Boolean> getChanges(Resource r1, Resource r2)  throws DatabaseException;
305         protected abstract UpdateTree getUpdateTree(GraphChanges changes) throws DatabaseException;
306         
307         protected void addFilters(List<ChangeFilter> filters) {
308                 
309         }
310         
311         public GraphChanges getChanges() {
312                 return changes;
313         }
314         
315         private void showWarning(String text) {
316                 errorComposite.setVisible(true);
317                 
318                 Label label = new Label(errorComposite, SWT.NONE);
319                 label.setImage(warning);
320                 label = new Label(errorComposite, SWT.NONE);
321                 label.setText(text);
322                 //this.setStatusMessage("Update contains structural changes (new or deleted symbols), please create a new model.");
323                 composite.layout(true);
324         
325         }
326         
327         private void updateSelection() {
328                 Stack<UpdateNode> nodeStack = new Stack<UpdateNode>();
329                 nodeStack.push((UpdateNode)updateTree.getRootNode());
330                 while (!nodeStack.isEmpty()) {
331                         UpdateNode n = nodeStack.pop();
332                         if (n.getOp() != null) {
333                                 boolean applied = n.getOp().applied();
334                                 if (applied) {
335                                         changeBrowser.setChecked(n, true);
336                                         changeBrowser.setGrayed(n, true);
337                                         selectedStructure.remove(n);
338                                 } else {
339                                         boolean sel = n.getOp().selected();
340                                         if (sel) {
341                                                 selectedStructure.add(n);
342                                                 
343                                         } else {
344                                                 selectedStructure.remove(n);
345                                         }
346                                         changeBrowser.setChecked(n, sel);
347                                         changeBrowser.setGrayed(n, false);
348                                 }
349                         } else {
350                                 changeBrowser.setGrayed(n, true);
351                                 changeBrowser.setChecked(n, true);
352                         }
353                         for (UpdateNode c : n.getChildren()) {
354                                 nodeStack.add((UpdateNode)c);
355                         }
356                 }
357                 
358                 changeBrowser.refresh();
359         }
360         
361         
362         
363         private void load() {
364                 
365                 addFilters(filters);
366
367                 UpdateEditorInput uei = (UpdateEditorInput)getEditorInput();
368                 Resource r1 = uei.getR1();
369                 Resource r2 = uei.getR2();
370                 
371
372                 try {
373                         
374                         Pair<GraphComparator,Boolean> result = getChanges(r1,r2);
375                         GraphComparator comparator  = result.first;
376                         if (result.second)
377                                 showWarning("Structural symbols have been changed. Model update is not able to update these, please create a new model.");
378                         comparator.test(getSession());
379                         changes = comparator.getChanges();
380                         changes = getSession().syncRequest(new FilterChangesRead(changes));
381                         updateTree = getUpdateTree(changes);
382                 } catch (DatabaseException e) {
383                         Text text = new Text(composite, SWT.MULTI);
384                         text.setText(e.getMessage());
385                         e.printStackTrace();
386                         return;
387                 }
388         
389
390
391                 changeViewer.setInput(changes.getModifications());
392                 changeBrowser.setInput(updateTree);
393                 updateSelection();
394         }
395         
396         
397         
398         private void updateAll() {
399                 updateAllButton.setEnabled(false);
400                 updateSelectedButton.setEnabled(false);
401                 getSession().asyncRequest(new WriteRequest(){
402                         @Override
403                         public void perform(WriteGraph graph) throws DatabaseException {
404                                 for (Pair<Statement, Statement> mod : changes.getModifications()) {
405                                         applyLiteralChange(graph, mod);
406                                 }
407                                 selected.clear();
408                                 changes.getModifications().clear();
409                                 
410                                 updateTree.getUpdateOps().applyAll(graph);
411                                 
412                                 Display.getDefault().asyncExec(new Runnable() {
413                                         
414                                         @Override
415                                         public void run() {
416                                                 
417                                                 updateAllButton.setEnabled(true);
418                                                 updateSelectedButton.setEnabled(true);
419                                                 updateSelection();
420                                                 changeViewer.refresh();
421                                         }
422                                 });
423                         }
424                         
425                         
426                 }, new Callback<DatabaseException>() {
427                         @Override
428                         public void run(DatabaseException parameter) {
429                                 if (parameter != null)
430                                         ExceptionUtils.logAndShowError("Cannot update model", parameter);
431                         }
432                 });
433         }
434         
435         private void applyLiteralChange(WriteGraph graph, Pair<Statement, Statement> mod) throws DoesNotContainValueException, ServiceException, ManyObjectsForFunctionalRelationException {
436                 
437                 Resource s = changes.getComparable().getLeft(mod.second.getSubject());
438                 Resource pred = mod.first.getPredicate();
439                 if (graph.hasValue(mod.second.getObject())) {
440                         Object value = graph.getValue(mod.second.getObject());
441                         graph.claimLiteral(s, pred, value);
442                 } else {
443                         graph.deny(s,pred);
444                 }
445                 
446                 
447         }
448         
449         private void updateSelected() {
450                 updateAllButton.setEnabled(false);
451                 updateSelectedButton.setEnabled(false);
452                 getSession().asyncRequest(new WriteRequest(){
453                         @Override
454                         public void perform(WriteGraph graph) throws DatabaseException {
455                                 for (Pair<Statement, Statement> mod : selected) {
456                                         changes.getModifications().remove(mod);
457                                         applyLiteralChange(graph, mod);
458                                 }
459                                 selected.clear();
460                                 
461                                 updateTree.getUpdateOps().applySelected(graph);
462                                 
463                                 Display.getDefault().asyncExec(new Runnable() {
464                                         
465                                         @Override
466                                         public void run() {
467                                                 changeViewer.refresh();
468                                                 updateAllButton.setEnabled(true);
469                                                 updateSelectedButton.setEnabled(true);
470                                                 updateSelection();
471                                         }
472                                 });
473                         }
474                 });
475         }
476
477         @Override
478         public void setFocus() {
479                 composite.setFocus();
480
481         }
482         
483         /**
484          * Filters changes:
485          * 1. Changes that are not essential for model update (changes that can be found when the models are axcatly the same)
486          * 2. Runs custom filters for value changes. 
487          * 
488          * @param g
489          * @param changes
490          * @return
491          * @throws DatabaseException
492          */
493         protected GraphChanges filterChanges(ReadGraph g, GraphChanges changes) throws DatabaseException 
494     {
495                 
496                 List<Pair<Statement,Statement>> modifications = new ArrayList<Pair<Statement,Statement>>();
497                 
498         for (Pair<Statement, Statement> mod : changes.getModifications()) {
499                 
500                 boolean accept = true;
501                 for (ChangeFilter filter : filters) {
502                         if (!filter.accept(g, mod)) {
503                                 accept = false;
504                                 break;
505                         }       
506                 }
507                 if (accept)
508                         modifications.add(mod);
509         }
510         GraphChanges newChanges =  new GraphChanges(changes.getResource1(),changes.getResource2(),changes.getDeletions(), changes.getAdditions(), modifications, changes.getComparable());
511         return newChanges;
512     }
513         
514         public interface ChangeFilter {
515                 public boolean accept(ReadGraph g, Pair<Statement, Statement> change) throws DatabaseException;
516         }
517         
518         
519         
520         
521         /**
522          * 
523          * Filters floating point value changes (default filter is set filter when the change is less than 1%)  
524          *
525          */
526         protected class FPValueFilter implements ChangeFilter  {
527                 
528                 private double percentage = 0.01;
529                 
530                 public FPValueFilter() {
531                         
532                 }
533                 
534                 public FPValueFilter(double percentage) {
535                         if (percentage < 0.0 || percentage > 1.0)
536                                 throw new IllegalArgumentException("Percentage must be between 0.0 and 1.0.");
537                         this.percentage = percentage;
538                 }
539                 
540                 @Override
541                 public boolean accept(ReadGraph g, Pair<Statement, Statement> change) throws DatabaseException {
542                         //filter floating point values that have less than 1% difference.
543                         if (!g.hasValue(change.first.getObject()) || !g.hasValue(change.second.getObject()))
544                                 return true;
545                 Object v1 = g.getValue(change.first.getObject());
546                 Object v2 = g.getValue(change.second.getObject());
547                 
548                 if (v1 instanceof Double && v2 instanceof Double) {
549                         double d1 = (Double)v1;
550                         double d2 = (Double)v2;
551                         if (Math.abs(d1-d2) / Math.max(Math.abs(d1), Math.abs(d2)) < percentage)
552                                 return false;
553                 } else if (v1 instanceof Float && v2 instanceof Float) {
554                         float d1 = (Float)v1;
555                         float d2 = (Float)v2;
556                         if (Math.abs(d1-d2) / Math.max(Math.abs(d1), Math.abs(d2)) < percentage)
557                                 return false;
558                 }
559
560                 return true;
561                 }
562         }
563
564         
565         private class FilterChangesRead implements Read<GraphChanges> {
566                 private GraphChanges changes;
567                 public FilterChangesRead(GraphChanges changes) {
568                         this.changes = changes;
569                 }
570                 
571                 @Override
572                 public GraphChanges perform(ReadGraph graph) throws DatabaseException {
573                         return filterChanges(graph, changes);
574                 }
575         }
576         
577         
578         private class ModificationListContentProvider implements IStructuredContentProvider {
579                 
580                 @SuppressWarnings("unchecked")
581                 @Override
582                 public Object[] getElements(Object inputElement) {
583                         if (inputElement == null)
584                                 return null;
585                         Collection<Pair<Statement, Statement>> coll = (Collection<Pair<Statement, Statement>>)inputElement;
586                         return coll.toArray();
587                 }
588                 
589                 @Override
590                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
591                         
592                 }
593                 
594                 @Override
595                 public void dispose() {
596                         
597                 }
598         }
599         
600         private class UpdateTreeContentProvider implements ITreeContentProvider {
601                 @Override
602                 public Object[] getElements(Object inputElement) {
603                         if (inputElement instanceof UpdateTree)
604                                 return new Object[]{((UpdateTree)inputElement).getRootNode()};
605                         if (inputElement instanceof UpdateNode) {
606                                 UpdateNode node = (UpdateNode)inputElement;
607                                 return node.getChildren().toArray();
608                         }
609                         return new Object[0];
610                 }
611                 
612                 @Override
613                 public Object getParent(Object element) {
614                         return null;
615                 }
616                 
617                 @Override
618                 public Object[] getChildren(Object parentElement) {
619                         UpdateNode node = (UpdateNode)parentElement;
620                         return node.getChildren().toArray();
621                 }
622                 
623                 @Override
624                 public boolean hasChildren(Object element) {
625                         UpdateNode node = (UpdateNode)element;
626                         return node.getChildren().size() > 0;
627                 }
628                 
629                 @Override
630                 public void dispose() {
631                         
632                 }
633                 
634                 @Override
635                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
636                         
637                 }
638         }
639         
640         private class SelectionLabelProvider extends ColumnLabelProvider {
641                 
642                 Collection<?>  selected;
643                 public SelectionLabelProvider(Collection<?>  selected) {
644                         this.selected = selected;
645                 }
646                 @Override
647                 public String getText(Object element) {
648                         return "";
649                 }
650                 
651                 @Override
652                 public Image getImage(Object element) {
653                         if (selected.contains(element))
654                                 return checked;
655                         else
656                                 return unchecked;
657                 }
658         }
659         
660         private class UpdateNodeLabelProvicer extends ColumnLabelProvider {
661                 
662                 @Override
663                 public String getText(Object element) {
664                         final UpdateNode node = (UpdateNode)element;
665                         try  {
666                                 return getSession().syncRequest(new Read<String>() {
667                                         @Override
668                                         public String perform(ReadGraph graph) throws DatabaseException {
669                                                 return node.getLabel(graph);
670                                         }
671                                 });
672                         } catch (Exception e) {
673                                 return e.getMessage();
674                         }
675                 }
676                 
677                 @Override
678                 public Image getImage(Object element) {
679                         final UpdateNode node = (UpdateNode)element;
680                         try  {
681                                 ImageDescriptor id = getSession().syncRequest(new Read<ImageDescriptor>() {
682                                         @Override
683                                         public ImageDescriptor perform(ReadGraph graph) throws DatabaseException {
684                                                 return node.getImage(graph);
685                                         }
686                                 });
687                                 return manager.createImage(id);
688                         } catch (Exception e) {
689                                 return null;
690                         }
691                 }
692                 
693                 @Override
694                 public String getToolTipText(Object element) {
695                         final UpdateNode node = (UpdateNode)element;
696                         if (node.getOp() != null) {
697                                 return node.getOp().toString();
698                         } else {
699                                 return null;
700                         }
701                 }
702                 
703                 @Override
704                 public int getToolTipDisplayDelayTime(Object object) {
705                         return 1000;
706                 }
707                 
708                 @Override
709                 public int getToolTipTimeDisplayed(Object object) {
710                         return 10000;
711                 }
712
713                 @Override
714                 public Color getBackground(Object element) {
715                         final UpdateNode node = (UpdateNode)element;
716                         Status status = node.getStatus();
717                         if (status == Status.CONTAINS)
718                                 return containsColor;
719                         if (status == Status.DELETED)
720                                 return deletedColor;
721                         if (status == Status.NEW)
722                                 return addedColor;
723                         return null;            
724                 }
725         }
726         
727         private class SelectionEditingSupport extends EditingSupport {
728                 
729                 @SuppressWarnings("rawtypes")
730                 Collection selected;
731
732                 
733                 @SuppressWarnings("rawtypes")
734                 public SelectionEditingSupport(ColumnViewer viewer, Collection selected) {
735                         super(viewer);
736                         this.selected = selected;
737                         
738                 }
739
740                 @Override
741                 protected boolean canEdit(Object element) {
742                         return true;
743                 }
744                 
745                 @Override
746                 protected CellEditor getCellEditor(Object element) {
747                         return new CheckboxCellEditor(null, SWT.CHECK);
748                 }
749                 
750                 @Override
751                 protected Object getValue(Object element) {
752                         return selected.contains(element);
753                 }
754                 
755                 @SuppressWarnings("unchecked")
756                 @Override
757                 protected void setValue(Object element, Object value) {
758                         if (Boolean.TRUE.equals(value))
759                                 selected.add(element);
760                         else
761                                 selected.remove(element);
762                         
763                         getViewer().refresh(element);
764                 }
765                 
766                 
767         }
768
769
770 }