IDEA-122076, IDEA-122172 Multicaret actions in quick find mode

This commit is contained in:
Dmitry Batrak
2014-07-18 12:11:16 +04:00
parent 8b2824dc45
commit d61da37eda
19 changed files with 782 additions and 177 deletions
@@ -0,0 +1,222 @@
/*
* Copyright 2000-2014 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.
*/
package com.intellij.find;
import com.intellij.find.editorHeaderActions.*;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.util.Getter;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
import javax.swing.text.JTextComponent;
import java.io.IOException;
public class FindInEditorMultiCaretTest extends LightPlatformCodeInsightFixtureTestCase {
public void testBasic() throws IOException {
init("abc\n" +
"abc\n" +
"abc");
initFind();
setTextToFind("b");
checkResultByText("a<selection>b<caret></selection>c\n" +
"abc\n" +
"abc");
addOccurrence();
checkResultByText("a<selection>b<caret></selection>c\n" +
"a<selection>b<caret></selection>c\n" +
"abc");
nextOccurrence();
checkResultByText("a<selection>b<caret></selection>c\n" +
"abc\n" +
"a<selection>b<caret></selection>c");
prevOccurrence();
checkResultByText("a<selection>b<caret></selection>c\n" +
"a<selection>b<caret></selection>c\n" +
"abc");
removeOccurrence();
checkResultByText("a<selection>b<caret></selection>c\n" +
"abc\n" +
"abc");
allOccurrences();
checkResultByText("a<selection>b<caret></selection>c\n" +
"a<selection>b<caret></selection>c\n" +
"a<selection>b<caret></selection>c");
assertNull(getEditorSearchComponent());
}
public void testActionsWorkFromEditor() throws IOException {
init("abc\n" +
"abc\n" +
"abc");
initFind();
setTextToFind("b");
checkResultByText("a<selection>b<caret></selection>c\n" +
"abc\n" +
"abc");
addOccurrenceFromEditor();
checkResultByText("a<selection>b<caret></selection>c\n" +
"a<selection>b<caret></selection>c\n" +
"abc");
nextOccurrenceFromEditor();
checkResultByText("a<selection>b<caret></selection>c\n" +
"abc\n" +
"a<selection>b<caret></selection>c");
prevOccurrenceFromEditor();
checkResultByText("a<selection>b<caret></selection>c\n" +
"a<selection>b<caret></selection>c\n" +
"abc");
removeOccurrenceFromEditor();
checkResultByText("a<selection>b<caret></selection>c\n" +
"abc\n" +
"abc");
allOccurrencesFromEditor();
checkResultByText("a<selection>b<caret></selection>c\n" +
"a<selection>b<caret></selection>c\n" +
"a<selection>b<caret></selection>c");
assertNull(getEditorSearchComponent());
}
public void testCloseRetainsMulticaretSelection() throws IOException {
init("abc\n" +
"abc\n" +
"abc");
initFind();
setTextToFind("b");
addOccurrence();
closeFind();
checkResultByText("a<selection>b<caret></selection>c\n" +
"a<selection>b<caret></selection>c\n" +
"abc");
}
public void testTextModificationRemovesOldSelections() throws IOException {
init("abc\n" +
"abc\n" +
"abc");
initFind();
setTextToFind("b");
addOccurrence();
setTextToFind("bc");
assertEquals(1, myFixture.getEditor().getCaretModel().getCaretCount());
assertEquals("bc", myFixture.getEditor().getSelectionModel().getSelectedText());
}
public void testSecondFindNavigatesToTheSameOccurrence() throws IOException {
init("ab<caret>c\n" +
"abc\n" +
"abc");
initFind();
setTextToFind("abc");
checkResultByText("abc\n" +
"<selection>abc<caret></selection>\n" +
"abc");
closeFind();
initFind();
setTextToFind("abc");
checkResultByText("abc\n" +
"<selection>abc<caret></selection>\n" +
"abc");
}
private void setTextToFind(String text) {
EditorSearchComponent editorSearchComponent = getEditorSearchComponent();
assertNotNull(editorSearchComponent);
JTextComponent searchField = editorSearchComponent.getSearchField();
assertNotNull(searchField);
for (int i = 0; i <= text.length(); i++) {
searchField.setText(text.substring(0, i)); // emulate typing chars one by one
}
}
private void nextOccurrence() {
final EditorSearchComponent editorSearchComponent = getEditorSearchComponent();
executeAction(new NextOccurrenceAction(editorSearchComponent, new Getter<JTextComponent>() {
@Override
public JTextComponent get() {
return editorSearchComponent.getSearchField();
}
}));
}
private void prevOccurrence() {
final EditorSearchComponent editorSearchComponent = getEditorSearchComponent();
executeAction(new PrevOccurrenceAction(editorSearchComponent, new Getter<JTextComponent>() {
@Override
public JTextComponent get() {
return editorSearchComponent.getSearchField();
}
}));
}
private void addOccurrence() {
executeAction(new AddOccurrenceAction(getEditorSearchComponent()));
}
private void removeOccurrence() {
executeAction(new RemoveOccurrenceAction(getEditorSearchComponent()));
}
private void allOccurrences() {
executeAction(new SelectAllAction(getEditorSearchComponent()));
}
private void nextOccurrenceFromEditor() {
myFixture.performEditorAction(IdeActions.ACTION_FIND_NEXT);
}
private void prevOccurrenceFromEditor() {
myFixture.performEditorAction(IdeActions.ACTION_FIND_PREVIOUS);
}
private void addOccurrenceFromEditor() {
myFixture.performEditorAction(IdeActions.ACTION_SELECT_NEXT_OCCURENCE);
}
private void removeOccurrenceFromEditor() {
myFixture.performEditorAction(IdeActions.ACTION_UNSELECT_PREVIOUS_OCCURENCE);
}
private void allOccurrencesFromEditor() {
myFixture.performEditorAction(IdeActions.ACTION_SELECT_ALL_OCCURRENCES);
}
private void closeFind() {
EditorSearchComponent editorSearchComponent = getEditorSearchComponent();
executeAction(new CloseOnESCAction(editorSearchComponent, editorSearchComponent.getSearchField()));
}
private static void executeAction(EditorHeaderAction action) {
action.actionPerformed(AnActionEvent.createFromInputEvent(action, null, ActionPlaces.EDITOR_TOOLBAR));
}
private void initFind() {
myFixture.performEditorAction("Find");
}
private EditorSearchComponent getEditorSearchComponent() {
return (EditorSearchComponent)myFixture.getEditor().getHeaderComponent();
}
private void init(String text) {
myFixture.configureByText(getTestName(false) + ".txt", text);
}
private void checkResultByText(String text) {
myFixture.checkResult(text);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -48,6 +48,7 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -68,11 +69,12 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
private final Project myProject;
private ActionToolbar myActionsToolbar;
@NotNull
public Editor getEditor() {
return myEditor;
}
@NotNull
private final Editor myEditor;
public JTextComponent getSearchField() {
@@ -173,7 +175,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
return findModel;
}
public EditorSearchComponent(Editor editor, Project project) {
public EditorSearchComponent(@NotNull Editor editor, Project project) {
this(editor, project, createDefaultFindModel(project, editor));
}
@@ -225,7 +227,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
}
@Override
public void cursorMoved(boolean toChangeSelection) {
public void cursorMoved() {
updateExcludeStatus();
}
@@ -233,10 +235,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
public void updateFinished() {
}
@Override
public void editorChanged(SearchResults sr, Editor oldEditor) { }
public EditorSearchComponent(final Editor editor, final Project project, FindModel findModel) {
public EditorSearchComponent(@NotNull final Editor editor, final Project project, FindModel findModel) {
myFindModel = findModel;
myProject = project;
@@ -367,6 +366,9 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
actionGroup.add(new ShowHistoryAction(mySearchFieldGetter, this));
actionGroup.add(new PrevOccurrenceAction(this, mySearchFieldGetter));
actionGroup.add(new NextOccurrenceAction(this, mySearchFieldGetter));
actionGroup.add(new AddOccurrenceAction(this));
actionGroup.add(new RemoveOccurrenceAction(this));
actionGroup.add(new SelectAllAction(this));
actionGroup.add(new FindAllAction(this));
actionGroup.add(new ToggleMultiline(this));
actionGroup.add(new ToggleMatchCase(this));
@@ -803,10 +805,6 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
}
public void close() {
if (myEditor.getSelectionModel().hasSelection()) {
myEditor.getCaretModel().moveToOffset(myEditor.getSelectionModel().getSelectionStart());
myEditor.getSelectionModel().removeSelection();
}
IdeFocusManager.getInstance(myProject).requestFocus(myEditor.getContentComponent(), false);
myLivePreviewController.dispose();
@@ -937,6 +935,18 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
return insets;
}
public void selectAllOccurrences() {
FindUtil.selectSearchResultsInEditor(myEditor, mySearchResults.getOccurrences().iterator(), -1);
}
public void removeOccurrence() {
mySearchResults.prevOccurrence(true);
}
public void addNextOccurrence() {
mySearchResults.nextOccurrence(true);
}
private static class MyUndoProvider extends TextComponentUndoProvider {
private boolean myEnabled = true;
public MyUndoProvider(JTextComponent textComponent) {
@@ -31,6 +31,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actions.EditorActionUtil;
import com.intellij.openapi.editor.actions.IncrementalFindAction;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
@@ -70,10 +71,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.*;
public class FindUtil {
private static final Key<Direction> KEY = Key.create("FindUtil.KEY");
@@ -960,4 +958,68 @@ public class FindUtil {
});
return view;
}
/**
* Creates a selection in editor per each search result. Existing carets and selections in editor are discarded.
*
* @param caretShiftFromSelectionStart if non-negative, defines caret position relative to selection start, for each created selection.
* if negative, carets will be positioned at selection ends
*/
public static void selectSearchResultsInEditor(@NotNull Editor editor,
@NotNull Iterator<FindResult> resultIterator,
int caretShiftFromSelectionStart) {
if (!editor.getCaretModel().supportsMultipleCarets()) {
return;
}
ArrayList<CaretState> caretStates = new ArrayList<CaretState>();
while (resultIterator.hasNext()) {
FindResult findResult = resultIterator.next();
int caretOffset = getCaretPosition(findResult, caretShiftFromSelectionStart);
int selectionStartOffset = findResult.getStartOffset();
int selectionEndOffset = findResult.getEndOffset();
EditorActionUtil.makePositionVisible(editor, caretOffset);
EditorActionUtil.makePositionVisible(editor, selectionStartOffset);
EditorActionUtil.makePositionVisible(editor, selectionEndOffset);
caretStates.add(new CaretState(editor.offsetToLogicalPosition(caretOffset),
editor.offsetToLogicalPosition(selectionStartOffset),
editor.offsetToLogicalPosition(selectionEndOffset)));
}
if (caretStates.isEmpty()) {
return;
}
editor.getCaretModel().setCaretsAndSelections(caretStates);
}
/**
* Attempts to add a new caret to editor, with selection corresponding to given search result.
*
* @param caretShiftFromSelectionStart if non-negative, defines caret position relative to selection start, for each created selection.
* if negative, caret will be positioned at selection end
* @return <code>true</code> if caret was added successfully, <code>false</code> if it cannot be done, e.g. because a caret already
* exists at target position
*/
public static boolean selectSearchResultInEditor(@NotNull Editor editor, @NotNull FindResult result, int caretShiftFromSelectionStart) {
if (!editor.getCaretModel().supportsMultipleCarets()) {
return false;
}
int caretOffset = getCaretPosition(result, caretShiftFromSelectionStart);
EditorActionUtil.makePositionVisible(editor, caretOffset);
Caret newCaret = editor.getCaretModel().addCaret(editor.offsetToVisualPosition(caretOffset));
if (newCaret == null) {
return false;
}
else {
int selectionStartOffset = result.getStartOffset();
int selectionEndOffset = result.getEndOffset();
EditorActionUtil.makePositionVisible(editor, selectionStartOffset);
EditorActionUtil.makePositionVisible(editor, selectionEndOffset);
newCaret.setSelection(selectionStartOffset, selectionEndOffset);
return true;
}
}
private static int getCaretPosition(FindResult findResult, int caretShiftFromSelectionStart) {
return caretShiftFromSelectionStart < 0
? findResult.getEndOffset() : Math.min(findResult.getStartOffset() + caretShiftFromSelectionStart, findResult.getEndOffset());
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2000-2014 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.
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchComponent;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAware;
import java.util.Arrays;
public class AddOccurrenceAction extends EditorHeaderAction implements DumbAware {
public AddOccurrenceAction(EditorSearchComponent editorSearchComponent) {
super(editorSearchComponent);
copyFrom(ActionManager.getInstance().getAction(IdeActions.ACTION_SELECT_NEXT_OCCURENCE));
getTemplatePresentation().setIcon(AllIcons.General.Add);
registerShortcutsForComponent(Arrays.asList(getShortcutSet().getShortcuts()), editorSearchComponent.getSearchField());
}
@Override
public void actionPerformed(AnActionEvent e) {
getEditorSearchComponent().addNextOccurrence();
}
@Override
public void update(AnActionEvent e) {
boolean isFind = !getEditorSearchComponent().getFindModel().isReplaceState();
boolean hasMatches = getEditorSearchComponent().hasMatches();
e.getPresentation().setVisible(isFind);
e.getPresentation().setEnabled(isFind && hasMatches);
}}
@@ -1,21 +1,34 @@
/*
* Copyright 2000-2014 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.
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchComponent;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.actionSystem.Shortcut;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
public abstract class EditorHeaderAction extends AnAction {
private final EditorSearchComponent myEditorSearchComponent;
protected static void registerShortcutsForComponent(List<Shortcut> shortcuts, JComponent component, AnAction a) {
a.registerCustomShortcutSet(
protected void registerShortcutsForComponent(List<Shortcut> shortcuts, JComponent component) {
registerCustomShortcutSet(
new CustomShortcutSet(shortcuts.toArray(new Shortcut[shortcuts.size()])),
component);
}
@@ -1,3 +1,18 @@
/*
* Copyright 2000-2014 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.
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchComponent;
@@ -35,7 +50,7 @@ public class NextOccurrenceAction extends EditorHeaderAction implements DumbAwar
shortcuts.add(new KeyboardShortcut(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), null));
}
registerShortcutsForComponent(shortcuts, editorTextField.get(), this);
registerShortcutsForComponent(shortcuts, editorTextField.get());
}
@Override
@@ -1,3 +1,18 @@
/*
* Copyright 2000-2014 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.
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchComponent;
@@ -34,7 +49,7 @@ public class PrevOccurrenceAction extends EditorHeaderAction implements DumbAwar
shortcuts.add(new KeyboardShortcut(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK), null));
}
registerShortcutsForComponent(shortcuts, editorTextField.get(), this);
registerShortcutsForComponent(shortcuts, editorTextField.get());
}
@Override
@@ -0,0 +1,49 @@
/*
* Copyright 2000-2014 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.
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchComponent;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.project.DumbAware;
import java.util.Arrays;
public class RemoveOccurrenceAction extends EditorHeaderAction implements DumbAware {
public RemoveOccurrenceAction(EditorSearchComponent editorSearchComponent) {
super(editorSearchComponent);
copyFrom(ActionManager.getInstance().getAction(IdeActions.ACTION_UNSELECT_PREVIOUS_OCCURENCE));
getTemplatePresentation().setIcon(AllIcons.General.Remove);
registerShortcutsForComponent(Arrays.asList(getShortcutSet().getShortcuts()), editorSearchComponent.getSearchField());
}
@Override
public void actionPerformed(AnActionEvent e) {
getEditorSearchComponent().removeOccurrence();
}
@Override
public void update(AnActionEvent e) {
boolean isFind = !getEditorSearchComponent().getFindModel().isReplaceState();
boolean hasMatches = getEditorSearchComponent().hasMatches();
e.getPresentation().setVisible(isFind);
e.getPresentation().setEnabled(isFind && hasMatches);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -39,8 +39,7 @@ public class RestorePreviousSettingsAction extends EditorHeaderAction implements
public RestorePreviousSettingsAction(EditorSearchComponent editorSearchComponent, JTextComponent textField) {
super(editorSearchComponent);
myTextField = textField;
registerShortcutsForComponent(Collections.<Shortcut>singletonList(SHORTCUT),
textField, this);
registerShortcutsForComponent(Collections.<Shortcut>singletonList(SHORTCUT), textField);
}
@Override
@@ -0,0 +1,53 @@
/*
* Copyright 2000-2014 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.
*/
package com.intellij.find.editorHeaderActions;
import com.intellij.find.EditorSearchComponent;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAware;
import com.intellij.util.containers.ContainerUtil;
import java.util.ArrayList;
import java.util.List;
public class SelectAllAction extends EditorHeaderAction implements DumbAware {
public SelectAllAction(EditorSearchComponent editorSearchComponent) {
super(editorSearchComponent);
copyFrom(ActionManager.getInstance().getAction(IdeActions.ACTION_SELECT_ALL_OCCURRENCES));
getTemplatePresentation().setIcon(AllIcons.Actions.Selectall);
List<Shortcut> shortcuts = new ArrayList<Shortcut>();
ContainerUtil.addAll(shortcuts, getShortcutSet().getShortcuts());
ContainerUtil.addAll(shortcuts, CommonShortcuts.ALT_ENTER.getShortcuts());
registerShortcutsForComponent(shortcuts, editorSearchComponent.getSearchField());
}
@Override
public void actionPerformed(AnActionEvent e) {
getEditorSearchComponent().selectAllOccurrences();
getEditorSearchComponent().close();
}
@Override
public void update(AnActionEvent e) {
boolean isFind = !getEditorSearchComponent().getFindModel().isReplaceState();
boolean hasMatches = getEditorSearchComponent().hasMatches();
e.getPresentation().setVisible(isFind);
e.getPresentation().setEnabled(isFind && hasMatches);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -121,7 +121,7 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search
}
highlightUsages();
updateCursorHighlighting(false);
updateCursorHighlighting();
if (myInSmartUpdate) {
clearUnusedHightlighters();
myInSmartUpdate = false;
@@ -218,9 +218,9 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search
}
@Override
public void cursorMoved(boolean toChangeSelection) {
public void cursorMoved() {
updateInSelectionHighlighters();
updateCursorHighlighting(toChangeSelection);
updateCursorHighlighting();
}
@Override
@@ -228,14 +228,7 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search
dumpState();
}
@Override
public void editorChanged(SearchResults sr, Editor oldEditor) {
removeFromEditor();
oldEditor.getDocument().removeDocumentListener(this);
mySearchResults.getEditor().getDocument().addDocumentListener(this);
}
private void updateCursorHighlighting(boolean scroll) {
private void updateCursorHighlighting() {
hideBalloon();
if (myCursorHighlighter != null) {
@@ -245,7 +238,6 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search
final FindResult cursor = mySearchResults.getCursor();
Editor editor = mySearchResults.getEditor();
SelectionModel selection = editor.getSelectionModel();
if (cursor != null) {
Set<RangeHighlighter> dummy = new HashSet<RangeHighlighter>();
highlightRange(cursor, new TextAttributes(null, null, Color.BLACK, EffectType.ROUNDED_BOX, 0), dummy);
@@ -253,33 +245,6 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search
myCursorHighlighter = dummy.iterator().next();
}
if (scroll) {
if (mySearchResults.getFindModel().isGlobal()) {
FoldingModel foldingModel = editor.getFoldingModel();
final FoldRegion[] allRegions = editor.getFoldingModel().getAllFoldRegions();
foldingModel.runBatchFoldingOperation(new Runnable() {
@Override
public void run() {
for (FoldRegion region : allRegions) {
if (!region.isValid()) continue;
if (cursor.intersects(TextRange.create(region))) {
region.setExpanded(true);
}
}
}
});
selection.setSelection(cursor.getStartOffset(), cursor.getEndOffset());
editor.getCaretModel().moveToOffset(cursor.getEndOffset());
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
} else {
if (!SearchResults.insideVisibleArea(editor, cursor)) {
LogicalPosition pos = editor.offsetToLogicalPosition(cursor.getStartOffset());
editor.getScrollingModel().scrollTo(pos, ScrollType.CENTER);
}
}
}
editor.getScrollingModel().runActionOnScrollingFinished(new Runnable() {
@Override
public void run() {
@@ -1,3 +1,18 @@
/*
* Copyright 2000-2014 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.
*/
package com.intellij.find.impl.livePreview;
import com.intellij.find.*;
@@ -83,9 +98,9 @@ public class LivePreviewController implements LivePreview.Delegate, FindUtil.Rep
public void moveCursor(SearchResults.Direction direction) {
if (direction == SearchResults.Direction.UP) {
mySearchResults.prevOccurrence();
mySearchResults.prevOccurrence(false);
} else {
mySearchResults.nextOccurrence();
mySearchResults.nextOccurrence(false);
}
}
@@ -21,9 +21,7 @@ import com.intellij.find.FindModel;
import com.intellij.find.FindResult;
import com.intellij.find.FindUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -38,6 +36,7 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.Stack;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -70,6 +69,7 @@ public class SearchResults implements DocumentListener {
private @Nullable FindResult myCursor;
@NotNull
private List<FindResult> myOccurrences = new ArrayList<FindResult>();
private final Set<RangeMarker> myExcluded = new HashSet<RangeMarker>();
@@ -90,6 +90,8 @@ public class SearchResults implements DocumentListener {
private final Stack<Pair<FindModel, FindResult>> myCursorPositions = new Stack<Pair<FindModel, FindResult>>();
private final SelectionManager mySelectionManager = new SelectionManager(this);
public SearchResults(Editor editor, Project project) {
myEditor = editor;
myProject = project;
@@ -127,9 +129,8 @@ public class SearchResults implements DocumentListener {
public void exclude(FindResult occurrence) {
boolean include = false;
final TextRange r = occurrence;
for (RangeMarker rangeMarker : myExcluded) {
if (TextRange.areSegmentsEqual(rangeMarker, r)) {
if (TextRange.areSegmentsEqual(rangeMarker, occurrence)) {
myExcluded.remove(rangeMarker);
rangeMarker.dispose();
include = true;
@@ -137,7 +138,7 @@ public class SearchResults implements DocumentListener {
}
}
if (!include) {
myExcluded.add(myEditor.getDocument().createRangeMarker(r.getStartOffset(), r.getEndOffset(), true));
myExcluded.add(myEditor.getDocument().createRangeMarker(occurrence.getStartOffset(), occurrence.getEndOffset(), true));
}
notifyChanged();
}
@@ -149,8 +150,7 @@ public class SearchResults implements DocumentListener {
public interface SearchResultsListener {
void searchResultsUpdated(SearchResults sr);
void editorChanged(SearchResults sr, Editor oldEditor);
void cursorMoved(boolean toChangeSelection);
void cursorMoved();
void updateFinished();
}
@@ -175,6 +175,7 @@ public class SearchResults implements DocumentListener {
return myCursor;
}
@NotNull
public List<FindResult> getOccurrences() {
return myOccurrences;
}
@@ -184,19 +185,7 @@ public class SearchResults implements DocumentListener {
return myProject;
}
public synchronized void setEditor(Editor editor) {
Editor oldOne = myEditor;
myEditor = editor;
notifyEditorChanged(oldOne);
}
private void notifyEditorChanged(Editor oldOne) {
for (SearchResultsListener listener : myListeners) {
listener.editorChanged(this, oldOne);
}
}
public synchronized Editor getEditor() {
public Editor getEditor() {
return myEditor;
}
@@ -334,7 +323,7 @@ public class SearchResults implements DocumentListener {
myEditor.getDocument().removeDocumentListener(this);
}
private void searchCompleted(List<FindResult> occurrences, Editor editor, @Nullable FindModel findModel,
private void searchCompleted(@NotNull List<FindResult> occurrences, Editor editor, @Nullable FindModel findModel,
boolean toChangeSelection, @Nullable TextRange next, int stamp) {
if (stamp < myLastUpdatedStamp){
return;
@@ -344,7 +333,7 @@ public class SearchResults implements DocumentListener {
return;
}
myOccurrences = occurrences;
final TextRange oldCursorRange = myCursor != null ? myCursor : null;
final TextRange oldCursorRange = myCursor;
Collections.sort(myOccurrences, new Comparator<FindResult>() {
@Override
public int compare(FindResult findResult, FindResult findResult1) {
@@ -357,7 +346,10 @@ public class SearchResults implements DocumentListener {
updateExcluded();
notifyChanged();
if (oldCursorRange == null || myCursor == null || !myCursor.equals(oldCursorRange)) {
notifyCursorMoved(toChangeSelection);
if (toChangeSelection) {
mySelectionManager.updateSelection(true, true);
}
notifyCursorMoved();
}
dumpIfNeeded();
}
@@ -389,7 +381,7 @@ public class SearchResults implements DocumentListener {
myCursor = firstOccurrenceAfterOffset(oldCursorRange.getEndOffset());
} else {
if (justReplaced) {
nextOccurrence(false, next, false, justReplaced);
nextOccurrence(false, next, false, true, false);
} else {
FindResult afterCaret = oldCursorRange == null ? firstOccurrenceAtOrAfterCaret() : firstOccurrenceAfterCaret();
if (afterCaret != null) {
@@ -405,7 +397,7 @@ public class SearchResults implements DocumentListener {
}
}
if (!justReplaced && myCursor == null && hasMatches()) {
nextOccurrence(true, oldCursorRange, false, false);
nextOccurrence(true, oldCursorRange, false, false, false);
}
if (toPush && myCursor != null){
push();
@@ -445,6 +437,13 @@ public class SearchResults implements DocumentListener {
return occurrence;
}
}
int selectionStartOffset = getEditor().getSelectionModel().getSelectionStart();
int selectionEndOffset = getEditor().getSelectionModel().getSelectionEnd();
for (FindResult occurrence : myOccurrences) {
if (selectionEndOffset >= occurrence.getEndOffset() && selectionStartOffset <= occurrence.getStartOffset()) {
return occurrence;
}
}
return firstOccurrenceAfterCaret();
}
@@ -461,25 +460,6 @@ public class SearchResults implements DocumentListener {
return visibleArea.contains(point);
}
@Nullable
private FindResult firstVisibleOccurrence() {
int offset = Integer.MAX_VALUE;
FindResult firstOccurrence = null;
FindResult firstVisibleOccurrence = null;
for (FindResult o : getOccurrences()) {
if (insideVisibleArea(myEditor, o)) {
if (firstVisibleOccurrence == null || o.getStartOffset() < firstVisibleOccurrence.getStartOffset()) {
firstVisibleOccurrence = o;
}
}
if (o.getStartOffset() < offset) {
offset = o.getStartOffset();
firstOccurrence = o;
}
}
return firstVisibleOccurrence != null ? firstVisibleOccurrence : firstOccurrence;
}
@Nullable
private FindResult firstOccurrenceBeforeCaret() {
int offset = getEditor().getCaretModel().getOffset();
@@ -554,32 +534,45 @@ public class SearchResults implements DocumentListener {
return null;
}
public void prevOccurrence() {
FindResult next = null;
if (myFindModel == null) return;
boolean processFromTheBeginning = false;
if (myNotFoundState) {
myNotFoundState = false;
processFromTheBeginning = true;
}
if (!myFindModel.isGlobal()) {
if (myCursor != null) {
next = prevOccurrence(myCursor);
public void prevOccurrence(boolean findSelected) {
if (findSelected) {
if (mySelectionManager.removeCurrentSelection()) {
myCursor = firstOccurrenceAtOrAfterCaret();
}
} else {
next = firstOccurrenceBeforeCaret();
else {
myCursor = null;
}
notifyCursorMoved();
}
if (next == null) {
if (processFromTheBeginning) {
if (hasMatches()) {
next = getOccurrences().get(getOccurrences().size()-1);
else {
FindResult next = null;
if (myFindModel == null) return;
boolean processFromTheBeginning = false;
if (myNotFoundState) {
myNotFoundState = false;
processFromTheBeginning = true;
}
if (!myFindModel.isGlobal()) {
if (myCursor != null) {
next = prevOccurrence(myCursor);
}
}
else {
next = firstOccurrenceBeforeCaret();
}
if (next == null) {
if (processFromTheBeginning) {
if (hasMatches()) {
next = getOccurrences().get(getOccurrences().size() - 1);
}
}
else {
setNotFoundState(false);
}
} else {
setNotFoundState(false);
}
}
moveCursorTo(next);
moveCursorTo(next, false);
}
push();
}
@@ -587,13 +580,13 @@ public class SearchResults implements DocumentListener {
myCursorPositions.push(Pair.create(myFindModel, myCursor));
}
public void nextOccurrence() {
public void nextOccurrence(boolean retainOldSelection) {
if (myFindModel == null) return;
nextOccurrence(false, myCursor != null ? myCursor : null, true, false);
nextOccurrence(false, myCursor, true, false, retainOldSelection);
push();
}
private void nextOccurrence(boolean processFromTheBeginning, TextRange cursor, boolean toNotify, boolean justReplaced) {
private void nextOccurrence(boolean processFromTheBeginning, TextRange cursor, boolean toNotify, boolean justReplaced, boolean retainOldSelection) {
FindResult next;
if (myNotFoundState) {
myNotFoundState = false;
@@ -614,22 +607,24 @@ public class SearchResults implements DocumentListener {
}
}
if (toNotify) {
moveCursorTo(next);
moveCursorTo(next, retainOldSelection);
} else {
myCursor = next;
}
}
public void moveCursorTo(FindResult next) {
if (next != null) {
public void moveCursorTo(FindResult next, boolean retainOldSelection) {
if (next != null && !mySelectionManager.isSelected(next)) {
retainOldSelection &= (myCursor != null && mySelectionManager.isSelected(myCursor));
myCursor = next;
notifyCursorMoved(true);
mySelectionManager.updateSelection(!retainOldSelection, false);
notifyCursorMoved();
}
}
private void notifyCursorMoved(boolean toChangeSelection) {
private void notifyCursorMoved() {
for (SearchResultsListener listener : myListeners) {
listener.cursorMoved(toChangeSelection);
listener.cursorMoved();
}
}
}
@@ -0,0 +1,90 @@
/*
* Copyright 2000-2014 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.
*/
package com.intellij.find.impl.livePreview;
import com.intellij.find.FindResult;
import com.intellij.find.FindUtil;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.NotNull;
public class SelectionManager {
@NotNull private final SearchResults mySearchResults;
public SelectionManager(@NotNull SearchResults results) {
mySearchResults = results;
}
public void updateSelection(boolean removePreviousSelection, boolean removeAllPreviousSelections) {
Editor editor = mySearchResults.getEditor();
if (removeAllPreviousSelections) {
editor.getCaretModel().removeSecondaryCarets();
}
final FindResult cursor = mySearchResults.getCursor();
if (cursor == null) {
return;
}
if (mySearchResults.getFindModel().isGlobal()) {
if (removePreviousSelection || removeAllPreviousSelections) {
FoldingModel foldingModel = editor.getFoldingModel();
final FoldRegion[] allRegions = editor.getFoldingModel().getAllFoldRegions();
foldingModel.runBatchFoldingOperation(new Runnable() {
@Override
public void run() {
for (FoldRegion region : allRegions) {
if (!region.isValid()) continue;
if (cursor.intersects(TextRange.create(region))) {
region.setExpanded(true);
}
}
}
});
editor.getSelectionModel().setSelection(cursor.getStartOffset(), cursor.getEndOffset());
editor.getCaretModel().moveToOffset(cursor.getEndOffset());
}
else {
FindUtil.selectSearchResultInEditor(editor, cursor, -1);
}
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
} else {
if (!SearchResults.insideVisibleArea(editor, cursor)) {
LogicalPosition pos = editor.offsetToLogicalPosition(cursor.getStartOffset());
editor.getScrollingModel().scrollTo(pos, ScrollType.CENTER);
}
}
}
public boolean removeCurrentSelection() {
Editor editor = mySearchResults.getEditor();
CaretModel caretModel = editor.getCaretModel();
Caret primaryCaret = caretModel.getPrimaryCaret();
if (caretModel.getCaretCount() > 1) {
caretModel.removeCaret(primaryCaret);
return true;
}
else {
primaryCaret.moveToOffset(primaryCaret.getSelectionStart());
primaryCaret.removeSelection();
return false;
}
}
public boolean isSelected(@NotNull FindResult result) {
Editor editor = mySearchResults.getEditor();
return editor.getCaretModel().getCaretAt(editor.offsetToVisualPosition(result.getEndOffset())) != null;
}
}
@@ -15,9 +15,9 @@
*/
package com.intellij.openapi.editor.actions;
import com.intellij.find.FindManager;
import com.intellij.find.FindModel;
import com.intellij.find.FindResult;
import com.intellij.find.*;
import com.intellij.find.editorHeaderActions.EditorHeaderAction;
import com.intellij.find.editorHeaderActions.SelectAllAction;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
@@ -27,6 +27,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.Nullable;
import java.util.Iterator;
public class SelectAllOccurrencesAction extends EditorAction {
protected SelectAllOccurrencesAction() {
super(new Handler());
@@ -39,7 +41,9 @@ public class SelectAllOccurrencesAction extends EditorAction {
}
@Override
public void doExecute(Editor editor, @Nullable Caret c, DataContext dataContext) {
public void doExecute(final Editor editor, @Nullable Caret c, DataContext dataContext) {
if (executeEquivalentFindPanelAction(editor, dataContext)) return;
Caret caret = c == null ? editor.getCaretModel().getPrimaryCaret() : c;
boolean wholeWordsSearch = false;
@@ -58,25 +62,36 @@ public class SelectAllOccurrencesAction extends EditorAction {
}
int caretShiftFromSelectionStart = caret.getOffset() - caret.getSelectionStart();
FindManager findManager = FindManager.getInstance(project);
final FindManager findManager = FindManager.getInstance(project);
FindModel model = new FindModel();
model.setStringToFind(selectedText);
model.setCaseSensitive(true);
model.setWholeWordsOnly(wholeWordsSearch);
final FindModel model = getFindModel(selectedText, wholeWordsSearch);
int searchStartOffset = 0;
FindResult findResult = findManager.findString(editor.getDocument().getCharsSequence(), searchStartOffset, model);
while (findResult.isStringFound()) {
int newCaretOffset = caretShiftFromSelectionStart + findResult.getStartOffset();
EditorActionUtil.makePositionVisible(editor, newCaretOffset);
Caret newCaret = editor.getCaretModel().addCaret(editor.offsetToVisualPosition(newCaretOffset));
if (newCaret != null) {
setSelection(editor, newCaret, findResult);
FindUtil.selectSearchResultsInEditor(editor, new Iterator<FindResult>() {
FindResult findResult = findManager.findString(editor.getDocument().getCharsSequence(), 0, model);
@Override
public boolean hasNext() {
return findResult.isStringFound();
}
findResult = findManager.findString(editor.getDocument().getCharsSequence(), findResult.getEndOffset(), model);
}
@Override
public FindResult next() {
FindResult result = findResult;
findResult = findManager.findString(editor.getDocument().getCharsSequence(), findResult.getEndOffset(), model);
return result;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}, caretShiftFromSelectionStart);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
@Override
protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
return new SelectAllAction(searchComponent);
}
}
}
@@ -15,9 +15,9 @@
*/
package com.intellij.openapi.editor.actions;
import com.intellij.find.FindManager;
import com.intellij.find.FindModel;
import com.intellij.find.FindResult;
import com.intellij.find.*;
import com.intellij.find.editorHeaderActions.AddOccurrenceAction;
import com.intellij.find.editorHeaderActions.EditorHeaderAction;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
@@ -40,6 +40,8 @@ public class SelectNextOccurrenceAction extends EditorAction {
@Override
public void doExecute(Editor editor, @Nullable Caret c, DataContext dataContext) {
if (executeEquivalentFindPanelAction(editor, dataContext)) return;
Caret caret = c == null ? editor.getCaretModel().getPrimaryCaret() : c;
TextRange wordSelectionRange = getSelectionRange(editor, caret);
boolean notFoundPreviously = getAndResetNotFoundStatus(editor);
@@ -52,10 +54,7 @@ public class SelectNextOccurrenceAction extends EditorAction {
}
FindManager findManager = FindManager.getInstance(project);
FindModel model = new FindModel();
model.setStringToFind(selectedText);
model.setCaseSensitive(true);
model.setWholeWordsOnly(wholeWordSearch);
FindModel model = getFindModel(selectedText, wholeWordSearch);
findManager.setFindWasPerformed();
findManager.setFindNextModel(model);
@@ -63,18 +62,13 @@ public class SelectNextOccurrenceAction extends EditorAction {
int searchStartOffset = notFoundPreviously ? 0 : caret.getSelectionEnd();
FindResult findResult = findManager.findString(editor.getDocument().getCharsSequence(), searchStartOffset, model);
if (findResult.isStringFound()) {
int newCaretOffset = caret.getOffset() - caret.getSelectionStart() + findResult.getStartOffset();
EditorActionUtil.makePositionVisible(editor, newCaretOffset);
Caret newCaret = editor.getCaretModel().addCaret(editor.offsetToVisualPosition(newCaretOffset));
if (newCaret == null) {
boolean caretAdded = FindUtil.selectSearchResultInEditor(editor, findResult, caret.getOffset() - caret.getSelectionStart());
if (!caretAdded) {
// this means that the found occurence is already selected
if (notFoundPreviously) {
setNotFoundStatus(editor); // to make sure we won't show hint anymore if there are no more occurrences
}
}
else {
setSelection(editor, newCaret, findResult);
}
}
else {
setNotFoundStatus(editor);
@@ -90,5 +84,10 @@ public class SelectNextOccurrenceAction extends EditorAction {
}
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
@Override
protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
return new AddOccurrenceAction(searchComponent);
}
}
}
@@ -19,8 +19,11 @@ import com.intellij.codeInsight.editorActions.SelectWordUtil;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.find.EditorSearchComponent;
import com.intellij.find.FindBundle;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.find.FindModel;
import com.intellij.find.editorHeaderActions.EditorHeaderAction;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorLastActionTracker;
@@ -96,4 +99,33 @@ abstract public class SelectOccurrencesActionHandler extends EditorActionHandler
String lastActionId = EditorLastActionTracker.getInstance().getLastActionId();
return SELECT_ACTIONS.contains(lastActionId);
}
protected static FindModel getFindModel(String text, boolean wholeWords) {
FindModel model = new FindModel();
model.setStringToFind(text);
model.setCaseSensitive(true);
model.setWholeWordsOnly(wholeWords);
return model;
}
protected boolean executeEquivalentFindPanelAction(Editor editor, DataContext context) {
if (editor.getHeaderComponent() instanceof EditorSearchComponent) {
EditorSearchComponent searchComponent = (EditorSearchComponent)editor.getHeaderComponent();
EditorHeaderAction action = getEquivalentFindPanelAction(searchComponent);
if (action != null) {
Presentation presentation = new Presentation();
AnActionEvent event = new AnActionEvent(null, context, ActionPlaces.MAIN_MENU, presentation, ActionManager.getInstance(), 0);
action.update(event);
if (presentation.isEnabled()) {
action.actionPerformed(event);
return true;
}
}
}
return false;
}
protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
return null;
}
}
@@ -15,6 +15,9 @@
*/
package com.intellij.openapi.editor.actions;
import com.intellij.find.EditorSearchComponent;
import com.intellij.find.editorHeaderActions.EditorHeaderAction;
import com.intellij.find.editorHeaderActions.RemoveOccurrenceAction;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
@@ -35,6 +38,8 @@ public class UnselectPreviousOccurrenceAction extends EditorAction {
@Override
public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
if (executeEquivalentFindPanelAction(editor, dataContext)) return;
if (editor.getCaretModel().getCaretCount() > 1) {
editor.getCaretModel().removeCaret(editor.getCaretModel().getPrimaryCaret());
}
@@ -44,5 +49,10 @@ public class UnselectPreviousOccurrenceAction extends EditorAction {
getAndResetNotFoundStatus(editor);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
@Override
protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
return new RemoveOccurrenceAction(searchComponent);
}
}
}
@@ -110,7 +110,7 @@ action.EditorMoveDownAndScrollWithSelection.text=Move Down and Scroll with Selec
action.EditorAddOrRemoveCaret.text=Add or Remove Caret
action.EditorCloneCaretBelow.text=Clone Caret Below
action.EditorCloneCaretAbove.text=Clone Caret Above
action.SelectNextOccurrence.text=Select Next Occurrence
action.SelectNextOccurrence.text=Add Selection for Next Occurrence
action.SelectAllOccurrences.text=Select All Occurrences
action.UnselectPreviousOccurrence.text=Unselect Occurrence
action.EditorToggleStickySelection.text=Toggle Sticky Selection