correctly adding/removing listeners in documents

This commit is contained in:
Anton Makeev
2010-10-08 18:14:43 +04:00
parent 132c2eed78
commit e4c2ba6154
@@ -77,6 +77,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
private final PropertyChangeSupport myPropertyChangeSupport = new PropertyChangeSupport(this);
private volatile MarkupModelEx myMarkupModel;
private DocumentListener[] myCachedDocumentListeners;
private final List<EditReadOnlyListener> myReadOnlyListeners = new ArrayList<EditReadOnlyListener>(1);
private int myCheckGuardedBlocks = 0;
@@ -468,12 +469,11 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
return null; // suppress events in shutdown hook
}
DocumentEvent event = new DocumentEventImpl(this, offset, oldString, newString, myModificationStamp, wholeTextReplaced);
//System.out.printf("%nbefore change: offset=%d, old text='%s', new text='%s', document modification stamp=%d%nDocument:'%s'%n",
// event.getOffset(), event.getOldFragment(), event.getNewFragment(), event.getDocument().getModificationStamp(),
// event.getDocument().getText());
for (int i = myDocumentListeners.size() - 1; i >= 0; i--) {
DocumentListener[] listeners = getCachedListeners();
for (int i = listeners.length - 1; i >= 0; i--) {
try {
myDocumentListeners.get(i).beforeDocumentChange(event);
listeners[i].beforeDocumentChange(event);
}
catch (Throwable e) {
LOG.error(e);
@@ -484,10 +484,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
return event;
}
@SuppressWarnings({"ForLoopReplaceableByForEach"})
private void changedUpdate(DocumentEvent event, long newModificationStamp) {
//System.out.printf("after change: new modification stamp=%d%ndocument='%s'%n", event.getDocument().getModificationStamp(),
// event.getDocument().getText());
if (ShutDownTracker.isShutdownHookRunning()) {
return; // suppress events in shutdown hook
}
@@ -497,10 +494,10 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
myLineSet.changedUpdate(event);
setModificationStamp(newModificationStamp);
// Don't use for-each in order to avoid unnecessary iterator construction during frequent document updates.
for (int i = 0; i < myDocumentListeners.size(); i++) {
DocumentListener[] listeners = getCachedListeners();
for (DocumentListener listener : listeners) {
try {
myDocumentListeners.get(i).documentChanged(event);
listener.documentChanged(event);
}
catch (Throwable e) {
LOG.error(e);
@@ -557,21 +554,9 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
public void addDocumentListener(@NotNull DocumentListener listener) {
myCachedDocumentListeners = null;
LOG.assertTrue(!myDocumentListeners.contains(listener), listener);
if (!(listener instanceof PrioritizedDocumentListener)) {
myDocumentListeners.add(listener);
return;
}
int i = Collections.binarySearch(myDocumentListeners, listener, PrioritizedDocumentListener.COMPARATOR);
if (i < 0) {
i = -i - 1;
}
if (i >= myDocumentListeners.size()) {
myDocumentListeners.add(listener);
}
else {
myDocumentListeners.add(i, listener);
}
myDocumentListeners.add(listener);
}
public void addDocumentListener(@NotNull final DocumentListener listener, @NotNull Disposable parentDisposable) {
@@ -584,6 +569,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
}
public void removeDocumentListener(@NotNull DocumentListener listener) {
myCachedDocumentListeners = null;
boolean success = myDocumentListeners.remove(listener);
LOG.assertTrue(success);
}
@@ -631,6 +617,15 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
return lineCount;
}
private DocumentListener[] getCachedListeners() {
if (myCachedDocumentListeners == null) {
Collections.sort(myDocumentListeners, PrioritizedDocumentListener.COMPARATOR);
myCachedDocumentListeners = myDocumentListeners.toArray(new DocumentListener[myDocumentListeners.size()]);
}
return myCachedDocumentListeners;
}
public void fireReadOnlyModificationAttempt() {
ApplicationManagerEx.getApplicationEx().assertReadAccessToDocumentsAllowed();
EditReadOnlyListener[] listeners = myReadOnlyListeners.toArray(