Mercurial > projects > dwt-addons
comparison dwtx/jface/text/TextPresentation.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, 2007 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.TextPresentation; | |
14 | |
15 import dwt.dwthelper.utils; | |
16 | |
17 import java.util.ArrayList; | |
18 import java.util.Iterator; | |
19 import java.util.NoSuchElementException; | |
20 | |
21 import dwt.DWT; | |
22 import dwt.custom.StyleRange; | |
23 import dwt.custom.StyledText; | |
24 import dwtx.core.runtime.Assert; | |
25 | |
26 | |
27 /** | |
28 * Describes the presentation styles for a section of an indexed text such as a | |
29 * document or string. A text presentation defines a default style for the whole | |
30 * section and in addition style differences for individual subsections. Text | |
31 * presentations can be narrowed down to a particular result window. All methods | |
32 * are result window aware, i.e. ranges outside the result window are always | |
33 * ignored. | |
34 * <p> | |
35 * All iterators provided by a text presentation assume that they enumerate non | |
36 * overlapping, consecutive ranges inside the default range. Thus, all these | |
37 * iterators do not include the default range. The default style range must be | |
38 * explicitly asked for using <code>getDefaultStyleRange</code>. | |
39 */ | |
40 public class TextPresentation { | |
41 | |
42 /** | |
43 * Applies the given presentation to the given text widget. Helper method. | |
44 * | |
45 * @param presentation the style information | |
46 * @param text the widget to which to apply the style information | |
47 * @since 2.0 | |
48 */ | |
49 public static void applyTextPresentation(TextPresentation presentation, StyledText text) { | |
50 | |
51 StyleRange[] ranges= new StyleRange[presentation.getDenumerableRanges()]; | |
52 | |
53 int i= 0; | |
54 Iterator e= presentation.getAllStyleRangeIterator(); | |
55 while (e.hasNext()) | |
56 ranges[i++]= (StyleRange) e.next(); | |
57 | |
58 text.setStyleRanges(ranges); | |
59 } | |
60 | |
61 | |
62 | |
63 | |
64 /** | |
65 * Enumerates all the <code>StyleRange</code>s included in the presentation. | |
66 */ | |
67 class FilterIterator : Iterator { | |
68 | |
69 /** The index of the next style range to be enumerated */ | |
70 protected int fIndex; | |
71 /** The upper bound of the indices of style ranges to be enumerated */ | |
72 protected int fLength; | |
73 /** Indicates whether ranges similar to the default range should be enumerated */ | |
74 protected bool fSkipDefaults; | |
75 /** The result window */ | |
76 protected IRegion fWindow; | |
77 | |
78 /** | |
79 * <code>skipDefaults</code> tells the enumeration to skip all those style ranges | |
80 * which define the same style as the presentation's default style range. | |
81 * | |
82 * @param skipDefaults <code>false</code> if ranges similar to the default range should be enumerated | |
83 */ | |
84 protected FilterIterator(bool skipDefaults) { | |
85 | |
86 fSkipDefaults= skipDefaults; | |
87 | |
88 fWindow= fResultWindow; | |
89 fIndex= getFirstIndexInWindow(fWindow); | |
90 fLength= getFirstIndexAfterWindow(fWindow); | |
91 | |
92 if (fSkipDefaults) | |
93 computeIndex(); | |
94 } | |
95 | |
96 /* | |
97 * @see Iterator#next() | |
98 */ | |
99 public Object next() { | |
100 try { | |
101 StyleRange r= (StyleRange) fRanges.get(fIndex++); | |
102 return createWindowRelativeRange(fWindow, r); | |
103 } catch (ArrayIndexOutOfBoundsException x) { | |
104 throw new NoSuchElementException(); | |
105 } finally { | |
106 if (fSkipDefaults) | |
107 computeIndex(); | |
108 } | |
109 } | |
110 | |
111 /* | |
112 * @see Iterator#hasNext() | |
113 */ | |
114 public bool hasNext() { | |
115 return fIndex < fLength; | |
116 } | |
117 | |
118 /* | |
119 * @see Iterator#remove() | |
120 */ | |
121 public void remove() { | |
122 throw new UnsupportedOperationException(); | |
123 } | |
124 | |
125 /** | |
126 * Returns whether the given object should be skipped. | |
127 * | |
128 * @param o the object to be checked | |
129 * @return <code>true</code> if the object should be skipped by the iterator | |
130 */ | |
131 protected bool skip(Object o) { | |
132 StyleRange r= (StyleRange) o; | |
133 return r.similarTo(fDefaultRange); | |
134 } | |
135 | |
136 /** | |
137 * Computes the index of the styled range that is the next to be enumerated. | |
138 */ | |
139 protected void computeIndex() { | |
140 while (fIndex < fLength && skip(fRanges.get(fIndex))) | |
141 ++ fIndex; | |
142 } | |
143 } | |
144 | |
145 /** The style information for the range covered by the whole presentation */ | |
146 private StyleRange fDefaultRange; | |
147 /** The member ranges of the presentation */ | |
148 private ArrayList fRanges; | |
149 /** A clipping region against which the presentation can be clipped when asked for results */ | |
150 private IRegion fResultWindow; | |
151 /** | |
152 * The optional extent for this presentation. | |
153 * @since 3.0 | |
154 */ | |
155 private IRegion fExtent; | |
156 | |
157 | |
158 /** | |
159 * Creates a new empty text presentation. | |
160 */ | |
161 public TextPresentation() { | |
162 fRanges= new ArrayList(50); | |
163 } | |
164 | |
165 /** | |
166 * Creates a new empty text presentation. <code>sizeHint</code> tells the | |
167 * expected size of this presentation. | |
168 * | |
169 * @param sizeHint the expected size of this presentation | |
170 */ | |
171 public TextPresentation(int sizeHint) { | |
172 Assert.isTrue(sizeHint > 0); | |
173 fRanges= new ArrayList(sizeHint); | |
174 } | |
175 | |
176 /** | |
177 * Creates a new empty text presentation with the given extent. | |
178 * <code>sizeHint</code> tells the expected size of this presentation. | |
179 * | |
180 * @param extent the extent of the created <code>TextPresentation</code> | |
181 * @param sizeHint the expected size of this presentation | |
182 * @since 3.0 | |
183 */ | |
184 public TextPresentation(IRegion extent, int sizeHint) { | |
185 this(sizeHint); | |
186 Assert.isNotNull(extent); | |
187 fExtent= extent; | |
188 } | |
189 | |
190 /** | |
191 * Sets the result window for this presentation. When dealing with | |
192 * this presentation all ranges which are outside the result window | |
193 * are ignored. For example, the size of the presentation is 0 | |
194 * when there is no range inside the window even if there are ranges | |
195 * outside the window. All methods are aware of the result window. | |
196 * | |
197 * @param resultWindow the result window | |
198 */ | |
199 public void setResultWindow(IRegion resultWindow) { | |
200 fResultWindow= resultWindow; | |
201 } | |
202 | |
203 /** | |
204 * Set the default style range of this presentation. | |
205 * The default style range defines the overall area covered | |
206 * by this presentation and its style information. | |
207 * | |
208 * @param range the range describing the default region | |
209 */ | |
210 public void setDefaultStyleRange(StyleRange range) { | |
211 fDefaultRange= range; | |
212 } | |
213 | |
214 /** | |
215 * Returns this presentation's default style range. The returned <code>StyleRange</code> | |
216 * is relative to the start of the result window. | |
217 * | |
218 * @return this presentation's default style range | |
219 */ | |
220 public StyleRange getDefaultStyleRange() { | |
221 StyleRange range= createWindowRelativeRange(fResultWindow, fDefaultRange); | |
222 if (range is null) | |
223 return null; | |
224 return (StyleRange)range.clone(); | |
225 | |
226 } | |
227 | |
228 /** | |
229 * Add the given range to the presentation. The range must be a | |
230 * subrange of the presentation's default range. | |
231 * | |
232 * @param range the range to be added | |
233 */ | |
234 public void addStyleRange(StyleRange range) { | |
235 checkConsistency(range); | |
236 fRanges.add(range); | |
237 } | |
238 | |
239 /** | |
240 * Replaces the given range in this presentation. The range must be a | |
241 * subrange of the presentation's default range. | |
242 * | |
243 * @param range the range to be added | |
244 * @since 3.0 | |
245 */ | |
246 public void replaceStyleRange(StyleRange range) { | |
247 applyStyleRange(range, false); | |
248 } | |
249 | |
250 /** | |
251 * Merges the given range into this presentation. The range must be a | |
252 * subrange of the presentation's default range. | |
253 * | |
254 * @param range the range to be added | |
255 * @since 3.0 | |
256 */ | |
257 public void mergeStyleRange(StyleRange range) { | |
258 applyStyleRange(range, true); | |
259 } | |
260 | |
261 /** | |
262 * Applies the given range to this presentation. The range must be a | |
263 * subrange of the presentation's default range. | |
264 * | |
265 * @param range the range to be added | |
266 * @param merge <code>true</code> if the style should be merged instead of replaced | |
267 * @since 3.0 | |
268 */ | |
269 private void applyStyleRange(StyleRange range, bool merge) { | |
270 if (range.length is 0) | |
271 return; | |
272 | |
273 checkConsistency(range); | |
274 | |
275 int start= range.start; | |
276 int length= range.length; | |
277 int end= start + length; | |
278 | |
279 if (fRanges.size() is 0) { | |
280 StyleRange defaultRange= getDefaultStyleRange(); | |
281 if (defaultRange is null) | |
282 defaultRange= range; | |
283 | |
284 defaultRange.start= start; | |
285 defaultRange.length= length; | |
286 applyStyle(range, defaultRange, merge); | |
287 fRanges.add(defaultRange); | |
288 } else { | |
289 IRegion rangeRegion= new Region(start, length); | |
290 int first= getFirstIndexInWindow(rangeRegion); | |
291 | |
292 if (first is fRanges.size()) { | |
293 StyleRange defaultRange= getDefaultStyleRange(); | |
294 if (defaultRange is null) | |
295 defaultRange= range; | |
296 defaultRange.start= start; | |
297 defaultRange.length= length; | |
298 applyStyle(range, defaultRange, merge); | |
299 fRanges.add(defaultRange); | |
300 return; | |
301 } | |
302 | |
303 int last= getFirstIndexAfterWindow(rangeRegion); | |
304 for (int i= first; i < last && length > 0; i++) { | |
305 | |
306 StyleRange current= (StyleRange)fRanges.get(i); | |
307 int currentStart= current.start; | |
308 int currentEnd= currentStart + current.length; | |
309 | |
310 if (end <= currentStart) { | |
311 fRanges.add(i, range); | |
312 return; | |
313 } | |
314 | |
315 if (start >= currentEnd) | |
316 continue; | |
317 | |
318 StyleRange currentCopy= null; | |
319 if (end < currentEnd) | |
320 currentCopy= (StyleRange)current.clone(); | |
321 | |
322 if (start < currentStart) { | |
323 // Apply style to new default range and add it | |
324 StyleRange defaultRange= getDefaultStyleRange(); | |
325 if (defaultRange is null) | |
326 defaultRange= new StyleRange(); | |
327 | |
328 defaultRange.start= start; | |
329 defaultRange.length= currentStart - start; | |
330 applyStyle(range, defaultRange, merge); | |
331 fRanges.add(i, defaultRange); | |
332 i++; last++; | |
333 | |
334 | |
335 // Apply style to first part of current range | |
336 current.length= Math.min(end, currentEnd) - currentStart; | |
337 applyStyle(range, current, merge); | |
338 } | |
339 | |
340 if (start >= currentStart) { | |
341 // Shorten the current range | |
342 current.length= start - currentStart; | |
343 | |
344 // Apply the style to the rest of the current range and add it | |
345 if (current.length > 0) { | |
346 current= (StyleRange)current.clone(); | |
347 i++; last++; | |
348 fRanges.add(i, current); | |
349 } | |
350 applyStyle(range, current, merge); | |
351 current.start= start; | |
352 current.length= Math.min(end, currentEnd) - start; | |
353 } | |
354 | |
355 if (end < currentEnd) { | |
356 // Add rest of current range | |
357 currentCopy.start= end; | |
358 currentCopy.length= currentEnd - end; | |
359 i++; last++; | |
360 fRanges.add(i, currentCopy); | |
361 } | |
362 | |
363 // Update range | |
364 range.start= currentEnd; | |
365 range.length= Math.max(end - currentEnd, 0); | |
366 start= range.start; | |
367 length= range.length; | |
368 } | |
369 if (length > 0) { | |
370 // Apply style to new default range and add it | |
371 StyleRange defaultRange= getDefaultStyleRange(); | |
372 if (defaultRange is null) | |
373 defaultRange= range; | |
374 defaultRange.start= start; | |
375 defaultRange.length= end - start; | |
376 applyStyle(range, defaultRange, merge); | |
377 fRanges.add(last, defaultRange); | |
378 } | |
379 } | |
380 } | |
381 | |
382 /** | |
383 * Replaces the given ranges in this presentation. Each range must be a | |
384 * subrange of the presentation's default range. The ranges must be ordered | |
385 * by increasing offset and must not overlap (but may be adjacent). | |
386 * | |
387 * @param ranges the ranges to be added | |
388 * @since 3.0 | |
389 */ | |
390 public void replaceStyleRanges(StyleRange[] ranges) { | |
391 applyStyleRanges(ranges, false); | |
392 } | |
393 | |
394 /** | |
395 * Merges the given ranges into this presentation. Each range must be a | |
396 * subrange of the presentation's default range. The ranges must be ordered | |
397 * by increasing offset and must not overlap (but may be adjacent). | |
398 * | |
399 * @param ranges the ranges to be added | |
400 * @since 3.0 | |
401 */ | |
402 public void mergeStyleRanges(StyleRange[] ranges) { | |
403 applyStyleRanges(ranges, true); | |
404 } | |
405 | |
406 /** | |
407 * Applies the given ranges to this presentation. Each range must be a | |
408 * subrange of the presentation's default range. The ranges must be ordered | |
409 * by increasing offset and must not overlap (but may be adjacent). | |
410 * | |
411 * @param ranges the ranges to be added | |
412 * @param merge <code>true</code> if the style should be merged instead of replaced | |
413 * @since 3.0 | |
414 */ | |
415 private void applyStyleRanges(StyleRange[] ranges, bool merge) { | |
416 int j= 0; | |
417 ArrayList oldRanges= fRanges; | |
418 ArrayList newRanges= new ArrayList(2*ranges.length + oldRanges.size()); | |
419 for (int i= 0, n= ranges.length; i < n; i++) { | |
420 StyleRange range= ranges[i]; | |
421 fRanges= oldRanges; // for getFirstIndexAfterWindow(...) | |
422 for (int m= getFirstIndexAfterWindow(new Region(range.start, range.length)); j < m; j++) | |
423 newRanges.add(oldRanges.get(j)); | |
424 fRanges= newRanges; // for mergeStyleRange(...) | |
425 applyStyleRange(range, merge); | |
426 } | |
427 for (int m= oldRanges.size(); j < m; j++) | |
428 newRanges.add(oldRanges.get(j)); | |
429 fRanges= newRanges; | |
430 } | |
431 | |
432 /** | |
433 * Applies the template's style to the target. | |
434 * | |
435 * @param template the style range to be used as template | |
436 * @param target the style range to which to apply the template | |
437 * @param merge <code>true</code> if the style should be merged instead of replaced | |
438 * @since 3.0 | |
439 */ | |
440 private void applyStyle(StyleRange template, StyleRange target, bool merge) { | |
441 if (merge) { | |
442 if (template.font !is null) | |
443 target.font= template.font; | |
444 target.fontStyle|= template.fontStyle; | |
445 | |
446 if (template.metrics !is null) | |
447 target.metrics= template.metrics; | |
448 | |
449 if (template.foreground !is null) | |
450 target.foreground= template.foreground; | |
451 if (template.background !is null) | |
452 target.background= template.background; | |
453 | |
454 target.strikeout|= template.strikeout; | |
455 if (template.strikeoutColor !is null) | |
456 target.strikeoutColor= template.strikeoutColor; | |
457 | |
458 target.underline|= template.underline; | |
459 if (template.underlineStyle !is DWT.NONE) | |
460 target.underlineStyle= template.underlineStyle; | |
461 if (template.underlineColor !is null) | |
462 target.underlineColor= template.underlineColor; | |
463 | |
464 if (template.borderStyle !is DWT.NONE) | |
465 target.borderStyle= template.borderStyle; | |
466 if (template.borderColor !is null) | |
467 target.borderColor= template.borderColor; | |
468 | |
469 } else { | |
470 target.font= template.font; | |
471 target.fontStyle= template.fontStyle; | |
472 target.metrics= template.metrics; | |
473 target.foreground= template.foreground; | |
474 target.background= template.background; | |
475 target.strikeout= template.strikeout; | |
476 target.strikeoutColor= template.strikeoutColor; | |
477 target.underline= template.underline; | |
478 target.underlineStyle= template.underlineStyle; | |
479 target.underlineColor= template.underlineColor; | |
480 target.borderStyle= template.borderStyle; | |
481 target.borderColor= template.borderColor; | |
482 } | |
483 } | |
484 | |
485 /** | |
486 * Checks whether the given range is a subrange of the presentation's | |
487 * default style range. | |
488 * | |
489 * @param range the range to be checked | |
490 * @exception IllegalArgumentException if range is not a subrange of the presentation's default range | |
491 */ | |
492 private void checkConsistency(StyleRange range) { | |
493 | |
494 if (range is null) | |
495 throw new IllegalArgumentException(); | |
496 | |
497 if (fDefaultRange !is null) { | |
498 | |
499 if (range.start < fDefaultRange.start) | |
500 range.start= fDefaultRange.start; | |
501 | |
502 int defaultEnd= fDefaultRange.start + fDefaultRange.length; | |
503 int end= range.start + range.length; | |
504 if (end > defaultEnd) | |
505 range.length -= (end - defaultEnd); | |
506 } | |
507 } | |
508 | |
509 /** | |
510 * Returns the index of the first range which overlaps with the | |
511 * specified window. | |
512 * | |
513 * @param window the window to be used for searching | |
514 * @return the index of the first range overlapping with the window | |
515 */ | |
516 private int getFirstIndexInWindow(IRegion window) { | |
517 if (window !is null) { | |
518 int start= window.getOffset(); | |
519 int i= -1, j= fRanges.size(); | |
520 while (j - i > 1) { | |
521 int k= (i + j) >> 1; | |
522 StyleRange r= (StyleRange) fRanges.get(k); | |
523 if (r.start + r.length > start) | |
524 j= k; | |
525 else | |
526 i= k; | |
527 } | |
528 return j; | |
529 } | |
530 return 0; | |
531 } | |
532 | |
533 /** | |
534 * Returns the index of the first range which comes after the specified window and does | |
535 * not overlap with this window. | |
536 * | |
537 * @param window the window to be used for searching | |
538 * @return the index of the first range behind the window and not overlapping with the window | |
539 */ | |
540 private int getFirstIndexAfterWindow(IRegion window) { | |
541 if (window !is null) { | |
542 int end= window.getOffset() + window.getLength(); | |
543 int i= -1, j= fRanges.size(); | |
544 while (j - i > 1) { | |
545 int k= (i + j) >> 1; | |
546 StyleRange r= (StyleRange) fRanges.get(k); | |
547 if (r.start < end) | |
548 i= k; | |
549 else | |
550 j= k; | |
551 } | |
552 return j; | |
553 } | |
554 return fRanges.size(); | |
555 } | |
556 | |
557 /** | |
558 * Returns a style range which is relative to the specified window and | |
559 * appropriately clipped if necessary. The original style range is not | |
560 * modified. | |
561 * | |
562 * @param window the reference window | |
563 * @param range the absolute range | |
564 * @return the window relative range based on the absolute range | |
565 */ | |
566 private StyleRange createWindowRelativeRange(IRegion window, StyleRange range) { | |
567 if (window is null || range is null) | |
568 return range; | |
569 | |
570 int start= range.start - window.getOffset(); | |
571 if (start < 0) | |
572 start= 0; | |
573 | |
574 int rangeEnd= range.start + range.length; | |
575 int windowEnd= window.getOffset() + window.getLength(); | |
576 int end= (rangeEnd > windowEnd ? windowEnd : rangeEnd); | |
577 end -= window.getOffset(); | |
578 | |
579 StyleRange newRange= (StyleRange) range.clone(); | |
580 newRange.start= start; | |
581 newRange.length= end - start; | |
582 return newRange; | |
583 } | |
584 | |
585 /** | |
586 * Returns the region which is relative to the specified window and | |
587 * appropriately clipped if necessary. | |
588 * | |
589 * @param coverage the absolute coverage | |
590 * @return the window relative region based on the absolute coverage | |
591 * @since 3.0 | |
592 */ | |
593 private IRegion createWindowRelativeRegion(IRegion coverage) { | |
594 if (fResultWindow is null || coverage is null) | |
595 return coverage; | |
596 | |
597 int start= coverage.getOffset() - fResultWindow.getOffset(); | |
598 if (start < 0) | |
599 start= 0; | |
600 | |
601 int rangeEnd= coverage.getOffset() + coverage.getLength(); | |
602 int windowEnd= fResultWindow.getOffset() + fResultWindow.getLength(); | |
603 int end= (rangeEnd > windowEnd ? windowEnd : rangeEnd); | |
604 end -= fResultWindow.getOffset(); | |
605 | |
606 return new Region(start, end - start); | |
607 } | |
608 | |
609 /** | |
610 * Returns an iterator which enumerates all style ranged which define a style | |
611 * different from the presentation's default style range. The default style range | |
612 * is not enumerated. | |
613 * | |
614 * @return a style range iterator | |
615 */ | |
616 public Iterator getNonDefaultStyleRangeIterator() { | |
617 return new FilterIterator(fDefaultRange !is null); | |
618 } | |
619 | |
620 /** | |
621 * Returns an iterator which enumerates all style ranges of this presentation | |
622 * except the default style range. The returned <code>StyleRange</code>s | |
623 * are relative to the start of the presentation's result window. | |
624 * | |
625 * @return a style range iterator | |
626 */ | |
627 public Iterator getAllStyleRangeIterator() { | |
628 return new FilterIterator(false); | |
629 } | |
630 | |
631 /** | |
632 * Returns whether this collection contains any style range including | |
633 * the default style range. | |
634 * | |
635 * @return <code>true</code> if there is no style range in this presentation | |
636 */ | |
637 public bool isEmpty() { | |
638 return (fDefaultRange is null && getDenumerableRanges() is 0); | |
639 } | |
640 | |
641 /** | |
642 * Returns the number of style ranges in the presentation not counting the default | |
643 * style range. | |
644 * | |
645 * @return the number of style ranges in the presentation excluding the default style range | |
646 */ | |
647 public int getDenumerableRanges() { | |
648 int size= getFirstIndexAfterWindow(fResultWindow) - getFirstIndexInWindow(fResultWindow); | |
649 return (size < 0 ? 0 : size); | |
650 } | |
651 | |
652 /** | |
653 * Returns the style range with the smallest offset ignoring the default style range or null | |
654 * if the presentation is empty. | |
655 * | |
656 * @return the style range with the smallest offset different from the default style range | |
657 */ | |
658 public StyleRange getFirstStyleRange() { | |
659 try { | |
660 | |
661 StyleRange range= (StyleRange) fRanges.get(getFirstIndexInWindow(fResultWindow)); | |
662 return createWindowRelativeRange(fResultWindow, range); | |
663 | |
664 } catch (NoSuchElementException x) { | |
665 } catch (IndexOutOfBoundsException x) { | |
666 } | |
667 | |
668 return null; | |
669 } | |
670 | |
671 /** | |
672 * Returns the style range with the highest offset ignoring the default style range. | |
673 * | |
674 * @return the style range with the highest offset different from the default style range | |
675 */ | |
676 public StyleRange getLastStyleRange() { | |
677 try { | |
678 | |
679 StyleRange range= (StyleRange) fRanges.get(getFirstIndexAfterWindow(fResultWindow) - 1); | |
680 return createWindowRelativeRange(fResultWindow, range); | |
681 | |
682 } catch (NoSuchElementException x) { | |
683 return null; | |
684 } catch (IndexOutOfBoundsException x) { | |
685 return null; | |
686 } | |
687 } | |
688 | |
689 /** | |
690 * Returns the coverage of this presentation as clipped by the presentation's | |
691 * result window. | |
692 * | |
693 * @return the coverage of this presentation | |
694 */ | |
695 public IRegion getCoverage() { | |
696 | |
697 if (fDefaultRange !is null) { | |
698 StyleRange range= getDefaultStyleRange(); | |
699 return new Region(range.start, range.length); | |
700 } | |
701 | |
702 StyleRange first= getFirstStyleRange(); | |
703 StyleRange last= getLastStyleRange(); | |
704 | |
705 if (first is null || last is null) | |
706 return null; | |
707 | |
708 return new Region(first.start, last.start - first. start + last.length); | |
709 } | |
710 | |
711 /** | |
712 * Returns the extent of this presentation clipped by the | |
713 * presentation's result window. | |
714 * | |
715 * @return the clipped extent | |
716 * @since 3.0 | |
717 */ | |
718 public IRegion getExtent() { | |
719 if (fExtent !is null) | |
720 return createWindowRelativeRegion(fExtent); | |
721 return getCoverage(); | |
722 } | |
723 | |
724 /** | |
725 * Clears this presentation by resetting all applied changes. | |
726 * @since 2.0 | |
727 */ | |
728 public void clear() { | |
729 fDefaultRange= null; | |
730 fResultWindow= null; | |
731 fRanges.clear(); | |
732 } | |
733 | |
734 | |
735 } |