replace: exclusion based on range-markers. bug in smart-update: reusable hightlighter must be VALID. clean-up replace denying.

This commit is contained in:
andrey zaytsev
2011-05-20 15:43:37 +04:00
parent d808dc1314
commit d3c7943afc
4 changed files with 54 additions and 55 deletions
@@ -113,16 +113,6 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec
@Override
public void replaceAllPerformed(Editor e) { }
@Override
public void replaceDenied() {
updateReplaceButton();
}
@Override
public void replaceAllowed() {
updateReplaceButton();
}
private void updateReplaceButton() {
if (myReplaceButton != null) {
myReplaceButton.setEnabled(mySearchResults != null && mySearchResults.getCursor() != null &&
@@ -50,10 +50,13 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele
private static final Key<Object> IN_SELECTION_KEY = Key.create("LivePreview.IN_SELECTION_KEY");
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<Object> MARKER_USED = Key.create("LivePreview.MARKER_USED");
private static final Object YES = new Object();
@Override
public void selectionChanged(SelectionEvent e) {
@@ -361,10 +364,11 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele
private RangeHighlighter highlightRange(TextRange textRange, TextAttributes attributes, Collection<RangeHighlighter> highlighters) {
if (myInSmartUpdate) {
for (RangeHighlighter highlighter : myHighlighters) {
if (highlighter.getStartOffset() == textRange.getStartOffset() && highlighter.getEndOffset() == textRange.getEndOffset()) {
if (highlighter.isValid() && highlighter.getStartOffset() == textRange.getStartOffset() && highlighter.getEndOffset() == textRange.getEndOffset()) {
if (attributes.equals(highlighter.getTextAttributes())) {
if (myInSmartUpdate) {
highlighter.putUserData(MARKER_USED, new Object());
highlighter.putUserData(MARKER_USED, YES);
if (highlighters != myHighlighters) {
highlighters.add(highlighter);
}
return highlighter;
}
@@ -373,7 +377,7 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele
}
final RangeHighlighter highlighter = doHightlightRange(textRange, attributes, highlighters);
if (myInSmartUpdate) {
highlighter.putUserData(MARKER_USED, new Object());
highlighter.putUserData(MARKER_USED, YES);
}
return highlighter;
}
@@ -384,8 +388,16 @@ public class LivePreview extends DocumentAdapter implements ReplacementView.Dele
highlightManager.addRangeHighlight(mySearchResults.getEditor(),
textRange.getStartOffset(), textRange.getEndOffset(),
attributes, false, dummy);
highlighters.addAll(dummy);
return dummy.get(0);
final RangeHighlighter h = dummy.get(0);
for (RangeHighlighter highlighter : highlighters) {
if (h.getStartOffset() == highlighter.getStartOffset() && h.getEndOffset() == highlighter.getEndOffset() &&
h.getTextAttributes().equals(highlighter.getTextAttributes())) {
return h;
}
}
highlighters.add(h);
return h;
}
@@ -64,7 +64,6 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil
@Override
public void searchResultsUpdated(SearchResults sr) {
//setReplaceDenied(false);
}
@Override
@@ -89,24 +88,9 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil
return myReplaceDenied;
}
public void setReplaceDenied(final boolean replaceDenied) {
boolean changed = replaceDenied != myReplaceDenied;
myReplaceDenied = replaceDenied;
if (changed && myReplaceListener != null) {
if (replaceDenied) {
myReplaceListener.replaceDenied();
}
else {
myReplaceListener.replaceAllowed();
}
}
}
public interface ReplaceListener {
void replacePerformed(LiveOccurrence occurrence, final String replacement, final Editor editor);
void replaceAllPerformed(Editor e);
void replaceDenied();
void replaceAllowed();
}
private ReplaceListener myReplaceListener;
@@ -146,17 +130,6 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil
Runnable request = new Runnable() {
@Override
public void run() {
Runnable denyReplace = new Runnable() {
@Override
public void run() {
//setReplaceDenied(true);
}
};
if (unitTestMode) {
denyReplace.run();
} else {
ApplicationManager.getApplication().invokeAndWait(denyReplace, modalityState);
}
mySearchResults.updateThreadSafe(copy, allowedToChangedEditorSelection, null, stamp);
}
};
@@ -213,10 +186,8 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil
if (myReplaceListener != null) {
myReplaceListener.replacePerformed(occurrence, replacement, editor);
}
//setReplaceDenied(true);
myLivePreview.inSmartUpdate();
mySearchResults.updateThreadSafe(findModel, true, result, mySearchResults.getStamp());
//myLivePreview.supressUpdate();
return result;
}
@@ -251,9 +222,8 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil
@Override
public boolean shouldReplace(TextRange range, String replace) {
for (LiveOccurrence o : mySearchResults.getExcluded()) {
TextRange primaryRange = o.getPrimaryRange();
if (primaryRange.equals(range)) {
for (RangeMarker r : mySearchResults.getExcluded()) {
if (r.getStartOffset() == range.getStartOffset() && r.getEndOffset() == range.getEndOffset()) {
return false;
}
}
@@ -7,10 +7,12 @@ 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.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
@@ -34,7 +36,7 @@ public class SearchResults {
private List<LiveOccurrence> myOccurrences = new ArrayList<LiveOccurrence>();
private Set<LiveOccurrence> myExcluded = new HashSet<LiveOccurrence>();
private Set<RangeMarker> myExcluded = new HashSet<RangeMarker>();
private Editor myEditor;
private FindModel myFindModel;
@@ -72,19 +74,32 @@ public class SearchResults {
}
public boolean isExcluded(LiveOccurrence occurrence) {
return myExcluded.contains(occurrence);
for (RangeMarker rangeMarker : myExcluded) {
if (rangeMarker.getStartOffset() == occurrence.getPrimaryRange().getStartOffset() && rangeMarker.getEndOffset() == occurrence.getPrimaryRange().getEndOffset()) {
return true;
}
}
return false;
}
public void exclude(LiveOccurrence occurrence) {
if (myExcluded.contains(occurrence)) {
myExcluded.remove(occurrence);
} else {
myExcluded.add(occurrence);
boolean include = false;
final TextRange r = occurrence.getPrimaryRange();
for (RangeMarker rangeMarker : myExcluded) {
if (rangeMarker.getStartOffset() == r.getStartOffset() && rangeMarker.getEndOffset() == r.getEndOffset()) {
myExcluded.remove(rangeMarker);
rangeMarker.dispose();
include = true;
break;
}
}
if (!include) {
myExcluded.add(myEditor.getDocument().createRangeMarker(r.getStartOffset(), r.getEndOffset(), true));
}
notifyChanged();
}
public Set<LiveOccurrence> getExcluded() {
public Set<RangeMarker> getExcluded() {
return myExcluded;
}
@@ -230,6 +245,7 @@ public class SearchResults {
myFindModel = findModel;
updateCursor(oldCursorRange, next);
updateExcluded();
myActualFound = size;
notifyChanged();
if (oldCursorRange == null || myCursor == null || !myCursor.getPrimaryRange().equals(oldCursorRange)) {
@@ -238,6 +254,17 @@ public class SearchResults {
}
}
private void updateExcluded() {
Set<RangeMarker> invalid = new HashSet<RangeMarker>();
for (RangeMarker marker : myExcluded) {
if (!marker.isValid()) {
invalid.add(marker);
marker.dispose();
}
}
myExcluded.removeAll(invalid);
}
private void updateCursor(@Nullable TextRange oldCursorRange, @Nullable TextRange next) {
boolean justReplaced = next != null;
if (justReplaced || !tryToRepairOldCursor(oldCursorRange)) {