package org.bundlemaker.core.ui.editor.sourceviewer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.AnnotationModelEvent;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.IAnnotationModelExtension;
import org.eclipse.jface.text.source.IAnnotationModelListener;
import org.eclipse.jface.text.source.IAnnotationModelListenerExtension;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
/**
* <p>
* </p>
*
* @author Gerd Wütherich (gerd@gerd-wuetherich.de)
*/
public final class ReferenceAnnotationModel implements IAnnotationModel {
/** REFERENCE_ANNOTATION_MODEL_KEY */
private static final String REFERENCE_ANNOTATION_MODEL_KEY = "REFERENCE_ANNOTATION_MODEL_KEY";
/** List of current ReferenceAnnotation objects */
private List<ReferenceAnnotation> _annotations = new ArrayList<ReferenceAnnotation>(32);
/** - */
private final IDocument _document;
/** - */
private Map<String, List<Position>> _references;
/** List of registered IAnnotationModelListener */
private List<IAnnotationModelListener> _listeners = new ArrayList<IAnnotationModelListener>(2);
/**
* <p>
* Creates a new instance of type {@link ReferenceAnnotationModel}.
* </p>
*
* @param editor
* @param document
* @param references
*/
private ReferenceAnnotationModel(IDocument document, Map<String, List<Position>> references) {
this._document = document;
_references = references;
//
createAnnotations();
}
/**
* <p>
* </p>
*
* @param editor
* @param fullyQualifiedName
* @param references
*/
public static void attach(SourceViewerEditor editor, String fullyQualifiedName, List<Position> references) {
//
Map<String, List<Position>> referencesMap = new HashMap<String, List<Position>>();
//
referencesMap.put(fullyQualifiedName, references);
//
attach(editor, referencesMap);
}
/**
* Attaches a coverage annotation model for the given editor if the editor can be annotated. Does nothing if the model
* is already attached.
*
* @param editor
* Editor to attach a annotation model to
*/
public static void attach(SourceViewerEditor editor, Map<String, List<Position>> references) {
//
// IAnnotationModel model = editor.getAnnotationModel();
//
// if (!(model instanceof IAnnotationModelExtension))
// return;
//
// //
// IAnnotationModelExtension modelExtension = (IAnnotationModelExtension) model;
//
// //
// if (modelExtension.getAnnotationModel(REFERENCE_ANNOTATION_MODEL_KEY) != null) {
// modelExtension.removeAnnotationModel(REFERENCE_ANNOTATION_MODEL_KEY);
// }
//
// //
// IDocument document = editor.getDocument();
// ReferenceAnnotationModel annotationModel = new ReferenceAnnotationModel(document, references);
// modelExtension.addAnnotationModel(REFERENCE_ANNOTATION_MODEL_KEY,
// annotationModel);
// annotationModel.createAnnotations();
}
/**
* Detaches the coverage annotation model from the given editor. If the editor does not have a model attached, this
* method does nothing.
*
* @param editor
* Editor to detach the annotation model from
*/
public static void detach(ITextEditor editor) {
IDocumentProvider provider = editor.getDocumentProvider();
// there may be text editors without document providers (SF #1725100)
if (provider == null)
return;
IAnnotationModel model = provider.getAnnotationModel(editor.getEditorInput());
if (!(model instanceof IAnnotationModelExtension))
return;
IAnnotationModelExtension modelex = (IAnnotationModelExtension) model;
modelex.removeAnnotationModel(REFERENCE_ANNOTATION_MODEL_KEY);
}
/**
* {@inheritDoc}
*/
@Override
public void addAnnotationModelListener(IAnnotationModelListener listener) {
if (!_listeners.contains(listener)) {
_listeners.add(listener);
fireModelChanged(new AnnotationModelEvent(this, true));
}
}
/**
* {@inheritDoc}
*/
@Override
public void removeAnnotationModelListener(IAnnotationModelListener listener) {
_listeners.remove(listener);
}
/**
* {@inheritDoc}
*/
@Override
public void connect(IDocument document) {
if (this._document != document)
throw new RuntimeException("Can't connect to different document."); //$NON-NLS-1$
for (final ReferenceAnnotation ca : _annotations) {
try {
document.addPosition(ca.getPosition());
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void disconnect(IDocument document) {
if (this._document != document)
throw new RuntimeException("Can't disconnect from different document."); //$NON-NLS-1$
for (final ReferenceAnnotation ca : _annotations) {
document.removePosition(ca.getPosition());
}
}
/**
* {@inheritDoc}
*/
@Override
public void addAnnotation(Annotation annotation, Position position) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public void removeAnnotation(Annotation annotation) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public Iterator<?> getAnnotationIterator() {
return _annotations.iterator();
}
/**
* {@inheritDoc}
*/
@Override
public Position getPosition(Annotation annotation) {
if (annotation instanceof ReferenceAnnotation) {
return ((ReferenceAnnotation) annotation).getPosition();
} else {
return null;
}
}
/**
* <p>
* </p>
*
* @param event
*/
private void fireModelChanged(AnnotationModelEvent event) {
event.markSealed();
if (!event.isEmpty()) {
for (final IAnnotationModelListener l : _listeners) {
if (l instanceof IAnnotationModelListenerExtension) {
((IAnnotationModelListenerExtension) l).modelChanged(event);
} else {
l.modelChanged(this);
}
}
}
}
/**
* <p>
* </p>
*
* @param event
*/
private void clear(AnnotationModelEvent event) {
for (final ReferenceAnnotation ca : _annotations) {
event.annotationRemoved(ca, ca.getPosition());
}
_annotations.clear();
}
/**
* <p>
* </p>
*/
public void createAnnotations() {
//
AnnotationModelEvent event = new AnnotationModelEvent(this);
clear(event);
//
// for (Entry<String, List<Position>> entry : _positions.entrySet()) {
//
// for (Position position : entry.getValue()) {
// //
// Annotation annotation = new Annotation(false);
// annotation.setType(ANNO_TYPE);
// _annotationModel.addAnnotation(annotation, position);
// }
// }
for (Map.Entry<String, List<Position>> entry : _references.entrySet()) {
for (Position position : entry.getValue()) {
ReferenceAnnotation ca = new ReferenceAnnotation(position.offset, position.length, entry.getKey());
_annotations.add(ca);
event.annotationAdded(ca);
}
}
fireModelChanged(event);
}
}