From b37838c8f7bcfc42a23c03b8bec287b8e37ad00f Mon Sep 17 00:00:00 2001 From: "Elena.Korotkova" Date: Sat, 26 Sep 2020 16:38:28 +0300 Subject: [PATCH] Extend SearchReplaceComponent for the explorer search in Rider REF #RIDER-47835 GitOrigin-RevId: 3422e2611b4906a55590121ae21532c93f9371a7 --- .../intellij/find/SearchReplaceComponent.java | 195 ++++++++++++------ .../messages/ApplicationBundle.properties | 1 + 2 files changed, 128 insertions(+), 68 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/SearchReplaceComponent.java b/platform/lang-impl/src/com/intellij/find/SearchReplaceComponent.java index 522e3d13b935..8c4087507655 100644 --- a/platform/lang-impl/src/com/intellij/find/SearchReplaceComponent.java +++ b/platform/lang-impl/src/com/intellij/find/SearchReplaceComponent.java @@ -45,10 +45,12 @@ import java.util.ArrayList; import java.util.EventListener; import java.util.List; +import static java.awt.FlowLayout.CENTER; import static java.awt.event.InputEvent.CTRL_DOWN_MASK; import static java.awt.event.InputEvent.META_DOWN_MASK; public final class SearchReplaceComponent extends EditorHeaderComponent implements DataProvider { + public static final int RIGHT_PANEL_WEST_OFFSET = 13; private final EventDispatcher myEventDispatcher = EventDispatcher.create(Listener.class); private final MyTextComponentWrapper mySearchFieldWrapper; @@ -57,9 +59,6 @@ public final class SearchReplaceComponent extends EditorHeaderComponent implemen private final MyTextComponentWrapper myReplaceFieldWrapper; private JTextComponent myReplaceTextComponent; - private final JPanel myLeftPanel; - private final JPanel myRightPanel; - private final DefaultActionGroup mySearchFieldActions; private final ActionToolbarImpl mySearchActionsToolbar; private final List myEmbeddedSearchActions = new ArrayList<>(); @@ -81,7 +80,11 @@ public final class SearchReplaceComponent extends EditorHeaderComponent implemen private final DataProvider myDataProviderDelegate; + private final boolean myMultilineEnabled; + private final boolean myUseSearchField; private boolean myMultilineMode; + private final boolean myAddSearchResultsToGlobalSearch; + @NotNull private @NlsContexts.Label String myStatusText = ""; @NotNull private Color myStatusColor = UIUtil.getLabelForeground(); private DefaultActionGroup myTouchbarActions; @@ -104,7 +107,10 @@ public final class SearchReplaceComponent extends EditorHeaderComponent implemen @Nullable Runnable closeAction, @Nullable DataProvider dataProvider, boolean showOnlySearchPanel, - boolean maximizeLeftPanelOnResize) { + boolean maximizeLeftPanelOnResize, + boolean multilineEnabled, + boolean addSearchResultsToGlobalSearch, + boolean useSearchField) { myProject = project; myTargetComponent = targetComponent; mySearchToolbarModifiedFlagGetter = searchToolbar1ModifiedFlagGetter; @@ -112,6 +118,10 @@ public final class SearchReplaceComponent extends EditorHeaderComponent implemen myReplaceFieldActions = replaceFieldActions; myReplaceAction = replaceAction; myCloseAction = closeAction; + myMultilineEnabled = multilineEnabled; + myAddSearchResultsToGlobalSearch = addSearchResultsToGlobalSearch; + myUseSearchField = useSearchField; + for (AnAction child : searchToolbar2Actions.getChildren(null)) { if (child instanceof Embeddable) { @@ -150,18 +160,18 @@ public final class SearchReplaceComponent extends EditorHeaderComponent implemen }; myReplaceFieldWrapper.setBorder(JBUI.Borders.emptyTop(1)); - myLeftPanel = new JPanel(new GridBagLayout()); - myLeftPanel.setBackground(JBColor.border()); + JPanel leftPanel = new JPanel(new GridBagLayout()); + leftPanel.setBackground(JBColor.border()); GridBagConstraints constraints = new GridBagConstraints(); constraints.gridx = 0; constraints.gridy = 0; constraints.fill = GridBagConstraints.BOTH; constraints.weightx = 1; constraints.weighty = 1; - myLeftPanel.add(mySearchFieldWrapper, constraints); + leftPanel.add(mySearchFieldWrapper, constraints); constraints.gridy++; - myLeftPanel.add(myReplaceFieldWrapper, constraints); - myLeftPanel.setBorder(JBUI.Borders.customLine(JBColor.border(), 0, 0, 0, 1)); + leftPanel.add(myReplaceFieldWrapper, constraints); + leftPanel.setBorder(JBUI.Borders.customLine(JBColor.border(), 0, 0, 0, 1)); searchToolbar1Actions.addAll(searchToolbar2Actions.getChildren(null)); replaceToolbar1Actions.addAll(replaceToolbar2Actions.getChildren(null)); @@ -178,44 +188,55 @@ public final class SearchReplaceComponent extends EditorHeaderComponent implemen myReplaceToolbarWrapper.add(replaceToolbarWrapper1, BorderLayout.WEST); myReplaceToolbarWrapper.setBorder(JBUI.Borders.emptyTop(3)); - JLabel closeLabel = new JLabel(null, AllIcons.Actions.Close, SwingConstants.RIGHT); - closeLabel.setBorder(JBUI.Borders.empty(2)); - closeLabel.addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(final MouseEvent e) { - close(); - } - }); - closeLabel.setToolTipText(FindBundle.message("tooltip.close.search.bar.escape")); - searchPair.add(new Wrapper(closeLabel), BorderLayout.EAST); - - myRightPanel = new NonOpaquePanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); - myRightPanel.add(searchPair); - myRightPanel.add(myReplaceToolbarWrapper); + if(closeAction != null) { + JLabel closeLabel = new JLabel(null, AllIcons.Actions.Close, SwingConstants.RIGHT); + closeLabel.setBorder(JBUI.Borders.empty(2)); + closeLabel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(final MouseEvent e) { + close(); + } + }); + closeLabel.setToolTipText(FindBundle.message("tooltip.close.search.bar.escape")); + searchPair.add(new Wrapper(closeLabel), BorderLayout.EAST); + } + JPanel rightPanel = new NonOpaquePanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); + rightPanel.add(searchPair); + rightPanel.add(myReplaceToolbarWrapper); if (showOnlySearchPanel) { - add(myLeftPanel, BorderLayout.CENTER); - } else { - OnePixelSplitter splitter = new OnePixelSplitter(false, .33F); - myRightPanel.setBorder(JBUI.Borders.emptyLeft(6)); - splitter.setFirstComponent(myLeftPanel); - splitter.setSecondComponent(myRightPanel); - splitter.setHonorComponentsMinimumSize(true); + add(leftPanel, BorderLayout.CENTER); + } else if(maximizeLeftPanelOnResize) { + OnePixelSplitter splitter = new OnePixelSplitter(false, 0.33F); + rightPanel.setLayout(new FlowLayout(CENTER, 0 , 0)); + rightPanel.setMinimumSize(new Dimension(mySearchActionsToolbar.getActions().size() + * ActionToolbar.DEFAULT_MINIMUM_BUTTON_SIZE.width + RIGHT_PANEL_WEST_OFFSET, 0)); + splitter.setDividerPositionStrategy(Splitter.DividerPositionStrategy.KEEP_SECOND_SIZE); splitter.setLackOfSpaceStrategy(Splitter.LackOfSpaceStrategy.HONOR_THE_SECOND_MIN_SIZE); - splitter.setHonorComponentsPreferredSize(true); - if(maximizeLeftPanelOnResize) { - splitter.setDividerPositionStrategy(Splitter.DividerPositionStrategy.KEEP_SECOND_SIZE); - splitter.setLackOfSpaceStrategy(Splitter.LackOfSpaceStrategy.SIMPLE_RATIO); - }else{ - splitter.setDividerPositionStrategy(Splitter.DividerPositionStrategy.KEEP_FIRST_SIZE); - } + rightPanel.setBorder(JBUI.Borders.emptyLeft(RIGHT_PANEL_WEST_OFFSET)); + splitter.setFirstComponent(leftPanel); + splitter.setSecondComponent(rightPanel); + splitter.setHonorComponentsMinimumSize(true); + splitter.setHonorComponentsPreferredSize(false); splitter.setAndLoadSplitterProportionKey("FindSplitterProportion"); splitter.setOpaque(false); splitter.getDivider().setOpaque(false); add(splitter, BorderLayout.CENTER); - } - - + }else{ + OnePixelSplitter splitter = new OnePixelSplitter(false, .33F); + splitter = new OnePixelSplitter(false); + rightPanel.setBorder(JBUI.Borders.emptyLeft(6)); + splitter.setFirstComponent(leftPanel); + splitter.setSecondComponent(rightPanel); + splitter.setHonorComponentsMinimumSize(true); + splitter.setLackOfSpaceStrategy(Splitter.LackOfSpaceStrategy.HONOR_THE_SECOND_MIN_SIZE); + splitter.setHonorComponentsPreferredSize(true); + splitter.setAndLoadSplitterProportionKey("FindSplitterProportion"); + splitter.setOpaque(false); + splitter.getDivider().setOpaque(false); + add(splitter, BorderLayout.CENTER); + splitter.setDividerPositionStrategy(Splitter.DividerPositionStrategy.KEEP_FIRST_SIZE); +} update("", "", false, false); // it's assigned after all action updates so that actions don't get access to uninitialized components @@ -440,7 +461,10 @@ public final class SearchReplaceComponent extends EditorHeaderComponent implemen mySearchActionsToolbar.updateActionsImmediately(); myReplaceActionsToolbar.updateActionsImmediately(); JComponent textComponent = mySearchFieldWrapper.getTargetComponent(); - if (textComponent instanceof SearchTextArea) ((SearchTextArea)textComponent).updateExtraActions(); + if (textComponent instanceof SearchTextArea) { + ((SearchTextArea) textComponent).updateExtraActions(); + ((SearchTextArea) textComponent).setMultilineEnabled(myMultilineEnabled); + } textComponent = myReplaceFieldWrapper.getTargetComponent(); if (textComponent instanceof SearchTextArea) ((SearchTextArea)textComponent).updateExtraActions(); } @@ -450,7 +474,9 @@ public final class SearchReplaceComponent extends EditorHeaderComponent implemen if (text.length() > 0) { FindInProjectSettings findInProjectSettings = FindInProjectSettings.getInstance(myProject); if (textField == mySearchTextComponent) { - findInProjectSettings.addStringToFind(text); + if(myAddSearchResultsToGlobalSearch) { + findInProjectSettings.addStringToFind(text); + } if (mySearchFieldWrapper.getTargetComponent() instanceof SearchTextField) { ((SearchTextField)mySearchFieldWrapper.getTargetComponent()).addCurrentTextToHistory(); } @@ -469,42 +495,52 @@ public final class SearchReplaceComponent extends EditorHeaderComponent implemen if (oldComponent != null) return false; final MyTextComponentWrapper wrapper = search ? mySearchFieldWrapper : myReplaceFieldWrapper; - final JBTextArea textComponent = new JBTextArea(); - textComponent.setRows(isMultiline() ? 2 : 1); - textComponent.setColumns(12); - if (search) { - textComponent.getAccessibleContext().setAccessibleName(FindBundle.message("find.search.accessible.name")); + @NotNull JTextComponent innerTextComponent; + @NotNull JComponent outerComponent; + + if(myUseSearchField) { + outerComponent = new SearchTextField(true, this.toString()); + innerTextComponent = ((SearchTextField) outerComponent).getTextEditor(); + innerTextComponent.setBorder(BorderFactory.createEmptyBorder()); + }else{ + innerTextComponent = new JBTextArea(); + ((JBTextArea)innerTextComponent).setRows(isMultiline() ? 2 : 1); + ((JBTextArea)innerTextComponent).setColumns(12); + outerComponent = new SearchTextArea(((JBTextArea)innerTextComponent), search); + if (search) { + myExtraSearchButtons.clear(); + myExtraSearchButtons.addAll(((SearchTextArea) outerComponent).setExtraActions(myEmbeddedSearchActions.toArray(AnAction.EMPTY_ARRAY))); + ((SearchTextArea) outerComponent).setMultilineEnabled(myMultilineEnabled); + } else { + myExtraReplaceButtons.clear(); + myExtraReplaceButtons.addAll(((SearchTextArea) outerComponent).setExtraActions(myEmbeddedReplaceActions.toArray(AnAction.EMPTY_ARRAY))); + } } - else { - textComponent.getAccessibleContext().setAccessibleName(FindBundle.message("find.replace.accessible.name")); - } - SearchTextArea textArea = new SearchTextArea(textComponent, search); + + UIUtil.addUndoRedoActions(innerTextComponent); + wrapper.setContent(outerComponent); + if (search) { - myExtraSearchButtons.clear(); - myExtraSearchButtons.addAll(textArea.setExtraActions(myEmbeddedSearchActions.toArray(AnAction.EMPTY_ARRAY))); + innerTextComponent.getAccessibleContext().setAccessibleName(FindBundle.message("find.search.accessible.name")); } else { - myExtraReplaceButtons.clear(); - myExtraReplaceButtons.addAll(textArea.setExtraActions(myEmbeddedReplaceActions.toArray(AnAction.EMPTY_ARRAY))); + innerTextComponent.getAccessibleContext().setAccessibleName(FindBundle.message("find.replace.accessible.name")); } // Display empty text only when focused - textComponent.putClientProperty( + innerTextComponent.putClientProperty( "StatusVisibleFunction", (BooleanFunction)(c -> c.getText().isEmpty() && c.isFocusOwner())); - wrapper.setContent(textArea); - - UIUtil.addUndoRedoActions(textComponent); - - textComponent.putClientProperty(UIUtil.HIDE_EDITOR_FROM_DATA_CONTEXT_PROPERTY, Boolean.TRUE); - textComponent.setBackground(UIUtil.getTextFieldBackground()); - textComponent.addFocusListener(new FocusListener() { + innerTextComponent.putClientProperty(UIUtil.HIDE_EDITOR_FROM_DATA_CONTEXT_PROPERTY, Boolean.TRUE); + innerTextComponent.setBackground(UIUtil.getTextFieldBackground()); + JComponent finalTextComponent = innerTextComponent; + innerTextComponent.addFocusListener(new FocusListener() { @Override public void focusGained(final FocusEvent e) { - textComponent.repaint(); + finalTextComponent.repaint(); } @Override public void focusLost(final FocusEvent e) { - textComponent.repaint(); + finalTextComponent.repaint(); } }); new CloseAction() { @@ -512,7 +548,7 @@ public final class SearchReplaceComponent extends EditorHeaderComponent implemen public void actionPerformed(@NotNull AnActionEvent e) { close(); } - }.registerCustomShortcutSet(KeymapUtil.getActiveKeymapShortcuts(IdeActions.ACTION_EDITOR_ESCAPE), textArea); + }.registerCustomShortcutSet(KeymapUtil.getActiveKeymapShortcuts(IdeActions.ACTION_EDITOR_ESCAPE), outerComponent); return true; } @@ -634,7 +670,9 @@ public final class SearchReplaceComponent extends EditorHeaderComponent implemen private boolean myShowOnlySearchPanel = false; private boolean myMaximizeLeftPanelOnResize = false; - + private boolean myMultilineEnabled = true; + private boolean myAddSearchResultsToGlobalSearch = true; + private boolean myUseSearchField = false; private Builder(@Nullable Project project, @NotNull JComponent component) { myProject = project; @@ -736,7 +774,28 @@ public final class SearchReplaceComponent extends EditorHeaderComponent implemen myCloseAction, myDataProvider, myShowOnlySearchPanel, - myMaximizeLeftPanelOnResize); + myMaximizeLeftPanelOnResize, + myMultilineEnabled, + myAddSearchResultsToGlobalSearch, + myUseSearchField); + } + + @NotNull + public Builder withMultilineEnabled(boolean b) { + myMultilineEnabled = b; + return this; + } + + @NotNull + public Builder withAddSearchResultsToGlobalSearch(boolean b) { + myAddSearchResultsToGlobalSearch = b; + return this; + } + + @NotNull + public Builder withUseSearchField(boolean b) { + myUseSearchField = b; + return this; } } diff --git a/platform/platform-api/resources/messages/ApplicationBundle.properties b/platform/platform-api/resources/messages/ApplicationBundle.properties index 6c0c01232385..0d9067e80e40 100644 --- a/platform/platform-api/resources/messages/ApplicationBundle.properties +++ b/platform/platform-api/resources/messages/ApplicationBundle.properties @@ -594,6 +594,7 @@ code.style.indent.provider.notification.settings=Code Style Settings editorsearch.replace.action.text=Replace editorsearch.replace.all.action.text=Replace All editorsearch.matches={0, choice, 0#0 results|1#1 result|2#{0} results} +editorsearch.matches.short={0, choice, 0#0 |1#1 |2#{0}} editorsearch.current.cursor.position={0}/{1} editorsearch.toomuch={0}+ editorsearch.noselection=No selection