1 package org.simantics.browsing.ui.nattable;
\r
3 import java.util.Collection;
\r
4 import java.util.List;
\r
5 import java.util.regex.Pattern;
\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
15 * Selects tree items based on pressed key events.<p>
\r
17 * The default implementation of SWT.Tree (Windows?) uses only the the first column when matching the items.<p>
\r
19 * This implementation checks all columns. Override <pre>matches(), matchesColumn()</pre> for customized behavior.<p>
\r
21 * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
\r
24 public class KeyToSelectionAdapter extends KeyAdapter {
\r
26 private static final int KEY_INPUT_DELAY = 500;
\r
28 private final NatTableGraphExplorer explorer;
\r
30 private String matcher = "";
\r
31 private int prevEvent = 0;
\r
32 private int columns = 0;
\r
34 protected Pattern alphaNum;
\r
37 * @param contextProvider
\r
40 public KeyToSelectionAdapter(GraphExplorer explorer) {
\r
41 assert explorer != null;
\r
43 this.explorer = (NatTableGraphExplorer)explorer;
\r
44 this.alphaNum = Pattern.compile("\\p{Alnum}");
\r
48 public void keyPressed(KeyEvent e) {
\r
49 if (explorer.isDisposed())
\r
53 if (!alphaNum.matcher(Character.toString(e.character)).matches())
\r
55 // concatenate / replace matcher.
\r
56 if ((e.time - prevEvent) > KEY_INPUT_DELAY )
\r
59 matcher = matcher += Character.toString(e.character);
\r
62 //TreeItem item = null;
\r
63 NatTable tree = explorer.getControl();
\r
64 columns = explorer.getColumns().length;
\r
66 IStructuredSelection sel = (IStructuredSelection)explorer.getWidgetSelection();
\r
67 Collection<RowSelectionItem> selected = AdaptionUtils.adaptToCollection(sel, RowSelectionItem.class);
\r
70 TreeNode item = find(tree, selected);
\r
72 if (item == null && matcher.length() > 1) {
\r
73 matcher = matcher.substring(matcher.length()-1);
\r
74 item = find(tree, selected);
\r
78 explorer.select(item);
\r
79 explorer.show(item);
\r
80 // tree.select(item);
\r
81 // tree.showItem(item);
\r
85 // without this the default handling would take over.
\r
89 private TreeNode previous = null;
\r
90 private boolean foundPrev = false;
\r
92 private TreeNode find(NatTable tree, Collection<RowSelectionItem> selected) {
\r
93 TreeNode item = null;
\r
95 List<TreeNode> items = explorer.getItems();
\r
97 if (selected.size() == 0) {
\r
100 item = findItem(items);
\r
103 previous = selected.iterator().next().item;
\r
105 item = findItem(items);
\r
106 if (item == null) {
\r
109 item = findItem(items);
\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
133 * @param depth Depth of the item in the tree.
\r
134 * @param columns Number of columns.
\r
135 * @param string Matching string.
\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
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