4343import javafx .scene .layout .StackPane ;
4444import javafx .stage .Popup ;
4545
46+ /**
47+ *
48+ * @param <T> Item type
49+ * @see SearchableTreeItem
50+ * @see SearchableTreeCell
51+ */
4652public class SearchableTreeView <T > extends TreeView <T > {
4753
4854 public static final int MIN_QUERY_LENGTH = 1 ;
@@ -81,6 +87,9 @@ private SearchableTreeItem<T> getRealRoot() {
8187 }
8288
8389
90+ /**
91+ * Textfield for the search query.
92+ */
8493 private void popSearchField () {
8594 TextField textField = new TextField ();
8695 textField .setPrefWidth (150 );
@@ -210,25 +219,27 @@ private Subscription subscribeKeyNav(int numResults, Var<Integer> curIdx, Node e
210219
211220 }
212221
213-
214222 private List <MatchResult <SearchableTreeItem <T >>> selectMatches (String query , List <SearchableTreeItem <T >> items ) {
215223 MatchSelector <SearchableTreeItem <T >> limiter =
216224 CamelCaseMatcher .<SearchableTreeItem <T >>allQueryStarts ()
217225 .andThen (c -> c .filter (it -> it .getScore () > 0 ))
218226 .andThen (Stream ::parallel )
227+ .andThen (CamelCaseMatcher .onlyWordStarts ())
219228 .andThen (MatchSelector .selectBestTies ());
220229
221230 return StringMatchUtil .filterResults (items , SearchableTreeItem ::getSearchableText , query , limiter )
222231 .sorted (Comparator .comparingInt (res -> res .getData ().getTreeIndex ()))
223232 .collect (Collectors .toList ());
224233 }
225234
235+
226236 public abstract static class SearchableTreeItem <T > extends TreeItem <T > {
227237
228238 private final Var <SearchableTreeCell <T >> treeCell = Var .newSimpleVar (null );
229239 private final Var <MatchResult <SearchableTreeItem <T >>> currentSearchResult = Var .newSimpleVar (null );
230240 private final int treeIndex ;
231241
242+
232243 public SearchableTreeItem (T n , int treeIndex ) {
233244 super (n );
234245 this .treeIndex = treeIndex ;
@@ -244,17 +255,33 @@ public Var<SearchableTreeCell<T>> treeCellProperty() {
244255 return treeCell ;
245256 }
246257
258+
247259 public Val <MatchResult <SearchableTreeItem <T >>> currentSearchResultProperty () {
248260 return currentSearchResult ;
249261 }
250262
263+
264+ /**
265+ * Text used to match search queries. This must be the
266+ * same text as is displayed on the cell in normal mode.
267+ */
251268 public abstract String getSearchableText ();
252269
270+
253271 public int getTreeIndex () {
254272 return treeIndex ;
255273 }
256274 }
257275
276+ /**
277+ * A searchable tree cell is bound both ways to a searchable
278+ * tree item. It has three visual states:
279+ * <ul>
280+ * <li>unbound (no underlying item, not visible in tree)
281+ * <li>bound with a search result (in which case it displays the styled search result)
282+ * <li>bound without a search result (in which case it displays the searchable text, maybe with some styling)
283+ * </ul>
284+ */
258285 public abstract static class SearchableTreeCell <T > extends TreeCell <T > {
259286
260287 public SearchableTreeCell () {
@@ -272,6 +299,7 @@ public SearchableTreeCell() {
272299 });
273300 }
274301
302+
275303 protected Val <MatchResult <SearchableTreeItem <T >>> searchResultProperty () {
276304 return realItemProperty ().flatMap (SearchableTreeItem ::currentSearchResultProperty );
277305 }
@@ -298,12 +326,19 @@ public void updateItem(T item, boolean empty) {
298326 }
299327 }
300328
329+
330+ /**
331+ * Update just for when the item is not a search result.
332+ */
301333 protected void setNonSearchState (SearchableTreeItem <T > realItem ) {
302334 setGraphic (null );
303- // todo would be nicer if the treeview had colors
304335 setText (realItem .getSearchableText ());
305336 }
306337
338+
339+ /**
340+ * Update for both visible states.
341+ */
307342 public abstract void commonUpdate (T item );
308343
309344
0 commit comments