diff --git a/openide.explorer/src/org/openide/explorer/view/TreeView.java b/openide.explorer/src/org/openide/explorer/view/TreeView.java --- a/openide.explorer/src/org/openide/explorer/view/TreeView.java +++ b/openide.explorer/src/org/openide/explorer/view/TreeView.java @@ -2079,6 +2079,9 @@ private List doSearch(String prefix) { List results = new ArrayList(); Set resSet = new HashSet(); + + // starting index of substring matches within the results + int startOfSubstringMatches = 0; int startIndex = origSelectionPaths != null ? Math.max(0, getRowForPath(origSelectionPaths[0])) : 0; int size = getRowCount(); @@ -2092,18 +2095,33 @@ startIndex = startIndex % size; TreePath path = null; + SubstringSearchResult substringSearchResult = null; if (quickSearchUsingSubstring) { - path = getNextSubstringMatch(prefix, startIndex, Position.Bias.Forward); + substringSearchResult = getNextSubstringMatch(prefix, startIndex, Position.Bias.Forward); + path = substringSearchResult != null? substringSearchResult.treePath: null; } else { path = getNextMatch(prefix, startIndex, Position.Bias.Forward); } if ((path != null) && !resSet.contains(path)) { startIndex = tree.getRowForPath(path); - results.add(path); + boolean isPrefixMatch = true; + if (quickSearchUsingSubstring) { + // put all prefix matches to the top of the list while + // substring matches remains in the end of the list + if (substringSearchResult.index == 0) { + results.add(startOfSubstringMatches++, path); + } else { + isPrefixMatch = false; + results.add(path); + } + } else { + results.add(path); + } resSet.add(path); - if (!quickSearchUsingSubstring) { + // calculate max prefix only with prefix matches + if (isPrefixMatch) { String elementName = ((VisualizerNode) path.getLastPathComponent()).getDisplayName(); // initialize prefix @@ -2135,8 +2153,11 @@ /** * Copied and adapted from JTree.getNextMatch(...). + * + * @return An instance of SubstringSearchResult containing the matching TreePath + * and the index of the first occurrence of the substring in TreePath. */ - private TreePath getNextSubstringMatch( + private SubstringSearchResult getNextSubstringMatch( String substring, int startingRow, Position.Bias bias) { int max = getRowCount(); @@ -2157,9 +2178,10 @@ String text = convertValueToText( path.getLastPathComponent(), isRowSelected(row), isExpanded(row), true, row, false); - - if (text.toUpperCase().indexOf(substring) >= 0) { - return path; + + int index = text.toUpperCase().indexOf(substring); + if (index >= 0) { + return new SubstringSearchResult(path, index); } row = (row + increment + max) % max; } while (row != startingRow); @@ -2456,6 +2478,18 @@ } } } + + private class SubstringSearchResult { + + TreePath treePath; // holds the matching TreePath + int index; // holds the index of the first occurrence of the substring in TreePath + + public SubstringSearchResult(TreePath treePath, int index) { + this.treePath = treePath; + this.index = index; + } + + } } private static class DummyTransferHandler extends TransferHandler /*implements UIResource*/ { diff --git a/openide.explorer/test/unit/src/org/openide/explorer/view/TreeViewQuickSearchTest.java b/openide.explorer/test/unit/src/org/openide/explorer/view/TreeViewQuickSearchTest.java --- a/openide.explorer/test/unit/src/org/openide/explorer/view/TreeViewQuickSearchTest.java +++ b/openide.explorer/test/unit/src/org/openide/explorer/view/TreeViewQuickSearchTest.java @@ -137,7 +137,7 @@ } if (phase[0] == 2) { - Node operateOn = substringSearch ? children[2] : children[4]; + Node operateOn = children[4]; TreePath[] paths = tree.getSelectionPaths(); assertNotNull("One node should be selected, but there are none.", paths); assertEquals("One node should be selected, but there are none.", 1, paths.length);