Merge "InputStream returns -1 on EOF instead of throwing IOException"
[simantics/platform.git] / bundles / org.simantics.browsing.ui.nattable / src / org / simantics / browsing / ui / nattable / KeyToSelectionAdapter.java
1 package org.simantics.browsing.ui.nattable;\r
2 \r
3 import java.util.Collection;\r
4 import java.util.List;\r
5 import java.util.regex.Pattern;\r
6 \r
7 import org.eclipse.jface.viewers.IStructuredSelection;\r
8 import org.eclipse.nebula.widgets.nattable.NatTable;\r
9 import org.eclipse.swt.events.KeyAdapter;\r
10 import org.eclipse.swt.events.KeyEvent;\r
11 import org.simantics.browsing.ui.GraphExplorer;\r
12 import org.simantics.utils.ui.AdaptionUtils;\r
13 \r
14 /**\r
15  * Selects tree items based on pressed key events.<p>\r
16  * \r
17  * The default implementation of SWT.Tree (Windows?) uses only the the first column when matching the items.<p>\r
18  * \r
19  * This implementation checks all columns. Override <pre>matches(), matchesColumn()</pre> for customized behavior.<p>\r
20  * \r
21  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
22  *\r
23  */\r
24 public class KeyToSelectionAdapter extends KeyAdapter {\r
25 \r
26         private static final int KEY_INPUT_DELAY = 500;\r
27         \r
28     private final NatTableGraphExplorer          explorer;\r
29 \r
30     private String matcher = "";\r
31     private int prevEvent = 0;\r
32     private int columns = 0;\r
33         \r
34     protected Pattern alphaNum;\r
35     \r
36     /**\r
37      * @param contextProvider\r
38      * @param explorer\r
39      */\r
40     public KeyToSelectionAdapter(GraphExplorer explorer) {\r
41         assert explorer != null;\r
42 \r
43         this.explorer = (NatTableGraphExplorer)explorer;\r
44         this.alphaNum = Pattern.compile("\\p{Alnum}");\r
45     }\r
46 \r
47     @Override\r
48     public void keyPressed(KeyEvent e) {\r
49         if (explorer.isDisposed())\r
50             return;\r
51 \r
52          \r
53          if (!alphaNum.matcher(Character.toString(e.character)).matches())\r
54                  return;\r
55          // concatenate / replace matcher.\r
56          if ((e.time - prevEvent) > KEY_INPUT_DELAY )\r
57                  matcher = "";\r
58          prevEvent = e.time;\r
59          matcher = matcher += Character.toString(e.character);\r
60 \r
61          \r
62          //TreeItem item = null;\r
63          NatTable tree = explorer.getControl();\r
64          columns = explorer.getColumns().length;\r
65          \r
66          IStructuredSelection sel = (IStructuredSelection)explorer.getWidgetSelection();\r
67          Collection<RowSelectionItem> selected = AdaptionUtils.adaptToCollection(sel, RowSelectionItem.class);\r
68          \r
69           \r
70          TreeNode item = find(tree, selected);\r
71          \r
72          if (item == null && matcher.length() > 1) {\r
73                  matcher = matcher.substring(matcher.length()-1);\r
74                  item = find(tree, selected);\r
75          }\r
76          \r
77          if (item != null) {\r
78                  explorer.select(item);\r
79                  explorer.show(item);\r
80 //                       tree.select(item);\r
81 //                       tree.showItem(item);\r
82                  \r
83                         \r
84                  } \r
85          // without this the default handling would take over.\r
86          e.doit = false;\r
87     }\r
88     \r
89     private TreeNode previous = null;\r
90     private boolean foundPrev = false;\r
91     \r
92         private TreeNode find(NatTable tree, Collection<RowSelectionItem> selected) {\r
93                 TreeNode item = null;\r
94 \r
95                 List<TreeNode> items = explorer.getItems();\r
96                 \r
97                 if (selected.size() == 0) {\r
98                         previous = null;\r
99                         foundPrev = true;\r
100                         item = findItem(items);\r
101 \r
102                 } else {\r
103                         previous = selected.iterator().next().item;\r
104                         foundPrev = false;\r
105                         item = findItem(items);\r
106                         if (item == null) {\r
107                                 previous = null;\r
108                                 foundPrev = true;\r
109                                 item = findItem(items);\r
110                         }\r
111                 }\r
112                 return item;\r
113         }\r
114     \r
115     private TreeNode findItem(List<TreeNode> items) {\r
116         for (int i = 0; i < items.size(); i++) {\r
117                 TreeNode item = items.get(i);\r
118                 if (item != previous) {\r
119                         if (foundPrev && matches(item, columns, matcher))\r
120                                 return item;\r
121                         \r
122                 } else {\r
123                         foundPrev = true;\r
124                 }\r
125         }\r
126         return null;\r
127     }\r
128     \r
129     \r
130     /**\r
131      * \r
132      * @param item\r
133      * @param depth Depth of the item in the tree.\r
134      * @param columns Number of columns.\r
135      * @param string Matching string.\r
136      * @return\r
137      */\r
138     protected boolean matches(TreeNode item, int columns, String matcher) {\r
139         for (int c = 0; c < columns; c++) {     \r
140                         if (matchesColumn(item, c, matcher)) {\r
141                                 return true;\r
142                         }\r
143                 }\r
144         return false;\r
145     }\r
146     \r
147     /**\r
148      * \r
149      * @param item\r
150      * @param column\r
151      * @param matcher\r
152      * @return\r
153      */\r
154     protected boolean matchesColumn(TreeNode item, int column, String matcher) {\r
155         String text = item.getValueString(column);\r
156                 if (text.toLowerCase().startsWith(matcher)) {\r
157                         return true;\r
158                 }\r
159                 return false;\r
160     }\r
161 \r
162 \r
163 }\r