]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.g3d/src/org/simantics/g3d/property/AnnotatedPropertyTabContributorFactory.java
Compiler warning elimination
[simantics/3d.git] / org.simantics.g3d / src / org / simantics / g3d / property / AnnotatedPropertyTabContributorFactory.java
index c0ea36e9005351f57075256e79aa664ace4281e5..7e3f85333bb88022ce5038e43670bdf0ab792346 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2012, 2013 Association for Decentralized Information Management in\r
- * Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.g3d.property;\r
-\r
-import java.lang.annotation.Annotation;\r
-import java.lang.reflect.Field;\r
-import java.lang.reflect.InvocationTargetException;\r
-import java.lang.reflect.Method;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.LinkedHashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-\r
-import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.viewers.AbstractTableViewer;\r
-import org.eclipse.jface.viewers.CellEditor;\r
-import org.eclipse.jface.viewers.CellEditor.LayoutData;\r
-import org.eclipse.jface.viewers.CellLabelProvider;\r
-import org.eclipse.jface.viewers.CellNavigationStrategy;\r
-import org.eclipse.jface.viewers.ColumnViewer;\r
-import org.eclipse.jface.viewers.ColumnViewerEditor;\r
-import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;\r
-import org.eclipse.jface.viewers.ColumnViewerEditorActivationListener;\r
-import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;\r
-import org.eclipse.jface.viewers.ColumnViewerEditorDeactivationEvent;\r
-import org.eclipse.jface.viewers.EditingSupport;\r
-import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;\r
-import org.eclipse.jface.viewers.ISelection;\r
-import org.eclipse.jface.viewers.ISelectionChangedListener;\r
-import org.eclipse.jface.viewers.ISelectionProvider;\r
-import org.eclipse.jface.viewers.IStructuredContentProvider;\r
-import org.eclipse.jface.viewers.SelectionChangedEvent;\r
-import org.eclipse.jface.viewers.StructuredSelection;\r
-import org.eclipse.jface.viewers.TableViewer;\r
-import org.eclipse.jface.viewers.TableViewerColumn;\r
-import org.eclipse.jface.viewers.TableViewerFocusCellManager;\r
-import org.eclipse.jface.viewers.TextCellEditor;\r
-import org.eclipse.jface.viewers.Viewer;\r
-import org.eclipse.jface.viewers.ViewerCell;\r
-import org.eclipse.jface.viewers.ViewerColumn;\r
-import org.eclipse.jface.viewers.ViewerRow;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.custom.TableEditor;\r
-import org.eclipse.swt.events.TraverseEvent;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Control;\r
-import org.eclipse.swt.widgets.Display;\r
-import org.eclipse.swt.widgets.Event;\r
-import org.eclipse.swt.widgets.Item;\r
-import org.eclipse.swt.widgets.TableColumn;\r
-import org.eclipse.swt.widgets.TableItem;\r
-import org.eclipse.ui.IWorkbenchSite;\r
-import org.simantics.db.management.ISessionContext;\r
-import org.simantics.g3d.property.annotations.CompoundGetPropertyValue;\r
-import org.simantics.g3d.property.annotations.CompoundSetPropertyValue;\r
-import org.simantics.g3d.property.annotations.GetPropertyValue;\r
-import org.simantics.g3d.property.annotations.PropertyTabBlacklist;\r
-import org.simantics.g3d.property.annotations.SetPropertyValue;\r
-import org.simantics.g3d.scenegraph.IG3DNode;\r
-import org.simantics.g3d.scenegraph.NodeMap;\r
-import org.simantics.g3d.scenegraph.NodeMapProvider;\r
-import org.simantics.g3d.scenegraph.base.INode;\r
-import org.simantics.g3d.scenegraph.base.NodeListener;\r
-import org.simantics.g3d.scenegraph.base.ParentNode;\r
-import org.simantics.g3d.scenegraph.structural.IStructuralNode;\r
-import org.simantics.g3d.tools.AdaptationUtils;\r
-import org.simantics.selectionview.IPropertyTab;\r
-import org.simantics.selectionview.IPropertyTab2;\r
-import org.simantics.utils.datastructures.Callback;\r
-import org.simantics.utils.datastructures.MapList;\r
-\r
-public class AnnotatedPropertyTabContributorFactory implements PropertyTabContributorFactory {\r
-\r
-       private static final boolean DEBUG = false;\r
-       \r
-       @SuppressWarnings("unchecked")\r
-       @Override\r
-       public List<PropertyTabContributor> getContributors(Object input) {\r
-               Map<String,IPropertyItem> items = new LinkedHashMap<String, IPropertyItem>();\r
-               List<String> blacklist = new ArrayList<String>();\r
-               try {\r
-                       collectItems(input.getClass(), items);\r
-                       collectBlacklist(input.getClass(), blacklist);\r
-               } catch (InstantiationException e) {\r
-                       // TODO Auto-generated catch block\r
-                       e.printStackTrace();\r
-               } catch (IllegalAccessException e) {\r
-                       // TODO Auto-generated catch block\r
-                       e.printStackTrace();\r
-               }\r
-               \r
-               if (items.size() == 0)\r
-                       return Collections.EMPTY_LIST;\r
-               \r
-               MapList<String, IPropertyItem> tabMap = new MapList<String, IPropertyItem>();\r
-               List<String> tabs = new ArrayList<String>();\r
-               for (String id : items.keySet()) {\r
-                       IPropertyItem item = items.get(id);\r
-                       tabMap.add(item.getTabId(), item);\r
-                       if (!tabs.contains(item.getTabId())) {\r
-                               tabs.add(item.getTabId());\r
-                               //System.out.println(item.tabId + " " + item.name + " " + item.id);\r
-                       }\r
-               }\r
-               for (String s : blacklist) {\r
-                       tabs.remove(s);\r
-               }\r
-               \r
-               List<PropertyTabContributor> contributors = new ArrayList<PropertyTabContributor>(tabs.size());\r
-               for (String tabId : tabs) {\r
-                       contributors.add(new AnnotatedPropertyTabContributor(tabId, tabMap.getValues(tabId)));\r
-               }\r
-               \r
-               return contributors;\r
-       }\r
-       \r
-       \r
-       private static void collectItems(Class<?> clazz, Map<String, IPropertyItem> items) throws InstantiationException, IllegalAccessException {\r
-                Class<?> superclass = clazz.getSuperclass();\r
-                if(superclass != null)\r
-                        collectItems(superclass, items);\r
-                \r
-                for (Method m : clazz.getDeclaredMethods()) {\r
-                        m.setAccessible(true);\r
-               for (Annotation annotation : m.getAnnotations()) {\r
-                       if (annotation.annotationType().equals(GetPropertyValue.class)) {\r
-                               GetPropertyValue get = (GetPropertyValue)annotation;\r
-                               PropertyItem item = (PropertyItem)items.get(get.value());\r
-                               if (item == null) {\r
-                                       item = new PropertyItem(get.value());\r
-                                       items.put(item.id, item);\r
-                               }\r
-\r
-                               item.getter = m;\r
-                               item.manipulatorClass = get.manipulator().newInstance().get(m,null);\r
-\r
-                               item.tabId = get.tabId();\r
-\r
-                               item.name = get.name();\r
-                               \r
-                               \r
-                       } else if (annotation.annotationType().equals(SetPropertyValue.class)) {\r
-                               SetPropertyValue set = (SetPropertyValue)annotation;\r
-                               PropertyItem item = (PropertyItem)items.get(set.value());\r
-                               if (item == null) {\r
-                                       item = new PropertyItem(set.value());\r
-                                       items.put(item.id, item);\r
-                               }\r
-                               \r
-                               item.setter = m;\r
-                       } else if (annotation.annotationType().equals(CompoundGetPropertyValue.class)) {\r
-                               CompoundGetPropertyValue get = (CompoundGetPropertyValue)annotation;\r
-                               CompoundPropertyItem item = (CompoundPropertyItem)items.get(get.value());\r
-                               if (item == null) {\r
-                                       item = new CompoundPropertyItem(get.value());\r
-                                       items.put(item.id, item);\r
-                               }\r
-\r
-                               item.getter = m;\r
-                               item.manipulatorFactory = get.manipulator().newInstance();\r
-\r
-                               item.tabId = get.tabId();\r
-\r
-                               item.name = get.name();\r
-                       } else if (annotation.annotationType().equals(CompoundSetPropertyValue.class)) {\r
-                               CompoundSetPropertyValue set = (CompoundSetPropertyValue)annotation;\r
-                               CompoundPropertyItem item = (CompoundPropertyItem)items.get(set.value());\r
-                               if (item == null) {\r
-                                       item = new CompoundPropertyItem(set.value());\r
-                                       items.put(item.id, item);\r
-                               }\r
-                               \r
-                               item.setter = m;\r
-                       }\r
-               }\r
-                }\r
-               \r
-               \r
-       }\r
-       \r
-       private static void collectBlacklist(Class<?> clazz, List<String> blacklist) throws InstantiationException, IllegalAccessException {\r
-                Class<?> superclass = clazz.getSuperclass();\r
-                if(superclass != null)\r
-                        collectBlacklist(superclass, blacklist);\r
-                \r
-                PropertyTabBlacklist ann = clazz.getAnnotation(PropertyTabBlacklist.class);\r
-                if (ann == null)\r
-                        return;\r
-                String s = ann.value();\r
-                if (s == null)\r
-                        return;\r
-                if (s.length() == 0)\r
-                        return;\r
-                for (String item : s.split(";")) {\r
-                        blacklist.add(item);\r
-                }\r
-                \r
-               \r
-       }\r
-       \r
-       private static Map<PropertyItem, PropertyManipulator> createManipulators(CompoundPropertyItem item, Object obj) {\r
-               try {\r
-                       \r
-                       Map<String,Object> map = (Map<String, Object>)item.getter.invoke(obj);\r
-                       Map<PropertyItem, PropertyManipulator> result = new HashMap<AnnotatedPropertyTabContributorFactory.PropertyItem, PropertyManipulator>();\r
-                       for (String key : map.keySet()) {\r
-                               MethodWithMapValueProvider provider = new MethodWithMapValueProvider(item.getter, item.setter, key);\r
-                               Class<? extends PropertyManipulator> clazz = item.manipulatorFactory.get(null,map.get(key));\r
-                               PropertyManipulator manipulator = clazz.getConstructor(ValueProvider.class,Object.class).newInstance(provider,obj);\r
-                               PropertyItem i = new PropertyItem(item.id+"."+key);\r
-                               i.getter = item.getter;\r
-                               i.setter = item.setter;\r
-                               i.name = key;\r
-                               i.tabId = item.tabId;\r
-                               result.put(i,manipulator);\r
-                       }\r
-                       return result;\r
-               } catch (Exception e) {\r
-                       e.printStackTrace();\r
-                       return Collections.EMPTY_MAP;\r
-               } \r
-               \r
-       }\r
-       \r
-       private static PropertyManipulator createManipulator(PropertyItem item, Object obj) {\r
-               try {\r
-                       MethodValueProvider provider = new MethodValueProvider(item.getter, item.setter);\r
-                       PropertyManipulator manipulator = item.manipulatorClass.getConstructor(ValueProvider.class,Object.class).newInstance(provider,obj);\r
-                       return manipulator;\r
-               } catch (Exception e) {\r
-                       e.printStackTrace();\r
-                       return null;\r
-               } \r
-       }\r
-       \r
-       private static interface IPropertyItem {\r
-               public String getTabId();\r
-       }\r
-       \r
-       private static class PropertyItem implements IPropertyItem{\r
-               private String id;\r
-               private String name;\r
-               private String tabId;\r
-               private Method getter;\r
-               private Method setter;\r
-               private Class<? extends PropertyManipulator> manipulatorClass;\r
-               \r
-               \r
-               public PropertyItem(String id) {\r
-                       if (id == null)\r
-                               throw new NullPointerException();\r
-                       this.id = id;\r
-               }\r
-               \r
-               @Override\r
-               public int hashCode() {\r
-                       return id.hashCode();\r
-               }\r
-               \r
-               @Override\r
-               public String getTabId() {\r
-                       return tabId;\r
-               }\r
-       }\r
-       \r
-       private static class CompoundPropertyItem implements IPropertyItem{\r
-               private String id;\r
-               private String name;\r
-               private String tabId;\r
-               private Method getter;\r
-               private Method setter;\r
-               private PropertyManipulatorFactory manipulatorFactory;\r
-               \r
-               \r
-               public CompoundPropertyItem(String id) {\r
-                       if (id == null)\r
-                               throw new NullPointerException();\r
-                       this.id = id;\r
-               }\r
-               \r
-               @Override\r
-               public int hashCode() {\r
-                       return id.hashCode();\r
-               }\r
-               \r
-               @Override\r
-               public String getTabId() {\r
-                       return tabId;\r
-               }\r
-       }\r
-       \r
-       private static class AnnotatedPropertyTabContributor implements PropertyTabContributor {\r
-               private String id; \r
-               List<IPropertyItem> items;\r
-               \r
-               public AnnotatedPropertyTabContributor(String id, List<IPropertyItem> items) {\r
-                       if (id == null)\r
-                               throw new NullPointerException();\r
-                       this.id = id;\r
-                       this.items = items;\r
-               }\r
-               \r
-               @Override\r
-               public IPropertyTab create(Composite parent, IWorkbenchSite site,\r
-                               ISessionContext context, Object input) {\r
-                       AnnotatedPropertyTab tab = new AnnotatedPropertyTab(id, items);\r
-                       tab.createControl(parent, context);\r
-                       return tab;\r
-               }\r
-               \r
-               @Override\r
-               public String getId() {\r
-                       return id;\r
-               }\r
-               \r
-       }\r
-       \r
-       private static class AnnotatedPropertyTab implements IPropertyTab2, NodeListener {\r
-               //private String id; \r
-               List<IPropertyItem> contibutedItems;\r
-               List<PropertyItem> resolvedItems = new ArrayList<PropertyItem>();\r
-               private Map<PropertyItem,PropertyManipulator> manipulators = new HashMap<PropertyItem, PropertyManipulator>();\r
-               \r
-               private TableViewer viewer;\r
-               \r
-               private IG3DNode node;\r
-               private NodeMap<?> nodeMap;\r
-               \r
-               private List<TableViewerColumn> valueColumns = new ArrayList<TableViewerColumn>();\r
-               \r
-               public AnnotatedPropertyTab(String id, List<IPropertyItem> items) {\r
-                       //this.id = id;\r
-                       this.contibutedItems = items;\r
-                       \r
-                                       \r
-               }\r
-               \r
-               @Override\r
-               public void createControl(Composite parent, ISessionContext context) {\r
-                       //parent.setLayout(new FillLayout());\r
-                       viewer = new TableViewer(parent, SWT.FULL_SELECTION | SWT.SINGLE);\r
-                       \r
-                       GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(viewer.getTable());\r
-                       \r
-                       //viewer.setLabelProvider(new AnnotatedTableLabelProvider(object))\r
-                       \r
-                       viewer.setContentProvider(new PropertyItemContentsProvider());\r
-                       \r
-                       TableViewerColumn name = new TableViewerColumn(viewer, SWT.LEFT);\r
-                       //TableViewerColumn value = new TableViewerColumn(viewer, SWT.LEFT);\r
-                       name.setLabelProvider(new PropertyItemNameProvider());\r
-                       //value.setLabelProvider(new PropertyValueLabelProvider(null));\r
-                       name.getColumn().setText("Property");\r
-                       //value.getColumn().setText("Value");\r
-                       name.getColumn().setWidth(200);\r
-                       //value.getColumn().setWidth(200);\r
-                       name.getViewer().addSelectionChangedListener(new ISelectionChangedListener() {\r
-                               \r
-                               @Override\r
-                               public void selectionChanged(SelectionChangedEvent event) {\r
-                                       PropertyItem item = AdaptationUtils.adaptToSingle(event.getSelection(),PropertyItem.class);\r
-                                       if (item != null) {\r
-                                               PropertyManipulator manipulator = manipulators.get(item);//createManipulator(item, null);\r
-                                               for (int i = 0; i < valueColumns.size(); i++) {\r
-                                                       TableViewerColumn c = valueColumns.get(i);\r
-                                                       if (i < manipulator.getValueCount()) {\r
-                                                               c.getColumn().setText(manipulator.getDescription(i));\r
-                                                       } else {\r
-                                                               c.getColumn().setText("");\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       \r
-                               }\r
-                       });\r
-                       \r
-                       int valueCount = 0;\r
-                       for (IPropertyItem item : contibutedItems) {\r
-                               if (item instanceof PropertyItem) {\r
-                                       PropertyManipulator manipulator = createManipulator((PropertyItem)item, null);\r
-                                       if (manipulator == null)\r
-                                               continue;\r
-                                       if (valueCount < manipulator.getValueCount())\r
-                                               valueCount = manipulator.getValueCount();\r
-                               } else if (item instanceof CompoundPropertyItem) {\r
-                                       if (valueCount < 1)\r
-                                               valueCount = 1;\r
-                               }\r
-                       }\r
-                       for (int i = 0; i < valueCount; i++) {\r
-                               TableViewerColumn value = new TableViewerColumn(viewer, SWT.LEFT);\r
-                               //value.getColumn().setText("Value " + (i+1));\r
-                               value.getColumn().setText("");\r
-                               value.getColumn().setWidth(200);\r
-                               valueColumns.add(value);\r
-                               //value.setEditingSupport(new )\r
-                       }\r
-                       viewer.getTable().setHeaderVisible(true);\r
-                       viewer.getTable().setLinesVisible(true);\r
-                       viewer.addSelectionChangedListener(new ISelectionChangedListener() {\r
-                               \r
-                               @Override\r
-                               public void selectionChanged(SelectionChangedEvent event) {\r
-                                       PropertyItem item = AdaptationUtils.adaptToSingle(event.getSelection(), PropertyItem.class);\r
-                                       selectedItem = item;\r
-                                       if (!manipulators.get(selectedItem).getEditMode())\r
-                                               manipulators.get(selectedItem).setEditMode(true);\r
-                                       \r
-\r
-                                       for (IPropertyItem i : delayedUpdate) {\r
-                                               if (!i.equals(selectedItem)) {\r
-                                                       manipulators.get(i).setEditMode(false);\r
-                                                       viewer.update(i,null);\r
-                                               }\r
-                                       }\r
-                                       if (delayedUpdate.contains(selectedItem)) {\r
-                                               delayedUpdate.clear();\r
-                                               delayedUpdate.add(selectedItem);\r
-                                       } else {\r
-                                               delayedUpdate.clear();\r
-                                       }\r
-                               }\r
-                       });\r
-                       \r
-                       CellNavigationStrategy nStrategy = new CellNavigationStrategy() {\r
-                               private ViewerCell internalFindSelectedCell(\r
-                                               ColumnViewer viewer, ViewerCell currentSelectedCell,\r
-                                               Event event) {\r
-                                       switch (event.keyCode) {\r
-                                       case SWT.ARROW_UP:\r
-                                               if (currentSelectedCell != null) {\r
-                                                       return getNeighbor(currentSelectedCell,\r
-                                                                       ViewerCell.ABOVE, false);\r
-                                               }\r
-                                               break;\r
-                                       case SWT.ARROW_DOWN:\r
-                                               if (currentSelectedCell != null) {\r
-                                                       return getNeighbor(currentSelectedCell,\r
-                                                                       ViewerCell.BELOW, false);\r
-                                               }\r
-                                               break;\r
-                                       case SWT.ARROW_LEFT:\r
-                                               if (currentSelectedCell != null) {\r
-                                                       return getNeighbor(currentSelectedCell,\r
-                                                                       ViewerCell.LEFT, true);\r
-                                               }\r
-                                               break;\r
-                                       case SWT.ARROW_RIGHT:\r
-                                               if (currentSelectedCell != null) {\r
-                                                       return getNeighbor(currentSelectedCell,\r
-                                                                       ViewerCell.RIGHT, true);\r
-                                               }\r
-                                               break;\r
-                                       }\r
-                                       return null;\r
-                               }\r
-                               \r
-                               public ViewerCell findSelectedCell(ColumnViewer viewer,\r
-                                               ViewerCell currentSelectedCell, Event event) {\r
-                                       ViewerCell cell = internalFindSelectedCell(viewer,\r
-                                                       currentSelectedCell, event);\r
-                                       if (cell != null) {\r
-                                               TableColumn t = AnnotatedPropertyTab.this.viewer.getTable().getColumn(\r
-                                                               cell.getColumnIndex());\r
-                                               AnnotatedPropertyTab.this.viewer.getTable().showColumn(t);\r
-                                       }\r
-                                       return cell;\r
-                               }\r
-                       };\r
-                       \r
-                       TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(\r
-                                       viewer, new FocusCellOwnerDrawHighlighter(viewer));\r
-                       try {\r
-                               Field f = focusCellManager.getClass().getSuperclass()\r
-                                               .getDeclaredField("navigationStrategy");\r
-                               f.setAccessible(true);\r
-                               f.set(focusCellManager, nStrategy);\r
-                       } catch (SecurityException e) {\r
-                               e.printStackTrace();\r
-                       } catch (NoSuchFieldException e) {\r
-                               e.printStackTrace();\r
-                       } catch (IllegalArgumentException e) {\r
-                               e.printStackTrace();\r
-                       } catch (IllegalAccessException e) {\r
-                               e.printStackTrace();\r
-                       }\r
-                       ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(\r
-                                       viewer) {\r
-                               protected boolean isEditorActivationEvent(\r
-                                               ColumnViewerEditorActivationEvent event) {\r
-                                       return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL\r
-                                                       || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION\r
-                                                       || (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR)\r
-                                                       || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;\r
-                               }\r
-                       };\r
-                       TableViewerEditor.create(viewer, focusCellManager, actSupport,\r
-                                       ColumnViewerEditor.TABBING_HORIZONTAL\r
-                                                       | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR\r
-                                                       | ColumnViewerEditor.TABBING_VERTICAL\r
-                                                       | ColumnViewerEditor.KEYBOARD_ACTIVATION);\r
-                       viewer.getColumnViewerEditor().addEditorActivationListener(\r
-                                       new ColumnViewerEditorActivationListener() {\r
-                                               public void afterEditorActivated(\r
-                                                               ColumnViewerEditorActivationEvent event) {\r
-                                               }\r
-\r
-                                               public void afterEditorDeactivated(\r
-                                                               ColumnViewerEditorDeactivationEvent event) {\r
-                                               }\r
-\r
-                                               public void beforeEditorActivated(\r
-                                                               ColumnViewerEditorActivationEvent event) {\r
-                                                       ViewerCell cell = (ViewerCell) event.getSource();\r
-                                                       viewer.getTable().showColumn(\r
-                                                                       viewer.getTable().getColumn(cell.getColumnIndex()));\r
-                                               }\r
-\r
-                                               public void beforeEditorDeactivated(\r
-                                                               ColumnViewerEditorDeactivationEvent event) {\r
-                                               }\r
-                                       });\r
-               }\r
-               \r
-               \r
-               \r
-               \r
-               private IPropertyItem selectedItem = null;\r
-               private Set<IPropertyItem> delayedUpdate = new HashSet<IPropertyItem>();\r
-               \r
-               \r
-               @Override\r
-               public void setInput(ISessionContext context, ISelection selection,\r
-                               boolean force) {\r
-                       Collection<IG3DNode> nodes = AdaptationUtils.adaptToCollection(selection, IG3DNode.class);\r
-                       if (nodes.size() != 1) {\r
-                               if (node != null) {\r
-                                       node.removeListener(this);\r
-                                       node = null;\r
-                               }\r
-                               return;\r
-                       }\r
-                       IG3DNode n = nodes.iterator().next();\r
-                       if (node != null) {\r
-                               if (!node.equals(n)) {\r
-                                       node.removeListener(this);\r
-                                       setInput(n);\r
-                               }\r
-                       } else {\r
-                               setInput(n);\r
-                       }\r
-               }\r
-               \r
-               \r
-               \r
-               private void setInput(IG3DNode node) {\r
-                       this.node = node;\r
-                       this.node.addListener(this);\r
-                       // resolve nodemap\r
-                       IG3DNode n = node;\r
-                       while (true) {\r
-                               if (n == null) {\r
-                                       nodeMap = null;\r
-                                       break;\r
-                               }\r
-                               if (n instanceof NodeMapProvider<?>) {\r
-                                       nodeMap = ((NodeMapProvider<?>) n).getNodeMap();\r
-                                       if (nodeMap != null)\r
-                                               break;\r
-                               }\r
-                               n = (IG3DNode)n.getParent();\r
-                       }\r
-                       boolean readOnly =  (node instanceof IStructuralNode && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot());\r
-                       // create label providers\r
-                       PropertyValueLabelProvider2 p = new PropertyValueLabelProvider2(this);\r
-                       int index = 0;\r
-                       for (TableViewerColumn c : valueColumns) {\r
-                               c.setLabelProvider(p);\r
-                               if (!readOnly) {\r
-                                       PropertyEditingSupport support = new PropertyEditingSupport(this, viewer, index++, nodeMap);\r
-                                       c.setEditingSupport(support);\r
-                               }\r
-                       }\r
-                       resolvedItems.clear();\r
-                       manipulators.clear();\r
-                       for (IPropertyItem item : contibutedItems) {\r
-                               if (item instanceof PropertyItem) {\r
-                                       resolvedItems.add((PropertyItem)item);\r
-                                       manipulators.put((PropertyItem)item, createManipulator((PropertyItem)item, node));\r
-                               }\r
-                               else {\r
-                                       CompoundPropertyItem compound = (CompoundPropertyItem)item;\r
-                                       Map<PropertyItem, PropertyManipulator> manipulators = createManipulators(compound, node);\r
-                                       for (PropertyItem i : manipulators.keySet()) {\r
-                                               resolvedItems.add(i);\r
-                                               this.manipulators.put(i, manipulators.get(i));\r
-                                       }\r
-                               }\r
-                       }\r
-                       \r
-                       viewer.getTable().setEnabled(!readOnly);\r
-                       viewer.setInput(resolvedItems);\r
-               }\r
-               \r
-               @Override\r
-               public void requestFocus() {\r
-                       viewer.getTable().forceFocus();\r
-               }\r
-               \r
-               @Override\r
-               public void dispose() {\r
-                       if (node != null) {\r
-                               node.removeListener(this);\r
-                               node = null;\r
-                       }\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public Control getControl() {\r
-                       return viewer.getTable();\r
-               }\r
-               \r
-               @Override\r
-               public ISelectionProvider getSelectionProvider() {\r
-                       return null;\r
-               }\r
-               \r
-               @Override\r
-               public boolean isDisposed() {\r
-                       return viewer.getTable().isDisposed();\r
-               }\r
-               \r
-               @Override\r
-               public <T extends INode> void nodeAdded(ParentNode<T> node,\r
-                               INode child, String rel) {\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public <T extends INode> void nodeRemoved(ParentNode<T> node,\r
-                               INode child, String rel) {\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public void propertyChanged(INode node, final String id) {\r
-//                     for (final PropertyItem item : items) {\r
-//                             if (item.id.equals(id)) {\r
-//                                     Display.getDefault().asyncExec(new Runnable() {\r
-//                                             \r
-//                                             @Override\r
-//                                             public void run() {\r
-//                                                     viewer.update(item, null);\r
-//                                                     \r
-//                                             }\r
-//                                     });\r
-//                             }\r
-//                     }\r
-                       if (Thread.currentThread() == Display.getDefault().getThread()) {\r
-                               if (DEBUG)System.out.println("Viewer refresh " + id);\r
-                               for (PropertyItem item : resolvedItems)\r
-                                       if (!item.equals(selectedItem))\r
-                                               viewer.refresh(item);\r
-                               if (selectedItem != null)\r
-                                       delayedUpdate.add(selectedItem);\r
-                       } else if (!editing){\r
-                               // running delayed refresh when a cell editor is active would cancel cell editing.\r
-                               Display.getDefault().asyncExec(new Runnable() {\r
-                                       @Override\r
-                                       public void run() {\r
-                                               if (viewer.getTable().isDisposed()) {\r
-                                                       if (AnnotatedPropertyTab.this.node != null)\r
-                                                               AnnotatedPropertyTab.this.node.removeListener(AnnotatedPropertyTab.this);\r
-                                                       return;\r
-                                               }\r
-                                               if (DEBUG) System.out.println("Viewer threaded refresh " + id);\r
-                                               for (PropertyItem item : resolvedItems)\r
-                                                       if (!item.equals(selectedItem))\r
-                                                               viewer.refresh(item);\r
-                                               if (selectedItem != null)\r
-                                                       delayedUpdate.add(selectedItem);\r
-                                               \r
-                                       }\r
-                               });\r
-                       } else {\r
-                               for (PropertyItem item : resolvedItems) {\r
-                                       delayedUpdate.add(item);\r
-                               }\r
-                       }\r
-                       \r
-               }\r
-               \r
-\r
-               \r
-               \r
-               \r
-               @Override\r
-               public void updatePartName(Callback<String> updateCallback) {\r
-                       if (node != null)\r
-                               updateCallback.run(node.toString()); \r
-                       \r
-               }\r
-               \r
-               public PropertyManipulator getManipulator(PropertyItem item) {\r
-                       return manipulators.get(item);\r
-               }\r
-               \r
-               private boolean editing = false;\r
-               \r
-               public void setEditing(boolean editing) {\r
-                       this.editing = editing;\r
-               }\r
-       }\r
-       \r
-       \r
-       \r
-       private static class PropertyEditingSupport extends EditingSupport {\r
-               AnnotatedPropertyTab tab;\r
-               int index;\r
-               NodeMap<?> nodeMap;\r
-               TableViewer viewer;\r
-               CellEditor editor;\r
-\r
-               public PropertyEditingSupport(AnnotatedPropertyTab tab, TableViewer viewer, int index, NodeMap<?> nodeMap) {\r
-                       super(viewer);\r
-                       this.tab = tab;\r
-                       this.index = index;\r
-                       this.viewer = viewer;\r
-                       this.nodeMap = nodeMap;\r
-               }\r
-               \r
-               @Override\r
-               protected boolean canEdit(Object element) {\r
-                       PropertyItem item = (PropertyItem)element;\r
-                       if (tab.getManipulator(item).getValueCount() <= index)\r
-                               return false;\r
-                       return (item.setter != null);\r
-               }\r
-               \r
-               @Override\r
-               protected CellEditor getCellEditor(Object element) {\r
-                       \r
-                       if (tab.getManipulator((PropertyItem)element).getValueCount() <= index)\r
-                               return null;\r
-                       if (editor == null)\r
-                               editor = new TextCellEditor(viewer.getTable(),SWT.NONE) {\r
-                               @Override\r
-                               public void activate() {\r
-                                       tab.setEditing(true);\r
-                               }\r
-                               \r
-                               @Override\r
-                               public void deactivate() {\r
-                                       super.deactivate();\r
-                                       tab.setEditing(false);\r
-                               }\r
-                       };\r
-                       if (DEBUG)System.err.println("CELL EDITOR: " + element);\r
-                       return editor;\r
-               }\r
-               \r
-               @Override\r
-               protected Object getValue(Object element) {\r
-                       PropertyItem item = (PropertyItem)element;\r
-                       PropertyManipulator manipulator = tab.getManipulator(item);//createManipulator(item, obj);\r
-                       if (manipulator.getValueCount() <= index)\r
-                               return null;\r
-                       Object value = manipulator.getValue(index);\r
-                       return value;\r
-               }\r
-               \r
-               @Override\r
-               protected void setValue(Object element, Object value) {\r
-                       \r
-                       PropertyItem item = (PropertyItem)element;\r
-                       PropertyManipulator manipulator = tab.getManipulator(item);//createManipulator(item, obj);\r
-                       if (manipulator.getValueCount() <= index)\r
-                               throw new IllegalAccessError("Editing value in index " + index + " is not allowed.");\r
-                       if (DEBUG)System.err.println("CELL SET VALUE: " + element + " " + value);\r
-                       manipulator.setValue((String)value,index);\r
-                       viewer.refresh(item);\r
-                       nodeMap.commit();\r
-                       \r
-               }\r
-               \r
-               \r
-\r
-       }\r
-       \r
-       private static class PropertyItemNameProvider extends CellLabelProvider {\r
-\r
-               \r
-               @Override\r
-               public void update(ViewerCell cell) {\r
-                       PropertyItem item = (PropertyItem)cell.getElement();\r
-\r
-                       if (item.name.length() > 0)\r
-                               cell.setText(item.name);\r
-                       else\r
-                               cell.setText(item.id);\r
-                       \r
-                       \r
-               }\r
-       }\r
-       \r
-       private static class PropertyValueLabelProvider2 extends CellLabelProvider {\r
-               AnnotatedPropertyTab tab;\r
-               //private Object object;\r
-               \r
-               public PropertyValueLabelProvider2(AnnotatedPropertyTab tab) {\r
-                       this.tab = tab;\r
-               }\r
-               \r
-               @Override\r
-               public void update(ViewerCell cell) {\r
-                       PropertyItem item = (PropertyItem)cell.getElement();\r
-                       int index = cell.getColumnIndex() -1;\r
-                       PropertyManipulator manipulator = tab.getManipulator(item);//createManipulator(item, object);\r
-                       if (manipulator.getValueCount() <= index)\r
-                               return;\r
-                       cell.setText(manipulator.getValue(index));\r
-               }\r
-       }\r
-       \r
-       private static class PropertyItemContentsProvider implements IStructuredContentProvider {\r
-               @SuppressWarnings("unchecked")\r
-               @Override\r
-               public Object[] getElements(Object inputElement) {\r
-                       List<PropertyItem> items = (List<PropertyItem>)inputElement;\r
-                       return items.toArray();\r
-               }\r
-               \r
-               @Override\r
-               public void dispose() {\r
-                       \r
-               }\r
-               \r
-               @Override\r
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
-                       \r
-               }\r
-       }\r
-       \r
-       \r
-       \r
-       private static ViewerCell getNeighbor(ViewerCell currentCell,\r
-                       int directionMask, boolean sameLevel) {\r
-               ViewerRow row;\r
-               if ((directionMask & ViewerCell.ABOVE) == ViewerCell.ABOVE) {\r
-                       row = currentCell.getViewerRow().getNeighbor(ViewerRow.ABOVE,\r
-                                       sameLevel);\r
-               } else if ((directionMask & ViewerCell.BELOW) == ViewerCell.BELOW) {\r
-                       row = currentCell.getViewerRow().getNeighbor(ViewerRow.BELOW,\r
-                                       sameLevel);\r
-               } else {\r
-                       row = currentCell.getViewerRow();\r
-               }\r
-               if (row != null) {\r
-                       int columnIndex;\r
-                       columnIndex = getVisualIndex(row, currentCell.getColumnIndex());\r
-                       int modifier = 0;\r
-                       if ((directionMask & ViewerCell.LEFT) == ViewerCell.LEFT) {\r
-                               modifier = -1;\r
-                       } else if ((directionMask & ViewerCell.RIGHT) == ViewerCell.RIGHT) {\r
-                               modifier = 1;\r
-                       }\r
-                       columnIndex += modifier;\r
-                       if (columnIndex >= 0 && columnIndex < row.getColumnCount()) {\r
-                               ViewerCell cell = getCellAtVisualIndex(row, columnIndex);\r
-                               if (cell != null) {\r
-                                       while (cell != null\r
-                                                       && columnIndex < row.getColumnCount() - 1\r
-                                                       && columnIndex > 0) {\r
-                                               if (isVisible(cell)) {\r
-                                                       break;\r
-                                               }\r
-                                               columnIndex += modifier;\r
-                                               cell = getCellAtVisualIndex(row, columnIndex);\r
-                                               if (cell == null) {\r
-                                                       break;\r
-                                               }\r
-                                       }\r
-                               }\r
-                               return cell;\r
-                       }\r
-               }\r
-               return null;\r
-       }\r
-       \r
-       \r
-       \r
-       public static class TableViewerEditor extends ColumnViewerEditor {\r
-               /**\r
-                * This viewer's table editor.\r
-                */\r
-               private TableEditor tableEditor;\r
-               private TableViewerFocusCellManager focusCellManager;\r
-               private int feature;\r
-\r
-               /**\r
-                * @param viewer\r
-                *            the viewer the editor is attached to\r
-                * @param focusCellManager\r
-                *            the cell focus manager if one used or <code>null</code>\r
-                * @param editorActivationStrategy\r
-                *            the strategy used to decide about the editor activation\r
-                * @param feature\r
-                *            the feature mask\r
-                */\r
-               TableViewerEditor(TableViewer viewer,\r
-                               TableViewerFocusCellManager focusCellManager,\r
-                               ColumnViewerEditorActivationStrategy editorActivationStrategy,\r
-                               int feature) {\r
-                       super(viewer, editorActivationStrategy, feature);\r
-                       this.feature = feature;\r
-                       tableEditor = new TableEditor(viewer.getTable());\r
-                       this.focusCellManager = focusCellManager;\r
-               }\r
-\r
-               /**\r
-                * Create a customized editor with focusable cells\r
-                * \r
-                * @param viewer\r
-                *            the viewer the editor is created for\r
-                * @param focusCellManager\r
-                *            the cell focus manager if one needed else\r
-                *            <code>null</code>\r
-                * @param editorActivationStrategy\r
-                *            activation strategy to control if an editor activated\r
-                * @param feature\r
-                *            bit mask controlling the editor\r
-                *            <ul>\r
-                *            <li>{@link ColumnViewerEditor#DEFAULT}</li>\r
-                *            <li>{@link ColumnViewerEditor#TABBING_CYCLE_IN_ROW}</li>\r
-                *            <li>{@link ColumnViewerEditor#TABBING_HORIZONTAL}</li>\r
-                *            <li>\r
-                *            {@link ColumnViewerEditor#TABBING_MOVE_TO_ROW_NEIGHBOR}</li>\r
-                *            <li>{@link ColumnViewerEditor#TABBING_VERTICAL}</li>\r
-                *            </ul>\r
-                * @see #create(TableViewer, ColumnViewerEditorActivationStrategy, int)\r
-                */\r
-               public static void create(TableViewer viewer,\r
-                               TableViewerFocusCellManager focusCellManager,\r
-                               ColumnViewerEditorActivationStrategy editorActivationStrategy,\r
-                               int feature) {\r
-                       TableViewerEditor editor = new TableViewerEditor(viewer,\r
-                                       focusCellManager, editorActivationStrategy, feature);\r
-                       viewer.setColumnViewerEditor(editor);\r
-                       if (focusCellManager != null) {\r
-                               try {\r
-                                       Method m = focusCellManager.getClass().getSuperclass()\r
-                                                       .getDeclaredMethod("init", null);\r
-                                       m.setAccessible(true);\r
-                                       m.invoke(focusCellManager, null);\r
-                               } catch (SecurityException e) {\r
-                                       e.printStackTrace();\r
-                               } catch (IllegalArgumentException e) {\r
-                                       e.printStackTrace();\r
-                               } catch (IllegalAccessException e) {\r
-                                       e.printStackTrace();\r
-                               } catch (NoSuchMethodException e) {\r
-                                       e.printStackTrace();\r
-                               } catch (InvocationTargetException e) {\r
-                                       e.printStackTrace();\r
-                               }\r
-                               // focusCellManager.init();\r
-                       }\r
-               }\r
-\r
-               /**\r
-                * Create a customized editor whose activation process is customized\r
-                * \r
-                * @param viewer\r
-                *            the viewer the editor is created for\r
-                * @param editorActivationStrategy\r
-                *            activation strategy to control if an editor activated\r
-                * @param feature\r
-                *            bit mask controlling the editor\r
-                *            <ul>\r
-                *            <li>{@link ColumnViewerEditor#DEFAULT}</li>\r
-                *            <li>{@link ColumnViewerEditor#TABBING_CYCLE_IN_ROW}</li>\r
-                *            <li>{@link ColumnViewerEditor#TABBING_HORIZONTAL}</li>\r
-                *            <li>\r
-                *            {@link ColumnViewerEditor#TABBING_MOVE_TO_ROW_NEIGHBOR}</li>\r
-                *            <li>{@link ColumnViewerEditor#TABBING_VERTICAL}</li>\r
-                *            </ul>\r
-                */\r
-               public static void create(TableViewer viewer,\r
-                               ColumnViewerEditorActivationStrategy editorActivationStrategy,\r
-                               int feature) {\r
-                       create(viewer, null, editorActivationStrategy, feature);\r
-               }\r
-\r
-               protected void setEditor(Control w, Item item, int columnNumber) {\r
-                       tableEditor.setEditor(w, (TableItem) item, columnNumber);\r
-               }\r
-\r
-               protected void setLayoutData(LayoutData layoutData) {\r
-                       tableEditor.grabHorizontal = layoutData.grabHorizontal;\r
-                       tableEditor.horizontalAlignment = layoutData.horizontalAlignment;\r
-                       tableEditor.minimumWidth = layoutData.minimumWidth;\r
-               }\r
-\r
-               public ViewerCell getFocusCell() {\r
-                       if (focusCellManager != null) {\r
-                               return focusCellManager.getFocusCell();\r
-                       }\r
-                       return super.getFocusCell();\r
-               }\r
-\r
-               protected void updateFocusCell(ViewerCell focusCell,\r
-                               ColumnViewerEditorActivationEvent event) {\r
-                       // Update the focus cell when we activated the editor with these 2\r
-                       // events\r
-                       if (event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC\r
-                                       || event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL) {\r
-                               if (focusCellManager != null) {\r
-                                       try {\r
-                                               if (DEBUG)System.err.println("FOCUS CELL: " + focusCell);\r
-                                               \r
-                                               Method m = AbstractTableViewer.class.getDeclaredMethod(\r
-                                                               "getSelectionFromWidget", null);\r
-                                               m.setAccessible(true);\r
-                                               List l = (List) m.invoke(getViewer(), null);\r
-                                               if (focusCellManager != null) {\r
-                                                       m = focusCellManager\r
-                                                                       .getClass()\r
-                                                                       .getSuperclass()\r
-                                                                       .getDeclaredMethod("setFocusCell",\r
-                                                                                       new Class[] { ViewerCell.class });\r
-                                                       m.setAccessible(true);\r
-                                                       m.invoke(focusCellManager,\r
-                                                                       new Object[] { focusCell });\r
-                                               }\r
-                                               if (!l.contains(focusCell.getElement())) {\r
-                                                       getViewer().setSelection(\r
-                                                                       new StructuredSelection(focusCell\r
-                                                                                       .getElement()));\r
-                                               }\r
-                                       } catch (SecurityException e) {\r
-                                               e.printStackTrace();\r
-                                       } catch (IllegalArgumentException e) {\r
-                                               e.printStackTrace();\r
-                                       } catch (IllegalAccessException e) {\r
-                                               e.printStackTrace();\r
-                                       } catch (NoSuchMethodException e) {\r
-                                               e.printStackTrace();\r
-                                       } catch (InvocationTargetException e) {\r
-                                               e.printStackTrace();\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-\r
-               protected void processTraverseEvent(int columnIndex, ViewerRow row,\r
-                               TraverseEvent event) {\r
-                       ViewerCell cell2edit = null;\r
-                       if (event.detail == SWT.TRAVERSE_TAB_PREVIOUS) {\r
-                               event.doit = false;\r
-                               if ((event.stateMask & SWT.CTRL) == SWT.CTRL\r
-                                               && (feature & TABBING_VERTICAL) == TABBING_VERTICAL) {\r
-                                       cell2edit = searchCellAboveBelow(row, getViewer(),\r
-                                                       columnIndex, true);\r
-                               } else if ((feature & TABBING_HORIZONTAL) == TABBING_HORIZONTAL) {\r
-                                       cell2edit = searchPreviousCell(row,\r
-                                                       row.getCell(columnIndex), row.getCell(columnIndex),\r
-                                                       getViewer());\r
-                               }\r
-                       } else if (event.detail == SWT.TRAVERSE_TAB_NEXT) {\r
-                               event.doit = false;\r
-                               if ((event.stateMask & SWT.CTRL) == SWT.CTRL\r
-                                               && (feature & TABBING_VERTICAL) == TABBING_VERTICAL) {\r
-                                       cell2edit = searchCellAboveBelow(row, getViewer(),\r
-                                                       columnIndex, false);\r
-                               } else if ((feature & TABBING_HORIZONTAL) == TABBING_HORIZONTAL) {\r
-                                       cell2edit = searchNextCell(row, row.getCell(columnIndex),\r
-                                                       row.getCell(columnIndex), getViewer());\r
-                               }\r
-                       }\r
-                       if (DEBUG) System.err.println("NEXT CELL: " + cell2edit);\r
-                       if (cell2edit != null) {\r
-                               getViewer().getControl().setRedraw(false);\r
-                               ColumnViewerEditorActivationEvent acEvent = new ColumnViewerEditorActivationEvent(\r
-                                               cell2edit, event);\r
-                               try {\r
-                                       Method m = ColumnViewer.class\r
-                                                       .getDeclaredMethod(\r
-                                                                       "triggerEditorActivationEvent",\r
-                                                                       new Class[] { ColumnViewerEditorActivationEvent.class });\r
-                                       m.setAccessible(true);\r
-                                       m.invoke(getViewer(), new Object[] { acEvent });\r
-                               } catch (SecurityException e) {\r
-                                       e.printStackTrace();\r
-                               } catch (NoSuchMethodException e) {\r
-                                       e.printStackTrace();\r
-                               } catch (IllegalArgumentException e) {\r
-                                       e.printStackTrace();\r
-                               } catch (IllegalAccessException e) {\r
-                                       e.printStackTrace();\r
-                               } catch (InvocationTargetException e) {\r
-                                       e.printStackTrace();\r
-                               }\r
-                               getViewer().getControl().setRedraw(true);\r
-                       }\r
-               }\r
-\r
-               private ViewerCell searchCellAboveBelow(ViewerRow row,\r
-                               ColumnViewer viewer, int columnIndex, boolean above) {\r
-                       ViewerCell rv = null;\r
-                       ViewerRow newRow = null;\r
-                       if (above) {\r
-                               newRow = row.getNeighbor(ViewerRow.ABOVE, false);\r
-                       } else {\r
-                               newRow = row.getNeighbor(ViewerRow.BELOW, false);\r
-                       }\r
-                       try {\r
-                               if (newRow != null) {\r
-                                       Method m = ColumnViewer.class.getDeclaredMethod(\r
-                                                       "getViewerColumn", new Class[] { int.class });\r
-                                       m.setAccessible(true);\r
-                                       ViewerColumn column = (ViewerColumn) m.invoke(viewer,\r
-                                                       new Object[] { new Integer(columnIndex) });\r
-                                       m = ViewerColumn.class.getDeclaredMethod(\r
-                                                       "getEditingSupport", null);\r
-                                       m.setAccessible(true);\r
-                                       EditingSupport es = (EditingSupport) m.invoke(column, null);\r
-                                       if (column != null && es != null) {\r
-                                               m = EditingSupport.class.getDeclaredMethod("canEdit",\r
-                                                               new Class[] { Object.class });\r
-                                               m.setAccessible(true);\r
-                                               Boolean b = (Boolean) m.invoke(es,\r
-                                                               new Object[] { newRow.getItem().getData() });\r
-                                               if (b.booleanValue()) {\r
-                                                       rv = newRow.getCell(columnIndex);\r
-                                               }\r
-                                       } else {\r
-                                               rv = searchCellAboveBelow(newRow, viewer, columnIndex,\r
-                                                               above);\r
-                                       }\r
-                               }\r
-                       } catch (Exception e) {\r
-                               e.printStackTrace();\r
-                       }\r
-                       return rv;\r
-               }\r
-\r
-               private ViewerCell searchPreviousCell(ViewerRow row,\r
-                               ViewerCell currentCell, ViewerCell originalCell,\r
-                               ColumnViewer viewer) {\r
-                       ViewerCell rv = null;\r
-                       ViewerCell previousCell;\r
-                       if (currentCell != null) {\r
-                               previousCell = getNeighbor(currentCell, ViewerCell.LEFT, true);\r
-                       } else {\r
-                               if (row.getColumnCount() != 0) {\r
-                                       previousCell = row.getCell(getCreationIndex(row,\r
-                                                       row.getColumnCount() - 1));\r
-                               } else {\r
-                                       previousCell = row.getCell(0);\r
-                               }\r
-                       }\r
-                       // No endless loop\r
-                       if (originalCell.equals(previousCell)) {\r
-                               return null;\r
-                       }\r
-                       if (previousCell != null) {\r
-                               if (isCellEditable(viewer, previousCell)) {\r
-                                       rv = previousCell;\r
-                               } else {\r
-                                       rv = searchPreviousCell(row, previousCell, originalCell,\r
-                                                       viewer);\r
-                               }\r
-                       } else {\r
-                               if ((feature & TABBING_CYCLE_IN_ROW) == TABBING_CYCLE_IN_ROW) {\r
-                                       rv = searchPreviousCell(row, null, originalCell, viewer);\r
-                               } else if ((feature & TABBING_MOVE_TO_ROW_NEIGHBOR) == TABBING_MOVE_TO_ROW_NEIGHBOR) {\r
-                                       ViewerRow rowAbove = row\r
-                                                       .getNeighbor(ViewerRow.ABOVE, false);\r
-                                       if (rowAbove != null) {\r
-                                               rv = searchPreviousCell(rowAbove, null, originalCell,\r
-                                                               viewer);\r
-                                       }\r
-                               }\r
-                       }\r
-                       return rv;\r
-               }\r
-\r
-               private ViewerCell searchNextCell(ViewerRow row,\r
-                               ViewerCell currentCell, ViewerCell originalCell,\r
-                               ColumnViewer viewer) {\r
-                       ViewerCell rv = null;\r
-                       ViewerCell nextCell;\r
-                       if (currentCell != null) {\r
-                               nextCell = getNeighbor(currentCell, ViewerCell.RIGHT, true);\r
-                       } else {\r
-                               nextCell = row.getCell(getCreationIndex(row, 0));\r
-                       }\r
-                       // No endless loop\r
-                       if (originalCell.equals(nextCell)) {\r
-                               return null;\r
-                       }\r
-                       if (nextCell != null) {\r
-                               if (isCellEditable(viewer, nextCell)) {\r
-                                       rv = nextCell;\r
-                               } else {\r
-                                       rv = searchNextCell(row, nextCell, originalCell, viewer);\r
-                               }\r
-                       } else {\r
-                               if ((feature & TABBING_CYCLE_IN_ROW) == TABBING_CYCLE_IN_ROW) {\r
-                                       rv = searchNextCell(row, null, originalCell, viewer);\r
-                               } else if ((feature & TABBING_MOVE_TO_ROW_NEIGHBOR) == TABBING_MOVE_TO_ROW_NEIGHBOR) {\r
-                                       ViewerRow rowBelow = row\r
-                                                       .getNeighbor(ViewerRow.BELOW, false);\r
-                                       if (rowBelow != null) {\r
-                                               rv = searchNextCell(rowBelow, null, originalCell,\r
-                                                               viewer);\r
-                                       }\r
-                               }\r
-                       }\r
-                       return rv;\r
-               }\r
-\r
-               private boolean isCellEditable(ColumnViewer viewer, ViewerCell cell) {\r
-                       try {\r
-                               Method m = ColumnViewer.class.getDeclaredMethod(\r
-                                               "getViewerColumn", new Class[] { int.class });\r
-                               m.setAccessible(true);\r
-                               ViewerColumn column = (ViewerColumn) m.invoke(viewer,\r
-                                               new Object[] { new Integer(cell.getColumnIndex()) });\r
-                               m = ViewerColumn.class.getDeclaredMethod("getEditingSupport",\r
-                                               null);\r
-                               m.setAccessible(true);\r
-                               EditingSupport es = (EditingSupport) m.invoke(column, null);\r
-                               if (column != null && es != null) {\r
-                                       m = EditingSupport.class.getDeclaredMethod("canEdit",\r
-                                                       new Class[] { Object.class });\r
-                                       m.setAccessible(true);\r
-                                       // return true;\r
-                                       Boolean b = (Boolean) m.invoke(es,\r
-                                                       new Object[] { cell.getElement() });\r
-                                       return b.booleanValue();\r
-                               }\r
-                       } catch (Exception e) {\r
-                               e.printStackTrace();\r
-                       }\r
-                       return false;\r
-               }\r
-       }\r
-       \r
-       // Reimplementation of ViewerCell-Methods\r
-       private static int getVisualIndex(ViewerRow row, int creationIndex) {\r
-               TableItem item = (TableItem) row.getItem();\r
-               int[] order = item.getParent().getColumnOrder();\r
-               for (int i = 0; i < order.length; i++) {\r
-                       if (order[i] == creationIndex) {\r
-                               return i;\r
-                       }\r
-               }\r
-               return creationIndex;\r
-       }\r
-       \r
-       private static int getCreationIndex(ViewerRow row, int visualIndex) {\r
-               TableItem item = (TableItem) row.getItem();\r
-               if (item != null && !item.isDisposed() /*\r
-                                                                                                * && hasColumns() &&\r
-                                                                                                * isValidOrderIndex\r
-                                                                                                * (visualIndex)\r
-                                                                                                */) {\r
-                       return item.getParent().getColumnOrder()[visualIndex];\r
-               }\r
-               return visualIndex;\r
-       }\r
-       \r
-       private static ViewerCell getCellAtVisualIndex(ViewerRow row,\r
-                       int visualIndex) {\r
-               return getCell(row, getCreationIndex(row, visualIndex));\r
-       }\r
-\r
-       private static boolean isVisible(ViewerCell cell) {\r
-               return getWidth(cell) > 0;\r
-       }\r
-\r
-       private static int getWidth(ViewerCell cell) {\r
-               TableItem item = (TableItem) cell.getViewerRow().getItem();\r
-               return item.getParent().getColumn(cell.getColumnIndex()).getWidth();\r
-       }\r
-\r
-       private static ViewerCell getCell(ViewerRow row, int index) {\r
-               return row.getCell(index);\r
-       }\r
-       \r
-       \r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.g3d.property;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.viewers.AbstractTableViewer;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.CellEditor.LayoutData;
+import org.eclipse.jface.viewers.CellLabelProvider;
+import org.eclipse.jface.viewers.CellNavigationStrategy;
+import org.eclipse.jface.viewers.ColumnViewer;
+import org.eclipse.jface.viewers.ColumnViewerEditor;
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationListener;
+import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
+import org.eclipse.jface.viewers.ColumnViewerEditorDeactivationEvent;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.TableViewerFocusCellManager;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerCell;
+import org.eclipse.jface.viewers.ViewerColumn;
+import org.eclipse.jface.viewers.ViewerRow;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.TableEditor;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.IWorkbenchSite;
+import org.simantics.db.management.ISessionContext;
+import org.simantics.g3d.property.annotations.CompoundGetPropertyValue;
+import org.simantics.g3d.property.annotations.CompoundSetPropertyValue;
+import org.simantics.g3d.property.annotations.GetPropertyValue;
+import org.simantics.g3d.property.annotations.PropertyTabBlacklist;
+import org.simantics.g3d.property.annotations.SetPropertyValue;
+import org.simantics.g3d.scenegraph.IG3DNode;
+import org.simantics.g3d.scenegraph.NodeMap;
+import org.simantics.g3d.scenegraph.NodeMapProvider;
+import org.simantics.g3d.scenegraph.base.INode;
+import org.simantics.g3d.scenegraph.base.NodeListener;
+import org.simantics.g3d.scenegraph.base.ParentNode;
+import org.simantics.g3d.scenegraph.structural.IStructuralNode;
+import org.simantics.g3d.tools.AdaptationUtils;
+import org.simantics.selectionview.IPropertyTab;
+import org.simantics.selectionview.IPropertyTab2;
+import org.simantics.utils.datastructures.MapList;
+
+public class AnnotatedPropertyTabContributorFactory implements PropertyTabContributorFactory {
+
+       private static final boolean DEBUG = false;
+       
+       @SuppressWarnings("unchecked")
+       @Override
+       public List<PropertyTabContributor> getContributors(Object input) {
+               Map<String,IPropertyItem> items = new LinkedHashMap<String, IPropertyItem>();
+               List<String> blacklist = new ArrayList<String>();
+               try {
+                       collectItems(input.getClass(), items);
+                       collectBlacklist(input.getClass(), blacklist);
+               } catch (InstantiationException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               } catch (IllegalAccessException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
+               
+               if (items.size() == 0)
+                       return Collections.EMPTY_LIST;
+               
+               MapList<String, IPropertyItem> tabMap = new MapList<String, IPropertyItem>();
+               List<String> tabs = new ArrayList<String>();
+               for (String id : items.keySet()) {
+                       IPropertyItem item = items.get(id);
+                       tabMap.add(item.getTabId(), item);
+                       if (!tabs.contains(item.getTabId())) {
+                               tabs.add(item.getTabId());
+                               //System.out.println(item.tabId + " " + item.name + " " + item.id);
+                       }
+               }
+               for (String s : blacklist) {
+                       tabs.remove(s);
+               }
+               
+               List<PropertyTabContributor> contributors = new ArrayList<PropertyTabContributor>(tabs.size());
+               for (String tabId : tabs) {
+                       contributors.add(new AnnotatedPropertyTabContributor(tabId, tabMap.getValues(tabId)));
+               }
+               
+               return contributors;
+       }
+       
+       
+       private static void collectItems(Class<?> clazz, Map<String, IPropertyItem> items) throws InstantiationException, IllegalAccessException {
+               Class<?> superclass = clazz.getSuperclass();
+               if(superclass != null)
+                       collectItems(superclass, items);
+               
+               for (Method m : clazz.getDeclaredMethods()) {
+                       m.setAccessible(true);
+                       for (Annotation annotation : m.getAnnotations()) {
+                               if (annotation.annotationType().equals(GetPropertyValue.class)) {
+                                       GetPropertyValue get = (GetPropertyValue)annotation;
+                                       PropertyItem item = (PropertyItem)items.get(get.value());
+                                       if (item == null) {
+                                               item = new PropertyItem(get.value());
+                                               items.put(item.id, item);
+                                       }
+
+                                       item.getter = m;
+                                       item.manipulatorClass = get.manipulator().newInstance().get(m,null);
+
+                                       item.tabId = get.tabId();
+
+                                       item.name = get.name();
+                                       
+                                       
+                               } else if (annotation.annotationType().equals(SetPropertyValue.class)) {
+                                       SetPropertyValue set = (SetPropertyValue)annotation;
+                                       PropertyItem item = (PropertyItem)items.get(set.value());
+                                       if (item == null) {
+                                               item = new PropertyItem(set.value());
+                                               items.put(item.id, item);
+                                       }
+                                       
+                                       item.setter = m;
+                               } else if (annotation.annotationType().equals(CompoundGetPropertyValue.class)) {
+                                       CompoundGetPropertyValue get = (CompoundGetPropertyValue)annotation;
+                                       CompoundPropertyItem item = (CompoundPropertyItem)items.get(get.value());
+                                       if (item == null) {
+                                               item = new CompoundPropertyItem(get.value());
+                                               items.put(item.id, item);
+                                       }
+
+                                       item.getter = m;
+                                       item.manipulatorFactory = get.manipulator().newInstance();
+
+                                       item.tabId = get.tabId();
+
+                                       item.name = get.name();
+                               } else if (annotation.annotationType().equals(CompoundSetPropertyValue.class)) {
+                                       CompoundSetPropertyValue set = (CompoundSetPropertyValue)annotation;
+                                       CompoundPropertyItem item = (CompoundPropertyItem)items.get(set.value());
+                                       if (item == null) {
+                                               item = new CompoundPropertyItem(set.value());
+                                               items.put(item.id, item);
+                                       }
+                                       
+                                       item.setter = m;
+                               }
+                       }
+               }
+               
+               
+       }
+       
+       private static void collectBlacklist(Class<?> clazz, List<String> blacklist) throws InstantiationException, IllegalAccessException {
+               Class<?> superclass = clazz.getSuperclass();
+               if(superclass != null)
+                       collectBlacklist(superclass, blacklist);
+               
+               PropertyTabBlacklist ann = clazz.getAnnotation(PropertyTabBlacklist.class);
+               if (ann == null)
+                       return;
+               String s = ann.value();
+               if (s == null)
+                       return;
+               if (s.length() == 0)
+                       return;
+               for (String item : s.split(";")) {
+                       blacklist.add(item);
+               }
+               
+               
+       }
+       
+       private static Map<PropertyItem, PropertyManipulator> createManipulators(CompoundPropertyItem item, Object obj) {
+               try {
+                       
+                       @SuppressWarnings("unchecked")
+                       Map<String,Object> map = (Map<String, Object>)item.getter.invoke(obj);
+                       Map<PropertyItem, PropertyManipulator> result = new HashMap<AnnotatedPropertyTabContributorFactory.PropertyItem, PropertyManipulator>();
+                       for (String key : map.keySet()) {
+                               MethodWithMapValueProvider provider = new MethodWithMapValueProvider(item.getter, item.setter, key);
+                               Class<? extends PropertyManipulator> clazz = item.manipulatorFactory.get(null,map.get(key));
+                               PropertyManipulator manipulator = clazz.getConstructor(ValueProvider.class,Object.class).newInstance(provider,obj);
+                               PropertyItem i = new PropertyItem(item.id+"."+key);
+                               i.getter = item.getter;
+                               i.setter = item.setter;
+                               i.name = key;
+                               i.tabId = item.tabId;
+                               result.put(i,manipulator);
+                       }
+                       return result;
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       return Collections.emptyMap();
+               } 
+               
+       }
+       
+       private static PropertyManipulator createManipulator(PropertyItem item, Object obj) {
+               try {
+                       MethodValueProvider provider = new MethodValueProvider(item.getter, item.setter);
+                       PropertyManipulator manipulator = item.manipulatorClass.getConstructor(ValueProvider.class,Object.class).newInstance(provider,obj);
+                       return manipulator;
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       return null;
+               } 
+       }
+       
+       private static interface IPropertyItem {
+               public String getTabId();
+               public String getName();
+       }
+       
+       private static class PropertyItem implements IPropertyItem{
+               private String id;
+               private String name;
+               private String tabId;
+               private Method getter;
+               private Method setter;
+               private Class<? extends PropertyManipulator> manipulatorClass;
+               
+               
+               public PropertyItem(String id) {
+                       if (id == null)
+                               throw new NullPointerException();
+                       this.id = id;
+               }
+               
+               @Override
+               public int hashCode() {
+                       return id.hashCode();
+               }
+               
+               @Override
+               public String getTabId() {
+                       return tabId;
+               }
+               
+               @Override
+               public String getName() {
+                   return name;
+               }
+       }
+       
+       private static class CompoundPropertyItem implements IPropertyItem{
+               private String id;
+               private String name;
+               private String tabId;
+               private Method getter;
+               private Method setter;
+               private PropertyManipulatorFactory manipulatorFactory;
+               
+               
+               public CompoundPropertyItem(String id) {
+                       if (id == null)
+                               throw new NullPointerException();
+                       this.id = id;
+               }
+               
+               @Override
+               public int hashCode() {
+                       return id.hashCode();
+               }
+               
+               @Override
+               public String getTabId() {
+                       return tabId;
+               }
+               
+               @Override
+        public String getName() {
+            return name;
+        }
+       }
+       
+       private static class AnnotatedPropertyTabContributor implements PropertyTabContributor {
+               private String id; 
+               List<IPropertyItem> items;
+               
+               public AnnotatedPropertyTabContributor(String id, List<IPropertyItem> items) {
+                       if (id == null)
+                               throw new NullPointerException();
+                       this.id = id;
+                       this.items = items;
+               }
+               
+               @Override
+               public IPropertyTab create(Composite parent, IWorkbenchSite site,
+                               ISessionContext context, Object input) {
+                       AnnotatedPropertyTab tab = new AnnotatedPropertyTab(id, items);
+                       tab.createControl(parent, context);
+                       return tab;
+               }
+               
+               @Override
+               public String getId() {
+                       return id;
+               }
+               
+       }
+       
+       private static class AnnotatedPropertyTab implements IPropertyTab2, NodeListener {
+               //private String id; 
+               List<IPropertyItem> contibutedItems;
+               List<PropertyItem> resolvedItems = new ArrayList<PropertyItem>();
+               private Map<PropertyItem,PropertyManipulator> manipulators = new HashMap<PropertyItem, PropertyManipulator>();
+               
+               private TableViewer viewer;
+               
+               private INode node;
+               private NodeMap<?,?,?> nodeMap;
+               
+               private List<TableViewerColumn> valueColumns = new ArrayList<TableViewerColumn>();
+               
+               public AnnotatedPropertyTab(String id, List<IPropertyItem> items) {
+                       //this.id = id;
+                       this.contibutedItems = items;
+                       
+                                       
+               }
+               
+               @Override
+               public void createControl(Composite parent, ISessionContext context) {
+                       //parent.setLayout(new FillLayout());
+                       viewer = new TableViewer(parent, SWT.FULL_SELECTION | SWT.SINGLE);
+                       
+                       GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(viewer.getTable());
+                       
+                       //viewer.setLabelProvider(new AnnotatedTableLabelProvider(object))
+                       
+                       viewer.setContentProvider(new PropertyItemContentsProvider());
+                       
+                       TableViewerColumn name = new TableViewerColumn(viewer, SWT.LEFT);
+                       //TableViewerColumn value = new TableViewerColumn(viewer, SWT.LEFT);
+                       name.setLabelProvider(new PropertyItemNameProvider());
+                       //value.setLabelProvider(new PropertyValueLabelProvider(null));
+                       name.getColumn().setText("Property");
+                       //value.getColumn().setText("Value");
+                       name.getColumn().setWidth(200);
+                       //value.getColumn().setWidth(200);
+                       name.getViewer().addSelectionChangedListener(new ISelectionChangedListener() {
+                               
+                               @Override
+                               public void selectionChanged(SelectionChangedEvent event) {
+                                       PropertyItem item = AdaptationUtils.adaptToSingle(event.getSelection(),PropertyItem.class);
+                                       if (item != null) {
+                                               PropertyManipulator manipulator = manipulators.get(item);//createManipulator(item, null);
+                                               for (int i = 0; i < valueColumns.size(); i++) {
+                                                       TableViewerColumn c = valueColumns.get(i);
+                                                       if (i < manipulator.getValueCount()) {
+                                                               c.getColumn().setText(manipulator.getDescription(i));
+                                                       } else {
+                                                               c.getColumn().setText("");
+                                                       }
+                                               }
+                                       }
+                                       
+                               }
+                       });
+                       
+                       viewer.getTable().setHeaderVisible(true);
+                       viewer.getTable().setLinesVisible(true);
+                       viewer.addSelectionChangedListener(new ISelectionChangedListener() {
+                               
+                               @Override
+                               public void selectionChanged(SelectionChangedEvent event) {
+                                       PropertyItem item = AdaptationUtils.adaptToSingle(event.getSelection(), PropertyItem.class);
+                                       selectedItem = item;
+                                       if (!manipulators.get(selectedItem).getEditMode())
+                                               manipulators.get(selectedItem).setEditMode(true);
+                                       
+
+                                       for (IPropertyItem i : delayedUpdate) {
+                                               if (!i.equals(selectedItem)) {
+                                                       manipulators.get(i).setEditMode(false);
+                                                       viewer.update(i,null);
+                                               }
+                                       }
+                                       if (delayedUpdate.contains(selectedItem)) {
+                                               delayedUpdate.clear();
+                                               delayedUpdate.add(selectedItem);
+                                       } else {
+                                               delayedUpdate.clear();
+                                       }
+                               }
+                       });
+                       
+                       CellNavigationStrategy nStrategy = new CellNavigationStrategy() {
+                               private ViewerCell internalFindSelectedCell(
+                                               ColumnViewer viewer, ViewerCell currentSelectedCell,
+                                               Event event) {
+                                       switch (event.keyCode) {
+                                       case SWT.ARROW_UP:
+                                               if (currentSelectedCell != null) {
+                                                       return getNeighbor(currentSelectedCell,
+                                                                       ViewerCell.ABOVE, false);
+                                               }
+                                               break;
+                                       case SWT.ARROW_DOWN:
+                                               if (currentSelectedCell != null) {
+                                                       return getNeighbor(currentSelectedCell,
+                                                                       ViewerCell.BELOW, false);
+                                               }
+                                               break;
+                                       case SWT.ARROW_LEFT:
+                                               if (currentSelectedCell != null) {
+                                                       return getNeighbor(currentSelectedCell,
+                                                                       ViewerCell.LEFT, true);
+                                               }
+                                               break;
+                                       case SWT.ARROW_RIGHT:
+                                               if (currentSelectedCell != null) {
+                                                       return getNeighbor(currentSelectedCell,
+                                                                       ViewerCell.RIGHT, true);
+                                               }
+                                               break;
+                                       }
+                                       return null;
+                               }
+                               
+                               public ViewerCell findSelectedCell(ColumnViewer viewer,
+                                               ViewerCell currentSelectedCell, Event event) {
+                                       ViewerCell cell = internalFindSelectedCell(viewer,
+                                                       currentSelectedCell, event);
+                                       if (cell != null) {
+                                               TableColumn t = AnnotatedPropertyTab.this.viewer.getTable().getColumn(
+                                                               cell.getColumnIndex());
+                                               AnnotatedPropertyTab.this.viewer.getTable().showColumn(t);
+                                       }
+                                       return cell;
+                               }
+                       };
+                       
+                       TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(
+                                       viewer, new FocusCellOwnerDrawHighlighter(viewer));
+                       try {
+                               Field f = focusCellManager.getClass().getSuperclass()
+                                               .getDeclaredField("navigationStrategy");
+                               f.setAccessible(true);
+                               f.set(focusCellManager, nStrategy);
+                       } catch (SecurityException e) {
+                               e.printStackTrace();
+                       } catch (NoSuchFieldException e) {
+                               e.printStackTrace();
+                       } catch (IllegalArgumentException e) {
+                               e.printStackTrace();
+                       } catch (IllegalAccessException e) {
+                               e.printStackTrace();
+                       }
+                       ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(
+                                       viewer) {
+                               protected boolean isEditorActivationEvent(
+                                               ColumnViewerEditorActivationEvent event) {
+                                       return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL
+                                                       || event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION
+                                                       || (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR)
+                                                       || event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;
+                               }
+                       };
+                       TableViewerEditor.create(viewer, focusCellManager, actSupport,
+                                       ColumnViewerEditor.TABBING_HORIZONTAL
+                                                       | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
+                                                       | ColumnViewerEditor.TABBING_VERTICAL
+                                                       | ColumnViewerEditor.KEYBOARD_ACTIVATION);
+                       viewer.getColumnViewerEditor().addEditorActivationListener(
+                                       new ColumnViewerEditorActivationListener() {
+                                               public void afterEditorActivated(
+                                                               ColumnViewerEditorActivationEvent event) {
+                                               }
+
+                                               public void afterEditorDeactivated(
+                                                               ColumnViewerEditorDeactivationEvent event) {
+                                               }
+
+                                               public void beforeEditorActivated(
+                                                               ColumnViewerEditorActivationEvent event) {
+                                                       ViewerCell cell = (ViewerCell) event.getSource();
+                                                       viewer.getTable().showColumn(
+                                                                       viewer.getTable().getColumn(cell.getColumnIndex()));
+                                               }
+
+                                               public void beforeEditorDeactivated(
+                                                               ColumnViewerEditorDeactivationEvent event) {
+                                               }
+                                       });
+               }
+               
+               
+               
+               
+               private IPropertyItem selectedItem = null;
+               private Set<IPropertyItem> delayedUpdate = new HashSet<IPropertyItem>();
+               
+               
+               @Override
+               public void setInput(ISessionContext context, ISelection selection,
+                               boolean force) {
+                       Collection<INode> nodes = AdaptationUtils.adaptToCollection(selection, INode.class);
+                       if (nodes.size() != 1) {
+                               if (node != null) {
+                                       node.removeListener(this);
+                                       node = null;
+                               }
+                               return;
+                       }
+                       INode n = nodes.iterator().next();
+                       if (node != null) {
+                               if (!node.equals(n)) {
+                                       node.removeListener(this);
+                                       setInput(n);
+                               }
+                       } else {
+                               setInput(n);
+                       }
+               }
+               
+               
+               
+               private void setInput(INode node) {
+                       this.node = node;
+                       this.node.addListener(this);
+                       // resolve nodemap
+                       INode n = node;
+                       while (true) {
+                               if (n == null) {
+                                       nodeMap = null;
+                                       break;
+                               }
+                               if (n instanceof NodeMapProvider<?,?,?>) {
+                                       nodeMap = ((NodeMapProvider<?,?,?>) n).getNodeMap();
+                                       if (nodeMap != null)
+                                               break;
+                               }
+                               n = (IG3DNode)n.getParent();
+                       }
+                       boolean readOnly =  (node instanceof IStructuralNode && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot());
+                       
+                       resolvedItems.clear();
+                       manipulators.clear();
+                       for (IPropertyItem item : contibutedItems) {
+                               if (item instanceof PropertyItem) {
+                                       resolvedItems.add((PropertyItem)item);
+                                       manipulators.put((PropertyItem)item, createManipulator((PropertyItem)item, node));
+                               }
+                               else {
+                                       CompoundPropertyItem compound = (CompoundPropertyItem)item;
+                                       Map<PropertyItem, PropertyManipulator> manipulators = createManipulators(compound, node);
+                                       for (PropertyItem i : manipulators.keySet()) {
+                                               resolvedItems.add(i);
+                                               this.manipulators.put(i, manipulators.get(i));
+                                       }
+                               }
+                       }
+                       
+                       int valueCount = 0;
+                       for (PropertyManipulator manipulator : manipulators.values()) {
+                           if (valueCount < manipulator.getValueCount())
+                   valueCount = manipulator.getValueCount();
+                       }
+            for (int i = 0; i < valueCount; i++) {
+                TableViewerColumn value = new TableViewerColumn(viewer, SWT.LEFT);
+                //value.getColumn().setText("Value " + (i+1));
+                value.getColumn().setText("");
+                value.getColumn().setWidth(200);
+                valueColumns.add(value);
+                //value.setEditingSupport(new )
+            }
+            
+            // create label providers
+            PropertyValueLabelProvider2 p = new PropertyValueLabelProvider2(this);
+            int index = 0;
+            for (TableViewerColumn c : valueColumns) {
+                c.setLabelProvider(p);
+                if (!readOnly) {
+                    PropertyEditingSupport support = new PropertyEditingSupport(this, viewer, index++, nodeMap);
+                    c.setEditingSupport(support);
+                }
+            }
+                       Collections.sort(resolvedItems, new Comparator<IPropertyItem>() {
+                           @Override
+                           public int compare(IPropertyItem o1, IPropertyItem o2) {
+                               return o1.getName().compareTo(o2.getName());
+                           }
+            });
+                       viewer.getTable().setEnabled(!readOnly);
+                       viewer.setInput(resolvedItems);
+               }
+               
+               @Override
+               public void requestFocus() {
+                       viewer.getTable().forceFocus();
+               }
+               
+               @Override
+               public void dispose() {
+                       if (node != null) {
+                               node.removeListener(this);
+                               node = null;
+                       }
+                       
+               }
+               
+               @Override
+               public Control getControl() {
+                       return viewer.getTable();
+               }
+               
+               @Override
+               public ISelectionProvider getSelectionProvider() {
+                       return null;
+               }
+               
+               @Override
+               public boolean isDisposed() {
+                       return viewer.getTable().isDisposed();
+               }
+               
+               @Override
+               public <T extends INode> void nodeAdded(ParentNode<T> node,
+                               INode child, String rel) {
+                       
+               }
+               
+               @Override
+               public <T extends INode> void nodeRemoved(ParentNode<T> node,
+                               INode child, String rel) {
+                       
+               }
+               
+               @Override
+               public void propertyChanged(INode node, final String id) {
+//                     for (final PropertyItem item : items) {
+//                             if (item.id.equals(id)) {
+//                                     Display.getDefault().asyncExec(new Runnable() {
+//                                             
+//                                             @Override
+//                                             public void run() {
+//                                                     viewer.update(item, null);
+//                                                     
+//                                             }
+//                                     });
+//                             }
+//                     }
+                       if (Thread.currentThread() == Display.getDefault().getThread()) {
+                               if (viewer.getTable().isDisposed())
+                                       return;
+                               if (DEBUG)System.out.println("Viewer refresh " + id);
+                               for (PropertyItem item : resolvedItems)
+                                       if (!item.equals(selectedItem))
+                                               viewer.refresh(item);
+                               if (selectedItem != null)
+                                       delayedUpdate.add(selectedItem);
+                       } else if (!editing){
+                               // running delayed refresh when a cell editor is active would cancel cell editing.
+                               Display.getDefault().asyncExec(new Runnable() {
+                                       @Override
+                                       public void run() {
+                                               if (viewer.getTable().isDisposed()) {
+                                                       if (AnnotatedPropertyTab.this.node != null)
+                                                               AnnotatedPropertyTab.this.node.removeListener(AnnotatedPropertyTab.this);
+                                                       return;
+                                               }
+                                               if (DEBUG) System.out.println("Viewer threaded refresh " + id);
+                                               for (PropertyItem item : resolvedItems)
+                                                       if (!item.equals(selectedItem))
+                                                               viewer.refresh(item);
+                                               if (selectedItem != null)
+                                                       delayedUpdate.add(selectedItem);
+                                               
+                                       }
+                               });
+                       } else {
+                               for (PropertyItem item : resolvedItems) {
+                                       delayedUpdate.add(item);
+                               }
+                       }
+                       
+               }
+               
+
+               
+               @Override
+               public void updatePartName(Consumer<String> updateCallback) {
+                       if (node != null)
+                               updateCallback.accept(node.toString()); 
+                       
+               }
+               
+               public PropertyManipulator getManipulator(PropertyItem item) {
+                       return manipulators.get(item);
+               }
+               
+               private boolean editing = false;
+               
+               public void setEditing(boolean editing) {
+                       this.editing = editing;
+               }
+       }
+       
+       
+       
+       private static class PropertyEditingSupport extends EditingSupport {
+               AnnotatedPropertyTab tab;
+               int index;
+               NodeMap<?,?,?> nodeMap;
+               TableViewer viewer;
+               CellEditor editor;
+
+               public PropertyEditingSupport(AnnotatedPropertyTab tab, TableViewer viewer, int index, NodeMap<?,?,?> nodeMap) {
+                       super(viewer);
+                       this.tab = tab;
+                       this.index = index;
+                       this.viewer = viewer;
+                       this.nodeMap = nodeMap;
+               }
+               
+               @Override
+               protected boolean canEdit(Object element) {
+                       PropertyItem item = (PropertyItem)element;
+                       if (tab.getManipulator(item).getValueCount() <= index)
+                               return false;
+                       if (item.setter == null)
+                               return false;
+                       if (getValue(element) == null)
+                               return false;
+                       return true;
+               }
+               
+               @Override
+               protected CellEditor getCellEditor(Object element) {
+                       
+                       if (tab.getManipulator((PropertyItem)element).getValueCount() <= index)
+                               return null;
+                       if (editor == null)
+                               editor = new TextCellEditor(viewer.getTable(),SWT.NONE) {
+                               @Override
+                               public void activate() {
+                                       tab.setEditing(true);
+                               }
+                               
+                               @Override
+                               public void deactivate() {
+                                       super.deactivate();
+                                       tab.setEditing(false);
+                               }
+                       };
+                       if (DEBUG)System.err.println("CELL EDITOR: " + element);
+                       return editor;
+               }
+               
+               @Override
+               protected Object getValue(Object element) {
+                       PropertyItem item = (PropertyItem)element;
+                       PropertyManipulator manipulator = tab.getManipulator(item);//createManipulator(item, obj);
+                       if (manipulator.getValueCount() <= index)
+                               return null;
+                       Object value = manipulator.getValue(index);
+                       return value;
+               }
+               
+               @Override
+               protected void setValue(Object element, Object value) {
+                       
+                       PropertyItem item = (PropertyItem)element;
+                       PropertyManipulator manipulator = tab.getManipulator(item);//createManipulator(item, obj);
+                       if (manipulator.getValueCount() <= index)
+                               throw new IllegalAccessError("Editing value in index " + index + " is not allowed.");
+                       if (DEBUG)System.err.println("CELL SET VALUE: " + element + " " + value);
+                       manipulator.setValue((String)value,index);
+                       viewer.refresh(item);
+                       nodeMap.commit("Set " + item.id + " value to " + value);
+                       
+               }
+               
+               
+
+       }
+       
+       private static class PropertyItemNameProvider extends CellLabelProvider {
+
+               
+               @Override
+               public void update(ViewerCell cell) {
+                       PropertyItem item = (PropertyItem)cell.getElement();
+
+                       if (item.name.length() > 0)
+                               cell.setText(item.name);
+                       else
+                               cell.setText(item.id);
+                       
+                       
+               }
+       }
+       
+       private static class PropertyValueLabelProvider2 extends CellLabelProvider {
+               AnnotatedPropertyTab tab;
+               //private Object object;
+               
+               public PropertyValueLabelProvider2(AnnotatedPropertyTab tab) {
+                       this.tab = tab;
+               }
+               
+               @Override
+               public void update(ViewerCell cell) {
+                       PropertyItem item = (PropertyItem)cell.getElement();
+                       int index = cell.getColumnIndex() -1;
+                       PropertyManipulator manipulator = tab.getManipulator(item);//createManipulator(item, object);
+                       if (manipulator.getValueCount() <= index)
+                               return;
+                       cell.setText(manipulator.getValue(index));
+               }
+       }
+       
+       private static class PropertyItemContentsProvider implements IStructuredContentProvider {
+               @SuppressWarnings("unchecked")
+               @Override
+               public Object[] getElements(Object inputElement) {
+                       List<PropertyItem> items = (List<PropertyItem>)inputElement;
+                       return items.toArray();
+               }
+               
+               @Override
+               public void dispose() {
+                       
+               }
+               
+               @Override
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+                       
+               }
+       }
+       
+       
+       
+       private static ViewerCell getNeighbor(ViewerCell currentCell,
+                       int directionMask, boolean sameLevel) {
+               ViewerRow row;
+               if ((directionMask & ViewerCell.ABOVE) == ViewerCell.ABOVE) {
+                       row = currentCell.getViewerRow().getNeighbor(ViewerRow.ABOVE,
+                                       sameLevel);
+               } else if ((directionMask & ViewerCell.BELOW) == ViewerCell.BELOW) {
+                       row = currentCell.getViewerRow().getNeighbor(ViewerRow.BELOW,
+                                       sameLevel);
+               } else {
+                       row = currentCell.getViewerRow();
+               }
+               if (row != null) {
+                       int columnIndex;
+                       columnIndex = getVisualIndex(row, currentCell.getColumnIndex());
+                       int modifier = 0;
+                       if ((directionMask & ViewerCell.LEFT) == ViewerCell.LEFT) {
+                               modifier = -1;
+                       } else if ((directionMask & ViewerCell.RIGHT) == ViewerCell.RIGHT) {
+                               modifier = 1;
+                       }
+                       columnIndex += modifier;
+                       if (columnIndex >= 0 && columnIndex < row.getColumnCount()) {
+                               ViewerCell cell = getCellAtVisualIndex(row, columnIndex);
+                               if (cell != null) {
+                                       while (cell != null
+                                                       && columnIndex < row.getColumnCount() - 1
+                                                       && columnIndex > 0) {
+                                               if (isVisible(cell)) {
+                                                       break;
+                                               }
+                                               columnIndex += modifier;
+                                               cell = getCellAtVisualIndex(row, columnIndex);
+                                               if (cell == null) {
+                                                       break;
+                                               }
+                                       }
+                               }
+                               return cell;
+                       }
+               }
+               return null;
+       }
+       
+       
+       
+       public static class TableViewerEditor extends ColumnViewerEditor {
+               /**
+                * This viewer's table editor.
+                */
+               private TableEditor tableEditor;
+               private TableViewerFocusCellManager focusCellManager;
+               private int feature;
+
+               /**
+                * @param viewer
+                *            the viewer the editor is attached to
+                * @param focusCellManager
+                *            the cell focus manager if one used or <code>null</code>
+                * @param editorActivationStrategy
+                *            the strategy used to decide about the editor activation
+                * @param feature
+                *            the feature mask
+                */
+               TableViewerEditor(TableViewer viewer,
+                               TableViewerFocusCellManager focusCellManager,
+                               ColumnViewerEditorActivationStrategy editorActivationStrategy,
+                               int feature) {
+                       super(viewer, editorActivationStrategy, feature);
+                       this.feature = feature;
+                       tableEditor = new TableEditor(viewer.getTable());
+                       this.focusCellManager = focusCellManager;
+               }
+
+               /**
+                * Create a customized editor with focusable cells
+                * 
+                * @param viewer
+                *            the viewer the editor is created for
+                * @param focusCellManager
+                *            the cell focus manager if one needed else
+                *            <code>null</code>
+                * @param editorActivationStrategy
+                *            activation strategy to control if an editor activated
+                * @param feature
+                *            bit mask controlling the editor
+                *            <ul>
+                *            <li>{@link ColumnViewerEditor#DEFAULT}</li>
+                *            <li>{@link ColumnViewerEditor#TABBING_CYCLE_IN_ROW}</li>
+                *            <li>{@link ColumnViewerEditor#TABBING_HORIZONTAL}</li>
+                *            <li>
+                *            {@link ColumnViewerEditor#TABBING_MOVE_TO_ROW_NEIGHBOR}</li>
+                *            <li>{@link ColumnViewerEditor#TABBING_VERTICAL}</li>
+                *            </ul>
+                * @see #create(TableViewer, ColumnViewerEditorActivationStrategy, int)
+                */
+               public static void create(TableViewer viewer,
+                               TableViewerFocusCellManager focusCellManager,
+                               ColumnViewerEditorActivationStrategy editorActivationStrategy,
+                               int feature) {
+                       TableViewerEditor editor = new TableViewerEditor(viewer,
+                                       focusCellManager, editorActivationStrategy, feature);
+                       viewer.setColumnViewerEditor(editor);
+                       if (focusCellManager != null) {
+                               try {
+                                       Method m = focusCellManager.getClass().getSuperclass()
+                                                       .getDeclaredMethod("init");
+                                       m.setAccessible(true);
+                                       m.invoke(focusCellManager);
+                               } catch (SecurityException e) {
+                                       e.printStackTrace();
+                               } catch (IllegalArgumentException e) {
+                                       e.printStackTrace();
+                               } catch (IllegalAccessException e) {
+                                       e.printStackTrace();
+                               } catch (NoSuchMethodException e) {
+                                       e.printStackTrace();
+                               } catch (InvocationTargetException e) {
+                                       e.printStackTrace();
+                               }
+                               // focusCellManager.init();
+                       }
+               }
+
+               /**
+                * Create a customized editor whose activation process is customized
+                * 
+                * @param viewer
+                *            the viewer the editor is created for
+                * @param editorActivationStrategy
+                *            activation strategy to control if an editor activated
+                * @param feature
+                *            bit mask controlling the editor
+                *            <ul>
+                *            <li>{@link ColumnViewerEditor#DEFAULT}</li>
+                *            <li>{@link ColumnViewerEditor#TABBING_CYCLE_IN_ROW}</li>
+                *            <li>{@link ColumnViewerEditor#TABBING_HORIZONTAL}</li>
+                *            <li>
+                *            {@link ColumnViewerEditor#TABBING_MOVE_TO_ROW_NEIGHBOR}</li>
+                *            <li>{@link ColumnViewerEditor#TABBING_VERTICAL}</li>
+                *            </ul>
+                */
+               public static void create(TableViewer viewer,
+                               ColumnViewerEditorActivationStrategy editorActivationStrategy,
+                               int feature) {
+                       create(viewer, null, editorActivationStrategy, feature);
+               }
+
+               protected void setEditor(Control w, Item item, int columnNumber) {
+                       tableEditor.setEditor(w, (TableItem) item, columnNumber);
+               }
+
+               protected void setLayoutData(LayoutData layoutData) {
+                       tableEditor.grabHorizontal = layoutData.grabHorizontal;
+                       tableEditor.horizontalAlignment = layoutData.horizontalAlignment;
+                       tableEditor.minimumWidth = layoutData.minimumWidth;
+               }
+
+               public ViewerCell getFocusCell() {
+                       if (focusCellManager != null) {
+                               return focusCellManager.getFocusCell();
+                       }
+                       return super.getFocusCell();
+               }
+
+               protected void updateFocusCell(ViewerCell focusCell,
+                               ColumnViewerEditorActivationEvent event) {
+                       // Update the focus cell when we activated the editor with these 2
+                       // events
+                       if (event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC
+                                       || event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL) {
+                               if (focusCellManager != null) {
+                                       try {
+                                               if (DEBUG)System.err.println("FOCUS CELL: " + focusCell);
+                                               
+                                               Method m = AbstractTableViewer.class.getDeclaredMethod(
+                                                               "getSelectionFromWidget");
+                                               m.setAccessible(true);
+                                               @SuppressWarnings("rawtypes")
+                                               List l = (List) m.invoke(getViewer());
+                                               if (focusCellManager != null) {
+                                                       m = focusCellManager
+                                                                       .getClass()
+                                                                       .getSuperclass()
+                                                                       .getDeclaredMethod("setFocusCell",
+                                                                                       new Class[] { ViewerCell.class });
+                                                       m.setAccessible(true);
+                                                       m.invoke(focusCellManager,
+                                                                       new Object[] { focusCell });
+                                               }
+                                               if (!l.contains(focusCell.getElement())) {
+                                                       getViewer().setSelection(
+                                                                       new StructuredSelection(focusCell
+                                                                                       .getElement()));
+                                               }
+                                       } catch (SecurityException e) {
+                                               e.printStackTrace();
+                                       } catch (IllegalArgumentException e) {
+                                               e.printStackTrace();
+                                       } catch (IllegalAccessException e) {
+                                               e.printStackTrace();
+                                       } catch (NoSuchMethodException e) {
+                                               e.printStackTrace();
+                                       } catch (InvocationTargetException e) {
+                                               e.printStackTrace();
+                                       }
+                               }
+                       }
+               }
+
+               protected void processTraverseEvent(int columnIndex, ViewerRow row,
+                               TraverseEvent event) {
+                       ViewerCell cell2edit = null;
+                       if (event.detail == SWT.TRAVERSE_TAB_PREVIOUS) {
+                               event.doit = false;
+                               if ((event.stateMask & SWT.CTRL) == SWT.CTRL
+                                               && (feature & TABBING_VERTICAL) == TABBING_VERTICAL) {
+                                       cell2edit = searchCellAboveBelow(row, getViewer(),
+                                                       columnIndex, true);
+                               } else if ((feature & TABBING_HORIZONTAL) == TABBING_HORIZONTAL) {
+                                       cell2edit = searchPreviousCell(row,
+                                                       row.getCell(columnIndex), row.getCell(columnIndex),
+                                                       getViewer());
+                               }
+                       } else if (event.detail == SWT.TRAVERSE_TAB_NEXT) {
+                               event.doit = false;
+                               if ((event.stateMask & SWT.CTRL) == SWT.CTRL
+                                               && (feature & TABBING_VERTICAL) == TABBING_VERTICAL) {
+                                       cell2edit = searchCellAboveBelow(row, getViewer(),
+                                                       columnIndex, false);
+                               } else if ((feature & TABBING_HORIZONTAL) == TABBING_HORIZONTAL) {
+                                       cell2edit = searchNextCell(row, row.getCell(columnIndex),
+                                                       row.getCell(columnIndex), getViewer());
+                               }
+                       }
+                       if (DEBUG) System.err.println("NEXT CELL: " + cell2edit);
+                       if (cell2edit != null) {
+                               getViewer().getControl().setRedraw(false);
+                               ColumnViewerEditorActivationEvent acEvent = new ColumnViewerEditorActivationEvent(
+                                               cell2edit, event);
+                               try {
+                                       Method m = ColumnViewer.class
+                                                       .getDeclaredMethod(
+                                                                       "triggerEditorActivationEvent",
+                                                                       new Class[] { ColumnViewerEditorActivationEvent.class });
+                                       m.setAccessible(true);
+                                       m.invoke(getViewer(), new Object[] { acEvent });
+                               } catch (SecurityException e) {
+                                       e.printStackTrace();
+                               } catch (NoSuchMethodException e) {
+                                       e.printStackTrace();
+                               } catch (IllegalArgumentException e) {
+                                       e.printStackTrace();
+                               } catch (IllegalAccessException e) {
+                                       e.printStackTrace();
+                               } catch (InvocationTargetException e) {
+                                       e.printStackTrace();
+                               }
+                               getViewer().getControl().setRedraw(true);
+                       }
+               }
+
+               private ViewerCell searchCellAboveBelow(ViewerRow row,
+                               ColumnViewer viewer, int columnIndex, boolean above) {
+                       ViewerCell rv = null;
+                       ViewerRow newRow = null;
+                       if (above) {
+                               newRow = row.getNeighbor(ViewerRow.ABOVE, false);
+                       } else {
+                               newRow = row.getNeighbor(ViewerRow.BELOW, false);
+                       }
+                       try {
+                               if (newRow != null) {
+                                       Method m = ColumnViewer.class.getDeclaredMethod(
+                                                       "getViewerColumn", new Class[] { int.class });
+                                       m.setAccessible(true);
+                                       ViewerColumn column = (ViewerColumn) m.invoke(viewer,
+                                                       new Object[] { new Integer(columnIndex) });
+                                       m = ViewerColumn.class.getDeclaredMethod(
+                                                       "getEditingSupport");
+                                       m.setAccessible(true);
+                                       EditingSupport es = (EditingSupport) m.invoke(column);
+                                       if (column != null && es != null) {
+                                               m = EditingSupport.class.getDeclaredMethod("canEdit",
+                                                               new Class[] { Object.class });
+                                               m.setAccessible(true);
+                                               Boolean b = (Boolean) m.invoke(es,
+                                                               new Object[] { newRow.getItem().getData() });
+                                               if (b.booleanValue()) {
+                                                       rv = newRow.getCell(columnIndex);
+                                               }
+                                       } else {
+                                               rv = searchCellAboveBelow(newRow, viewer, columnIndex,
+                                                               above);
+                                       }
+                               }
+                       } catch (Exception e) {
+                               e.printStackTrace();
+                       }
+                       return rv;
+               }
+
+               private ViewerCell searchPreviousCell(ViewerRow row,
+                               ViewerCell currentCell, ViewerCell originalCell,
+                               ColumnViewer viewer) {
+                       ViewerCell rv = null;
+                       ViewerCell previousCell;
+                       if (currentCell != null) {
+                               previousCell = getNeighbor(currentCell, ViewerCell.LEFT, true);
+                       } else {
+                               if (row.getColumnCount() != 0) {
+                                       previousCell = row.getCell(getCreationIndex(row,
+                                                       row.getColumnCount() - 1));
+                               } else {
+                                       previousCell = row.getCell(0);
+                               }
+                       }
+                       // No endless loop
+                       if (originalCell.equals(previousCell)) {
+                               return null;
+                       }
+                       if (previousCell != null) {
+                               if (isCellEditable(viewer, previousCell)) {
+                                       rv = previousCell;
+                               } else {
+                                       rv = searchPreviousCell(row, previousCell, originalCell,
+                                                       viewer);
+                               }
+                       } else {
+                               if ((feature & TABBING_CYCLE_IN_ROW) == TABBING_CYCLE_IN_ROW) {
+                                       rv = searchPreviousCell(row, null, originalCell, viewer);
+                               } else if ((feature & TABBING_MOVE_TO_ROW_NEIGHBOR) == TABBING_MOVE_TO_ROW_NEIGHBOR) {
+                                       ViewerRow rowAbove = row
+                                                       .getNeighbor(ViewerRow.ABOVE, false);
+                                       if (rowAbove != null) {
+                                               rv = searchPreviousCell(rowAbove, null, originalCell,
+                                                               viewer);
+                                       }
+                               }
+                       }
+                       return rv;
+               }
+
+               private ViewerCell searchNextCell(ViewerRow row,
+                               ViewerCell currentCell, ViewerCell originalCell,
+                               ColumnViewer viewer) {
+                       ViewerCell rv = null;
+                       ViewerCell nextCell;
+                       if (currentCell != null) {
+                               nextCell = getNeighbor(currentCell, ViewerCell.RIGHT, true);
+                       } else {
+                               nextCell = row.getCell(getCreationIndex(row, 0));
+                       }
+                       // No endless loop
+                       if (originalCell.equals(nextCell)) {
+                               return null;
+                       }
+                       if (nextCell != null) {
+                               if (isCellEditable(viewer, nextCell)) {
+                                       rv = nextCell;
+                               } else {
+                                       rv = searchNextCell(row, nextCell, originalCell, viewer);
+                               }
+                       } else {
+                               if ((feature & TABBING_CYCLE_IN_ROW) == TABBING_CYCLE_IN_ROW) {
+                                       rv = searchNextCell(row, null, originalCell, viewer);
+                               } else if ((feature & TABBING_MOVE_TO_ROW_NEIGHBOR) == TABBING_MOVE_TO_ROW_NEIGHBOR) {
+                                       ViewerRow rowBelow = row
+                                                       .getNeighbor(ViewerRow.BELOW, false);
+                                       if (rowBelow != null) {
+                                               rv = searchNextCell(rowBelow, null, originalCell,
+                                                               viewer);
+                                       }
+                               }
+                       }
+                       return rv;
+               }
+
+               private boolean isCellEditable(ColumnViewer viewer, ViewerCell cell) {
+                       try {
+                               Method m = ColumnViewer.class.getDeclaredMethod(
+                                               "getViewerColumn", new Class[] { int.class });
+                               m.setAccessible(true);
+                               ViewerColumn column = (ViewerColumn) m.invoke(viewer,
+                                               new Object[] { new Integer(cell.getColumnIndex()) });
+                               m = ViewerColumn.class.getDeclaredMethod("getEditingSupport");
+                               m.setAccessible(true);
+                               EditingSupport es = (EditingSupport) m.invoke(column);
+                               if (column != null && es != null) {
+                                       m = EditingSupport.class.getDeclaredMethod("canEdit",
+                                                       new Class[] { Object.class });
+                                       m.setAccessible(true);
+                                       // return true;
+                                       Boolean b = (Boolean) m.invoke(es,
+                                                       new Object[] { cell.getElement() });
+                                       return b.booleanValue();
+                               }
+                       } catch (Exception e) {
+                               e.printStackTrace();
+                       }
+                       return false;
+               }
+       }
+       
+       // Reimplementation of ViewerCell-Methods
+       private static int getVisualIndex(ViewerRow row, int creationIndex) {
+               TableItem item = (TableItem) row.getItem();
+               int[] order = item.getParent().getColumnOrder();
+               for (int i = 0; i < order.length; i++) {
+                       if (order[i] == creationIndex) {
+                               return i;
+                       }
+               }
+               return creationIndex;
+       }
+       
+       private static int getCreationIndex(ViewerRow row, int visualIndex) {
+               TableItem item = (TableItem) row.getItem();
+               if (item != null && !item.isDisposed() /*
+                                                                                                * && hasColumns() &&
+                                                                                                * isValidOrderIndex
+                                                                                                * (visualIndex)
+                                                                                                */) {
+                       return item.getParent().getColumnOrder()[visualIndex];
+               }
+               return visualIndex;
+       }
+       
+       private static ViewerCell getCellAtVisualIndex(ViewerRow row,
+                       int visualIndex) {
+               return getCell(row, getCreationIndex(row, visualIndex));
+       }
+
+       private static boolean isVisible(ViewerCell cell) {
+               return getWidth(cell) > 0;
+       }
+
+       private static int getWidth(ViewerCell cell) {
+               TableItem item = (TableItem) cell.getViewerRow().getItem();
+               return item.getParent().getColumn(cell.getColumnIndex()).getWidth();
+       }
+
+       private static ViewerCell getCell(ViewerRow row, int index) {
+               return row.getCell(index);
+       }
+       
+       
+}