diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java index e382a76fa679..ab0f53555ac9 100644 --- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java +++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java @@ -36,6 +36,7 @@ import com.intellij.openapi.editor.event.SelectionListener; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.LightColors; @@ -93,6 +94,8 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec private MyLivePreviewController myLivePreviewController; private LivePreview myLivePreview; + private boolean mySupressUpdate = false; + private boolean myListeningSelection = false; private SearchResults mySearchResults; @@ -650,7 +653,12 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec private void initLivePreview() { myDocumentListener = new DocumentAdapter() { public void documentChanged(final DocumentEvent e) { - updateResults(false); + if (!mySupressUpdate) { + myLivePreview.inSmartUpdate(); + updateResults(false); + } else { + mySupressUpdate = false; + } } }; @@ -787,8 +795,12 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec } public void performReplace() { + mySupressUpdate = true; String replacement = getStringToReplace(myEditor, mySearchResults.getCursor()); - performReplace(mySearchResults.getCursor(), replacement, myEditor); + final TextRange textRange = performReplace(mySearchResults.getCursor(), replacement, myEditor); + if (textRange == null) { + mySupressUpdate = false; + } //getFocusBack(); addTextToRecents(myReplaceField) ; } 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 ae01bf38dc45..98dc5b45e4e4 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 @@ -51,12 +51,23 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele private static final Object IN_SELECTION1 = new Object(); private static final Object IN_SELECTION2 = new Object(); private boolean myListeningSelection = false; + private boolean mySuppressedUpdate = false; + private boolean myInSmartUpdate = false; + private static final Key MARKER_USED = Key.create("LivePreview.MARKER_USED"); @Override public void selectionChanged(SelectionEvent e) { updateInSelectionHighlighters(); } + public void supressUpdate() { + mySuppressedUpdate = true; + } + + public void inSmartUpdate() { + myInSmartUpdate = true; + } + public interface Delegate { @Nullable @@ -120,10 +131,38 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele @Override public void searchResultsUpdated(SearchResults sr) { if (mySearchResults.getProject().isDisposed()) return; - removeFromEditor(mySearchResults.getEditor()); + if (mySuppressedUpdate) { + mySuppressedUpdate = false; + return; + } + if (!myInSmartUpdate) { + removeFromEditor(); + } highlightUsages(); updateCursorHighlighting(false); + if (myInSmartUpdate) { + clearUnusedHightlighters(); + myInSmartUpdate = false; + } + } + + private void clearUnusedHightlighters() { + Set unused = new com.intellij.util.containers.HashSet(); + for (RangeHighlighter highlighter : myHighlighters) { + if (highlighter.getUserData(MARKER_USED) == null) { + unused.add(highlighter); + } else { + highlighter.putUserData(MARKER_USED, null); + } + } + myHighlighters.removeAll(unused); + Project project = mySearchResults.getProject(); + if (!project.isDisposed()) { + for (RangeHighlighter highlighter : unused) { + HighlightManager.getInstance(project).removeSegmentHighlighter(mySearchResults.getEditor(), highlighter); + } + } } @Override @@ -133,7 +172,7 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele } public void editorChanged(SearchResults sr, Editor oldEditor) { - removeFromEditor(mySearchResults.getEditor()); + removeFromEditor(); oldEditor.getDocument().removeDocumentListener(this); mySearchResults.getEditor().getDocument().addDocumentListener(this); } @@ -187,14 +226,15 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele public void cleanUp() { - removeFromEditor(mySearchResults.getEditor()); + removeFromEditor(); } public void dispose() { mySearchResults.removeListener(this); } - private void removeFromEditor(Editor editor) { + private void removeFromEditor() { + Editor editor = mySearchResults.getEditor(); if (myReplacementBalloon != null) { myReplacementBalloon.hide(); } @@ -244,7 +284,7 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele mySearchResults.getEditor().getSelectionModel().addSelectionListener(this); myListeningSelection = true; } - + } private void updateInSelectionHighlighters() { @@ -319,6 +359,26 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele @NotNull private RangeHighlighter highlightRange(TextRange textRange, TextAttributes attributes, Collection highlighters) { + if (myInSmartUpdate) { + for (RangeHighlighter highlighter : myHighlighters) { + if (highlighter.getStartOffset() == textRange.getStartOffset() && highlighter.getEndOffset() == textRange.getEndOffset()) { + if (attributes.equals(highlighter.getTextAttributes())) { + if (myInSmartUpdate) { + highlighter.putUserData(MARKER_USED, new Object()); + } + return highlighter; + } + } + } + } + final RangeHighlighter highlighter = doHightlightRange(textRange, attributes, highlighters); + if (myInSmartUpdate) { + highlighter.putUserData(MARKER_USED, new Object()); + } + return highlighter; + } + + private RangeHighlighter doHightlightRange(TextRange textRange, TextAttributes attributes, Collection highlighters) { HighlightManager highlightManager = HighlightManager.getInstance(mySearchResults.getProject()); final ArrayList dummy = new ArrayList(); highlightManager.addRangeHighlight(mySearchResults.getEditor(), diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java index 2b8861bbf30c..d8b38eafddfb 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java @@ -64,7 +64,7 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil @Override public void searchResultsUpdated(SearchResults sr) { - setReplaceDenied(false); + //setReplaceDenied(false); } @Override @@ -149,7 +149,7 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil Runnable denyReplace = new Runnable() { @Override public void run() { - setReplaceDenied(true); + //setReplaceDenied(true); } }; if (unitTestMode) { @@ -213,8 +213,10 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil if (myReplaceListener != null) { myReplaceListener.replacePerformed(occurrence, replacement, editor); } - setReplaceDenied(true); + //setReplaceDenied(true); + myLivePreview.inSmartUpdate(); mySearchResults.updateThreadSafe(findModel, true, result, mySearchResults.getStamp()); + //myLivePreview.supressUpdate(); return result; }