IDEA-80056 Column selection mode improvement

implementation of select/unselect next occurrence actions
This commit is contained in:
Dmitry Batrak
2014-02-19 18:54:27 +04:00
parent 62ec1ba200
commit 718ee80dd4
14 changed files with 591 additions and 4 deletions
@@ -0,0 +1,38 @@
/*
* 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.openapi.actionSystem;
import com.intellij.openapi.application.ApplicationManager;
import org.jetbrains.annotations.Nullable;
/**
* This component provides the notion of last action. Its purpose is to be able to determine whether some action was performed right after
* another specific action.
* <p>
* It's supposed to be used from EDT only.
*/
public abstract class LastActionTracker {
public static LastActionTracker getInstance() {
return ApplicationManager.getApplication().getComponent(LastActionTracker.class);
}
/**
* Returns the id of the previously invoked action or <code>null</code>, if no history exists yet, or last user activity was of
* non-action type, like mouse clicking in editor or text typing.
*/
@Nullable
public abstract String getLastActionId();
}
@@ -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.
@@ -65,7 +65,7 @@ public class SelectWordUtil {
return SELECTIONERS;
}
private static final CharCondition JAVA_IDENTIFIER_PART_CONDITION = new CharCondition() {
public static final CharCondition JAVA_IDENTIFIER_PART_CONDITION = new CharCondition() {
@Override
public boolean value(char ch) {
return Character.isJavaIdentifierPart(ch);
@@ -0,0 +1,156 @@
/*
* 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.openapi.editor.actions;
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.FindBundle;
import com.intellij.find.FindManager;
import com.intellij.find.FindModel;
import com.intellij.find.FindResult;
import com.intellij.openapi.actionSystem.LastActionTracker;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.ui.LightweightHint;
import org.jetbrains.annotations.Nullable;
public class SelectNextOccurrenceAction extends EditorAction {
private static final Key<Boolean> NOT_FOUND = Key.create("select.next.occurence.not.found");
private static final Key<Boolean> WHOLE_WORDS = Key.create("select.next.occurence.whole.words");
protected SelectNextOccurrenceAction() {
super(new Handler());
}
private static class Handler extends EditorActionHandler {
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return super.isEnabled(editor, dataContext) && editor.getProject() != null && editor.getCaretModel().supportsMultipleCarets();
}
@Override
public void execute(Editor editor, @Nullable Caret c, DataContext dataContext) {
Caret caret = c == null ? editor.getCaretModel().getPrimaryCaret() : c;
TextRange wordSelectionRange = SelectWordUtil.getWordSelectionRange(editor.getDocument().getCharsSequence(),
caret.getOffset(),
SelectWordUtil.JAVA_IDENTIFIER_PART_CONDITION);
boolean notFoundPreviously = getAndResetNotFoundStatus(editor);
Boolean wholeWordSearch = isWholeWordSearch(editor);
if (caret.hasSelection()) {
Project project = editor.getProject();
String selectedText = caret.getSelectedText();
if (project == null || selectedText == null) {
return;
}
FindManager findManager = FindManager.getInstance(project);
if (wholeWordSearch == null) {
wholeWordSearch = wordSelectionRange != null
&& wordSelectionRange.getStartOffset() == caret.getSelectionStart()
&& wordSelectionRange.getEndOffset() == caret.getSelectionEnd();
setWholeWordSearch(editor, wholeWordSearch);
}
FindModel model = new FindModel();
model.setStringToFind(caret.getSelectedText());
model.setCaseSensitive(true);
model.setWholeWordsOnly(wholeWordSearch);
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) {
// 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);
showHint(editor);
}
}
else {
if (wordSelectionRange == null) {
return;
}
setSelection(editor, caret, wordSelectionRange);
setWholeWordSearch(editor, true);
}
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
private static void setSelection(Editor editor, Caret caret, TextRange selectionRange) {
EditorActionUtil.makePositionVisible(editor, selectionRange.getStartOffset());
EditorActionUtil.makePositionVisible(editor, selectionRange.getEndOffset());
caret.setSelection(selectionRange.getStartOffset(), selectionRange.getEndOffset());
}
private static void showHint(final Editor editor) {
String message = FindBundle.message("select.next.occurence.not.found.message");
final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message));
HintManagerImpl.getInstanceImpl().showEditorHint(hint,
editor,
HintManager.UNDER,
HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING,
0,
false);
}
private static boolean getAndResetNotFoundStatus(Editor editor) {
boolean status = editor.getUserData(NOT_FOUND) != null;
editor.putUserData(NOT_FOUND, null);
return status && isRepeatedActionInvocation();
}
private static void setNotFoundStatus(Editor editor) {
editor.putUserData(NOT_FOUND, Boolean.TRUE);
}
private static Boolean isWholeWordSearch(Editor editor) {
if (!isRepeatedActionInvocation()) {
editor.putUserData(WHOLE_WORDS, null);
}
return editor.getUserData(WHOLE_WORDS);
}
private static void setWholeWordSearch(Editor editor, boolean isWholeWordSearch) {
editor.putUserData(WHOLE_WORDS, isWholeWordSearch);
}
private static boolean isRepeatedActionInvocation() {
String lastActionId = LastActionTracker.getInstance().getLastActionId();
return IdeActions.ACTION_SELECT_NEXT_OCCURENCE.equals(lastActionId) || IdeActions.ACTION_UNSELECT_LAST_OCCURENCE.equals(lastActionId);
}
}
}
@@ -0,0 +1,48 @@
/*
* 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.openapi.editor.actions;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import org.jetbrains.annotations.Nullable;
public class UnselectLastOccurrenceAction extends EditorAction {
protected UnselectLastOccurrenceAction() {
super(new Handler());
}
private static class Handler extends EditorActionHandler {
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return super.isEnabled(editor, dataContext) && editor.getCaretModel().supportsMultipleCarets();
}
@Override
public void execute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
if (editor.getCaretModel().getAllCarets().size() > 1) {
editor.getCaretModel().removeCaret(editor.getCaretModel().getPrimaryCaret());
}
else {
editor.getSelectionModel().removeSelection();
}
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
}
}
@@ -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.
@@ -114,6 +114,8 @@ public interface IdeActions {
@NonNls String ACTION_FIND = "Find";
@NonNls String ACTION_FIND_NEXT = "FindNext";
@NonNls String ACTION_FIND_PREVIOUS = "FindPrevious";
@NonNls String ACTION_SELECT_NEXT_OCCURENCE = "SelectNextOccurrence";
@NonNls String ACTION_UNSELECT_LAST_OCCURENCE = "UnselectLastOccurrence";
@NonNls String ACTION_COMPILE = "Compile";
@NonNls String ACTION_COMPILE_PROJECT = "CompileProject";
@NonNls String ACTION_MAKE_MODULE = "MakeModule";
@@ -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.
@@ -587,6 +587,7 @@ public class HintManagerImpl extends HintManager implements Disposable {
@NotNull LogicalPosition pos2,
@PositionFlags short constraint,
boolean showByBalloon) {
if (ApplicationManager.getApplication().isUnitTestMode()) return new Point();
Point p = _getHintPosition(hint, editor, pos1, pos2, constraint, showByBalloon);
JLayeredPane layeredPane = editor.getComponent().getRootPane().getLayeredPane();
Dimension hintSize = hint.getComponent().getPreferredSize();
@@ -0,0 +1,116 @@
/*
* 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.openapi.actionSystem.impl;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.AnActionListener;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.event.EditorEventMulticaster;
import com.intellij.openapi.editor.event.EditorMouseEvent;
import com.intellij.openapi.editor.event.EditorMouseListener;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class LastActionTrackerImpl extends LastActionTracker implements ApplicationComponent, AnActionListener, EditorMouseListener {
private final ActionManager myActionManager;
private final EditorEventMulticaster myEditorEventMulticaster;
private String myLastActionId;
private Editor myLastEditor;
LastActionTrackerImpl(ActionManager actionManager, EditorFactory editorFactory) {
myActionManager = actionManager;
myEditorEventMulticaster = editorFactory.getEventMulticaster();
}
@Override
public void initComponent() {
myActionManager.addAnActionListener(this);
myEditorEventMulticaster.addEditorMouseListener(this);
}
@Override
public void disposeComponent() {
myEditorEventMulticaster.removeEditorMouseListener(this);
myActionManager.removeAnActionListener(this);
}
@NotNull
@Override
public String getComponentName() {
return "LastActionTracker";
}
@Override
@Nullable
public String getLastActionId() {
return myLastActionId;
}
@Override
public void beforeActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) {
if (CommonDataKeys.EDITOR.getData(dataContext) != myLastEditor) {
resetLastAction();
}
}
@Override
public void afterActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) {
myLastActionId = getActionId(action);
myLastEditor = CommonDataKeys.EDITOR.getData(dataContext);
}
@Override
public void beforeEditorTyping(char c, DataContext dataContext) {
resetLastAction();
}
@Override
public void mousePressed(EditorMouseEvent e) {
resetLastAction();
}
@Override
public void mouseClicked(EditorMouseEvent e) {
resetLastAction();
}
@Override
public void mouseReleased(EditorMouseEvent e) {
resetLastAction();
}
@Override
public void mouseEntered(EditorMouseEvent e) {
}
@Override
public void mouseExited(EditorMouseEvent e) {
}
private String getActionId(AnAction action) {
return action instanceof ActionStub ? ((ActionStub)action).getId() : myActionManager.getId(action);
}
private void resetLastAction() {
myLastActionId = null;
myLastEditor = null;
}
}
@@ -784,4 +784,21 @@ public class EditorActionUtil {
public static void moveCaretToLineStartIgnoringSoftWraps(@NotNull Editor editor) {
editor.getCaretModel().moveToLogicalPosition(EditorUtil.calcCaretLineRange(editor).first);
}
/**
* This method will make required expansions of collapsed region to make given offset 'visible'.
*/
public static void makePositionVisible(@NotNull final Editor editor, final int offset) {
FoldingModel foldingModel = editor.getFoldingModel();
FoldRegion collapsedRegionAtOffset;
while ((collapsedRegionAtOffset = foldingModel.getCollapsedRegionAtOffset(offset)) != null) {
final FoldRegion region = collapsedRegionAtOffset;
foldingModel.runBatchFoldingOperation(new Runnable() {
@Override
public void run() {
region.setExpanded(true);
}
});
}
}
}
@@ -107,6 +107,8 @@ action.EditorMoveUpAndScrollWithSelection.text=Move Up and Scroll with Selection
action.EditorMoveDownAndScrollWithSelection.text=Move Down and Scroll with Selection
action.EditorCloneCaretBelow.text=Clone Caret Below
action.EditorCloneCaretAbove.text=Clone Caret Above
action.SelectNextOccurence.text=Select Next Occurence
action.UnselectLastOccurence.text=Unselect Last Occurence
action.EditorToggleStickySelection.text=Toggle Sticky Selection
action.EditorSwapSelectionBoundaries.text=Swap selection boundaries
action.EditorLineStart.text=Move Caret to Line Start
@@ -7,6 +7,7 @@ find.search.again.from.top.hotkey.message={0}, press {1} to search from the top
find.search.again.from.top.action.message={0}, perform \"Find Next\" again to search from the top
find.search.again.from.bottom.hotkey.message={0}, press {1} to search from the bottom
find.search.again.from.bottom.action.message={0}, perform \"Find Previous\" again to search from the bottom
select.next.occurence.not.found.message=Not found, try again to search from top
find.no.usages.at.cursor.error=Cannot search for usages. \nPosition to an element to find usages for, and try again.
find.what.group=Find
@@ -21,6 +21,10 @@
<interface-class>com.intellij.openapi.actionSystem.ActionManager</interface-class>
<implementation-class>com.intellij.openapi.actionSystem.impl.ActionManagerImpl</implementation-class>
</component>
<component>
<interface-class>com.intellij.openapi.actionSystem.LastActionTracker</interface-class>
<implementation-class>com.intellij.openapi.actionSystem.impl.LastActionTrackerImpl</implementation-class>
</component>
<component>
<interface-class>com.intellij.openapi.keymap.KeymapManager</interface-class>
<implementation-class>com.intellij.openapi.keymap.impl.KeymapManagerImpl</implementation-class>
@@ -112,6 +112,12 @@
<action id="FindWordAtCaret">
<keyboard-shortcut first-keystroke="control F3"/>
</action>
<action id="SelectNextOccurrence">
<keyboard-shortcut first-keystroke="alt N"/>
</action>
<action id="UnselectLastOccurrence">
<keyboard-shortcut first-keystroke="alt shift N"/>
</action>
<action id="GotoDeclaration">
<keyboard-shortcut first-keystroke="control B"/>
<mouse-shortcut keystroke="ctrl button1"/>
@@ -225,6 +225,8 @@
<action id="FindNext" class="com.intellij.ide.actions.SearchAgainAction"/>
<action id="FindPrevious" class="com.intellij.ide.actions.SearchBackAction"/>
<action id="FindWordAtCaret" class="com.intellij.openapi.editor.actions.FindWordAtCaretAction"/>
<action id="SelectNextOccurrence" class="com.intellij.openapi.editor.actions.SelectNextOccurrenceAction"/>
<action id="UnselectLastOccurrence" class="com.intellij.openapi.editor.actions.UnselectLastOccurrenceAction"/>
<separator/>
<action id="FindInPath" class="com.intellij.find.actions.FindInPathAction"/>
<action id="ReplaceInPath" class="com.intellij.find.actions.ReplaceInPathAction"/>
@@ -0,0 +1,194 @@
/*
* 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.openapi.editor.actions;
import com.intellij.codeInsight.hint.EditorHintListener;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.FoldRegion;
import com.intellij.openapi.editor.FoldingModel;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.testFramework.EditorTestUtil;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
import com.intellij.ui.LightweightHint;
public class SelectUnselectOccurrenceActionsTest extends LightPlatformCodeInsightFixtureTestCase {
private int hintCount;
@Override
public void setUp() throws Exception {
super.setUp();
EditorTestUtil.enableMultipleCarets();
EditorHintListener listener = new EditorHintListener() {
@Override
public void hintShown(Project project, LightweightHint hint, int flags) {
hintCount++;
}
};
ApplicationManager.getApplication().getMessageBus().connect(myTestRootDisposable).subscribe(EditorHintListener.TOPIC, listener);
}
@Override
public void tearDown() throws Exception {
EditorTestUtil.disableMultipleCarets();
super.tearDown();
}
public void testNoInitialSelection() throws Exception {
init("some t<caret>ext\n" +
"some texts\n" +
"another text here"
);
executeAction();
checkResult("some <selection>t<caret>ext</selection>\n" +
"some texts\n" +
"another text here");
assertEquals(0, hintCount);
}
public void testInitialWholeWordSelection() throws Exception {
init("some <selection>t<caret>ext</selection>\n" +
"some texts\n" +
"another text here");
executeAction();
checkResult("some <selection>t<caret>ext</selection>\n" +
"some texts\n" +
"another <selection>t<caret>ext</selection> here");
assertEquals(0, hintCount);
}
public void testShowingHint() throws Exception {
init("some <selection>t<caret>ext</selection>\n" +
"some texts\n" +
"another <selection>t<caret>ext</selection> here");
executeAction();
assertEquals(1, hintCount);
checkResult("some <selection>t<caret>ext</selection>\n" +
"some texts\n" +
"another <selection>t<caret>ext</selection> here");
executeAction();
assertEquals(1, hintCount);
checkResult("some <selection>t<caret>ext</selection>\n" +
"some texts\n" +
"another <selection>t<caret>ext</selection> here");
}
public void testRevert() throws Exception {
init("some <selection>t<caret>ext</selection>\n" +
"some texts\n" +
"another <selection>t<caret>ext</selection> here");
executeReverseAction();
checkResult("some <selection>t<caret>ext</selection>\n" +
"some texts\n" +
"another text here");
assertEquals(0, hintCount);
}
public void testRevertSingleSelection() throws Exception {
init("some <selection>t<caret>ext</selection>\n" +
"some texts\n" +
"another text here");
executeReverseAction();
checkResult("some t<caret>ext\n" +
"some texts\n" +
"another text here");
assertEquals(0, hintCount);
}
public void testSelectAfterHint() throws Exception {
init("some text\n" +
"some texts\n" +
"another <selection>t<caret>ext</selection> here");
executeAction();
checkResult("some text\n" +
"some texts\n" +
"another <selection>t<caret>ext</selection> here");
assertEquals(1, hintCount);
executeAction();
checkResult("some <selection>t<caret>ext</selection>\n" +
"some texts\n" +
"another <selection>t<caret>ext</selection> here");
assertEquals(1, hintCount);
}
public void testInitialNonWholeWordSelection() throws Exception {
init("some <selection>t<caret>ex</selection>t\n" +
"some texts\n" +
"another text here");
executeAction();
checkResult("some <selection>t<caret>ex</selection>t\n" +
"some <selection>t<caret>ex</selection>ts\n" +
"another text here");
executeAction();
checkResult("some <selection>t<caret>ex</selection>t\n" +
"some <selection>t<caret>ex</selection>ts\n" +
"another <selection>t<caret>ex</selection>t here");
assertEquals(0, hintCount);
}
public void testWholeWordinessIsRememberedAtStart() throws Exception {
init("some <selection>text<caret></selection>s\n" +
"another text\n" +
"some other texts");
executeAction();
checkResult("some <selection>text<caret></selection>s\n" +
"another <selection>text<caret></selection>\n" +
"some other texts");
executeAction();
checkResult("some <selection>text<caret></selection>s\n" +
"another <selection>text<caret></selection>\n" +
"some other <selection>text<caret></selection>s");
assertEquals(0, hintCount);
}
public void testOccurrenceInCollapsedRegion() throws Exception {
init("normal <selection><caret>line</selection>\n" +
"collapsed line");
final FoldingModel foldingModel = myFixture.getEditor().getFoldingModel();
final Document document = myFixture.getEditor().getDocument();
foldingModel.runBatchFoldingOperation(new Runnable() {
@Override
public void run() {
FoldRegion foldRegion = foldingModel.addFoldRegion(document.getLineStartOffset(1), document.getLineEndOffset(1), "...");
assertNotNull(foldRegion);
foldRegion.setExpanded(false);
}
});
executeAction();
checkResult("normal <selection><caret>line</selection>\n" +
"collapsed <selection><caret>line</selection>");
FoldRegion[] foldRegions = foldingModel.getAllFoldRegions();
assertEquals(1, foldRegions.length);
assertTrue(foldRegions[0].isExpanded());
}
private void init(String text) {
myFixture.configureByText(FileTypes.PLAIN_TEXT, text);
}
private void checkResult(String text) {
myFixture.checkResult(text);
}
private void executeAction() {
myFixture.performEditorAction("SelectNextOccurrence");
}
private void executeReverseAction() {
myFixture.performEditorAction("UnselectLastOccurrence");
}
}