package sk.stuba.fiit.perconik.core.resources;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextInputListener;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import sk.stuba.fiit.perconik.core.listeners.DocumentListener;
import sk.stuba.fiit.perconik.core.listeners.PartListener;
import sk.stuba.fiit.perconik.eclipse.ui.Parts;
import static com.google.common.collect.Maps.newHashMap;
import static sk.stuba.fiit.perconik.core.resources.Ui.dereferencePart;
final class DocumentHook extends InternalHook<IDocument, DocumentListener> implements PartListener {
private final Map<ITextViewer, TextInputChangeFix> fixes;
DocumentHook(final DocumentListener listener) {
super(new DocumentHandler(listener));
this.fixes = newHashMap();
}
static final class Support extends AbstractHookSupport<DocumentHook, IDocument, DocumentListener> {
public Hook<IDocument, DocumentListener> create(final DocumentListener listener) {
return new DocumentHook(listener);
}
}
private static final class DocumentHandler extends InternalHandler<IDocument, DocumentListener> {
DocumentHandler(final DocumentListener listener) {
super(IDocument.class, listener);
}
public void register(final IDocument document) {
document.addDocumentListener(this.listener);
}
public void unregister(final IDocument document) {
document.removeDocumentListener(this.listener);
}
}
private final class TextInputChangeFix implements ITextInputListener {
TextInputChangeFix() {}
public void inputDocumentAboutToBeChanged(final IDocument before, final IDocument after) {}
public void inputDocumentChanged(final IDocument before, final IDocument after) {
Hooks.removeNonNull(DocumentHook.this, before);
Hooks.addNonNull(DocumentHook.this, after);
}
}
@Override
void preRegisterInternal() {
Hooks.addDocumentsAsynchronouslyTo(this);
}
@Override
void postUnregisterInternal() {
synchronized (this.fixes) {
for (Entry<ITextViewer, TextInputChangeFix> entry: this.fixes.entrySet()) {
entry.getKey().removeTextInputListener(entry.getValue());
}
}
}
public void partOpened(final IWorkbenchPartReference reference) {
IWorkbenchPart part = dereferencePart(reference);
ITextViewer viewer = Parts.getTextViewer(part);
IDocument document = Parts.getDocument(viewer);
if (viewer != null) {
synchronized (this.fixes) {
if (!this.fixes.containsKey(viewer)) {
TextInputChangeFix fix = new TextInputChangeFix();
this.fixes.put(viewer, fix);
viewer.addTextInputListener(fix);
}
}
Hooks.addNonNull(DocumentHook.this, document);
}
}
public void partClosed(final IWorkbenchPartReference reference) {
IWorkbenchPart part = dereferencePart(reference);
ITextViewer viewer = Parts.getTextViewer(part);
IDocument document = Parts.getDocument(viewer);
if (viewer != null) {
synchronized (this.fixes) {
TextInputChangeFix fix = this.fixes.remove(viewer);
if (fix != null) {
viewer.removeTextInputListener(fix);
}
}
}
Hooks.removeNonNull(DocumentHook.this, document);
}
public void partActivated(final IWorkbenchPartReference reference) {}
public void partDeactivated(final IWorkbenchPartReference reference) {}
public void partVisible(final IWorkbenchPartReference reference) {}
public void partHidden(final IWorkbenchPartReference reference) {}
public void partBroughtToTop(final IWorkbenchPartReference reference) {}
public void partInputChanged(final IWorkbenchPartReference reference) {}
}