All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jface.text.source.AnnotationModel Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2000, 2011 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Anton Leherbauer  - [implementation] AnnotationModel.fModificationStamp leaks annotations - http://bugs.eclipse.org/345715
 *******************************************************************************/
package org.eclipse.jface.text.source;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

import org.eclipse.core.runtime.Assert;

import org.eclipse.jface.text.AbstractDocument;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.ISynchronizable;
import org.eclipse.jface.text.Position;


/**
 * Standard implementation of {@link IAnnotationModel} and its extension
 * interfaces. This class can directly be used by clients. Subclasses may adapt
 * this annotation model to other existing annotation mechanisms. This class
 * also implements {@link org.eclipse.jface.text.ISynchronizable}. All
 * modifications of the model's internal annotation map are synchronized using
 * the model's lock object.
 */
public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtension, IAnnotationModelExtension2, ISynchronizable {


	/**
	 * Iterator that returns the annotations for a given region.
	 *
	 * @since 3.4
	 * @see AnnotationModel.RegionIterator#RegionIterator(Iterator, IAnnotationModel, int, int, boolean, boolean)
	 */
	private static final class RegionIterator implements Iterator {

		private final Iterator fParentIterator;
		private final boolean fCanEndAfter;
		private final boolean fCanStartBefore;
		private final IAnnotationModel fModel;
		private Object fNext;
		private Position fRegion;

		/**
		 * Iterator that returns all annotations from the parent iterator which
		 * have a position in the given model inside the given region.
		 * 

* See {@link IAnnotationModelExtension2} for a definition of inside. *

* * @param parentIterator iterator containing all annotations * @param model the model to use to retrieve positions from for each * annotation * @param offset start position of the region * @param length length of the region * @param canStartBefore include annotations starting before region * @param canEndAfter include annotations ending after region * @see IAnnotationModelExtension2 */ public RegionIterator(Iterator parentIterator, IAnnotationModel model, int offset, int length, boolean canStartBefore, boolean canEndAfter) { fParentIterator= parentIterator; fModel= model; fRegion= new Position(offset, length); fCanEndAfter= canEndAfter; fCanStartBefore= canStartBefore; fNext= findNext(); } /* * @see java.util.Iterator#hasNext() */ public boolean hasNext() { return fNext != null; } /* * @see java.util.Iterator#next() */ public Object next() { if (!hasNext()) throw new NoSuchElementException(); Object result= fNext; fNext= findNext(); return result; } /* * @see java.util.Iterator#remove() */ public void remove() { throw new UnsupportedOperationException(); } private Object findNext() { while (fParentIterator.hasNext()) { Annotation next= (Annotation) fParentIterator.next(); Position position= fModel.getPosition(next); if (position != null) { int offset= position.getOffset(); if (isWithinRegion(offset, position.getLength())) return next; } } return null; } private boolean isWithinRegion(int start, int length) { if (fCanStartBefore && fCanEndAfter) return fRegion.overlapsWith(start, length); else if (fCanStartBefore) return fRegion.includes(start + length - (length > 0 ? 1 : 0)); else if (fCanEndAfter) return fRegion.includes(start); else return fRegion.includes(start) && fRegion.includes(start + length - (length > 0 ? 1 : 0)); } } /** * An iterator iteration over a Positions and mapping positions to * annotations using a provided map if the provided map contains the element. * * @since 3.4 */ private static final class AnnotationsInterator implements Iterator { private Object fNext; private final Position[] fPositions; private int fIndex; private final Map fMap; /** * @param positions positions to iterate over * @param map a map to map positions to annotations */ public AnnotationsInterator(Position[] positions, Map map) { fPositions= positions; fIndex= 0; fMap= map; fNext= findNext(); } /* (non-Javadoc) * @see java.util.Iterator#hasNext() */ public boolean hasNext() { return fNext != null; } /* (non-Javadoc) * @see java.util.Iterator#next() */ public Object next() { Object result= fNext; fNext= findNext(); return result; } /* (non-Javadoc) * @see java.util.Iterator#remove() */ public void remove() { throw new UnsupportedOperationException(); } private Object findNext() { while (fIndex < fPositions.length) { Position position= fPositions[fIndex]; fIndex++; if (fMap.containsKey(position)) return fMap.get(position); } return null; } } /** * A single iterator builds its behavior based on a sequence of iterators. * * @since 3.1 */ private static class MetaIterator implements Iterator { /** The iterator over a list of iterators. */ private Iterator fSuperIterator; /** The current iterator. */ private Iterator fCurrent; /** The current element. */ private Object fCurrentElement; public MetaIterator(Iterator iterator) { fSuperIterator= iterator; fCurrent= (Iterator) fSuperIterator.next(); // there is at least one. } public void remove() { throw new UnsupportedOperationException(); } public boolean hasNext() { if (fCurrentElement != null) return true; if (fCurrent.hasNext()) { fCurrentElement= fCurrent.next(); return true; } else if (fSuperIterator.hasNext()) { fCurrent= (Iterator) fSuperIterator.next(); return hasNext(); } else return false; } public Object next() { if (!hasNext()) throw new NoSuchElementException(); Object element= fCurrentElement; fCurrentElement= null; return element; } } /** * Internal annotation model listener for forwarding annotation model changes from the attached models to the * registered listeners of the outer most annotation model. * * @since 3.0 */ private class InternalModelListener implements IAnnotationModelListener, IAnnotationModelListenerExtension { /* * @see org.eclipse.jface.text.source.IAnnotationModelListener#modelChanged(org.eclipse.jface.text.source.IAnnotationModel) */ public void modelChanged(IAnnotationModel model) { AnnotationModel.this.fireModelChanged(new AnnotationModelEvent(model, true)); } /* * @see org.eclipse.jface.text.source.IAnnotationModelListenerExtension#modelChanged(org.eclipse.jface.text.source.AnnotationModelEvent) */ public void modelChanged(AnnotationModelEvent event) { AnnotationModel.this.fireModelChanged(event); } } /** * The list of managed annotations * @deprecated since 3.0 use getAnnotationMap instead */ protected Map fAnnotations; /** * The map which maps {@link Position} to {@link Annotation}. * @since 3.4 **/ private IdentityHashMap fPositions; /** The list of annotation model listeners */ protected ArrayList fAnnotationModelListeners; /** The document connected with this model */ protected IDocument fDocument; /** The number of open connections to the same document */ private int fOpenConnections= 0; /** The document listener for tracking whether document positions might have been changed. */ private IDocumentListener fDocumentListener; /** The flag indicating whether the document positions might have been changed. */ private boolean fDocumentChanged= true; /** * The model's attachment. * @since 3.0 */ private Map fAttachments= new HashMap(); /** * The annotation model listener on attached sub-models. * @since 3.0 */ private IAnnotationModelListener fModelListener= new InternalModelListener(); /** * The current annotation model event. * @since 3.0 */ private AnnotationModelEvent fModelEvent; /** * The modification stamp. * @since 3.0 */ private Object fModificationStamp= new Object(); /** * Creates a new annotation model. The annotation is empty, i.e. does not * manage any annotations and is not connected to any document. */ public AnnotationModel() { fAnnotations= new AnnotationMap(10); fPositions= new IdentityHashMap(10); fAnnotationModelListeners= new ArrayList(2); fDocumentListener= new IDocumentListener() { public void documentAboutToBeChanged(DocumentEvent event) { } public void documentChanged(DocumentEvent event) { fDocumentChanged= true; } }; } /** * Returns the annotation map internally used by this annotation model. * * @return the annotation map internally used by this annotation model * @since 3.0 */ protected IAnnotationMap getAnnotationMap() { return (IAnnotationMap) fAnnotations; } /* * @see org.eclipse.jface.text.ISynchronizable#getLockObject() * @since 3.0 */ public Object getLockObject() { return getAnnotationMap().getLockObject(); } /* * @see org.eclipse.jface.text.ISynchronizable#setLockObject(java.lang.Object) * @since 3.0 */ public void setLockObject(Object lockObject) { getAnnotationMap().setLockObject(lockObject); } /** * Returns the current annotation model event. This is the event that will be sent out * when calling fireModelChanged. * * @return the current annotation model event * @since 3.0 */ protected final AnnotationModelEvent getAnnotationModelEvent() { synchronized (getLockObject()) { if (fModelEvent == null) { fModelEvent= createAnnotationModelEvent(); fModelEvent.markWorldChange(false); fModificationStamp= new Object(); } return fModelEvent; } } /* * @see org.eclipse.jface.text.source.IAnnotationModel#addAnnotation(org.eclipse.jface.text.source.Annotation, org.eclipse.jface.text.Position) */ public void addAnnotation(Annotation annotation, Position position) { try { addAnnotation(annotation, position, true); } catch (BadLocationException e) { // ignore invalid position } } /* * @see org.eclipse.jface.text.source.IAnnotationModelExtension#replaceAnnotations(org.eclipse.jface.text.source.Annotation[], java.util.Map) * @since 3.0 */ public void replaceAnnotations(Annotation[] annotationsToRemove, Map annotationsToAdd) { try { replaceAnnotations(annotationsToRemove, annotationsToAdd, true); } catch (BadLocationException x) { } } /** * Replaces the given annotations in this model and if advised fires a * model change event. * * @param annotationsToRemove the annotations to be removed * @param annotationsToAdd the annotations to be added * @param fireModelChanged true if a model change event * should be fired, false otherwise * @throws BadLocationException in case an annotation should be added at an * invalid position * @since 3.0 */ protected void replaceAnnotations(Annotation[] annotationsToRemove, Map annotationsToAdd, boolean fireModelChanged) throws BadLocationException { if (annotationsToRemove != null) { for (int i= 0, length= annotationsToRemove.length; i < length; i++) removeAnnotation(annotationsToRemove[i], false); } if (annotationsToAdd != null) { Iterator iter= annotationsToAdd.entrySet().iterator(); while (iter.hasNext()) { Map.Entry mapEntry= (Map.Entry) iter.next(); Annotation annotation= (Annotation) mapEntry.getKey(); Position position= (Position) mapEntry.getValue(); addAnnotation(annotation, position, false); } } if (fireModelChanged) fireModelChanged(); } /** * Adds the given annotation to this model. Associates the * annotation with the given position. If requested, all annotation * model listeners are informed about this model change. If the annotation * is already managed by this model nothing happens. * * @param annotation the annotation to add * @param position the associate position * @param fireModelChanged indicates whether to notify all model listeners * @throws BadLocationException if the position is not a valid document position */ protected void addAnnotation(Annotation annotation, Position position, boolean fireModelChanged) throws BadLocationException { if (!fAnnotations.containsKey(annotation)) { addPosition(fDocument, position); fAnnotations.put(annotation, position); fPositions.put(position, annotation); synchronized (getLockObject()) { getAnnotationModelEvent().annotationAdded(annotation); } if (fireModelChanged) fireModelChanged(); } } /* * @see org.eclipse.jface.text.source.IAnnotationModel#addAnnotationModelListener(org.eclipse.jface.text.source.IAnnotationModelListener) */ public void addAnnotationModelListener(IAnnotationModelListener listener) { if (!fAnnotationModelListeners.contains(listener)) { fAnnotationModelListeners.add(listener); if (listener instanceof IAnnotationModelListenerExtension) { IAnnotationModelListenerExtension extension= (IAnnotationModelListenerExtension) listener; AnnotationModelEvent event= createAnnotationModelEvent(); event.markSealed(); extension.modelChanged(event); } else listener.modelChanged(this); } } /** * Adds the given position to the default position category of the * given document. * * @param document the document to which to add the position * @param position the position to add * @throws BadLocationException if the position is not a valid document position */ protected void addPosition(IDocument document, Position position) throws BadLocationException { if (document != null) document.addPosition(position); } /** * Removes the given position from the default position category of the * given document. * * @param document the document to which to add the position * @param position the position to add * * @since 3.0 */ protected void removePosition(IDocument document, Position position) { if (document != null) document.removePosition(position); } /* * @see org.eclipse.jface.text.source.IAnnotationModel#connect(org.eclipse.jface.text.IDocument) */ public void connect(IDocument document) { Assert.isTrue(fDocument == null || fDocument == document); if (fDocument == null) { fDocument= document; Iterator e= getAnnotationMap().valuesIterator(); while (e.hasNext()) try { addPosition(document, (Position) e.next()); } catch (BadLocationException x) { // ignore invalid position } } ++ fOpenConnections; if (fOpenConnections == 1) { document.addDocumentListener(fDocumentListener); connected(); } for (Iterator it= fAttachments.keySet().iterator(); it.hasNext();) { IAnnotationModel model= (IAnnotationModel) fAttachments.get(it.next()); model.connect(document); } } /** * Hook method. Is called as soon as this model becomes connected to a document. * Subclasses may re-implement. */ protected void connected() { } /** * Hook method. Is called as soon as this model becomes disconnected from its document. * Subclasses may re-implement. */ protected void disconnected() { } /* * @see org.eclipse.jface.text.source.IAnnotationModel#disconnect(org.eclipse.jface.text.IDocument) */ public void disconnect(IDocument document) { Assert.isTrue(fDocument == document); for (Iterator it= fAttachments.keySet().iterator(); it.hasNext();) { IAnnotationModel model= (IAnnotationModel) fAttachments.get(it.next()); model.disconnect(document); } -- fOpenConnections; if (fOpenConnections == 0) { disconnected(); document.removeDocumentListener(fDocumentListener); Iterator e= getAnnotationMap().valuesIterator(); while (e.hasNext()) { Position p= (Position) e.next(); removePosition(document, p); } fDocument= null; } } /** * Informs all annotation model listeners that this model has been changed. */ protected void fireModelChanged() { AnnotationModelEvent modelEvent= null; synchronized(getLockObject()) { if (fModelEvent != null) { modelEvent= fModelEvent; fModelEvent= null; } } if (modelEvent != null) fireModelChanged(modelEvent); } /** * Creates and returns a new annotation model event. Subclasses may override. * * @return a new and empty annotation model event * @since 3.0 */ protected AnnotationModelEvent createAnnotationModelEvent() { return new AnnotationModelEvent(this); } /** * Informs all annotation model listeners that this model has been changed * as described in the annotation model event. The event is sent out * to all listeners implementing IAnnotationModelListenerExtension. * All other listeners are notified by just calling modelChanged(IAnnotationModel). * * @param event the event to be sent out to the listeners * @since 2.0 */ protected void fireModelChanged(AnnotationModelEvent event) { event.markSealed(); if (event.isEmpty()) return; ArrayList v= new ArrayList(fAnnotationModelListeners); Iterator e= v.iterator(); while (e.hasNext()) { IAnnotationModelListener l= (IAnnotationModelListener) e.next(); if (l instanceof IAnnotationModelListenerExtension) ((IAnnotationModelListenerExtension) l).modelChanged(event); else if (l != null) l.modelChanged(this); } } /** * Removes the given annotations from this model. If requested all * annotation model listeners will be informed about this change. * modelInitiated indicates whether the deletion has * been initiated by this model or by one of its clients. * * @param annotations the annotations to be removed * @param fireModelChanged indicates whether to notify all model listeners * @param modelInitiated indicates whether this changes has been initiated by this model */ protected void removeAnnotations(List annotations, boolean fireModelChanged, boolean modelInitiated) { if (annotations.size() > 0) { Iterator e= annotations.iterator(); while (e.hasNext()) removeAnnotation((Annotation) e.next(), false); if (fireModelChanged) fireModelChanged(); } } /** * Removes all annotations from the model whose associated positions have been * deleted. If requested inform all model listeners about the change. * * @param fireModelChanged indicates whether to notify all model listeners */ protected void cleanup(boolean fireModelChanged) { cleanup(fireModelChanged, true); } /** * Removes all annotations from the model whose associated positions have been * deleted. If requested inform all model listeners about the change. If requested * a new thread is created for the notification of the model listeners. * * @param fireModelChanged indicates whether to notify all model listeners * @param forkNotification true iff notification should be done in a new thread * @since 3.0 */ private void cleanup(boolean fireModelChanged, boolean forkNotification) { if (fDocumentChanged) { fDocumentChanged= false; ArrayList deleted= new ArrayList(); Iterator e= getAnnotationMap().keySetIterator(); while (e.hasNext()) { Annotation a= (Annotation) e.next(); Position p= (Position) fAnnotations.get(a); if (p == null || p.isDeleted()) deleted.add(a); } if (fireModelChanged && forkNotification) { removeAnnotations(deleted, false, false); synchronized (getLockObject()) { if (fModelEvent != null) new Thread() { public void run() { fireModelChanged(); } }.start(); } } else removeAnnotations(deleted, fireModelChanged, false); } } /* * @see org.eclipse.jface.text.source.IAnnotationModel#getAnnotationIterator() */ public Iterator getAnnotationIterator() { return getAnnotationIterator(true, true); } /** * {@inheritDoc} * * @since 3.4 */ public Iterator getAnnotationIterator(int offset, int length, boolean canStartBefore, boolean canEndAfter) { Iterator regionIterator= getRegionAnnotationIterator(offset, length, canStartBefore, canEndAfter); if (fAttachments.isEmpty()) return regionIterator; List iterators= new ArrayList(fAttachments.size() + 1); iterators.add(regionIterator); Iterator it= fAttachments.keySet().iterator(); while (it.hasNext()) { IAnnotationModel attachment= (IAnnotationModel) fAttachments.get(it.next()); if (attachment instanceof IAnnotationModelExtension2) iterators.add(((IAnnotationModelExtension2) attachment).getAnnotationIterator(offset, length, canStartBefore, canEndAfter)); else iterators.add(new RegionIterator(attachment.getAnnotationIterator(), attachment, offset, length, canStartBefore, canEndAfter)); } return new MetaIterator(iterators.iterator()); } /** * Returns an iterator as specified in {@link IAnnotationModelExtension2#getAnnotationIterator(int, int, boolean, boolean)} * * @param offset region start * @param length region length * @param canStartBefore position can start before region * @param canEndAfter position can end after region * @return an iterator to iterate over annotations in region * @see IAnnotationModelExtension2#getAnnotationIterator(int, int, boolean, boolean) * @since 3.4 */ private Iterator getRegionAnnotationIterator(int offset, int length, boolean canStartBefore, boolean canEndAfter) { if (!(fDocument instanceof AbstractDocument)) return new RegionIterator(getAnnotationIterator(true), this, offset, length, canStartBefore, canEndAfter); AbstractDocument document= (AbstractDocument) fDocument; cleanup(true); try { Position[] positions= document.getPositions(IDocument.DEFAULT_CATEGORY, offset, length, canStartBefore, canEndAfter); return new AnnotationsInterator(positions, fPositions); } catch (BadPositionCategoryException e) { //can not happen Assert.isTrue(false); return null; } } /** * Returns all annotations managed by this model. cleanup * indicates whether all annotations whose associated positions are * deleted should previously be removed from the model. recurse indicates * whether annotations of attached sub-models should also be returned. * * @param cleanup indicates whether annotations with deleted associated positions are removed * @param recurse whether to return annotations managed by sub-models. * @return all annotations managed by this model * @since 3.0 */ private Iterator getAnnotationIterator(boolean cleanup, boolean recurse) { Iterator iter= getAnnotationIterator(cleanup); if (!recurse || fAttachments.isEmpty()) return iter; List iterators= new ArrayList(fAttachments.size() + 1); iterators.add(iter); Iterator it= fAttachments.keySet().iterator(); while (it.hasNext()) iterators.add(((IAnnotationModel) fAttachments.get(it.next())).getAnnotationIterator()); return new MetaIterator(iterators.iterator()); } /** * Returns all annotations managed by this model. cleanup * indicates whether all annotations whose associated positions are * deleted should previously be removed from the model. * * @param cleanup indicates whether annotations with deleted associated positions are removed * @return all annotations managed by this model */ protected Iterator getAnnotationIterator(boolean cleanup) { if (cleanup) cleanup(true); return getAnnotationMap().keySetIterator(); } /* * @see org.eclipse.jface.text.source.IAnnotationModel#getPosition(org.eclipse.jface.text.source.Annotation) */ public Position getPosition(Annotation annotation) { Position position= (Position) fAnnotations.get(annotation); if (position != null) return position; Iterator it= fAttachments.values().iterator(); while (position == null && it.hasNext()) position= ((IAnnotationModel) it.next()).getPosition(annotation); return position; } /* * @see org.eclipse.jface.text.source.IAnnotationModelExtension#removeAllAnnotations() * @since 3.0 */ public void removeAllAnnotations() { removeAllAnnotations(true); } /** * Removes all annotations from the annotation model. If requested * inform all model change listeners about this change. * * @param fireModelChanged indicates whether to notify all model listeners */ protected void removeAllAnnotations(boolean fireModelChanged) { if (fDocument != null) { Iterator e= getAnnotationMap().keySetIterator(); while (e.hasNext()) { Annotation a= (Annotation) e.next(); Position p= (Position) fAnnotations.get(a); removePosition(fDocument, p); // p.delete(); synchronized (getLockObject()) { getAnnotationModelEvent().annotationRemoved(a, p); } } } fAnnotations.clear(); fPositions.clear(); if (fireModelChanged) fireModelChanged(); } /* * @see org.eclipse.jface.text.source.IAnnotationModel#removeAnnotation(org.eclipse.jface.text.source.Annotation) */ public void removeAnnotation(Annotation annotation) { removeAnnotation(annotation, true); } /** * Removes the given annotation from the annotation model. * If requested inform all model change listeners about this change. * * @param annotation the annotation to be removed * @param fireModelChanged indicates whether to notify all model listeners */ protected void removeAnnotation(Annotation annotation, boolean fireModelChanged) { if (fAnnotations.containsKey(annotation)) { Position p= null; p= (Position) fAnnotations.get(annotation); if (fDocument != null) { removePosition(fDocument, p); // p.delete(); } fAnnotations.remove(annotation); fPositions.remove(p); synchronized (getLockObject()) { getAnnotationModelEvent().annotationRemoved(annotation, p); } if (fireModelChanged) fireModelChanged(); } } /* * @see org.eclipse.jface.text.source.IAnnotationModelExtension#modifyAnnotationPosition(org.eclipse.jface.text.source.Annotation, org.eclipse.jface.text.Position) * @since 3.0 */ public void modifyAnnotationPosition(Annotation annotation, Position position) { modifyAnnotationPosition(annotation, position, true); } /** * Modifies the associated position of the given annotation to the given * position. If the annotation is not yet managed by this annotation model, * the annotation is added. When the position is null, the * annotation is removed from the model. *

* If requested, all annotation model change listeners will be informed * about the change. * * @param annotation the annotation whose associated position should be * modified * @param position the position to whose values the associated position * should be changed * @param fireModelChanged indicates whether to notify all model listeners * @since 3.0 */ protected void modifyAnnotationPosition(Annotation annotation, Position position, boolean fireModelChanged) { if (position == null) { removeAnnotation(annotation, fireModelChanged); } else { Position p= (Position) fAnnotations.get(annotation); if (p != null) { if (position.getOffset() != p.getOffset() || position.getLength() != p.getLength()) { fDocument.removePosition(p); p.setOffset(position.getOffset()); p.setLength(position.getLength()); try { fDocument.addPosition(p); } catch (BadLocationException e) { // ignore invalid position } } synchronized (getLockObject()) { getAnnotationModelEvent().annotationChanged(annotation); } if (fireModelChanged) fireModelChanged(); } else { try { addAnnotation(annotation, position, fireModelChanged); } catch (BadLocationException x) { // ignore invalid position } } } } /** * Modifies the given annotation if the annotation is managed by this * annotation model. *

* If requested, all annotation model change listeners will be informed * about the change. * * @param annotation the annotation to be modified * @param fireModelChanged indicates whether to notify all model listeners * @since 3.0 */ protected void modifyAnnotation(Annotation annotation, boolean fireModelChanged) { if (fAnnotations.containsKey(annotation)) { synchronized (getLockObject()) { getAnnotationModelEvent().annotationChanged(annotation); } if (fireModelChanged) fireModelChanged(); } } /* * @see IAnnotationModel#removeAnnotationModelListener(IAnnotationModelListener) */ public void removeAnnotationModelListener(IAnnotationModelListener listener) { fAnnotationModelListeners.remove(listener); } /* * @see org.eclipse.jface.text.source.IAnnotationModelExtension#attach(java.lang.Object, java.lang.Object) * @since 3.0 */ public void addAnnotationModel(Object key, IAnnotationModel attachment) { Assert.isNotNull(attachment); if (!fAttachments.containsValue(attachment)) { fAttachments.put(key, attachment); for (int i= 0; i < fOpenConnections; i++) attachment.connect(fDocument); attachment.addAnnotationModelListener(fModelListener); } } /* * @see org.eclipse.jface.text.source.IAnnotationModelExtension#get(java.lang.Object) * @since 3.0 */ public IAnnotationModel getAnnotationModel(Object key) { return (IAnnotationModel) fAttachments.get(key); } /* * @see org.eclipse.jface.text.source.IAnnotationModelExtension#detach(java.lang.Object) * @since 3.0 */ public IAnnotationModel removeAnnotationModel(Object key) { IAnnotationModel ret= (IAnnotationModel) fAttachments.remove(key); if (ret != null) { for (int i= 0; i < fOpenConnections; i++) ret.disconnect(fDocument); ret.removeAnnotationModelListener(fModelListener); } return ret; } /* * @see org.eclipse.jface.text.source.IAnnotationModelExtension#getModificationStamp() * @since 3.0 */ public Object getModificationStamp() { return fModificationStamp; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy