]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.nattable/src/org/simantics/browsing/ui/nattable/KeyToSelectionAdapter.java
7e0202be37974204df55852aa43406b18773eaf7
[simantics/platform.git] / bundles / org.simantics.browsing.ui.nattable / src / org / simantics / browsing / ui / nattable / KeyToSelectionAdapter.java
1 package org.simantics.browsing.ui.nattable;
2
3 import java.util.Collection;
4 import java.util.List;
5 import java.util.regex.Pattern;
6
7 import org.eclipse.jface.viewers.IStructuredSelection;
8 import org.eclipse.nebula.widgets.nattable.NatTable;
9 import org.eclipse.swt.events.KeyAdapter;
10 import org.eclipse.swt.events.KeyEvent;
11 import org.simantics.browsing.ui.GraphExplorer;
12 import org.simantics.utils.ui.AdaptionUtils;
13
14 /**
15  * Selects tree items based on pressed key events.<p>
16  * 
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 NatTableGraphExplorer          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 = (NatTableGraphExplorer)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          NatTable tree = explorer.getControl();
59          columns = explorer.getColumns().length;
60          
61          IStructuredSelection sel = (IStructuredSelection)explorer.getWidgetSelection();
62          Collection<RowSelectionItem> selected = AdaptionUtils.adaptToCollection(sel, RowSelectionItem.class);
63          
64           
65          TreeNode item = find(tree, selected);
66          
67          if (item == null && matcher.length() > 1) {
68                  matcher = matcher.substring(matcher.length()-1);
69                  item = find(tree, selected);
70          }
71          
72          if (item != null) {
73                  explorer.select(item);
74                  explorer.show(item);
75                  } 
76          // without this the default handling would take over.
77          e.doit = false;
78     }
79     
80     private TreeNode previous = null;
81     private boolean foundPrev = false;
82     
83         private TreeNode find(NatTable tree, Collection<RowSelectionItem> selected) {
84                 TreeNode item = null;
85
86                 List<TreeNode> items = explorer.getItems();
87                 
88                 if (selected.size() == 0) {
89                         previous = null;
90                         foundPrev = true;
91                         item = findItem(items);
92
93                 } else {
94                         previous = selected.iterator().next().item;
95                         foundPrev = false;
96                         item = findItem(items);
97                         if (item == null) {
98                                 previous = null;
99                                 foundPrev = true;
100                                 item = findItem(items);
101                         }
102                 }
103                 return item;
104         }
105     
106     private TreeNode findItem(List<TreeNode> items) {
107         for (int i = 0; i < items.size(); i++) {
108                 TreeNode item = items.get(i);
109                 if (item != previous) {
110                         if (foundPrev && matches(item, columns, matcher))
111                                 return item;
112                         
113                 } else {
114                         foundPrev = true;
115                 }
116         }
117         return null;
118     }
119     
120     
121     /**
122      * 
123      * @param item
124      * @param depth Depth of the item in the tree.
125      * @param columns Number of columns.
126      * @param string Matching string.
127      * @return
128      */
129     protected boolean matches(TreeNode item, int columns, String matcher) {
130         for (int c = 0; c < columns; c++) {     
131                         if (matchesColumn(item, c, matcher)) {
132                                 return true;
133                         }
134                 }
135         return false;
136     }
137     
138     /**
139      * 
140      * @param item
141      * @param column
142      * @param matcher
143      * @return
144      */
145     protected boolean matchesColumn(TreeNode item, int column, String matcher) {
146         String text = item.getValueString(column);
147                 if (text.toLowerCase().startsWith(matcher)) {
148                         return true;
149                 }
150                 return false;
151     }
152
153 }