]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/KeyToSelectionAdapter.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.browsing.ui.swt / src / org / simantics / browsing / ui / swt / KeyToSelectionAdapter.java
diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/KeyToSelectionAdapter.java b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/KeyToSelectionAdapter.java
new file mode 100644 (file)
index 0000000..c50029d
--- /dev/null
@@ -0,0 +1,155 @@
+package org.simantics.browsing.ui.swt;\r
+\r
+import java.util.regex.Pattern;\r
+\r
+import org.eclipse.swt.events.KeyAdapter;\r
+import org.eclipse.swt.events.KeyEvent;\r
+import org.eclipse.swt.widgets.Tree;\r
+import org.eclipse.swt.widgets.TreeItem;\r
+import org.simantics.browsing.ui.GraphExplorer;\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 GraphExplorer          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 = 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
+        TreeItem item = null;\r
+        Tree tree = explorer.getControl();\r
+        columns = tree.getColumnCount();\r
+        TreeItem[] selected = tree.getSelection();\r
+       \r
+        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
+                        tree.select(item);\r
+                        tree.showItem(item);\r
+                       \r
+                } \r
+        // without this the default handling would take over.\r
+        e.doit = false;\r
+    }\r
+    \r
+    private TreeItem previous = null;\r
+    private boolean foundPrev = false;\r
+    \r
+       private TreeItem find(Tree tree, TreeItem[] selected) {\r
+               TreeItem item = null;\r
+\r
+               TreeItem items[] = tree.getItems();\r
+               if (selected.length == 0) {\r
+                       previous = null;\r
+                       foundPrev = true;\r
+                       item = findItem(items, 0);\r
+\r
+               } else {\r
+                       previous = selected[0];\r
+                       foundPrev = false;\r
+                       item = findItem(items, 0);\r
+                       if (item == null) {\r
+                               previous = null;\r
+                               foundPrev = true;\r
+                               item = findItem(items, 0);\r
+                       }\r
+               }\r
+               return item;\r
+       }\r
+    \r
+    private TreeItem findItem(TreeItem items[], int depth) {\r
+       for (int i = 0; i < items.length; i++) {\r
+               TreeItem item = items[i];\r
+               if (item != previous) {\r
+                       if (foundPrev && matches(item, depth, columns, matcher))\r
+                               return item;\r
+                       \r
+               } else {\r
+                       foundPrev = true;\r
+               }\r
+               TreeItem childItem = findItem(item.getItems(),depth+1); \r
+               if (childItem != null)\r
+                       return childItem;\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(TreeItem item, int depth, 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(TreeItem item, int column, String matcher) {\r
+       String text = item.getText(column);\r
+               if (text.toLowerCase().startsWith(matcher)) {\r
+                       return true;\r
+               }\r
+               return false;\r
+    }\r
+\r
+\r
+}\r