Mercurial > projects > dwt-addons
comparison dwtx/jface/text/ListLineTracker.d @ 129:eb30df5ca28b
Added JFace Text sources
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 23 Aug 2008 19:10:48 +0200 |
parents | |
children | c4fb132a086c |
comparison
equal
deleted
inserted
replaced
128:8df1d4193877 | 129:eb30df5ca28b |
---|---|
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 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module dwtx.jface.text.ListLineTracker; | |
14 | |
15 import dwt.dwthelper.utils; | |
16 | |
17 import java.util.ArrayList; | |
18 import java.util.List; | |
19 | |
20 import dwtx.jface.text.AbstractLineTracker.DelimiterInfo; | |
21 | |
22 /** | |
23 * Abstract, read-only implementation of <code>ILineTracker</code>. It lets the definition of | |
24 * line delimiters to subclasses. Assuming that '\n' is the only line delimiter, this abstract | |
25 * implementation defines the following line scheme: | |
26 * <ul> | |
27 * <li> "" -> [0,0] | |
28 * <li> "a" -> [0,1] | |
29 * <li> "\n" -> [0,1], [1,0] | |
30 * <li> "a\n" -> [0,2], [2,0] | |
31 * <li> "a\nb" -> [0,2], [2,1] | |
32 * <li> "a\nbc\n" -> [0,2], [2,3], [5,0] | |
33 * </ul> | |
34 * This class must be subclassed. | |
35 * | |
36 * @since 3.2 | |
37 */ | |
38 abstract class ListLineTracker : ILineTracker { | |
39 | |
40 /** The line information */ | |
41 private final List fLines= new ArrayList(); | |
42 /** The length of the tracked text */ | |
43 private int fTextLength; | |
44 | |
45 /** | |
46 * Creates a new line tracker. | |
47 */ | |
48 protected ListLineTracker() { | |
49 } | |
50 | |
51 /** | |
52 * Binary search for the line at a given offset. | |
53 * | |
54 * @param offset the offset whose line should be found | |
55 * @return the line of the offset | |
56 */ | |
57 private int findLine(int offset) { | |
58 | |
59 if (fLines.size() is 0) | |
60 return -1; | |
61 | |
62 int left= 0; | |
63 int right= fLines.size() - 1; | |
64 int mid= 0; | |
65 Line line= null; | |
66 | |
67 while (left < right) { | |
68 | |
69 mid= (left + right) / 2; | |
70 | |
71 line= (Line) fLines.get(mid); | |
72 if (offset < line.offset) { | |
73 if (left is mid) | |
74 right= left; | |
75 else | |
76 right= mid - 1; | |
77 } else if (offset > line.offset) { | |
78 if (right is mid) | |
79 left= right; | |
80 else | |
81 left= mid + 1; | |
82 } else if (offset is line.offset) { | |
83 left= right= mid; | |
84 } | |
85 } | |
86 | |
87 line= (Line) fLines.get(left); | |
88 if (line.offset > offset) | |
89 --left; | |
90 return left; | |
91 } | |
92 | |
93 /** | |
94 * Returns the number of lines covered by the specified text range. | |
95 * | |
96 * @param startLine the line where the text range starts | |
97 * @param offset the start offset of the text range | |
98 * @param length the length of the text range | |
99 * @return the number of lines covered by this text range | |
100 * @exception BadLocationException if range is undefined in this tracker | |
101 */ | |
102 private int getNumberOfLines(int startLine, int offset, int length) throws BadLocationException { | |
103 | |
104 if (length is 0) | |
105 return 1; | |
106 | |
107 int target= offset + length; | |
108 | |
109 Line l= (Line) fLines.get(startLine); | |
110 | |
111 if (l.delimiter is null) | |
112 return 1; | |
113 | |
114 if (l.offset + l.length > target) | |
115 return 1; | |
116 | |
117 if (l.offset + l.length is target) | |
118 return 2; | |
119 | |
120 return getLineNumberOfOffset(target) - startLine + 1; | |
121 } | |
122 | |
123 /* | |
124 * @see dwtx.jface.text.ILineTracker#getLineLength(int) | |
125 */ | |
126 public final int getLineLength(int line) throws BadLocationException { | |
127 int lines= fLines.size(); | |
128 | |
129 if (line < 0 || line > lines) | |
130 throw new BadLocationException(); | |
131 | |
132 if (lines is 0 || lines is line) | |
133 return 0; | |
134 | |
135 Line l= (Line) fLines.get(line); | |
136 return l.length; | |
137 } | |
138 | |
139 /* | |
140 * @see dwtx.jface.text.ILineTracker#getLineNumberOfOffset(int) | |
141 */ | |
142 public final int getLineNumberOfOffset(int position) throws BadLocationException { | |
143 if (position < 0 || position > fTextLength) | |
144 throw new BadLocationException(); | |
145 | |
146 if (position is fTextLength) { | |
147 | |
148 int lastLine= fLines.size() - 1; | |
149 if (lastLine < 0) | |
150 return 0; | |
151 | |
152 Line l= (Line) fLines.get(lastLine); | |
153 return (l.delimiter !is null ? lastLine + 1 : lastLine); | |
154 } | |
155 | |
156 return findLine(position); | |
157 } | |
158 | |
159 /* | |
160 * @see dwtx.jface.text.ILineTracker#getLineInformationOfOffset(int) | |
161 */ | |
162 public final IRegion getLineInformationOfOffset(int position) throws BadLocationException { | |
163 if (position > fTextLength) | |
164 throw new BadLocationException(); | |
165 | |
166 if (position is fTextLength) { | |
167 int size= fLines.size(); | |
168 if (size is 0) | |
169 return new Region(0, 0); | |
170 Line l= (Line) fLines.get(size - 1); | |
171 return (l.delimiter !is null ? new Line(fTextLength, 0) : new Line(fTextLength - l.length, l.length)); | |
172 } | |
173 | |
174 return getLineInformation(findLine(position)); | |
175 } | |
176 | |
177 /* | |
178 * @see dwtx.jface.text.ILineTracker#getLineInformation(int) | |
179 */ | |
180 public final IRegion getLineInformation(int line) throws BadLocationException { | |
181 int lines= fLines.size(); | |
182 | |
183 if (line < 0 || line > lines) | |
184 throw new BadLocationException(); | |
185 | |
186 if (lines is 0) | |
187 return new Line(0, 0); | |
188 | |
189 if (line is lines) { | |
190 Line l= (Line) fLines.get(line - 1); | |
191 return new Line(l.offset + l.length, 0); | |
192 } | |
193 | |
194 Line l= (Line) fLines.get(line); | |
195 return (l.delimiter !is null ? new Line(l.offset, l.length - l.delimiter.length()) : l); | |
196 } | |
197 | |
198 /* | |
199 * @see dwtx.jface.text.ILineTracker#getLineOffset(int) | |
200 */ | |
201 public final int getLineOffset(int line) throws BadLocationException { | |
202 int lines= fLines.size(); | |
203 | |
204 if (line < 0 || line > lines) | |
205 throw new BadLocationException(); | |
206 | |
207 if (lines is 0) | |
208 return 0; | |
209 | |
210 if (line is lines) { | |
211 Line l= (Line) fLines.get(line - 1); | |
212 if (l.delimiter !is null) | |
213 return l.offset + l.length; | |
214 throw new BadLocationException(); | |
215 } | |
216 | |
217 Line l= (Line) fLines.get(line); | |
218 return l.offset; | |
219 } | |
220 | |
221 /* | |
222 * @see dwtx.jface.text.ILineTracker#getNumberOfLines() | |
223 */ | |
224 public final int getNumberOfLines() { | |
225 int lines= fLines.size(); | |
226 | |
227 if (lines is 0) | |
228 return 1; | |
229 | |
230 Line l= (Line) fLines.get(lines - 1); | |
231 return (l.delimiter !is null ? lines + 1 : lines); | |
232 } | |
233 | |
234 /* | |
235 * @see dwtx.jface.text.ILineTracker#getNumberOfLines(int, int) | |
236 */ | |
237 public final int getNumberOfLines(int position, int length) throws BadLocationException { | |
238 | |
239 if (position < 0 || position + length > fTextLength) | |
240 throw new BadLocationException(); | |
241 | |
242 if (length is 0) // optimization | |
243 return 1; | |
244 | |
245 return getNumberOfLines(getLineNumberOfOffset(position), position, length); | |
246 } | |
247 | |
248 /* | |
249 * @see dwtx.jface.text.ILineTracker#computeNumberOfLines(java.lang.String) | |
250 */ | |
251 public final int computeNumberOfLines(String text) { | |
252 int count= 0; | |
253 int start= 0; | |
254 DelimiterInfo delimiterInfo= nextDelimiterInfo(text, start); | |
255 while (delimiterInfo !is null && delimiterInfo.delimiterIndex > -1) { | |
256 ++count; | |
257 start= delimiterInfo.delimiterIndex + delimiterInfo.delimiterLength; | |
258 delimiterInfo= nextDelimiterInfo(text, start); | |
259 } | |
260 return count; | |
261 } | |
262 | |
263 /* | |
264 * @see dwtx.jface.text.ILineTracker#getLineDelimiter(int) | |
265 */ | |
266 public final String getLineDelimiter(int line) throws BadLocationException { | |
267 int lines= fLines.size(); | |
268 | |
269 if (line < 0 || line > lines) | |
270 throw new BadLocationException(); | |
271 | |
272 if (lines is 0) | |
273 return null; | |
274 | |
275 if (line is lines) | |
276 return null; | |
277 | |
278 Line l= (Line) fLines.get(line); | |
279 return l.delimiter; | |
280 } | |
281 | |
282 /** | |
283 * Returns the information about the first delimiter found in the given text starting at the | |
284 * given offset. | |
285 * | |
286 * @param text the text to be searched | |
287 * @param offset the offset in the given text | |
288 * @return the information of the first found delimiter or <code>null</code> | |
289 */ | |
290 protected abstract DelimiterInfo nextDelimiterInfo(String text, int offset); | |
291 | |
292 /** | |
293 * Creates the line structure for the given text. Newly created lines are inserted into the line | |
294 * structure starting at the given position. Returns the number of newly created lines. | |
295 * | |
296 * @param text the text for which to create a line structure | |
297 * @param insertPosition the position at which the newly created lines are inserted into the | |
298 * tracker's line structure | |
299 * @param offset the offset of all newly created lines | |
300 * @return the number of newly created lines | |
301 */ | |
302 private int createLines(String text, int insertPosition, int offset) { | |
303 | |
304 int count= 0; | |
305 int start= 0; | |
306 DelimiterInfo delimiterInfo= nextDelimiterInfo(text, 0); | |
307 | |
308 while (delimiterInfo !is null && delimiterInfo.delimiterIndex > -1) { | |
309 | |
310 int index= delimiterInfo.delimiterIndex + (delimiterInfo.delimiterLength - 1); | |
311 | |
312 if (insertPosition + count >= fLines.size()) | |
313 fLines.add(new Line(offset + start, offset + index, delimiterInfo.delimiter)); | |
314 else | |
315 fLines.add(insertPosition + count, new Line(offset + start, offset + index, delimiterInfo.delimiter)); | |
316 | |
317 ++count; | |
318 start= index + 1; | |
319 delimiterInfo= nextDelimiterInfo(text, start); | |
320 } | |
321 | |
322 if (start < text.length()) { | |
323 if (insertPosition + count < fLines.size()) { | |
324 // there is a line below the current | |
325 Line l= (Line) fLines.get(insertPosition + count); | |
326 int delta= text.length() - start; | |
327 l.offset-= delta; | |
328 l.length+= delta; | |
329 } else { | |
330 fLines.add(new Line(offset + start, offset + text.length() - 1, null)); | |
331 ++count; | |
332 } | |
333 } | |
334 | |
335 return count; | |
336 } | |
337 | |
338 /* | |
339 * @see dwtx.jface.text.ILineTracker#replace(int, int, java.lang.String) | |
340 */ | |
341 public final void replace(int position, int length, String text) throws BadLocationException { | |
342 throw new UnsupportedOperationException(); | |
343 } | |
344 | |
345 /* | |
346 * @see dwtx.jface.text.ILineTracker#set(java.lang.String) | |
347 */ | |
348 public final void set(String text) { | |
349 fLines.clear(); | |
350 if (text !is null) { | |
351 fTextLength= text.length(); | |
352 createLines(text, 0, 0); | |
353 } | |
354 } | |
355 | |
356 /** | |
357 * Returns the internal data structure, a {@link List} of {@link Line}s. Used only by | |
358 * {@link TreeLineTracker#TreeLineTracker(ListLineTracker)}. | |
359 * | |
360 * @return the internal list of lines. | |
361 */ | |
362 final List getLines() { | |
363 return fLines; | |
364 } | |
365 } |