Skip to content

Commit

Permalink
Changed the functionality of the regex search with control decorations
Browse files Browse the repository at this point in the history
  • Loading branch information
jannisCode committed Oct 14, 2024
1 parent 090a18a commit 91762a5
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -140,8 +141,7 @@ public class TextSearchPage extends DialogPage implements ISearchPage, IReplaceP
*/
private String[] fPreviousExtensions;
private Label fFileNamePatternDescription;


private ControlDecoration fPatternDecoration;
private static class SearchPatternData {
public final boolean isCaseSensitive;
public final boolean isRegExSearch;
Expand Down Expand Up @@ -450,6 +450,7 @@ public void setVisible(boolean visible) {
}

final void updateOKStatus() {
fPatternDecoration.hide();
boolean regexStatus= validateRegex();
getContainer().setPerformActionEnabled(regexStatus);
}
Expand Down Expand Up @@ -479,24 +480,19 @@ public void createControl(Composite parent) {
setControl(result);
Dialog.applyDialogFont(result);
PlatformUI.getWorkbench().getHelpSystem().setHelp(result, ISearchHelpContextIds.TEXT_SEARCH_PAGE);
}
}

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.validateRegex(fPattern.getText(), fPatternDecoration);
return false;
}
statusMessage(false, ""); //$NON-NLS-1$
} else {
statusMessage(false, SearchMessages.SearchPage_containingText_hint);
fPatternDecoration.hide();
}
return true;
}
Expand All @@ -512,6 +508,8 @@ private void addTextPatternControls(Composite group) {

// 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() {
Expand Down Expand Up @@ -561,7 +559,6 @@ public void widgetSelected(SelectionEvent e) {
public void widgetSelected(SelectionEvent e) {
fIsRegExSearch= fIsRegExCheckbox.getSelection();
updateOKStatus();

writeConfiguration();
fPatterFieldContentAssist.setEnabled(fIsRegExSearch);
fIsWholeWordCheckbox.setEnabled(!fIsRegExSearch);
Expand Down Expand Up @@ -860,15 +857,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());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -146,6 +148,7 @@ private final class KeyboardShortcuts {
private Color normalTextForegroundColor;
private boolean positionAtTop = true;
private final TargetPartVisibilityHandler targetPartVisibilityHandler;
private ControlDecoration searchBarDecoration;
private ContentAssistCommandAdapter contentAssistSearchField, contentAssistReplaceField;

public FindReplaceOverlay(Shell parent, IWorkbenchPart part, IFindReplaceTarget target) {
Expand Down Expand Up @@ -581,6 +584,7 @@ private void createRegexSearchButton() {
wholeWordSearchButton.setEnabled(findReplaceLogic.isAvailable(SearchOptions.WHOLE_WORD));
updateIncrementalSearch();
updateContentAssistAvailability();
decorate();
}).withShortcuts(KeyboardShortcuts.OPTION_REGEX).build();
regexSearchButton.setSelection(findReplaceLogic.isActive(SearchOptions.REGEX));
}
Expand Down Expand Up @@ -650,6 +654,7 @@ private void createSearchBar() {
HistoryStore searchHistory = new HistoryStore(getDialogSettings(), "searchhistory", //$NON-NLS-1$
HISTORY_SIZE);
searchBar = new HistoryTextWrapper(searchHistory, searchBarContainer, SWT.SINGLE);
searchBarDecoration = new ControlDecoration(searchBar, SWT.BOTTOM | SWT.LEFT);
GridDataFactory.fillDefaults().grab(true, true).align(GridData.FILL, GridData.FILL).applyTo(searchBar);
searchBar.forceFocus();
searchBar.selectAll();
Expand All @@ -674,6 +679,9 @@ public void focusLost(FocusEvent e) {
});
searchBar.setMessage(FindReplaceMessages.FindReplaceOverlay_searchBar_message);
contentAssistSearchField = createContentAssistField(searchBar, true);
searchBar.addModifyListener(Event -> {
decorate();
});
}

private void updateIncrementalSearch() {
Expand Down Expand Up @@ -1061,4 +1069,13 @@ private void setContentAssistsEnablement(boolean enable) {
private void updateContentAssistAvailability() {
setContentAssistsEnablement(findReplaceLogic.isAvailableAndActive(SearchOptions.REGEX));
}

private void decorate() {
if (regexSearchButton.getSelection()) {
SearchDecoration.validateRegex(getFindString(), searchBarDecoration);
} else {
searchBarDecoration.hide();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -64,13 +65,15 @@

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.findandreplace.status.InvalidRegExStatus;
import org.eclipse.ui.internal.texteditor.SWTUtil;

/**
Expand Down Expand Up @@ -147,7 +150,10 @@ public void modifyText(ModifyEvent e) {
fIgnoreNextEvent = false;
return;
}
evaluateFindReplaceStatus();
modificationHandler.run();
fFindField.addModifyListener(event -> {
decorate();
});

updateButtonState(!findReplaceLogic.isActive(SearchOptions.INCREMENTAL));
}
Expand Down Expand Up @@ -196,6 +202,7 @@ public void modifyText(ModifyEvent e) {
* @since 3.0
*/
private boolean fGiveFocusToFindField = true;
private ControlDecoration fFindFieldDecoration;

/**
* Holds the mnemonic/button pairs for all buttons.
Expand Down Expand Up @@ -345,6 +352,7 @@ public void widgetSelected(SelectionEvent e) {
evaluateFindReplaceStatus();
}
});

setGridData(fReplaceFindButton, SWT.FILL, false, SWT.FILL, false);

fReplaceSelectionButton = makeButton(panel, FindReplaceMessages.FindReplace_ReplaceSelectionButton_label, 104,
Expand Down Expand Up @@ -634,6 +642,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);
Expand Down Expand Up @@ -750,6 +760,7 @@ public void widgetDefaultSelected(SelectionEvent e) {
@Override
public void widgetSelected(SelectionEvent e) {
boolean newState = fIsRegExCheckBox.getSelection();
decorate();
setupFindReplaceLogic();
storeSettings();
updateButtonState();
Expand Down Expand Up @@ -1050,9 +1061,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;
}

/**
Expand Down Expand Up @@ -1102,7 +1114,6 @@ private void updateButtonState(boolean disableReplace) {
}
}


/**
* Updates the given combo with the given content.
*
Expand Down Expand Up @@ -1335,19 +1346,27 @@ private void activateInFindReplaceLogicIf(SearchOptions option, boolean shouldAc
}
}

/**
* Evaluate the status of the FindReplaceLogic object.
*/
private void decorate() {
if (fIsRegExCheckBox.getSelection()) {
SearchDecoration.validateRegex(fFindField.getText(), fFindFieldDecoration);
} else {
fFindFieldDecoration.hide();
}
}

private void evaluateFindReplaceStatus() {
IFindReplaceStatus status = findReplaceLogic.getStatus();

String dialogMessage = status.accept(new FindReplaceLogicMessageGenerator());
fStatusLabel.setText(dialogMessage);
if (status.isInputValid()) {
fStatusLabel.setForeground(fReplaceLabel.getForeground());
} else {
fStatusLabel.setForeground(JFaceColors.getErrorText(fStatusLabel.getDisplay()));
if (!(status instanceof InvalidRegExStatus)) {
String dialogMessage = status.accept(new FindReplaceLogicMessageGenerator());
fStatusLabel.setText(dialogMessage);
if (status.isInputValid()) {
fStatusLabel.setForeground(fReplaceLabel.getForeground());
} else {
fStatusLabel.setForeground(JFaceColors.getErrorText(fStatusLabel.getDisplay()));
}
}

}

private String getCurrentSelection() {
Expand Down
2 changes: 1 addition & 1 deletion bundles/org.eclipse.ui/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ 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
Export-Package: org.eclipse.ui.internal;x-friends:="org.eclipse.ui.workbench.texteditor,org.eclipse.search"
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,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*******************************************************************************
* 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 contains methods to validate and decorate search fields.
*/
public class SearchDecoration {

private SearchDecoration() {
// avoid instantiation
}

/**
* Validate the given regular expression and change the control decoration
* accordingly. If the expression is invalid then the decoration will show an
* error icon and a message and if the expression is valid then the decoration
* will be hidden.
*
* @param regex The regular expression to be validated.
* @param targetDecoration The control decoration that will show the result of
* the validation.
*/
public static void validateRegex(String regex, ControlDecoration targetDecoration) {
String errorMessage = getValidationError(regex);
if (errorMessage.isEmpty()) {
targetDecoration.hide();
return;

}

Image decorationImage = FieldDecorationRegistry.getDefault()
.getFieldDecoration(FieldDecorationRegistry.DEC_ERROR).getImage();
targetDecoration.setImage(decorationImage);
targetDecoration.setDescriptionText(errorMessage);
targetDecoration.show();
}

/**
* Validate a regular expression.
*
* @return The appropriate error message if the regex is invalid or an empty
* string if the regex is valid.
*/
private static String getValidationError(String regex) {
try {
Pattern.compile(regex);
return ""; //$NON-NLS-1$
} catch (PatternSyntaxException e) {
String message = e.getLocalizedMessage();

// Only preserve the first line of the original error message.
int i = 0;
while (i < message.length() && "\n\r".indexOf(message.charAt(i)) == -1) { //$NON-NLS-1$
i++;
}

return message.substring(0, i);
}
}

}

0 comments on commit 91762a5

Please sign in to comment.