diff options
Diffstat (limited to 'platform/lang-impl/src/com/intellij/find/impl/livePreview')
4 files changed, 185 insertions, 118 deletions
diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java index c20b5925721d..4ba97e0151e5 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java @@ -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() { @@ -496,6 +461,8 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search new Processor<RangeHighlighterEx>() { @Override public boolean process(RangeHighlighterEx highlighter) { + if (!highlighter.getEditorFilter().avaliableIn(mySearchResults.getEditor())) return true; + TextAttributes textAttributes = highlighter.getTextAttributes(); if (highlighter.getUserData(SEARCH_MARKER) != null && diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewController.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewController.java index 8368f1b2f2aa..94a6c3f9c1bc 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewController.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewController.java @@ -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); } } diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java index dff4989bb2f6..39b17dd2acc8 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/SearchResults.java @@ -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(); } @@ -462,25 +461,6 @@ public class SearchResults implements DocumentListener { } @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(); return firstOccurrenceBeforeOffset(offset); @@ -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(); - } - if (next == null) { - if (processFromTheBeginning) { - if (hasMatches()) { - next = getOccurrences().get(getOccurrences().size()-1); + else { + myCursor = null; + } + notifyCursorMoved(); + } + 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(); } } } diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/SelectionManager.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/SelectionManager.java new file mode 100644 index 000000000000..50f37927c506 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/SelectionManager.java @@ -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; + } +} |