mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of ssh://git-hosting.labs.intellij.net/idea-community
This commit is contained in:
@@ -217,7 +217,7 @@ public class GlobalSearchScopesCore {
|
||||
myDirectory = psiDirectory.getVirtualFile();
|
||||
}
|
||||
|
||||
private DirectoryScope(@NotNull Project project, @NotNull VirtualFile directory, final boolean withSubdirectories) {
|
||||
public DirectoryScope(@NotNull Project project, @NotNull VirtualFile directory, final boolean withSubdirectories) {
|
||||
super(project);
|
||||
myWithSubdirectories = withSubdirectories;
|
||||
myDirectory = directory;
|
||||
|
||||
@@ -121,6 +121,7 @@ public class PsiInvalidElementAccessException extends RuntimeException implement
|
||||
@Nullable Object trace) {
|
||||
String reason = "Element: " + element.getClass();
|
||||
if (!recursiveInvocation) {
|
||||
reason += " #" + element.getLanguage() + " ";
|
||||
String traceText = !isTrackingInvalidation() ? "disabled" :
|
||||
trace != null ? "see attachment" :
|
||||
"no info";
|
||||
|
||||
+16
-7
@@ -488,9 +488,25 @@ public class CodeCompletionHandlerBase {
|
||||
if (context.shouldAddCompletionChar()) {
|
||||
WriteAction.run(() -> addCompletionChar(context, item, editor, completionChar));
|
||||
}
|
||||
checkPsiTextConcistency(indicator);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
private static void checkPsiTextConcistency(CompletionProcessEx indicator) {
|
||||
PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(InjectedLanguageUtil.getTopLevelEditor(indicator.getEditor()), indicator.getProject());
|
||||
if (psiFile != null) {
|
||||
if (Registry.is("ide.check.stub.text.consistency") ||
|
||||
ApplicationManager.getApplication().isUnitTestMode() && !ApplicationInfoImpl.isInStressTest()) {
|
||||
StubTextInconsistencyException.checkStubTextConsistency(psiFile);
|
||||
if (PsiDocumentManager.getInstance(psiFile.getProject()).hasUncommitedDocuments()) {
|
||||
PsiDocumentManager.getInstance(psiFile.getProject()).commitAllDocuments();
|
||||
StubTextInconsistencyException.checkStubTextConsistency(psiFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void afterItemInsertion(final CompletionProgressIndicator indicator, final Runnable laterRunnable) {
|
||||
if (laterRunnable != null) {
|
||||
ActionTracker tracker = new ActionTracker(indicator.getEditor(), indicator);
|
||||
@@ -551,13 +567,6 @@ public class CodeCompletionHandlerBase {
|
||||
context.stopWatching();
|
||||
}
|
||||
|
||||
if (psiFile.isValid()) {
|
||||
if (Registry.is("ide.check.stub.text.consistency") ||
|
||||
ApplicationManager.getApplication().isUnitTestMode() && !ApplicationInfoImpl.isInStressTest()) {
|
||||
StubTextInconsistencyException.checkStubTextConsistency(psiFile);
|
||||
}
|
||||
}
|
||||
|
||||
EditorModificationUtil.scrollToCaret(editor);
|
||||
});
|
||||
if (lookup != null) {
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2018 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.execution.ui;
|
||||
|
||||
import com.intellij.execution.CommonProgramRunConfigurationParameters;
|
||||
@@ -95,23 +81,8 @@ public class CommonProgramParametersPanel extends JPanel implements PanelWithAnc
|
||||
ExecutionBundle.message("run.configuration.program.parameters"));
|
||||
ExpandableTextField expandableTextField = (ExpandableTextField)myProgramParametersComponent.getComponent().getTextField();
|
||||
if (Registry.is("allow.macros.for.run.configurations")) {
|
||||
expandableTextField.addExtension(new ExtendableTextComponent.Extension() {
|
||||
@Override
|
||||
public Icon getIcon(boolean hovered) {
|
||||
return AllIcons.General.Add;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltip() {
|
||||
return "Insert Macros";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Runnable getActionOnClick() {
|
||||
return () -> MacrosDialog.show(expandableTextField,
|
||||
macro -> !(macro instanceof PromptingMacro) && !(macro instanceof EditorMacro));
|
||||
}
|
||||
});
|
||||
expandableTextField.addExtension(ExtendableTextComponent.Extension.create(AllIcons.General.Add, "Insert Macros", ()
|
||||
-> MacrosDialog.show(expandableTextField, macro -> !(macro instanceof PromptingMacro) && !(macro instanceof EditorMacro))));
|
||||
}
|
||||
|
||||
FileChooserDescriptor fileChooserDescriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2018 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.ide;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
|
||||
public abstract class RemoteDesktopService {
|
||||
@@ -9,7 +10,7 @@ public abstract class RemoteDesktopService {
|
||||
}
|
||||
|
||||
public static boolean isRemoteSession() {
|
||||
return getInstance().isRemoteDesktopConnected();
|
||||
return ApplicationManager.getApplication() != null && getInstance().isRemoteDesktopConnected();
|
||||
}
|
||||
|
||||
public abstract boolean isRemoteDesktopConnected();
|
||||
|
||||
@@ -52,31 +52,14 @@ public class ComponentWithBrowseButton<Comp extends JComponent> extends JPanel i
|
||||
setFocusable(false);
|
||||
boolean inlineBrowseButton = myComponent instanceof ExtendableTextComponent && Experiments.isFeatureEnabled("inline.browse.button");
|
||||
if (inlineBrowseButton) {
|
||||
ExtendableTextComponent.Extension action = new ExtendableTextComponent.Extension() {
|
||||
@Override
|
||||
public Icon getIcon(boolean hovered) {
|
||||
return hovered ? AllIcons.General.OpenDiskHover : AllIcons.General.OpenDisk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltip() {
|
||||
return UIBundle.message("component.with.browse.button.browse.button.tooltip.text");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Runnable getActionOnClick() {
|
||||
return () -> {
|
||||
for (ActionListener listener : myBrowseButton.getActionListeners()) {
|
||||
listener.actionPerformed(new ActionEvent(myComponent, ActionEvent.ACTION_PERFORMED, "action"));
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
((ExtendableTextComponent)myComponent).addExtension(action);
|
||||
((ExtendableTextComponent)myComponent).addExtension(ExtendableTextComponent.Extension.create(
|
||||
AllIcons.General.OpenDisk, AllIcons.General.OpenDiskHover,
|
||||
UIBundle.message("component.with.browse.button.browse.button.tooltip.text"),
|
||||
this::notifyActionListeners));
|
||||
new DumbAwareAction() {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
action.getActionOnClick().run();
|
||||
notifyActionListeners();
|
||||
}
|
||||
}.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK)), myComponent);
|
||||
}
|
||||
@@ -101,6 +84,11 @@ public class ComponentWithBrowseButton<Comp extends JComponent> extends JPanel i
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyActionListeners() {
|
||||
ActionEvent event = new ActionEvent(myComponent, ActionEvent.ACTION_PERFORMED, "action");
|
||||
for (ActionListener listener: myBrowseButton.getActionListeners()) listener.actionPerformed(event);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public final Comp getChildComponent() {
|
||||
return myComponent;
|
||||
|
||||
@@ -111,27 +111,14 @@ public abstract class AbstractFieldPanel extends JPanel {
|
||||
|
||||
if (myBrowseButtonActionListener != null) {
|
||||
if (Experiments.isFeatureEnabled("inline.browse.button") && myComponent instanceof ExtendableTextComponent) {
|
||||
ExtendableTextComponent.Extension action = new ExtendableTextComponent.Extension() {
|
||||
@Override
|
||||
public Icon getIcon(boolean hovered) {
|
||||
return hovered ? AllIcons.General.OpenDiskHover : AllIcons.General.OpenDisk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltip() {
|
||||
return UIBundle.message("component.with.browse.button.browse.button.tooltip.text");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Runnable getActionOnClick() {
|
||||
return () -> myBrowseButtonActionListener.actionPerformed(new ActionEvent(myComponent, ActionEvent.ACTION_PERFORMED, "action"));
|
||||
}
|
||||
};
|
||||
((ExtendableTextComponent)myComponent).addExtension(action);
|
||||
((ExtendableTextComponent)myComponent).addExtension(ExtendableTextComponent.Extension.create(
|
||||
AllIcons.General.OpenDisk, AllIcons.General.OpenDiskHover,
|
||||
UIBundle.message("component.with.browse.button.browse.button.tooltip.text"),
|
||||
this::notifyActionListener));
|
||||
new DumbAwareAction() {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
action.getActionOnClick().run();
|
||||
notifyActionListener();
|
||||
}
|
||||
}.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK)), myComponent);
|
||||
|
||||
@@ -164,6 +151,11 @@ public abstract class AbstractFieldPanel extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyActionListener() {
|
||||
ActionEvent event = new ActionEvent(myComponent, ActionEvent.ACTION_PERFORMED, "action");
|
||||
if (myBrowseButtonActionListener != null) myBrowseButtonActionListener.actionPerformed(event);
|
||||
}
|
||||
|
||||
public void setBrowseButtonActionListener(ActionListener browseButtonActionListener) {
|
||||
myBrowseButtonActionListener = browseButtonActionListener;
|
||||
}
|
||||
|
||||
@@ -74,21 +74,17 @@ public class CellRendererPanel extends JPanel {
|
||||
if (count == 1) {
|
||||
Rectangle bounds = new Rectangle(getWidth(), getHeight());
|
||||
JBInsets.removeFrom(bounds, getInsets());
|
||||
Component child = getComponent(0);
|
||||
child.setBounds(bounds);
|
||||
if (child instanceof CellRendererPanel) {
|
||||
((CellRendererPanel)child).invalidateLayout();
|
||||
child.doLayout();
|
||||
}
|
||||
JComponent child = (JComponent)getComponent(0);
|
||||
reshapeImpl(child, bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
invalidateLayout(child);
|
||||
child.doLayout();
|
||||
}
|
||||
else {
|
||||
invalidateLayout();
|
||||
invalidateLayout(this);
|
||||
super.doLayout();
|
||||
for (int i = 0; i < count; i++) {
|
||||
Component c = getComponent(i);
|
||||
if (c instanceof CellRendererPanel) {
|
||||
c.doLayout();
|
||||
}
|
||||
c.doLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,10 +104,14 @@ public class CellRendererPanel extends JPanel {
|
||||
|
||||
@Override
|
||||
public void reshape(int x, int y, int w, int h) {
|
||||
reshapeImpl(this, x, y, w, h);
|
||||
}
|
||||
|
||||
static void reshapeImpl(JComponent component, int x, int y, int w, int h) {
|
||||
// suppress per-cell "moved" and "resized" events on paint
|
||||
// see Component#setBounds, Component#notifyNewBounds
|
||||
AWTAccessor.getComponentAccessor().setLocation(this, x, y);
|
||||
AWTAccessor.getComponentAccessor().setSize(this, w, h);
|
||||
AWTAccessor.getComponentAccessor().setLocation(component, x, y);
|
||||
AWTAccessor.getComponentAccessor().setSize(component, w, h);
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
@@ -121,10 +121,10 @@ public class CellRendererPanel extends JPanel {
|
||||
super.invalidate();
|
||||
}
|
||||
|
||||
private void invalidateLayout() {
|
||||
LayoutManager layout = getLayout();
|
||||
private static void invalidateLayout(JComponent component) {
|
||||
LayoutManager layout = component.getLayout();
|
||||
if (layout instanceof LayoutManager2) {
|
||||
((LayoutManager2)layout).invalidateLayout(this);
|
||||
((LayoutManager2)layout).invalidateLayout(component);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
// Copyright 2000-2018 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.ui.components.fields;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.ui.Expandable;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.components.JBScrollBar;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.ui.components.fields.ExtendableTextComponent.Extension;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ui.JBInsets;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.ApiStatus.Experimental;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.AncestorListener;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import static com.intellij.openapi.keymap.KeymapUtil.createTooltipText;
|
||||
import static java.awt.event.InputEvent.CTRL_MASK;
|
||||
import static java.beans.EventHandler.create;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static javax.swing.KeyStroke.getKeyStroke;
|
||||
import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
|
||||
|
||||
@Experimental
|
||||
public abstract class ExpandableSupport<Source extends JComponent> implements Expandable {
|
||||
private static final int MINIMAL_WIDTH = 50;
|
||||
private final Source source;
|
||||
private final Function<String, String> onShow;
|
||||
private final Function<String, String> onHide;
|
||||
private JBPopup popup;
|
||||
private String title;
|
||||
private String comment;
|
||||
|
||||
public ExpandableSupport(@NotNull Source source, Function<String, String> onShow, Function<String, String> onHide) {
|
||||
this.source = source;
|
||||
this.onShow = onShow != null ? onShow : Function.ID;
|
||||
this.onHide = onHide != null ? onHide : Function.ID;
|
||||
source.putClientProperty(Expandable.class, this);
|
||||
source.addAncestorListener(create(AncestorListener.class, this, "collapse"));
|
||||
source.addComponentListener(create(ComponentListener.class, this, "collapse"));
|
||||
}
|
||||
|
||||
protected abstract boolean isEditable(@NotNull Source source);
|
||||
|
||||
protected abstract int getCaretPosition(@NotNull Source source);
|
||||
|
||||
protected abstract String getText(@NotNull Source source);
|
||||
|
||||
protected abstract void setText(@NotNull Source source, String text, int caret);
|
||||
|
||||
protected abstract Insets getInsets(@NotNull Source source);
|
||||
|
||||
public final String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public final void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public final String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
public final void setComment(String comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isExpanded() {
|
||||
return popup != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void collapse() {
|
||||
if (popup != null) popup.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void expand() {
|
||||
if (popup != null || !source.isEnabled()) return;
|
||||
|
||||
Font font = source.getFont();
|
||||
FontMetrics metrics = font == null ? null : source.getFontMetrics(font);
|
||||
int height = metrics == null ? 16 : metrics.getHeight();
|
||||
Dimension size = new Dimension(height * 32, height * 16);
|
||||
|
||||
JTextArea area = new JTextArea(onShow.fun(getText(source)));
|
||||
area.putClientProperty(Expandable.class, this);
|
||||
area.setEditable(isEditable(source));
|
||||
area.setBackground(source.getBackground());
|
||||
area.setForeground(source.getForeground());
|
||||
area.setFont(font);
|
||||
area.setWrapStyleWord(true);
|
||||
area.setLineWrap(true);
|
||||
setCaretPositionSafely(area, getCaretPosition(source));
|
||||
UIUtil.addUndoRedoActions(area);
|
||||
|
||||
JBScrollPane pane = new JBScrollPane(area);
|
||||
addExtension(pane, createCollapseExtension(this));
|
||||
|
||||
Insets insets = getInsets(source);
|
||||
//TODO: support scroll pane
|
||||
|
||||
JBInsets.addTo(size, insets);
|
||||
JBInsets.addTo(size, pane.getInsets());
|
||||
if (size.width - MINIMAL_WIDTH < source.getWidth()) size.width = source.getWidth();
|
||||
|
||||
Point location = new Point(0, 0);
|
||||
SwingUtilities.convertPointToScreen(location, source);
|
||||
Rectangle screen = ScreenUtil.getScreenRectangle(source);
|
||||
int bottom = screen.y - location.y + screen.height;
|
||||
if (bottom < size.height) {
|
||||
int top = location.y - screen.y + source.getHeight();
|
||||
if (top < bottom) {
|
||||
size.height = bottom;
|
||||
}
|
||||
else {
|
||||
if (size.height > top) size.height = top;
|
||||
location.y -= size.height - source.getHeight();
|
||||
}
|
||||
}
|
||||
pane.setPreferredSize(size);
|
||||
pane.setViewportBorder(BorderFactory.createEmptyBorder(insets.top, insets.left, insets.bottom, insets.right));
|
||||
|
||||
popup = JBPopupFactory
|
||||
.getInstance()
|
||||
.createComponentPopupBuilder(pane, area)
|
||||
.setMayBeParent(true) // this creates a popup as a dialog with alwaysOnTop=false
|
||||
.setFocusable(true)
|
||||
.setRequestFocus(true)
|
||||
.setTitle(title)
|
||||
.setAdText(comment)
|
||||
.setLocateByContent(true)
|
||||
.setCancelOnWindowDeactivation(false)
|
||||
.setKeyboardActions(singletonList(Pair.create(event -> {
|
||||
collapse();
|
||||
Window window = UIUtil.getWindow(source);
|
||||
if (window != null) {
|
||||
window.dispatchEvent(
|
||||
new KeyEvent(source, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), CTRL_MASK, KeyEvent.VK_ENTER, '\r'));
|
||||
}
|
||||
}, getKeyStroke(KeyEvent.VK_ENTER, CTRL_MASK))))
|
||||
.setCancelCallback(() -> {
|
||||
try {
|
||||
if (isEditable(source)) {
|
||||
setText(source, onHide.fun(area.getText()), area.getCaretPosition());
|
||||
}
|
||||
popup = null;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
return false;
|
||||
}
|
||||
}).createPopup();
|
||||
popup.show(new RelativePoint(location));
|
||||
}
|
||||
|
||||
private static void setCaretPositionSafely(JTextComponent component, int caret) {
|
||||
try {
|
||||
component.setCaretPosition(caret);
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public static Extension createCollapseExtension(@NotNull Expandable expandable) {
|
||||
return Extension.create(AllIcons.General.CollapseComponent,
|
||||
AllIcons.General.CollapseComponentHover,
|
||||
createTooltipText("Collapse", "CollapseExpandableComponent"),
|
||||
expandable::collapse);
|
||||
}
|
||||
|
||||
public static Extension createExpandExtension(@NotNull Expandable expandable) {
|
||||
return Extension.create(AllIcons.General.ExpandComponent,
|
||||
AllIcons.General.ExpandComponentHover,
|
||||
createTooltipText("Expand", "ExpandExpandableComponent"),
|
||||
expandable::collapse);
|
||||
}
|
||||
|
||||
private static void addExtension(@NotNull JScrollPane pane, @NotNull Extension extension) {
|
||||
pane.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
|
||||
JScrollBar vsb = pane.getVerticalScrollBar();
|
||||
if (vsb != null) {
|
||||
vsb.add(JBScrollBar.LEADING, new JLabel(extension.getIcon(false)) {{
|
||||
setToolTipText(extension.getTooltip());
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
setBorder(JBUI.Borders.empty(5, 0, 5, 5));
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent event) {
|
||||
setIcon(extension.getIcon(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent event) {
|
||||
setIcon(extension.getIcon(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent event) {
|
||||
Runnable action = extension.getActionOnClick();
|
||||
if (action != null) action.run();
|
||||
}
|
||||
});
|
||||
}});
|
||||
JViewport viewport = pane.getViewport();
|
||||
if (viewport != null) {
|
||||
Component view = viewport.getView();
|
||||
if (view != null) vsb.setBackground(view.getBackground());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class TextComponent<Source extends JTextComponent> extends ExpandableSupport<Source> {
|
||||
TextComponent(@NotNull Source source, Function<String, String> onShow, Function<String, String> onHide) {
|
||||
super(source, onShow, onHide);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEditable(@NotNull Source source) {
|
||||
return source.isEditable();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getCaretPosition(@NotNull Source source) {
|
||||
return source.getCaretPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getText(@NotNull Source source) {
|
||||
return source.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setText(@NotNull Source source, String text, int caret) {
|
||||
source.setText(text);
|
||||
setCaretPositionSafely(source, caret);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Insets getInsets(@NotNull Source source) {
|
||||
Insets insets = source.getInsets();
|
||||
Insets margin = source.getMargin();
|
||||
if (margin != null) {
|
||||
insets.top += margin.top;
|
||||
insets.left += margin.left;
|
||||
insets.right += margin.right;
|
||||
insets.bottom += margin.bottom;
|
||||
}
|
||||
return insets;
|
||||
}
|
||||
}
|
||||
|
||||
static final class Area extends TextComponent<JTextArea> {
|
||||
Area(@NotNull JTextArea area, Function<String, String> onShow, Function<String, String> onHide) {
|
||||
super(area, onShow, onHide);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setText(@NotNull JTextArea source, String text, int caret) {
|
||||
super.setText(source, text, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Insets getInsets(@NotNull JTextArea source) {
|
||||
//noinspection UnnecessaryLocalVariable //TODO: support scroll pane
|
||||
Insets insets = super.getInsets(source);
|
||||
return insets;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-162
@@ -1,50 +1,22 @@
|
||||
// Copyright 2000-2018 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.ui.components.fields;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.Expandable;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.components.JBScrollBar;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.execution.ParametersListUtil;
|
||||
import com.intellij.util.ui.JBInsets;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.AncestorListener;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.openapi.keymap.KeymapUtil.createTooltipText;
|
||||
import static java.awt.event.InputEvent.CTRL_MASK;
|
||||
import static java.beans.EventHandler.create;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static javax.swing.KeyStroke.getKeyStroke;
|
||||
import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
|
||||
|
||||
/**
|
||||
* @author Sergey Malenkov
|
||||
*/
|
||||
public class ExpandableTextField extends ExtendableTextField implements Expandable {
|
||||
private static final int MINIMAL_WIDTH = 50;
|
||||
private final Function<String, String> parser;
|
||||
private final Function<String, String> joiner;
|
||||
private JBPopup popup;
|
||||
private String title;
|
||||
private final ExpandableSupport support;
|
||||
|
||||
/**
|
||||
* Creates an expandable text field with the default line parser/joiner,
|
||||
@@ -60,39 +32,23 @@ public class ExpandableTextField extends ExtendableTextField implements Expandab
|
||||
* @see ParametersListUtil
|
||||
*/
|
||||
public ExpandableTextField(@NotNull Function<String, List<String>> parser, @NotNull Function<List<String>, String> joiner) {
|
||||
this.parser = text -> StringUtil.join(parser.fun(text), "\n");
|
||||
this.joiner = text -> joiner.fun(Arrays.asList(StringUtil.splitByLines(text)));
|
||||
addAncestorListener(create(AncestorListener.class, this, "collapse"));
|
||||
addComponentListener(create(ComponentListener.class, this, "collapse"));
|
||||
Function<String, String> onShow = text -> StringUtil.join(parser.fun(text), "\n");
|
||||
Function<String, String> onHide = text -> joiner.fun(asList(StringUtil.splitByLines(text)));
|
||||
support = new ExpandableSupport.TextComponent<>(this, onShow, onHide);
|
||||
putClientProperty("monospaced", true);
|
||||
setExtensions(createExtensions());
|
||||
}
|
||||
|
||||
protected List<ExtendableTextComponent.Extension> createExtensions() {
|
||||
return singletonList(new ExtendableTextComponent.Extension() {
|
||||
@Override
|
||||
public Icon getIcon(boolean hovered) {
|
||||
return hovered ? AllIcons.General.ExpandComponentHover : AllIcons.General.ExpandComponent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Runnable getActionOnClick() {
|
||||
return ExpandableTextField.this::expand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltip() {
|
||||
return createTooltipText("Expand", "ExpandExpandableComponent");
|
||||
}
|
||||
});
|
||||
return singletonList(ExpandableSupport.createExpandExtension(support));
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
return support.getTitle();
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
support.setTitle(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,123 +59,16 @@ public class ExpandableTextField extends ExtendableTextField implements Expandab
|
||||
|
||||
@Override
|
||||
public void collapse() {
|
||||
if (popup != null) popup.cancel();
|
||||
support.collapse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpanded() {
|
||||
return popup != null;
|
||||
return support.isExpanded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expand() {
|
||||
if (popup != null || !isEnabled()) return;
|
||||
|
||||
Font font = getFont();
|
||||
FontMetrics metrics = font == null ? null : getFontMetrics(font);
|
||||
int height = metrics == null ? 16 : metrics.getHeight();
|
||||
Dimension size = new Dimension(height * 32, height * 16);
|
||||
|
||||
JTextArea area = new JTextArea(parser.fun(getText()));
|
||||
area.setEditable(isEditable());
|
||||
area.setBackground(getBackground());
|
||||
area.setForeground(getForeground());
|
||||
area.setFont(font);
|
||||
area.setWrapStyleWord(true);
|
||||
area.setLineWrap(true);
|
||||
area.putClientProperty(Expandable.class, this);
|
||||
copyCaretPosition(this, area);
|
||||
UIUtil.addUndoRedoActions(area);
|
||||
|
||||
JBScrollPane pane = new JBScrollPane(area);
|
||||
pane.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
|
||||
pane.getVerticalScrollBar().setBackground(area.getBackground());
|
||||
pane.getVerticalScrollBar().add(JBScrollBar.LEADING, new JLabel(AllIcons.General.CollapseComponent) {{
|
||||
setToolTipText(createTooltipText("Collapse", "CollapseExpandableComponent"));
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
setBorder(JBUI.Borders.empty(5, 0, 5, 5));
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent event) {
|
||||
setIcon(AllIcons.General.CollapseComponentHover);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent event) {
|
||||
setIcon(AllIcons.General.CollapseComponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent event) {
|
||||
collapse();
|
||||
}
|
||||
});
|
||||
}});
|
||||
|
||||
Insets insets = getInsets();
|
||||
Insets margins = getMargin();
|
||||
|
||||
JBInsets.addTo(size, insets);
|
||||
JBInsets.addTo(size, margins);
|
||||
JBInsets.addTo(size, pane.getInsets());
|
||||
if (size.width - MINIMAL_WIDTH < getWidth()) size.width = getWidth();
|
||||
|
||||
Point location = new Point(0, 0);
|
||||
SwingUtilities.convertPointToScreen(location, this);
|
||||
Rectangle screen = ScreenUtil.getScreenRectangle(this);
|
||||
int bottom = screen.y - location.y + screen.height;
|
||||
if (bottom < size.height) {
|
||||
int top = location.y - screen.y + getHeight();
|
||||
if (top < bottom) {
|
||||
size.height = bottom;
|
||||
}
|
||||
else {
|
||||
if (size.height > top) size.height = top;
|
||||
location.y -= size.height - getHeight();
|
||||
}
|
||||
}
|
||||
pane.setPreferredSize(size);
|
||||
pane.setViewportBorder(BorderFactory.createEmptyBorder(insets.top + margins.top,
|
||||
insets.left + margins.left,
|
||||
insets.bottom + margins.bottom,
|
||||
insets.right + margins.right));
|
||||
|
||||
popup = JBPopupFactory.getInstance()
|
||||
.createComponentPopupBuilder(pane, area)
|
||||
.setMayBeParent(true) // this creates a popup as a dialog with alwaysOnTop=false
|
||||
.setFocusable(true)
|
||||
.setRequestFocus(true)
|
||||
.setTitle(title)
|
||||
.setLocateByContent(true)
|
||||
.setCancelOnWindowDeactivation(false)
|
||||
.setKeyboardActions(singletonList(Pair.create(event -> {
|
||||
collapse();
|
||||
Window window = UIUtil.getWindow(this);
|
||||
if (window != null) {
|
||||
window.dispatchEvent(new KeyEvent(this, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), CTRL_MASK, KeyEvent.VK_ENTER, '\r'));
|
||||
}
|
||||
}, getKeyStroke(KeyEvent.VK_ENTER, CTRL_MASK))))
|
||||
.setCancelCallback(() -> {
|
||||
try {
|
||||
if (isEditable()) {
|
||||
setText(joiner.fun(area.getText()));
|
||||
copyCaretPosition(area, this);
|
||||
}
|
||||
popup = null;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ignore) {
|
||||
return false;
|
||||
}
|
||||
}).createPopup();
|
||||
popup.show(new RelativePoint(location));
|
||||
}
|
||||
|
||||
private static void copyCaretPosition(JTextComponent source, JTextComponent destination) {
|
||||
try {
|
||||
destination.setCaretPosition(source.getCaretPosition());
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
}
|
||||
support.expand();
|
||||
}
|
||||
}
|
||||
|
||||
+24
-1
@@ -3,7 +3,7 @@ package com.intellij.ui.components.fields;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.Icon;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -58,5 +58,28 @@ public interface ExtendableTextComponent {
|
||||
default String getTooltip() {
|
||||
return null;
|
||||
}
|
||||
|
||||
static Extension create(@NotNull Icon icon, String tooltip, Runnable action) {
|
||||
return create(icon, icon, tooltip, action);
|
||||
}
|
||||
|
||||
static Extension create(@NotNull Icon defaultIcon, @NotNull Icon hoveredIcon, String tooltip, Runnable action) {
|
||||
return new Extension() {
|
||||
@Override
|
||||
public Icon getIcon(boolean hovered) {
|
||||
return hovered ? hoveredIcon : defaultIcon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltip() {
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Runnable getActionOnClick() {
|
||||
return action;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +153,7 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
|
||||
|
||||
EditorEx editor = (EditorEx)ObjectUtils.assertNotNull(field.getEditor());
|
||||
editor.setRendererMode(true);
|
||||
editor.getSettings().setAnimatedScrolling(false);
|
||||
|
||||
editor.setColorsScheme(editor.createBoundColorSchemeDelegate(null));
|
||||
editor.getSettings().setCaretRowShown(false);
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.intellij.structuralsearch;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.JDOMExternalizable;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.structuralsearch.impl.matcher.compiler.StringToConstraintsTransformer;
|
||||
@@ -23,8 +24,9 @@ public class MatchOptions implements JDOMExternalizable {
|
||||
private boolean caseSensitiveMatch;
|
||||
private FileType myFileType;
|
||||
private Language myDialect;
|
||||
|
||||
private SearchScope scope;
|
||||
private Scopes.Type scopeType;
|
||||
private String scopeDescriptor;
|
||||
private String pattern;
|
||||
|
||||
private String myPatternContext;
|
||||
@@ -36,6 +38,9 @@ public class MatchOptions implements JDOMExternalizable {
|
||||
@NonNls private static final String CONSTRAINT_TAG_NAME = "constraint";
|
||||
@NonNls private static final String FILE_TYPE_ATTR_NAME = "type";
|
||||
@NonNls private static final String DIALECT_ATTR_NAME = "dialect";
|
||||
@NonNls private static final String SCOPE_TYPE = "scope_type";
|
||||
@NonNls private static final String SCOPE_DESCRIPTOR = "scope_descriptor";
|
||||
|
||||
@NonNls public static final String INSTANCE_MODIFIER_NAME = "Instance";
|
||||
@NonNls public static final String MODIFIER_ANNOTATION_NAME = "Modifier";
|
||||
|
||||
@@ -56,6 +61,8 @@ public class MatchOptions implements JDOMExternalizable {
|
||||
myFileType = options.myFileType;
|
||||
myDialect = options.myDialect;
|
||||
scope = options.scope;
|
||||
scopeType = options.scopeType;
|
||||
scopeDescriptor = options.scopeDescriptor;
|
||||
pattern = options.pattern;
|
||||
myPatternContext = options.myPatternContext;
|
||||
}
|
||||
@@ -64,6 +71,12 @@ public class MatchOptions implements JDOMExternalizable {
|
||||
return new MatchOptions(this);
|
||||
}
|
||||
|
||||
public void initScope(Project project) {
|
||||
if (scope == null && scopeType != null && scopeDescriptor != null) {
|
||||
scope = Scopes.createScope(project, scopeDescriptor, scopeType);
|
||||
}
|
||||
}
|
||||
|
||||
public void addVariableConstraint(@NotNull MatchVariableConstraint constraint) {
|
||||
variableConstraints.put(constraint.getName(), constraint);
|
||||
}
|
||||
@@ -153,8 +166,6 @@ public class MatchOptions implements JDOMExternalizable {
|
||||
element.setAttribute(RECURSIVE_ATTRIBUTE_NAME,String.valueOf(recursiveSearch));
|
||||
element.setAttribute(CASESENSITIVE_ATTRIBUTE_NAME,String.valueOf(caseSensitiveMatch));
|
||||
|
||||
//@TODO serialize scope!
|
||||
|
||||
if (myFileType != null) {
|
||||
element.setAttribute(FILE_TYPE_ATTR_NAME, myFileType.getName());
|
||||
}
|
||||
@@ -163,6 +174,10 @@ public class MatchOptions implements JDOMExternalizable {
|
||||
element.setAttribute(DIALECT_ATTR_NAME, myDialect.getID());
|
||||
}
|
||||
|
||||
if (scope != null) {
|
||||
element.setAttribute(SCOPE_TYPE, Scopes.getType(scope).toString()).setAttribute(SCOPE_DESCRIPTOR, Scopes.getDescriptor(scope));
|
||||
}
|
||||
|
||||
for (final MatchVariableConstraint matchVariableConstraint : variableConstraints.values()) {
|
||||
if (matchVariableConstraint.isArtificial()) continue;
|
||||
final Element infoElement = new Element(CONSTRAINT_TAG_NAME);
|
||||
@@ -208,7 +223,14 @@ public class MatchOptions implements JDOMExternalizable {
|
||||
myDialect = Language.findLanguageByID(attr.getValue());
|
||||
}
|
||||
|
||||
// @TODO deserialize scope
|
||||
attr = element.getAttribute(SCOPE_TYPE);
|
||||
if (attr != null) {
|
||||
scopeType = Scopes.Type.valueOf(attr.getValue());
|
||||
}
|
||||
attr = element.getAttribute(SCOPE_DESCRIPTOR);
|
||||
if (attr != null) {
|
||||
scopeDescriptor = attr.getValue();
|
||||
}
|
||||
|
||||
for (final Element element1 : element.getChildren(CONSTRAINT_TAG_NAME)) {
|
||||
final MatchVariableConstraint constraint = new MatchVariableConstraint();
|
||||
@@ -236,11 +258,9 @@ public class MatchOptions implements JDOMExternalizable {
|
||||
final MatchOptions matchOptions = (MatchOptions)o;
|
||||
|
||||
if (caseSensitiveMatch != matchOptions.caseSensitiveMatch) return false;
|
||||
//if (enableAutoIdentifySearchTarget != matchOptions.enableAutoIdentifySearchTarget) return false;
|
||||
if (looseMatching != matchOptions.looseMatching) return false;
|
||||
if (recursiveSearch != matchOptions.recursiveSearch) return false;
|
||||
// @TODO support scope
|
||||
|
||||
if (scope != null ? !scope.equals(matchOptions.scope) : matchOptions.scope != null) return false;
|
||||
if (!pattern.equals(matchOptions.pattern)) return false;
|
||||
if (!variableConstraints.equals(matchOptions.variableConstraints)) return false;
|
||||
if (myFileType != matchOptions.myFileType) return false;
|
||||
@@ -254,9 +274,9 @@ public class MatchOptions implements JDOMExternalizable {
|
||||
int result = (looseMatching ? 1 : 0);
|
||||
result = 29 * result + (recursiveSearch ? 1 : 0);
|
||||
result = 29 * result + (caseSensitiveMatch ? 1 : 0);
|
||||
// @TODO support scope
|
||||
result = 29 * result + pattern.hashCode();
|
||||
result = 29 * result + variableConstraints.hashCode();
|
||||
if (scope != null) result = 29 * result + scope.hashCode();
|
||||
if (myFileType != null) result = 29 * result + myFileType.hashCode();
|
||||
if (myDialect != null) result = 29 * result + myDialect.hashCode();
|
||||
return result;
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright 2000-2018 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;
|
||||
|
||||
import com.intellij.ide.util.scopeChooser.ScopeChooserUtils;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.impl.scopes.ModuleWithDependenciesScope;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.GlobalSearchScopesCore;
|
||||
import com.intellij.psi.search.ProjectScopeImpl;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public final class Scopes {
|
||||
|
||||
private Scopes() {}
|
||||
|
||||
public static Type getType(@Nullable SearchScope scope) {
|
||||
if (scope instanceof ProjectScopeImpl || scope == null) {
|
||||
return Type.PROJECT;
|
||||
}
|
||||
else if (scope instanceof ModuleWithDependenciesScope) {
|
||||
return Type.MODULE;
|
||||
}
|
||||
else if (scope instanceof GlobalSearchScopesCore.DirectoryScope) {
|
||||
return Type.DIRECTORY;
|
||||
}
|
||||
else {
|
||||
return Type.NAMED;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getDescriptor(SearchScope scope) {
|
||||
if (scope instanceof ProjectScopeImpl || scope == null) {
|
||||
return "";
|
||||
}
|
||||
else if (scope instanceof ModuleWithDependenciesScope) {
|
||||
return ((ModuleWithDependenciesScope)scope).getModule().getName();
|
||||
}
|
||||
else if (scope instanceof GlobalSearchScopesCore.DirectoryScope) {
|
||||
final GlobalSearchScopesCore.DirectoryScope directoryScope = (GlobalSearchScopesCore.DirectoryScope)scope;
|
||||
final String url = directoryScope.getDirectory().getPresentableUrl();
|
||||
return directoryScope.isWithSubdirectories() ? "*" + url : url;
|
||||
}
|
||||
else {
|
||||
return scope.getDisplayName();
|
||||
}
|
||||
}
|
||||
|
||||
public static SearchScope createScope(@NotNull Project project, @NotNull String descriptor, @NotNull Type scopeType) {
|
||||
if (scopeType == Type.PROJECT) {
|
||||
return GlobalSearchScope.projectScope(project);
|
||||
}
|
||||
else if (scopeType == Type.MODULE) {
|
||||
final Module module = ModuleManager.getInstance(project).findModuleByName(descriptor);
|
||||
if (module != null) {
|
||||
return GlobalSearchScope.moduleScope(module);
|
||||
}
|
||||
}
|
||||
else if (scopeType == Type.DIRECTORY) {
|
||||
final boolean recursive = StringUtil.startsWithChar(descriptor, '*');
|
||||
if (recursive) {
|
||||
descriptor = descriptor.substring(1);
|
||||
}
|
||||
final String path = FileUtil.toSystemIndependentName(descriptor.substring(1));
|
||||
final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(path);
|
||||
if (virtualFile == null) return null;
|
||||
return new GlobalSearchScopesCore.DirectoryScope(project, virtualFile, recursive);
|
||||
}
|
||||
else if (scopeType == Type.NAMED) {
|
||||
return ScopeChooserUtils.findScopeByName(project, descriptor);
|
||||
}
|
||||
assert false;
|
||||
return null;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
PROJECT,
|
||||
MODULE,
|
||||
DIRECTORY,
|
||||
NAMED
|
||||
}
|
||||
}
|
||||
+2
@@ -51,6 +51,7 @@ public class ConfigurationManager implements PersistentStateComponent<Element> {
|
||||
configurations.clear();
|
||||
historyConfigurations.clear();
|
||||
readConfigurations(state, configurations, historyConfigurations);
|
||||
historyConfigurations.forEach(c -> c.getMatchOptions().initScope(myProject));
|
||||
}
|
||||
|
||||
public void addHistoryConfiguration(Configuration configuration) {
|
||||
@@ -75,6 +76,7 @@ public class ConfigurationManager implements PersistentStateComponent<Element> {
|
||||
@NotNull Collection<Configuration> configurations,
|
||||
@NotNull Collection<Configuration> historyConfigurations) {
|
||||
for (final Configuration configuration : configurations) {
|
||||
configuration.getMatchOptions().setScope(null);
|
||||
saveConfiguration(element, configuration);
|
||||
}
|
||||
|
||||
|
||||
+43
-91
@@ -7,24 +7,17 @@ import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CustomShortcutSet;
|
||||
import com.intellij.openapi.actionSystem.ToggleAction;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileChooser.FileChooser;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.fileChooser.FileChooserFactory;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.openapi.ui.FixedSizeButton;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileProvider;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileSystem;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.ui.ComboboxWithBrowseButton;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -33,129 +26,87 @@ import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class DirectoryComboBoxWithButtons extends JPanel {
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final ComboBox<String> myDirectoryComboBox;
|
||||
@NotNull private final ComboboxWithBrowseButton myDirectoryComboBox;
|
||||
private boolean myRecursive = true;
|
||||
private BiConsumer<VirtualFile, Boolean> myCallback;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public DirectoryComboBoxWithButtons(@NotNull Project project) {
|
||||
super(new BorderLayout());
|
||||
|
||||
myProject = project;
|
||||
myDirectoryComboBox = new ComboBox<>(200);
|
||||
myDirectoryComboBox.setEditable(true);
|
||||
final ComboBox<Object> comboBox = new ComboBox<>(200);
|
||||
myDirectoryComboBox = new ComboboxWithBrowseButton(comboBox);
|
||||
myDirectoryComboBox.getComboBox().addItemListener(e -> myCallback.accept(getDirectory(), myRecursive));
|
||||
comboBox.setEditable(true);
|
||||
|
||||
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
|
||||
Component editorComponent = myDirectoryComboBox.getEditor().getEditorComponent();
|
||||
final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
|
||||
final Component editorComponent = comboBox.getEditor().getEditorComponent();
|
||||
if (editorComponent instanceof JTextField) {
|
||||
JTextField field = (JTextField)editorComponent;
|
||||
final JTextField field = (JTextField)editorComponent;
|
||||
field.setColumns(40);
|
||||
FileChooserFactory.getInstance().installFileCompletion(field, descriptor, true, null);
|
||||
}
|
||||
myDirectoryComboBox.setMaximumRowCount(8);
|
||||
comboBox.setMaximumRowCount(8);
|
||||
|
||||
FixedSizeButton mySelectDirectoryButton = new FixedSizeButton(myDirectoryComboBox);
|
||||
TextFieldWithBrowseButton.MyDoClickAction.addTo(mySelectDirectoryButton, myDirectoryComboBox);
|
||||
mySelectDirectoryButton.setMargin(JBUI.emptyInsets());
|
||||
myDirectoryComboBox.addBrowseFolderListener(project, descriptor);
|
||||
|
||||
mySelectDirectoryButton.addActionListener(__ -> {
|
||||
FileChooser.chooseFiles(descriptor, myProject, null, null,
|
||||
new FileChooser.FileChooserConsumer() {
|
||||
@Override
|
||||
public void consume(List<VirtualFile> files) {
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
IdeFocusManager.getInstance(myProject).requestFocus(myDirectoryComboBox.getEditor().getEditorComponent(), true);
|
||||
myDirectoryComboBox.getEditor().setItem(files.get(0).getPresentableUrl());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelled() {
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
IdeFocusManager.getInstance(myProject).requestFocus(myDirectoryComboBox.getEditor().getEditorComponent(), true);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
RecursiveAction
|
||||
recursiveDirectoryAction = new RecursiveAction();
|
||||
int mnemonicModifiers = SystemInfo.isMac ? InputEvent.ALT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK : InputEvent.ALT_DOWN_MASK;
|
||||
final RecursiveAction recursiveDirectoryAction = new RecursiveAction();
|
||||
final int mnemonicModifiers = SystemInfo.isMac ? InputEvent.ALT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK : InputEvent.ALT_DOWN_MASK;
|
||||
recursiveDirectoryAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_Y, mnemonicModifiers)), myDirectoryComboBox);
|
||||
|
||||
add(myDirectoryComboBox, BorderLayout.CENTER);
|
||||
JPanel buttonsPanel = new JPanel(new GridLayout(1, 2));
|
||||
buttonsPanel.add(mySelectDirectoryButton);
|
||||
buttonsPanel.add(FindPopupPanel.createToolbar(recursiveDirectoryAction).getComponent()); //check if toolbar updates the button with no delays
|
||||
add(buttonsPanel, BorderLayout.EAST);
|
||||
add(FindPopupPanel.createToolbar(recursiveDirectoryAction), BorderLayout.EAST);
|
||||
}
|
||||
|
||||
public void init(@Nullable String currentDirectory, @NotNull List<String> recentDirectories) {
|
||||
if (myDirectoryComboBox.getItemCount() > 0) {
|
||||
myDirectoryComboBox.removeAllItems();
|
||||
}
|
||||
if (currentDirectory != null && !currentDirectory.isEmpty()) {
|
||||
recentDirectories.remove(currentDirectory);
|
||||
myDirectoryComboBox.addItem(currentDirectory);
|
||||
}
|
||||
public void setCallback(BiConsumer<VirtualFile, Boolean> callback) {
|
||||
myCallback = callback;
|
||||
}
|
||||
|
||||
public void setRecentDirectories(@NotNull List<String> recentDirectories) {
|
||||
@SuppressWarnings("unchecked") final JComboBox<String> comboBox = myDirectoryComboBox.getComboBox();
|
||||
comboBox.removeAllItems();
|
||||
for (int i = recentDirectories.size() - 1; i >= 0; i--) {
|
||||
myDirectoryComboBox.addItem(recentDirectories.get(i));
|
||||
}
|
||||
if (myDirectoryComboBox.getItemCount() == 0) {
|
||||
myDirectoryComboBox.addItem("");
|
||||
comboBox.addItem(recentDirectories.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void setCurrentDirectory(@NotNull VirtualFile directory) {
|
||||
final String text = directory.getPresentableUrl();
|
||||
final int count = myDirectoryComboBox.getItemCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (text.equals(myDirectoryComboBox.getItemAt(i))) {
|
||||
myDirectoryComboBox.removeItemAt(i);
|
||||
}
|
||||
}
|
||||
myDirectoryComboBox.setSelectedItem(text);
|
||||
public void setDirectory(@NotNull VirtualFile directory) {
|
||||
setDirectory(directory.getPresentableUrl());
|
||||
}
|
||||
|
||||
private void setDirectory(String path) {
|
||||
@SuppressWarnings("unchecked") final JComboBox<String> comboBox = myDirectoryComboBox.getComboBox();
|
||||
comboBox.removeItem(path);
|
||||
comboBox.insertItemAt(path, 0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VirtualFile getDirectory() {
|
||||
String directoryName = (String)myDirectoryComboBox.getSelectedItem();
|
||||
@SuppressWarnings("unchecked") final JComboBox<String> comboBox = myDirectoryComboBox.getComboBox();
|
||||
final String directoryName = (String)comboBox.getSelectedItem();
|
||||
if (StringUtil.isEmptyOrSpaces(directoryName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String path = FileUtil.toSystemIndependentName(directoryName);
|
||||
VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(path);
|
||||
if (virtualFile == null || !virtualFile.isDirectory()) {
|
||||
virtualFile = null;
|
||||
@SuppressWarnings("deprecation") VirtualFileSystem[] fileSystems = ApplicationManager.getApplication().getComponents(VirtualFileSystem.class);
|
||||
for (VirtualFileSystem fs : fileSystems) {
|
||||
if (fs instanceof LocalFileProvider) {
|
||||
@SuppressWarnings("deprecation") VirtualFile file = ((LocalFileProvider)fs).findLocalVirtualFileByPath(path);
|
||||
if (file != null && file.isDirectory()) {
|
||||
if (file.getChildren().length > 0) {
|
||||
virtualFile = file;
|
||||
break;
|
||||
}
|
||||
if (virtualFile == null) {
|
||||
virtualFile = file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return virtualFile;
|
||||
final String path = FileUtil.toSystemIndependentName(directoryName);
|
||||
final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(path);
|
||||
return virtualFile == null || !virtualFile.isDirectory() ? null : virtualFile;
|
||||
}
|
||||
|
||||
public boolean isRecursive() {
|
||||
return myRecursive;
|
||||
}
|
||||
|
||||
public void setRecursive(boolean recursive) {
|
||||
myRecursive = recursive;
|
||||
}
|
||||
|
||||
private class RecursiveAction extends ToggleAction {
|
||||
RecursiveAction() {
|
||||
super(FindBundle.message("find.scope.directory.recursive.checkbox"), "Recursively", AllIcons.Actions.ShowAsTree);
|
||||
@@ -168,7 +119,8 @@ public class DirectoryComboBoxWithButtons extends JPanel {
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
myRecursive = true;
|
||||
myRecursive = state;
|
||||
myCallback.accept(getDirectory(), myRecursive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+537
-117
@@ -4,7 +4,6 @@ package com.intellij.structuralsearch.plugin.ui;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.fileTypes.FileTypes;
|
||||
@@ -12,16 +11,20 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileFactory;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.structuralsearch.MatchVariableConstraint;
|
||||
import com.intellij.structuralsearch.SSRBundle;
|
||||
import com.intellij.structuralsearch.StructuralSearchProfile;
|
||||
import com.intellij.structuralsearch.impl.matcher.CompiledPattern;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.components.fields.IntegerField;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.ui.table.TableView;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.ui.ColumnInfo;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.ListTableModel;
|
||||
import com.intellij.util.ui.table.JBListTable;
|
||||
import com.intellij.util.ui.table.JBTableRow;
|
||||
@@ -31,10 +34,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.JTableHeader;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -43,20 +46,30 @@ import java.util.List;
|
||||
public class FilterPanel {
|
||||
|
||||
private final JPanel myFilterPanel;
|
||||
private final JBListTable myFilterTable;
|
||||
private final ListTableModel<Filter> myTableModel;
|
||||
@NotNull private final Project myProject;
|
||||
private MatchVariableConstraint myConstraint;
|
||||
final JBListTable myFilterTable;
|
||||
final ListTableModel<Filter> myTableModel;
|
||||
|
||||
public FilterPanel(@NotNull Project project, Disposable parent) {
|
||||
@NotNull private final Project myProject;
|
||||
private CompiledPattern myCompiledPattern;
|
||||
MatchVariableConstraint myConstraint;
|
||||
StructuralSearchProfile myProfile;
|
||||
|
||||
final Header myHeader = new Header();
|
||||
private final TextFilter myTextFilter = new TextFilter();
|
||||
private final CountFilter myCountFilter = new CountFilter();
|
||||
private final TypeFilter myTypeFilter = new TypeFilter();
|
||||
private final ReferenceFilter myReferenceFilter = new ReferenceFilter();
|
||||
|
||||
public FilterPanel(@NotNull Project project, StructuralSearchProfile profile, Disposable parent) {
|
||||
myProject = project;
|
||||
myTableModel = new ListTableModel<>(new ColumnInfo<Filter, Filter>("") {
|
||||
myProfile = profile;
|
||||
myTableModel = new ListTableModel<>(new ColumnInfo[]{new ColumnInfo<Filter, Filter>("") {
|
||||
@Nullable
|
||||
@Override
|
||||
public Filter valueOf(Filter s) {
|
||||
return s;
|
||||
}
|
||||
});
|
||||
}}, new SmartList<>());
|
||||
myFilterTable = new JBListTable(new TableView<>(myTableModel), parent) {
|
||||
|
||||
@Override
|
||||
@@ -64,17 +77,18 @@ public class FilterPanel {
|
||||
return new JBTableRowRenderer() {
|
||||
@Override
|
||||
public JComponent getRowRendererComponent(JTable table, int row, boolean selected, boolean focused) {
|
||||
return myTableModel.getRowValue(row).getRowRendererComponent();
|
||||
return myTableModel.getRowValue(row).getRenderer();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JBTableRowEditor getRowEditor(int row) {
|
||||
return myTableModel.getRowValue(row).getRowEditor();
|
||||
return myTableModel.getRowValue(row).getEditor();
|
||||
}
|
||||
};
|
||||
final JBTable table = myFilterTable.getTable();
|
||||
table.setTableHeader(new JTableHeader());
|
||||
table.setStriped(false);
|
||||
myFilterPanel = ToolbarDecorator.createDecorator(table)
|
||||
.disableUpDownActions()
|
||||
@@ -87,39 +101,43 @@ public class FilterPanel {
|
||||
showAddFilterPopup(button.getContextComponent(), point);
|
||||
}
|
||||
})
|
||||
.setRemoveAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
myFilterTable.stopEditing();
|
||||
final int selectedRow = myFilterTable.getTable().getSelectedRow();
|
||||
final Filter filter = myTableModel.getRowValue(selectedRow);
|
||||
if (filter instanceof FilterAction) {
|
||||
((FilterAction)filter).removeFilter();
|
||||
}
|
||||
}
|
||||
})
|
||||
.setRemoveActionUpdater(new AnActionButtonUpdater() {
|
||||
@Override
|
||||
public boolean isEnabled(AnActionEvent e) {
|
||||
return myFilterTable.getTable().getSelectedRow() != 0;
|
||||
}
|
||||
})
|
||||
.setPanelBorder(null)
|
||||
.createPanel();
|
||||
myFilterPanel.setPreferredSize(new Dimension(350, 40));
|
||||
myFilterPanel.setVisible(false);
|
||||
myFilterPanel.setBorder(com.intellij.util.ui.UIUtil.getTextFieldBorder());
|
||||
myFilterPanel.setPreferredSize(new Dimension(350, 60));
|
||||
myFilterPanel.setBorder(BorderFactory.createCompoundBorder(JBUI.Borders.empty(3, 0), myFilterPanel.getBorder()));
|
||||
}
|
||||
|
||||
private void showAddFilterPopup(Component component, RelativePoint point) {
|
||||
final DefaultActionGroup group = new DefaultActionGroup(
|
||||
new AnAction("Text") {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
myTableModel.addRow(new TextFilter(myConstraint));
|
||||
}
|
||||
},
|
||||
new AnAction("Type") {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
assert false : "not implemented";
|
||||
}
|
||||
},
|
||||
new AnAction("Reference") {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
assert false : "not implemented";
|
||||
}
|
||||
},
|
||||
new AnAction("Script") {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
assert false : "not implemented";
|
||||
}
|
||||
void showAddFilterPopup(Component component, RelativePoint point) {
|
||||
myFilterTable.getTable().requestFocus();
|
||||
final DefaultActionGroup group = new DefaultActionGroup();
|
||||
group.add(myTextFilter);
|
||||
group.add(myCountFilter);
|
||||
group.add(myTypeFilter);
|
||||
group.add(myReferenceFilter);
|
||||
|
||||
group.add(new AnAction("Script") {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
assert false : "not implemented";
|
||||
}
|
||||
);
|
||||
});
|
||||
final DataContext context = DataManager.getInstance().getDataContext(component);
|
||||
final ListPopup popup = JBPopupFactory.getInstance().createActionGroupPopup("Add Filter", group, context,
|
||||
JBPopupFactory.ActionSelectionAid.ALPHA_NUMBERING, true, null);
|
||||
@@ -130,51 +148,44 @@ public class FilterPanel {
|
||||
return myFilterPanel;
|
||||
}
|
||||
|
||||
public void setFilters(MatchVariableConstraint constraint) {
|
||||
myConstraint = constraint;
|
||||
final List<Filter> items = new SmartList<>();
|
||||
final String name = constraint.getName();
|
||||
items.add(() -> {
|
||||
final SimpleColoredComponent label = new SimpleColoredComponent();
|
||||
label.append("Filters for $" + name + "$:", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
return label;
|
||||
});
|
||||
if (!StringUtil.isEmpty(constraint.getRegExp())) {
|
||||
items.add(new TextFilter(constraint));
|
||||
}
|
||||
final int min = constraint.getMinCount();
|
||||
final int max = constraint.getMaxCount();
|
||||
if (min != 1 || max != 1) {
|
||||
items.add(() -> new SimpleColoredComponent().append("count=[" + min + "," + (max == Integer.MAX_VALUE ? "∞" : max) + ']'));
|
||||
}
|
||||
|
||||
if (items.size() <= 1) {
|
||||
items.clear();
|
||||
final String message;
|
||||
if (Configuration.CONTEXT_VAR_NAME.equals(name)) {
|
||||
message = "No filters added for the complete match.";
|
||||
}
|
||||
else {
|
||||
message = "No Filters added for $" + name + "$.";
|
||||
}
|
||||
myFilterTable.getTable().getEmptyText().setText(message)
|
||||
.appendSecondaryText("Add filter", SimpleTextAttributes.LINK_ATTRIBUTES,
|
||||
new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final JBTable table = myFilterTable.getTable();
|
||||
showAddFilterPopup(table, new RelativePoint(table, table.getMousePosition()));
|
||||
}
|
||||
});
|
||||
}
|
||||
myTableModel.setItems(items);
|
||||
public void setProfile(StructuralSearchProfile profile) {
|
||||
myProfile = profile;
|
||||
}
|
||||
|
||||
private EditorTextField createTextComponent(String text) {
|
||||
public void setCompiledPattern(CompiledPattern compiledPattern) {
|
||||
myCompiledPattern = compiledPattern;
|
||||
}
|
||||
|
||||
public void setFilters(MatchVariableConstraint constraint) {
|
||||
myConstraint = constraint;
|
||||
final String varName = myConstraint.getName();
|
||||
final List<PsiElement> nodes = myCompiledPattern.getVariableNodes(varName);
|
||||
final boolean completePattern = Configuration.CONTEXT_VAR_NAME.equals(varName);
|
||||
final boolean target = myConstraint.isPartOfSearchResults();
|
||||
myTableModel.setItems(new SmartList<>());
|
||||
myTextFilter.init(nodes, completePattern, target);
|
||||
myCountFilter.init(nodes, completePattern, target);
|
||||
myTypeFilter.init(nodes, completePattern, target);
|
||||
|
||||
final String message = Configuration.CONTEXT_VAR_NAME.equals(varName)
|
||||
? "No filters added for the complete match."
|
||||
: "No Filters added for $" + varName + "$.";
|
||||
myFilterTable.getTable().getEmptyText().setText(message)
|
||||
.appendSecondaryText("Add filter", SimpleTextAttributes.LINK_ATTRIBUTES,
|
||||
new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final JBTable table = myFilterTable.getTable();
|
||||
showAddFilterPopup(table, new RelativePoint(table, table.getMousePosition()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
EditorTextField createTextComponent(String text) {
|
||||
return createEditorComponent(text, "1.txt");
|
||||
}
|
||||
|
||||
private EditorTextField createRegexComponent(String text) {
|
||||
EditorTextField createRegexComponent(String text) {
|
||||
return createEditorComponent(text, "1.regexp");
|
||||
}
|
||||
|
||||
@@ -187,54 +198,83 @@ public class FilterPanel {
|
||||
return new EditorTextField(text, myProject, getFileType(fileName));
|
||||
}
|
||||
|
||||
private Document createDocument(final String fileName, final FileType fileType, String text) {
|
||||
final PsiFile file = PsiFileFactory.getInstance(myProject).createFileFromText(fileName, fileType, text, -1, true);
|
||||
return PsiDocumentManager.getInstance(myProject).getDocument(file);
|
||||
}
|
||||
|
||||
private static FileType getFileType(final String fileName) {
|
||||
FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName);
|
||||
if (fileType == FileTypes.UNKNOWN) fileType = FileTypes.PLAIN_TEXT;
|
||||
return fileType;
|
||||
}
|
||||
|
||||
private interface Filter {
|
||||
JComponent getRowRendererComponent();
|
||||
default JBTableRowEditor getRowEditor() {
|
||||
return null;
|
||||
private class Header implements Filter {
|
||||
|
||||
private final SimpleColoredComponent myLabel = new SimpleColoredComponent();
|
||||
|
||||
Header() {}
|
||||
|
||||
@Override
|
||||
public int position() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SimpleColoredComponent getRenderer() {
|
||||
myLabel.clear();
|
||||
final String varName = myConstraint.getName();
|
||||
myLabel.append(Configuration.CONTEXT_VAR_NAME.equals(varName) ? "Filters for the Complete Match:" : "Filters for $" + varName + "$:",
|
||||
SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
return myLabel;
|
||||
}
|
||||
}
|
||||
|
||||
private class TextFilter implements Filter {
|
||||
private class TextFilter extends FilterAction {
|
||||
|
||||
private final MatchVariableConstraint myConstraint;
|
||||
boolean showHierarchy;
|
||||
|
||||
public TextFilter(MatchVariableConstraint constraint) {
|
||||
myConstraint = constraint;
|
||||
TextFilter() {
|
||||
super("Text");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getRowRendererComponent() {
|
||||
final SimpleColoredComponent component = new SimpleColoredComponent();
|
||||
component.append("text=" + myConstraint.getRegExp());
|
||||
if (myConstraint.isWholeWordsOnly()) component.append(", whole words", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
if (myConstraint.isWithinHierarchy()) component.append(", within hierarchy", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
return component;
|
||||
public int position() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JBTableRowEditor getRowEditor() {
|
||||
return new JBTableRowEditor() {
|
||||
protected boolean hasFilter() {
|
||||
return !StringUtil.isEmpty(myConstraint.getRegExp());
|
||||
}
|
||||
|
||||
private final EditorTextField myTextField = createRegexComponent(myConstraint.getRegExp());
|
||||
private final JCheckBox myWordsCheckBox = new JCheckBox("Words", myConstraint.isWholeWordsOnly());
|
||||
private final JCheckBox myHierarchyCheckBox = new JCheckBox("Within type hierarchy", myConstraint.isWithinHierarchy());
|
||||
public void clearFilter() {
|
||||
myConstraint.setRegExp("");
|
||||
myConstraint.setWholeWordsOnly(false);
|
||||
myConstraint.setWithinHierarchy(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareEditor(JTable table, int row) {
|
||||
final JLabel nameLabel = new JLabel("name=");
|
||||
final ContextHelpLabel helpLabel = ContextHelpLabel.create("Text of the match is checked against the provided pattern.");
|
||||
@Override
|
||||
public boolean isApplicable(List<PsiElement> nodes, boolean completePattern, boolean target) {
|
||||
showHierarchy = myProfile.isApplicableConstraint(UIUtil.TEXT_HIERARCHY, nodes, completePattern, target);
|
||||
return myProfile.isApplicableConstraint(UIUtil.TEXT, nodes, completePattern, target);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setLabel(SimpleColoredComponent component) {
|
||||
myLabel.append("text=");
|
||||
if (myConstraint.isInvertRegExp()) myLabel.append("!");
|
||||
myLabel.append(myConstraint.getRegExp());
|
||||
if (myConstraint.isWholeWordsOnly()) myLabel.append(", whole words", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
if (myConstraint.isWithinHierarchy()) myLabel.append(", within hierarchy", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterEditor getEditor() {
|
||||
return new FilterEditor(myConstraint) {
|
||||
|
||||
private final EditorTextField myTextField = createRegexComponent("");
|
||||
private final JCheckBox myWordsCheckBox = new JCheckBox("Words", false);
|
||||
private final JCheckBox myHierarchyCheckBox = new JCheckBox("Within type hierarchy", false);
|
||||
private final JLabel myNameLabel = new JLabel("name=");
|
||||
private final ContextHelpLabel myHelpLabel = ContextHelpLabel.create("Text of the match is checked against the provided pattern.");
|
||||
|
||||
protected void layoutComponents() {
|
||||
final GroupLayout layout = new GroupLayout(this);
|
||||
setLayout(layout);
|
||||
layout.setAutoCreateContainerGaps(true);
|
||||
@@ -243,10 +283,10 @@ public class FilterPanel {
|
||||
layout.createParallelGroup()
|
||||
.addGroup(
|
||||
layout.createSequentialGroup()
|
||||
.addComponent(nameLabel)
|
||||
.addComponent(myNameLabel)
|
||||
.addComponent(myTextField)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 1, 1)
|
||||
.addComponent(helpLabel)
|
||||
.addComponent(myHelpLabel)
|
||||
)
|
||||
.addGroup(
|
||||
layout.createSequentialGroup()
|
||||
@@ -259,9 +299,9 @@ public class FilterPanel {
|
||||
layout.createSequentialGroup()
|
||||
.addGroup(
|
||||
layout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(nameLabel)
|
||||
.addComponent(myNameLabel)
|
||||
.addComponent(myTextField)
|
||||
.addComponent(helpLabel)
|
||||
.addComponent(myHelpLabel)
|
||||
)
|
||||
.addGroup(
|
||||
layout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
@@ -272,11 +312,18 @@ public class FilterPanel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JBTableRow getValue() {
|
||||
protected void loadValues() {
|
||||
myTextField.setText(myConstraint.getRegExp());
|
||||
myWordsCheckBox.setSelected(myConstraint.isWholeWordsOnly());
|
||||
myHierarchyCheckBox.setSelected(myConstraint.isWithinHierarchy());
|
||||
myHierarchyCheckBox.setVisible(showHierarchy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveValues() {
|
||||
myConstraint.setRegExp(myTextField.getText());
|
||||
myConstraint.setWholeWordsOnly(myWordsCheckBox.isSelected());
|
||||
myConstraint.setWithinHierarchy(myHierarchyCheckBox.isSelected());
|
||||
return __ -> this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -291,4 +338,377 @@ public class FilterPanel {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class CountFilter extends FilterAction {
|
||||
|
||||
boolean myMinZero;
|
||||
boolean myMaxUnlimited;
|
||||
|
||||
CountFilter() {
|
||||
super("Count");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int position() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasFilter() {
|
||||
return myConstraint.getMinCount() != 1 || myConstraint.getMaxCount() != 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearFilter() {
|
||||
myConstraint.setMinCount(1);
|
||||
myConstraint.setMaxCount(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(List<PsiElement> nodes, boolean completePattern, boolean target) {
|
||||
myMinZero = myProfile.isApplicableConstraint(UIUtil.MINIMUM_ZERO, nodes, completePattern, false);
|
||||
myMaxUnlimited = myProfile.isApplicableConstraint(UIUtil.MAXIMUM_UNLIMITED, nodes, completePattern, false);
|
||||
return myMinZero || myMaxUnlimited;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setLabel(SimpleColoredComponent component) {
|
||||
final int min = myConstraint.getMinCount();
|
||||
final int max = myConstraint.getMaxCount();
|
||||
myLabel.append("count=[" + min + "," + (max == Integer.MAX_VALUE ? "∞" : max) + ']');
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterEditor getEditor() {
|
||||
return new FilterEditor(myConstraint) {
|
||||
|
||||
private final IntegerField myMinField = new IntegerField();
|
||||
private final IntegerField myMaxField = new IntegerField();
|
||||
private final JLabel myMinLabel = new JLabel("min=");
|
||||
private final JLabel myMaxLabel = new JLabel("max=");
|
||||
|
||||
{
|
||||
myMinField.getValueEditor().addListener(newValue -> {
|
||||
if (myMinField.getValueEditor().isValid(newValue) && myMaxField.getValue() < newValue) myMaxField.setValue(newValue);
|
||||
});
|
||||
myMaxField.getValueEditor().addListener(newValue -> {
|
||||
if (myMaxField.getValueEditor().isValid(newValue) && myMinField.getValue() > newValue) myMinField.setValue(newValue);
|
||||
});
|
||||
}
|
||||
|
||||
protected void layoutComponents() {
|
||||
final GroupLayout layout = new GroupLayout(this);
|
||||
setLayout(layout);
|
||||
layout.setAutoCreateContainerGaps(true);
|
||||
|
||||
layout.setHorizontalGroup(
|
||||
layout.createSequentialGroup()
|
||||
.addComponent(myMinLabel)
|
||||
.addComponent(myMinField)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 20, 20)
|
||||
.addComponent(myMaxLabel)
|
||||
.addComponent(myMaxField)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(myMinLabel)
|
||||
.addComponent(myMinField)
|
||||
.addComponent(myMaxLabel)
|
||||
.addComponent(myMaxField)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadValues() {
|
||||
myMinField.setMinValue(myMinZero ? 0 : 1);
|
||||
myMinField.setDefaultValue(myMinZero ? 0 : 1);
|
||||
myMinField.setDefaultValueText(myMinZero ? "0" : "1");
|
||||
myMinField.setValue(myConstraint.getMinCount());
|
||||
myMinField.selectAll();
|
||||
|
||||
myMaxField.setMaxValue(myMaxUnlimited ? Integer.MAX_VALUE : 1);
|
||||
myMaxField.setDefaultValue(myMaxUnlimited ? Integer.MAX_VALUE : 1);
|
||||
myMaxField.setDefaultValueText(myMaxUnlimited ? SSRBundle.message("editvarcontraints.unlimited") : "1");
|
||||
myMaxField.setValue(myConstraint.getMaxCount());
|
||||
myMaxField.selectAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveValues() {
|
||||
myConstraint.setMinCount(myMinField.getValue());
|
||||
myConstraint.setMaxCount(myMaxField.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myMinField;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent[] getFocusableComponents() {
|
||||
return new JComponent[] {myMinField, myMaxField};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class TypeFilter extends FilterAction {
|
||||
|
||||
TypeFilter() {
|
||||
super("Type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int position() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasFilter() {
|
||||
return !StringUtil.isEmpty(myConstraint.getNameOfExprType());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearFilter() {
|
||||
myConstraint.setNameOfExprType("");
|
||||
myConstraint.setInvertExprType(false);
|
||||
myConstraint.setExprTypeWithinHierarchy(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(List<PsiElement> nodes, boolean completePattern, boolean target) {
|
||||
return myProfile.isApplicableConstraint(UIUtil.TYPE, nodes, completePattern, target);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setLabel(SimpleColoredComponent component) {
|
||||
myLabel.append("type=");
|
||||
if (myConstraint.isInvertExprType()) myLabel.append("!");
|
||||
myLabel.append(myConstraint.getNameOfExprType());
|
||||
if (myConstraint.isExprTypeWithinHierarchy()) myLabel.append(", within hierarchy", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterEditor getEditor() {
|
||||
return new FilterEditor(myConstraint) {
|
||||
|
||||
private final EditorTextField myTextField = createTextComponent("");
|
||||
private final JLabel myTypeLabel = new JLabel("type=");
|
||||
private final JCheckBox myHierarchyCheckBox = new JCheckBox("Within type hierarchy", false);
|
||||
|
||||
protected void layoutComponents() {
|
||||
final GroupLayout layout = new GroupLayout(this);
|
||||
setLayout(layout);
|
||||
layout.setAutoCreateContainerGaps(true);
|
||||
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup()
|
||||
.addGroup(
|
||||
layout.createSequentialGroup()
|
||||
.addComponent(myTypeLabel)
|
||||
.addComponent(myTextField)
|
||||
)
|
||||
.addComponent(myHierarchyCheckBox)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createSequentialGroup()
|
||||
.addGroup(
|
||||
layout.createParallelGroup(GroupLayout.Alignment.CENTER)
|
||||
.addComponent(myTypeLabel)
|
||||
.addComponent(myTextField)
|
||||
)
|
||||
.addComponent(myHierarchyCheckBox)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadValues() {
|
||||
myTextField.setText((myConstraint.isInvertExprType() ? "!" : "") + myConstraint.getNameOfExprType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveValues() {
|
||||
final String text = myTextField.getText();
|
||||
if (text.startsWith("!")) {
|
||||
myConstraint.setNameOfExprType(text.substring(1));
|
||||
myConstraint.setInvertExprType(true);
|
||||
}
|
||||
else {
|
||||
myConstraint.setNameOfExprType(text);
|
||||
myConstraint.setInvertExprType(false);
|
||||
}
|
||||
myConstraint.setExprTypeWithinHierarchy(myHierarchyCheckBox.isSelected());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myTextField;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent[] getFocusableComponents() {
|
||||
return new JComponent[] { myTextField };
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class ReferenceFilter extends FilterAction {
|
||||
|
||||
ReferenceFilter() {
|
||||
super("Reference");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int position() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasFilter() {
|
||||
return !StringUtil.isEmpty(myConstraint.getReferenceConstraint());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearFilter() {
|
||||
myConstraint.setReferenceConstraint("");
|
||||
myConstraint.setInvertReference(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(List<PsiElement> nodes, boolean completePattern, boolean target) {
|
||||
return myProfile.isApplicableConstraint(UIUtil.REFERENCE, nodes, completePattern, target);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setLabel(SimpleColoredComponent component) {
|
||||
component.append("reference");
|
||||
if (myConstraint.isInvertReference()) component.append("!");
|
||||
component.append(myConstraint.getReferenceConstraint());
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class FilterAction extends AnAction implements Filter {
|
||||
|
||||
protected final SimpleColoredComponent myLabel = new SimpleColoredComponent();
|
||||
|
||||
protected FilterAction(@Nullable String text) {
|
||||
super(text);
|
||||
}
|
||||
|
||||
public final void init(List<PsiElement> nodes, boolean completePattern, boolean target) {
|
||||
if (isApplicable(nodes, completePattern, target) && !myTableModel.getItems().contains(this)) {
|
||||
addFilterIfPresent();
|
||||
}
|
||||
else {
|
||||
clearFilter();
|
||||
getTemplatePresentation().setEnabledAndVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void actionPerformed(AnActionEvent e) {
|
||||
addFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SimpleColoredComponent getRenderer() {
|
||||
if (!hasFilter()) removeFilter();
|
||||
myLabel.clear();
|
||||
setLabel(myLabel);
|
||||
return myLabel;
|
||||
}
|
||||
|
||||
protected abstract void setLabel(SimpleColoredComponent component);
|
||||
|
||||
protected abstract boolean hasFilter();
|
||||
|
||||
public final void addFilterIfPresent() {
|
||||
if (hasFilter()) {
|
||||
getTemplatePresentation().setEnabledAndVisible(false);
|
||||
if (myTableModel.getRowCount() == 0) {
|
||||
myTableModel.addRow(myHeader);
|
||||
}
|
||||
myTableModel.addRow(this);
|
||||
}
|
||||
else {
|
||||
getTemplatePresentation().setEnabledAndVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
public final void addFilter() {
|
||||
getTemplatePresentation().setEnabledAndVisible(false);
|
||||
final JBTable table = myFilterTable.getTable();
|
||||
TableUtil.stopEditing(table);
|
||||
table.setRowHeight(table.getRowHeight()); // reset
|
||||
int index = 0;
|
||||
for (int max = myTableModel.getRowCount(); index < max; index++) {
|
||||
if (position() < myTableModel.getItem(index).position()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index == 0) {
|
||||
myTableModel.addRow(myHeader);
|
||||
index = 1;
|
||||
}
|
||||
myTableModel.insertRow(index, this);
|
||||
table.editCellAt(index, 0);
|
||||
table.setRowSelectionInterval(index, index);
|
||||
table.setColumnSelectionInterval(0, 0);
|
||||
TableUtil.updateScroller(table);
|
||||
final Component editorComponent = table.getEditorComponent();
|
||||
if (editorComponent != null) {
|
||||
table.scrollRectToVisible(editorComponent.getBounds());
|
||||
IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(editorComponent, true));
|
||||
}
|
||||
}
|
||||
|
||||
public final void removeFilter() {
|
||||
final int index = myTableModel.indexOf(this);
|
||||
if (index >= 0) myTableModel.removeRow(index);
|
||||
if (myTableModel.getRowCount() == 1) myTableModel.removeRow(0); // remove header
|
||||
getTemplatePresentation().setEnabledAndVisible(true);
|
||||
clearFilter();
|
||||
}
|
||||
|
||||
protected abstract void clearFilter();
|
||||
|
||||
public abstract boolean isApplicable(List<PsiElement> nodes, boolean completePattern, boolean target);
|
||||
}
|
||||
|
||||
abstract static class FilterEditor extends JBTableRowEditor {
|
||||
|
||||
protected final MatchVariableConstraint myConstraint;
|
||||
|
||||
public FilterEditor(MatchVariableConstraint constraint) {
|
||||
myConstraint = constraint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final JBTableRow getValue() {
|
||||
saveValues();
|
||||
return __ -> this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void prepareEditor(JTable table, int row) {
|
||||
layoutComponents();
|
||||
loadValues();
|
||||
}
|
||||
|
||||
protected abstract void layoutComponents();
|
||||
|
||||
protected abstract void loadValues();
|
||||
|
||||
protected abstract void saveValues();
|
||||
|
||||
}
|
||||
|
||||
private interface Filter {
|
||||
int position();
|
||||
SimpleColoredComponent getRenderer();
|
||||
default FilterEditor getEditor() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+88
-81
@@ -3,9 +3,9 @@ package com.intellij.structuralsearch.plugin.ui;
|
||||
|
||||
import com.intellij.application.options.ModulesComboBox;
|
||||
import com.intellij.find.FindBundle;
|
||||
import com.intellij.find.FindInProjectSettings;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ide.util.scopeChooser.ScopeChooserCombo;
|
||||
import com.intellij.ide.util.scopeChooser.ScopeDescriptor;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -15,8 +15,9 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.GlobalSearchScopesCore;
|
||||
import com.intellij.psi.search.ProjectScopeImpl;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.structuralsearch.Scopes;
|
||||
import com.intellij.ui.JBCardLayout;
|
||||
import com.intellij.util.ui.EmptyIcon;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
@@ -26,6 +27,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -34,51 +36,42 @@ import java.util.function.Consumer;
|
||||
class ScopePanel extends JPanel {
|
||||
|
||||
private final Project myProject;
|
||||
private SearchScope mySelectedScope;
|
||||
private SearchScope myScope;
|
||||
private Scopes.Type myScopeType;
|
||||
private Consumer<SearchScope> myCallback;
|
||||
|
||||
private final ActionToolbarImpl myToolbar;
|
||||
private final JPanel myScopeDetailsPanel = new JPanel(new CardLayout());
|
||||
private final JPanel myScopeDetailsPanel = new JPanel(new JBCardLayout());
|
||||
private final ModulesComboBox myModulesComboBox = new ModulesComboBox();
|
||||
private final DirectoryComboBoxWithButtons myDirectoryComboBox;
|
||||
private final ScopeChooserCombo myScopeChooserComboBox = new ScopeChooserCombo();
|
||||
private final ScopeChooserCombo myScopesComboBox = new ScopeChooserCombo();
|
||||
|
||||
public ScopePanel(@NotNull Project project, SearchScope selectedScope) {
|
||||
public ScopePanel(@NotNull Project project) {
|
||||
super(null);
|
||||
myProject = project;
|
||||
mySelectedScope = selectedScope;
|
||||
|
||||
Module[] allModules = ModuleManager.getInstance(project).getModules();
|
||||
final Module[] allModules = ModuleManager.getInstance(project).getModules();
|
||||
myModulesComboBox.setModules(Arrays.asList(allModules));
|
||||
if (allModules.length > 0) myModulesComboBox.setSelectedModule(allModules[0]);
|
||||
myScopeChooserComboBox.init(project, true, false, "",
|
||||
descriptor -> IdeBundle.message("scope.class.hierarchy").equals(descriptor.getDisplay()) ||
|
||||
!(descriptor.getScope() instanceof ModuleWithDependenciesScope));
|
||||
myModulesComboBox.addItemListener(e -> setScopeFromUI(Scopes.Type.MODULE));
|
||||
myScopesComboBox.init(project, true, false, "",
|
||||
(ScopeDescriptor descriptor) -> IdeBundle.message("scope.class.hierarchy").equals(descriptor.getDisplay()) ||
|
||||
!(descriptor.getScope() instanceof ModuleWithDependenciesScope));
|
||||
myScopesComboBox.getComboBox().addItemListener(e -> setScopeFromUI(Scopes.Type.NAMED));
|
||||
myDirectoryComboBox = new DirectoryComboBoxWithButtons(myProject);
|
||||
myDirectoryComboBox.init(null, FindInProjectSettings.getInstance(myProject).getRecentDirectories()); // todo
|
||||
myDirectoryComboBox.setCallback((vFile, recursive) -> setScopeFromUI(Scopes.Type.DIRECTORY));
|
||||
|
||||
if (selectedScope instanceof ModuleWithDependenciesScope) {
|
||||
final ModuleWithDependenciesScope scope = (ModuleWithDependenciesScope)selectedScope;
|
||||
myModulesComboBox.setSelectedModule(scope.getModule());
|
||||
}
|
||||
else if (selectedScope instanceof GlobalSearchScopesCore.DirectoryScope) {
|
||||
//myDirectoryComboBox.setS;
|
||||
}
|
||||
else if (selectedScope != null) {
|
||||
myScopeChooserComboBox.init(project, true, false, selectedScope.getDisplayName());
|
||||
}
|
||||
|
||||
myScopeDetailsPanel.add(ScopeType.PROJECT.toString(), new JLabel());
|
||||
myScopeDetailsPanel.add(ScopeType.MODULE.toString(), myModulesComboBox);
|
||||
myScopeDetailsPanel.add(ScopeType.DIRECTORY.toString(), myDirectoryComboBox);
|
||||
myScopeDetailsPanel.add(ScopeType.SCOPE.toString(), myScopeChooserComboBox);
|
||||
myScopeDetailsPanel.add(Scopes.Type.PROJECT.toString(), new JLabel());
|
||||
myScopeDetailsPanel.add(Scopes.Type.MODULE.toString(), shrinkWrap(myModulesComboBox));
|
||||
myScopeDetailsPanel.add(Scopes.Type.DIRECTORY.toString(), myDirectoryComboBox);
|
||||
myScopeDetailsPanel.add(Scopes.Type.NAMED.toString(), shrinkWrap(myScopesComboBox));
|
||||
|
||||
myScopeDetailsPanel.setBorder(JBUI.Borders.emptyBottom(UIUtil.isUnderDefaultMacTheme() ? 0 : 3));
|
||||
final DefaultActionGroup scopeActionGroup = new DefaultActionGroup(
|
||||
new ScopeToggleAction(FindBundle.message("find.popup.scope.project"), ScopeType.PROJECT),
|
||||
new ScopeToggleAction(FindBundle.message("find.popup.scope.module"), ScopeType.MODULE),
|
||||
new ScopeToggleAction(FindBundle.message("find.popup.scope.directory"), ScopeType.DIRECTORY),
|
||||
new ScopeToggleAction(FindBundle.message("find.popup.scope.scope"), ScopeType.SCOPE)
|
||||
new ScopeToggleAction(FindBundle.message("find.popup.scope.project"), Scopes.Type.PROJECT),
|
||||
new ScopeToggleAction(FindBundle.message("find.popup.scope.module"), Scopes.Type.MODULE),
|
||||
new ScopeToggleAction(FindBundle.message("find.popup.scope.directory"), Scopes.Type.DIRECTORY),
|
||||
new ScopeToggleAction(FindBundle.message("find.popup.scope.scope"), Scopes.Type.NAMED)
|
||||
);
|
||||
myToolbar = (ActionToolbarImpl)ActionManager.getInstance().createActionToolbar("ScopePanel", scopeActionGroup, true);
|
||||
myToolbar.setForceMinimumSize(true);
|
||||
@@ -90,7 +83,7 @@ class ScopePanel extends JPanel {
|
||||
layout.createSequentialGroup()
|
||||
.addComponent(myToolbar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 25, 25)
|
||||
.addComponent(myScopeDetailsPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(myScopeDetailsPanel)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup()
|
||||
@@ -99,19 +92,73 @@ class ScopePanel extends JPanel {
|
||||
);
|
||||
}
|
||||
|
||||
private static JComponent shrinkWrap(JComponent component) {
|
||||
final JPanel wrapper = new JPanel(new BorderLayout());
|
||||
wrapper.add(component, BorderLayout.WEST);
|
||||
wrapper.add(Box.createHorizontalGlue(), BorderLayout.CENTER);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
public void setRecentDirectories(@NotNull List<String> recentDirectories) {
|
||||
myDirectoryComboBox.setRecentDirectories(recentDirectories);
|
||||
}
|
||||
|
||||
public void setScope(SearchScope selectedScope) {
|
||||
myScope = (selectedScope == null) ? GlobalSearchScope.projectScope(myProject) : selectedScope;
|
||||
myScopeType = Scopes.getType(myScope);
|
||||
|
||||
if (selectedScope instanceof ModuleWithDependenciesScope) {
|
||||
final ModuleWithDependenciesScope scope = (ModuleWithDependenciesScope)selectedScope;
|
||||
myModulesComboBox.setSelectedModule(scope.getModule());
|
||||
}
|
||||
else if (selectedScope instanceof GlobalSearchScopesCore.DirectoryScope) {
|
||||
final GlobalSearchScopesCore.DirectoryScope directoryScope = (GlobalSearchScopesCore.DirectoryScope)selectedScope;
|
||||
final VirtualFile directory = directoryScope.getDirectory();
|
||||
myDirectoryComboBox.setDirectory(directory);
|
||||
myDirectoryComboBox.setRecursive(directoryScope.isWithSubdirectories());
|
||||
}
|
||||
else if (selectedScope != null) {
|
||||
myScopesComboBox.init(myProject, true, false, selectedScope.getDisplayName());
|
||||
}
|
||||
myToolbar.updateActionsImmediately();
|
||||
((JBCardLayout)myScopeDetailsPanel.getLayout()).show(myScopeDetailsPanel, myScopeType.toString());
|
||||
}
|
||||
|
||||
public void setScopeCallback(Consumer<SearchScope> callback) {
|
||||
myCallback = callback;
|
||||
}
|
||||
|
||||
public SearchScope getSelectedScope() {
|
||||
return mySelectedScope;
|
||||
public SearchScope getScope() {
|
||||
return myScope;
|
||||
}
|
||||
|
||||
private void setScopeFromUI(Scopes.Type type) {
|
||||
switch (type) {
|
||||
case PROJECT:
|
||||
myScope = GlobalSearchScope.projectScope(myProject);
|
||||
break;
|
||||
case MODULE:
|
||||
final Module module = myModulesComboBox.getSelectedModule();
|
||||
if (module == null) return;
|
||||
myScope = GlobalSearchScope.moduleScope(module);
|
||||
break;
|
||||
case DIRECTORY:
|
||||
final VirtualFile directory = myDirectoryComboBox.getDirectory();
|
||||
if (directory == null) return;
|
||||
myScope = GlobalSearchScopesCore.directoryScope(myProject, directory, myDirectoryComboBox.isRecursive());
|
||||
break;
|
||||
case NAMED:
|
||||
myScope = myScopesComboBox.getSelectedScope();
|
||||
break;
|
||||
}
|
||||
if (myCallback != null) myCallback.accept(myScope);
|
||||
}
|
||||
|
||||
class ScopeToggleAction extends ToggleAction {
|
||||
|
||||
private final ScopeType myScopeType;
|
||||
private final Scopes.Type myScopeType;
|
||||
|
||||
public ScopeToggleAction(@Nullable String text, ScopeType scopeType) {
|
||||
public ScopeToggleAction(@Nullable String text, Scopes.Type scopeType) {
|
||||
super(text, null, EmptyIcon.ICON_0);
|
||||
myScopeType = scopeType;
|
||||
getTemplatePresentation().setDisabledIcon(EmptyIcon.ICON_0);
|
||||
@@ -119,35 +166,17 @@ class ScopePanel extends JPanel {
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return myScopeType == ScopeType.fromScope(mySelectedScope);
|
||||
return myScopeType == ScopePanel.this.myScopeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
if (state) {
|
||||
switch (myScopeType) {
|
||||
case PROJECT:
|
||||
mySelectedScope = GlobalSearchScope.projectScope(myProject);
|
||||
break;
|
||||
case MODULE:
|
||||
final Module module = myModulesComboBox.getSelectedModule();
|
||||
if (module != null) {
|
||||
mySelectedScope = GlobalSearchScope.moduleScope(module);
|
||||
}
|
||||
break;
|
||||
case DIRECTORY:
|
||||
final VirtualFile directory = myDirectoryComboBox.getDirectory();
|
||||
if (directory != null) {
|
||||
mySelectedScope = GlobalSearchScopesCore.directoryScope(myProject, directory, myDirectoryComboBox.isRecursive());
|
||||
}
|
||||
break;
|
||||
case SCOPE:
|
||||
mySelectedScope = myScopeChooserComboBox.getSelectedScope();
|
||||
break;
|
||||
}
|
||||
((JBCardLayout)myScopeDetailsPanel.getLayout()).swipe(myScopeDetailsPanel, myScopeType.toString(),
|
||||
ScopePanel.this.myScopeType.compareTo(myScopeType) > 0 ? JBCardLayout.SwipeDirection.FORWARD : JBCardLayout.SwipeDirection.BACKWARD);
|
||||
ScopePanel.this.myScopeType = myScopeType;
|
||||
setScopeFromUI(myScopeType);
|
||||
myToolbar.updateActionsImmediately();
|
||||
((CardLayout)myScopeDetailsPanel.getLayout()).show(myScopeDetailsPanel, myScopeType.toString());
|
||||
if (myCallback != null) myCallback.accept(mySelectedScope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,26 +185,4 @@ class ScopePanel extends JPanel {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
enum ScopeType {
|
||||
PROJECT,
|
||||
MODULE,
|
||||
DIRECTORY,
|
||||
SCOPE;
|
||||
|
||||
static ScopeType fromScope(SearchScope scope) {
|
||||
if (scope instanceof ProjectScopeImpl || scope == null) {
|
||||
return PROJECT;
|
||||
}
|
||||
else if (scope instanceof ModuleWithDependenciesScope) {
|
||||
return MODULE;
|
||||
}
|
||||
else if (scope instanceof GlobalSearchScopesCore.DirectoryScope) {
|
||||
return DIRECTORY;
|
||||
}
|
||||
else {
|
||||
return SCOPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+190
-140
@@ -4,6 +4,7 @@ package com.intellij.structuralsearch.plugin.ui;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInsight.template.impl.TemplateEditorUtil;
|
||||
import com.intellij.find.FindBundle;
|
||||
import com.intellij.find.FindInProjectSettings;
|
||||
import com.intellij.find.FindSettings;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
@@ -27,18 +28,28 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.project.ProjectManagerListener;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.GlobalSearchScopesCore;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.structuralsearch.*;
|
||||
import com.intellij.structuralsearch.impl.matcher.CompiledPattern;
|
||||
import com.intellij.structuralsearch.impl.matcher.compiler.PatternCompiler;
|
||||
import com.intellij.structuralsearch.plugin.StructuralSearchPlugin;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.OnePixelSplitter;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.SmartList;
|
||||
@@ -50,11 +61,13 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -62,37 +75,34 @@ import java.util.List;
|
||||
*/
|
||||
public class StructuralSearchDialog extends DialogWrapper {
|
||||
static final Key<Boolean> STRUCTURAL_SEARCH = Key.create("STRUCTURAL_SEARCH_AREA");
|
||||
protected SearchContext searchContext;
|
||||
|
||||
// text for search
|
||||
protected EditorTextField searchCriteriaEdit;
|
||||
|
||||
private JCheckBox recursiveMatching;
|
||||
private JCheckBox caseSensitiveMatch;
|
||||
|
||||
private FileTypeSelector fileTypes;
|
||||
|
||||
protected Configuration myConfiguration;
|
||||
private JCheckBox openInNewTab;
|
||||
private final Alarm myAlarm;
|
||||
|
||||
public static final String USER_DEFINED = SSRBundle.message("new.template.defaultname");
|
||||
private boolean useLastConfiguration;
|
||||
|
||||
@NonNls private FileType ourFtSearchVariant = StructuralSearchUtil.getDefaultFileType();
|
||||
private static Language ourDialect = null;
|
||||
private static String ourContext = null;
|
||||
// search info
|
||||
protected SearchContext mySearchContext;
|
||||
protected Configuration myConfiguration;
|
||||
@NonNls private FileType myFileType = StructuralSearchUtil.getDefaultFileType();
|
||||
private Language myDialect = null;
|
||||
private String myContext = null;
|
||||
|
||||
// ui management
|
||||
private final Alarm myAlarm;
|
||||
private boolean myUseLastConfiguration;
|
||||
private final boolean myShowScopePanel;
|
||||
private final boolean myRunFindActionOnClose;
|
||||
private boolean myDoingOkAction;
|
||||
|
||||
private String mySavedEditorText;
|
||||
private JPanel myEditorPanel;
|
||||
private boolean myFilterButtonEnabled = false;
|
||||
private FilterPanel myFilterPanel;
|
||||
|
||||
// components
|
||||
private JCheckBox myRecursiveMatching;
|
||||
private JCheckBox myCaseSensitiveMatch;
|
||||
private FileTypeSelector myFileTypesComboBox;
|
||||
protected EditorTextField mySearchCriteriaEdit;
|
||||
private OnePixelSplitter myEditorPanel;
|
||||
private FilterPanel myFilterPanel;
|
||||
private LinkComboBox myTargetComboBox;
|
||||
private ScopePanel myScopePanel;
|
||||
private JCheckBox myOpenInNewTab;
|
||||
|
||||
public StructuralSearchDialog(SearchContext searchContext) {
|
||||
this(searchContext, true, true);
|
||||
@@ -104,7 +114,7 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
if (showScope) setModal(false);
|
||||
myShowScopePanel = showScope;
|
||||
myRunFindActionOnClose = runFindActionOnClose;
|
||||
this.searchContext = searchContext;
|
||||
this.mySearchContext = searchContext;
|
||||
setTitle(getDefaultTitle());
|
||||
|
||||
if (runFindActionOnClose) {
|
||||
@@ -124,7 +134,7 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
public void setUseLastConfiguration(boolean useLastConfiguration) {
|
||||
this.useLastConfiguration = useLastConfiguration;
|
||||
this.myUseLastConfiguration = useLastConfiguration;
|
||||
}
|
||||
|
||||
void setSearchPattern(final Configuration config) {
|
||||
@@ -133,14 +143,9 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
protected EditorTextField createEditor(final SearchContext searchContext, String text) {
|
||||
final FileTypeInfo info = fileTypes.getSelectedItem();
|
||||
assert info != null;
|
||||
final FileType fileType = info.getFileType();
|
||||
final Language dialect = info.getDialect();
|
||||
|
||||
final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(fileType);
|
||||
final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(myFileType);
|
||||
assert profile != null;
|
||||
final Document document = profile.createDocument(searchContext.getProject(), fileType, dialect, text);
|
||||
final Document document = profile.createDocument(searchContext.getProject(), myFileType, myDialect, text);
|
||||
document.addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void documentChanged(final DocumentEvent event) {
|
||||
@@ -148,7 +153,7 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
}
|
||||
});
|
||||
|
||||
final EditorTextField textField = new EditorTextField(document, searchContext.getProject(), fileType) {
|
||||
final EditorTextField textField = new EditorTextField(document, searchContext.getProject(), myFileType) {
|
||||
@Override
|
||||
protected EditorEx createEditor() {
|
||||
EditorEx editorEx = super.createEditor();
|
||||
@@ -158,6 +163,7 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
}
|
||||
};
|
||||
textField.setPreferredSize(new Dimension(850, 150));
|
||||
textField.setMinimumSize(new Dimension(200, 50));
|
||||
return textField;
|
||||
}
|
||||
|
||||
@@ -200,7 +206,9 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
|
||||
private boolean isCompiled() {
|
||||
try {
|
||||
return PatternCompiler.compilePattern(getProject(), myConfiguration.getMatchOptions(), false) != null;
|
||||
final CompiledPattern compiledPattern = PatternCompiler.compilePattern(getProject(), myConfiguration.getMatchOptions(), false);
|
||||
myFilterPanel.setCompiledPattern(compiledPattern);
|
||||
return compiledPattern != null;
|
||||
} catch (MalformedPatternException e) {
|
||||
return false;
|
||||
}
|
||||
@@ -208,45 +216,44 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
|
||||
void updateEditor() {
|
||||
if (myEditorPanel != null) {
|
||||
if (searchCriteriaEdit != null) {
|
||||
mySavedEditorText = searchCriteriaEdit.getText();
|
||||
myEditorPanel.remove(searchCriteriaEdit);
|
||||
if (mySearchCriteriaEdit != null) {
|
||||
mySavedEditorText = mySearchCriteriaEdit.getText();
|
||||
myEditorPanel.remove(mySearchCriteriaEdit);
|
||||
}
|
||||
searchCriteriaEdit = createEditor(searchContext, mySavedEditorText != null ? mySavedEditorText : "");
|
||||
myEditorPanel.add(searchCriteriaEdit, BorderLayout.CENTER);
|
||||
mySearchCriteriaEdit = createEditor(mySearchContext, mySavedEditorText != null ? mySavedEditorText : "");
|
||||
myEditorPanel.setFirstComponent(mySearchCriteriaEdit);
|
||||
myEditorPanel.revalidate();
|
||||
final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(ourFtSearchVariant);
|
||||
final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(myFileType);
|
||||
assert profile != null;
|
||||
|
||||
searchCriteriaEdit.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
mySearchCriteriaEdit.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
final Editor editor = searchCriteriaEdit.getEditor();
|
||||
final Editor editor = mySearchCriteriaEdit.getEditor();
|
||||
if (editor == null) return;
|
||||
TemplateEditorUtil.setHighlighter(editor, profile.getTemplateContextType());
|
||||
SubstitutionShortInfoHandler.install(editor, variableName ->
|
||||
myFilterPanel.setFilters(myConfiguration.getMatchOptions().getVariableConstraint(variableName)));
|
||||
myFilterPanel.setFilters(UIUtil.getOrAddVariableConstraint(Configuration.CONTEXT_VAR_NAME, myConfiguration));
|
||||
//myFilterPanel.setFilters(UIUtil.getOrAddVariableConstraint(Configuration.CONTEXT_VAR_NAME, myConfiguration));
|
||||
editor.putUserData(SubstitutionShortInfoHandler.CURRENT_CONFIGURATION_KEY, myConfiguration);
|
||||
final Project project = searchContext.getProject();
|
||||
final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(searchCriteriaEdit.getDocument());
|
||||
final Project project = mySearchContext.getProject();
|
||||
final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(mySearchCriteriaEdit.getDocument());
|
||||
if (file != null) {
|
||||
DaemonCodeAnalyzer.getInstance(project).setHighlightingEnabled(file, false);
|
||||
}
|
||||
searchCriteriaEdit.removePropertyChangeListener(this);
|
||||
mySearchCriteriaEdit.removePropertyChangeListener(this);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void detectFileTypeAndDialect() {
|
||||
final PsiFile file = searchContext.getFile();
|
||||
final PsiFile file = mySearchContext.getFile();
|
||||
if (file != null) {
|
||||
PsiElement context = null;
|
||||
|
||||
if (searchContext.getEditor() != null) {
|
||||
context = file.findElementAt(searchContext.getEditor().getCaretModel().getOffset());
|
||||
if (mySearchContext.getEditor() != null) {
|
||||
context = file.findElementAt(mySearchContext.getEditor().getCaretModel().getOffset());
|
||||
if (context != null) {
|
||||
context = context.getParent();
|
||||
}
|
||||
@@ -274,9 +281,7 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
ourFtSearchVariant = detectedFileType != null ?
|
||||
detectedFileType :
|
||||
StructuralSearchUtil.getDefaultFileType();
|
||||
myFileType = (detectedFileType != null) ? detectedFileType : StructuralSearchUtil.getDefaultFileType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,19 +303,20 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
break;
|
||||
}
|
||||
}
|
||||
myScopePanel.setScope(matchOptions.getScope());
|
||||
myScopePanel.setRecentDirectories(FindInProjectSettings.getInstance(getProject()).getRecentDirectories());
|
||||
|
||||
final Document document = searchCriteriaEdit.getDocument();
|
||||
CommandProcessor.getInstance().executeCommand(searchContext.getProject(), () -> {
|
||||
final Document document = mySearchCriteriaEdit.getDocument();
|
||||
CommandProcessor.getInstance().executeCommand(mySearchContext.getProject(), () -> {
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
document.replaceString(0, document.getTextLength(), matchOptions.getSearchPattern());
|
||||
});
|
||||
}, null, null);
|
||||
|
||||
recursiveMatching.setSelected(isRecursiveSearchEnabled() && matchOptions.isRecursiveSearch());
|
||||
caseSensitiveMatch.setSelected(matchOptions.isCaseSensitiveMatch());
|
||||
|
||||
fileTypes.setSelectedItem(matchOptions.getFileType(), matchOptions.getDialect(), matchOptions.getPatternContext());
|
||||
final Editor editor = searchCriteriaEdit.getEditor();
|
||||
myRecursiveMatching.setSelected(isRecursiveSearchEnabled() && matchOptions.isRecursiveSearch());
|
||||
myCaseSensitiveMatch.setSelected(matchOptions.isCaseSensitiveMatch());
|
||||
myFileTypesComboBox.setSelectedItem(matchOptions.getFileType(), matchOptions.getDialect(), matchOptions.getPatternContext());
|
||||
final Editor editor = mySearchCriteriaEdit.getEditor();
|
||||
if (editor != null) {
|
||||
editor.putUserData(SubstitutionShortInfoHandler.CURRENT_CONFIGURATION_KEY, myConfiguration);
|
||||
}
|
||||
@@ -321,13 +327,13 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
protected void setText(String text) {
|
||||
setTextForEditor(text, searchCriteriaEdit);
|
||||
setTextForEditor(text, mySearchCriteriaEdit);
|
||||
}
|
||||
|
||||
protected final void setTextForEditor(final String selection, EditorTextField editor) {
|
||||
editor.setText(selection);
|
||||
editor.selectAll();
|
||||
final Project project = searchContext.getProject();
|
||||
final Project project = mySearchContext.getProject();
|
||||
final Document document = editor.getDocument();
|
||||
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
|
||||
documentManager.commitDocument(document);
|
||||
@@ -340,7 +346,7 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
protected void startSearching() {
|
||||
new SearchCommand(myConfiguration, searchContext).startSearching();
|
||||
new SearchCommand(myConfiguration, mySearchContext).startSearching();
|
||||
}
|
||||
|
||||
protected String getDefaultTitle() {
|
||||
@@ -349,15 +355,46 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
myEditorPanel = new JPanel(new BorderLayout());
|
||||
searchCriteriaEdit = createEditor(searchContext, mySavedEditorText != null ? mySavedEditorText : "");
|
||||
myEditorPanel.add(BorderLayout.CENTER, searchCriteriaEdit);
|
||||
myEditorPanel = new OnePixelSplitter(false, 1.0f) {
|
||||
/*final Timer myTimer = com.intellij.util.ui.UIUtil.createNamedTimer("SlidingSplitter", 17);
|
||||
|
||||
myScopePanel = new ScopePanel(getProject(), myConfiguration.getMatchOptions().getScope());
|
||||
myScopePanel.setEnabled(myShowScopePanel); // todo initiateValidation() on change
|
||||
@Override
|
||||
public void setSecondComponent(@Nullable JComponent component) {
|
||||
if (component != null) {
|
||||
final Dimension size = component.getMinimumSize();
|
||||
component.setMinimumSize(new Dimension(0, size.height));
|
||||
final ActionListener listener = e -> {
|
||||
final int width = component.getMinimumSize().width;
|
||||
if (width < size.width) {
|
||||
component.setMinimumSize(new Dimension(width + 1, size.height));
|
||||
myEditorPanel.revalidate();
|
||||
}
|
||||
else {
|
||||
myTimer.stop();
|
||||
}
|
||||
};
|
||||
for (ActionListener actionListener: myTimer.getActionListeners()) {
|
||||
myTimer.removeActionListener(actionListener);
|
||||
}
|
||||
myTimer.addActionListener(listener);
|
||||
myTimer.start();
|
||||
super.setSecondComponent(component);
|
||||
}
|
||||
super.setSecondComponent(component);
|
||||
}*/
|
||||
};
|
||||
myEditorPanel.setLackOfSpaceStrategy(Splitter.LackOfSpaceStrategy.HONOR_THE_SECOND_MIN_SIZE);
|
||||
myEditorPanel.getDivider().setOpaque(false);
|
||||
mySearchCriteriaEdit = createEditor(mySearchContext, mySavedEditorText != null ? mySavedEditorText : "");
|
||||
myEditorPanel.add(BorderLayout.CENTER, mySearchCriteriaEdit);
|
||||
|
||||
myFilterPanel = new FilterPanel(getProject(), getDisposable());
|
||||
myFilterPanel.getComponent().setMinimumSize(new Dimension(400, searchCriteriaEdit.getMinimumSize().height));
|
||||
myScopePanel = new ScopePanel(getProject());
|
||||
myScopePanel.setEnabled(myShowScopePanel);
|
||||
myScopePanel.setScopeCallback(s -> initiateValidation());
|
||||
|
||||
myFilterPanel =
|
||||
new FilterPanel(getProject(), StructuralSearchUtil.getProfileByFileType(myFileType), getDisposable());
|
||||
myFilterPanel.getComponent().setMinimumSize(new Dimension(300, 50));
|
||||
|
||||
final JLabel searchTargetLabel = new JLabel(SSRBundle.message("search.target.label"));
|
||||
myTargetComboBox = new LinkComboBox(SSRBundle.message("complete.match.variable.name"));
|
||||
@@ -369,23 +406,25 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
layout.createParallelGroup()
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(myEditorPanel)
|
||||
.addComponent(myFilterPanel.getComponent()))
|
||||
)
|
||||
.addComponent(myScopePanel)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(searchTargetLabel)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 5, 5)
|
||||
.addComponent(myTargetComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(myTargetComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup()
|
||||
.addComponent(myEditorPanel)
|
||||
.addComponent(myFilterPanel.getComponent()))
|
||||
)
|
||||
.addComponent(myScopePanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 2, 2)
|
||||
.addGroup(layout.createParallelGroup()
|
||||
.addComponent(searchTargetLabel)
|
||||
.addComponent(myTargetComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(myTargetComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
)
|
||||
);
|
||||
|
||||
updateEditor();
|
||||
@@ -398,7 +437,7 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
final DefaultActionGroup historyActionGroup = new DefaultActionGroup(new AnAction(getShowHistoryIcon()) {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final SelectTemplateDialog dialog = new SelectTemplateDialog(searchContext.getProject(), true, isReplaceDialog());
|
||||
final SelectTemplateDialog dialog = new SelectTemplateDialog(mySearchContext.getProject(), true, isReplaceDialog());
|
||||
if (!dialog.showAndGet()) {
|
||||
return;
|
||||
}
|
||||
@@ -415,9 +454,9 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
final JLabel label = new JLabel(SSRBundle.message("search.template"));
|
||||
UIUtil.installCompleteMatchInfo(label, () -> myConfiguration);
|
||||
|
||||
recursiveMatching = new JCheckBox(SSRBundle.message("recursive.matching.checkbox"), true);
|
||||
recursiveMatching.setVisible(isRecursiveSearchEnabled());
|
||||
caseSensitiveMatch = new JCheckBox(FindBundle.message("find.popup.case.sensitive"), true);
|
||||
myRecursiveMatching = new JCheckBox(SSRBundle.message("recursive.matching.checkbox"), true);
|
||||
myRecursiveMatching.setVisible(isRecursiveSearchEnabled());
|
||||
myCaseSensitiveMatch = new JCheckBox(FindBundle.message("find.popup.case.sensitive"), true);
|
||||
final List<FileType> types = new ArrayList<>();
|
||||
for (FileType fileType : StructuralSearchUtil.getSuitableFileTypes()) {
|
||||
if (StructuralSearchUtil.getProfileByFileType(fileType) != null) {
|
||||
@@ -425,20 +464,27 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
Collections.sort(types, (o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName()));
|
||||
fileTypes = new FileTypeSelector(types);
|
||||
fileTypes.setMinimumAndPreferredWidth(200);
|
||||
fileTypes.setSelectedItem(ourFtSearchVariant, ourDialect, ourContext);
|
||||
fileTypes.addItemListener(new ItemListener() {
|
||||
myFileTypesComboBox = new FileTypeSelector(types);
|
||||
myFileTypesComboBox.setMinimumAndPreferredWidth(200);
|
||||
myFileTypesComboBox.setSelectedItem(myFileType, myDialect, myContext);
|
||||
myFileTypesComboBox.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
final FileTypeInfo item = myFileTypesComboBox.getSelectedItem();
|
||||
if (item == null) return;
|
||||
myFileType = item.getFileType();
|
||||
myDialect = item.getDialect();
|
||||
myContext = item.getContext();
|
||||
updateEditor();
|
||||
final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(myFileType);
|
||||
myFilterPanel.setProfile(profile);
|
||||
initiateValidation();
|
||||
}
|
||||
}
|
||||
});
|
||||
final JLabel fileTypeLabel = new JLabel(SSRBundle.message("search.dialog.file.type.label"));
|
||||
fileTypeLabel.setLabelFor(fileTypes);
|
||||
fileTypeLabel.setLabelFor(myFileTypesComboBox);
|
||||
final DefaultActionGroup templateActionGroup = new DefaultActionGroup(
|
||||
new AnAction(SSRBundle.message("save.template.text.button")) {
|
||||
|
||||
@@ -450,11 +496,12 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
new AnAction(SSRBundle.message("copy.existing.template.button")) {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
SelectTemplateDialog dialog = new SelectTemplateDialog(searchContext.getProject(), false, isReplaceDialog());
|
||||
System.out.println("StructuralSearchDialog.actionPerformed(" + e + ")");
|
||||
final SelectTemplateDialog dialog = new SelectTemplateDialog(mySearchContext.getProject(), false, isReplaceDialog());
|
||||
if (!dialog.showAndGet()) {
|
||||
return;
|
||||
}
|
||||
Configuration[] configurations = dialog.getSelectedConfigurations();
|
||||
final Configuration[] configurations = dialog.getSelectedConfigurations();
|
||||
if (configurations.length == 1) {
|
||||
setSearchPattern(configurations[0]);
|
||||
}
|
||||
@@ -468,15 +515,12 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return myFilterPanel.getComponent().isVisible();
|
||||
return myEditorPanel.getSecondComponent() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
if (state) {
|
||||
myFilterPanel.getComponent().setMinimumSize(new Dimension(400, searchCriteriaEdit.getMinimumSize().height));
|
||||
}
|
||||
myFilterPanel.getComponent().setVisible(state);
|
||||
myEditorPanel.setSecondComponent(state ? myFilterPanel.getComponent() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -485,7 +529,7 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
}
|
||||
};
|
||||
final DefaultActionGroup optionsActionGroup = new DefaultActionGroup(filterAction, templateActionGroup);
|
||||
ActionToolbarImpl optionsToolbar =
|
||||
final ActionToolbarImpl optionsToolbar =
|
||||
(ActionToolbarImpl)ActionManager.getInstance().createActionToolbar(ActionPlaces.EDITOR_TOOLBAR, optionsActionGroup, true);
|
||||
optionsToolbar.setLayoutPolicy(ActionToolbar.NOWRAP_LAYOUT_POLICY);
|
||||
optionsToolbar.setForceMinimumSize(true);
|
||||
@@ -499,23 +543,23 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
.addComponent(historyToolbar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(label)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 20, Integer.MAX_VALUE)
|
||||
.addComponent(recursiveMatching)
|
||||
.addComponent(myRecursiveMatching)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 15, 15)
|
||||
.addComponent(caseSensitiveMatch)
|
||||
.addComponent(myCaseSensitiveMatch)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 15, 15)
|
||||
.addComponent(fileTypeLabel)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 5, 5)
|
||||
.addComponent(fileTypes, 125, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(myFileTypesComboBox, 125, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(optionsToolbar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(historyToolbar)
|
||||
.addComponent(label)
|
||||
.addComponent(recursiveMatching)
|
||||
.addComponent(caseSensitiveMatch)
|
||||
.addComponent(myRecursiveMatching)
|
||||
.addComponent(myCaseSensitiveMatch)
|
||||
.addComponent(fileTypeLabel)
|
||||
.addComponent(fileTypes)
|
||||
.addComponent(myFileTypesComboBox)
|
||||
.addComponent(optionsToolbar)
|
||||
);
|
||||
|
||||
@@ -529,9 +573,9 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
if (!myRunFindActionOnClose) return null;
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(BorderFactory.createEmptyBorder(0, 6, 0, 0));
|
||||
openInNewTab = new JCheckBox(SSRBundle.message("open.in.new.tab.checkbox"));
|
||||
openInNewTab.setSelected(FindSettings.getInstance().isShowResultsInSeparateView());
|
||||
panel.add(openInNewTab, BorderLayout.EAST);
|
||||
myOpenInNewTab = new JCheckBox(SSRBundle.message("open.in.new.tab.checkbox"));
|
||||
myOpenInNewTab.setSelected(FindSettings.getInstance().isShowResultsInSeparateView());
|
||||
panel.add(myOpenInNewTab, BorderLayout.EAST);
|
||||
return panel;
|
||||
}
|
||||
|
||||
@@ -541,7 +585,7 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
|
||||
@NotNull
|
||||
private List<String> getSearchVariables() {
|
||||
final Editor editor = searchCriteriaEdit.getEditor();
|
||||
final Editor editor = mySearchCriteriaEdit.getEditor();
|
||||
if (editor == null) {
|
||||
return new SmartList<>();
|
||||
}
|
||||
@@ -554,7 +598,7 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
public final Project getProject() {
|
||||
return searchContext.getProject();
|
||||
return mySearchContext.getProject();
|
||||
}
|
||||
|
||||
protected boolean isReplaceDialog() {
|
||||
@@ -565,8 +609,8 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
public void show() {
|
||||
StructuralSearchPlugin.getInstance(getProject()).setDialogVisible(true);
|
||||
|
||||
if (!useLastConfiguration) {
|
||||
final Editor editor = searchContext.getEditor();
|
||||
if (!myUseLastConfiguration) {
|
||||
final Editor editor = mySearchContext.getEditor();
|
||||
boolean setSomeText = false;
|
||||
|
||||
if (editor != null) {
|
||||
@@ -593,7 +637,7 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return searchCriteriaEdit;
|
||||
return mySearchCriteriaEdit;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -604,24 +648,29 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
if (!result) return;
|
||||
|
||||
myAlarm.cancelAllRequests();
|
||||
removeUnusedVariableConstraints(myConfiguration);
|
||||
super.doOKAction();
|
||||
if (!myRunFindActionOnClose) return;
|
||||
|
||||
final SearchScope selectedScope = myScopePanel.getSelectedScope();
|
||||
if (selectedScope == null) return;
|
||||
final SearchScope scope = myScopePanel.getScope();
|
||||
if (scope == null) return;
|
||||
|
||||
if (scope instanceof GlobalSearchScopesCore.DirectoryScope) {
|
||||
final GlobalSearchScopesCore.DirectoryScope directoryScope = (GlobalSearchScopesCore.DirectoryScope)scope;
|
||||
FindInProjectSettings.getInstance(getProject()).addDirectory(directoryScope.getDirectory().getPresentableUrl());
|
||||
}
|
||||
|
||||
final FindSettings findSettings = FindSettings.getInstance();
|
||||
findSettings.setDefaultScopeName(selectedScope.getDisplayName());
|
||||
findSettings.setShowResultsInSeparateView(openInNewTab.isSelected());
|
||||
findSettings.setDefaultScopeName(scope.getDisplayName());
|
||||
findSettings.setShowResultsInSeparateView(myOpenInNewTab.isSelected());
|
||||
|
||||
try {
|
||||
removeUnusedVariableConstraints(myConfiguration);
|
||||
ConfigurationManager.getInstance(getProject()).addHistoryConfiguration(myConfiguration);
|
||||
|
||||
startSearching();
|
||||
}
|
||||
catch (MalformedPatternException ex) {
|
||||
reportMessage(SSRBundle.message("this.pattern.is.malformed.message", ex.getMessage()), searchCriteriaEdit);
|
||||
reportMessage(SSRBundle.message("this.pattern.is.malformed.message", ex.getMessage()), mySearchCriteriaEdit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,34 +688,42 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
|
||||
protected boolean isValid() {
|
||||
try {
|
||||
Matcher.validate(searchContext.getProject(), getConfiguration().getMatchOptions());
|
||||
Matcher.validate(mySearchContext.getProject(), getConfiguration().getMatchOptions());
|
||||
}
|
||||
catch (MalformedPatternException ex) {
|
||||
reportMessage(SSRBundle.message("this.pattern.is.malformed.message",
|
||||
(ex.getMessage() != null) ? ex.getMessage() : ""), searchCriteriaEdit);
|
||||
(ex.getMessage() != null) ? ex.getMessage() : ""), mySearchCriteriaEdit);
|
||||
return false;
|
||||
}
|
||||
catch (UnsupportedPatternException ex) {
|
||||
reportMessage(SSRBundle.message("this.pattern.is.unsupported.message", ex.getMessage()), searchCriteriaEdit);
|
||||
reportMessage(SSRBundle.message("this.pattern.is.unsupported.message", ex.getMessage()), mySearchCriteriaEdit);
|
||||
return false;
|
||||
}
|
||||
catch (NoMatchFoundException e) {
|
||||
reportMessage(e.getMessage(), searchCriteriaEdit);
|
||||
reportMessage(e.getMessage(), mySearchCriteriaEdit);
|
||||
return false;
|
||||
}
|
||||
reportMessage(null, searchCriteriaEdit);
|
||||
reportMessage(null, mySearchCriteriaEdit);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void reportMessage(String message, EditorTextField editor) {
|
||||
com.intellij.util.ui.UIUtil.invokeLaterIfNeeded(() -> {
|
||||
editor.putClientProperty("JComponent.outline", message == null ? null : "error");
|
||||
editor.setToolTipText(message);
|
||||
editor.repaint();
|
||||
//status.setText(message);
|
||||
//status.setToolTipText(message);
|
||||
//status.revalidate();
|
||||
//statusText.setLabelFor(editor != null ? editor.getContentComponent() : null);
|
||||
protected void reportMessage(String message, JComponent component) {
|
||||
com.intellij.util.ui.UIUtil.invokeLaterIfNeeded(() -> {
|
||||
component.putClientProperty("JComponent.outline", message == null ? null : "error");
|
||||
component.repaint();
|
||||
|
||||
if (message == null) return;
|
||||
final Balloon balloon = JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(message, MessageType.ERROR, null).createBalloon();
|
||||
if (component == mySearchCriteriaEdit) {
|
||||
balloon.show(new RelativePoint(component, new Point(component.getWidth() / 2, component.getHeight())), Balloon.Position.below);
|
||||
}
|
||||
else {
|
||||
balloon.show(new RelativePoint(component, new Point(component.getWidth() / 2, 0)), Balloon.Position.above);
|
||||
}
|
||||
//balloon.show(new RelativePoint(component, new Point(component.getWidth() / 2, 0)), Balloon.Position.above);
|
||||
balloon.showInCenterOf(component);
|
||||
Disposer.register(myDisposable, balloon);
|
||||
IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(component, true));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -674,26 +731,19 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
MatchOptions options = config.getMatchOptions();
|
||||
|
||||
if (myShowScopePanel) {
|
||||
final SearchScope scope = myScopePanel.getSelectedScope();
|
||||
final SearchScope scope = myScopePanel.getScope();
|
||||
if (scope != null) {
|
||||
boolean searchWithinHierarchy = IdeBundle.message("scope.class.hierarchy").equals(scope.getDisplayName());
|
||||
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
|
||||
options.setScope(searchWithinHierarchy && !myDoingOkAction ? GlobalSearchScope.projectScope(getProject()) : scope);
|
||||
}
|
||||
}
|
||||
options.setRecursiveSearch(isRecursiveSearchEnabled() && recursiveMatching.isSelected());
|
||||
|
||||
final FileTypeInfo info = fileTypes.getSelectedItem();
|
||||
ourFtSearchVariant = info != null ? info.getFileType() : null;
|
||||
ourDialect = info != null ? info.getDialect() : null;
|
||||
ourContext = info != null ? info.getContext() : null;
|
||||
FileType fileType = ourFtSearchVariant;
|
||||
options.setFileType(fileType);
|
||||
options.setDialect(ourDialect);
|
||||
options.setPatternContext(ourContext);
|
||||
|
||||
options.setSearchPattern(searchCriteriaEdit.getDocument().getText());
|
||||
options.setCaseSensitiveMatch(caseSensitiveMatch.isSelected());
|
||||
options.setRecursiveSearch(isRecursiveSearchEnabled() && myRecursiveMatching.isSelected());
|
||||
options.setFileType(myFileType);
|
||||
options.setDialect(myDialect);
|
||||
options.setPatternContext(myContext);
|
||||
options.setSearchPattern(mySearchCriteriaEdit.getDocument().getText());
|
||||
options.setCaseSensitiveMatch(myCaseSensitiveMatch.isSelected());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -705,7 +755,7 @@ public class StructuralSearchDialog extends DialogWrapper {
|
||||
public void dispose() {
|
||||
StructuralSearchPlugin.getInstance(getProject()).setDialogVisible(false);
|
||||
myAlarm.cancelAllRequests();
|
||||
searchCriteriaEdit.removeNotify();
|
||||
mySearchCriteriaEdit.removeNotify();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +1,37 @@
|
||||
<?xml version='1.0'?>
|
||||
<!DOCTYPE xs:schema SYSTEM "XMLSchema.dtd" [
|
||||
<!ELEMENT p ANY>
|
||||
<!ELEMENT a ANY>
|
||||
<!ATTLIST a href CDATA #IMPLIED>
|
||||
<!ELEMENT hr ANY>
|
||||
<!ELEMENT h1 ANY>
|
||||
<!ELEMENT br ANY>
|
||||
]>
|
||||
<xs:schema targetNamespace="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns="http://www.w3.org/1999/xhtml">
|
||||
<xs:annotation>
|
||||
<xs:documentation xmlns="http://www.w3.org/1999/xhtml">
|
||||
<xs:documentation>
|
||||
<h1>XML Schema instance namespace</h1>
|
||||
<p>See <a href="http://www.w3.org/TR/xmlschema-1/">The XML Schema draft recommendation</a> for an introduction</p>
|
||||
<p>See <a href="http://www.w3.org/TR/xmlschema-1/">the XML Schema
|
||||
Recommendation</a> for an introduction</p>
|
||||
|
||||
|
||||
<hr />
|
||||
$Date: 2004/06/09 12:44:55 $<br />
|
||||
$Id: XMLSchema-instance.xsd,v 1.1 2004/06/09 12:44:55 max Exp $
|
||||
$Date: 2001/03/16 20:25:57 $<br />
|
||||
$Id: XMLSchema-instance.xsd,v 1.4 2001/03/16 20:25:57 ht Exp $
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:annotation>
|
||||
<xs:documentation><p>This schema should never be used as such:
|
||||
<a href="http://www.w3.org/TR/xmlschema-1/#no-xsi">the XML
|
||||
Schema Recommendation</a> forbids the declaration of
|
||||
attributes in this namespace</p>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:attribute name="type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>No definitions are provided here, as
|
||||
this schema is never used as such</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
|
||||
<xs:attribute name="nill"/>
|
||||
<xs:attribute name="nil"/>
|
||||
<xs:attribute name="type"/>
|
||||
<xs:attribute name="schemaLocation"/>
|
||||
<xs:attribute name="noNamespaceSchemaLocation"/>
|
||||
</xs:schema>
|
||||
|
||||
Reference in New Issue
Block a user