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