Mercurial > projects > dwt-addons
annotate dwtx/jface/text/TextPresentation.d @ 153:f70d9508c95c
Fix java Collection imports
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 25 Aug 2008 00:27:31 +0200 |
parents | 26688fec6d23 |
children | 25f1f92fa3df |
rev | line source |
---|---|
129 | 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 | |
131 | 15 import dwtx.jface.text.IDocumentPartitioningListener; // packageimport |
16 import dwtx.jface.text.DefaultTextHover; // packageimport | |
17 import dwtx.jface.text.AbstractInformationControl; // packageimport | |
18 import dwtx.jface.text.TextUtilities; // packageimport | |
19 import dwtx.jface.text.IInformationControlCreatorExtension; // packageimport | |
20 import dwtx.jface.text.AbstractInformationControlManager; // packageimport | |
21 import dwtx.jface.text.ITextViewerExtension2; // packageimport | |
22 import dwtx.jface.text.IDocumentPartitioner; // packageimport | |
23 import dwtx.jface.text.DefaultIndentLineAutoEditStrategy; // packageimport | |
24 import dwtx.jface.text.ITextSelection; // packageimport | |
25 import dwtx.jface.text.Document; // packageimport | |
26 import dwtx.jface.text.FindReplaceDocumentAdapterContentProposalProvider; // packageimport | |
27 import dwtx.jface.text.ITextListener; // packageimport | |
28 import dwtx.jface.text.BadPartitioningException; // packageimport | |
29 import dwtx.jface.text.ITextViewerExtension5; // packageimport | |
30 import dwtx.jface.text.IDocumentPartitionerExtension3; // packageimport | |
31 import dwtx.jface.text.IUndoManager; // packageimport | |
32 import dwtx.jface.text.ITextHoverExtension2; // packageimport | |
33 import dwtx.jface.text.IRepairableDocument; // packageimport | |
34 import dwtx.jface.text.IRewriteTarget; // packageimport | |
35 import dwtx.jface.text.DefaultPositionUpdater; // packageimport | |
36 import dwtx.jface.text.RewriteSessionEditProcessor; // packageimport | |
37 import dwtx.jface.text.TextViewerHoverManager; // packageimport | |
38 import dwtx.jface.text.DocumentRewriteSession; // packageimport | |
39 import dwtx.jface.text.TextViewer; // packageimport | |
40 import dwtx.jface.text.ITextViewerExtension8; // packageimport | |
41 import dwtx.jface.text.RegExMessages; // packageimport | |
42 import dwtx.jface.text.IDelayedInputChangeProvider; // packageimport | |
43 import dwtx.jface.text.ITextOperationTargetExtension; // packageimport | |
44 import dwtx.jface.text.IWidgetTokenOwner; // packageimport | |
45 import dwtx.jface.text.IViewportListener; // packageimport | |
46 import dwtx.jface.text.GapTextStore; // packageimport | |
47 import dwtx.jface.text.MarkSelection; // packageimport | |
48 import dwtx.jface.text.IDocumentPartitioningListenerExtension; // packageimport | |
49 import dwtx.jface.text.IDocumentAdapterExtension; // packageimport | |
50 import dwtx.jface.text.IInformationControlExtension; // packageimport | |
51 import dwtx.jface.text.IDocumentPartitioningListenerExtension2; // packageimport | |
52 import dwtx.jface.text.DefaultDocumentAdapter; // packageimport | |
53 import dwtx.jface.text.ITextViewerExtension3; // packageimport | |
54 import dwtx.jface.text.IInformationControlCreator; // packageimport | |
55 import dwtx.jface.text.TypedRegion; // packageimport | |
56 import dwtx.jface.text.ISynchronizable; // packageimport | |
57 import dwtx.jface.text.IMarkRegionTarget; // packageimport | |
58 import dwtx.jface.text.TextViewerUndoManager; // packageimport | |
59 import dwtx.jface.text.IRegion; // packageimport | |
60 import dwtx.jface.text.IInformationControlExtension2; // packageimport | |
61 import dwtx.jface.text.IDocumentExtension4; // packageimport | |
62 import dwtx.jface.text.IDocumentExtension2; // packageimport | |
63 import dwtx.jface.text.IDocumentPartitionerExtension2; // packageimport | |
64 import dwtx.jface.text.Assert; // packageimport | |
65 import dwtx.jface.text.DefaultInformationControl; // packageimport | |
66 import dwtx.jface.text.IWidgetTokenOwnerExtension; // packageimport | |
67 import dwtx.jface.text.DocumentClone; // packageimport | |
68 import dwtx.jface.text.DefaultUndoManager; // packageimport | |
69 import dwtx.jface.text.IFindReplaceTarget; // packageimport | |
70 import dwtx.jface.text.IAutoEditStrategy; // packageimport | |
71 import dwtx.jface.text.ILineTrackerExtension; // packageimport | |
72 import dwtx.jface.text.IUndoManagerExtension; // packageimport | |
73 import dwtx.jface.text.TextSelection; // packageimport | |
74 import dwtx.jface.text.DefaultAutoIndentStrategy; // packageimport | |
75 import dwtx.jface.text.IAutoIndentStrategy; // packageimport | |
76 import dwtx.jface.text.IPainter; // packageimport | |
77 import dwtx.jface.text.IInformationControl; // packageimport | |
78 import dwtx.jface.text.IInformationControlExtension3; // packageimport | |
79 import dwtx.jface.text.ITextViewerExtension6; // packageimport | |
80 import dwtx.jface.text.IInformationControlExtension4; // packageimport | |
81 import dwtx.jface.text.DefaultLineTracker; // packageimport | |
82 import dwtx.jface.text.IDocumentInformationMappingExtension; // packageimport | |
83 import dwtx.jface.text.IRepairableDocumentExtension; // packageimport | |
84 import dwtx.jface.text.ITextHover; // packageimport | |
85 import dwtx.jface.text.FindReplaceDocumentAdapter; // packageimport | |
86 import dwtx.jface.text.ILineTracker; // packageimport | |
87 import dwtx.jface.text.Line; // packageimport | |
88 import dwtx.jface.text.ITextViewerExtension; // packageimport | |
89 import dwtx.jface.text.IDocumentAdapter; // packageimport | |
90 import dwtx.jface.text.TextEvent; // packageimport | |
91 import dwtx.jface.text.BadLocationException; // packageimport | |
92 import dwtx.jface.text.AbstractDocument; // packageimport | |
93 import dwtx.jface.text.AbstractLineTracker; // packageimport | |
94 import dwtx.jface.text.TreeLineTracker; // packageimport | |
95 import dwtx.jface.text.ITextPresentationListener; // packageimport | |
96 import dwtx.jface.text.Region; // packageimport | |
97 import dwtx.jface.text.ITextViewer; // packageimport | |
98 import dwtx.jface.text.IDocumentInformationMapping; // packageimport | |
99 import dwtx.jface.text.MarginPainter; // packageimport | |
100 import dwtx.jface.text.IPaintPositionManager; // packageimport | |
101 import dwtx.jface.text.IFindReplaceTargetExtension; // packageimport | |
102 import dwtx.jface.text.ISlaveDocumentManagerExtension; // packageimport | |
103 import dwtx.jface.text.ISelectionValidator; // packageimport | |
104 import dwtx.jface.text.IDocumentExtension; // packageimport | |
105 import dwtx.jface.text.PropagatingFontFieldEditor; // packageimport | |
106 import dwtx.jface.text.ConfigurableLineTracker; // packageimport | |
107 import dwtx.jface.text.SlaveDocumentEvent; // packageimport | |
108 import dwtx.jface.text.IDocumentListener; // packageimport | |
109 import dwtx.jface.text.PaintManager; // packageimport | |
110 import dwtx.jface.text.IFindReplaceTargetExtension3; // packageimport | |
111 import dwtx.jface.text.ITextDoubleClickStrategy; // packageimport | |
112 import dwtx.jface.text.IDocumentExtension3; // packageimport | |
113 import dwtx.jface.text.Position; // packageimport | |
114 import dwtx.jface.text.TextMessages; // packageimport | |
115 import dwtx.jface.text.CopyOnWriteTextStore; // packageimport | |
116 import dwtx.jface.text.WhitespaceCharacterPainter; // packageimport | |
117 import dwtx.jface.text.IPositionUpdater; // packageimport | |
118 import dwtx.jface.text.DefaultTextDoubleClickStrategy; // packageimport | |
119 import dwtx.jface.text.ListLineTracker; // packageimport | |
120 import dwtx.jface.text.ITextInputListener; // packageimport | |
121 import dwtx.jface.text.BadPositionCategoryException; // packageimport | |
122 import dwtx.jface.text.IWidgetTokenKeeperExtension; // packageimport | |
123 import dwtx.jface.text.IInputChangedListener; // packageimport | |
124 import dwtx.jface.text.ITextOperationTarget; // packageimport | |
125 import dwtx.jface.text.IDocumentInformationMappingExtension2; // packageimport | |
126 import dwtx.jface.text.ITextViewerExtension7; // packageimport | |
127 import dwtx.jface.text.IInformationControlExtension5; // packageimport | |
128 import dwtx.jface.text.IDocumentRewriteSessionListener; // packageimport | |
129 import dwtx.jface.text.JFaceTextUtil; // packageimport | |
130 import dwtx.jface.text.AbstractReusableInformationControlCreator; // packageimport | |
131 import dwtx.jface.text.TabsToSpacesConverter; // packageimport | |
132 import dwtx.jface.text.CursorLinePainter; // packageimport | |
133 import dwtx.jface.text.ITextHoverExtension; // packageimport | |
134 import dwtx.jface.text.IEventConsumer; // packageimport | |
135 import dwtx.jface.text.IDocument; // packageimport | |
136 import dwtx.jface.text.IWidgetTokenKeeper; // packageimport | |
137 import dwtx.jface.text.DocumentCommand; // packageimport | |
138 import dwtx.jface.text.TypedPosition; // packageimport | |
139 import dwtx.jface.text.IEditingSupportRegistry; // packageimport | |
140 import dwtx.jface.text.IDocumentPartitionerExtension; // packageimport | |
141 import dwtx.jface.text.AbstractHoverInformationControlManager; // packageimport | |
142 import dwtx.jface.text.IEditingSupport; // packageimport | |
143 import dwtx.jface.text.IMarkSelection; // packageimport | |
144 import dwtx.jface.text.ISlaveDocumentManager; // packageimport | |
145 import dwtx.jface.text.DocumentEvent; // packageimport | |
146 import dwtx.jface.text.DocumentPartitioningChangedEvent; // packageimport | |
147 import dwtx.jface.text.ITextStore; // packageimport | |
148 import dwtx.jface.text.JFaceTextMessages; // packageimport | |
149 import dwtx.jface.text.DocumentRewriteSessionEvent; // packageimport | |
150 import dwtx.jface.text.SequentialRewriteTextStore; // packageimport | |
151 import dwtx.jface.text.DocumentRewriteSessionType; // packageimport | |
152 import dwtx.jface.text.TextAttribute; // packageimport | |
153 import dwtx.jface.text.ITextViewerExtension4; // packageimport | |
154 import dwtx.jface.text.ITypedRegion; // packageimport | |
155 | |
156 | |
129 | 157 import dwt.dwthelper.utils; |
158 | |
153
f70d9508c95c
Fix java Collection imports
Frank Benoit <benoit@tionex.de>
parents:
140
diff
changeset
|
159 import dwtx.dwtxhelper.Collection; |
f70d9508c95c
Fix java Collection imports
Frank Benoit <benoit@tionex.de>
parents:
140
diff
changeset
|
160 |
129 | 161 import java.util.NoSuchElementException; |
162 | |
163 import dwt.DWT; | |
164 import dwt.custom.StyleRange; | |
165 import dwt.custom.StyledText; | |
166 import dwtx.core.runtime.Assert; | |
167 | |
168 | |
169 /** | |
170 * Describes the presentation styles for a section of an indexed text such as a | |
171 * document or string. A text presentation defines a default style for the whole | |
172 * section and in addition style differences for individual subsections. Text | |
173 * presentations can be narrowed down to a particular result window. All methods | |
174 * are result window aware, i.e. ranges outside the result window are always | |
175 * ignored. | |
176 * <p> | |
177 * All iterators provided by a text presentation assume that they enumerate non | |
178 * overlapping, consecutive ranges inside the default range. Thus, all these | |
179 * iterators do not include the default range. The default style range must be | |
180 * explicitly asked for using <code>getDefaultStyleRange</code>. | |
181 */ | |
182 public class TextPresentation { | |
183 | |
184 /** | |
185 * Applies the given presentation to the given text widget. Helper method. | |
186 * | |
187 * @param presentation the style information | |
188 * @param text the widget to which to apply the style information | |
189 * @since 2.0 | |
190 */ | |
191 public static void applyTextPresentation(TextPresentation presentation, StyledText text) { | |
192 | |
193 StyleRange[] ranges= new StyleRange[presentation.getDenumerableRanges()]; | |
194 | |
195 int i= 0; | |
196 Iterator e= presentation.getAllStyleRangeIterator(); | |
197 while (e.hasNext()) | |
134 | 198 ranges[i++]= cast(StyleRange) e.next(); |
129 | 199 |
200 text.setStyleRanges(ranges); | |
201 } | |
202 | |
203 | |
204 | |
205 | |
206 /** | |
207 * Enumerates all the <code>StyleRange</code>s included in the presentation. | |
208 */ | |
209 class FilterIterator : Iterator { | |
210 | |
211 /** The index of the next style range to be enumerated */ | |
212 protected int fIndex; | |
213 /** The upper bound of the indices of style ranges to be enumerated */ | |
214 protected int fLength; | |
215 /** Indicates whether ranges similar to the default range should be enumerated */ | |
216 protected bool fSkipDefaults; | |
217 /** The result window */ | |
218 protected IRegion fWindow; | |
219 | |
220 /** | |
221 * <code>skipDefaults</code> tells the enumeration to skip all those style ranges | |
222 * which define the same style as the presentation's default style range. | |
223 * | |
224 * @param skipDefaults <code>false</code> if ranges similar to the default range should be enumerated | |
225 */ | |
133
7d818bd32d63
Fix ctors to this with gvim regexp
Frank Benoit <benoit@tionex.de>
parents:
131
diff
changeset
|
226 protected this(bool skipDefaults) { |
129 | 227 |
228 fSkipDefaults= skipDefaults; | |
229 | |
230 fWindow= fResultWindow; | |
231 fIndex= getFirstIndexInWindow(fWindow); | |
232 fLength= getFirstIndexAfterWindow(fWindow); | |
233 | |
234 if (fSkipDefaults) | |
235 computeIndex(); | |
236 } | |
237 | |
238 /* | |
239 * @see Iterator#next() | |
240 */ | |
241 public Object next() { | |
242 try { | |
134 | 243 StyleRange r= cast(StyleRange) fRanges.get(fIndex++); |
129 | 244 return createWindowRelativeRange(fWindow, r); |
245 } catch (ArrayIndexOutOfBoundsException x) { | |
246 throw new NoSuchElementException(); | |
247 } finally { | |
248 if (fSkipDefaults) | |
249 computeIndex(); | |
250 } | |
251 } | |
252 | |
253 /* | |
254 * @see Iterator#hasNext() | |
255 */ | |
256 public bool hasNext() { | |
257 return fIndex < fLength; | |
258 } | |
259 | |
260 /* | |
261 * @see Iterator#remove() | |
262 */ | |
263 public void remove() { | |
264 throw new UnsupportedOperationException(); | |
265 } | |
266 | |
267 /** | |
268 * Returns whether the given object should be skipped. | |
269 * | |
270 * @param o the object to be checked | |
271 * @return <code>true</code> if the object should be skipped by the iterator | |
272 */ | |
273 protected bool skip(Object o) { | |
134 | 274 StyleRange r= cast(StyleRange) o; |
129 | 275 return r.similarTo(fDefaultRange); |
276 } | |
277 | |
278 /** | |
279 * Computes the index of the styled range that is the next to be enumerated. | |
280 */ | |
281 protected void computeIndex() { | |
282 while (fIndex < fLength && skip(fRanges.get(fIndex))) | |
283 ++ fIndex; | |
284 } | |
285 } | |
286 | |
287 /** The style information for the range covered by the whole presentation */ | |
288 private StyleRange fDefaultRange; | |
289 /** The member ranges of the presentation */ | |
290 private ArrayList fRanges; | |
291 /** A clipping region against which the presentation can be clipped when asked for results */ | |
292 private IRegion fResultWindow; | |
293 /** | |
294 * The optional extent for this presentation. | |
295 * @since 3.0 | |
296 */ | |
297 private IRegion fExtent; | |
298 | |
299 | |
300 /** | |
301 * Creates a new empty text presentation. | |
302 */ | |
133
7d818bd32d63
Fix ctors to this with gvim regexp
Frank Benoit <benoit@tionex.de>
parents:
131
diff
changeset
|
303 public this() { |
129 | 304 fRanges= new ArrayList(50); |
305 } | |
306 | |
307 /** | |
308 * Creates a new empty text presentation. <code>sizeHint</code> tells the | |
309 * expected size of this presentation. | |
310 * | |
311 * @param sizeHint the expected size of this presentation | |
312 */ | |
133
7d818bd32d63
Fix ctors to this with gvim regexp
Frank Benoit <benoit@tionex.de>
parents:
131
diff
changeset
|
313 public this(int sizeHint) { |
129 | 314 Assert.isTrue(sizeHint > 0); |
315 fRanges= new ArrayList(sizeHint); | |
316 } | |
317 | |
318 /** | |
319 * Creates a new empty text presentation with the given extent. | |
320 * <code>sizeHint</code> tells the expected size of this presentation. | |
321 * | |
322 * @param extent the extent of the created <code>TextPresentation</code> | |
323 * @param sizeHint the expected size of this presentation | |
324 * @since 3.0 | |
325 */ | |
133
7d818bd32d63
Fix ctors to this with gvim regexp
Frank Benoit <benoit@tionex.de>
parents:
131
diff
changeset
|
326 public this(IRegion extent, int sizeHint) { |
129 | 327 this(sizeHint); |
328 Assert.isNotNull(extent); | |
329 fExtent= extent; | |
330 } | |
331 | |
332 /** | |
333 * Sets the result window for this presentation. When dealing with | |
334 * this presentation all ranges which are outside the result window | |
335 * are ignored. For example, the size of the presentation is 0 | |
336 * when there is no range inside the window even if there are ranges | |
337 * outside the window. All methods are aware of the result window. | |
338 * | |
339 * @param resultWindow the result window | |
340 */ | |
341 public void setResultWindow(IRegion resultWindow) { | |
342 fResultWindow= resultWindow; | |
343 } | |
344 | |
345 /** | |
346 * Set the default style range of this presentation. | |
347 * The default style range defines the overall area covered | |
348 * by this presentation and its style information. | |
349 * | |
350 * @param range the range describing the default region | |
351 */ | |
352 public void setDefaultStyleRange(StyleRange range) { | |
353 fDefaultRange= range; | |
354 } | |
355 | |
356 /** | |
357 * Returns this presentation's default style range. The returned <code>StyleRange</code> | |
358 * is relative to the start of the result window. | |
359 * | |
360 * @return this presentation's default style range | |
361 */ | |
362 public StyleRange getDefaultStyleRange() { | |
363 StyleRange range= createWindowRelativeRange(fResultWindow, fDefaultRange); | |
364 if (range is null) | |
365 return null; | |
134 | 366 return cast(StyleRange)range.clone(); |
129 | 367 |
368 } | |
369 | |
370 /** | |
371 * Add the given range to the presentation. The range must be a | |
372 * subrange of the presentation's default range. | |
373 * | |
374 * @param range the range to be added | |
375 */ | |
376 public void addStyleRange(StyleRange range) { | |
377 checkConsistency(range); | |
378 fRanges.add(range); | |
379 } | |
380 | |
381 /** | |
382 * Replaces the given range in this presentation. The range must be a | |
383 * subrange of the presentation's default range. | |
384 * | |
385 * @param range the range to be added | |
386 * @since 3.0 | |
387 */ | |
388 public void replaceStyleRange(StyleRange range) { | |
389 applyStyleRange(range, false); | |
390 } | |
391 | |
392 /** | |
393 * Merges the given range into this presentation. The range must be a | |
394 * subrange of the presentation's default range. | |
395 * | |
396 * @param range the range to be added | |
397 * @since 3.0 | |
398 */ | |
399 public void mergeStyleRange(StyleRange range) { | |
400 applyStyleRange(range, true); | |
401 } | |
402 | |
403 /** | |
404 * Applies the given range to this presentation. The range must be a | |
405 * subrange of the presentation's default range. | |
406 * | |
407 * @param range the range to be added | |
408 * @param merge <code>true</code> if the style should be merged instead of replaced | |
409 * @since 3.0 | |
410 */ | |
411 private void applyStyleRange(StyleRange range, bool merge) { | |
412 if (range.length is 0) | |
413 return; | |
414 | |
415 checkConsistency(range); | |
416 | |
417 int start= range.start; | |
418 int length= range.length; | |
419 int end= start + length; | |
420 | |
421 if (fRanges.size() is 0) { | |
422 StyleRange defaultRange= getDefaultStyleRange(); | |
423 if (defaultRange is null) | |
424 defaultRange= range; | |
425 | |
426 defaultRange.start= start; | |
427 defaultRange.length= length; | |
428 applyStyle(range, defaultRange, merge); | |
429 fRanges.add(defaultRange); | |
430 } else { | |
431 IRegion rangeRegion= new Region(start, length); | |
432 int first= getFirstIndexInWindow(rangeRegion); | |
433 | |
434 if (first is fRanges.size()) { | |
435 StyleRange defaultRange= getDefaultStyleRange(); | |
436 if (defaultRange is null) | |
437 defaultRange= range; | |
438 defaultRange.start= start; | |
439 defaultRange.length= length; | |
440 applyStyle(range, defaultRange, merge); | |
441 fRanges.add(defaultRange); | |
442 return; | |
443 } | |
444 | |
445 int last= getFirstIndexAfterWindow(rangeRegion); | |
446 for (int i= first; i < last && length > 0; i++) { | |
447 | |
134 | 448 StyleRange current= cast(StyleRange)fRanges.get(i); |
129 | 449 int currentStart= current.start; |
450 int currentEnd= currentStart + current.length; | |
451 | |
452 if (end <= currentStart) { | |
453 fRanges.add(i, range); | |
454 return; | |
455 } | |
456 | |
457 if (start >= currentEnd) | |
458 continue; | |
459 | |
460 StyleRange currentCopy= null; | |
461 if (end < currentEnd) | |
134 | 462 currentCopy= cast(StyleRange)current.clone(); |
129 | 463 |
464 if (start < currentStart) { | |
465 // Apply style to new default range and add it | |
466 StyleRange defaultRange= getDefaultStyleRange(); | |
467 if (defaultRange is null) | |
468 defaultRange= new StyleRange(); | |
469 | |
470 defaultRange.start= start; | |
471 defaultRange.length= currentStart - start; | |
472 applyStyle(range, defaultRange, merge); | |
473 fRanges.add(i, defaultRange); | |
474 i++; last++; | |
475 | |
476 | |
477 // Apply style to first part of current range | |
478 current.length= Math.min(end, currentEnd) - currentStart; | |
479 applyStyle(range, current, merge); | |
480 } | |
481 | |
482 if (start >= currentStart) { | |
483 // Shorten the current range | |
484 current.length= start - currentStart; | |
485 | |
486 // Apply the style to the rest of the current range and add it | |
487 if (current.length > 0) { | |
134 | 488 current= cast(StyleRange)current.clone(); |
129 | 489 i++; last++; |
490 fRanges.add(i, current); | |
491 } | |
492 applyStyle(range, current, merge); | |
493 current.start= start; | |
494 current.length= Math.min(end, currentEnd) - start; | |
495 } | |
496 | |
497 if (end < currentEnd) { | |
498 // Add rest of current range | |
499 currentCopy.start= end; | |
500 currentCopy.length= currentEnd - end; | |
501 i++; last++; | |
502 fRanges.add(i, currentCopy); | |
503 } | |
504 | |
505 // Update range | |
506 range.start= currentEnd; | |
507 range.length= Math.max(end - currentEnd, 0); | |
508 start= range.start; | |
509 length= range.length; | |
510 } | |
511 if (length > 0) { | |
512 // Apply style to new default range and add it | |
513 StyleRange defaultRange= getDefaultStyleRange(); | |
514 if (defaultRange is null) | |
515 defaultRange= range; | |
516 defaultRange.start= start; | |
517 defaultRange.length= end - start; | |
518 applyStyle(range, defaultRange, merge); | |
519 fRanges.add(last, defaultRange); | |
520 } | |
521 } | |
522 } | |
523 | |
524 /** | |
525 * Replaces the given ranges in this presentation. Each range must be a | |
526 * subrange of the presentation's default range. The ranges must be ordered | |
527 * by increasing offset and must not overlap (but may be adjacent). | |
528 * | |
529 * @param ranges the ranges to be added | |
530 * @since 3.0 | |
531 */ | |
532 public void replaceStyleRanges(StyleRange[] ranges) { | |
533 applyStyleRanges(ranges, false); | |
534 } | |
535 | |
536 /** | |
537 * Merges the given ranges into this presentation. Each range must be a | |
538 * subrange of the presentation's default range. The ranges must be ordered | |
539 * by increasing offset and must not overlap (but may be adjacent). | |
540 * | |
541 * @param ranges the ranges to be added | |
542 * @since 3.0 | |
543 */ | |
544 public void mergeStyleRanges(StyleRange[] ranges) { | |
545 applyStyleRanges(ranges, true); | |
546 } | |
547 | |
548 /** | |
549 * Applies the given ranges to this presentation. Each range must be a | |
550 * subrange of the presentation's default range. The ranges must be ordered | |
551 * by increasing offset and must not overlap (but may be adjacent). | |
552 * | |
553 * @param ranges the ranges to be added | |
554 * @param merge <code>true</code> if the style should be merged instead of replaced | |
555 * @since 3.0 | |
556 */ | |
557 private void applyStyleRanges(StyleRange[] ranges, bool merge) { | |
558 int j= 0; | |
559 ArrayList oldRanges= fRanges; | |
560 ArrayList newRanges= new ArrayList(2*ranges.length + oldRanges.size()); | |
561 for (int i= 0, n= ranges.length; i < n; i++) { | |
562 StyleRange range= ranges[i]; | |
563 fRanges= oldRanges; // for getFirstIndexAfterWindow(...) | |
564 for (int m= getFirstIndexAfterWindow(new Region(range.start, range.length)); j < m; j++) | |
565 newRanges.add(oldRanges.get(j)); | |
566 fRanges= newRanges; // for mergeStyleRange(...) | |
567 applyStyleRange(range, merge); | |
568 } | |
569 for (int m= oldRanges.size(); j < m; j++) | |
570 newRanges.add(oldRanges.get(j)); | |
571 fRanges= newRanges; | |
572 } | |
573 | |
574 /** | |
140
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
575 * Applies the template_'s style to the target. |
129 | 576 * |
140
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
577 * @param template_ the style range to be used as template_ |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
578 * @param target the style range to which to apply the template_ |
129 | 579 * @param merge <code>true</code> if the style should be merged instead of replaced |
580 * @since 3.0 | |
581 */ | |
140
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
582 private void applyStyle(StyleRange template_, StyleRange target, bool merge) { |
129 | 583 if (merge) { |
140
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
584 if (template_.font !is null) |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
585 target.font= template_.font; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
586 target.fontStyle|= template_.fontStyle; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
587 |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
588 if (template_.metrics !is null) |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
589 target.metrics= template_.metrics; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
590 |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
591 if (template_.foreground !is null) |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
592 target.foreground= template_.foreground; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
593 if (template_.background !is null) |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
594 target.background= template_.background; |
129 | 595 |
140
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
596 target.strikeout|= template_.strikeout; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
597 if (template_.strikeoutColor !is null) |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
598 target.strikeoutColor= template_.strikeoutColor; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
599 |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
600 target.underline|= template_.underline; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
601 if (template_.underlineStyle !is DWT.NONE) |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
602 target.underlineStyle= template_.underlineStyle; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
603 if (template_.underlineColor !is null) |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
604 target.underlineColor= template_.underlineColor; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
605 |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
606 if (template_.borderStyle !is DWT.NONE) |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
607 target.borderStyle= template_.borderStyle; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
608 if (template_.borderColor !is null) |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
609 target.borderColor= template_.borderColor; |
129 | 610 |
611 } else { | |
140
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
612 target.font= template_.font; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
613 target.fontStyle= template_.fontStyle; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
614 target.metrics= template_.metrics; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
615 target.foreground= template_.foreground; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
616 target.background= template_.background; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
617 target.strikeout= template_.strikeout; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
618 target.strikeoutColor= template_.strikeoutColor; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
619 target.underline= template_.underline; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
620 target.underlineStyle= template_.underlineStyle; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
621 target.underlineColor= template_.underlineColor; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
622 target.borderStyle= template_.borderStyle; |
26688fec6d23
Following dsss compile errors
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
623 target.borderColor= template_.borderColor; |
129 | 624 } |
625 } | |
626 | |
627 /** | |
628 * Checks whether the given range is a subrange of the presentation's | |
629 * default style range. | |
630 * | |
631 * @param range the range to be checked | |
632 * @exception IllegalArgumentException if range is not a subrange of the presentation's default range | |
633 */ | |
634 private void checkConsistency(StyleRange range) { | |
635 | |
636 if (range is null) | |
637 throw new IllegalArgumentException(); | |
638 | |
639 if (fDefaultRange !is null) { | |
640 | |
641 if (range.start < fDefaultRange.start) | |
642 range.start= fDefaultRange.start; | |
643 | |
644 int defaultEnd= fDefaultRange.start + fDefaultRange.length; | |
645 int end= range.start + range.length; | |
646 if (end > defaultEnd) | |
647 range.length -= (end - defaultEnd); | |
648 } | |
649 } | |
650 | |
651 /** | |
652 * Returns the index of the first range which overlaps with the | |
653 * specified window. | |
654 * | |
655 * @param window the window to be used for searching | |
656 * @return the index of the first range overlapping with the window | |
657 */ | |
658 private int getFirstIndexInWindow(IRegion window) { | |
659 if (window !is null) { | |
660 int start= window.getOffset(); | |
661 int i= -1, j= fRanges.size(); | |
662 while (j - i > 1) { | |
663 int k= (i + j) >> 1; | |
134 | 664 StyleRange r= cast(StyleRange) fRanges.get(k); |
129 | 665 if (r.start + r.length > start) |
666 j= k; | |
667 else | |
668 i= k; | |
669 } | |
670 return j; | |
671 } | |
672 return 0; | |
673 } | |
674 | |
675 /** | |
676 * Returns the index of the first range which comes after the specified window and does | |
677 * not overlap with this window. | |
678 * | |
679 * @param window the window to be used for searching | |
680 * @return the index of the first range behind the window and not overlapping with the window | |
681 */ | |
682 private int getFirstIndexAfterWindow(IRegion window) { | |
683 if (window !is null) { | |
684 int end= window.getOffset() + window.getLength(); | |
685 int i= -1, j= fRanges.size(); | |
686 while (j - i > 1) { | |
687 int k= (i + j) >> 1; | |
134 | 688 StyleRange r= cast(StyleRange) fRanges.get(k); |
129 | 689 if (r.start < end) |
690 i= k; | |
691 else | |
692 j= k; | |
693 } | |
694 return j; | |
695 } | |
696 return fRanges.size(); | |
697 } | |
698 | |
699 /** | |
700 * Returns a style range which is relative to the specified window and | |
701 * appropriately clipped if necessary. The original style range is not | |
702 * modified. | |
703 * | |
704 * @param window the reference window | |
705 * @param range the absolute range | |
706 * @return the window relative range based on the absolute range | |
707 */ | |
708 private StyleRange createWindowRelativeRange(IRegion window, StyleRange range) { | |
709 if (window is null || range is null) | |
710 return range; | |
711 | |
712 int start= range.start - window.getOffset(); | |
713 if (start < 0) | |
714 start= 0; | |
715 | |
716 int rangeEnd= range.start + range.length; | |
717 int windowEnd= window.getOffset() + window.getLength(); | |
718 int end= (rangeEnd > windowEnd ? windowEnd : rangeEnd); | |
719 end -= window.getOffset(); | |
720 | |
134 | 721 StyleRange newRange= cast(StyleRange) range.clone(); |
129 | 722 newRange.start= start; |
723 newRange.length= end - start; | |
724 return newRange; | |
725 } | |
726 | |
727 /** | |
728 * Returns the region which is relative to the specified window and | |
729 * appropriately clipped if necessary. | |
730 * | |
731 * @param coverage the absolute coverage | |
732 * @return the window relative region based on the absolute coverage | |
733 * @since 3.0 | |
734 */ | |
735 private IRegion createWindowRelativeRegion(IRegion coverage) { | |
736 if (fResultWindow is null || coverage is null) | |
737 return coverage; | |
738 | |
739 int start= coverage.getOffset() - fResultWindow.getOffset(); | |
740 if (start < 0) | |
741 start= 0; | |
742 | |
743 int rangeEnd= coverage.getOffset() + coverage.getLength(); | |
744 int windowEnd= fResultWindow.getOffset() + fResultWindow.getLength(); | |
745 int end= (rangeEnd > windowEnd ? windowEnd : rangeEnd); | |
746 end -= fResultWindow.getOffset(); | |
747 | |
748 return new Region(start, end - start); | |
749 } | |
750 | |
751 /** | |
752 * Returns an iterator which enumerates all style ranged which define a style | |
753 * different from the presentation's default style range. The default style range | |
754 * is not enumerated. | |
755 * | |
756 * @return a style range iterator | |
757 */ | |
758 public Iterator getNonDefaultStyleRangeIterator() { | |
759 return new FilterIterator(fDefaultRange !is null); | |
760 } | |
761 | |
762 /** | |
763 * Returns an iterator which enumerates all style ranges of this presentation | |
764 * except the default style range. The returned <code>StyleRange</code>s | |
765 * are relative to the start of the presentation's result window. | |
766 * | |
767 * @return a style range iterator | |
768 */ | |
769 public Iterator getAllStyleRangeIterator() { | |
770 return new FilterIterator(false); | |
771 } | |
772 | |
773 /** | |
774 * Returns whether this collection contains any style range including | |
775 * the default style range. | |
776 * | |
777 * @return <code>true</code> if there is no style range in this presentation | |
778 */ | |
779 public bool isEmpty() { | |
780 return (fDefaultRange is null && getDenumerableRanges() is 0); | |
781 } | |
782 | |
783 /** | |
784 * Returns the number of style ranges in the presentation not counting the default | |
785 * style range. | |
786 * | |
787 * @return the number of style ranges in the presentation excluding the default style range | |
788 */ | |
789 public int getDenumerableRanges() { | |
790 int size= getFirstIndexAfterWindow(fResultWindow) - getFirstIndexInWindow(fResultWindow); | |
791 return (size < 0 ? 0 : size); | |
792 } | |
793 | |
794 /** | |
795 * Returns the style range with the smallest offset ignoring the default style range or null | |
796 * if the presentation is empty. | |
797 * | |
798 * @return the style range with the smallest offset different from the default style range | |
799 */ | |
800 public StyleRange getFirstStyleRange() { | |
801 try { | |
802 | |
134 | 803 StyleRange range= cast(StyleRange) fRanges.get(getFirstIndexInWindow(fResultWindow)); |
129 | 804 return createWindowRelativeRange(fResultWindow, range); |
805 | |
806 } catch (NoSuchElementException x) { | |
807 } catch (IndexOutOfBoundsException x) { | |
808 } | |
809 | |
810 return null; | |
811 } | |
812 | |
813 /** | |
814 * Returns the style range with the highest offset ignoring the default style range. | |
815 * | |
816 * @return the style range with the highest offset different from the default style range | |
817 */ | |
818 public StyleRange getLastStyleRange() { | |
819 try { | |
820 | |
134 | 821 StyleRange range= cast(StyleRange) fRanges.get(getFirstIndexAfterWindow(fResultWindow) - 1); |
129 | 822 return createWindowRelativeRange(fResultWindow, range); |
823 | |
824 } catch (NoSuchElementException x) { | |
825 return null; | |
826 } catch (IndexOutOfBoundsException x) { | |
827 return null; | |
828 } | |
829 } | |
830 | |
831 /** | |
832 * Returns the coverage of this presentation as clipped by the presentation's | |
833 * result window. | |
834 * | |
835 * @return the coverage of this presentation | |
836 */ | |
837 public IRegion getCoverage() { | |
838 | |
839 if (fDefaultRange !is null) { | |
840 StyleRange range= getDefaultStyleRange(); | |
841 return new Region(range.start, range.length); | |
842 } | |
843 | |
844 StyleRange first= getFirstStyleRange(); | |
845 StyleRange last= getLastStyleRange(); | |
846 | |
847 if (first is null || last is null) | |
848 return null; | |
849 | |
850 return new Region(first.start, last.start - first. start + last.length); | |
851 } | |
852 | |
853 /** | |
854 * Returns the extent of this presentation clipped by the | |
855 * presentation's result window. | |
856 * | |
857 * @return the clipped extent | |
858 * @since 3.0 | |
859 */ | |
860 public IRegion getExtent() { | |
861 if (fExtent !is null) | |
862 return createWindowRelativeRegion(fExtent); | |
863 return getCoverage(); | |
864 } | |
865 | |
866 /** | |
867 * Clears this presentation by resetting all applied changes. | |
868 * @since 2.0 | |
869 */ | |
870 public void clear() { | |
871 fDefaultRange= null; | |
872 fResultWindow= null; | |
873 fRanges.clear(); | |
874 } | |
875 | |
876 | |
877 } |