mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
SSR: rework dialog validation (IDEA-201479)
GitOrigin-RevId: a78aac65bbb1a45abc46f4800730d787cea9c071
This commit is contained in:
committed by
intellij-monorepo-bot
parent
102b188350
commit
fc06e1a491
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.ui;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
@@ -331,6 +331,16 @@ public abstract class DialogWrapper {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to disable continuous validation.
|
||||
* When disabled {@link #initValidation()} needs to be invoked after every change of the dialog to validate.
|
||||
*
|
||||
* @return {@code false} to disable continuous validation
|
||||
*/
|
||||
protected boolean continuousValidation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates user input and returns {@code null} if everything is fine
|
||||
* or validation description with component where problem has been found.
|
||||
@@ -382,7 +392,7 @@ public abstract class DialogWrapper {
|
||||
private void installErrorPainter() {
|
||||
if (myErrorPainterInstalled) return;
|
||||
myErrorPainterInstalled = true;
|
||||
UIUtil.invokeLaterIfNeeded(() -> IdeGlassPaneUtil.installPainter(getContentPanel(), myErrorPainter, myDisposable));
|
||||
IdeGlassPaneUtil.installPainter(getContentPanel(), myErrorPainter, myDisposable);
|
||||
}
|
||||
|
||||
protected void updateErrorInfo(@NotNull List<ValidationInfo> info) {
|
||||
@@ -390,6 +400,10 @@ public abstract class DialogWrapper {
|
||||
if (updateNeeded) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (myDisposed) return;
|
||||
if (!info.isEmpty()) {
|
||||
installErrorPainter();
|
||||
}
|
||||
myErrorPainter.setValidationInfo(info);
|
||||
setErrorInfoAll(info);
|
||||
myPeer.getRootPane().getGlassPane().repaint();
|
||||
getOKAction().setEnabled(info.isEmpty() || info.stream().allMatch(info1 -> info1.okEnabled));
|
||||
@@ -1413,6 +1427,7 @@ public abstract class DialogWrapper {
|
||||
}
|
||||
|
||||
protected void startTrackingValidation() {
|
||||
if (!continuousValidation()) return;
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (!myValidationStarted && !myDisposed) {
|
||||
myValidationStarted = true;
|
||||
@@ -1425,14 +1440,9 @@ public abstract class DialogWrapper {
|
||||
myValidationAlarm.cancelAllRequests();
|
||||
final Runnable validateRequest = () -> {
|
||||
if (myDisposed) return;
|
||||
List<ValidationInfo> result = doValidateAll();
|
||||
if (!result.isEmpty()) {
|
||||
installErrorPainter();
|
||||
}
|
||||
myErrorPainter.setValidationInfo(result);
|
||||
updateErrorInfo(result);
|
||||
updateErrorInfo(doValidateAll());
|
||||
|
||||
if (!myDisposed) {
|
||||
if (!myDisposed && continuousValidation()) {
|
||||
initValidation();
|
||||
}
|
||||
};
|
||||
@@ -1889,7 +1899,7 @@ public abstract class DialogWrapper {
|
||||
if (!isInplaceValidationToolTipEnabled()) {
|
||||
DialogEarthquakeShaker.shake(getPeer().getWindow());
|
||||
}
|
||||
|
||||
updateErrorInfo(infoList);
|
||||
startTrackingValidation();
|
||||
if(infoList.stream().anyMatch(info1 -> !info1.okEnabled)) return;
|
||||
}
|
||||
|
||||
+4
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.structuralsearch.impl.matcher.compiler;
|
||||
|
||||
import com.intellij.codeInsight.template.Template;
|
||||
@@ -72,6 +72,9 @@ public final class PatternCompiler {
|
||||
|
||||
try {
|
||||
final List<PsiElement> elements = compileByAllPrefixes(project, options, result, context, prefixes, checkForErrors);
|
||||
if (elements.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
final CompiledPattern pattern = context.getPattern();
|
||||
collectVariableNodes(pattern, elements, checkForErrors);
|
||||
pattern.setNodes(elements);
|
||||
|
||||
+90
-128
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.structuralsearch.plugin.ui;
|
||||
|
||||
import com.intellij.codeInsight.highlighting.HighlightHandlerBase;
|
||||
@@ -46,15 +46,16 @@ import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.ide.CopyPasteManager;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
|
||||
import com.intellij.openapi.project.*;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.ui.ValidationInfo;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -99,9 +100,6 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.intellij.openapi.util.text.StringUtil.isEmpty;
|
||||
import static com.intellij.openapi.util.text.StringUtil.trimEnd;
|
||||
|
||||
/**
|
||||
* This dialog is used in two ways:
|
||||
* 1. a non-modal search dialog, showing a scope panel
|
||||
@@ -155,7 +153,6 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
private final Alarm myAlarm;
|
||||
private boolean myUseLastConfiguration;
|
||||
private final boolean myEditConfigOnly;
|
||||
private boolean myDoingOkAction;
|
||||
|
||||
// components
|
||||
private final FileTypeChooser myFileTypeChooser = new FileTypeChooser();
|
||||
@@ -238,6 +235,7 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
|
||||
init();
|
||||
myAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, myDisposable);
|
||||
setValidationDelay(100);
|
||||
}
|
||||
|
||||
private void addRestartHighlightingListenerToCurrentEditor() {
|
||||
@@ -273,41 +271,7 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
|
||||
@Override
|
||||
public void documentChanged(@NotNull final DocumentEvent event) {
|
||||
initiateValidation();
|
||||
}
|
||||
|
||||
private void initiateValidation() {
|
||||
if (myAlarm.isDisposed()) return;
|
||||
myAlarm.cancelAllRequests();
|
||||
myAlarm.addRequest(() -> {
|
||||
final boolean success = ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(() -> {
|
||||
try {
|
||||
final CompiledPattern compiledPattern = compilePattern();
|
||||
checkReplacementPattern();
|
||||
final JRootPane component = getRootPane();
|
||||
if (component == null) {
|
||||
return;
|
||||
}
|
||||
initializeFilterPanel();
|
||||
if (compiledPattern != null) {
|
||||
addMatchHighlights();
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
setSearchTargets(myConfiguration.getMatchOptions());
|
||||
getOKAction().setEnabled(compiledPattern != null);
|
||||
}, ModalityState.stateForComponent(component));
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
Logger.getInstance(StructuralSearchDialog.class).error(e);
|
||||
}
|
||||
});
|
||||
if (!success) {
|
||||
initiateValidation();
|
||||
}
|
||||
}, 100);
|
||||
initValidation();
|
||||
}
|
||||
|
||||
private void initializeFilterPanel() {
|
||||
@@ -413,14 +377,14 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
myScopePanel = new ScopePanel(getProject(), myDisposable);
|
||||
if (!myEditConfigOnly) {
|
||||
myScopePanel.setRecentDirectories(FindInProjectSettings.getInstance(getProject()).getRecentDirectories());
|
||||
myScopePanel.setScopeConsumer(scope -> initiateValidation());
|
||||
myScopePanel.setScopeConsumer(scope -> initValidation());
|
||||
}
|
||||
else {
|
||||
myScopePanel.setVisible(false);
|
||||
}
|
||||
|
||||
myFilterPanel = new FilterPanel(getProject(), myFileType, getDisposable());
|
||||
myFilterPanel.setConstraintChangedCallback(() -> initiateValidation());
|
||||
myFilterPanel.setConstraintChangedCallback(() -> initValidation());
|
||||
myFilterPanel.getComponent().setMinimumSize(new Dimension(300, 50));
|
||||
mySearchEditorPanel.setSecondComponent(myFilterPanel.getComponent());
|
||||
|
||||
@@ -431,7 +395,7 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
for (String name : matchOptions.getVariableConstraintNames()) {
|
||||
matchOptions.getVariableConstraint(name).setPartOfSearchResults(name.equals(item));
|
||||
}
|
||||
initiateValidation();
|
||||
initValidation();
|
||||
});
|
||||
|
||||
final JPanel centerPanel = new JPanel(null);
|
||||
@@ -601,7 +565,7 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
@Override
|
||||
public void setSelected(@NotNull AnActionEvent e, boolean state) {
|
||||
myConfiguration.getMatchOptions().setSearchInjectedCode(state);
|
||||
initiateValidation();
|
||||
initValidation();
|
||||
}
|
||||
};
|
||||
final CheckboxAction recursive = new CheckboxAction(SSRBundle.message("recursive.matching.checkbox")) {
|
||||
@@ -621,7 +585,7 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
public void setSelected(@NotNull AnActionEvent e, boolean state) {
|
||||
if (myConfiguration instanceof SearchConfiguration) {
|
||||
myConfiguration.getMatchOptions().setRecursiveSearch(state);
|
||||
initiateValidation();
|
||||
initValidation();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -634,7 +598,7 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
@Override
|
||||
public void setSelected(@NotNull AnActionEvent e, boolean state) {
|
||||
myConfiguration.getMatchOptions().setCaseSensitiveMatch(state);
|
||||
initiateValidation();
|
||||
initValidation();
|
||||
}
|
||||
};
|
||||
myFileType = UIUtil.detectFileType(mySearchContext);
|
||||
@@ -670,7 +634,7 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
myReplaceCriteriaEdit.setNewDocumentAndFileType(myFileType, replaceDocument);
|
||||
replaceDocument.putUserData(STRUCTURAL_SEARCH_PATTERN_CONTEXT_ID, contextId);
|
||||
|
||||
initiateValidation();
|
||||
initValidation();
|
||||
});
|
||||
final DefaultActionGroup templateActionGroup = new DefaultActionGroup();
|
||||
templateActionGroup.add(
|
||||
@@ -839,15 +803,10 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
myDoingOkAction = true;
|
||||
super.doOKAction();
|
||||
removeMatchHighlights();
|
||||
final CompiledPattern compiledPattern = compilePattern();
|
||||
myDoingOkAction = false;
|
||||
if (compiledPattern == null) return;
|
||||
|
||||
myAlarm.cancelAllRequests();
|
||||
myConfiguration.removeUnusedVariables();
|
||||
super.doOKAction();
|
||||
if (myEditConfigOnly) return;
|
||||
|
||||
final SearchScope scope = myScopePanel.getScope();
|
||||
@@ -856,16 +815,9 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
FindInProjectSettings.getInstance(getProject()).addDirectory(directoryScope.getDirectory().getPresentableUrl());
|
||||
}
|
||||
|
||||
final FindSettings findSettings = FindSettings.getInstance();
|
||||
findSettings.setShowResultsInSeparateView(myOpenInNewTab.isSelected());
|
||||
|
||||
try {
|
||||
ConfigurationManager.getInstance(getProject()).addHistoryConfiguration(myConfiguration);
|
||||
startSearching();
|
||||
}
|
||||
catch (MalformedPatternException ex) {
|
||||
reportMessage(SSRBundle.message("this.pattern.is.malformed.message", ex.getMessage()), true, mySearchCriteriaEdit);
|
||||
}
|
||||
FindSettings.getInstance().setShowResultsInSeparateView(myOpenInNewTab.isSelected());
|
||||
ConfigurationManager.getInstance(getProject()).addHistoryConfiguration(myConfiguration);
|
||||
startSearching();
|
||||
}
|
||||
|
||||
public Configuration getConfiguration() {
|
||||
@@ -873,55 +825,6 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
return myConfiguration.copy();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CompiledPattern compilePattern() {
|
||||
final MatchOptions matchOptions = getConfiguration().getMatchOptions();
|
||||
final Project project = getProject();
|
||||
try {
|
||||
final CompiledPattern compiledPattern = PatternCompiler.compilePattern(project, matchOptions, true, !myEditConfigOnly);
|
||||
reportMessage(null, false, mySearchCriteriaEdit);
|
||||
return compiledPattern;
|
||||
}
|
||||
catch (MalformedPatternException e) {
|
||||
removeMatchHighlights();
|
||||
final String message = isEmpty(matchOptions.getSearchPattern())
|
||||
? null
|
||||
: SSRBundle.message("this.pattern.is.malformed.message", (e.getMessage() != null) ? e.getMessage() : "");
|
||||
if (!e.isErrorElement || !Registry.is("ssr.in.editor.problem.highlighting")) {
|
||||
reportMessage(message, true, mySearchCriteriaEdit);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (UnsupportedPatternException e) {
|
||||
removeMatchHighlights();
|
||||
reportMessage(SSRBundle.message("this.pattern.is.unsupported.message", e.getMessage()), true, mySearchCriteriaEdit);
|
||||
return null;
|
||||
}
|
||||
catch (NoMatchFoundException e) {
|
||||
removeMatchHighlights();
|
||||
reportMessage(e.getMessage(), false, myScopePanel);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkReplacementPattern() {
|
||||
if (!myReplace) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Replacer.checkReplacementPattern(getProject(), myConfiguration.getReplaceOptions());
|
||||
reportMessage(null, false, myReplaceCriteriaEdit);
|
||||
}
|
||||
catch (UnsupportedPatternException ex) {
|
||||
reportMessage(SSRBundle.message("unsupported.replacement.pattern.message", ex.getMessage()), true, myReplaceCriteriaEdit);
|
||||
}
|
||||
catch (MalformedPatternException ex) {
|
||||
if (!ex.isErrorElement || !Registry.is("ssr.in.editor.problem.highlighting")) {
|
||||
reportMessage(SSRBundle.message("malformed.replacement.pattern.message", ex.getMessage()), true, myReplaceCriteriaEdit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeMatchHighlights() {
|
||||
if (myEditConfigOnly || myRangeHighlighters.isEmpty()) {
|
||||
return;
|
||||
@@ -1017,25 +920,87 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean continuousValidation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull List<ValidationInfo> doValidateAll() {
|
||||
final JRootPane component = getRootPane();
|
||||
if (component == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<ValidationInfo> errors = new SmartList<>();
|
||||
if (mySearchCriteriaEdit.getText().trim().isEmpty()) {
|
||||
errors.add(new ValidationInfo(""));
|
||||
}
|
||||
final MatchOptions matchOptions = getConfiguration().getMatchOptions();
|
||||
try {
|
||||
final Project project = getProject();
|
||||
CompiledPattern compiledPattern = null;
|
||||
try {
|
||||
compiledPattern = PatternCompiler.compilePattern(project, matchOptions, true, !myEditConfigOnly && !myPerformAction);
|
||||
}
|
||||
catch (MalformedPatternException e) {
|
||||
removeMatchHighlights();
|
||||
if (!StringUtil.isEmptyOrSpaces(matchOptions.getSearchPattern())) {
|
||||
final String message = e.getMessage();
|
||||
errors.add(new ValidationInfo((message == null)
|
||||
? SSRBundle.message("this.pattern.is.malformed.message")
|
||||
: message,
|
||||
mySearchCriteriaEdit));
|
||||
}
|
||||
}
|
||||
catch (UnsupportedPatternException e) {
|
||||
removeMatchHighlights();
|
||||
errors.add(new ValidationInfo(e.getMessage(), mySearchCriteriaEdit));
|
||||
}
|
||||
catch (NoMatchFoundException e) {
|
||||
removeMatchHighlights();
|
||||
errors.add(new ValidationInfo(e.getMessage(), mySearchCriteriaEdit));
|
||||
}
|
||||
if (myReplace) {
|
||||
try {
|
||||
Replacer.checkReplacementPattern(getProject(), myConfiguration.getReplaceOptions());
|
||||
}
|
||||
catch (UnsupportedPatternException e) {
|
||||
errors.add(new ValidationInfo(e.getMessage(), myReplaceCriteriaEdit));
|
||||
}
|
||||
catch (MalformedPatternException e) {
|
||||
errors.add(new ValidationInfo(e.getMessage(), myReplaceCriteriaEdit));
|
||||
}
|
||||
}
|
||||
|
||||
initializeFilterPanel();
|
||||
if (compiledPattern != null) {
|
||||
addMatchHighlights();
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
setSearchTargets(myConfiguration.getMatchOptions());
|
||||
}, ModalityState.stateForComponent(component));
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
Logger.getInstance(StructuralSearchDialog.class).error(e);
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
private Balloon myBalloon;
|
||||
private void reportMessage(@NlsContexts.PopupContent @Nullable String message, boolean error, @NotNull JComponent component) {
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
if (isDisposed()) return;
|
||||
if (myBalloon != null) myBalloon.hide();
|
||||
component.putClientProperty("JComponent.outline", (!error || message == null) ? null : "error");
|
||||
component.repaint();
|
||||
|
||||
if (message == null) return;
|
||||
myBalloon = JBPopupFactory.getInstance()
|
||||
.createHtmlTextBalloonBuilder(message, error ? MessageType.ERROR : MessageType.WARNING, null)
|
||||
.setHideOnFrameResize(false)
|
||||
.createBalloon();
|
||||
if (component != myScopePanel) {
|
||||
myBalloon.show(new RelativePoint(component, new Point(component.getWidth() / 2, component.getHeight())), Balloon.Position.below);
|
||||
}
|
||||
else {
|
||||
myBalloon.show(new RelativePoint(component, new Point(component.getWidth() / 2, 0)), Balloon.Position.above);
|
||||
}
|
||||
myBalloon.showInCenterOf(component);
|
||||
myBalloon.show(new RelativePoint(component, new Point(component.getWidth() / 2, component.getHeight())), Balloon.Position.below);
|
||||
Disposer.register(myDisposable, myBalloon);
|
||||
}, ModalityState.stateForComponent(component));
|
||||
}
|
||||
@@ -1192,7 +1157,7 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
final SearchScope scope = myScopePanel.getScope();
|
||||
final boolean searchWithinHierarchy = IdeBundle.message("scope.class.hierarchy").equals(scope.getDisplayName());
|
||||
// We need to reset search within hierarchy scope during online validation since the scope works with user participation
|
||||
matchOptions.setScope(searchWithinHierarchy && !myDoingOkAction ? GlobalSearchScope.projectScope(getProject()) : scope);
|
||||
matchOptions.setScope(searchWithinHierarchy && !myPerformAction ? GlobalSearchScope.projectScope(getProject()) : scope);
|
||||
}
|
||||
else {
|
||||
matchOptions.setScope(null);
|
||||
@@ -1389,7 +1354,7 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
SubstitutionShortInfoHandler.install(editor, variableName -> {
|
||||
if (variableName.endsWith(ReplaceConfiguration.REPLACEMENT_VARIABLE_SUFFIX)) {
|
||||
//noinspection AssignmentToLambdaParameter
|
||||
variableName = trimEnd(variableName, ReplaceConfiguration.REPLACEMENT_VARIABLE_SUFFIX);
|
||||
variableName = StringUtil.trimEnd(variableName, ReplaceConfiguration.REPLACEMENT_VARIABLE_SUFFIX);
|
||||
assert myConfiguration instanceof ReplaceConfiguration;
|
||||
myFilterPanel.initFilters(UIUtil.getOrAddReplacementVariable(variableName, myConfiguration));
|
||||
}
|
||||
@@ -1402,10 +1367,7 @@ public class StructuralSearchDialog extends DialogWrapper implements DocumentLis
|
||||
}, myDisposable, myReplace);
|
||||
editor.putUserData(SubstitutionShortInfoHandler.CURRENT_CONFIGURATION_KEY, myConfiguration);
|
||||
getDocument().putUserData(STRUCTURAL_SEARCH_ERROR_CALLBACK, () -> {
|
||||
putClientProperty("JComponent.outline", "error");
|
||||
repaint();
|
||||
getOKAction().setEnabled(false);
|
||||
if (!myReplace) removeMatchHighlights();
|
||||
if (getClientProperty("JComponent.outline") == null) initValidation();
|
||||
});
|
||||
|
||||
TextCompletionUtil.installCompletionHint(editor);
|
||||
|
||||
@@ -50,8 +50,7 @@ found.occurrences=Found Matches in {0}
|
||||
targets.node.text=Structural Search Template
|
||||
|
||||
# search dialog messages
|
||||
this.pattern.is.malformed.message=The specified template is malformed\n {0}
|
||||
this.pattern.is.unsupported.message=The specified template is unsupported
|
||||
this.pattern.is.malformed.message=The specified template is malformed
|
||||
incorrect.pattern.message=Incorrect template
|
||||
|
||||
used.templates.history.dialog.title=Used Templates History
|
||||
@@ -109,10 +108,6 @@ structural.replace.title=Structural Replace
|
||||
shorten.fully.qualified.names.checkbox=Sh&orten fully qualified names
|
||||
replacement.template.label=Replace template:
|
||||
|
||||
# Replace validation messages
|
||||
unsupported.replacement.pattern.message=Unsupported replacement template {0}
|
||||
malformed.replacement.pattern.message=Malformed replacement template {0}
|
||||
|
||||
#replacement usage view specific
|
||||
preview.replacement.button=&Preview Replacement
|
||||
do.replace.all.button=Replace &All
|
||||
|
||||
Reference in New Issue
Block a user