]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d/src/org/simantics/g3d/property/AnnotatedPropertyTabContributorFactory.java
461319ebb9a81eeb0a66f169b69b771c1cf836f4
[simantics/3d.git] / org.simantics.g3d / src / org / simantics / g3d / property / AnnotatedPropertyTabContributorFactory.java
1 package org.simantics.g3d.property;\r
2 \r
3 import java.lang.annotation.Annotation;\r
4 import java.lang.reflect.Field;\r
5 import java.lang.reflect.InvocationTargetException;\r
6 import java.lang.reflect.Method;\r
7 import java.util.ArrayList;\r
8 import java.util.Collection;\r
9 import java.util.Collections;\r
10 import java.util.HashMap;\r
11 import java.util.HashSet;\r
12 import java.util.LinkedHashMap;\r
13 import java.util.List;\r
14 import java.util.Map;\r
15 import java.util.Set;\r
16 \r
17 import org.eclipse.jface.layout.GridDataFactory;\r
18 import org.eclipse.jface.viewers.AbstractTableViewer;\r
19 import org.eclipse.jface.viewers.CellEditor;\r
20 import org.eclipse.jface.viewers.CellEditor.LayoutData;\r
21 import org.eclipse.jface.viewers.CellLabelProvider;\r
22 import org.eclipse.jface.viewers.CellNavigationStrategy;\r
23 import org.eclipse.jface.viewers.ColumnViewer;\r
24 import org.eclipse.jface.viewers.ColumnViewerEditor;\r
25 import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;\r
26 import org.eclipse.jface.viewers.ColumnViewerEditorActivationListener;\r
27 import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;\r
28 import org.eclipse.jface.viewers.ColumnViewerEditorDeactivationEvent;\r
29 import org.eclipse.jface.viewers.EditingSupport;\r
30 import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;\r
31 import org.eclipse.jface.viewers.ISelection;\r
32 import org.eclipse.jface.viewers.ISelectionChangedListener;\r
33 import org.eclipse.jface.viewers.ISelectionProvider;\r
34 import org.eclipse.jface.viewers.IStructuredContentProvider;\r
35 import org.eclipse.jface.viewers.SelectionChangedEvent;\r
36 import org.eclipse.jface.viewers.StructuredSelection;\r
37 import org.eclipse.jface.viewers.TableViewer;\r
38 import org.eclipse.jface.viewers.TableViewerColumn;\r
39 import org.eclipse.jface.viewers.TableViewerFocusCellManager;\r
40 import org.eclipse.jface.viewers.TextCellEditor;\r
41 import org.eclipse.jface.viewers.Viewer;\r
42 import org.eclipse.jface.viewers.ViewerCell;\r
43 import org.eclipse.jface.viewers.ViewerColumn;\r
44 import org.eclipse.jface.viewers.ViewerRow;\r
45 import org.eclipse.swt.SWT;\r
46 import org.eclipse.swt.custom.TableEditor;\r
47 import org.eclipse.swt.events.TraverseEvent;\r
48 import org.eclipse.swt.widgets.Composite;\r
49 import org.eclipse.swt.widgets.Control;\r
50 import org.eclipse.swt.widgets.Display;\r
51 import org.eclipse.swt.widgets.Event;\r
52 import org.eclipse.swt.widgets.Item;\r
53 import org.eclipse.swt.widgets.TableColumn;\r
54 import org.eclipse.swt.widgets.TableItem;\r
55 import org.eclipse.ui.IWorkbenchSite;\r
56 import org.simantics.db.management.ISessionContext;\r
57 import org.simantics.g3d.property.annotations.CompoundGetPropertyValue;\r
58 import org.simantics.g3d.property.annotations.CompoundSetPropertyValue;\r
59 import org.simantics.g3d.property.annotations.GetPropertyValue;\r
60 import org.simantics.g3d.property.annotations.PropertyTabBlacklist;\r
61 import org.simantics.g3d.property.annotations.SetPropertyValue;\r
62 import org.simantics.g3d.scenegraph.IG3DNode;\r
63 import org.simantics.g3d.scenegraph.NodeMap;\r
64 import org.simantics.g3d.scenegraph.NodeMapProvider;\r
65 import org.simantics.g3d.scenegraph.base.INode;\r
66 import org.simantics.g3d.scenegraph.base.NodeListener;\r
67 import org.simantics.g3d.scenegraph.base.ParentNode;\r
68 import org.simantics.g3d.scenegraph.structural.IStructuralNode;\r
69 import org.simantics.g3d.tools.AdaptationUtils;\r
70 import org.simantics.selectionview.IPropertyTab;\r
71 import org.simantics.selectionview.IPropertyTab2;\r
72 import org.simantics.utils.datastructures.Callback;\r
73 import org.simantics.utils.datastructures.MapList;\r
74 \r
75 public class AnnotatedPropertyTabContributorFactory implements PropertyTabContributorFactory {\r
76 \r
77         private static final boolean DEBUG = false;\r
78         \r
79         @SuppressWarnings("unchecked")\r
80         @Override\r
81         public List<PropertyTabContributor> getContributors(Object input) {\r
82                 Map<String,IPropertyItem> items = new LinkedHashMap<String, IPropertyItem>();\r
83                 List<String> blacklist = new ArrayList<String>();\r
84                 try {\r
85                         collectItems(input.getClass(), items);\r
86                         collectBlacklist(input.getClass(), blacklist);\r
87                 } catch (InstantiationException e) {\r
88                         // TODO Auto-generated catch block\r
89                         e.printStackTrace();\r
90                 } catch (IllegalAccessException e) {\r
91                         // TODO Auto-generated catch block\r
92                         e.printStackTrace();\r
93                 }\r
94                 \r
95                 if (items.size() == 0)\r
96                         return Collections.EMPTY_LIST;\r
97                 \r
98                 MapList<String, IPropertyItem> tabMap = new MapList<String, IPropertyItem>();\r
99                 List<String> tabs = new ArrayList<String>();\r
100                 for (String id : items.keySet()) {\r
101                         IPropertyItem item = items.get(id);\r
102                         tabMap.add(item.getTabId(), item);\r
103                         if (!tabs.contains(item.getTabId())) {\r
104                                 tabs.add(item.getTabId());\r
105                                 //System.out.println(item.tabId + " " + item.name + " " + item.id);\r
106                         }\r
107                 }\r
108                 for (String s : blacklist) {\r
109                         tabs.remove(s);\r
110                 }\r
111                 \r
112                 List<PropertyTabContributor> contributors = new ArrayList<PropertyTabContributor>(tabs.size());\r
113                 for (String tabId : tabs) {\r
114                         contributors.add(new AnnotatedPropertyTabContributor(tabId, tabMap.getValues(tabId)));\r
115                 }\r
116                 \r
117                 return contributors;\r
118         }\r
119         \r
120         \r
121         private static void collectItems(Class<?> clazz, Map<String, IPropertyItem> items) throws InstantiationException, IllegalAccessException {\r
122                  Class<?> superclass = clazz.getSuperclass();\r
123                  if(superclass != null)\r
124                          collectItems(superclass, items);\r
125                  \r
126                  for (Method m : clazz.getDeclaredMethods()) {\r
127                          m.setAccessible(true);\r
128                 for (Annotation annotation : m.getAnnotations()) {\r
129                         if (annotation.annotationType().equals(GetPropertyValue.class)) {\r
130                                 GetPropertyValue get = (GetPropertyValue)annotation;\r
131                                 PropertyItem item = (PropertyItem)items.get(get.value());\r
132                                 if (item == null) {\r
133                                         item = new PropertyItem(get.value());\r
134                                         items.put(item.id, item);\r
135                                 }\r
136 \r
137                                 item.getter = m;\r
138                                 item.manipulatorClass = get.manipulator().newInstance().get(m,null);\r
139 \r
140                                 item.tabId = get.tabId();\r
141 \r
142                                 item.name = get.name();\r
143                                 \r
144                                 \r
145                         } else if (annotation.annotationType().equals(SetPropertyValue.class)) {\r
146                                 SetPropertyValue set = (SetPropertyValue)annotation;\r
147                                 PropertyItem item = (PropertyItem)items.get(set.value());\r
148                                 if (item == null) {\r
149                                         item = new PropertyItem(set.value());\r
150                                         items.put(item.id, item);\r
151                                 }\r
152                                 \r
153                                 item.setter = m;\r
154                         } else if (annotation.annotationType().equals(CompoundGetPropertyValue.class)) {\r
155                                 CompoundGetPropertyValue get = (CompoundGetPropertyValue)annotation;\r
156                                 CompoundPropertyItem item = (CompoundPropertyItem)items.get(get.value());\r
157                                 if (item == null) {\r
158                                         item = new CompoundPropertyItem(get.value());\r
159                                         items.put(item.id, item);\r
160                                 }\r
161 \r
162                                 item.getter = m;\r
163                                 item.manipulatorFactory = get.manipulator().newInstance();\r
164 \r
165                                 item.tabId = get.tabId();\r
166 \r
167                                 item.name = get.name();\r
168                         } else if (annotation.annotationType().equals(CompoundSetPropertyValue.class)) {\r
169                                 CompoundSetPropertyValue set = (CompoundSetPropertyValue)annotation;\r
170                                 CompoundPropertyItem item = (CompoundPropertyItem)items.get(set.value());\r
171                                 if (item == null) {\r
172                                         item = new CompoundPropertyItem(set.value());\r
173                                         items.put(item.id, item);\r
174                                 }\r
175                                 \r
176                                 item.setter = m;\r
177                         }\r
178                 }\r
179                  }\r
180                 \r
181                 \r
182         }\r
183         \r
184         private static void collectBlacklist(Class<?> clazz, List<String> blacklist) throws InstantiationException, IllegalAccessException {\r
185                  Class<?> superclass = clazz.getSuperclass();\r
186                  if(superclass != null)\r
187                          collectBlacklist(superclass, blacklist);\r
188                  \r
189                  PropertyTabBlacklist ann = clazz.getAnnotation(PropertyTabBlacklist.class);\r
190                  if (ann == null)\r
191                          return;\r
192                  String s = ann.value();\r
193                  if (s == null)\r
194                          return;\r
195                  if (s.length() == 0)\r
196                          return;\r
197                  for (String item : s.split(";")) {\r
198                          blacklist.add(item);\r
199                  }\r
200                  \r
201                 \r
202         }\r
203         \r
204         private static Map<PropertyItem, PropertyManipulator> createManipulators(CompoundPropertyItem item, Object obj) {\r
205                 try {\r
206                         \r
207                         Map<String,Object> map = (Map<String, Object>)item.getter.invoke(obj);\r
208                         Map<PropertyItem, PropertyManipulator> result = new HashMap<AnnotatedPropertyTabContributorFactory.PropertyItem, PropertyManipulator>();\r
209                         for (String key : map.keySet()) {\r
210                                 MethodWithMapValueProvider provider = new MethodWithMapValueProvider(item.getter, item.setter, key);\r
211                                 Class<? extends PropertyManipulator> clazz = item.manipulatorFactory.get(null,map.get(key));\r
212                                 PropertyManipulator manipulator = clazz.getConstructor(ValueProvider.class,Object.class).newInstance(provider,obj);\r
213                                 PropertyItem i = new PropertyItem(item.id+"."+key);\r
214                                 i.getter = item.getter;\r
215                                 i.setter = item.setter;\r
216                                 i.name = key;\r
217                                 i.tabId = item.tabId;\r
218                                 result.put(i,manipulator);\r
219                         }\r
220                         return result;\r
221                 } catch (Exception e) {\r
222                         e.printStackTrace();\r
223                         return Collections.EMPTY_MAP;\r
224                 } \r
225                 \r
226         }\r
227         \r
228         private static PropertyManipulator createManipulator(PropertyItem item, Object obj) {\r
229                 try {\r
230                         MethodValueProvider provider = new MethodValueProvider(item.getter, item.setter);\r
231                         PropertyManipulator manipulator = item.manipulatorClass.getConstructor(ValueProvider.class,Object.class).newInstance(provider,obj);\r
232                         return manipulator;\r
233                 } catch (Exception e) {\r
234                         e.printStackTrace();\r
235                         return null;\r
236                 } \r
237         }\r
238         \r
239         private static interface IPropertyItem {\r
240                 public String getTabId();\r
241         }\r
242         \r
243         private static class PropertyItem implements IPropertyItem{\r
244                 private String id;\r
245                 private String name;\r
246                 private String tabId;\r
247                 private Method getter;\r
248                 private Method setter;\r
249                 private Class<? extends PropertyManipulator> manipulatorClass;\r
250                 \r
251                 \r
252                 public PropertyItem(String id) {\r
253                         if (id == null)\r
254                                 throw new NullPointerException();\r
255                         this.id = id;\r
256                 }\r
257                 \r
258                 @Override\r
259                 public int hashCode() {\r
260                         return id.hashCode();\r
261                 }\r
262                 \r
263                 @Override\r
264                 public String getTabId() {\r
265                         return tabId;\r
266                 }\r
267         }\r
268         \r
269         private static class CompoundPropertyItem implements IPropertyItem{\r
270                 private String id;\r
271                 private String name;\r
272                 private String tabId;\r
273                 private Method getter;\r
274                 private Method setter;\r
275                 private PropertyManipulatorFactory manipulatorFactory;\r
276                 \r
277                 \r
278                 public CompoundPropertyItem(String id) {\r
279                         if (id == null)\r
280                                 throw new NullPointerException();\r
281                         this.id = id;\r
282                 }\r
283                 \r
284                 @Override\r
285                 public int hashCode() {\r
286                         return id.hashCode();\r
287                 }\r
288                 \r
289                 @Override\r
290                 public String getTabId() {\r
291                         return tabId;\r
292                 }\r
293         }\r
294         \r
295         private static class AnnotatedPropertyTabContributor implements PropertyTabContributor {\r
296                 private String id; \r
297                 List<IPropertyItem> items;\r
298                 \r
299                 public AnnotatedPropertyTabContributor(String id, List<IPropertyItem> items) {\r
300                         if (id == null)\r
301                                 throw new NullPointerException();\r
302                         this.id = id;\r
303                         this.items = items;\r
304                 }\r
305                 \r
306                 @Override\r
307                 public IPropertyTab create(Composite parent, IWorkbenchSite site,\r
308                                 ISessionContext context, Object input) {\r
309                         AnnotatedPropertyTab tab = new AnnotatedPropertyTab(id, items);\r
310                         tab.createControl(parent, context);\r
311                         return tab;\r
312                 }\r
313                 \r
314                 @Override\r
315                 public String getId() {\r
316                         return id;\r
317                 }\r
318                 \r
319         }\r
320         \r
321         private static class AnnotatedPropertyTab implements IPropertyTab2, NodeListener {\r
322                 //private String id; \r
323                 List<IPropertyItem> contibutedItems;\r
324                 List<PropertyItem> resolvedItems = new ArrayList<PropertyItem>();\r
325                 private Map<PropertyItem,PropertyManipulator> manipulators = new HashMap<PropertyItem, PropertyManipulator>();\r
326                 \r
327                 private TableViewer viewer;\r
328                 \r
329                 private IG3DNode node;\r
330                 private NodeMap<?> nodeMap;\r
331                 \r
332                 private List<TableViewerColumn> valueColumns = new ArrayList<TableViewerColumn>();\r
333                 \r
334                 public AnnotatedPropertyTab(String id, List<IPropertyItem> items) {\r
335                         //this.id = id;\r
336                         this.contibutedItems = items;\r
337                         \r
338                                         \r
339                 }\r
340                 \r
341                 @Override\r
342                 public void createControl(Composite parent, ISessionContext context) {\r
343                         //parent.setLayout(new FillLayout());\r
344                         viewer = new TableViewer(parent, SWT.FULL_SELECTION | SWT.SINGLE);\r
345                         \r
346                         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(viewer.getTable());\r
347                         \r
348                         //viewer.setLabelProvider(new AnnotatedTableLabelProvider(object))\r
349                         \r
350                         viewer.setContentProvider(new PropertyItemContentsProvider());\r
351                         \r
352                         TableViewerColumn name = new TableViewerColumn(viewer, SWT.LEFT);\r
353                         //TableViewerColumn value = new TableViewerColumn(viewer, SWT.LEFT);\r
354                         name.setLabelProvider(new PropertyItemNameProvider());\r
355                         //value.setLabelProvider(new PropertyValueLabelProvider(null));\r
356                         name.getColumn().setText("Property");\r
357                         //value.getColumn().setText("Value");\r
358                         name.getColumn().setWidth(200);\r
359                         //value.getColumn().setWidth(200);\r
360                         name.getViewer().addSelectionChangedListener(new ISelectionChangedListener() {\r
361                                 \r
362                                 @Override\r
363                                 public void selectionChanged(SelectionChangedEvent event) {\r
364                                         PropertyItem item = AdaptationUtils.adaptToSingle(event.getSelection(),PropertyItem.class);\r
365                                         if (item != null) {\r
366                                                 PropertyManipulator manipulator = manipulators.get(item);//createManipulator(item, null);\r
367                                                 for (int i = 0; i < valueColumns.size(); i++) {\r
368                                                         TableViewerColumn c = valueColumns.get(i);\r
369                                                         if (i < manipulator.getValueCount()) {\r
370                                                                 c.getColumn().setText(manipulator.getDescription(i));\r
371                                                         } else {\r
372                                                                 c.getColumn().setText("");\r
373                                                         }\r
374                                                 }\r
375                                         }\r
376                                         \r
377                                 }\r
378                         });\r
379                         \r
380                         int valueCount = 0;\r
381                         for (IPropertyItem item : contibutedItems) {\r
382                                 if (item instanceof PropertyItem) {\r
383                                         PropertyManipulator manipulator = createManipulator((PropertyItem)item, null);\r
384                                         if (manipulator == null)\r
385                                                 continue;\r
386                                         if (valueCount < manipulator.getValueCount())\r
387                                                 valueCount = manipulator.getValueCount();\r
388                                 } else if (item instanceof CompoundPropertyItem) {\r
389                                         if (valueCount < 1)\r
390                                                 valueCount = 1;\r
391                                 }\r
392                         }\r
393                         for (int i = 0; i < valueCount; i++) {\r
394                                 TableViewerColumn value = new TableViewerColumn(viewer, SWT.LEFT);\r
395                                 //value.getColumn().setText("Value " + (i+1));\r
396                                 value.getColumn().setText("");\r
397                                 value.getColumn().setWidth(200);\r
398                                 valueColumns.add(value);\r
399                                 //value.setEditingSupport(new )\r
400                         }\r
401                         viewer.getTable().setHeaderVisible(true);\r
402                         viewer.getTable().setLinesVisible(true);\r
403                         viewer.addSelectionChangedListener(new ISelectionChangedListener() {\r
404                                 \r
405                                 @Override\r
406                                 public void selectionChanged(SelectionChangedEvent event) {\r
407                                         PropertyItem item = AdaptationUtils.adaptToSingle(event.getSelection(), PropertyItem.class);\r
408                                         selectedItem = item;\r
409                                         if (!manipulators.get(selectedItem).getEditMode())\r
410                                                 manipulators.get(selectedItem).setEditMode(true);\r
411                                         \r
412 \r
413                                         for (IPropertyItem i : delayedUpdate) {\r
414                                                 if (!i.equals(selectedItem)) {\r
415                                                         manipulators.get(i).setEditMode(false);\r
416                                                         viewer.update(i,null);\r
417                                                 }\r
418                                         }\r
419                                         if (delayedUpdate.contains(selectedItem)) {\r
420                                                 delayedUpdate.clear();\r
421                                                 delayedUpdate.add(selectedItem);\r
422                                         } else {\r
423                                                 delayedUpdate.clear();\r
424                                         }\r
425                                 }\r
426                         });\r
427                         \r
428                         CellNavigationStrategy nStrategy = new CellNavigationStrategy() {\r
429                                 private ViewerCell internalFindSelectedCell(\r
430                                                 ColumnViewer viewer, ViewerCell currentSelectedCell,\r
431                                                 Event event) {\r
432                                         switch (event.keyCode) {\r
433                                         case SWT.ARROW_UP:\r
434                                                 if (currentSelectedCell != null) {\r
435                                                         return getNeighbor(currentSelectedCell,\r
436                                                                         ViewerCell.ABOVE, false);\r
437                                                 }\r
438                                                 break;\r
439                                         case SWT.ARROW_DOWN:\r
440                                                 if (currentSelectedCell != null) {\r
441                                                         return getNeighbor(currentSelectedCell,\r
442                                                                         ViewerCell.BELOW, false);\r
443                                                 }\r
444                                                 break;\r
445                                         case SWT.ARROW_LEFT:\r
446                                                 if (currentSelectedCell != null) {\r
447                                                         return getNeighbor(currentSelectedCell,\r
448                                                                         ViewerCell.LEFT, true);\r
449                                                 }\r
450                                                 break;\r
451                                         case SWT.ARROW_RIGHT:\r
452                                                 if (currentSelectedCell != null) {\r
453                                                         return getNeighbor(currentSelectedCell,\r
454                                                                         ViewerCell.RIGHT, true);\r
455                                                 }\r
456                                                 break;\r
457                                         }\r
458                                         return null;\r
459                                 }\r
460                                 \r
461                                 public ViewerCell findSelectedCell(ColumnViewer viewer,\r
462                                                 ViewerCell currentSelectedCell, Event event) {\r
463                                         ViewerCell cell = internalFindSelectedCell(viewer,\r
464                                                         currentSelectedCell, event);\r
465                                         if (cell != null) {\r
466                                                 TableColumn t = AnnotatedPropertyTab.this.viewer.getTable().getColumn(\r
467                                                                 cell.getColumnIndex());\r
468                                                 AnnotatedPropertyTab.this.viewer.getTable().showColumn(t);\r
469                                         }\r
470                                         return cell;\r
471                                 }\r
472                         };\r
473                         \r
474                         TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(\r
475                                         viewer, new FocusCellOwnerDrawHighlighter(viewer));\r
476                         try {\r
477                                 Field f = focusCellManager.getClass().getSuperclass()\r
478                                                 .getDeclaredField("navigationStrategy");\r
479                                 f.setAccessible(true);\r
480                                 f.set(focusCellManager, nStrategy);\r
481                         } catch (SecurityException e) {\r
482                                 e.printStackTrace();\r
483                         } catch (NoSuchFieldException e) {\r
484                                 e.printStackTrace();\r
485                         } catch (IllegalArgumentException e) {\r
486                                 e.printStackTrace();\r
487                         } catch (IllegalAccessException e) {\r
488                                 e.printStackTrace();\r
489                         }\r
490                         ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(\r
491                                         viewer) {\r
492                                 protected boolean isEditorActivationEvent(\r
493                                                 ColumnViewerEditorActivationEvent event) {\r
494                                         return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL\r
495                                                         || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION\r
496                                                         || (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR)\r
497                                                         || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;\r
498                                 }\r
499                         };\r
500                         TableViewerEditor.create(viewer, focusCellManager, actSupport,\r
501                                         ColumnViewerEditor.TABBING_HORIZONTAL\r
502                                                         | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR\r
503                                                         | ColumnViewerEditor.TABBING_VERTICAL\r
504                                                         | ColumnViewerEditor.KEYBOARD_ACTIVATION);\r
505                         viewer.getColumnViewerEditor().addEditorActivationListener(\r
506                                         new ColumnViewerEditorActivationListener() {\r
507                                                 public void afterEditorActivated(\r
508                                                                 ColumnViewerEditorActivationEvent event) {\r
509                                                 }\r
510 \r
511                                                 public void afterEditorDeactivated(\r
512                                                                 ColumnViewerEditorDeactivationEvent event) {\r
513                                                 }\r
514 \r
515                                                 public void beforeEditorActivated(\r
516                                                                 ColumnViewerEditorActivationEvent event) {\r
517                                                         ViewerCell cell = (ViewerCell) event.getSource();\r
518                                                         viewer.getTable().showColumn(\r
519                                                                         viewer.getTable().getColumn(cell.getColumnIndex()));\r
520                                                 }\r
521 \r
522                                                 public void beforeEditorDeactivated(\r
523                                                                 ColumnViewerEditorDeactivationEvent event) {\r
524                                                 }\r
525                                         });\r
526                 }\r
527                 \r
528                 \r
529                 \r
530                 \r
531                 private IPropertyItem selectedItem = null;\r
532                 private Set<IPropertyItem> delayedUpdate = new HashSet<IPropertyItem>();\r
533                 \r
534                 \r
535                 @Override\r
536                 public void setInput(ISessionContext context, ISelection selection,\r
537                                 boolean force) {\r
538                         Collection<IG3DNode> nodes = AdaptationUtils.adaptToCollection(selection, IG3DNode.class);\r
539                         if (nodes.size() != 1) {\r
540                                 if (node != null) {\r
541                                         node.removeListener(this);\r
542                                         node = null;\r
543                                 }\r
544                                 return;\r
545                         }\r
546                         IG3DNode n = nodes.iterator().next();\r
547                         if (node != null) {\r
548                                 if (!node.equals(n)) {\r
549                                         node.removeListener(this);\r
550                                         setInput(n);\r
551                                 }\r
552                         } else {\r
553                                 setInput(n);\r
554                         }\r
555                 }\r
556                 \r
557                 \r
558                 \r
559                 private void setInput(IG3DNode node) {\r
560                         this.node = node;\r
561                         this.node.addListener(this);\r
562                         // resolve nodemap\r
563                         IG3DNode n = node;\r
564                         while (true) {\r
565                                 if (n == null) {\r
566                                         nodeMap = null;\r
567                                         break;\r
568                                 }\r
569                                 if (n instanceof NodeMapProvider<?>) {\r
570                                         nodeMap = ((NodeMapProvider<?>) n).getNodeMap();\r
571                                         if (nodeMap != null)\r
572                                                 break;\r
573                                 }\r
574                                 n = (IG3DNode)n.getParent();\r
575                         }\r
576                         boolean readOnly =  (node instanceof IStructuralNode && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot());\r
577                         // create label providers\r
578                         PropertyValueLabelProvider2 p = new PropertyValueLabelProvider2(this);\r
579                         int index = 0;\r
580                         for (TableViewerColumn c : valueColumns) {\r
581                                 c.setLabelProvider(p);\r
582                                 if (!readOnly) {\r
583                                         PropertyEditingSupport support = new PropertyEditingSupport(this, viewer, index++, nodeMap);\r
584                                         c.setEditingSupport(support);\r
585                                 }\r
586                         }\r
587                         resolvedItems.clear();\r
588                         manipulators.clear();\r
589                         for (IPropertyItem item : contibutedItems) {\r
590                                 if (item instanceof PropertyItem) {\r
591                                         resolvedItems.add((PropertyItem)item);\r
592                                         manipulators.put((PropertyItem)item, createManipulator((PropertyItem)item, node));\r
593                                 }\r
594                                 else {\r
595                                         CompoundPropertyItem compound = (CompoundPropertyItem)item;\r
596                                         Map<PropertyItem, PropertyManipulator> manipulators = createManipulators(compound, node);\r
597                                         for (PropertyItem i : manipulators.keySet()) {\r
598                                                 resolvedItems.add(i);\r
599                                                 this.manipulators.put(i, manipulators.get(i));\r
600                                         }\r
601                                 }\r
602                         }\r
603                         \r
604                         viewer.getTable().setEnabled(!readOnly);\r
605                         viewer.setInput(resolvedItems);\r
606                 }\r
607                 \r
608                 @Override\r
609                 public void requestFocus() {\r
610                         viewer.getTable().forceFocus();\r
611                 }\r
612                 \r
613                 @Override\r
614                 public void dispose() {\r
615                         if (node != null) {\r
616                                 node.removeListener(this);\r
617                                 node = null;\r
618                         }\r
619                         \r
620                 }\r
621                 \r
622                 @Override\r
623                 public Control getControl() {\r
624                         return viewer.getTable();\r
625                 }\r
626                 \r
627                 @Override\r
628                 public ISelectionProvider getSelectionProvider() {\r
629                         return null;\r
630                 }\r
631                 \r
632                 @Override\r
633                 public boolean isDisposed() {\r
634                         return viewer.getTable().isDisposed();\r
635                 }\r
636                 \r
637                 @Override\r
638                 public <T extends INode> void nodeAdded(ParentNode<T> node,\r
639                                 INode child, String rel) {\r
640                         \r
641                 }\r
642                 \r
643                 @Override\r
644                 public <T extends INode> void nodeRemoved(ParentNode<T> node,\r
645                                 INode child, String rel) {\r
646                         \r
647                 }\r
648                 \r
649                 @Override\r
650                 public void propertyChanged(INode node, final String id) {\r
651 //                      for (final PropertyItem item : items) {\r
652 //                              if (item.id.equals(id)) {\r
653 //                                      Display.getDefault().asyncExec(new Runnable() {\r
654 //                                              \r
655 //                                              @Override\r
656 //                                              public void run() {\r
657 //                                                      viewer.update(item, null);\r
658 //                                                      \r
659 //                                              }\r
660 //                                      });\r
661 //                              }\r
662 //                      }\r
663                         if (Thread.currentThread() == Display.getDefault().getThread()) {\r
664                                 if (DEBUG)System.out.println("Viewer refresh " + id);\r
665                                 for (PropertyItem item : resolvedItems)\r
666                                         if (!item.equals(selectedItem))\r
667                                                 viewer.refresh(item);\r
668                                 if (selectedItem != null)\r
669                                         delayedUpdate.add(selectedItem);\r
670                         } else if (!editing){\r
671                                 // running delayed refresh when a cell editor is active would cancel cell editing.\r
672                                 Display.getDefault().asyncExec(new Runnable() {\r
673                                         @Override\r
674                                         public void run() {\r
675                                                 if (viewer.getTable().isDisposed()) {\r
676                                                         if (AnnotatedPropertyTab.this.node != null)\r
677                                                                 AnnotatedPropertyTab.this.node.removeListener(AnnotatedPropertyTab.this);\r
678                                                         return;\r
679                                                 }\r
680                                                 if (DEBUG) System.out.println("Viewer threaded refresh " + id);\r
681                                                 for (PropertyItem item : resolvedItems)\r
682                                                         if (!item.equals(selectedItem))\r
683                                                                 viewer.refresh(item);\r
684                                                 if (selectedItem != null)\r
685                                                         delayedUpdate.add(selectedItem);\r
686                                                 \r
687                                         }\r
688                                 });\r
689                         } else {\r
690                                 for (PropertyItem item : resolvedItems) {\r
691                                         delayedUpdate.add(item);\r
692                                 }\r
693                         }\r
694                         \r
695                 }\r
696                 \r
697 \r
698                 \r
699                 \r
700                 \r
701                 @Override\r
702                 public void updatePartName(Callback<String> updateCallback) {\r
703                         if (node != null)\r
704                                 updateCallback.run(node.toString()); \r
705                         \r
706                 }\r
707                 \r
708                 public PropertyManipulator getManipulator(PropertyItem item) {\r
709                         return manipulators.get(item);\r
710                 }\r
711                 \r
712                 private boolean editing = false;\r
713                 \r
714                 public void setEditing(boolean editing) {\r
715                         this.editing = editing;\r
716                 }\r
717         }\r
718         \r
719         \r
720         \r
721         private static class PropertyEditingSupport extends EditingSupport {\r
722                 AnnotatedPropertyTab tab;\r
723                 int index;\r
724                 NodeMap<?> nodeMap;\r
725                 TableViewer viewer;\r
726                 CellEditor editor;\r
727 \r
728                 public PropertyEditingSupport(AnnotatedPropertyTab tab, TableViewer viewer, int index, NodeMap<?> nodeMap) {\r
729                         super(viewer);\r
730                         this.tab = tab;\r
731                         this.index = index;\r
732                         this.viewer = viewer;\r
733                         this.nodeMap = nodeMap;\r
734                 }\r
735                 \r
736                 @Override\r
737                 protected boolean canEdit(Object element) {\r
738                         PropertyItem item = (PropertyItem)element;\r
739                         if (tab.getManipulator(item).getValueCount() <= index)\r
740                                 return false;\r
741                         return (item.setter != null);\r
742                 }\r
743                 \r
744                 @Override\r
745                 protected CellEditor getCellEditor(Object element) {\r
746                         \r
747                         if (tab.getManipulator((PropertyItem)element).getValueCount() <= index)\r
748                                 return null;\r
749                         if (editor == null)\r
750                                 editor = new TextCellEditor(viewer.getTable(),SWT.NONE) {\r
751                                 @Override\r
752                                 public void activate() {\r
753                                         tab.setEditing(true);\r
754                                 }\r
755                                 \r
756                                 @Override\r
757                                 public void deactivate() {\r
758                                         super.deactivate();\r
759                                         tab.setEditing(false);\r
760                                 }\r
761                         };\r
762                         if (DEBUG)System.err.println("CELL EDITOR: " + element);\r
763                         return editor;\r
764                 }\r
765                 \r
766                 @Override\r
767                 protected Object getValue(Object element) {\r
768                         PropertyItem item = (PropertyItem)element;\r
769                         PropertyManipulator manipulator = tab.getManipulator(item);//createManipulator(item, obj);\r
770                         if (manipulator.getValueCount() <= index)\r
771                                 return null;\r
772                         Object value = manipulator.getValue(index);\r
773                         return value;\r
774                 }\r
775                 \r
776                 @Override\r
777                 protected void setValue(Object element, Object value) {\r
778                         \r
779                         PropertyItem item = (PropertyItem)element;\r
780                         PropertyManipulator manipulator = tab.getManipulator(item);//createManipulator(item, obj);\r
781                         if (manipulator.getValueCount() <= index)\r
782                                 throw new IllegalAccessError("Editing value in index " + index + " is not allowed.");\r
783                         if (DEBUG)System.err.println("CELL SET VALUE: " + element + " " + value);\r
784                         manipulator.setValue((String)value,index);\r
785                         viewer.refresh(item);\r
786                         nodeMap.commit();\r
787                         \r
788                 }\r
789                 \r
790                 \r
791 \r
792         }\r
793         \r
794         private static class PropertyItemNameProvider extends CellLabelProvider {\r
795 \r
796                 \r
797                 @Override\r
798                 public void update(ViewerCell cell) {\r
799                         PropertyItem item = (PropertyItem)cell.getElement();\r
800 \r
801                         if (item.name.length() > 0)\r
802                                 cell.setText(item.name);\r
803                         else\r
804                                 cell.setText(item.id);\r
805                         \r
806                         \r
807                 }\r
808         }\r
809         \r
810         private static class PropertyValueLabelProvider2 extends CellLabelProvider {\r
811                 AnnotatedPropertyTab tab;\r
812                 //private Object object;\r
813                 \r
814                 public PropertyValueLabelProvider2(AnnotatedPropertyTab tab) {\r
815                         this.tab = tab;\r
816                 }\r
817                 \r
818                 @Override\r
819                 public void update(ViewerCell cell) {\r
820                         PropertyItem item = (PropertyItem)cell.getElement();\r
821                         int index = cell.getColumnIndex() -1;\r
822                         PropertyManipulator manipulator = tab.getManipulator(item);//createManipulator(item, object);\r
823                         if (manipulator.getValueCount() <= index)\r
824                                 return;\r
825                         cell.setText(manipulator.getValue(index));\r
826                 }\r
827         }\r
828         \r
829         private static class PropertyItemContentsProvider implements IStructuredContentProvider {\r
830                 @SuppressWarnings("unchecked")\r
831                 @Override\r
832                 public Object[] getElements(Object inputElement) {\r
833                         List<PropertyItem> items = (List<PropertyItem>)inputElement;\r
834                         return items.toArray();\r
835                 }\r
836                 \r
837                 @Override\r
838                 public void dispose() {\r
839                         \r
840                 }\r
841                 \r
842                 @Override\r
843                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
844                         \r
845                 }\r
846         }\r
847         \r
848         \r
849         \r
850         private static ViewerCell getNeighbor(ViewerCell currentCell,\r
851                         int directionMask, boolean sameLevel) {\r
852                 ViewerRow row;\r
853                 if ((directionMask & ViewerCell.ABOVE) == ViewerCell.ABOVE) {\r
854                         row = currentCell.getViewerRow().getNeighbor(ViewerRow.ABOVE,\r
855                                         sameLevel);\r
856                 } else if ((directionMask & ViewerCell.BELOW) == ViewerCell.BELOW) {\r
857                         row = currentCell.getViewerRow().getNeighbor(ViewerRow.BELOW,\r
858                                         sameLevel);\r
859                 } else {\r
860                         row = currentCell.getViewerRow();\r
861                 }\r
862                 if (row != null) {\r
863                         int columnIndex;\r
864                         columnIndex = getVisualIndex(row, currentCell.getColumnIndex());\r
865                         int modifier = 0;\r
866                         if ((directionMask & ViewerCell.LEFT) == ViewerCell.LEFT) {\r
867                                 modifier = -1;\r
868                         } else if ((directionMask & ViewerCell.RIGHT) == ViewerCell.RIGHT) {\r
869                                 modifier = 1;\r
870                         }\r
871                         columnIndex += modifier;\r
872                         if (columnIndex >= 0 && columnIndex < row.getColumnCount()) {\r
873                                 ViewerCell cell = getCellAtVisualIndex(row, columnIndex);\r
874                                 if (cell != null) {\r
875                                         while (cell != null\r
876                                                         && columnIndex < row.getColumnCount() - 1\r
877                                                         && columnIndex > 0) {\r
878                                                 if (isVisible(cell)) {\r
879                                                         break;\r
880                                                 }\r
881                                                 columnIndex += modifier;\r
882                                                 cell = getCellAtVisualIndex(row, columnIndex);\r
883                                                 if (cell == null) {\r
884                                                         break;\r
885                                                 }\r
886                                         }\r
887                                 }\r
888                                 return cell;\r
889                         }\r
890                 }\r
891                 return null;\r
892         }\r
893         \r
894         \r
895         \r
896         public static class TableViewerEditor extends ColumnViewerEditor {\r
897                 /**\r
898                  * This viewer's table editor.\r
899                  */\r
900                 private TableEditor tableEditor;\r
901                 private TableViewerFocusCellManager focusCellManager;\r
902                 private int feature;\r
903 \r
904                 /**\r
905                  * @param viewer\r
906                  *            the viewer the editor is attached to\r
907                  * @param focusCellManager\r
908                  *            the cell focus manager if one used or <code>null</code>\r
909                  * @param editorActivationStrategy\r
910                  *            the strategy used to decide about the editor activation\r
911                  * @param feature\r
912                  *            the feature mask\r
913                  */\r
914                 TableViewerEditor(TableViewer viewer,\r
915                                 TableViewerFocusCellManager focusCellManager,\r
916                                 ColumnViewerEditorActivationStrategy editorActivationStrategy,\r
917                                 int feature) {\r
918                         super(viewer, editorActivationStrategy, feature);\r
919                         this.feature = feature;\r
920                         tableEditor = new TableEditor(viewer.getTable());\r
921                         this.focusCellManager = focusCellManager;\r
922                 }\r
923 \r
924                 /**\r
925                  * Create a customized editor with focusable cells\r
926                  * \r
927                  * @param viewer\r
928                  *            the viewer the editor is created for\r
929                  * @param focusCellManager\r
930                  *            the cell focus manager if one needed else\r
931                  *            <code>null</code>\r
932                  * @param editorActivationStrategy\r
933                  *            activation strategy to control if an editor activated\r
934                  * @param feature\r
935                  *            bit mask controlling the editor\r
936                  *            <ul>\r
937                  *            <li>{@link ColumnViewerEditor#DEFAULT}</li>\r
938                  *            <li>{@link ColumnViewerEditor#TABBING_CYCLE_IN_ROW}</li>\r
939                  *            <li>{@link ColumnViewerEditor#TABBING_HORIZONTAL}</li>\r
940                  *            <li>\r
941                  *            {@link ColumnViewerEditor#TABBING_MOVE_TO_ROW_NEIGHBOR}</li>\r
942                  *            <li>{@link ColumnViewerEditor#TABBING_VERTICAL}</li>\r
943                  *            </ul>\r
944                  * @see #create(TableViewer, ColumnViewerEditorActivationStrategy, int)\r
945                  */\r
946                 public static void create(TableViewer viewer,\r
947                                 TableViewerFocusCellManager focusCellManager,\r
948                                 ColumnViewerEditorActivationStrategy editorActivationStrategy,\r
949                                 int feature) {\r
950                         TableViewerEditor editor = new TableViewerEditor(viewer,\r
951                                         focusCellManager, editorActivationStrategy, feature);\r
952                         viewer.setColumnViewerEditor(editor);\r
953                         if (focusCellManager != null) {\r
954                                 try {\r
955                                         Method m = focusCellManager.getClass().getSuperclass()\r
956                                                         .getDeclaredMethod("init", null);\r
957                                         m.setAccessible(true);\r
958                                         m.invoke(focusCellManager, null);\r
959                                 } catch (SecurityException e) {\r
960                                         e.printStackTrace();\r
961                                 } catch (IllegalArgumentException e) {\r
962                                         e.printStackTrace();\r
963                                 } catch (IllegalAccessException e) {\r
964                                         e.printStackTrace();\r
965                                 } catch (NoSuchMethodException e) {\r
966                                         e.printStackTrace();\r
967                                 } catch (InvocationTargetException e) {\r
968                                         e.printStackTrace();\r
969                                 }\r
970                                 // focusCellManager.init();\r
971                         }\r
972                 }\r
973 \r
974                 /**\r
975                  * Create a customized editor whose activation process is customized\r
976                  * \r
977                  * @param viewer\r
978                  *            the viewer the editor is created for\r
979                  * @param editorActivationStrategy\r
980                  *            activation strategy to control if an editor activated\r
981                  * @param feature\r
982                  *            bit mask controlling the editor\r
983                  *            <ul>\r
984                  *            <li>{@link ColumnViewerEditor#DEFAULT}</li>\r
985                  *            <li>{@link ColumnViewerEditor#TABBING_CYCLE_IN_ROW}</li>\r
986                  *            <li>{@link ColumnViewerEditor#TABBING_HORIZONTAL}</li>\r
987                  *            <li>\r
988                  *            {@link ColumnViewerEditor#TABBING_MOVE_TO_ROW_NEIGHBOR}</li>\r
989                  *            <li>{@link ColumnViewerEditor#TABBING_VERTICAL}</li>\r
990                  *            </ul>\r
991                  */\r
992                 public static void create(TableViewer viewer,\r
993                                 ColumnViewerEditorActivationStrategy editorActivationStrategy,\r
994                                 int feature) {\r
995                         create(viewer, null, editorActivationStrategy, feature);\r
996                 }\r
997 \r
998                 protected void setEditor(Control w, Item item, int columnNumber) {\r
999                         tableEditor.setEditor(w, (TableItem) item, columnNumber);\r
1000                 }\r
1001 \r
1002                 protected void setLayoutData(LayoutData layoutData) {\r
1003                         tableEditor.grabHorizontal = layoutData.grabHorizontal;\r
1004                         tableEditor.horizontalAlignment = layoutData.horizontalAlignment;\r
1005                         tableEditor.minimumWidth = layoutData.minimumWidth;\r
1006                 }\r
1007 \r
1008                 public ViewerCell getFocusCell() {\r
1009                         if (focusCellManager != null) {\r
1010                                 return focusCellManager.getFocusCell();\r
1011                         }\r
1012                         return super.getFocusCell();\r
1013                 }\r
1014 \r
1015                 protected void updateFocusCell(ViewerCell focusCell,\r
1016                                 ColumnViewerEditorActivationEvent event) {\r
1017                         // Update the focus cell when we activated the editor with these 2\r
1018                         // events\r
1019                         if (event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC\r
1020                                         || event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL) {\r
1021                                 if (focusCellManager != null) {\r
1022                                         try {\r
1023                                                 if (DEBUG)System.err.println("FOCUS CELL: " + focusCell);\r
1024                                                 \r
1025                                                 Method m = AbstractTableViewer.class.getDeclaredMethod(\r
1026                                                                 "getSelectionFromWidget", null);\r
1027                                                 m.setAccessible(true);\r
1028                                                 List l = (List) m.invoke(getViewer(), null);\r
1029                                                 if (focusCellManager != null) {\r
1030                                                         m = focusCellManager\r
1031                                                                         .getClass()\r
1032                                                                         .getSuperclass()\r
1033                                                                         .getDeclaredMethod("setFocusCell",\r
1034                                                                                         new Class[] { ViewerCell.class });\r
1035                                                         m.setAccessible(true);\r
1036                                                         m.invoke(focusCellManager,\r
1037                                                                         new Object[] { focusCell });\r
1038                                                 }\r
1039                                                 if (!l.contains(focusCell.getElement())) {\r
1040                                                         getViewer().setSelection(\r
1041                                                                         new StructuredSelection(focusCell\r
1042                                                                                         .getElement()));\r
1043                                                 }\r
1044                                         } catch (SecurityException e) {\r
1045                                                 e.printStackTrace();\r
1046                                         } catch (IllegalArgumentException e) {\r
1047                                                 e.printStackTrace();\r
1048                                         } catch (IllegalAccessException e) {\r
1049                                                 e.printStackTrace();\r
1050                                         } catch (NoSuchMethodException e) {\r
1051                                                 e.printStackTrace();\r
1052                                         } catch (InvocationTargetException e) {\r
1053                                                 e.printStackTrace();\r
1054                                         }\r
1055                                 }\r
1056                         }\r
1057                 }\r
1058 \r
1059                 protected void processTraverseEvent(int columnIndex, ViewerRow row,\r
1060                                 TraverseEvent event) {\r
1061                         ViewerCell cell2edit = null;\r
1062                         if (event.detail == SWT.TRAVERSE_TAB_PREVIOUS) {\r
1063                                 event.doit = false;\r
1064                                 if ((event.stateMask & SWT.CTRL) == SWT.CTRL\r
1065                                                 && (feature & TABBING_VERTICAL) == TABBING_VERTICAL) {\r
1066                                         cell2edit = searchCellAboveBelow(row, getViewer(),\r
1067                                                         columnIndex, true);\r
1068                                 } else if ((feature & TABBING_HORIZONTAL) == TABBING_HORIZONTAL) {\r
1069                                         cell2edit = searchPreviousCell(row,\r
1070                                                         row.getCell(columnIndex), row.getCell(columnIndex),\r
1071                                                         getViewer());\r
1072                                 }\r
1073                         } else if (event.detail == SWT.TRAVERSE_TAB_NEXT) {\r
1074                                 event.doit = false;\r
1075                                 if ((event.stateMask & SWT.CTRL) == SWT.CTRL\r
1076                                                 && (feature & TABBING_VERTICAL) == TABBING_VERTICAL) {\r
1077                                         cell2edit = searchCellAboveBelow(row, getViewer(),\r
1078                                                         columnIndex, false);\r
1079                                 } else if ((feature & TABBING_HORIZONTAL) == TABBING_HORIZONTAL) {\r
1080                                         cell2edit = searchNextCell(row, row.getCell(columnIndex),\r
1081                                                         row.getCell(columnIndex), getViewer());\r
1082                                 }\r
1083                         }\r
1084                         if (DEBUG) System.err.println("NEXT CELL: " + cell2edit);\r
1085                         if (cell2edit != null) {\r
1086                                 getViewer().getControl().setRedraw(false);\r
1087                                 ColumnViewerEditorActivationEvent acEvent = new ColumnViewerEditorActivationEvent(\r
1088                                                 cell2edit, event);\r
1089                                 try {\r
1090                                         Method m = ColumnViewer.class\r
1091                                                         .getDeclaredMethod(\r
1092                                                                         "triggerEditorActivationEvent",\r
1093                                                                         new Class[] { ColumnViewerEditorActivationEvent.class });\r
1094                                         m.setAccessible(true);\r
1095                                         m.invoke(getViewer(), new Object[] { acEvent });\r
1096                                 } catch (SecurityException e) {\r
1097                                         e.printStackTrace();\r
1098                                 } catch (NoSuchMethodException e) {\r
1099                                         e.printStackTrace();\r
1100                                 } catch (IllegalArgumentException e) {\r
1101                                         e.printStackTrace();\r
1102                                 } catch (IllegalAccessException e) {\r
1103                                         e.printStackTrace();\r
1104                                 } catch (InvocationTargetException e) {\r
1105                                         e.printStackTrace();\r
1106                                 }\r
1107                                 getViewer().getControl().setRedraw(true);\r
1108                         }\r
1109                 }\r
1110 \r
1111                 private ViewerCell searchCellAboveBelow(ViewerRow row,\r
1112                                 ColumnViewer viewer, int columnIndex, boolean above) {\r
1113                         ViewerCell rv = null;\r
1114                         ViewerRow newRow = null;\r
1115                         if (above) {\r
1116                                 newRow = row.getNeighbor(ViewerRow.ABOVE, false);\r
1117                         } else {\r
1118                                 newRow = row.getNeighbor(ViewerRow.BELOW, false);\r
1119                         }\r
1120                         try {\r
1121                                 if (newRow != null) {\r
1122                                         Method m = ColumnViewer.class.getDeclaredMethod(\r
1123                                                         "getViewerColumn", new Class[] { int.class });\r
1124                                         m.setAccessible(true);\r
1125                                         ViewerColumn column = (ViewerColumn) m.invoke(viewer,\r
1126                                                         new Object[] { new Integer(columnIndex) });\r
1127                                         m = ViewerColumn.class.getDeclaredMethod(\r
1128                                                         "getEditingSupport", null);\r
1129                                         m.setAccessible(true);\r
1130                                         EditingSupport es = (EditingSupport) m.invoke(column, null);\r
1131                                         if (column != null && es != null) {\r
1132                                                 m = EditingSupport.class.getDeclaredMethod("canEdit",\r
1133                                                                 new Class[] { Object.class });\r
1134                                                 m.setAccessible(true);\r
1135                                                 Boolean b = (Boolean) m.invoke(es,\r
1136                                                                 new Object[] { newRow.getItem().getData() });\r
1137                                                 if (b.booleanValue()) {\r
1138                                                         rv = newRow.getCell(columnIndex);\r
1139                                                 }\r
1140                                         } else {\r
1141                                                 rv = searchCellAboveBelow(newRow, viewer, columnIndex,\r
1142                                                                 above);\r
1143                                         }\r
1144                                 }\r
1145                         } catch (Exception e) {\r
1146                                 e.printStackTrace();\r
1147                         }\r
1148                         return rv;\r
1149                 }\r
1150 \r
1151                 private ViewerCell searchPreviousCell(ViewerRow row,\r
1152                                 ViewerCell currentCell, ViewerCell originalCell,\r
1153                                 ColumnViewer viewer) {\r
1154                         ViewerCell rv = null;\r
1155                         ViewerCell previousCell;\r
1156                         if (currentCell != null) {\r
1157                                 previousCell = getNeighbor(currentCell, ViewerCell.LEFT, true);\r
1158                         } else {\r
1159                                 if (row.getColumnCount() != 0) {\r
1160                                         previousCell = row.getCell(getCreationIndex(row,\r
1161                                                         row.getColumnCount() - 1));\r
1162                                 } else {\r
1163                                         previousCell = row.getCell(0);\r
1164                                 }\r
1165                         }\r
1166                         // No endless loop\r
1167                         if (originalCell.equals(previousCell)) {\r
1168                                 return null;\r
1169                         }\r
1170                         if (previousCell != null) {\r
1171                                 if (isCellEditable(viewer, previousCell)) {\r
1172                                         rv = previousCell;\r
1173                                 } else {\r
1174                                         rv = searchPreviousCell(row, previousCell, originalCell,\r
1175                                                         viewer);\r
1176                                 }\r
1177                         } else {\r
1178                                 if ((feature & TABBING_CYCLE_IN_ROW) == TABBING_CYCLE_IN_ROW) {\r
1179                                         rv = searchPreviousCell(row, null, originalCell, viewer);\r
1180                                 } else if ((feature & TABBING_MOVE_TO_ROW_NEIGHBOR) == TABBING_MOVE_TO_ROW_NEIGHBOR) {\r
1181                                         ViewerRow rowAbove = row\r
1182                                                         .getNeighbor(ViewerRow.ABOVE, false);\r
1183                                         if (rowAbove != null) {\r
1184                                                 rv = searchPreviousCell(rowAbove, null, originalCell,\r
1185                                                                 viewer);\r
1186                                         }\r
1187                                 }\r
1188                         }\r
1189                         return rv;\r
1190                 }\r
1191 \r
1192                 private ViewerCell searchNextCell(ViewerRow row,\r
1193                                 ViewerCell currentCell, ViewerCell originalCell,\r
1194                                 ColumnViewer viewer) {\r
1195                         ViewerCell rv = null;\r
1196                         ViewerCell nextCell;\r
1197                         if (currentCell != null) {\r
1198                                 nextCell = getNeighbor(currentCell, ViewerCell.RIGHT, true);\r
1199                         } else {\r
1200                                 nextCell = row.getCell(getCreationIndex(row, 0));\r
1201                         }\r
1202                         // No endless loop\r
1203                         if (originalCell.equals(nextCell)) {\r
1204                                 return null;\r
1205                         }\r
1206                         if (nextCell != null) {\r
1207                                 if (isCellEditable(viewer, nextCell)) {\r
1208                                         rv = nextCell;\r
1209                                 } else {\r
1210                                         rv = searchNextCell(row, nextCell, originalCell, viewer);\r
1211                                 }\r
1212                         } else {\r
1213                                 if ((feature & TABBING_CYCLE_IN_ROW) == TABBING_CYCLE_IN_ROW) {\r
1214                                         rv = searchNextCell(row, null, originalCell, viewer);\r
1215                                 } else if ((feature & TABBING_MOVE_TO_ROW_NEIGHBOR) == TABBING_MOVE_TO_ROW_NEIGHBOR) {\r
1216                                         ViewerRow rowBelow = row\r
1217                                                         .getNeighbor(ViewerRow.BELOW, false);\r
1218                                         if (rowBelow != null) {\r
1219                                                 rv = searchNextCell(rowBelow, null, originalCell,\r
1220                                                                 viewer);\r
1221                                         }\r
1222                                 }\r
1223                         }\r
1224                         return rv;\r
1225                 }\r
1226 \r
1227                 private boolean isCellEditable(ColumnViewer viewer, ViewerCell cell) {\r
1228                         try {\r
1229                                 Method m = ColumnViewer.class.getDeclaredMethod(\r
1230                                                 "getViewerColumn", new Class[] { int.class });\r
1231                                 m.setAccessible(true);\r
1232                                 ViewerColumn column = (ViewerColumn) m.invoke(viewer,\r
1233                                                 new Object[] { new Integer(cell.getColumnIndex()) });\r
1234                                 m = ViewerColumn.class.getDeclaredMethod("getEditingSupport",\r
1235                                                 null);\r
1236                                 m.setAccessible(true);\r
1237                                 EditingSupport es = (EditingSupport) m.invoke(column, null);\r
1238                                 if (column != null && es != null) {\r
1239                                         m = EditingSupport.class.getDeclaredMethod("canEdit",\r
1240                                                         new Class[] { Object.class });\r
1241                                         m.setAccessible(true);\r
1242                                         // return true;\r
1243                                         Boolean b = (Boolean) m.invoke(es,\r
1244                                                         new Object[] { cell.getElement() });\r
1245                                         return b.booleanValue();\r
1246                                 }\r
1247                         } catch (Exception e) {\r
1248                                 e.printStackTrace();\r
1249                         }\r
1250                         return false;\r
1251                 }\r
1252         }\r
1253         \r
1254         // Reimplementation of ViewerCell-Methods\r
1255         private static int getVisualIndex(ViewerRow row, int creationIndex) {\r
1256                 TableItem item = (TableItem) row.getItem();\r
1257                 int[] order = item.getParent().getColumnOrder();\r
1258                 for (int i = 0; i < order.length; i++) {\r
1259                         if (order[i] == creationIndex) {\r
1260                                 return i;\r
1261                         }\r
1262                 }\r
1263                 return creationIndex;\r
1264         }\r
1265         \r
1266         private static int getCreationIndex(ViewerRow row, int visualIndex) {\r
1267                 TableItem item = (TableItem) row.getItem();\r
1268                 if (item != null && !item.isDisposed() /*\r
1269                                                                                                  * && hasColumns() &&\r
1270                                                                                                  * isValidOrderIndex\r
1271                                                                                                  * (visualIndex)\r
1272                                                                                                  */) {\r
1273                         return item.getParent().getColumnOrder()[visualIndex];\r
1274                 }\r
1275                 return visualIndex;\r
1276         }\r
1277         \r
1278         private static ViewerCell getCellAtVisualIndex(ViewerRow row,\r
1279                         int visualIndex) {\r
1280                 return getCell(row, getCreationIndex(row, visualIndex));\r
1281         }\r
1282 \r
1283         private static boolean isVisible(ViewerCell cell) {\r
1284                 return getWidth(cell) > 0;\r
1285         }\r
1286 \r
1287         private static int getWidth(ViewerCell cell) {\r
1288                 TableItem item = (TableItem) cell.getViewerRow().getItem();\r
1289                 return item.getParent().getColumn(cell.getColumnIndex()).getWidth();\r
1290         }\r
1291 \r
1292         private static ViewerCell getCell(ViewerRow row, int index) {\r
1293                 return row.getCell(index);\r
1294         }\r
1295         \r
1296         \r
1297 }\r