KickJava   Java API By Example, From Geeks To Geeks.

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


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 import java.util.ArrayList JavaDoc;
14 import java.util.List JavaDoc;
15
16 import org.eclipse.jface.text.AbstractLineTracker.DelimiterInfo;
17
18 /**
19  * Abstract, read-only implementation of <code>ILineTracker</code>. It lets the definition of
20  * line delimiters to subclasses. Assuming that '\n' is the only line delimiter, this abstract
21  * implementation defines the following line scheme:
22  * <ul>
23  * <li> "" -> [0,0]
24  * <li> "a" -> [0,1]
25  * <li> "\n" -> [0,1], [1,0]
26  * <li> "a\n" -> [0,2], [2,0]
27  * <li> "a\nb" -> [0,2], [2,1]
28  * <li> "a\nbc\n" -> [0,2], [2,3], [5,0]
29  * </ul>
30  * This class must be subclassed.
31  *
32  * @since 3.2
33  */

34 abstract class ListLineTracker implements ILineTracker {
35
36     /** The line information */
37     private final List JavaDoc fLines= new ArrayList JavaDoc();
38     /** The length of the tracked text */
39     private int fTextLength;
40
41     /**
42      * Creates a new line tracker.
43      */

44     protected ListLineTracker() {
45     }
46
47     /**
48      * Binary search for the line at a given offset.
49      *
50      * @param offset the offset whose line should be found
51      * @return the line of the offset
52      */

53     private int findLine(int offset) {
54
55         if (fLines.size() == 0)
56             return -1;
57
58         int left= 0;
59         int right= fLines.size() - 1;
60         int mid= 0;
61         Line line= null;
62
63         while (left < right) {
64
65             mid= (left + right) / 2;
66
67             line= (Line) fLines.get(mid);
68             if (offset < line.offset) {
69                 if (left == mid)
70                     right= left;
71                 else
72                     right= mid - 1;
73             } else if (offset > line.offset) {
74                 if (right == mid)
75                     left= right;
76                 else
77                     left= mid + 1;
78             } else if (offset == line.offset) {
79                 left= right= mid;
80             }
81         }
82
83         line= (Line) fLines.get(left);
84         if (line.offset > offset)
85             --left;
86         return left;
87     }
88
89     /**
90      * Returns the number of lines covered by the specified text range.
91      *
92      * @param startLine the line where the text range starts
93      * @param offset the start offset of the text range
94      * @param length the length of the text range
95      * @return the number of lines covered by this text range
96      * @exception BadLocationException if range is undefined in this tracker
97      */

98     private int getNumberOfLines(int startLine, int offset, int length) throws BadLocationException {
99
100         if (length == 0)
101             return 1;
102
103         int target= offset + length;
104
105         Line l= (Line) fLines.get(startLine);
106
107         if (l.delimiter == null)
108             return 1;
109
110         if (l.offset + l.length > target)
111             return 1;
112
113         if (l.offset + l.length == target)
114             return 2;
115
116         return getLineNumberOfOffset(target) - startLine + 1;
117     }
118
119     /*
120      * @see org.eclipse.jface.text.ILineTracker#getLineLength(int)
121      */

122     public final int getLineLength(int line) throws BadLocationException {
123         int lines= fLines.size();
124
125         if (line < 0 || line > lines)
126             throw new BadLocationException();
127
128         if (lines == 0 || lines == line)
129             return 0;
130
131         Line l= (Line) fLines.get(line);
132         return l.length;
133     }
134
135     /*
136      * @see org.eclipse.jface.text.ILineTracker#getLineNumberOfOffset(int)
137      */

138     public final int getLineNumberOfOffset(int position) throws BadLocationException {
139         if (position < 0 || position > fTextLength)
140             throw new BadLocationException();
141
142         if (position == fTextLength) {
143
144             int lastLine= fLines.size() - 1;
145             if (lastLine < 0)
146                 return 0;
147
148             Line l= (Line) fLines.get(lastLine);
149             return (l.delimiter != null ? lastLine + 1 : lastLine);
150         }
151
152         return findLine(position);
153     }
154
155     /*
156      * @see org.eclipse.jface.text.ILineTracker#getLineInformationOfOffset(int)
157      */

158     public final IRegion getLineInformationOfOffset(int position) throws BadLocationException {
159         if (position > fTextLength)
160             throw new BadLocationException();
161
162         if (position == fTextLength) {
163             int size= fLines.size();
164             if (size == 0)
165                 return new Region(0, 0);
166             Line l= (Line) fLines.get(size - 1);
167             return (l.delimiter != null ? new Line(fTextLength, 0) : new Line(fTextLength - l.length, l.length));
168         }
169
170         return getLineInformation(findLine(position));
171     }
172
173     /*
174      * @see org.eclipse.jface.text.ILineTracker#getLineInformation(int)
175      */

176     public final IRegion getLineInformation(int line) throws BadLocationException {
177         int lines= fLines.size();
178
179         if (line < 0 || line > lines)
180             throw new BadLocationException();
181
182         if (lines == 0)
183             return new Line(0, 0);
184
185         if (line == lines) {
186             Line l= (Line) fLines.get(line - 1);
187             return new Line(l.offset + l.length, 0);
188         }
189
190         Line l= (Line) fLines.get(line);
191         return (l.delimiter != null ? new Line(l.offset, l.length - l.delimiter.length()) : l);
192     }
193
194     /*
195      * @see org.eclipse.jface.text.ILineTracker#getLineOffset(int)
196      */

197     public final int getLineOffset(int line) throws BadLocationException {
198         int lines= fLines.size();
199
200         if (line < 0 || line > lines)
201             throw new BadLocationException();
202
203         if (lines == 0)
204             return 0;
205
206         if (line == lines) {
207             Line l= (Line) fLines.get(line - 1);
208             if (l.delimiter != null)
209                 return l.offset + l.length;
210             throw new BadLocationException();
211         }
212
213         Line l= (Line) fLines.get(line);
214         return l.offset;
215     }
216
217     /*
218      * @see org.eclipse.jface.text.ILineTracker#getNumberOfLines()
219      */

220     public final int getNumberOfLines() {
221         int lines= fLines.size();
222
223         if (lines == 0)
224             return 1;
225
226         Line l= (Line) fLines.get(lines - 1);
227         return (l.delimiter != null ? lines + 1 : lines);
228     }
229
230     /*
231      * @see org.eclipse.jface.text.ILineTracker#getNumberOfLines(int, int)
232      */

233     public final int getNumberOfLines(int position, int length) throws BadLocationException {
234
235         if (position < 0 || position + length > fTextLength)
236             throw new BadLocationException();
237
238         if (length == 0) // optimization
239
return 1;
240
241         return getNumberOfLines(getLineNumberOfOffset(position), position, length);
242     }
243
244     /*
245      * @see org.eclipse.jface.text.ILineTracker#computeNumberOfLines(java.lang.String)
246      */

247     public final int computeNumberOfLines(String JavaDoc text) {
248         int count= 0;
249         int start= 0;
250         DelimiterInfo delimiterInfo= nextDelimiterInfo(text, start);
251         while (delimiterInfo != null && delimiterInfo.delimiterIndex > -1) {
252             ++count;
253             start= delimiterInfo.delimiterIndex + delimiterInfo.delimiterLength;
254             delimiterInfo= nextDelimiterInfo(text, start);
255         }
256         return count;
257     }
258
259     /*
260      * @see org.eclipse.jface.text.ILineTracker#getLineDelimiter(int)
261      */

262     public final String JavaDoc getLineDelimiter(int line) throws BadLocationException {
263         int lines= fLines.size();
264
265         if (line < 0 || line > lines)
266             throw new BadLocationException();
267
268         if (lines == 0)
269             return null;
270
271         if (line == lines)
272             return null;
273
274         Line l= (Line) fLines.get(line);
275         return l.delimiter;
276     }
277
278     /**
279      * Returns the information about the first delimiter found in the given text starting at the
280      * given offset.
281      *
282      * @param text the text to be searched
283      * @param offset the offset in the given text
284      * @return the information of the first found delimiter or <code>null</code>
285      */

286     protected abstract DelimiterInfo nextDelimiterInfo(String JavaDoc text, int offset);
287
288     /**
289      * Creates the line structure for the given text. Newly created lines are inserted into the line
290      * structure starting at the given position. Returns the number of newly created lines.
291      *
292      * @param text the text for which to create a line structure
293      * @param insertPosition the position at which the newly created lines are inserted into the
294      * tracker's line structure
295      * @param offset the offset of all newly created lines
296      * @return the number of newly created lines
297      */

298     private int createLines(String JavaDoc text, int insertPosition, int offset) {
299
300         int count= 0;
301         int start= 0;
302         DelimiterInfo delimiterInfo= nextDelimiterInfo(text, 0);
303
304         while (delimiterInfo != null && delimiterInfo.delimiterIndex > -1) {
305
306             int index= delimiterInfo.delimiterIndex + (delimiterInfo.delimiterLength - 1);
307
308             if (insertPosition + count >= fLines.size())
309                 fLines.add(new Line(offset + start, offset + index, delimiterInfo.delimiter));
310             else
311                 fLines.add(insertPosition + count, new Line(offset + start, offset + index, delimiterInfo.delimiter));
312
313             ++count;
314             start= index + 1;
315             delimiterInfo= nextDelimiterInfo(text, start);
316         }
317
318         if (start < text.length()) {
319             if (insertPosition + count < fLines.size()) {
320                 // there is a line below the current
321
Line l= (Line) fLines.get(insertPosition + count);
322                 int delta= text.length() - start;
323                 l.offset-= delta;
324                 l.length+= delta;
325             } else {
326                 fLines.add(new Line(offset + start, offset + text.length() - 1, null));
327                 ++count;
328             }
329         }
330
331         return count;
332     }
333
334     /*
335      * @see org.eclipse.jface.text.ILineTracker#replace(int, int, java.lang.String)
336      */

337     public final void replace(int position, int length, String JavaDoc text) throws BadLocationException {
338         throw new UnsupportedOperationException JavaDoc();
339     }
340
341     /*
342      * @see org.eclipse.jface.text.ILineTracker#set(java.lang.String)
343      */

344     public final void set(String JavaDoc text) {
345         fLines.clear();
346         if (text != null) {
347             fTextLength= text.length();
348             createLines(text, 0, 0);
349         }
350     }
351
352     /**
353      * Returns the internal data structure, a {@link List} of {@link Line}s. Used only by
354      * {@link TreeLineTracker#TreeLineTracker(ListLineTracker)}.
355      *
356      * @return the internal list of lines.
357      */

358     final List JavaDoc getLines() {
359         return fLines;
360     }
361 }
362
Popular Tags