From c40b7a177e4be437a644ba578ace8ed6d0cbaaf0 Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Tue, 19 Mar 2024 15:37:06 +0100 Subject: [PATCH] Properly use selected string for replacements in FindReplaceDialog #1754 When opening the FindReplaceDialog with an active selection in a text viewer, the input field for the find string is filled with the content of that selection. In addition, the replace functionality of the dialog is activated. Currently, using the replace functionality does not work because it requires a find operation to be executed before, which is currently not done. With this change, initializing the dialog with the current selection performs the missing find operation before executing a replace operation. The according functionality is refactored and a regression test is added. Fixes https://github.com/eclipse-platform/eclipse.platform.ui/issues/1754 --- .../ui/texteditor/FindReplaceDialog.java | 74 +++++++++++++------ .../tests/FindReplaceDialogTest.java | 26 +++++++ 2 files changed, 76 insertions(+), 24 deletions(-) diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceDialog.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceDialog.java index 8fa2d1affa5..2c03b116e14 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceDialog.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceDialog.java @@ -259,7 +259,7 @@ public void create() { updateCombo(fReplaceField, replaceHistory.get()); // get find string - initFindStringFromSelection(); + initFindString(); // set dialog position if (fDialogPositionInit != null) @@ -898,35 +898,61 @@ private void storeSettings() { writeConfiguration(); } + /** + * Initializes the string to search for and the according text in the find field + * based on either the selection in the target or, if nothing is selected, with + * the newest search history entry. + */ + private void initFindString() { + if (!okToUse(fFindField)) { + return; + } + + fFindField.removeModifyListener(fFindModifyListener); + if (hasTargetSelection()) { + initFindStringFromSelection(); + } else { + initFindStringFromHistory(); + } + fFindField.setSelection(new Point(0, fFindField.getText().length())); + fFindField.addModifyListener(fFindModifyListener); + } + + private boolean hasTargetSelection() { + String selection = getCurrentSelection(); + return selection != null && !selection.isEmpty(); + } + /** * Initializes the string to search for and the appropriate text in the Find * field based on the selection found in the action's target. */ private void initFindStringFromSelection() { - String fullSelection = getCurrentSelection(); - if (fullSelection != null && okToUse(fFindField)) { - boolean isRegEx = findReplaceLogic.isRegExSearchAvailableAndActive(); - fFindField.removeModifyListener(fFindModifyListener); - if (!fullSelection.isEmpty()) { - String firstLine = getFirstLine(fullSelection); - String pattern = isRegEx ? FindReplaceDocumentAdapter.escapeForRegExPattern(fullSelection) : firstLine; - fFindField.setText(pattern); - if (!firstLine.equals(fullSelection)) { - // multiple lines selected - findReplaceLogic.deactivate(SearchOptions.GLOBAL); - fGlobalRadioButton.setSelection(false); - fSelectedRangeRadioButton.setSelection(true); - } + String selection = getCurrentSelection(); + String searchInput = getFirstLine(selection); + boolean isSingleLineInput = searchInput.equals(selection); + if (findReplaceLogic.isRegExSearchAvailableAndActive()) { + searchInput = FindReplaceDocumentAdapter.escapeForRegExPattern(selection); + } + fFindField.setText(searchInput); + + if (isSingleLineInput) { + // initialize search with current selection to allow for execution of replace + // operations + findReplaceLogic.findAndSelect(findReplaceLogic.getTarget().getSelection().x, fFindField.getText()); + } else { + fGlobalRadioButton.setSelection(false); + fSelectedRangeRadioButton.setSelection(true); + } + } + + private void initFindStringFromHistory() { + if ("".equals(fFindField.getText())) { //$NON-NLS-1$ + if (!findHistory.isEmpty()) { + fFindField.setText(findHistory.get(0)); } else { - if ("".equals(fFindField.getText())) { //$NON-NLS-1$ - if (!findHistory.isEmpty()) - fFindField.setText(findHistory.get(0)); - else - fFindField.setText(""); //$NON-NLS-1$ - } + fFindField.setText(""); //$NON-NLS-1$ } - fFindField.setSelection(new Point(0, fFindField.getText().length())); - fFindField.addModifyListener(fFindModifyListener); } } @@ -1164,7 +1190,7 @@ public void updateTarget(IFindReplaceTarget target, boolean isTargetEditable, bo fReplaceField.setEnabled(targetExists && findReplaceLogic.getTarget().isEditable()); fReplaceAllButton.setEnabled(targetExists && findReplaceLogic.getTarget().isEditable()); if (initializeFindString) { - initFindStringFromSelection(); + initFindString(); fGiveFocusToFindField = true; } } diff --git a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/FindReplaceDialogTest.java b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/FindReplaceDialogTest.java index 2a4c0738cfa..f9410ddcf54 100644 --- a/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/FindReplaceDialogTest.java +++ b/tests/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/FindReplaceDialogTest.java @@ -92,6 +92,8 @@ private class DialogAccess { Button regExCheckBox; + Button replaceFindButton; + private Supplier shellRetriever; private Runnable closeOperation; @@ -106,6 +108,7 @@ private class DialogAccess { wholeWordCheckBox= (Button) findReplaceDialogAccessor.get("fWholeWordCheckBox"); incrementalCheckBox= (Button) findReplaceDialogAccessor.get("fIncrementalCheckBox"); regExCheckBox= (Button) findReplaceDialogAccessor.get("fIsRegExCheckBox"); + replaceFindButton= (Button) findReplaceDialogAccessor.get("fReplaceFindButton"); shellRetriever= () -> ((Shell) findReplaceDialogAccessor.get("fActiveShell")); closeOperation= () -> findReplaceDialogAccessor.invoke("close", null); assertInitialConfiguration(); @@ -176,10 +179,17 @@ private void openTextViewerAndFindReplaceDialog() { } private void openTextViewerAndFindReplaceDialog(String content) { + openTextViewer(content); + openFindReplaceDialogForTextViewer(); + } + + private void openTextViewer(String content) { fTextViewer= new TextViewer(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); fTextViewer.setDocument(new Document(content)); fTextViewer.getControl().setFocus(); + } + private void openFindReplaceDialogForTextViewer() { Accessor fFindReplaceAction; fFindReplaceAction= new Accessor("org.eclipse.ui.texteditor.FindReplaceAction", getClass().getClassLoader(), new Class[] { ResourceBundle.class, String.class, Shell.class, IFindReplaceTarget.class }, @@ -366,6 +376,22 @@ public void testFindWithWholeWordEnabledWithMultipleWords() { assertEquals(dialog.findCombo.getText().length(), (target.getSelection()).y); } + @Test + public void testReplaceAndFindAfterInitializingFindWithSelectedString() { + openTextViewer("text text text"); + fTextViewer.setSelectedRange(0, 4); + openFindReplaceDialogForTextViewer(); + + IFindReplaceTarget target= dialog.findReplaceLogic.getTarget(); + assertEquals(0, (target.getSelection()).x); + assertEquals(4, (target.getSelection()).y); + select(dialog.replaceFindButton); + + assertEquals(" text text", fTextViewer.getDocument().get()); + assertEquals(1, (target.getSelection()).x); + assertEquals(4, (target.getSelection()).y); + } + private static void select(Button button) { button.setSelection(true); button.notifyListeners(SWT.Selection, null);