KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > link > LinkedPositionAnnotations


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jface.text.link;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import org.eclipse.core.runtime.Assert;
21
22 import org.eclipse.jface.text.BadLocationException;
23 import org.eclipse.jface.text.IDocument;
24 import org.eclipse.jface.text.Position;
25 import org.eclipse.jface.text.link.LinkedModeModel;
26 import org.eclipse.jface.text.link.LinkedPosition;
27 import org.eclipse.jface.text.link.LinkedPositionGroup;
28 import org.eclipse.jface.text.source.Annotation;
29 import org.eclipse.jface.text.source.AnnotationModel;
30
31 /**
32  * Internal class.
33  *
34  * @since 3.0
35  */

36 final class LinkedPositionAnnotations extends AnnotationModel {
37
38     /* annotation types */
39     private static final String JavaDoc TARGET_ANNOTATION_TYPE= "org.eclipse.ui.internal.workbench.texteditor.link.target"; //$NON-NLS-1$
40
private static final String JavaDoc SLAVE_ANNOTATION_TYPE= "org.eclipse.ui.internal.workbench.texteditor.link.slave"; //$NON-NLS-1$
41
private static final String JavaDoc FOCUS_ANNOTATION_TYPE= "org.eclipse.ui.internal.workbench.texteditor.link.master"; //$NON-NLS-1$
42
private static final String JavaDoc EXIT_ANNOTATION_TYPE= "org.eclipse.ui.internal.workbench.texteditor.link.exit"; //$NON-NLS-1$
43

44     /* configuration */
45     private boolean fMarkTargets= true;
46     private boolean fMarkSlaves= true;
47     private boolean fMarkFocus= true;
48     private boolean fMarkExitTarget= true;
49
50     private Annotation fFocusAnnotation= null;
51     private Annotation fExitAnnotation= null;
52     private final Map JavaDoc fGroupAnnotations= new HashMap JavaDoc();
53     private final Map JavaDoc fTargetAnnotations= new HashMap JavaDoc();
54     private Position[] fTargets= new Position[0];
55     private LinkedPosition fExitPosition= null;
56
57     /**
58      * Sets the position that should be highlighted as the focus position, i.e.
59      * as the position whose changes are propagated to all its linked positions
60      * by the linked environment.
61      *
62      * @param position the new focus position, or <code>null</code> if no focus is set.
63      * @throws BadLocationException if <code>position</code> is invalid
64      */

65     private void setFocusPosition(Position position) throws BadLocationException {
66         if (fMarkFocus && getPosition(fFocusAnnotation) != position) {
67             removeAnnotation(fFocusAnnotation, false);
68             if (position != null) {
69                 fFocusAnnotation= new Annotation(FOCUS_ANNOTATION_TYPE, false, ""); //$NON-NLS-1$
70
addAnnotation(fFocusAnnotation, position, false);
71             } else
72                 fFocusAnnotation= null;
73         }
74     }
75
76     /**
77      * Sets the position that should be highlighted as the exit position, i.e.
78      * as the position whose changes are propagated to all its linked positions
79      * by the linked environment.
80      *
81      * @param position the new exit position, or <code>null</code> if no focus is set.
82      * @throws BadLocationException in case <code>position</code> is invalid
83      */

84     private void setExitPosition(Position position) throws BadLocationException {
85         if (fMarkExitTarget && getPosition(fExitAnnotation) != position) {
86             removeAnnotation(fExitAnnotation, false);
87             if (position != null) {
88                 fExitAnnotation= new Annotation(EXIT_ANNOTATION_TYPE, false, ""); //$NON-NLS-1$
89
addAnnotation(fExitAnnotation, position, false);
90             } else
91                 fExitAnnotation= null;
92         }
93     }
94
95     /**
96      * Sets the positions that should be highlighted as the slave positions, i.e.
97      * as the positions that are linked to the focus position.
98      *
99      * @param positions the new slave positions, or <code>null</code> if no slave positions are to be set
100      * @throws BadLocationException in case any of the given positions is invalid
101      */

102     private void setGroupPositions(List JavaDoc positions) throws BadLocationException {
103         if (!fMarkSlaves)
104             return;
105
106         // remove all positions which are already there
107
// Algorithm: toRemove contains all mappings at first, but all that are in
108
// positions get removed -> toRemove contains the difference set of previous - new
109
// toAdd are the new positions, which don't exist in previous = new - previous
110
List JavaDoc toRemove= new ArrayList JavaDoc(fGroupAnnotations.values());
111         Map JavaDoc toAdd= new HashMap JavaDoc();
112         if (positions != null) {
113             for (Iterator JavaDoc iter= positions.iterator(); iter.hasNext();) {
114                 Position p= (Position) iter.next();
115                 if (fGroupAnnotations.containsKey(p)) {
116                     toRemove.remove(fGroupAnnotations.get(p));
117                 } else {
118                     Annotation a= new Annotation(SLAVE_ANNOTATION_TYPE, false, ""); //$NON-NLS-1$
119
toAdd.put(a, p);
120                     fGroupAnnotations.put(p, a);
121                 }
122             }
123         }
124         fGroupAnnotations.values().removeAll(toRemove);
125
126         replaceAnnotations((Annotation[]) toRemove.toArray(new Annotation[0]), toAdd, false);
127     }
128
129     /**
130      * Sets the positions that should be highlighted as the target positions, i.e.
131      * as the positions that can be jumped to in a linked set up.
132      *
133      * @param positions the new target positions, or <code>null</code> if no target positions are to be set
134      * @throws BadLocationException in case any of the given positions is invalid
135      */

136     private void setTargetPositions(List JavaDoc positions) throws BadLocationException {
137         if (!fMarkTargets)
138             return;
139
140         // remove all positions which are already there
141
// Algorithm: toRemove contains all mappings at first, but all that are in
142
// positions get removed -> toRemove contains the difference set of previous - new
143
// toAdd are the new positions, which don't exist in previous = new - previous
144
List JavaDoc toRemove= new ArrayList JavaDoc(fTargetAnnotations.values());
145         Map JavaDoc toAdd= new HashMap JavaDoc();
146         if (positions != null) {
147             for (Iterator JavaDoc iter= positions.iterator(); iter.hasNext();) {
148                 Position p= (Position) iter.next();
149                 if (fTargetAnnotations.containsKey(p)) {
150                     toRemove.remove(fTargetAnnotations.get(p));
151                 } else {
152                     Annotation a= new Annotation(TARGET_ANNOTATION_TYPE, false, ""); //$NON-NLS-1$
153
toAdd.put(a, p);
154                     fTargetAnnotations.put(p, a);
155                 }
156             }
157         }
158         fTargetAnnotations.values().removeAll(toRemove);
159
160         replaceAnnotations((Annotation[]) toRemove.toArray(new Annotation[0]), toAdd, false);
161     }
162
163     /**
164      * Switches the focus position to <code>position</code> given the
165      * <code>LinkedModeModel env</code>. The slave positions for <code>position</code>
166      * is extracted from the environment and set accordingly, the target positions
167      * are updated as well.
168      *
169      * @param env
170      * @param position
171      */

172     public void switchToPosition(LinkedModeModel env, LinkedPosition position) {
173         if (fDocument == null ||
174                 (position != null && getPosition(fFocusAnnotation) == position) ||
175                 (position == null && fFocusAnnotation == null))
176             return;
177
178         LinkedPositionGroup linkedGroup= null;
179         if (position != null)
180             linkedGroup= env.getGroupForPosition(position);
181
182         List JavaDoc targets= new ArrayList JavaDoc();
183         targets.addAll(Arrays.asList(fTargets));
184
185         List JavaDoc group;
186         if (linkedGroup != null)
187             group= new ArrayList JavaDoc(Arrays.asList(linkedGroup.getPositions()));
188         else
189             group= new ArrayList JavaDoc();
190
191         if (position == null || !fDocument.equals(position.getDocument()))
192             // position is not valid if not in this document
193
position= null;
194
195         LinkedPosition exit= fExitPosition;
196         if (exit == null || !fDocument.equals(exit.getDocument()))
197             // position is not valid if not in this document
198
exit= null;
199
200
201         if (exit != null) {
202             group.remove(exit);
203             targets.remove(exit);
204         }
205
206         group.removeAll(targets);
207         targets.remove(position);
208         group.remove(position);
209         prune(targets);
210         prune(group);
211
212         try {
213             setFocusPosition(position);
214             setExitPosition(exit);
215             setGroupPositions(group);
216             setTargetPositions(targets);
217         } catch (BadLocationException e) {
218             // will never happen as we don't actually add/remove positions from the document
219
// see the addPosition / removePosition methods
220
Assert.isTrue(false);
221         }
222         fireModelChanged();
223
224     }
225
226     /**
227      * Prune <code>list</code> of all <code>LinkedPosition</code>s that
228      * do not belong to this model's <code>IDocument</code>.
229      *
230      * @param list the list of positions to prune
231      */

232     private void prune(List JavaDoc list) {
233         for (Iterator JavaDoc iter= list.iterator(); iter.hasNext();) {
234             LinkedPosition pos= (LinkedPosition) iter.next();
235             if (!pos.getDocument().equals(fDocument))
236                 iter.remove();
237         }
238     }
239
240     /**
241      * Sets the target positions
242      * @param positions
243      */

244     public void setTargets(Position[] positions) {
245         fTargets= positions;
246     }
247
248     /**
249      * Sets the exit position.
250      *
251      * @param position the new exit position, or <code>null</code> if no exit position should be set
252      */

253     public void setExitTarget(LinkedPosition position) {
254         fExitPosition = position;
255     }
256
257     /*
258      * @see org.eclipse.jface.text.source.AnnotationModel#addPosition(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.Position)
259      */

260     protected void addPosition(IDocument document, Position position) {
261         // don't to anything as our positions are managed by custom
262
// position updaters
263
}
264
265     /*
266      * @see org.eclipse.jface.text.source.AnnotationModel#removePosition(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.Position)
267      */

268     protected void removePosition(IDocument document, Position pos) {
269         // don't to anything as our positions are managed by custom
270
// position updaters
271
}
272
273     /*
274      * @see org.eclipse.jface.text.source.AnnotationModel#fireModelChanged()
275      */

276     public void fireModelChanged() {
277         super.fireModelChanged();
278     }
279
280     /**
281      * Sets the drawing state for the exit target. Default is <code>true</code>.
282      *
283      * @param markExitTargets the new drawing state for exit targets
284      */

285     public void markExitTarget(boolean markExitTargets) {
286         fMarkExitTarget= markExitTargets;
287     }
288
289     /**
290      * Sets the drawing state for the focus position. Default is <code>true</code>.
291      *
292      * @param markFocus the new drawing state for exit targets
293      */

294     public void markFocus(boolean markFocus) {
295         fMarkFocus= markFocus;
296     }
297
298     /**
299      * Sets the drawing state for slave positions. Default is <code>true</code>.
300      *
301      * @param markSlaves the new drawing state for slaves
302      */

303     public void markSlaves(boolean markSlaves) {
304         fMarkSlaves= markSlaves;
305     }
306
307     /**
308      * Sets the drawing state for targets. Default is <code>true</code>.
309      *
310      * @param markTargets the new drawing state for targets
311      */

312     public void markTargets(boolean markTargets) {
313         fMarkTargets= markTargets;
314     }
315 }
316
Popular Tags