KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > DefaultPositionUpdater


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;
12
13
14 /**
15  * Default implementation of {@link org.eclipse.jface.text.IPositionUpdater}.
16  * <p>
17  * A default position updater must be configured with the position category whose positions it will
18  * update. Other position categories are not affected by this updater.
19  * </p>
20  * <p>
21  * This implementation follows the specification below:
22  * </p>
23  * <ul>
24  * <li>Inserting or deleting text before the position shifts the position accordingly.</li>
25  * <li>Inserting text at the position offset shifts the position accordingly.</li>
26  * <li>Inserting or deleting text strictly contained by the position shrinks or stretches the
27  * position.</li>
28  * <li>Inserting or deleting text after a position does not affect the position.</li>
29  * <li>Deleting text which strictly contains the position deletes the position. Note that the
30  * position is not deleted if its only shrunken to length zero. To delete a position, the
31  * modification must delete from <i>strictly before</i> to <i>strictly after</i> the position.</li>
32  * <li>Replacing text overlapping with the position is considered as a sequence of first deleting
33  * the replaced text and afterwards inserting the new text. Thus, a position might first be shifted
34  * and shrunken and then be stretched.</li>
35  * </ul>
36  * This class can be used as is or be adapted by subclasses. Fields are protected to allow
37  * subclasses direct access. Because of the frequency with which position updaters are used this is
38  * a performance decision.
39  */

40 public class DefaultPositionUpdater implements IPositionUpdater {
41
42     /** The position category the updater draws responsible for */
43     private String JavaDoc fCategory;
44
45     /** Caches the currently investigated position */
46     protected Position fPosition;
47     /**
48      * Remembers the original state of the investigated position
49      * @since 2.1
50      */

51     protected Position fOriginalPosition= new Position(0, 0);
52     /** Caches the offset of the replaced text */
53     protected int fOffset;
54     /** Caches the length of the replaced text */
55     protected int fLength;
56     /** Caches the length of the newly inserted text */
57     protected int fReplaceLength;
58     /** Catches the document */
59     protected IDocument fDocument;
60
61
62     /**
63      * Creates a new default position updater for the given category.
64      *
65      * @param category the category the updater is responsible for
66      */

67     public DefaultPositionUpdater(String JavaDoc category) {
68         fCategory= category;
69     }
70
71     /**
72      * Returns the category this updater is responsible for.
73      *
74      * @return the category this updater is responsible for
75      */

76     protected String JavaDoc getCategory() {
77         return fCategory;
78     }
79
80     /**
81      * Returns whether the current event describes a well formed replace
82      * by which the current position is directly affected.
83      *
84      * @return <code>true</code> the current position is directly affected
85      * @since 3.0
86      */

87     protected boolean isAffectingReplace() {
88         return fLength > 0 && fReplaceLength > 0 && fPosition.length < fOriginalPosition.length;
89     }
90
91     /**
92      * Adapts the currently investigated position to an insertion.
93      */

94     protected void adaptToInsert() {
95
96         int myStart= fPosition.offset;
97         int myEnd= fPosition.offset + fPosition.length - 1;
98         myEnd= Math.max(myStart, myEnd);
99
100         int yoursStart= fOffset;
101         int yoursEnd= fOffset + fReplaceLength -1;
102         yoursEnd= Math.max(yoursStart, yoursEnd);
103
104         if (myEnd < yoursStart)
105             return;
106
107         if (fLength <= 0) {
108
109             if (myStart < yoursStart)
110                 fPosition.length += fReplaceLength;
111             else
112                 fPosition.offset += fReplaceLength;
113
114         } else {
115
116             if (myStart <= yoursStart && fOriginalPosition.offset <= yoursStart)
117                 fPosition.length += fReplaceLength;
118             else
119                 fPosition.offset += fReplaceLength;
120         }
121     }
122
123     /**
124      * Adapts the currently investigated position to a deletion.
125      */

126     protected void adaptToRemove() {
127
128         int myStart= fPosition.offset;
129         int myEnd= fPosition.offset + fPosition.length -1;
130         myEnd= Math.max(myStart, myEnd);
131
132         int yoursStart= fOffset;
133         int yoursEnd= fOffset + fLength -1;
134         yoursEnd= Math.max(yoursStart, yoursEnd);
135
136         if (myEnd < yoursStart)
137             return;
138
139         if (myStart <= yoursStart) {
140
141             if (yoursEnd <= myEnd)
142                 fPosition.length -= fLength;
143             else
144                 fPosition.length -= (myEnd - yoursStart +1);
145
146         } else if (yoursStart < myStart) {
147
148             if (yoursEnd < myStart)
149                 fPosition.offset -= fLength;
150             else {
151                 fPosition.offset -= (myStart - yoursStart);
152                 fPosition.length -= (yoursEnd - myStart +1);
153             }
154
155         }
156
157         // validate position to allowed values
158
if (fPosition.offset < 0)
159             fPosition.offset= 0;
160
161         if (fPosition.length < 0)
162             fPosition.length= 0;
163     }
164
165     /**
166      * Adapts the currently investigated position to the replace operation.
167      * First it checks whether the change replaces the whole range of the position.
168      * If not, it performs first the deletion of the previous text and afterwards
169      * the insertion of the new text.
170      */

171     protected void adaptToReplace() {
172
173         if (fPosition.offset == fOffset && fPosition.length == fLength && fPosition.length > 0) {
174
175             // replace the whole range of the position
176
fPosition.length += (fReplaceLength - fLength);
177             if (fPosition.length < 0) {
178                 fPosition.offset += fPosition.length;
179                 fPosition.length= 0;
180             }
181
182         } else {
183
184             if (fLength > 0)
185                 adaptToRemove();
186
187             if (fReplaceLength > 0)
188                 adaptToInsert();
189         }
190     }
191
192     /**
193      * Determines whether the currently investigated position has been deleted by
194      * the replace operation specified in the current event. If so, it deletes
195      * the position and removes it from the document's position category.
196      *
197      * @return <code>true</code> if position has been deleted
198      */

199     protected boolean notDeleted() {
200
201         if (fOffset < fPosition.offset && (fPosition.offset + fPosition.length < fOffset + fLength)) {
202
203             fPosition.delete();
204
205             try {
206                 fDocument.removePosition(fCategory, fPosition);
207             } catch (BadPositionCategoryException x) {
208             }
209
210             return false;
211         }
212
213         return true;
214     }
215
216     /*
217      * @see org.eclipse.jface.text.IPositionUpdater#update(org.eclipse.jface.text.DocumentEvent)
218      */

219     public void update(DocumentEvent event) {
220
221         try {
222
223
224             fOffset= event.getOffset();
225             fLength= event.getLength();
226             fReplaceLength= (event.getText() == null ? 0 : event.getText().length());
227             fDocument= event.getDocument();
228
229             Position[] category= fDocument.getPositions(fCategory);
230             for (int i= 0; i < category.length; i++) {
231
232                 fPosition= category[i];
233                 fOriginalPosition.offset= fPosition.offset;
234                 fOriginalPosition.length= fPosition.length;
235
236                 if (notDeleted())
237                     adaptToReplace();
238             }
239
240         } catch (BadPositionCategoryException x) {
241             // do nothing
242
} finally {
243             fDocument= null;
244         }
245     }
246 }
247
Popular Tags