From 93f7f838f86aa56de2b05008e778746e7afa6092 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 | 35 ++++----- .../META-INF/MANIFEST.MF | 1 + .../overlay/FindReplaceOverlay.java | 30 ++++++++ .../ui/texteditor/FindReplaceDialog.java | 38 ++++++---- bundles/org.eclipse.ui/META-INF/MANIFEST.MF | 4 +- .../eclipse/ui/internal/SearchDecoration.java | 76 +++++++++++++++++++ .../src/org/eclipse/ui/internal/UIPlugin.java | 1 + .../ui/internal/UIPreferenceInitializer.java | 7 +- 10 files changed, 159 insertions(+), 39 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..738c2124e0b 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,7 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP */ private String[] fPreviousExtensions; private Label fFileNamePatternDescription; + private ControlDecoration decoration; private static class SearchPatternData { @@ -450,6 +452,7 @@ public void setVisible(boolean visible) { } final void updateOKStatus() { + decoration.hide(); boolean regexStatus= validateRegex(); getContainer().setPerformActionEnabled(regexStatus); } @@ -481,22 +484,19 @@ public void createControl(Composite parent) { PlatformUI.getWorkbench().getHelpSystem().setHelp(result, ISearchHelpContextIds.TEXT_SEARCH_PAGE); } - private boolean validateRegex() { +private boolean validateRegex() { + SearchDecoration sDecoration = new SearchDecoration(); + 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 + + sDecoration.decorateA(decoration, fPattern.getText()); return false; } - statusMessage(false, ""); //$NON-NLS-1$ } else { - statusMessage(false, SearchMessages.SearchPage_containingText_hint); + decoration.hide(); } return true; } @@ -510,8 +510,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); + decoration = new ControlDecoration(fPattern, SWT.BOTTOM | SWT.LEFT); + // Not done here to prevent page from resizing // fPattern.setItems(getPreviousSearchPatterns()); fPattern.addSelectionListener(new SelectionAdapter() { @@ -561,7 +564,6 @@ public void widgetSelected(SelectionEvent e) { public void widgetSelected(SelectionEvent e) { fIsRegExSearch= fIsRegExCheckbox.getSelection(); updateOKStatus(); - writeConfiguration(); fPatterFieldContentAssist.setEnabled(fIsRegExSearch); fIsWholeWordCheckbox.setEnabled(!fIsRegExSearch); @@ -860,15 +862,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..be178ff370d 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 decoration; + private SearchDecoration dec; + 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.dec = new SearchDecoration(); } @Override @@ -581,6 +589,11 @@ private void createRegexSearchButton() { wholeWordSearchButton.setEnabled(findReplaceLogic.isAvailable(SearchOptions.WHOLE_WORD)); updateIncrementalSearch(); updateContentAssistAvailability(); + if (!regexSearchButton.getSelection()) { + decoration.hide(); + } else { + dec.decorateA(decoration, 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); + decoration = 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,17 @@ private void setContentAssistsEnablement(boolean enable) { private void updateContentAssistAvailability() { setContentAssistsEnablement(findReplaceLogic.isAvailableAndActive(SearchOptions.REGEX)); } + + public void decorate() { +// decoration = new ControlDecoration(searchBar, SWT.BOTTOM | SWT.LEFT); + + searchBar.addModifyListener(event -> { + if (regexSearchButton.getSelection()) { + dec.decorateA(decoration, getFindString()); + } else + decoration.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..bd1b9e5cb95 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,9 +49,9 @@ 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; import org.eclipse.jface.util.Util; import org.eclipse.jface.text.FindReplaceDocumentAdapter; @@ -64,13 +64,12 @@ 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; import org.eclipse.ui.internal.findandreplace.HistoryStore; import org.eclipse.ui.internal.findandreplace.IFindReplaceLogic; import org.eclipse.ui.internal.findandreplace.SearchOptions; -import org.eclipse.ui.internal.findandreplace.status.IFindReplaceStatus; import org.eclipse.ui.internal.texteditor.SWTUtil; /** @@ -196,6 +195,8 @@ public void modifyText(ModifyEvent e) { * @since 3.0 */ private boolean fGiveFocusToFindField = true; + private ControlDecoration decoration; + private SearchDecoration dec = new SearchDecoration(); /** * Holds the mnemonic/button pairs for all buttons. @@ -634,6 +635,8 @@ private Composite createInputPanel(Composite parent) { FindReplaceDocumentAdapterContentProposalProvider findProposer = new FindReplaceDocumentAdapterContentProposalProvider( true); fFindField = new Combo(panel, SWT.DROP_DOWN | SWT.BORDER); + decoration = 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 +753,11 @@ public void widgetDefaultSelected(SelectionEvent e) { @Override public void widgetSelected(SelectionEvent e) { boolean newState = fIsRegExCheckBox.getSelection(); + if (!newState) { + decoration.hide(); + } else { + dec.decorateA(decoration, getFindString()); + } setupFindReplaceLogic(); storeSettings(); updateButtonState(); @@ -1050,9 +1058,10 @@ private void addDecorationMargin(Control control) { if (!(layoutData instanceof GridData)) return; GridData gd = (GridData) layoutData; - FieldDecoration dec = FieldDecorationRegistry.getDefault() + + FieldDecoration dec_one = FieldDecorationRegistry.getDefault() .getFieldDecoration(FieldDecorationRegistry.DEC_CONTENT_PROPOSAL); - gd.horizontalIndent = dec.getImage().getBounds().width; + gd.horizontalIndent = dec_one.getImage().getBounds().width; } /** @@ -1339,15 +1348,18 @@ private void activateInFindReplaceLogicIf(SearchOptions option, boolean shouldAc * Evaluate the status of the FindReplaceLogic object. */ private void evaluateFindReplaceStatus() { - IFindReplaceStatus status = findReplaceLogic.getStatus(); + decorate(); + } - String dialogMessage = status.accept(new FindReplaceLogicMessageGenerator()); - fStatusLabel.setText(dialogMessage); - if (status.isInputValid()) { - fStatusLabel.setForeground(fReplaceLabel.getForeground()); - } else { - fStatusLabel.setForeground(JFaceColors.getErrorText(fStatusLabel.getDisplay())); - } + public void decorate() { + + fFindField.addModifyListener(event -> { + if (fIsRegExCheckBox.getSelection()) { + dec.decorateA(decoration, fFindField.getText()); + } else { + decoration.hide(); + } + }); } private String getCurrentSelection() { 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..a114ba5ea62 --- /dev/null +++ b/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/SearchDecoration.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2023 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 diff --git a/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/UIPlugin.java b/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/UIPlugin.java index 4a4d69bb16c..d7227a12654 100644 --- a/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/UIPlugin.java +++ b/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/UIPlugin.java @@ -24,6 +24,7 @@ * The plug-in class for the org.eclipse.ui plug-in. * This class is internal to the workbench and should not be * referenced by clients. + * @since 3.207 */ public final class UIPlugin extends AbstractUIPlugin { diff --git a/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/UIPreferenceInitializer.java b/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/UIPreferenceInitializer.java index 43d4221d6a7..5390fca3f56 100644 --- a/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/UIPreferenceInitializer.java +++ b/bundles/org.eclipse.ui/src/org/eclipse/ui/internal/UIPreferenceInitializer.java @@ -37,7 +37,12 @@ * org.eclipse.core.runtime.compatibility. For more details, see bug 58975 - New * preference mechanism does not properly initialize defaults. * - * @since 3.0 + */ + +/** + * + * @since 3.207 + * */ public class UIPreferenceInitializer extends AbstractPreferenceInitializer {