Skip to content

Commit 8007e93

Browse files
committed
Add result count to Find/Replace overlay
Display the total number of search results in the Find/Replace overlay if any else hide the bar
1 parent bacf493 commit 8007e93

1 file changed

Lines changed: 134 additions & 1 deletion

File tree

  • bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay

bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.eclipse.swt.widgets.Composite;
3939
import org.eclipse.swt.widgets.Control;
4040
import org.eclipse.swt.widgets.Display;
41+
import org.eclipse.swt.widgets.Label;
4142
import org.eclipse.swt.widgets.Listener;
4243
import org.eclipse.swt.widgets.ScrollBar;
4344
import org.eclipse.swt.widgets.Scrollable;
@@ -127,6 +128,7 @@ private static final class KeyboardShortcuts {
127128
private Composite searchContainer;
128129
private Composite searchBarContainer;
129130
private HistoryTextWrapper searchBar;
131+
private Label countLabel;
130132
private AccessibleToolBar searchTools;
131133
private ToolItem searchInSelectionButton;
132134
private ToolItem wholeWordSearchButton;
@@ -723,6 +725,7 @@ public void focusLost(FocusEvent e) {
723725

724726
private void updateIncrementalSearch() {
725727
findReplaceLogic.setFindString(searchBar.getText());
728+
updateCount();
726729
evaluateStatusAfterFind();
727730
}
728731

@@ -747,14 +750,142 @@ private void createReplaceBar() {
747750
private void createSearchContainer() {
748751
searchContainer = new FixedColorComposite(contentGroup, SWT.NONE, widgetBackgroundColor);
749752
GridDataFactory.fillDefaults().grab(true, true).align(GridData.FILL, GridData.FILL).applyTo(searchContainer);
750-
GridLayoutFactory.fillDefaults().numColumns(3).extendedMargins(7, 4, 3, 5).equalWidth(false)
753+
GridLayoutFactory.fillDefaults().numColumns(4).extendedMargins(7, 4, 3, 5).equalWidth(false)
751754
.applyTo(searchContainer);
752755

753756
createSearchBar();
757+
createCountLabel();
754758
createSearchTools();
755759
createCloseTools();
756760
}
757761

762+
private void createCountLabel() {
763+
countLabel = new Label(searchContainer, SWT.NONE);
764+
countLabel.setForeground(normalTextForegroundColor);
765+
countLabel.setBackground(widgetBackgroundColor);
766+
GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).hint(SWT.DEFAULT, SWT.DEFAULT).exclude(true)
767+
.applyTo(countLabel);
768+
countLabel.setVisible(false);
769+
}
770+
771+
private void updateCount() {
772+
if (!okayToUse(countLabel)) {
773+
return;
774+
}
775+
String inputString = searchBar.getText();
776+
if (inputString.isEmpty()) {
777+
hideCountLabel();
778+
return;
779+
}
780+
781+
try {
782+
int totalCount = inputTextCount(inputString);
783+
if (totalCount == 0) {
784+
hideCountLabel();
785+
} else {
786+
int currentIndex = getCurrentIndex(inputString, totalCount);
787+
countLabel.setText(currentIndex + " of " + totalCount); //$NON-NLS-1$
788+
showCountLabel();
789+
}
790+
} catch (Exception e) {
791+
hideCountLabel();
792+
}
793+
}
794+
795+
private void showCountLabel() {
796+
if (!countLabel.isVisible()) {
797+
countLabel.setVisible(true);
798+
((GridData) countLabel.getLayoutData()).exclude = false;
799+
}
800+
countLabel.pack();
801+
countLabel.getParent().layout();
802+
}
803+
804+
private void hideCountLabel() {
805+
if (countLabel.isVisible()) {
806+
countLabel.setVisible(false);
807+
((GridData) countLabel.getLayoutData()).exclude = true;
808+
countLabel.getParent().layout();
809+
}
810+
}
811+
812+
private int inputTextCount(String inputString) {
813+
if (inputString.isEmpty() || findReplaceLogic.getTarget() == null) {
814+
return 0;
815+
}
816+
if (!(targetPart instanceof StatusTextEditor)) {
817+
return 0;
818+
}
819+
StatusTextEditor textEditor = (StatusTextEditor) targetPart;
820+
ITextViewer viewer = textEditor.getAdapter(ITextViewer.class);
821+
if (viewer == null || viewer.getDocument() == null) {
822+
return 0;
823+
}
824+
825+
FindReplaceDocumentAdapter docAdapter = new FindReplaceDocumentAdapter(viewer.getDocument());
826+
return findMatches(docAdapter, inputString, -1);
827+
}
828+
829+
private int getCurrentIndex(String inputString, int totalCount) {
830+
if (totalCount == 0 || findReplaceLogic.getTarget() == null) {
831+
return 0;
832+
}
833+
834+
IFindReplaceTarget target = findReplaceLogic.getTarget();
835+
Point selection = target.getSelection();
836+
int currentOffset = selection.x;
837+
838+
if (!(targetPart instanceof StatusTextEditor)) {
839+
return 0;
840+
}
841+
842+
StatusTextEditor textEditor = (StatusTextEditor) targetPart;
843+
ITextViewer viewer = textEditor.getAdapter(ITextViewer.class);
844+
if (viewer == null || viewer.getDocument() == null) {
845+
return 0;
846+
}
847+
848+
FindReplaceDocumentAdapter docAdapter = new FindReplaceDocumentAdapter(viewer.getDocument());
849+
int index = findMatches(docAdapter, inputString, currentOffset);
850+
return index > 0 ? index : 1;
851+
}
852+
853+
/**
854+
* Iterates through all matches of the search string in the document.
855+
*
856+
* @param docAdapter the document adapter to search in
857+
* @param searchString the string to search for
858+
* @param stopOffset if stopOffset>= 0, stops and returns the index when a
859+
* match at or after this offset is found; if stopOffset< 0,
860+
* counts all matches
861+
* @return the count of all matches (if stopOffset < 0) or the index of the
862+
* first match at or after stopOffset.
863+
*/
864+
private int findMatches(FindReplaceDocumentAdapter docAdapter, String searchString, int stopOffset) {
865+
boolean isCaseSensitive = findReplaceLogic.isActive(SearchOptions.CASE_SENSITIVE);
866+
boolean isWholeWord = findReplaceLogic.isActive(SearchOptions.WHOLE_WORD);
867+
boolean isRegEx = findReplaceLogic.isActive(SearchOptions.REGEX);
868+
869+
int index = 0;
870+
int startOffset = 0;
871+
try {
872+
while (true) {
873+
org.eclipse.jface.text.IRegion match = docAdapter.find(startOffset, searchString, true,
874+
isCaseSensitive, isWholeWord, isRegEx);
875+
if (match == null) {
876+
break;
877+
}
878+
index++;
879+
if (stopOffset >= 0 && match.getOffset() >= stopOffset) {
880+
return index;
881+
}
882+
startOffset = match.getOffset() + Math.max(1, match.getLength());
883+
}
884+
} catch (Exception e) {
885+
}
886+
return index;
887+
}
888+
758889
private void createReplaceContainer() {
759890
replaceContainer = new FixedColorComposite(contentGroup, SWT.NONE, widgetBackgroundColor);
760891
GridDataFactory.fillDefaults().grab(true, true).align(GridData.FILL, GridData.FILL).applyTo(replaceContainer);
@@ -973,6 +1104,7 @@ private String getFindString() {
9731104
private void performSingleReplace() {
9741105
if (findReplaceLogic.performSelectAndReplace()) {
9751106
findReplaceLogic.performSearch();
1107+
updateCount();
9761108
evaluateStatusAfterFind();
9771109
} else {
9781110
evaluateStatusAfterReplace();
@@ -987,6 +1119,7 @@ private void performSearch(boolean forward) {
9871119
activateInFindReplacerIf(SearchOptions.FORWARD, forward);
9881120
findReplaceLogic.performSearch();
9891121
activateInFindReplacerIf(SearchOptions.FORWARD, oldForwardSearchSetting);
1122+
updateCount();
9901123
evaluateStatusAfterFind();
9911124
searchBar.storeHistory();
9921125
}

0 commit comments

Comments
 (0)