1 package org.simantics.browsing.ui.swt;
\r
3 import java.util.regex.Pattern;
\r
5 import org.eclipse.swt.events.KeyAdapter;
\r
6 import org.eclipse.swt.events.KeyEvent;
\r
7 import org.eclipse.swt.widgets.Tree;
\r
8 import org.eclipse.swt.widgets.TreeItem;
\r
9 import org.simantics.browsing.ui.GraphExplorer;
\r
12 * Selects tree items based on pressed key events.<p>
\r
14 * The default implementation of SWT.Tree (Windows?) uses only the the first column when matching the items.<p>
\r
16 * This implementation checks all columns. Override <pre>matches(), matchesColumn()</pre> for customized behavior.<p>
\r
18 * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
\r
21 public class KeyToSelectionAdapter extends KeyAdapter {
\r
23 private static final int KEY_INPUT_DELAY = 500;
\r
25 private final GraphExplorer explorer;
\r
27 private String matcher = "";
\r
28 private int prevEvent = 0;
\r
29 private int columns = 0;
\r
31 protected Pattern alphaNum;
\r
34 * @param contextProvider
\r
37 public KeyToSelectionAdapter(GraphExplorer explorer) {
\r
38 assert explorer != null;
\r
40 this.explorer = explorer;
\r
41 this.alphaNum = Pattern.compile("\\p{Alnum}");
\r
45 public void keyPressed(KeyEvent e) {
\r
46 if (explorer.isDisposed())
\r
50 if (!alphaNum.matcher(Character.toString(e.character)).matches())
\r
52 // concatenate / replace matcher.
\r
53 if ((e.time - prevEvent) > KEY_INPUT_DELAY )
\r
56 matcher = matcher += Character.toString(e.character);
\r
58 TreeItem item = null;
\r
59 Tree tree = explorer.getControl();
\r
60 columns = tree.getColumnCount();
\r
61 TreeItem[] selected = tree.getSelection();
\r
63 item = find(tree, selected);
\r
65 if (item == null && matcher.length() > 1) {
\r
66 matcher = matcher.substring(matcher.length()-1);
\r
67 item = find(tree, selected);
\r
72 tree.showItem(item);
\r
75 // without this the default handling would take over.
\r
79 private TreeItem previous = null;
\r
80 private boolean foundPrev = false;
\r
82 private TreeItem find(Tree tree, TreeItem[] selected) {
\r
83 TreeItem item = null;
\r
85 TreeItem items[] = tree.getItems();
\r
86 if (selected.length == 0) {
\r
89 item = findItem(items, 0);
\r
92 previous = selected[0];
\r
94 item = findItem(items, 0);
\r
98 item = findItem(items, 0);
\r
104 private TreeItem findItem(TreeItem items[], int depth) {
\r
105 for (int i = 0; i < items.length; i++) {
\r
106 TreeItem item = items[i];
\r
107 if (item != previous) {
\r
108 if (foundPrev && matches(item, depth, columns, matcher))
\r
114 TreeItem childItem = findItem(item.getItems(),depth+1);
\r
115 if (childItem != null)
\r
125 * @param depth Depth of the item in the tree.
\r
126 * @param columns Number of columns.
\r
127 * @param string Matching string.
\r
130 protected boolean matches(TreeItem item, int depth, int columns, String matcher) {
\r
131 for (int c = 0; c < columns; c++) {
\r
132 if (matchesColumn(item, c, matcher)) {
\r
146 protected boolean matchesColumn(TreeItem item, int column, String matcher) {
\r
147 String text = item.getText(column);
\r
148 if (text.toLowerCase().startsWith(matcher)) {
\r