From 3b530e1eeca9c2d9fb755fc5eb528e9620114f17 Mon Sep 17 00:00:00 2001 From: jannisCode Date: Tue, 8 Oct 2024 10:15:08 +0200 Subject: [PATCH] Changed the functionality of the regex search with control decorations --- .../META-INF/MANIFEST.MF | 2 + .../org.eclipse.search/META-INF/MANIFEST.MF | 4 +- .../internal/ui/text/TextSearchPage.java | 36 ++++----- .../META-INF/MANIFEST.MF | 1 + .../overlay/FindReplaceOverlay.java | 28 +++++++ .../ui/texteditor/FindReplaceDialog.java | 39 +++++++++- bundles/org.eclipse.ui/META-INF/MANIFEST.MF | 4 +- .../eclipse/ui/internal/SearchDecoration.java | 78 +++++++++++++++++++ 8 files changed, 164 insertions(+), 28 deletions(-) create mode 100644 bundles/org.eclipse.ui/src/org/eclipse/ui/internal/SearchDecoration.java diff --git a/bundles/org.eclipse.search.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.search.core/META-INF/MANIFEST.MF index 8b5a65960b0..ebe7d95ebf6 100644 --- a/bundles/org.eclipse.search.core/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.search.core/META-INF/MANIFEST.MF @@ -19,3 +19,5 @@ Require-Bundle: org.eclipse.text;bundle-version="3.13.100" Bundle-RequiredExecutionEnvironment: JavaSE-17 Automatic-Module-Name: org.eclipse.search.core +Import-Package: org.eclipse.jface.fieldassist, + org.eclipse.swt.graphics diff --git a/bundles/org.eclipse.search/META-INF/MANIFEST.MF b/bundles/org.eclipse.search/META-INF/MANIFEST.MF index 1f073adf212..3c0e54c4c03 100644 --- a/bundles/org.eclipse.search/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.search/META-INF/MANIFEST.MF @@ -17,6 +17,7 @@ Export-Package: org.eclipse.search.internal.ui;x-internal:=true, org.eclipse.search2.internal.ui.basic.views;x-internal:=true, org.eclipse.search2.internal.ui.text;x-internal:=true, org.eclipse.search2.internal.ui.text2;x-internal:=true +Import-Package: org.eclipse.ui.internal.findandreplace Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.29.0,4.0.0)", org.eclipse.core.resources;bundle-version="[3.14.0,4.0.0)", @@ -29,7 +30,8 @@ Require-Bundle: org.eclipse.ui.forms;bundle-version="[3.4.0,4.0.0)", org.eclipse.ltk.core.refactoring;bundle-version="[3.5.0,4.0.0)", org.eclipse.ltk.ui.refactoring;bundle-version="[3.5.0,4.0.0)", - org.eclipse.search.core;bundle-version="[3.16.0,4.0.0)";visibility:=reexport + org.eclipse.search.core;bundle-version="[3.16.0,4.0.0)";visibility:=reexport, + org.eclipse.ui.browser;bundle-version="3.8.400" Bundle-RequiredExecutionEnvironment: JavaSE-17 Automatic-Module-Name: org.eclipse.search Service-Component: OSGI-INF/*.xml diff --git a/bundles/org.eclipse.search/search/org/eclipse/search/internal/ui/text/TextSearchPage.java b/bundles/org.eclipse.search/search/org/eclipse/search/internal/ui/text/TextSearchPage.java index 194abb008ce..805b332548c 100644 --- a/bundles/org.eclipse.search/search/org/eclipse/search/internal/ui/text/TextSearchPage.java +++ b/bundles/org.eclipse.search/search/org/eclipse/search/internal/ui/text/TextSearchPage.java @@ -54,7 +54,7 @@ import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.fieldassist.ComboContentAdapter; -import org.eclipse.jface.resource.JFaceColors; +import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.text.FindReplaceDocumentAdapter; @@ -68,6 +68,7 @@ import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter; +import org.eclipse.ui.internal.SearchDecoration; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; @@ -140,6 +141,8 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP */ private String[] fPreviousExtensions; private Label fFileNamePatternDescription; + private ControlDecoration fPatternDecoration; + private static class SearchPatternData { @@ -450,6 +453,7 @@ public void setVisible(boolean visible) { } final void updateOKStatus() { + fPatternDecoration.hide(); boolean regexStatus= validateRegex(); getContainer().setPerformActionEnabled(regexStatus); } @@ -481,22 +485,19 @@ public void createControl(Composite parent) { PlatformUI.getWorkbench().getHelpSystem().setHelp(result, ISearchHelpContextIds.TEXT_SEARCH_PAGE); } - private boolean validateRegex() { +private boolean validateRegex() { + if (fIsRegExCheckbox.getSelection()) { try { PatternConstructor.createPattern(fPattern.getText(), fIsCaseSensitive, true); } catch (PatternSyntaxException e) { - String locMessage= e.getLocalizedMessage(); - int i= 0; - while (i < locMessage.length() && "\n\r".indexOf(locMessage.charAt(i)) == -1) { //$NON-NLS-1$ - i++; - } - statusMessage(true, locMessage.substring(0, i)); // only take first line + SearchDecoration searchDecoration = new SearchDecoration(); + + searchDecoration.decorateA(fPatternDecoration, fPattern.getText()); return false; } - statusMessage(false, ""); //$NON-NLS-1$ } else { - statusMessage(false, SearchMessages.SearchPage_containingText_hint); + fPatternDecoration.hide(); } return true; } @@ -510,8 +511,11 @@ private void addTextPatternControls(Composite group) { label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1)); label.setFont(group.getFont()); + // Pattern combo fPattern= new Combo(group, SWT.SINGLE | SWT.BORDER); + fPatternDecoration = new ControlDecoration(fPattern, SWT.BOTTOM | SWT.LEFT); + // Not done here to prevent page from resizing // fPattern.setItems(getPreviousSearchPatterns()); fPattern.addSelectionListener(new SelectionAdapter() { @@ -561,7 +565,6 @@ public void widgetSelected(SelectionEvent e) { public void widgetSelected(SelectionEvent e) { fIsRegExSearch= fIsRegExCheckbox.getSelection(); updateOKStatus(); - writeConfiguration(); fPatterFieldContentAssist.setEnabled(fIsRegExSearch); fIsWholeWordCheckbox.setEnabled(!fIsRegExSearch); @@ -860,15 +863,4 @@ private void writeConfiguration() { } - private void statusMessage(boolean error, String message) { - fStatusLabel.setText(message); - if (error) { - fStatusLabel.setForeground(JFaceColors.getErrorText(fStatusLabel.getDisplay())); - } - else { - // use same color as another label to respect styling - fStatusLabel.setForeground(fFileNamePatternDescription.getForeground()); - } - } - } diff --git a/bundles/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF index b58b26bfbfc..ce6fe19fd3c 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.ui.workbench.texteditor/META-INF/MANIFEST.MF @@ -36,3 +36,4 @@ Require-Bundle: org.eclipse.jface.notifications Bundle-RequiredExecutionEnvironment: JavaSE-17 Automatic-Module-Name: org.eclipse.ui.workbench.texteditor +Import-Package: org.eclipse.search.internal.core.text diff --git a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java index 2abad115952..b3a958b1703 100644 --- a/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java +++ b/bundles/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/internal/findandreplace/overlay/FindReplaceOverlay.java @@ -51,6 +51,7 @@ import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.IPageChangedListener; import org.eclipse.jface.dialogs.PageChangedEvent; +import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.fieldassist.TextContentAdapter; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; @@ -67,6 +68,7 @@ import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter; +import org.eclipse.ui.internal.SearchDecoration; import org.eclipse.ui.internal.findandreplace.FindReplaceLogic; import org.eclipse.ui.internal.findandreplace.FindReplaceMessages; import org.eclipse.ui.internal.findandreplace.HistoryStore; @@ -146,8 +148,13 @@ private final class KeyboardShortcuts { private Color normalTextForegroundColor; private boolean positionAtTop = true; private final TargetPartVisibilityHandler targetPartVisibilityHandler; + + private ControlDecoration controldecoration; + private SearchDecoration searchDecoration; + private ContentAssistCommandAdapter contentAssistSearchField, contentAssistReplaceField; + public FindReplaceOverlay(Shell parent, IWorkbenchPart part, IFindReplaceTarget target) { super(parent); createFindReplaceLogic(target); @@ -157,6 +164,7 @@ public FindReplaceOverlay(Shell parent, IWorkbenchPart part, IFindReplaceTarget targetPart = part; targetPartVisibilityHandler = new TargetPartVisibilityHandler(targetPart, this::asyncExecIfOpen, this::close, this::updatePlacementAndVisibility); + this.searchDecoration = new SearchDecoration(); } @Override @@ -581,6 +589,11 @@ private void createRegexSearchButton() { wholeWordSearchButton.setEnabled(findReplaceLogic.isAvailable(SearchOptions.WHOLE_WORD)); updateIncrementalSearch(); updateContentAssistAvailability(); + if (!regexSearchButton.getSelection()) { + controldecoration.hide(); + } else { + searchDecoration.decorateA(controldecoration, getFindString()); + } }).withShortcuts(KeyboardShortcuts.OPTION_REGEX).build(); regexSearchButton.setSelection(findReplaceLogic.isActive(SearchOptions.REGEX)); } @@ -650,6 +663,7 @@ private void createSearchBar() { HistoryStore searchHistory = new HistoryStore(getDialogSettings(), "searchhistory", //$NON-NLS-1$ HISTORY_SIZE); searchBar = new HistoryTextWrapper(searchHistory, searchBarContainer, SWT.SINGLE); + controldecoration = new ControlDecoration(searchBar, SWT.BOTTOM | SWT.LEFT); GridDataFactory.fillDefaults().grab(true, true).align(GridData.FILL, GridData.FILL).applyTo(searchBar); searchBar.forceFocus(); searchBar.selectAll(); @@ -674,6 +688,8 @@ public void focusLost(FocusEvent e) { }); searchBar.setMessage(FindReplaceMessages.FindReplaceOverlay_searchBar_message); contentAssistSearchField = createContentAssistField(searchBar, true); + + decorate(); } private void updateIncrementalSearch() { @@ -991,6 +1007,7 @@ private void performSearch(boolean forward) { activateInFindReplacerIf(SearchOptions.FORWARD, oldForwardSearchSetting); evaluateFindReplaceStatus(); searchBar.storeHistory(); + } private void updateFromTargetSelection() { @@ -1061,4 +1078,15 @@ private void setContentAssistsEnablement(boolean enable) { private void updateContentAssistAvailability() { setContentAssistsEnablement(findReplaceLogic.isAvailableAndActive(SearchOptions.REGEX)); } + + public void decorate() { + searchBar.addModifyListener(event -> { + if (regexSearchButton.getSelection()) { + searchDecoration.decorateA(controldecoration, getFindString()); + } else + controldecoration.hide(); + }); + + } + } \ No newline at end of file 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 2ab91df8d15..815ed96fc5b 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 @@ -49,6 +49,7 @@ import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.fieldassist.ComboContentAdapter; +import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.fieldassist.FieldDecoration; import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.jface.resource.JFaceColors; @@ -64,6 +65,7 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter; +import org.eclipse.ui.internal.SearchDecoration; import org.eclipse.ui.internal.findandreplace.FindReplaceLogic; import org.eclipse.ui.internal.findandreplace.FindReplaceLogicMessageGenerator; import org.eclipse.ui.internal.findandreplace.FindReplaceMessages; @@ -147,7 +149,8 @@ public void modifyText(ModifyEvent e) { fIgnoreNextEvent = false; return; } - evaluateFindReplaceStatus(); + modificationHandler.run(); + decorate(); updateButtonState(!findReplaceLogic.isActive(SearchOptions.INCREMENTAL)); } @@ -196,6 +199,8 @@ public void modifyText(ModifyEvent e) { * @since 3.0 */ private boolean fGiveFocusToFindField = true; + private ControlDecoration fFindFieldDecoration; + private SearchDecoration fFindFieldSearchDecoration = new SearchDecoration(); /** * Holds the mnemonic/button pairs for all buttons. @@ -312,6 +317,8 @@ public void widgetSelected(SelectionEvent e) { updateButtonState(!somethingFound); updateFindHistory(); evaluateFindReplaceStatus(); + + decorate(); } }); setGridData(fFindNextButton, SWT.FILL, true, SWT.FILL, false); @@ -326,6 +333,7 @@ public void widgetSelected(SelectionEvent e) { updateButtonState(); updateFindAndReplaceHistory(); evaluateFindReplaceStatus(); + decorate(); } }); setGridData(fSelectAllButton, SWT.FILL, true, SWT.FILL, false); @@ -343,6 +351,8 @@ public void widgetSelected(SelectionEvent e) { updateButtonState(); updateFindAndReplaceHistory(); evaluateFindReplaceStatus(); + + decorate(); } }); setGridData(fReplaceFindButton, SWT.FILL, false, SWT.FILL, false); @@ -357,6 +367,8 @@ public void widgetSelected(SelectionEvent e) { updateButtonState(); updateFindAndReplaceHistory(); evaluateFindReplaceStatus(); + + decorate(); } }); setGridData(fReplaceSelectionButton, SWT.FILL, false, SWT.FILL, false); @@ -371,6 +383,8 @@ public void widgetSelected(SelectionEvent e) { updateButtonState(); updateFindAndReplaceHistory(); evaluateFindReplaceStatus(); + + decorate(); } }); setGridData(fReplaceAllButton, SWT.FILL, true, SWT.FILL, false); @@ -634,6 +648,8 @@ private Composite createInputPanel(Composite parent) { FindReplaceDocumentAdapterContentProposalProvider findProposer = new FindReplaceDocumentAdapterContentProposalProvider( true); fFindField = new Combo(panel, SWT.DROP_DOWN | SWT.BORDER); + fFindFieldDecoration = new ControlDecoration(fFindField, SWT.BOTTOM | SWT.LEFT); + fContentAssistFindField = new ContentAssistCommandAdapter(fFindField, contentAdapter, findProposer, ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS, new char[0], true); setGridData(fFindField, SWT.FILL, true, SWT.CENTER, false); @@ -750,6 +766,11 @@ public void widgetDefaultSelected(SelectionEvent e) { @Override public void widgetSelected(SelectionEvent e) { boolean newState = fIsRegExCheckBox.getSelection(); + if (!newState) { + fFindFieldDecoration.hide(); + } else { + fFindFieldSearchDecoration.decorateA(fFindFieldDecoration, getFindString()); + } setupFindReplaceLogic(); storeSettings(); updateButtonState(); @@ -1050,9 +1071,10 @@ private void addDecorationMargin(Control control) { if (!(layoutData instanceof GridData)) return; GridData gd = (GridData) layoutData; - FieldDecoration dec = FieldDecorationRegistry.getDefault() + + FieldDecoration fieldDecoration = FieldDecorationRegistry.getDefault() .getFieldDecoration(FieldDecorationRegistry.DEC_CONTENT_PROPOSAL); - gd.horizontalIndent = dec.getImage().getBounds().width; + gd.horizontalIndent = fieldDecoration.getImage().getBounds().width; } /** @@ -1335,6 +1357,17 @@ private void activateInFindReplaceLogicIf(SearchOptions option, boolean shouldAc } } + public void decorate() { + + fFindField.addModifyListener(event -> { + if (fIsRegExCheckBox.getSelection()) { + fFindFieldSearchDecoration.decorateA(fFindFieldDecoration, fFindField.getText()); + } else { + fFindFieldDecoration.hide(); + } + }); + } + /** * Evaluate the status of the FindReplaceLogic object. */ diff --git a/bundles/org.eclipse.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui/META-INF/MANIFEST.MF index 165143157ed..eb6e0d62361 100644 --- a/bundles/org.eclipse.ui/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.ui/META-INF/MANIFEST.MF @@ -2,12 +2,12 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Plugin.name Bundle-SymbolicName: org.eclipse.ui; singleton:=true -Bundle-Version: 3.206.200.qualifier +Bundle-Version: 3.207.0.qualifier +Export-Package: org.eclipse.ui.internal Bundle-Activator: org.eclipse.ui.internal.UIPlugin Bundle-ActivationPolicy: lazy Bundle-Vendor: %Plugin.providerName Bundle-Localization: plugin -Export-Package: org.eclipse.ui.internal;x-internal:=true Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.29.0,4.0.0)", org.eclipse.swt;bundle-version="[3.126.0,4.0.0)";visibility:=reexport, org.eclipse.jface;bundle-version="[3.34.0,4.0.0)";visibility:=reexport, diff --git a/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/SearchDecoration.java b/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/SearchDecoration.java new file mode 100644 index 00000000000..6bb0493a290 --- /dev/null +++ b/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/SearchDecoration.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2024 Vector Informatik GmbH and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Vector Informatik GmbH - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal; + +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +import org.eclipse.jface.fieldassist.ControlDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.swt.graphics.Image; + +/** + * This class is used for decorating a searchBar. Usually it is used for the + * strg +f and strg + h search. Changing something here will change the + * decoration which is used while searching for regex in both these searches. + * + * @since 3.207 + * + */ +public class SearchDecoration { + String message; + + public void decorateA(ControlDecoration decoration, String regex) { + if (!isValidRegex(regex)) { + Image decorationImage = FieldDecorationRegistry.getDefault() + .getFieldDecoration(FieldDecorationRegistry.DEC_ERROR).getImage(); + decoration.setImage(decorationImage); + decoration.setDescriptionText(message); + decoration.show(); + } else { + decoration.hide(); + + } + } + + /** + * checks if string is a valid regex + * + * @param string the string + * @return if the string is valid regex + */ + private boolean isValidRegex(String string) { + try { + Pattern p = Pattern.compile(string); + p.toString(); + message = ""; //$NON-NLS-1$ + return true; + } catch (PatternSyntaxException e) { + message = e.getLocalizedMessage(); + createMessage(); + return false; + } + } + + /** + * creates the message which will be shown when hovering over the decoration + */ + private void createMessage() { + int i = 0; + while (i < message.length() && "\n\r".indexOf(message.charAt(i)) == -1) { //$NON-NLS-1$ + i++; + } + message = message.substring(0, i); + } + +} \ No newline at end of file