Skip to content

Commit 76c7011

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 956129f commit 76c7011

1 file changed

Lines changed: 132 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: 132 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,140 @@ 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 match at or after this offset is found;
859+
* if stopOffset< 0, counts all matches
860+
* @return the count of all matches (if stopOffset < 0) or the index of the first match at or after stopOffset
861+
*/
862+
private int findMatches(FindReplaceDocumentAdapter docAdapter, String searchString, int stopOffset) {
863+
boolean isCaseSensitive = findReplaceLogic.isActive(SearchOptions.CASE_SENSITIVE);
864+
boolean isWholeWord = findReplaceLogic.isActive(SearchOptions.WHOLE_WORD);
865+
boolean isRegEx = findReplaceLogic.isActive(SearchOptions.REGEX);
866+
867+
int index = 0;
868+
int startOffset = 0;
869+
try {
870+
while (true) {
871+
org.eclipse.jface.text.IRegion match = docAdapter.find(startOffset, searchString, true,
872+
isCaseSensitive, isWholeWord, isRegEx);
873+
if (match == null) {
874+
break;
875+
}
876+
index++;
877+
if (stopOffset >= 0 && match.getOffset() >= stopOffset) {
878+
return index;
879+
}
880+
startOffset = match.getOffset() + Math.max(1, match.getLength());
881+
}
882+
} catch (Exception e) {
883+
}
884+
return index;
885+
}
886+
758887
private void createReplaceContainer() {
759888
replaceContainer = new FixedColorComposite(contentGroup, SWT.NONE, widgetBackgroundColor);
760889
GridDataFactory.fillDefaults().grab(true, true).align(GridData.FILL, GridData.FILL).applyTo(replaceContainer);
@@ -973,6 +1102,7 @@ private String getFindString() {
9731102
private void performSingleReplace() {
9741103
if (findReplaceLogic.performSelectAndReplace()) {
9751104
findReplaceLogic.performSearch();
1105+
updateCount();
9761106
evaluateStatusAfterFind();
9771107
} else {
9781108
evaluateStatusAfterReplace();
@@ -987,6 +1117,7 @@ private void performSearch(boolean forward) {
9871117
activateInFindReplacerIf(SearchOptions.FORWARD, forward);
9881118
findReplaceLogic.performSearch();
9891119
activateInFindReplacerIf(SearchOptions.FORWARD, oldForwardSearchSetting);
1120+
updateCount();
9901121
evaluateStatusAfterFind();
9911122
searchBar.storeHistory();
9921123
}

0 commit comments

Comments
 (0)