]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Sync git svn branch with SVN repository r33334.
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 14 Oct 2016 12:00:33 +0000 (15:00 +0300)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 14 Oct 2016 12:00:33 +0000 (15:00 +0300)
refs #6654
refs #6756

bundles/org.simantics.browsing.ui.nattable/images/transparent.png [new file with mode: 0644]
bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/GENatTableThemeConfiguration.java
bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/GETreeLayer.java
bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/GETreeRowModel.java
bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/KeyToSelectionAdapter.java [new file with mode: 0644]
bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/NatTableGraphExplorer.java
bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/NatTableSelectionAdaptor.java
bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/TreeNode.java
bundles/org.simantics.modeling/src/org/simantics/modeling/ModelingUtils.java

diff --git a/bundles/org.simantics.browsing.ui.nattable/images/transparent.png b/bundles/org.simantics.browsing.ui.nattable/images/transparent.png
new file mode 100644 (file)
index 0000000..e9cd02b
Binary files /dev/null and b/bundles/org.simantics.browsing.ui.nattable/images/transparent.png differ
index bcb8bba53a445da1172ffebca139e83bd6486ee5..41d5f2e4617bfe6b628e881186371e3a811d0fb5 100644 (file)
@@ -1,13 +1,19 @@
 package org.simantics.browsing.ui.nattable;\r
 \r
+import org.eclipse.core.runtime.FileLocator;\r
+import org.eclipse.core.runtime.Path;\r
+import org.eclipse.nebula.widgets.nattable.painter.cell.BackgroundPainter;\r
 import org.eclipse.nebula.widgets.nattable.painter.cell.TextPainter;\r
 import org.eclipse.nebula.widgets.nattable.painter.cell.decorator.PaddingDecorator;\r
 import org.eclipse.nebula.widgets.nattable.style.theme.ModernNatTableThemeConfiguration;\r
+import org.eclipse.nebula.widgets.nattable.tree.painter.IndentedTreeImagePainter;\r
+import org.eclipse.nebula.widgets.nattable.tree.painter.TreeImagePainter;\r
+import org.eclipse.nebula.widgets.nattable.ui.util.CellEdgeEnum;\r
 import org.eclipse.nebula.widgets.nattable.util.GUIHelper;\r
 \r
 public class GENatTableThemeConfiguration extends ModernNatTableThemeConfiguration{\r
        \r
-       public GENatTableThemeConfiguration(GETreeData treeData) {\r
+       public GENatTableThemeConfiguration(GETreeData treeData, int style) {\r
                super();\r
                this.oddRowBgColor = GUIHelper.getColor(250, 250, 250);\r
                this.defaultCellPainter =\r
@@ -20,6 +26,55 @@ public class GENatTableThemeConfiguration extends ModernNatTableThemeConfigurati
                                        0,\r
                                        5,\r
                                        false)));\r
+               \r
+                TreeImagePainter treeImagePainter =\r
+                       new TreeImagePainter(\r
+                               false,\r
+                               GUIHelper.getImage("right"), //$NON-NLS-1$\r
+                               GUIHelper.getImage("right_down"), //$NON-NLS-1$\r
+                               GUIHelper.getImageByURL("transparent", \r
+                                               FileLocator.find(Activator.getDefault().getBundle(), \r
+                                               new Path("images/transparent.png"), null))); //$NON-NLS-1$\r
+               this.treeStructurePainter =\r
+                       new BackgroundPainter(\r
+                               new PaddingDecorator(\r
+                                       new IndentedTreeImagePainter(\r
+                                               10,\r
+                                               null,\r
+                                               CellEdgeEnum.LEFT,\r
+                                               treeImagePainter,\r
+                                               false,\r
+                                               2,\r
+                                               true),\r
+                                       0,\r
+                                       5,\r
+                                       0,\r
+                                       5,\r
+                                       false));\r
+               TreeImagePainter treeSelectionImagePainter =\r
+                       new TreeImagePainter(\r
+                               false,\r
+                               GUIHelper.getImage("right_inv"), //$NON-NLS-1$\r
+                               GUIHelper.getImage("right_down_inv"), //$NON-NLS-1$\r
+                               GUIHelper.getImageByURL("transparent", \r
+                                               FileLocator.find(Activator.getDefault().getBundle(), \r
+                                               new Path("images/transparent.png"), null))); //$NON-NLS-1$\r
+               this.treeStructureSelectionPainter =\r
+                       new BackgroundPainter(\r
+                               new PaddingDecorator(\r
+                                       new IndentedTreeImagePainter(\r
+                                               10,\r
+                                               null,\r
+                                               CellEdgeEnum.LEFT,\r
+                                               treeSelectionImagePainter,\r
+                                               false,\r
+                                               2,\r
+                                               true),\r
+                                       0,\r
+                                       5,\r
+                                       0,\r
+                                       5,\r
+                                       false));\r
        }\r
 \r
 }\r
index dbc30050ae63a0ac038bcc441cec4ddbb358bfa2..309e4daa85f5bfa084416b043449d90be8250b65 100644 (file)
@@ -1,9 +1,9 @@
 package org.simantics.browsing.ui.nattable;\r
 \r
 import java.util.ArrayList;\r
-import java.util.Collection;\r
 import java.util.Collections;\r
 import java.util.Comparator;\r
+import java.util.HashSet;\r
 import java.util.Iterator;\r
 import java.util.List;\r
 import java.util.Set;\r
@@ -31,7 +31,7 @@ import it.unimi.dsi.fastutil.ints.IntRBTreeSet;
 public class GETreeLayer  extends TreeLayer2 {\r
 \r
        //Set<IEcoReportTask> collapsed = new HashSet<IEcoReportTask>();\r
-       Set<TreeNode> collapsed = new IdentityHashSet<TreeNode>();\r
+       Set<TreeNode> expanded = new IdentityHashSet<TreeNode>();\r
        GETreeData treeData;\r
        Comparator<int[]> comparator = new FirstElementComparator();\r
        \r
@@ -51,7 +51,7 @@ public class GETreeLayer  extends TreeLayer2 {
        @Override\r
        public void collapseTreeRow(int parentIndex) {\r
                TreeNode task = treeData.getDataAtIndex(parentIndex);\r
-               collapsed.add(task);\r
+               expanded.remove(task);\r
                task.setExpanded(false);\r
                super.collapseTreeRow(parentIndex);\r
        }\r
@@ -73,7 +73,7 @@ public class GETreeLayer  extends TreeLayer2 {
        @Override\r
        public void expandTreeRow(int parentIndex) {\r
                TreeNode task = treeData.getDataAtIndex(parentIndex);\r
-               collapsed.remove(task);\r
+               expanded.add(task);\r
                task.setExpanded(true);\r
                super.expandTreeRow(parentIndex);\r
        }\r
@@ -117,7 +117,7 @@ public class GETreeLayer  extends TreeLayer2 {
                                TreeNode task = treeData.getDataAtIndex(parentIndex);\r
                                if (task != null) {\r
                                        task.setExpanded(false);\r
-                                       collapsed.add(task);\r
+                                       expanded.remove(task);\r
                                }\r
                                rowIndexes.addAll(getModel().collapse(parentIndex));\r
                        }\r
@@ -145,7 +145,7 @@ public class GETreeLayer  extends TreeLayer2 {
                        if (parentIndex >= 0) {\r
                                TreeNode task = treeData.getDataAtIndex(parentIndex);\r
                                task.setExpanded(false);\r
-                               collapsed.add(task);\r
+                               expanded.remove(task);\r
                                rowIndexes.addAll(getModel().collapse(parentIndex));\r
                        }\r
                }\r
@@ -175,7 +175,7 @@ public class GETreeLayer  extends TreeLayer2 {
                                \r
                        } \r
                        t.setExpanded(false);\r
-                       collapsed.add(t);\r
+                       expanded.remove(t);\r
                        getModel().collapse(i);\r
                        \r
                }\r
@@ -189,8 +189,9 @@ public class GETreeLayer  extends TreeLayer2 {
                for (int parentIndex : parentIndices) {\r
                        TreeNode task = treeData.getDataAtIndex(parentIndex);\r
                        task.setExpanded(true);\r
-                       collapsed.remove(task);\r
+                       expanded.add(task);\r
                        rowIndexes.addAll(getModel().expand(parentIndex));\r
+                       rowIndexes.add(parentIndex);\r
                }\r
                \r
                //Implementation uses tree set, so removing in reverse order is faster.\r
@@ -207,7 +208,7 @@ public class GETreeLayer  extends TreeLayer2 {
                for (int parentIndex : parentIndices) {\r
                        TreeNode task = treeData.getDataAtIndex(parentIndex);\r
                        task.setExpanded(true);\r
-                       collapsed.remove(task);\r
+                       expanded.add(task);\r
                        rowIndexes.addAll(getModel().expand(parentIndex));\r
                }\r
                \r
@@ -220,20 +221,20 @@ public class GETreeLayer  extends TreeLayer2 {
                fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));\r
        }\r
        \r
-       public void expandAllRows() {\r
-               Collection<Integer> parentIndices = getHiddenRowIndexes();\r
-               List<Integer> rowIndexes = new ArrayList<Integer>();\r
-               for (int parentIndex : parentIndices) {\r
-                       rowIndexes.addAll(getModel().expand(parentIndex));\r
-               }\r
-               for (TreeNode t : collapsed)\r
-                       t.setExpanded(true);\r
-               collapsed.clear();\r
-               getHiddenRowIndexes().clear();\r
-               ((GETreeRowModel)getModel()).clear();\r
-               invalidateCache();\r
-               fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));\r
-       }\r
+//     public void expandAllRows() {\r
+//             Collection<Integer> parentIndices = getHiddenRowIndexes();\r
+//             List<Integer> rowIndexes = new ArrayList<Integer>();\r
+//             for (int parentIndex : parentIndices) {\r
+//                     rowIndexes.addAll(getModel().expand(parentIndex));\r
+//             }\r
+//             for (TreeNode t : collapsed)\r
+//                     t.setExpanded(true);\r
+//             collapsed.clear();\r
+//             getHiddenRowIndexes().clear();\r
+//             ((GETreeRowModel)getModel()).clear();\r
+//             invalidateCache();\r
+//             fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));\r
+//     }\r
        \r
        @Override\r
        protected void invalidateCache() {\r
@@ -242,6 +243,23 @@ public class GETreeLayer  extends TreeLayer2 {
                hiddenPos.add(new int[]{0,0});\r
        }\r
        \r
+       private void _collapseAllRows() {\r
+               int count = treeData.getElementCount();\r
+               List <Integer> rowIndexes = new ArrayList<Integer>(count);\r
+               for (int i = 0; i < count; i++) {\r
+                       TreeNode t = treeData.getDataAtIndex(i);\r
+                       // we don't want to hide the roots of the tree\r
+                       if (!treeData.isRoot(t)) { \r
+                               rowIndexes.add(i);\r
+                               \r
+                       } \r
+                       getModel().collapse(i);\r
+                       \r
+               }\r
+               this.getHiddenRowIndexes().addAll(rowIndexes);\r
+               invalidateCache();\r
+       }\r
+       \r
        @Override\r
        public void handleLayerEvent(ILayerEvent event) {\r
                // Currently sorting is implemented by sorting the underlaying list.\r
@@ -251,31 +269,68 @@ public class GETreeLayer  extends TreeLayer2 {
                // Another option would use some sort of sorting layers, so that the original data is kept intact, and\r
                // sorting layer would map the row indexes to sorted row positions.\r
                \r
-               // preserve collapsed nodes \r
+               // preserve expanded nodes \r
                Set<TreeNode> coll = null;\r
+//             int hiddenCount = 0;\r
                if (event instanceof IStructuralChangeEvent) {\r
                        IStructuralChangeEvent structuralChangeEvent = (IStructuralChangeEvent) event;\r
                        if (structuralChangeEvent.isVerticalStructureChanged()) {\r
-                               // expand old indices\r
-                               ((GETreeRowModel)getModel()).clear();\r
+                               // store old indices\r
+                               internalRefresh = true;\r
+                               ((GETreeRowModel<?>)getModel()).clear();\r
+//                             hiddenCount = getHiddenRowIndexes().size();\r
                                getHiddenRowIndexes().clear();\r
-                               coll = collapsed;\r
+                               // store expanded nodes and clear disposed nodes.\r
+                               coll = new HashSet<>();\r
+                               for (TreeNode n : expanded)\r
+                                       if (!n.isDisposed())\r
+                                               coll.add(n);\r
+                               expanded.clear();\r
+                               expanded.addAll(coll);\r
+                               // filter hidden nodes (nodes that have collapsed ancestors)\r
+                               coll.clear();\r
+                               for (TreeNode n : expanded)\r
+                                       if (!n.isHidden())\r
+                                               coll.add(n);\r
                        }\r
                }\r
                super.handleLayerEvent(event);\r
                if (coll != null) {\r
-                       // collapse new indices\r
+                       _collapseAllRows();\r
+                       // expand new indices\r
                        int ind[] = new int[coll.size()];\r
                        Iterator<TreeNode> iter = coll.iterator();\r
                        for (int i = 0; i < ind.length; i++) {\r
                                ind[i] = treeData.indexOf(iter.next());\r
                        }\r
-                       collapseTreeRow(ind);\r
+                       expandTreeRow(ind);\r
+//                     if (getHiddenRowIndexes().size() != hiddenCount) {\r
+//                             System.out.println(getHiddenRowIndexes().size() + " != " + hiddenCount);\r
+//                             ((GETreeRowModel<?>)getModel()).clear();\r
+//                             getHiddenRowIndexes().clear();\r
+//                             _collapseAllRows();\r
+//                             //collapseAll();\r
+//                             // expand new indices\r
+//                             iter = coll.iterator();\r
+//                             for (int i = 0; i < ind.length; i++) {\r
+//                                     ind[i] = treeData.indexOf(iter.next());\r
+//                             }\r
+//                             expandTreeRow(ind);\r
+//                     }\r
+                       internalRefresh = false;\r
                }\r
        }\r
        \r
-       public Set<TreeNode> getCollapsed() {\r
-               return collapsed;\r
+       private boolean internalRefresh = false;\r
+       \r
+       public void fireLayerEvent(ILayerEvent event) {\r
+               if (!internalRefresh)\r
+                       super.fireLayerEvent(event);\r
+               \r
+       }\r
+       \r
+       public Set<TreeNode> getExpanded() {\r
+               return expanded;\r
        }\r
        \r
        List<int[]> hiddenPos;\r
index ebfb962db7a129cf7af9cdc93e7f64f433d2585c..762b47ce008ab29f1e96d8ed520ba402d0e685d5 100644 (file)
@@ -22,7 +22,7 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
 public class GETreeRowModel<T> implements ITreeRowModel<T>{\r
        //private final HashSet<Integer> parentIndexes = new HashSet<Integer>();\r
        //private final TIntHashSet parentIndexes = new TIntHashSet(1000, 0.8f);\r
-       private final IntOpenHashSet parentIndexes = new IntOpenHashSet();\r
+       private final IntOpenHashSet expandedIndexes = new IntOpenHashSet();\r
 \r
        private final Collection<ITreeRowModelListener> listeners = new HashSet<ITreeRowModelListener>();\r
 \r
@@ -59,11 +59,11 @@ public class GETreeRowModel<T> implements ITreeRowModel<T>{
        }\r
        \r
        public boolean isCollapsed(int index) {\r
-               return this.parentIndexes.contains(index);\r
+               return !this.expandedIndexes.contains(index);\r
        }\r
 \r
        public void clear() {\r
-               this.parentIndexes.clear();\r
+               this.expandedIndexes.clear();\r
        }\r
        \r
        @Override\r
@@ -73,16 +73,18 @@ public class GETreeRowModel<T> implements ITreeRowModel<T>{
 \r
        @Override\r
        public List<Integer> collapse(int index) {\r
-               this.parentIndexes.add(index);\r
+               this.expandedIndexes.remove(index);\r
                notifyListeners();\r
-               return getChildIndexes(index);\r
+               List<Integer> list = getChildIndexes(index);\r
+               //this.parentIndexes.addAll(list);\r
+               return list;\r
        }\r
        \r
        \r
 \r
        @Override\r
        public List<Integer> expand(int index) {\r
-               this.parentIndexes.remove(index);\r
+               this.expandedIndexes.add(index);\r
                notifyListeners();\r
                List<Integer> children = getExpandedChildIndexes(index);\r
                return children;\r
@@ -90,7 +92,6 @@ public class GETreeRowModel<T> implements ITreeRowModel<T>{
        \r
        @Override\r
        public List<Integer> collapseAll() {\r
-               // TODO Auto-generated method stub\r
                return null;\r
        }\r
        \r
@@ -195,7 +196,7 @@ public class GETreeRowModel<T> implements ITreeRowModel<T>{
                        int index = this.treeData.indexOf(child);\r
                        if (index >= 0) {\r
                                result.add(index);\r
-                               if (!parentIndexes.contains(index))\r
+                               if (expandedIndexes.contains(index))\r
                                        result.addAll(getExpandedChildIndexes(index));\r
                        } else {\r
                                result.addAll(getExpandedChildIndexes(child));\r
@@ -211,7 +212,7 @@ public class GETreeRowModel<T> implements ITreeRowModel<T>{
                        int index = this.treeData.indexOf(child);\r
                        if (index >= 0) {\r
                                result.add(index);\r
-                               if (!parentIndexes.contains(index))\r
+                               if (expandedIndexes.contains(index))\r
                                        result.addAll(getExpandedChildIndexes(index));\r
                        } else {\r
                                result.addAll(getExpandedChildIndexes(child));\r
diff --git a/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/KeyToSelectionAdapter.java b/bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/KeyToSelectionAdapter.java
new file mode 100644 (file)
index 0000000..9d43c35
--- /dev/null
@@ -0,0 +1,163 @@
+package org.simantics.browsing.ui.nattable;\r
+\r
+import java.util.Collection;\r
+import java.util.List;\r
+import java.util.regex.Pattern;\r
+\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.nebula.widgets.nattable.NatTable;\r
+import org.eclipse.swt.events.KeyAdapter;\r
+import org.eclipse.swt.events.KeyEvent;\r
+import org.simantics.browsing.ui.GraphExplorer;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
+\r
+/**\r
+ * Selects tree items based on pressed key events.<p>\r
+ * \r
+ * The default implementation of SWT.Tree (Windows?) uses only the the first column when matching the items.<p>\r
+ * \r
+ * This implementation checks all columns. Override <pre>matches(), matchesColumn()</pre> for customized behavior.<p>\r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class KeyToSelectionAdapter extends KeyAdapter {\r
+\r
+       private static final int KEY_INPUT_DELAY = 500;\r
+       \r
+    private final NatTableGraphExplorer          explorer;\r
+\r
+    private String matcher = "";\r
+    private int prevEvent = 0;\r
+    private int columns = 0;\r
+        \r
+    protected Pattern alphaNum;\r
+    \r
+    /**\r
+     * @param contextProvider\r
+     * @param explorer\r
+     */\r
+    public KeyToSelectionAdapter(GraphExplorer explorer) {\r
+        assert explorer != null;\r
+\r
+        this.explorer = (NatTableGraphExplorer)explorer;\r
+        this.alphaNum = Pattern.compile("\\p{Alnum}");\r
+    }\r
+\r
+    @Override\r
+    public void keyPressed(KeyEvent e) {\r
+       if (explorer.isDisposed())\r
+            return;\r
+\r
+         \r
+         if (!alphaNum.matcher(Character.toString(e.character)).matches())\r
+                return;\r
+         // concatenate / replace matcher.\r
+         if ((e.time - prevEvent) > KEY_INPUT_DELAY )\r
+                matcher = "";\r
+        prevEvent = e.time;\r
+        matcher = matcher += Character.toString(e.character);\r
+\r
+        \r
+        //TreeItem item = null;\r
+        NatTable tree = explorer.getControl();\r
+        columns = explorer.getColumns().length;\r
+        \r
+        IStructuredSelection sel = (IStructuredSelection)explorer.getWidgetSelection();\r
+        Collection<RowSelectionItem> selected = AdaptionUtils.adaptToCollection(sel, RowSelectionItem.class);\r
+        \r
+         \r
+        TreeNode item = find(tree, selected);\r
+        \r
+        if (item == null && matcher.length() > 1) {\r
+                matcher = matcher.substring(matcher.length()-1);\r
+                item = find(tree, selected);\r
+        }\r
+        \r
+        if (item != null) {\r
+                explorer.select(item);\r
+                explorer.show(item);\r
+//                      tree.select(item);\r
+//                      tree.showItem(item);\r
+                \r
+                       \r
+                } \r
+        // without this the default handling would take over.\r
+        e.doit = false;\r
+    }\r
+    \r
+    private TreeNode previous = null;\r
+    private boolean foundPrev = false;\r
+    \r
+       private TreeNode find(NatTable tree, Collection<RowSelectionItem> selected) {\r
+               TreeNode item = null;\r
+\r
+               List<TreeNode> items = explorer.getItems();\r
+               \r
+               if (selected.size() == 0) {\r
+                       previous = null;\r
+                       foundPrev = true;\r
+                       item = findItem(items);\r
+\r
+               } else {\r
+                       previous = selected.iterator().next().item;\r
+                       foundPrev = false;\r
+                       item = findItem(items);\r
+                       if (item == null) {\r
+                               previous = null;\r
+                               foundPrev = true;\r
+                               item = findItem(items);\r
+                       }\r
+               }\r
+               return item;\r
+       }\r
+    \r
+    private TreeNode findItem(List<TreeNode> items) {\r
+       for (int i = 0; i < items.size(); i++) {\r
+               TreeNode item = items.get(i);\r
+               if (item != previous) {\r
+                       if (foundPrev && matches(item, columns, matcher))\r
+                               return item;\r
+                       \r
+               } else {\r
+                       foundPrev = true;\r
+               }\r
+       }\r
+       return null;\r
+    }\r
+    \r
+    \r
+    /**\r
+     * \r
+     * @param item\r
+     * @param depth Depth of the item in the tree.\r
+     * @param columns Number of columns.\r
+     * @param string Matching string.\r
+     * @return\r
+     */\r
+    protected boolean matches(TreeNode item, int columns, String matcher) {\r
+       for (int c = 0; c < columns; c++) {     \r
+                       if (matchesColumn(item, c, matcher)) {\r
+                               return true;\r
+                       }\r
+               }\r
+       return false;\r
+    }\r
+    \r
+    /**\r
+     * \r
+     * @param item\r
+     * @param column\r
+     * @param matcher\r
+     * @return\r
+     */\r
+    protected boolean matchesColumn(TreeNode item, int column, String matcher) {\r
+       String text = item.getValueString(column);\r
+               if (text.toLowerCase().startsWith(matcher)) {\r
+                       return true;\r
+               }\r
+               return false;\r
+    }\r
+\r
+\r
+}\r
index aa2c5b21e568485fdfdd709534a2619cf252b711..f38f5fd9350bae2d3b5f4ecf338eb396afb2527b 100644 (file)
@@ -28,8 +28,6 @@ import org.eclipse.core.runtime.MultiStatus;
 import org.eclipse.core.runtime.Platform;\r
 import org.eclipse.core.runtime.Status;\r
 import org.eclipse.core.runtime.jobs.Job;\r
-import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.layout.TreeColumnLayout;\r
 import org.eclipse.jface.resource.ColorDescriptor;\r
 import org.eclipse.jface.resource.DeviceResourceException;\r
 import org.eclipse.jface.resource.DeviceResourceManager;\r
@@ -55,11 +53,13 @@ import org.eclipse.nebula.widgets.nattable.coordinate.Range;
 import org.eclipse.nebula.widgets.nattable.data.IDataProvider;\r
 import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;\r
 import org.eclipse.nebula.widgets.nattable.data.convert.DefaultDisplayConverter;\r
+import org.eclipse.nebula.widgets.nattable.data.validate.IDataValidator;\r
+import org.eclipse.nebula.widgets.nattable.data.validate.ValidationFailedException;\r
 import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;\r
 import org.eclipse.nebula.widgets.nattable.edit.EditConfigHelper;\r
 import org.eclipse.nebula.widgets.nattable.edit.ICellEditHandler;\r
-import org.eclipse.nebula.widgets.nattable.edit.config.DefaultEditBindings;\r
 import org.eclipse.nebula.widgets.nattable.edit.config.DefaultEditConfiguration;\r
+import org.eclipse.nebula.widgets.nattable.edit.config.DialogErrorHandling;\r
 import org.eclipse.nebula.widgets.nattable.edit.editor.AbstractCellEditor;\r
 import org.eclipse.nebula.widgets.nattable.edit.editor.ComboBoxCellEditor;\r
 import org.eclipse.nebula.widgets.nattable.edit.editor.ICellEditor;\r
@@ -85,14 +85,18 @@ import org.eclipse.nebula.widgets.nattable.layer.LabelStack;
 import org.eclipse.nebula.widgets.nattable.layer.cell.ColumnOverrideLabelAccumulator;\r
 import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;\r
 import org.eclipse.nebula.widgets.nattable.layer.event.ILayerEvent;\r
-import org.eclipse.nebula.widgets.nattable.painter.cell.ICellPainter;\r
+import org.eclipse.nebula.widgets.nattable.painter.NatTableBorderOverlayPainter;\r
 import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;\r
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;\r
 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum;\r
+import org.eclipse.nebula.widgets.nattable.selection.command.SelectCellCommand;\r
 import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;\r
+import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes;\r
 import org.eclipse.nebula.widgets.nattable.style.DisplayMode;\r
+import org.eclipse.nebula.widgets.nattable.style.Style;\r
 import org.eclipse.nebula.widgets.nattable.ui.menu.AbstractHeaderMenuConfiguration;\r
 import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder;\r
+import org.eclipse.nebula.widgets.nattable.util.GUIHelper;\r
 import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;\r
 import org.eclipse.nebula.widgets.nattable.widget.EditModeEnum;\r
 import org.eclipse.swt.SWT;\r
@@ -106,7 +110,6 @@ import org.eclipse.swt.events.MouseEvent;
 import org.eclipse.swt.events.MouseListener;\r
 import org.eclipse.swt.events.SelectionListener;\r
 import org.eclipse.swt.graphics.Color;\r
-import org.eclipse.swt.graphics.GC;\r
 import org.eclipse.swt.graphics.Point;\r
 import org.eclipse.swt.graphics.RGB;\r
 import org.eclipse.swt.graphics.Rectangle;\r
@@ -202,11 +205,13 @@ import gnu.trove.map.hash.THashMap;
 import gnu.trove.map.hash.TObjectIntHashMap;\r
 \r
 /**\r
- * NatTable base GraphExplorer\r
+ * NatTable based GraphExplorer\r
+ * \r
+ * This GraphExplorer is not fully compatible with the other implementations, since it is not based on SWT.Tree. \r
+ * \r
+ * This implementation is useful in scenarios, where there are a lot of data to be displayed, the performance of NatTable is much better to SWT.Tree based implementations.\r
  * \r
  * \r
- * FIXME : asynchronous node loading does not work properly + check expanded/collapsed sate handling\r
- * TODO: InputValidators + input errors\r
  * TODO: ability to hide headers\r
  * TODO: code cleanup (copied from GraphExplorerImpl2) \r
  * \r
@@ -214,7 +219,7 @@ import gnu.trove.map.hash.TObjectIntHashMap;
  *\r
  */\r
 public class NatTableGraphExplorer extends GraphExplorerImplBase implements GraphExplorer{\r
-    public static final int      DEFAULT_MAX_CHILDREN                    = 1000;\r
+    public static final int      DEFAULT_MAX_CHILDREN                    = 10000;\r
        private static final boolean DEBUG_SELECTION_LISTENERS = false;\r
        private static final boolean DEBUG = false;\r
        \r
@@ -349,7 +354,7 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                originalFont = JFaceResources.getDefaultFontDescriptor();\r
 \r
                columns = new Column[0];\r
-               createNatTable();\r
+               createNatTable(style);\r
                layout = new NatTableColumnLayout(natTable, columnHeaderDataProvider, rowHeaderDataLayer);\r
                this.composite.setLayout(layout);\r
                                \r
@@ -531,8 +536,6 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
         //refreshColumnSizes();\r
         rootNode = new TreeNode(rootContext, explorerContext);\r
         if (DEBUG) System.out.println("setRoot " + rootNode);\r
-      \r
-       // viewer.setInput(rootNode);\r
         \r
         // Delay content reading.\r
         \r
@@ -545,8 +548,8 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                        public void run() {\r
                                if (rootNode != null) {\r
                                    rootNode.updateChildren();\r
+                                   rootNode.setExpanded(true);\r
                                    listReIndex();\r
-                                   natTable.refresh(true);\r
                                }\r
                        }\r
                });\r
@@ -554,9 +557,13 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
     }\r
     \r
     private synchronized void listReIndex() {\r
+       for (TreeNode n : list) {\r
+               n.setListIndex(-2);\r
+       }\r
        list.clear();\r
        for (TreeNode c : rootNode.getChildren())\r
                _insertToList(c);\r
+       natTable.refresh();\r
     }\r
     \r
     private void _insertToList(TreeNode n) {\r
@@ -567,6 +574,10 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
        }\r
     }\r
     \r
+    public List<TreeNode> getItems() {\r
+       return Collections.unmodifiableList(list);\r
+    }\r
+    \r
     private void initializeState() {\r
         if (persistor == null)\r
             return;\r
@@ -689,7 +700,7 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                     if (natTable.isDisposed())\r
                         return;\r
                     doSetColumns(columns, callback);\r
-                    natTable.refresh(true);\r
+                    natTable.refresh();\r
                     natTable.getParent().layout();\r
                 }\r
             });\r
@@ -1065,6 +1076,30 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
         \r
     }\r
     \r
+       public boolean select(TreeNode node) {\r
+               assertNotDisposed();\r
+\r
+               if (!list.contains(node)) {\r
+                       StructuredSelection s = new StructuredSelection();\r
+            selectionAdaptor.setSelection(s);\r
+            selectionProvider.setAndFireNonEqualSelection(s);\r
+                       return true;\r
+               }\r
+               selectionAdaptor.setSelection(new StructuredSelection(node));\r
+               return false;\r
+       }\r
+       \r
+       public void show(TreeNode node) {\r
+               int index = node.getListIndex();\r
+               \r
+               int position = treeLayer.getRowPositionByIndex(index);\r
+               if (position < 0) {\r
+                       treeLayer.expandToTreeRow(index);\r
+                       position = treeLayer.getRowPositionByIndex(index);\r
+               }\r
+               viewportLayer.moveRowPositionIntoViewport(position);\r
+       }\r
+    \r
     @Override\r
     public boolean selectPath(Collection<NodeContext> contexts) {\r
        \r
@@ -1171,7 +1206,6 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                else\r
                        treeLayer.collapseTreeRow(n.getListIndex());\r
        }\r
-       //viewer.setExpandedState(context, expanded);\r
        \r
     }\r
     \r
@@ -1179,7 +1213,6 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
     public void setAutoExpandLevel(int level) {\r
         this.autoExpandLevel = level;\r
         treeLayer.expandAllToLevel(level);\r
-        //viewer.setAutoExpandLevel(level);\r
     }\r
     \r
     int maxChildren = DEFAULT_MAX_CHILDREN;\r
@@ -1244,22 +1277,51 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                                if (element.isDisposed()) {\r
                                return;\r
                                }\r
-                       if (((TreeNode)element).updateChildren()) {\r
+                       if (element.updateChildren()) {\r
+                               if (DEBUG) {\r
+                                       System.out.println("Update Item updateChildren " + element.listIndex + " " + element);\r
+                                       printDebug(NatTableGraphExplorer.this);\r
+                               }\r
                                listReIndex();\r
-                               natTable.refresh(true);\r
-                               //viewer.refresh(element,true);\r
+                               if (!element.isHidden()) { \r
+                                       if (!element.isExpanded()) {\r
+                                               if (element.listIndex >= 0)\r
+                                                       treeLayer.collapseTreeRow(element.listIndex);\r
+                                               if (DEBUG) {\r
+                                                       System.out.println("Update Item collapse " + element.listIndex);\r
+                                                       printDebug(NatTableGraphExplorer.this);\r
+                                               }\r
+                                       } else {\r
+                                               for (TreeNode c : element.getChildren())\r
+                                                       c.initData();\r
+                                       }\r
+                               } else {\r
+                                       TreeNode p = element.getCollapsedAncestor();\r
+                                       if (p != null) {\r
+                                               if (element.listIndex >= 0)\r
+                                                       treeLayer.collapseTreeRow(element.listIndex);\r
+                                               if (p.listIndex >= 0) \r
+                                                       treeLayer.collapseTreeRow(p.listIndex);\r
+                                               if (DEBUG) {\r
+                                                       System.out.println("Update Item ancetor collapse " + p.listIndex);\r
+                                                       printDebug(NatTableGraphExplorer.this);\r
+                                               }\r
+                                       }\r
+                               }\r
                        } else {\r
-                               if (columnIndex >= 0) {\r
-                                       natTable.redraw();\r
-                                       //viewer.update(element, new String[]{columns[columnIndex].getKey()});\r
-                               } else {\r
-                                       natTable.redraw();\r
-                                       //viewer.refresh(element,true);\r
-                               }\r
+//                             if (columnIndex >= 0) {\r
+//                                     viewer.update(element, new String[]{columns[columnIndex].getKey()});\r
+//                             } else {\r
+//                                     viewer.refresh(element,true);\r
+//                             }\r
+                               natTable.redraw();\r
                        }\r
                        \r
-                       if (!element.isDisposed() && autoExpandLevel > 1 && !element.isExpanded() && element.getDepth() <= autoExpandLevel) {\r
+                       if (!element.autoExpanded && !element.isDisposed() && autoExpandLevel > 1 && !element.isExpanded() && element.getDepth() <= autoExpandLevel) {\r
                                expand = true;\r
+                               element.autoExpanded = true;\r
+                               element.initData();\r
+                               if (DEBUG) System.out.println("Update Item expand " + element.listIndex);\r
                                treeLayer.expandTreeRow(element.getListIndex());\r
                                //viewer.setExpandedState(element, true);\r
                                expand = false;\r
@@ -1267,8 +1329,6 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                        } else {\r
                                if (rootNode.updateChildren()) {\r
                                        listReIndex();\r
-                               natTable.refresh(true);\r
-                                       //viewer.refresh(rootNode,true);\r
                                }\r
                        }\r
        }\r
@@ -1296,11 +1356,13 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
     }\r
     \r
     private void update(final TreeNode element, final int columnIndex) {\r
-       if (DEBUG)System.out.println("update " + element + " " + columnIndex);\r
        if (natTable.isDisposed())\r
                return;\r
+       if (element != null && element.isDisposed())\r
+               return;\r
+       if (DEBUG) System.out.println("update " + element + " " + columnIndex);\r
        synchronized (pendingItems) {\r
-                       pendingItems.add(new UpdateItem(element, columnIndex));\r
+               pendingItems.add(new UpdateItem(element, columnIndex));\r
                        if (updating) return;\r
                        updateCounter++;\r
                        scheduleUpdater();\r
@@ -1308,14 +1370,14 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
     }\r
 \r
     private void update(final TreeNode element) {\r
-       if (DEBUG)System.out.println("update " + element);\r
+       \r
        if (natTable.isDisposed())\r
                return;\r
        if (element != null && element.isDisposed())\r
                return;\r
+       if (DEBUG) System.out.println("update " + element);\r
        synchronized (pendingItems) {\r
-               \r
-                       pendingItems.add(new UpdateItem(element));\r
+               pendingItems.add(new UpdateItem(element));\r
                        if (updating) return;\r
                        updateCounter++;\r
                        scheduleUpdater();\r
@@ -1449,7 +1511,7 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                return (double)dpi.x/96.0;\r
        }\r
     \r
-    private void createNatTable() {\r
+    private void createNatTable(int style) {\r
        GETreeData treeData = new GETreeData(list);\r
                GETreeRowModel<TreeNode> treeRowModel = new GETreeRowModel<TreeNode>(treeData);\r
                columnAccessor = new GEColumnAccessor(this);\r
@@ -1529,7 +1591,7 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                natTable.addConfiguration(new SingleClickSortConfiguration());\r
                //natTable.addLayerListener(this);\r
                \r
-               natTable.addConfiguration(new GENatTableThemeConfiguration(treeData));\r
+               natTable.addConfiguration(new GENatTableThemeConfiguration(treeData, style));\r
                natTable.addConfiguration(new NatTableHeaderMenuConfiguration(natTable));\r
                \r
                natTable.addConfiguration(new AbstractRegistryConfiguration() {\r
@@ -1559,13 +1621,25 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
 \r
                                });\r
                                  configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITOR, new AdaptableCellEditor());\r
+                                 configRegistry.registerConfigAttribute(EditConfigAttributes.CONVERSION_ERROR_HANDLER, new DialogErrorHandling(), DisplayMode.EDIT);\r
+                                 configRegistry.registerConfigAttribute(EditConfigAttributes.VALIDATION_ERROR_HANDLER, new DialogErrorHandling(), DisplayMode.EDIT);\r
+                                 configRegistry.registerConfigAttribute(EditConfigAttributes.DATA_VALIDATOR, new AdaptableDataValidator(),DisplayMode.EDIT);\r
+                                 \r
+                                 Style conversionErrorStyle = new Style();\r
+                                 conversionErrorStyle.setAttributeValue(CellStyleAttributes.BACKGROUND_COLOR, GUIHelper.COLOR_RED);\r
+                                 conversionErrorStyle.setAttributeValue(CellStyleAttributes.FOREGROUND_COLOR, GUIHelper.COLOR_WHITE);\r
+                                 configRegistry.registerConfigAttribute(EditConfigAttributes.CONVERSION_ERROR_STYLE, conversionErrorStyle, DisplayMode.EDIT);\r
+                                 \r
                                  configRegistry.registerConfigAttribute(CellConfigAttributes.DISPLAY_CONVERTER, new DefaultDisplayConverter(),DisplayMode.EDIT);\r
-                                // configRegistry.registerConfigAttribute(CellConfigAttributes.CELL_PAINTER, new GECellPainter(),DisplayMode.NORMAL);\r
-\r
-                               \r
+                                 \r
+                                 \r
                        }\r
                });\r
                \r
+               if ((style & SWT.BORDER) > 0) {\r
+                       natTable.addOverlayPainter(new NatTableBorderOverlayPainter());\r
+               }\r
+               \r
                natTable.configure();\r
                \r
 //             natTable.addListener(SWT.MenuDetect, new NatTableMenuListener());\r
@@ -1764,8 +1838,29 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                public Rectangle calculateControlBounds(Rectangle cellBounds) {\r
                        return editor.calculateControlBounds(cellBounds);\r
                }\r
+    }\r
+    \r
+    private class AdaptableDataValidator implements IDataValidator {\r
+       @Override\r
+       public boolean validate(ILayerCell cell, IConfigRegistry configRegistry, Object newValue) {\r
+               int col = cell.getColumnIndex();\r
+                       int row = cell.getRowIndex();\r
+                       return validate(col, row, newValue);\r
+       }\r
        \r
-       \r
+       @Override\r
+       public boolean validate(int col, int row, Object newValue) {\r
+               TreeNode node = list.get(row);\r
+                       Modifier modifier = getModifier(node, col);\r
+                       if (modifier == null)\r
+                               return false;\r
+                       \r
+                       String err =  modifier.isValid(newValue.toString());\r
+                       if (err == null)\r
+                               return true;\r
+                       modifier.isValid(newValue.toString());\r
+                       throw new ValidationFailedException(err);\r
+       }\r
     }\r
     \r
     private class CustomCellEditor extends AbstractCellEditor {\r
@@ -2079,7 +2174,7 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                }\r
                if (DEBUG) System.out.println("UpdateRunner.doRun() " + items.size());\r
 \r
-               ge.natTable.setRedraw(false);\r
+               //ge.natTable.setRedraw(false);\r
             for (UpdateItem item : items) {\r
                 item.update(ge.natTable);\r
             }\r
@@ -2091,7 +2186,7 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                ge.natTable.getParent().layout();\r
             }\r
             \r
-            ge.natTable.setRedraw(true);\r
+            //ge.natTable.setRedraw(true);\r
             \r
                synchronized (ge.pendingItems) {\r
                    if (!ge.scheduleUpdater()) {\r
@@ -2100,13 +2195,36 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                }\r
                if (DEBUG) {\r
                        if (!ge.updating) {\r
-                                ge.printTree(ge.rootNode, 0);\r
+                                printDebug(ge); \r
                        }\r
                }\r
            }\r
 \r
        }\r
     \r
+       private static void printDebug(NatTableGraphExplorer ge) {\r
+                ge.printTree(ge.rootNode, 0);\r
+                System.out.println("Expanded");\r
+                for (TreeNode n : ge.treeLayer.expanded)\r
+                        System.out.println(n);\r
+                System.out.println("Expanded end");\r
+                System.out.println("Hidden ");\r
+                for (int i : ge.treeLayer.getHiddenRowIndexes()) {\r
+                        System.out.print(i + " ");\r
+                }\r
+                System.out.println();\r
+//              Display.getCurrent().timerExec(1000, new Runnable() {\r
+//                     \r
+//                     @Override\r
+//                     public void run() {\r
+//                              System.out.println("Hidden delayed ");\r
+//                              for (int i : ge.treeLayer.getHiddenRowIndexes()) {\r
+//                                      System.out.print(i + " ");\r
+//                              }\r
+//                              System.out.println();\r
+//                     }\r
+//             });\r
+       }\r
     \r
     \r
     public static class GeViewerContext extends AbstractDisposable implements IGraphExplorerContext {\r
@@ -2348,23 +2466,22 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                        \r
                        @Override\r
                        public void handleLayerEvent(ILayerEvent event) {\r
-                               // TODO Auto-generated method stub\r
                                if (event instanceof ShowRowPositionsEvent) {\r
                                        ShowRowPositionsEvent e = (ShowRowPositionsEvent)event;\r
                                        for (Range r : e.getRowPositionRanges()) {\r
                                                int expanded = viewportLayer.getRowIndexByPosition(r.start-2)+1;\r
-                                               //System.out.println("ex " + expanded);\r
-                                               if (expanded < 0) {\r
+                                               if (DEBUG)System.out.println("IsExpandedProcessor expand " + expanded);\r
+                                               if (expanded < 0 || expanded >= list.size()) {\r
                                                        return;\r
                                                }\r
-                                               nodeStatusChanged(list.get(expanded).getContext(), false);\r
+                                               nodeStatusChanged(list.get(expanded).getContext(), true);\r
                                        }\r
                                } else if (event instanceof HideRowPositionsEvent) {\r
                                        HideRowPositionsEvent e = (HideRowPositionsEvent)event;\r
                                        for (Range r : e.getRowPositionRanges()) {\r
-                                               int collapsed = viewportLayer.getRowIndexByPosition(r.start-2)+1;\r
-                                               //System.out.println("col " + collapsed);\r
-                                               if (collapsed < 0) {\r
+                                               int collapsed = viewportLayer.getRowIndexByPosition(r.start-2);\r
+                                               if (DEBUG)System.out.println("IsExpandedProcessor collapse " + collapsed);\r
+                                               if (collapsed < 0 || collapsed >= list.size()) {\r
                                                        return;\r
                                                }\r
                                                nodeStatusChanged(list.get(collapsed).getContext(), false);\r
@@ -2714,7 +2831,7 @@ public class NatTableGraphExplorer extends GraphExplorerImplBase implements Grap
                }\r
     }\r
     \r
-private class NatTableHeaderMenuConfiguration extends AbstractHeaderMenuConfiguration {\r
+    private class NatTableHeaderMenuConfiguration extends AbstractHeaderMenuConfiguration {\r
                \r
                \r
                public NatTableHeaderMenuConfiguration(NatTable natTable) {\r
@@ -2755,8 +2872,8 @@ private class NatTableHeaderMenuConfiguration extends AbstractHeaderMenuConfigur
         Point point = new Point(e.x, e.y);\r
         int y = natTable.getRowPositionByY(point.y);\r
         int x = natTable.getColumnPositionByX(point.x);\r
-        if (x < 0 | y < 0)\r
+        if (x < 0 | y <= 0)\r
                return null;\r
-        return list.get(y); \r
+        return list.get(y-1); \r
     }\r
 }\r
index 4302cdeacf74d4d69bca07c6de6bfdd7ff476772..03588ae76736ecafa64cb054f0fc12d41c629ed2 100644 (file)
@@ -1,6 +1,7 @@
 package org.simantics.browsing.ui.nattable;\r
 \r
 import java.util.ArrayList;\r
+import java.util.Collection;\r
 import java.util.List;\r
 \r
 import org.eclipse.jface.viewers.IPostSelectionProvider;\r
@@ -21,6 +22,7 @@ import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.graphics.Point;\r
 import org.eclipse.swt.widgets.Event;\r
 import org.simantics.utils.datastructures.MapList;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
 \r
 public class NatTableSelectionAdaptor implements ISelectionProvider, IPostSelectionProvider, ILayerListener {\r
        NatTable natTable;\r
@@ -76,9 +78,41 @@ public class NatTableSelectionAdaptor implements ISelectionProvider, IPostSelect
        public void setSelection(ISelection selection) {\r
                if (!(selection instanceof StructuredSelection))\r
                        throw new IllegalArgumentException("Selection must be structured selection");\r
+               if (selection.isEmpty()) {\r
+                       selectionLayer.clear(false);\r
+                       natTable.redraw();\r
+                       return;\r
+               }\r
+               List<RowSelectionItem> rowItems = new ArrayList<>(AdaptionUtils.adaptToCollection(selection, RowSelectionItem.class));\r
+               if (rowItems.size() > 0) {\r
+               \r
+                       setSelectionExternal(rowItems);\r
+                       return;\r
+               }\r
+               Collection<TreeNode> nodes = AdaptionUtils.adaptToCollection(selection, TreeNode.class);\r
+               if (nodes.size() > 0) {\r
+                       List<RowSelectionItem> selected = new ArrayList<>();\r
+                       int allCols[] = new int[selectionLayer.getColumnCount()];\r
+                       for (int i = 0; i < allCols.length; i++)\r
+                               allCols[i] = i;\r
+                       for (TreeNode n : nodes) {\r
+                               selected.add(new RowSelectionItem(n, n.listIndex, allCols));\r
+                       }\r
+                       setSelectionExternal(selected);\r
+                       return;\r
+               }\r
                \r
        }\r
        \r
+       private void setSelectionExternal(List<RowSelectionItem> items) {\r
+               selectionLayer.clear(true);\r
+               for (RowSelectionItem item : items) {\r
+                       for (int c : item.columnIndex)\r
+                               selectionLayer.selectCell(c, item.rowIndex, false, true);\r
+               }\r
+               selection = new StructuredSelection(items);\r
+               fireEvents();\r
+       }\r
        \r
        \r
        private List<Point> selectedCells = new ArrayList<Point>();\r
index 941c6f319be56e491909cc35472e7173a5040ccf..30a37e3292205da607911c2d757528bf555d47f5 100644 (file)
@@ -38,6 +38,7 @@ public class TreeNode implements IAdaptable {
        TreeNode parent;\r
        List<TreeNode> children = new ArrayList<TreeNode>();\r
        boolean expanded;\r
+       boolean autoExpanded = false;\r
        \r
        public TreeNode(NodeContext context, GeViewerContext explorerContext) {\r
                this.context = context;\r
@@ -47,13 +48,13 @@ public class TreeNode implements IAdaptable {
                explorerContext.getContextToNodeMap().add(context, this);\r
        }\r
        \r
-       int getDepth() {\r
+       public int getDepth() {\r
                if (parent == null)\r
                        return 0;\r
                return parent.getDepth() + 1;\r
        }\r
        \r
-       int listIndex;\r
+       int listIndex = -1;\r
        \r
        public int getListIndex() {\r
                return listIndex;\r
@@ -79,6 +80,27 @@ public class TreeNode implements IAdaptable {
                return expanded;\r
        }\r
        \r
+       public boolean isHidden() {\r
+               TreeNode n = parent;\r
+               while (n != null) {\r
+                       if (!n.isExpanded())\r
+                               return true;\r
+                       n = n.getParent();\r
+               }\r
+               return false;\r
+       }\r
+       \r
+       public TreeNode getCollapsedAncestor() {\r
+               TreeNode collapsed = null;\r
+               TreeNode n = parent;\r
+               while (n != null) {\r
+                       if (!n.isExpanded())\r
+                               collapsed = n;\r
+                       n = n.getParent();\r
+               }\r
+               return collapsed;\r
+       }\r
+       \r
        public NodeContext getContext() {\r
                return context;\r
        }\r
@@ -92,9 +114,8 @@ public class TreeNode implements IAdaptable {
        Map<String, String> runtimeLabels;\r
        \r
        public String getValueString(int column) {\r
-               if (column == 0) {\r
+               if (column == 0)\r
                        initData();\r
-               }\r
                if (labeler != null) {\r
                        String key = explorerContext.getGe().getColumns()[column].getKey();\r
                        String s = null;\r
@@ -199,7 +220,7 @@ public class TreeNode implements IAdaptable {
 \r
        }\r
        \r
-       private void initData() {\r
+       public void initData() {\r
                labeler = manager.query(context, BuiltinKeys.SELECTED_LABELER);\r
                imager = manager.query(context, BuiltinKeys.SELECTED_IMAGER);\r
                labelDecorators = manager.query(context, BuiltinKeys.LABEL_DECORATORS);\r
@@ -319,7 +340,13 @@ public class TreeNode implements IAdaptable {
                                \r
                        }\r
                        for (int i = oldCount; i < childContexts.length; i++) {\r
-                               addChild(childContexts[i], explorerContext);\r
+                               Integer oldIndex = indexes.getLeft(i);\r
+                               if (oldIndex == null) {\r
+                                       addChild(childContexts[i], explorerContext);\r
+                               } else {\r
+                                       TreeNode n = oldChildren.get(oldIndex);\r
+                                       children.add(n);\r
+                               }\r
                        }\r
                        } else {\r
                                for (int i = 0; i < childContexts.length; i++) {\r
@@ -363,5 +390,10 @@ public class TreeNode implements IAdaptable {
                \r
                return context.getAdapter(adapter);\r
        }\r
+       \r
+       @Override\r
+       public String toString() {\r
+               return "TreeNode: " + listIndex + " " + (expanded ? "(+)" : "(-)") + " " + context ;\r
+       }\r
 \r
 }\r
index e1494cf3201f3fd79fefe0efc9956d0c6e4ea5a8..709e981bc16850e11ab78f61accbc478c8c7727f 100644 (file)
@@ -2312,6 +2312,7 @@ public class ModelingUtils {
                String extension = (String)t.get(1);\r
                filterNames[index] = filterName;\r
                extensions[index] = extension;\r
+               index++;\r
         }\r
         \r
         dialog.setFilterExtensions(extensions);\r