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