package org.vaadin.mideaas.editor;
import java.util.LinkedList;
import java.util.concurrent.CopyOnWriteArrayList;
import org.vaadin.aceeditor.AceEditor;
import org.vaadin.aceeditor.AceEditor.DiffEvent;
import org.vaadin.aceeditor.AceEditor.DiffListener;
import org.vaadin.aceeditor.ServerSideDocDiff;
import org.vaadin.aceeditor.client.AceDoc;
/**
* An {@link AceDoc} to be collaboratively edited by {@link AceEditor}s.
*
*/
public class SharedDoc implements DiffListener {
public interface Listener {
public void changed();
}
private final CopyOnWriteArrayList<Listener> listeners = new CopyOnWriteArrayList<Listener>();
private LinkedList<AceEditor> editors = new LinkedList<AceEditor>();
private AceDoc doc;
public SharedDoc(AceDoc doc) {
this.doc = doc;
}
public synchronized void attachEditor(final AceEditor editor) {
boolean wasReadonly = editor.isReadOnly();
editor.setReadOnly(false);
editor.setDoc(getDoc());
editor.setReadOnly(wasReadonly);
editors.add(editor);
editor.addDiffListener(this);
}
public synchronized void detachEditor(AceEditor editor) {
editors.remove(editor);
editor.removeDiffListener(this);
}
public void applyDiff(ServerSideDocDiff diff) {
if (diff.isIdentity()) {
return;
}
AceDoc newDoc = applyDiffNoFire(diff);
if (newDoc!=null) {
fireChanged();
}
}
private synchronized AceDoc applyDiffNoFire(ServerSideDocDiff diff) {
return setDocNoFire(diff.applyTo(doc));
}
synchronized AceDoc setDocNoFire(final AceDoc doc) {
if (this.doc.equals(doc)) {
return null;
}
// XXX
// try {
// Thread.sleep(new Random().nextInt(1000));
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
this.doc = doc;
for (final AceEditor editor : editors) {
editor.getUI().access(new Runnable() {
@Override
public void run() {
editor.setDoc(doc);
}
});
}
return doc;
}
public void setDoc(AceDoc doc) {
AceDoc newDoc = setDocNoFire(doc);
if (newDoc!=null) {
fireChanged();
}
}
public synchronized AceDoc getDoc() {
return doc;
}
public void addListener(Listener li) {
listeners.add(li);
}
public void removeListener(Listener li) {
listeners.remove(li);
}
public void fireChanged() {
for (Listener li : listeners) {
li.changed();
}
}
@Override
public void diff(DiffEvent e) {
applyDiff(e.getDiff());
}
public DocDiffMediator fork() {
SharedDoc fork = new SharedDoc(getDoc());
return new DocDiffMediator(this, fork);
}
}