Mercurial > projects > dwt-addons
annotate dwtx/jface/text/AbstractDocument.d @ 134:51e6e63f930e
Regex fix for casts
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 24 Aug 2008 01:46:20 +0200 |
parents | 7d818bd32d63 |
children | 6dcb0baaa031 |
rev | line source |
---|---|
129 | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2008 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 | |
131 | 14 |
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.AbstractLineTracker; // packageimport | |
93 import dwtx.jface.text.TreeLineTracker; // packageimport | |
94 import dwtx.jface.text.ITextPresentationListener; // packageimport | |
95 import dwtx.jface.text.Region; // packageimport | |
96 import dwtx.jface.text.ITextViewer; // packageimport | |
97 import dwtx.jface.text.IDocumentInformationMapping; // packageimport | |
98 import dwtx.jface.text.MarginPainter; // packageimport | |
99 import dwtx.jface.text.IPaintPositionManager; // packageimport | |
100 import dwtx.jface.text.TextPresentation; // 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 | |
129 | 156 module dwtx.jface.text.AbstractDocument; |
157 | |
158 import dwt.dwthelper.utils; | |
159 | |
160 | |
161 import java.util.ArrayList; | |
162 import java.util.Arrays; | |
163 import java.util.HashMap; | |
164 import java.util.Iterator; | |
165 import java.util.List; | |
166 import java.util.Map; | |
167 import java.util.regex.PatternSyntaxException; | |
168 | |
169 import dwtx.core.runtime.Assert; | |
170 import dwtx.core.runtime.ListenerList; | |
171 | |
172 | |
173 /** | |
174 * Abstract default implementation of <code>IDocument</code> and its extension | |
175 * interfaces {@link dwtx.jface.text.IDocumentExtension}, | |
176 * {@link dwtx.jface.text.IDocumentExtension2}, | |
177 * {@link dwtx.jface.text.IDocumentExtension3}, | |
178 * {@link dwtx.jface.text.IDocumentExtension4}, as well as | |
179 * {@link dwtx.jface.text.IRepairableDocument}. | |
180 * <p> | |
181 * | |
182 * An <code>AbstractDocument</code> supports the following implementation | |
183 * plug-ins: | |
184 * <ul> | |
185 * <li>a text store implementing {@link dwtx.jface.text.ITextStore} for | |
186 * storing and managing the document's content,</li> | |
187 * <li>a line tracker implementing {@link dwtx.jface.text.ILineTracker} | |
188 * to map character positions to line numbers and vice versa</li> | |
189 * </ul> | |
190 * The document can dynamically change the text store when switching between | |
191 * sequential rewrite mode and normal mode. | |
192 * <p> | |
193 * | |
194 * This class must be subclassed. Subclasses must configure which implementation | |
195 * plug-ins the document instance should use. Subclasses are not intended to | |
196 * overwrite existing methods. | |
197 * | |
198 * @see dwtx.jface.text.ITextStore | |
199 * @see dwtx.jface.text.ILineTracker | |
200 */ | |
201 public abstract class AbstractDocument : IDocument, IDocumentExtension, IDocumentExtension2, IDocumentExtension3, IDocumentExtension4, IRepairableDocument, IRepairableDocumentExtension { | |
202 | |
203 /** | |
204 * Tells whether this class is in debug mode. | |
205 * @since 3.1 | |
206 */ | |
207 private static final bool DEBUG= false; | |
208 | |
209 | |
210 /** | |
211 * Inner class to bundle a registered post notification replace operation together with its | |
212 * owner. | |
213 * | |
214 * @since 2.0 | |
215 */ | |
216 static private class RegisteredReplace { | |
217 /** The owner of this replace operation. */ | |
218 IDocumentListener fOwner; | |
219 /** The replace operation */ | |
220 IDocumentExtension.IReplace fReplace; | |
221 | |
222 /** | |
223 * Creates a new bundle object. | |
224 * @param owner the document listener owning the replace operation | |
225 * @param replace the replace operation | |
226 */ | |
133
7d818bd32d63
Fix ctors to this with gvim regexp
Frank Benoit <benoit@tionex.de>
parents:
131
diff
changeset
|
227 this(IDocumentListener owner, IDocumentExtension.IReplace replace) { |
129 | 228 fOwner= owner; |
229 fReplace= replace; | |
230 } | |
231 } | |
232 | |
233 | |
234 /** The document's text store */ | |
235 private ITextStore fStore; | |
236 /** The document's line tracker */ | |
237 private ILineTracker fTracker; | |
238 /** The registered document listeners */ | |
239 private ListenerList fDocumentListeners; | |
240 /** The registered pre-notified document listeners */ | |
241 private ListenerList fPrenotifiedDocumentListeners; | |
242 /** The registered document partitioning listeners */ | |
243 private ListenerList fDocumentPartitioningListeners; | |
244 /** All positions managed by the document ordered by their start positions. */ | |
245 private Map fPositions; | |
246 /** | |
247 * All positions managed by the document ordered by there end positions. | |
248 * @since 3.4 | |
249 */ | |
250 private Map fEndPositions; | |
251 /** All registered document position updaters */ | |
252 private List fPositionUpdaters; | |
253 /** | |
254 * The list of post notification changes | |
255 * @since 2.0 | |
256 */ | |
257 private List fPostNotificationChanges; | |
258 /** | |
259 * The reentrance count for post notification changes. | |
260 * @since 2.0 | |
261 */ | |
262 private int fReentranceCount= 0; | |
263 /** | |
264 * Indicates whether post notification change processing has been stopped. | |
265 * @since 2.0 | |
266 */ | |
267 private int fStoppedCount= 0; | |
268 /** | |
269 * Indicates whether the registration of post notification changes should be ignored. | |
270 * @since 2.1 | |
271 */ | |
272 private bool fAcceptPostNotificationReplaces= true; | |
273 /** | |
274 * Indicates whether the notification of listeners has been stopped. | |
275 * @since 2.1 | |
276 */ | |
277 private int fStoppedListenerNotification= 0; | |
278 /** | |
279 * The document event to be sent after listener notification has been resumed. | |
280 * @since 2.1 | |
281 */ | |
282 private DocumentEvent fDeferredDocumentEvent; | |
283 /** | |
284 * The registered document partitioners. | |
285 * @since 3.0 | |
286 */ | |
287 private Map fDocumentPartitioners; | |
288 /** | |
289 * The partitioning changed event. | |
290 * @since 3.0 | |
291 */ | |
292 private DocumentPartitioningChangedEvent fDocumentPartitioningChangedEvent; | |
293 /** | |
294 * The find/replace document adapter. | |
295 * @since 3.0 | |
296 */ | |
297 private FindReplaceDocumentAdapter fFindReplaceDocumentAdapter; | |
298 /** | |
299 * The active document rewrite session. | |
300 * @since 3.1 | |
301 */ | |
302 private DocumentRewriteSession fDocumentRewriteSession; | |
303 /** | |
304 * The registered document rewrite session listeners. | |
305 * @since 3.1 | |
306 */ | |
307 private List fDocumentRewriteSessionListeners; | |
308 /** | |
309 * The current modification stamp. | |
310 * @since 3.1 | |
311 */ | |
312 private long fModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP; | |
313 /** | |
314 * Keeps track of next modification stamp. | |
315 * @since 3.1.1 | |
316 */ | |
317 private long fNextModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP; | |
318 /** | |
319 * This document's default line delimiter. | |
320 * @since 3.1 | |
321 */ | |
322 private String fInitialLineDelimiter; | |
323 | |
324 | |
325 /** | |
326 * The default constructor does not perform any configuration | |
327 * but leaves it to the clients who must first initialize the | |
328 * implementation plug-ins and then call <code>completeInitialization</code>. | |
329 * Results in the construction of an empty document. | |
330 */ | |
133
7d818bd32d63
Fix ctors to this with gvim regexp
Frank Benoit <benoit@tionex.de>
parents:
131
diff
changeset
|
331 protected this() { |
129 | 332 fModificationStamp= getNextModificationStamp(); |
333 } | |
334 | |
335 | |
336 /** | |
337 * Returns the document's text store. Assumes that the | |
338 * document has been initialized with a text store. | |
339 * | |
340 * @return the document's text store | |
341 */ | |
342 protected ITextStore getStore() { | |
343 Assert.isNotNull(fStore); | |
344 return fStore; | |
345 } | |
346 | |
347 /** | |
348 * Returns the document's line tracker. Assumes that the | |
349 * document has been initialized with a line tracker. | |
350 * | |
351 * @return the document's line tracker | |
352 */ | |
353 protected ILineTracker getTracker() { | |
354 Assert.isNotNull(fTracker); | |
355 return fTracker; | |
356 } | |
357 | |
358 /** | |
359 * Returns the document's document listeners. | |
360 * | |
361 * @return the document's document listeners | |
362 */ | |
363 protected List getDocumentListeners() { | |
364 return Arrays.asList(fDocumentListeners.getListeners()); | |
365 } | |
366 | |
367 /** | |
368 * Returns the document's partitioning listeners. | |
369 * | |
370 * @return the document's partitioning listeners | |
371 */ | |
372 protected List getDocumentPartitioningListeners() { | |
373 return Arrays.asList(fDocumentPartitioningListeners.getListeners()); | |
374 } | |
375 | |
376 /** | |
377 * Returns all positions managed by the document grouped by category. | |
378 * | |
379 * @return the document's positions | |
380 */ | |
381 protected Map getDocumentManagedPositions() { | |
382 return fPositions; | |
383 } | |
384 | |
385 /* | |
386 * @see dwtx.jface.text.IDocument#getDocumentPartitioner() | |
387 */ | |
388 public IDocumentPartitioner getDocumentPartitioner() { | |
389 return getDocumentPartitioner(DEFAULT_PARTITIONING); | |
390 } | |
391 | |
392 | |
393 | |
394 //--- implementation configuration interface ------------ | |
395 | |
396 /** | |
397 * Sets the document's text store. | |
398 * Must be called at the beginning of the constructor. | |
399 * | |
400 * @param store the document's text store | |
401 */ | |
402 protected void setTextStore(ITextStore store) { | |
403 fStore= store; | |
404 } | |
405 | |
406 /** | |
407 * Sets the document's line tracker. | |
408 * Must be called at the beginning of the constructor. | |
409 * | |
410 * @param tracker the document's line tracker | |
411 */ | |
412 protected void setLineTracker(ILineTracker tracker) { | |
413 fTracker= tracker; | |
414 } | |
415 | |
416 /* | |
417 * @see dwtx.jface.text.IDocument#setDocumentPartitioner(dwtx.jface.text.IDocumentPartitioner) | |
418 */ | |
419 public void setDocumentPartitioner(IDocumentPartitioner partitioner) { | |
420 setDocumentPartitioner(DEFAULT_PARTITIONING, partitioner); | |
421 } | |
422 | |
423 /** | |
424 * Initializes document listeners, positions, and position updaters. | |
425 * Must be called inside the constructor after the implementation plug-ins | |
426 * have been set. | |
427 */ | |
428 protected void completeInitialization() { | |
429 | |
430 fPositions= new HashMap(); | |
431 fEndPositions= new HashMap(); | |
432 fPositionUpdaters= new ArrayList(); | |
433 fDocumentListeners= new ListenerList(ListenerList.IDENTITY); | |
434 fPrenotifiedDocumentListeners= new ListenerList(ListenerList.IDENTITY); | |
435 fDocumentPartitioningListeners= new ListenerList(ListenerList.IDENTITY); | |
436 fDocumentRewriteSessionListeners= new ArrayList(); | |
437 | |
438 addPositionCategory(DEFAULT_CATEGORY); | |
439 addPositionUpdater(new DefaultPositionUpdater(DEFAULT_CATEGORY)); | |
440 } | |
441 | |
442 | |
443 //------------------------------------------------------- | |
444 | |
445 /* | |
446 * @see dwtx.jface.text.IDocument#addDocumentListener(dwtx.jface.text.IDocumentListener) | |
447 */ | |
448 public void addDocumentListener(IDocumentListener listener) { | |
449 Assert.isNotNull(listener); | |
450 fDocumentListeners.add(listener); | |
451 } | |
452 | |
453 /* | |
454 * @see dwtx.jface.text.IDocument#removeDocumentListener(dwtx.jface.text.IDocumentListener) | |
455 */ | |
456 public void removeDocumentListener(IDocumentListener listener) { | |
457 Assert.isNotNull(listener); | |
458 fDocumentListeners.remove(listener); | |
459 } | |
460 | |
461 /* | |
462 * @see dwtx.jface.text.IDocument#addPrenotifiedDocumentListener(dwtx.jface.text.IDocumentListener) | |
463 */ | |
464 public void addPrenotifiedDocumentListener(IDocumentListener listener) { | |
465 Assert.isNotNull(listener); | |
466 fPrenotifiedDocumentListeners.add(listener); | |
467 } | |
468 | |
469 /* | |
470 * @see dwtx.jface.text.IDocument#removePrenotifiedDocumentListener(dwtx.jface.text.IDocumentListener) | |
471 */ | |
472 public void removePrenotifiedDocumentListener(IDocumentListener listener) { | |
473 Assert.isNotNull(listener); | |
474 fPrenotifiedDocumentListeners.remove(listener); | |
475 } | |
476 | |
477 /* | |
478 * @see dwtx.jface.text.IDocument#addDocumentPartitioningListener(dwtx.jface.text.IDocumentPartitioningListener) | |
479 */ | |
480 public void addDocumentPartitioningListener(IDocumentPartitioningListener listener) { | |
481 Assert.isNotNull(listener); | |
482 fDocumentPartitioningListeners.add(listener); | |
483 } | |
484 | |
485 /* | |
486 * @see dwtx.jface.text.IDocument#removeDocumentPartitioningListener(dwtx.jface.text.IDocumentPartitioningListener) | |
487 */ | |
488 public void removeDocumentPartitioningListener(IDocumentPartitioningListener listener) { | |
489 Assert.isNotNull(listener); | |
490 fDocumentPartitioningListeners.remove(listener); | |
491 } | |
492 | |
493 /* | |
494 * @see dwtx.jface.text.IDocument#addPosition(java.lang.String, dwtx.jface.text.Position) | |
495 */ | |
496 public void addPosition(String category, Position position) throws BadLocationException, BadPositionCategoryException { | |
497 | |
498 if ((0 > position.offset) || (0 > position.length) || (position.offset + position.length > getLength())) | |
499 throw new BadLocationException(); | |
500 | |
501 if (category is null) | |
502 throw new BadPositionCategoryException(); | |
503 | |
134 | 504 List list= cast(List) fPositions.get(category); |
129 | 505 if (list is null) |
506 throw new BadPositionCategoryException(); | |
507 list.add(computeIndexInPositionList(list, position.offset), position); | |
508 | |
134 | 509 List endPositions= cast(List) fEndPositions.get(category); |
129 | 510 if (endPositions is null) |
511 throw new BadPositionCategoryException(); | |
512 endPositions.add(computeIndexInPositionList(endPositions, position.offset + position.length - 1, false), position); | |
513 } | |
514 | |
515 /* | |
516 * @see dwtx.jface.text.IDocument#addPosition(dwtx.jface.text.Position) | |
517 */ | |
518 public void addPosition(Position position) throws BadLocationException { | |
519 try { | |
520 addPosition(DEFAULT_CATEGORY, position); | |
521 } catch (BadPositionCategoryException e) { | |
522 } | |
523 } | |
524 | |
525 /* | |
526 * @see dwtx.jface.text.IDocument#addPositionCategory(java.lang.String) | |
527 */ | |
528 public void addPositionCategory(String category) { | |
529 | |
530 if (category is null) | |
531 return; | |
532 | |
533 if (!containsPositionCategory(category)) { | |
534 fPositions.put(category, new ArrayList()); | |
535 fEndPositions.put(category, new ArrayList()); | |
536 } | |
537 } | |
538 | |
539 /* | |
540 * @see dwtx.jface.text.IDocument#addPositionUpdater(dwtx.jface.text.IPositionUpdater) | |
541 */ | |
542 public void addPositionUpdater(IPositionUpdater updater) { | |
543 insertPositionUpdater(updater, fPositionUpdaters.size()); | |
544 } | |
545 | |
546 /* | |
547 * @see dwtx.jface.text.IDocument#containsPosition(java.lang.String, int, int) | |
548 */ | |
549 public bool containsPosition(String category, int offset, int length) { | |
550 | |
551 if (category is null) | |
552 return false; | |
553 | |
134 | 554 List list= cast(List) fPositions.get(category); |
129 | 555 if (list is null) |
556 return false; | |
557 | |
558 int size= list.size(); | |
559 if (size is 0) | |
560 return false; | |
561 | |
562 int index= computeIndexInPositionList(list, offset); | |
563 if (index < size) { | |
134 | 564 Position p= cast(Position) list.get(index); |
129 | 565 while (p !is null && p.offset is offset) { |
566 if (p.length is length) | |
567 return true; | |
568 ++ index; | |
134 | 569 p= (index < size) ? cast(Position) list.get(index) : null; |
129 | 570 } |
571 } | |
572 | |
573 return false; | |
574 } | |
575 | |
576 /* | |
577 * @see dwtx.jface.text.IDocument#containsPositionCategory(java.lang.String) | |
578 */ | |
579 public bool containsPositionCategory(String category) { | |
580 if (category !is null) | |
581 return fPositions.containsKey(category); | |
582 return false; | |
583 } | |
584 | |
585 | |
586 /** | |
587 * Computes the index in the list of positions at which a position with the given | |
588 * offset would be inserted. The position is supposed to become the first in this list | |
589 * of all positions with the same offset. | |
590 * | |
591 * @param positions the list in which the index is computed | |
592 * @param offset the offset for which the index is computed | |
593 * @return the computed index | |
594 * | |
595 * @see IDocument#computeIndexInCategory(String, int) | |
596 * @deprecated As of 3.4, replaced by {@link #computeIndexInPositionList(List, int, bool)} | |
597 */ | |
598 protected int computeIndexInPositionList(List positions, int offset) { | |
599 return computeIndexInPositionList(positions, offset, true); | |
600 } | |
601 | |
602 /** | |
603 * Computes the index in the list of positions at which a position with the given | |
604 * position would be inserted. The position to insert is supposed to become the first | |
605 * in this list of all positions with the same position. | |
606 * | |
607 * @param positions the list in which the index is computed | |
608 * @param offset the offset for which the index is computed | |
609 * @param orderedByOffset <code>true</code> if ordered by offset, false if ordered by end position | |
610 * @return the computed index | |
611 * @since 3.4 | |
612 */ | |
613 protected int computeIndexInPositionList(List positions, int offset, bool orderedByOffset) { | |
614 if (positions.size() is 0) | |
615 return 0; | |
616 | |
617 int left= 0; | |
618 int right= positions.size() -1; | |
619 int mid= 0; | |
620 Position p= null; | |
621 | |
622 while (left < right) { | |
623 | |
624 mid= (left + right) / 2; | |
625 | |
134 | 626 p= cast(Position) positions.get(mid); |
129 | 627 int pOffset= getOffset(orderedByOffset, p); |
628 if (offset < pOffset) { | |
629 if (left is mid) | |
630 right= left; | |
631 else | |
632 right= mid -1; | |
633 } else if (offset > pOffset) { | |
634 if (right is mid) | |
635 left= right; | |
636 else | |
637 left= mid +1; | |
638 } else if (offset is pOffset) { | |
639 left= right= mid; | |
640 } | |
641 | |
642 } | |
643 | |
644 int pos= left; | |
134 | 645 p= cast(Position) positions.get(pos); |
129 | 646 int pPosition= getOffset(orderedByOffset, p); |
647 if (offset > pPosition) { | |
648 // append to the end | |
649 pos++; | |
650 } else { | |
651 // entry will become the first of all entries with the same offset | |
652 do { | |
653 --pos; | |
654 if (pos < 0) | |
655 break; | |
134 | 656 p= cast(Position) positions.get(pos); |
129 | 657 pPosition= getOffset(orderedByOffset, p); |
658 } while (offset is pPosition); | |
659 ++pos; | |
660 } | |
661 | |
662 Assert.isTrue(0 <= pos && pos <= positions.size()); | |
663 | |
664 return pos; | |
665 } | |
666 | |
667 /* | |
668 * @since 3.4 | |
669 */ | |
670 private int getOffset(bool orderedByOffset, Position position) { | |
671 if (orderedByOffset || position.getLength() is 0) | |
672 return position.getOffset(); | |
673 return position.getOffset() + position.getLength() - 1; | |
674 } | |
675 | |
676 /* | |
677 * @see dwtx.jface.text.IDocument#computeIndexInCategory(java.lang.String, int) | |
678 */ | |
679 public int computeIndexInCategory(String category, int offset) throws BadLocationException, BadPositionCategoryException { | |
680 | |
681 if (0 > offset || offset > getLength()) | |
682 throw new BadLocationException(); | |
683 | |
134 | 684 List c= cast(List) fPositions.get(category); |
129 | 685 if (c is null) |
686 throw new BadPositionCategoryException(); | |
687 | |
688 return computeIndexInPositionList(c, offset); | |
689 } | |
690 | |
691 /** | |
692 * Fires the document partitioning changed notification to all registered | |
693 * document partitioning listeners. Uses a robust iterator. | |
694 * | |
695 * @deprecated as of 2.0. Use <code>fireDocumentPartitioningChanged(IRegion)</code> instead. | |
696 */ | |
697 protected void fireDocumentPartitioningChanged() { | |
698 if (fDocumentPartitioningListeners is null) | |
699 return; | |
700 | |
701 Object[] listeners= fDocumentPartitioningListeners.getListeners(); | |
702 for (int i= 0; i < listeners.length; i++) | |
134 | 703 (cast(IDocumentPartitioningListener)listeners[i]).documentPartitioningChanged(this); |
129 | 704 } |
705 | |
706 /** | |
707 * Fires the document partitioning changed notification to all registered | |
708 * document partitioning listeners. Uses a robust iterator. | |
709 * | |
710 * @param region the region in which partitioning has changed | |
711 * | |
712 * @see IDocumentPartitioningListenerExtension | |
713 * @since 2.0 | |
714 * @deprecated as of 3.0. Use | |
715 * <code>fireDocumentPartitioningChanged(DocumentPartitioningChangedEvent)</code> | |
716 * instead. | |
717 */ | |
718 protected void fireDocumentPartitioningChanged(IRegion region) { | |
719 if (fDocumentPartitioningListeners is null) | |
720 return; | |
721 | |
722 Object[] listeners= fDocumentPartitioningListeners.getListeners(); | |
723 for (int i= 0; i < listeners.length; i++) { | |
134 | 724 IDocumentPartitioningListener l= cast(IDocumentPartitioningListener)listeners[i]; |
129 | 725 if (l instanceof IDocumentPartitioningListenerExtension) |
134 | 726 (cast(IDocumentPartitioningListenerExtension) l).documentPartitioningChanged(this, region); |
129 | 727 else |
728 l.documentPartitioningChanged(this); | |
729 } | |
730 } | |
731 | |
732 /** | |
733 * Fires the document partitioning changed notification to all registered | |
734 * document partitioning listeners. Uses a robust iterator. | |
735 * | |
736 * @param event the document partitioning changed event | |
737 * | |
738 * @see IDocumentPartitioningListenerExtension2 | |
739 * @since 3.0 | |
740 */ | |
741 protected void fireDocumentPartitioningChanged(DocumentPartitioningChangedEvent event) { | |
742 if (fDocumentPartitioningListeners is null) | |
743 return; | |
744 | |
745 Object[] listeners= fDocumentPartitioningListeners.getListeners(); | |
746 for (int i= 0; i < listeners.length; i++) { | |
134 | 747 IDocumentPartitioningListener l= cast(IDocumentPartitioningListener)listeners[i]; |
129 | 748 if (l instanceof IDocumentPartitioningListenerExtension2) { |
134 | 749 IDocumentPartitioningListenerExtension2 extension2= cast(IDocumentPartitioningListenerExtension2) l; |
129 | 750 extension2.documentPartitioningChanged(event); |
751 } else if (l instanceof IDocumentPartitioningListenerExtension) { | |
134 | 752 IDocumentPartitioningListenerExtension extension= cast(IDocumentPartitioningListenerExtension) l; |
129 | 753 extension.documentPartitioningChanged(this, event.getCoverage()); |
754 } else { | |
755 l.documentPartitioningChanged(this); | |
756 } | |
757 } | |
758 } | |
759 | |
760 /** | |
761 * Fires the given document event to all registers document listeners informing them | |
762 * about the forthcoming document manipulation. Uses a robust iterator. | |
763 * | |
764 * @param event the event to be sent out | |
765 */ | |
766 protected void fireDocumentAboutToBeChanged(DocumentEvent event) { | |
767 | |
768 // IDocumentExtension | |
769 if (fReentranceCount is 0) | |
770 flushPostNotificationChanges(); | |
771 | |
772 if (fDocumentPartitioners !is null) { | |
773 Iterator e= fDocumentPartitioners.values().iterator(); | |
774 while (e.hasNext()) { | |
134 | 775 IDocumentPartitioner p= cast(IDocumentPartitioner) e.next(); |
129 | 776 if (p instanceof IDocumentPartitionerExtension3) { |
134 | 777 IDocumentPartitionerExtension3 extension= cast(IDocumentPartitionerExtension3) p; |
129 | 778 if (extension.getActiveRewriteSession() !is null) |
779 continue; | |
780 } | |
781 p.documentAboutToBeChanged(event); | |
782 } | |
783 } | |
784 | |
785 Object[] listeners= fPrenotifiedDocumentListeners.getListeners(); | |
786 for (int i= 0; i < listeners.length; i++) | |
134 | 787 (cast(IDocumentListener)listeners[i]).documentAboutToBeChanged(event); |
129 | 788 |
789 listeners= fDocumentListeners.getListeners(); | |
790 for (int i= 0; i < listeners.length; i++) | |
134 | 791 (cast(IDocumentListener)listeners[i]).documentAboutToBeChanged(event); |
129 | 792 } |
793 | |
794 | |
795 /** | |
796 * Updates document partitioning and document positions according to the | |
797 * specification given by the document event. | |
798 * | |
799 * @param event the document event describing the change to which structures must be adapted | |
800 */ | |
801 protected void updateDocumentStructures(DocumentEvent event) { | |
802 | |
803 if (fDocumentPartitioners !is null) { | |
804 fDocumentPartitioningChangedEvent= new DocumentPartitioningChangedEvent(this); | |
805 Iterator e= fDocumentPartitioners.keySet().iterator(); | |
806 while (e.hasNext()) { | |
134 | 807 String partitioning= cast(String) e.next(); |
808 IDocumentPartitioner partitioner= cast(IDocumentPartitioner) fDocumentPartitioners.get(partitioning); | |
129 | 809 |
810 if (partitioner instanceof IDocumentPartitionerExtension3) { | |
134 | 811 IDocumentPartitionerExtension3 extension= cast(IDocumentPartitionerExtension3) partitioner; |
129 | 812 if (extension.getActiveRewriteSession() !is null) |
813 continue; | |
814 } | |
815 | |
816 if (partitioner instanceof IDocumentPartitionerExtension) { | |
134 | 817 IDocumentPartitionerExtension extension= cast(IDocumentPartitionerExtension) partitioner; |
129 | 818 IRegion r= extension.documentChanged2(event); |
819 if (r !is null) | |
820 fDocumentPartitioningChangedEvent.setPartitionChange(partitioning, r.getOffset(), r.getLength()); | |
821 } else { | |
822 if (partitioner.documentChanged(event)) | |
823 fDocumentPartitioningChangedEvent.setPartitionChange(partitioning, 0, event.getDocument().getLength()); | |
824 } | |
825 } | |
826 } | |
827 | |
828 if (fPositions.size() > 0) | |
829 updatePositions(event); | |
830 } | |
831 | |
832 /** | |
833 * Notifies all listeners about the given document change. Uses a robust | |
834 * iterator. | |
835 * <p> | |
836 * Executes all registered post notification replace operation. | |
837 * | |
838 * @param event the event to be sent out. | |
839 */ | |
840 protected void doFireDocumentChanged(DocumentEvent event) { | |
841 bool changed= fDocumentPartitioningChangedEvent !is null && !fDocumentPartitioningChangedEvent.isEmpty(); | |
842 IRegion change= changed ? fDocumentPartitioningChangedEvent.getCoverage() : null; | |
843 doFireDocumentChanged(event, changed, change); | |
844 } | |
845 | |
846 /** | |
847 * Notifies all listeners about the given document change. | |
848 * Uses a robust iterator. <p> | |
849 * Executes all registered post notification replace operation. | |
850 * | |
851 * @param event the event to be sent out | |
852 * @param firePartitionChange <code>true</code> if a partition change notification should be sent | |
853 * @param partitionChange the region whose partitioning changed | |
854 * @since 2.0 | |
855 * @deprecated as of 3.0. Use <code>doFireDocumentChanged2(DocumentEvent)</code> instead; this method will be removed. | |
856 */ | |
857 protected void doFireDocumentChanged(DocumentEvent event, bool firePartitionChange, IRegion partitionChange) { | |
858 doFireDocumentChanged2(event); | |
859 } | |
860 | |
861 /** | |
862 * Notifies all listeners about the given document change. Uses a robust | |
863 * iterator. | |
864 * <p> | |
865 * Executes all registered post notification replace operation. | |
866 * <p> | |
867 * This method will be renamed to <code>doFireDocumentChanged</code>. | |
868 * | |
869 * @param event the event to be sent out | |
870 * @since 3.0 | |
871 */ | |
872 protected void doFireDocumentChanged2(DocumentEvent event) { | |
873 | |
874 DocumentPartitioningChangedEvent p= fDocumentPartitioningChangedEvent; | |
875 fDocumentPartitioningChangedEvent= null; | |
876 if (p !is null && !p.isEmpty()) | |
877 fireDocumentPartitioningChanged(p); | |
878 | |
879 Object[] listeners= fPrenotifiedDocumentListeners.getListeners(); | |
880 for (int i= 0; i < listeners.length; i++) | |
134 | 881 (cast(IDocumentListener)listeners[i]).documentChanged(event); |
129 | 882 |
883 listeners= fDocumentListeners.getListeners(); | |
884 for (int i= 0; i < listeners.length; i++) | |
134 | 885 (cast(IDocumentListener)listeners[i]).documentChanged(event); |
129 | 886 |
887 // IDocumentExtension | |
888 ++ fReentranceCount; | |
889 try { | |
890 if (fReentranceCount is 1) | |
891 executePostNotificationChanges(); | |
892 } finally { | |
893 -- fReentranceCount; | |
894 } | |
895 } | |
896 | |
897 /** | |
898 * Updates the internal document structures and informs all document listeners | |
899 * if listener notification has been enabled. Otherwise it remembers the event | |
900 * to be sent to the listeners on resume. | |
901 * | |
902 * @param event the document event to be sent out | |
903 */ | |
904 protected void fireDocumentChanged(DocumentEvent event) { | |
905 updateDocumentStructures(event); | |
906 | |
907 if (fStoppedListenerNotification is 0) | |
908 doFireDocumentChanged(event); | |
909 else | |
910 fDeferredDocumentEvent= event; | |
911 } | |
912 | |
913 /* | |
914 * @see dwtx.jface.text.IDocument#getChar(int) | |
915 */ | |
916 public char getChar(int pos) throws BadLocationException { | |
917 if ((0 > pos) || (pos >= getLength())) | |
918 throw new BadLocationException(); | |
919 return getStore().get(pos); | |
920 } | |
921 | |
922 /* | |
923 * @see dwtx.jface.text.IDocument#getContentType(int) | |
924 */ | |
925 public String getContentType(int offset) throws BadLocationException { | |
926 String contentType= null; | |
927 try { | |
928 contentType= getContentType(DEFAULT_PARTITIONING, offset, false); | |
929 Assert.isNotNull(contentType); | |
930 } catch (BadPartitioningException e) { | |
931 Assert.isTrue(false); | |
932 } | |
933 return contentType; | |
934 } | |
935 | |
936 /* | |
937 * @see dwtx.jface.text.IDocument#getLegalContentTypes() | |
938 */ | |
939 public String[] getLegalContentTypes() { | |
940 String[] contentTypes= null; | |
941 try { | |
942 contentTypes= getLegalContentTypes(DEFAULT_PARTITIONING); | |
943 Assert.isNotNull(contentTypes); | |
944 } catch (BadPartitioningException e) { | |
945 Assert.isTrue(false); | |
946 } | |
947 return contentTypes; | |
948 } | |
949 | |
950 /* | |
951 * @see dwtx.jface.text.IDocument#getLength() | |
952 */ | |
953 public int getLength() { | |
954 return getStore().getLength(); | |
955 } | |
956 | |
957 /* | |
958 * @see dwtx.jface.text.IDocument#getLineDelimiter(int) | |
959 */ | |
960 public String getLineDelimiter(int line) throws BadLocationException { | |
961 return getTracker().getLineDelimiter(line); | |
962 } | |
963 | |
964 /* | |
965 * @see dwtx.jface.text.IDocument#getLegalLineDelimiters() | |
966 */ | |
967 public String[] getLegalLineDelimiters() { | |
968 return getTracker().getLegalLineDelimiters(); | |
969 } | |
970 | |
971 /* | |
972 * @see dwtx.jface.text.IDocumentExtension4#getDefaultLineDelimiter() | |
973 * @since 3.1 | |
974 */ | |
975 public String getDefaultLineDelimiter() { | |
976 | |
977 String lineDelimiter= null; | |
978 | |
979 try { | |
980 lineDelimiter= getLineDelimiter(0); | |
981 } catch (BadLocationException x) { | |
982 } | |
983 | |
984 if (lineDelimiter !is null) | |
985 return lineDelimiter; | |
986 | |
987 if (fInitialLineDelimiter !is null) | |
988 return fInitialLineDelimiter; | |
989 | |
990 String sysLineDelimiter= System.getProperty("line.separator"); //$NON-NLS-1$ | |
991 String[] delimiters= getLegalLineDelimiters(); | |
992 Assert.isTrue(delimiters.length > 0); | |
993 for (int i= 0; i < delimiters.length; i++) { | |
994 if (delimiters[i].equals(sysLineDelimiter)) { | |
995 lineDelimiter= sysLineDelimiter; | |
996 break; | |
997 } | |
998 } | |
999 | |
1000 if (lineDelimiter is null) | |
1001 lineDelimiter= delimiters[0]; | |
1002 | |
1003 return lineDelimiter; | |
1004 | |
1005 } | |
1006 | |
1007 /* | |
1008 * @see dwtx.jface.text.IDocumentExtension4#setInitialLineDelimiter(java.lang.String) | |
1009 * @since 3.1 | |
1010 */ | |
1011 public void setInitialLineDelimiter(String lineDelimiter) { | |
1012 Assert.isNotNull(lineDelimiter); | |
1013 fInitialLineDelimiter= lineDelimiter; | |
1014 } | |
1015 | |
1016 /* | |
1017 * @see dwtx.jface.text.IDocument#getLineLength(int) | |
1018 */ | |
1019 public int getLineLength(int line) throws BadLocationException { | |
1020 return getTracker().getLineLength(line); | |
1021 } | |
1022 | |
1023 /* | |
1024 * @see dwtx.jface.text.IDocument#getLineOfOffset(int) | |
1025 */ | |
1026 public int getLineOfOffset(int pos) throws BadLocationException { | |
1027 return getTracker().getLineNumberOfOffset(pos); | |
1028 } | |
1029 | |
1030 /* | |
1031 * @see dwtx.jface.text.IDocument#getLineOffset(int) | |
1032 */ | |
1033 public int getLineOffset(int line) throws BadLocationException { | |
1034 return getTracker().getLineOffset(line); | |
1035 } | |
1036 | |
1037 /* | |
1038 * @see dwtx.jface.text.IDocument#getLineInformation(int) | |
1039 */ | |
1040 public IRegion getLineInformation(int line) throws BadLocationException { | |
1041 return getTracker().getLineInformation(line); | |
1042 } | |
1043 | |
1044 /* | |
1045 * @see dwtx.jface.text.IDocument#getLineInformationOfOffset(int) | |
1046 */ | |
1047 public IRegion getLineInformationOfOffset(int offset) throws BadLocationException { | |
1048 return getTracker().getLineInformationOfOffset(offset); | |
1049 } | |
1050 | |
1051 /* | |
1052 * @see dwtx.jface.text.IDocument#getNumberOfLines() | |
1053 */ | |
1054 public int getNumberOfLines() { | |
1055 return getTracker().getNumberOfLines(); | |
1056 } | |
1057 | |
1058 /* | |
1059 * @see dwtx.jface.text.IDocument#getNumberOfLines(int, int) | |
1060 */ | |
1061 public int getNumberOfLines(int offset, int length) throws BadLocationException { | |
1062 return getTracker().getNumberOfLines(offset, length); | |
1063 } | |
1064 | |
1065 /* | |
1066 * @see dwtx.jface.text.IDocument#computeNumberOfLines(java.lang.String) | |
1067 */ | |
1068 public int computeNumberOfLines(String text) { | |
1069 return getTracker().computeNumberOfLines(text); | |
1070 } | |
1071 | |
1072 /* | |
1073 * @see dwtx.jface.text.IDocument#getPartition(int) | |
1074 */ | |
1075 public ITypedRegion getPartition(int offset) throws BadLocationException { | |
1076 ITypedRegion partition= null; | |
1077 try { | |
1078 partition= getPartition(DEFAULT_PARTITIONING, offset, false); | |
1079 Assert.isNotNull(partition); | |
1080 } catch (BadPartitioningException e) { | |
1081 Assert.isTrue(false); | |
1082 } | |
1083 return partition; | |
1084 } | |
1085 | |
1086 /* | |
1087 * @see dwtx.jface.text.IDocument#computePartitioning(int, int) | |
1088 */ | |
1089 public ITypedRegion[] computePartitioning(int offset, int length) throws BadLocationException { | |
1090 ITypedRegion[] partitioning= null; | |
1091 try { | |
1092 partitioning= computePartitioning(DEFAULT_PARTITIONING, offset, length, false); | |
1093 Assert.isNotNull(partitioning); | |
1094 } catch (BadPartitioningException e) { | |
1095 Assert.isTrue(false); | |
1096 } | |
1097 return partitioning; | |
1098 } | |
1099 | |
1100 /* | |
1101 * @see dwtx.jface.text.IDocument#getPositions(java.lang.String) | |
1102 */ | |
1103 public Position[] getPositions(String category) throws BadPositionCategoryException { | |
1104 | |
1105 if (category is null) | |
1106 throw new BadPositionCategoryException(); | |
1107 | |
134 | 1108 List c= cast(List) fPositions.get(category); |
129 | 1109 if (c is null) |
1110 throw new BadPositionCategoryException(); | |
1111 | |
1112 Position[] positions= new Position[c.size()]; | |
1113 c.toArray(positions); | |
1114 return positions; | |
1115 } | |
1116 | |
1117 /* | |
1118 * @see dwtx.jface.text.IDocument#getPositionCategories() | |
1119 */ | |
1120 public String[] getPositionCategories() { | |
1121 String[] categories= new String[fPositions.size()]; | |
1122 Iterator keys= fPositions.keySet().iterator(); | |
1123 for (int i= 0; i < categories.length; i++) | |
134 | 1124 categories[i]= cast(String) keys.next(); |
129 | 1125 return categories; |
1126 } | |
1127 | |
1128 /* | |
1129 * @see dwtx.jface.text.IDocument#getPositionUpdaters() | |
1130 */ | |
1131 public IPositionUpdater[] getPositionUpdaters() { | |
1132 IPositionUpdater[] updaters= new IPositionUpdater[fPositionUpdaters.size()]; | |
1133 fPositionUpdaters.toArray(updaters); | |
1134 return updaters; | |
1135 } | |
1136 | |
1137 /* | |
1138 * @see dwtx.jface.text.IDocument#get() | |
1139 */ | |
1140 public String get() { | |
1141 return getStore().get(0, getLength()); | |
1142 } | |
1143 | |
1144 /* | |
1145 * @see dwtx.jface.text.IDocument#get(int, int) | |
1146 */ | |
1147 public String get(int pos, int length) throws BadLocationException { | |
1148 int myLength= getLength(); | |
1149 if ((0 > pos) || (0 > length) || (pos + length > myLength)) | |
1150 throw new BadLocationException(); | |
1151 return getStore().get(pos, length); | |
1152 } | |
1153 | |
1154 /* | |
1155 * @see dwtx.jface.text.IDocument#insertPositionUpdater(dwtx.jface.text.IPositionUpdater, int) | |
1156 */ | |
1157 public void insertPositionUpdater(IPositionUpdater updater, int index) { | |
1158 | |
1159 for (int i= fPositionUpdaters.size() - 1; i >= 0; i--) { | |
1160 if (fPositionUpdaters.get(i) is updater) | |
1161 return; | |
1162 } | |
1163 | |
1164 if (index is fPositionUpdaters.size()) | |
1165 fPositionUpdaters.add(updater); | |
1166 else | |
1167 fPositionUpdaters.add(index, updater); | |
1168 } | |
1169 | |
1170 /* | |
1171 * @see dwtx.jface.text.IDocument#removePosition(java.lang.String, dwtx.jface.text.Position) | |
1172 */ | |
1173 public void removePosition(String category, Position position) throws BadPositionCategoryException { | |
1174 | |
1175 if (position is null) | |
1176 return; | |
1177 | |
1178 if (category is null) | |
1179 throw new BadPositionCategoryException(); | |
1180 | |
134 | 1181 List c= cast(List) fPositions.get(category); |
129 | 1182 if (c is null) |
1183 throw new BadPositionCategoryException(); | |
1184 removeFromPositionsList(c, position, true); | |
1185 | |
134 | 1186 List endPositions= cast(List) fEndPositions.get(category); |
129 | 1187 if (endPositions is null) |
1188 throw new BadPositionCategoryException(); | |
1189 removeFromPositionsList(endPositions, position, false); | |
1190 } | |
1191 | |
1192 /** | |
1193 * Remove the given position form the given list of positions based on identity not equality. | |
1194 * | |
1195 * @param positions a list of positions | |
1196 * @param position the position to remove | |
1197 * @param orderedByOffset true if <code>positions</code> is ordered by offset, false if ordered by end position | |
1198 * @since 3.4 | |
1199 */ | |
1200 private void removeFromPositionsList(List positions, Position position, bool orderedByOffset) { | |
1201 int size= positions.size(); | |
1202 | |
1203 //Assume position is somewhere near it was before | |
1204 int index= computeIndexInPositionList(positions, orderedByOffset ? position.offset : position.offset + position.length - 1, orderedByOffset); | |
1205 if (index < size && positions.get(index) is position) { | |
1206 positions.remove(index); | |
1207 return; | |
1208 } | |
1209 | |
1210 int back= index - 1; | |
1211 int forth= index + 1; | |
1212 while (back >= 0 || forth < size) { | |
1213 if (back >= 0) { | |
1214 if (position is positions.get(back)) { | |
1215 positions.remove(back); | |
1216 return; | |
1217 } | |
1218 back--; | |
1219 } | |
1220 | |
1221 if (forth < size) { | |
1222 if (position is positions.get(forth)) { | |
1223 positions.remove(forth); | |
1224 return; | |
1225 } | |
1226 forth++; | |
1227 } | |
1228 } | |
1229 } | |
1230 | |
1231 /* | |
1232 * @see dwtx.jface.text.IDocument#removePosition(dwtx.jface.text.Position) | |
1233 */ | |
1234 public void removePosition(Position position) { | |
1235 try { | |
1236 removePosition(DEFAULT_CATEGORY, position); | |
1237 } catch (BadPositionCategoryException e) { | |
1238 } | |
1239 } | |
1240 | |
1241 /* | |
1242 * @see dwtx.jface.text.IDocument#removePositionCategory(java.lang.String) | |
1243 */ | |
1244 public void removePositionCategory(String category) throws BadPositionCategoryException { | |
1245 | |
1246 if (category is null) | |
1247 return; | |
1248 | |
1249 if ( !containsPositionCategory(category)) | |
1250 throw new BadPositionCategoryException(); | |
1251 | |
1252 fPositions.remove(category); | |
1253 fEndPositions.remove(category); | |
1254 } | |
1255 | |
1256 /* | |
1257 * @see dwtx.jface.text.IDocument#removePositionUpdater(dwtx.jface.text.IPositionUpdater) | |
1258 */ | |
1259 public void removePositionUpdater(IPositionUpdater updater) { | |
1260 for (int i= fPositionUpdaters.size() - 1; i >= 0; i--) { | |
1261 if (fPositionUpdaters.get(i) is updater) { | |
1262 fPositionUpdaters.remove(i); | |
1263 return; | |
1264 } | |
1265 } | |
1266 } | |
1267 | |
1268 private long getNextModificationStamp() { | |
1269 if (fNextModificationStamp is Long.MAX_VALUE || fNextModificationStamp is IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP) | |
1270 fNextModificationStamp= 0; | |
1271 else | |
1272 fNextModificationStamp= fNextModificationStamp + 1; | |
1273 | |
1274 return fNextModificationStamp; | |
1275 } | |
1276 | |
1277 /* | |
1278 * @see dwtx.jface.text.IDocumentExtension4#getModificationStamp() | |
1279 * @since 3.1 | |
1280 */ | |
1281 public long getModificationStamp() { | |
1282 return fModificationStamp; | |
1283 } | |
1284 | |
1285 /* | |
1286 * @see dwtx.jface.text.IDocument#replace(int, int, java.lang.String) | |
1287 * @since 3.1 | |
1288 */ | |
1289 public void replace(int pos, int length, String text, long modificationStamp) throws BadLocationException { | |
1290 if ((0 > pos) || (0 > length) || (pos + length > getLength())) | |
1291 throw new BadLocationException(); | |
1292 | |
1293 DocumentEvent e= new DocumentEvent(this, pos, length, text); | |
1294 fireDocumentAboutToBeChanged(e); | |
1295 | |
1296 getStore().replace(pos, length, text); | |
1297 getTracker().replace(pos, length, text); | |
1298 | |
1299 fModificationStamp= modificationStamp; | |
1300 fNextModificationStamp= Math.max(fModificationStamp, fNextModificationStamp); | |
1301 e.fModificationStamp= fModificationStamp; | |
1302 | |
1303 fireDocumentChanged(e); | |
1304 } | |
1305 | |
1306 /** | |
1307 * {@inheritDoc} | |
1308 * | |
1309 * @since 3.4 | |
1310 */ | |
1311 public bool isLineInformationRepairNeeded(int offset, int length, String text) throws BadLocationException { | |
1312 return false; | |
1313 } | |
1314 | |
1315 /* | |
1316 * @see dwtx.jface.text.IDocument#replace(int, int, java.lang.String) | |
1317 */ | |
1318 public void replace(int pos, int length, String text) throws BadLocationException { | |
1319 if (length is 0 && (text is null || text.length() is 0)) | |
1320 replace(pos, length, text, getModificationStamp()); | |
1321 else | |
1322 replace(pos, length, text, getNextModificationStamp()); | |
1323 } | |
1324 | |
1325 /* | |
1326 * @see dwtx.jface.text.IDocument#set(java.lang.String) | |
1327 */ | |
1328 public void set(String text) { | |
1329 set(text, getNextModificationStamp()); | |
1330 } | |
1331 | |
1332 /* | |
1333 * @see dwtx.jface.text.IDocumentExtension4#set(java.lang.String, long) | |
1334 * @since 3.1 | |
1335 */ | |
1336 public void set(String text, long modificationStamp) { | |
1337 int length= getStore().getLength(); | |
1338 | |
1339 DocumentEvent e= new DocumentEvent(this, 0, length, text); | |
1340 fireDocumentAboutToBeChanged(e); | |
1341 | |
1342 getStore().set(text); | |
1343 getTracker().set(text); | |
1344 | |
1345 fModificationStamp= modificationStamp; | |
1346 fNextModificationStamp= Math.max(fModificationStamp, fNextModificationStamp); | |
1347 e.fModificationStamp= fModificationStamp; | |
1348 | |
1349 fireDocumentChanged(e); | |
1350 } | |
1351 | |
1352 /** | |
1353 * Updates all positions of all categories to the change described by the | |
1354 * document event. All registered document updaters are called in the | |
1355 * sequence they have been arranged. Uses a robust iterator. | |
1356 * | |
1357 * @param event the document event describing the change to which to adapt | |
1358 * the positions | |
1359 */ | |
1360 protected void updatePositions(DocumentEvent event) { | |
1361 List list= new ArrayList(fPositionUpdaters); | |
1362 Iterator e= list.iterator(); | |
1363 while (e.hasNext()) { | |
134 | 1364 IPositionUpdater u= cast(IPositionUpdater) e.next(); |
129 | 1365 u.update(event); |
1366 } | |
1367 } | |
1368 | |
1369 /* | |
1370 * @see dwtx.jface.text.IDocument#search(int, java.lang.String, bool, bool, bool) | |
1371 */ | |
1372 public int search(int startPosition, String findString, bool forwardSearch, bool caseSensitive, bool wholeWord) throws BadLocationException { | |
1373 try { | |
1374 IRegion region= getFindReplaceDocumentAdapter().find(startPosition, findString, forwardSearch, caseSensitive, wholeWord, false); | |
1375 return region is null ? -1 : region.getOffset(); | |
1376 } catch (IllegalStateException ex) { | |
1377 return -1; | |
1378 } catch (PatternSyntaxException ex) { | |
1379 return -1; | |
1380 } | |
1381 } | |
1382 | |
1383 /** | |
1384 * Returns the find/replace adapter for this document. | |
1385 * | |
1386 * @return this document's find/replace document adapter | |
1387 * @since 3.0 | |
1388 */ | |
1389 private FindReplaceDocumentAdapter getFindReplaceDocumentAdapter() { | |
1390 if (fFindReplaceDocumentAdapter is null) | |
1391 fFindReplaceDocumentAdapter= new FindReplaceDocumentAdapter(this); | |
1392 | |
1393 return fFindReplaceDocumentAdapter; | |
1394 } | |
1395 | |
1396 /** | |
1397 * Flushes all registered post notification changes. | |
1398 * | |
1399 * @since 2.0 | |
1400 */ | |
1401 private void flushPostNotificationChanges() { | |
1402 if (fPostNotificationChanges !is null) | |
1403 fPostNotificationChanges.clear(); | |
1404 } | |
1405 | |
1406 /** | |
1407 * Executes all registered post notification changes. The process is | |
1408 * repeated until no new post notification changes are added. | |
1409 * | |
1410 * @since 2.0 | |
1411 */ | |
1412 private void executePostNotificationChanges() { | |
1413 | |
1414 if (fStoppedCount > 0) | |
1415 return; | |
1416 | |
1417 while (fPostNotificationChanges !is null) { | |
1418 List changes= fPostNotificationChanges; | |
1419 fPostNotificationChanges= null; | |
1420 | |
1421 Iterator e= changes.iterator(); | |
1422 while (e.hasNext()) { | |
134 | 1423 RegisteredReplace replace= cast(RegisteredReplace) e.next(); |
129 | 1424 replace.fReplace.perform(this, replace.fOwner); |
1425 } | |
1426 } | |
1427 } | |
1428 | |
1429 /* | |
1430 * @see dwtx.jface.text.IDocumentExtension2#acceptPostNotificationReplaces() | |
1431 * @since 2.1 | |
1432 */ | |
1433 public void acceptPostNotificationReplaces() { | |
1434 fAcceptPostNotificationReplaces= true; | |
1435 } | |
1436 | |
1437 /* | |
1438 * @see dwtx.jface.text.IDocumentExtension2#ignorePostNotificationReplaces() | |
1439 * @since 2.1 | |
1440 */ | |
1441 public void ignorePostNotificationReplaces() { | |
1442 fAcceptPostNotificationReplaces= false; | |
1443 } | |
1444 | |
1445 /* | |
1446 * @see dwtx.jface.text.IDocumentExtension#registerPostNotificationReplace(dwtx.jface.text.IDocumentListener, dwtx.jface.text.IDocumentExtension.IReplace) | |
1447 * @since 2.0 | |
1448 */ | |
1449 public void registerPostNotificationReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) { | |
1450 if (fAcceptPostNotificationReplaces) { | |
1451 if (fPostNotificationChanges is null) | |
1452 fPostNotificationChanges= new ArrayList(1); | |
1453 fPostNotificationChanges.add(new RegisteredReplace(owner, replace)); | |
1454 } | |
1455 } | |
1456 | |
1457 /* | |
1458 * @see dwtx.jface.text.IDocumentExtension#stopPostNotificationProcessing() | |
1459 * @since 2.0 | |
1460 */ | |
1461 public void stopPostNotificationProcessing() { | |
1462 ++ fStoppedCount; | |
1463 } | |
1464 | |
1465 /* | |
1466 * @see dwtx.jface.text.IDocumentExtension#resumePostNotificationProcessing() | |
1467 * @since 2.0 | |
1468 */ | |
1469 public void resumePostNotificationProcessing() { | |
1470 -- fStoppedCount; | |
1471 if (fStoppedCount is 0 && fReentranceCount is 0) | |
1472 executePostNotificationChanges(); | |
1473 } | |
1474 | |
1475 /* | |
1476 * @see dwtx.jface.text.IDocumentExtension#startSequentialRewrite(bool) | |
1477 * @since 2.0 | |
1478 */ | |
1479 public void startSequentialRewrite(bool normalized) { | |
1480 } | |
1481 | |
1482 /* | |
1483 * @see dwtx.jface.text.IDocumentExtension#stopSequentialRewrite() | |
1484 * @since 2.0 | |
1485 */ | |
1486 public void stopSequentialRewrite() { | |
1487 } | |
1488 | |
1489 /* | |
1490 * @see dwtx.jface.text.IDocumentExtension2#resumeListenerNotification() | |
1491 * @since 2.1 | |
1492 */ | |
1493 public void resumeListenerNotification() { | |
1494 -- fStoppedListenerNotification; | |
1495 if (fStoppedListenerNotification is 0) { | |
1496 resumeDocumentListenerNotification(); | |
1497 } | |
1498 } | |
1499 | |
1500 /* | |
1501 * @see dwtx.jface.text.IDocumentExtension2#stopListenerNotification() | |
1502 * @since 2.1 | |
1503 */ | |
1504 public void stopListenerNotification() { | |
1505 ++ fStoppedListenerNotification; | |
1506 } | |
1507 | |
1508 /** | |
1509 * Resumes the document listener notification by sending out the remembered | |
1510 * partition changed and document event. | |
1511 * | |
1512 * @since 2.1 | |
1513 */ | |
1514 private void resumeDocumentListenerNotification() { | |
1515 if (fDeferredDocumentEvent !is null) { | |
1516 DocumentEvent event= fDeferredDocumentEvent; | |
1517 fDeferredDocumentEvent= null; | |
1518 doFireDocumentChanged(event); | |
1519 } | |
1520 } | |
1521 | |
1522 /* | |
1523 * @see dwtx.jface.text.IDocumentExtension3#computeZeroLengthPartitioning(java.lang.String, int, int) | |
1524 * @since 3.0 | |
1525 */ | |
1526 public ITypedRegion[] computePartitioning(String partitioning, int offset, int length, bool includeZeroLengthPartitions) throws BadLocationException, BadPartitioningException { | |
1527 if ((0 > offset) || (0 > length) || (offset + length > getLength())) | |
1528 throw new BadLocationException(); | |
1529 | |
1530 IDocumentPartitioner partitioner= getDocumentPartitioner(partitioning); | |
1531 | |
1532 if (partitioner instanceof IDocumentPartitionerExtension2) { | |
1533 checkStateOfPartitioner(partitioner, partitioning); | |
134 | 1534 return (cast(IDocumentPartitionerExtension2) partitioner).computePartitioning(offset, length, includeZeroLengthPartitions); |
129 | 1535 } else if (partitioner !is null) { |
1536 checkStateOfPartitioner(partitioner, partitioning); | |
1537 return partitioner.computePartitioning(offset, length); | |
1538 } else if (DEFAULT_PARTITIONING.equals(partitioning)) | |
1539 return new TypedRegion[] { new TypedRegion(offset, length, DEFAULT_CONTENT_TYPE) }; | |
1540 else | |
1541 throw new BadPartitioningException(); | |
1542 } | |
1543 | |
1544 /* | |
1545 * @see dwtx.jface.text.IDocumentExtension3#getZeroLengthContentType(java.lang.String, int) | |
1546 * @since 3.0 | |
1547 */ | |
1548 public String getContentType(String partitioning, int offset, bool preferOpenPartitions) throws BadLocationException, BadPartitioningException { | |
1549 if ((0 > offset) || (offset > getLength())) | |
1550 throw new BadLocationException(); | |
1551 | |
1552 IDocumentPartitioner partitioner= getDocumentPartitioner(partitioning); | |
1553 | |
1554 if (partitioner instanceof IDocumentPartitionerExtension2) { | |
1555 checkStateOfPartitioner(partitioner, partitioning); | |
134 | 1556 return (cast(IDocumentPartitionerExtension2) partitioner).getContentType(offset, preferOpenPartitions); |
129 | 1557 } else if (partitioner !is null) { |
1558 checkStateOfPartitioner(partitioner, partitioning); | |
1559 return partitioner.getContentType(offset); | |
1560 } else if (DEFAULT_PARTITIONING.equals(partitioning)) | |
1561 return DEFAULT_CONTENT_TYPE; | |
1562 else | |
1563 throw new BadPartitioningException(); | |
1564 } | |
1565 | |
1566 /* | |
1567 * @see dwtx.jface.text.IDocumentExtension3#getDocumentPartitioner(java.lang.String) | |
1568 * @since 3.0 | |
1569 */ | |
1570 public IDocumentPartitioner getDocumentPartitioner(String partitioning) { | |
134 | 1571 return fDocumentPartitioners !is null ? cast(IDocumentPartitioner) fDocumentPartitioners.get(partitioning) : null; |
129 | 1572 } |
1573 | |
1574 /* | |
1575 * @see dwtx.jface.text.IDocumentExtension3#getLegalContentTypes(java.lang.String) | |
1576 * @since 3.0 | |
1577 */ | |
1578 public String[] getLegalContentTypes(String partitioning) throws BadPartitioningException { | |
1579 IDocumentPartitioner partitioner= getDocumentPartitioner(partitioning); | |
1580 if (partitioner !is null) | |
1581 return partitioner.getLegalContentTypes(); | |
1582 if (DEFAULT_PARTITIONING.equals(partitioning)) | |
1583 return new String[] { DEFAULT_CONTENT_TYPE }; | |
1584 throw new BadPartitioningException(); | |
1585 } | |
1586 | |
1587 /* | |
1588 * @see dwtx.jface.text.IDocumentExtension3#getZeroLengthPartition(java.lang.String, int) | |
1589 * @since 3.0 | |
1590 */ | |
1591 public ITypedRegion getPartition(String partitioning, int offset, bool preferOpenPartitions) throws BadLocationException, BadPartitioningException { | |
1592 if ((0 > offset) || (offset > getLength())) | |
1593 throw new BadLocationException(); | |
1594 | |
1595 IDocumentPartitioner partitioner= getDocumentPartitioner(partitioning); | |
1596 | |
1597 if (partitioner instanceof IDocumentPartitionerExtension2) { | |
1598 checkStateOfPartitioner(partitioner, partitioning); | |
134 | 1599 return (cast(IDocumentPartitionerExtension2) partitioner).getPartition(offset, preferOpenPartitions); |
129 | 1600 } else if (partitioner !is null) { |
1601 checkStateOfPartitioner(partitioner, partitioning); | |
1602 return partitioner.getPartition(offset); | |
1603 } else if (DEFAULT_PARTITIONING.equals(partitioning)) | |
1604 return new TypedRegion(0, getLength(), DEFAULT_CONTENT_TYPE); | |
1605 else | |
1606 throw new BadPartitioningException(); | |
1607 } | |
1608 | |
1609 /* | |
1610 * @see dwtx.jface.text.IDocumentExtension3#getPartitionings() | |
1611 * @since 3.0 | |
1612 */ | |
1613 public String[] getPartitionings() { | |
1614 if (fDocumentPartitioners is null) | |
1615 return new String[0]; | |
1616 String[] partitionings= new String[fDocumentPartitioners.size()]; | |
1617 fDocumentPartitioners.keySet().toArray(partitionings); | |
1618 return partitionings; | |
1619 } | |
1620 | |
1621 /* | |
1622 * @see dwtx.jface.text.IDocumentExtension3#setDocumentPartitioner(java.lang.String, dwtx.jface.text.IDocumentPartitioner) | |
1623 * @since 3.0 | |
1624 */ | |
1625 public void setDocumentPartitioner(String partitioning, IDocumentPartitioner partitioner) { | |
1626 if (partitioner is null) { | |
1627 if (fDocumentPartitioners !is null) { | |
1628 fDocumentPartitioners.remove(partitioning); | |
1629 if (fDocumentPartitioners.size() is 0) | |
1630 fDocumentPartitioners= null; | |
1631 } | |
1632 } else { | |
1633 if (fDocumentPartitioners is null) | |
1634 fDocumentPartitioners= new HashMap(); | |
1635 fDocumentPartitioners.put(partitioning, partitioner); | |
1636 } | |
1637 DocumentPartitioningChangedEvent event= new DocumentPartitioningChangedEvent(this); | |
1638 event.setPartitionChange(partitioning, 0, getLength()); | |
1639 fireDocumentPartitioningChanged(event); | |
1640 } | |
1641 | |
1642 /* | |
1643 * @see dwtx.jface.text.IRepairableDocument#repairLineInformation() | |
1644 * @since 3.0 | |
1645 */ | |
1646 public void repairLineInformation() { | |
1647 getTracker().set(get()); | |
1648 } | |
1649 | |
1650 /** | |
1651 * Fires the given event to all registered rewrite session listeners. Uses robust iterators. | |
1652 * | |
1653 * @param event the event to be fired | |
1654 * @since 3.1 | |
1655 */ | |
1656 protected void fireRewriteSessionChanged(DocumentRewriteSessionEvent event) { | |
1657 if (fDocumentRewriteSessionListeners.size() > 0) { | |
1658 List list= new ArrayList(fDocumentRewriteSessionListeners); | |
1659 Iterator e= list.iterator(); | |
1660 while (e.hasNext()) { | |
134 | 1661 IDocumentRewriteSessionListener l= cast(IDocumentRewriteSessionListener) e.next(); |
129 | 1662 l.documentRewriteSessionChanged(event); |
1663 } | |
1664 } | |
1665 } | |
1666 | |
1667 /* | |
1668 * @see dwtx.jface.text.IDocumentExtension4#getActiveRewriteSession() | |
1669 */ | |
1670 public final DocumentRewriteSession getActiveRewriteSession() { | |
1671 return fDocumentRewriteSession; | |
1672 } | |
1673 | |
1674 /* | |
1675 * @see dwtx.jface.text.IDocumentExtension4#startRewriteSession(dwtx.jface.text.DocumentRewriteSessionType) | |
1676 * @since 3.1 | |
1677 */ | |
1678 public DocumentRewriteSession startRewriteSession(DocumentRewriteSessionType sessionType) { | |
1679 | |
1680 if (getActiveRewriteSession() !is null) | |
1681 throw new IllegalStateException(); | |
1682 | |
1683 | |
1684 fDocumentRewriteSession= new DocumentRewriteSession(sessionType); | |
134 | 1685 if cast(DEBUG) |
129 | 1686 System.out.println("AbstractDocument: Starting rewrite session: " + fDocumentRewriteSession); //$NON-NLS-1$ |
1687 | |
1688 fireRewriteSessionChanged(new DocumentRewriteSessionEvent(this, fDocumentRewriteSession, DocumentRewriteSessionEvent.SESSION_START)); | |
1689 | |
1690 startRewriteSessionOnPartitioners(fDocumentRewriteSession); | |
1691 | |
1692 ILineTracker tracker= getTracker(); | |
1693 if (tracker instanceof ILineTrackerExtension) { | |
134 | 1694 ILineTrackerExtension extension= cast(ILineTrackerExtension) tracker; |
129 | 1695 extension.startRewriteSession(fDocumentRewriteSession); |
1696 } | |
1697 | |
1698 if (DocumentRewriteSessionType.SEQUENTIAL is sessionType) | |
1699 startSequentialRewrite(false); | |
1700 else if (DocumentRewriteSessionType.STRICTLY_SEQUENTIAL is sessionType) | |
1701 startSequentialRewrite(true); | |
1702 | |
1703 return fDocumentRewriteSession; | |
1704 } | |
1705 | |
1706 /** | |
1707 * Starts the given rewrite session. | |
1708 * | |
1709 * @param session the rewrite session | |
1710 * @since 3.1 | |
1711 */ | |
1712 protected final void startRewriteSessionOnPartitioners(DocumentRewriteSession session) { | |
1713 if (fDocumentPartitioners !is null) { | |
1714 Iterator e= fDocumentPartitioners.values().iterator(); | |
1715 while (e.hasNext()) { | |
1716 Object partitioner= e.next(); | |
1717 if (partitioner instanceof IDocumentPartitionerExtension3) { | |
134 | 1718 IDocumentPartitionerExtension3 extension= cast(IDocumentPartitionerExtension3) partitioner; |
129 | 1719 extension.startRewriteSession(session); |
1720 } | |
1721 } | |
1722 } | |
1723 } | |
1724 | |
1725 /* | |
1726 * @see dwtx.jface.text.IDocumentExtension4#stopRewriteSession(dwtx.jface.text.DocumentRewriteSession) | |
1727 * @since 3.1 | |
1728 */ | |
1729 public void stopRewriteSession(DocumentRewriteSession session) { | |
1730 if (fDocumentRewriteSession is session) { | |
1731 | |
134 | 1732 if cast(DEBUG) |
129 | 1733 System.out.println("AbstractDocument: Stopping rewrite session: " + session); //$NON-NLS-1$ |
1734 | |
1735 DocumentRewriteSessionType sessionType= session.getSessionType(); | |
1736 if (DocumentRewriteSessionType.SEQUENTIAL is sessionType || DocumentRewriteSessionType.STRICTLY_SEQUENTIAL is sessionType) | |
1737 stopSequentialRewrite(); | |
1738 | |
1739 ILineTracker tracker= getTracker(); | |
1740 if (tracker instanceof ILineTrackerExtension) { | |
134 | 1741 ILineTrackerExtension extension= cast(ILineTrackerExtension) tracker; |
129 | 1742 extension.stopRewriteSession(session, get()); |
1743 } | |
1744 | |
1745 stopRewriteSessionOnPartitioners(fDocumentRewriteSession); | |
1746 | |
1747 fDocumentRewriteSession= null; | |
1748 fireRewriteSessionChanged(new DocumentRewriteSessionEvent(this, session, DocumentRewriteSessionEvent.SESSION_STOP)); | |
1749 } | |
1750 } | |
1751 | |
1752 /** | |
1753 * Stops the given rewrite session. | |
1754 * | |
1755 * @param session the rewrite session | |
1756 * @since 3.1 | |
1757 */ | |
1758 protected final void stopRewriteSessionOnPartitioners(DocumentRewriteSession session) { | |
1759 if (fDocumentPartitioners !is null) { | |
1760 DocumentPartitioningChangedEvent event= new DocumentPartitioningChangedEvent(this); | |
1761 Iterator e= fDocumentPartitioners.keySet().iterator(); | |
1762 while (e.hasNext()) { | |
134 | 1763 String partitioning= cast(String) e.next(); |
1764 IDocumentPartitioner partitioner= cast(IDocumentPartitioner) fDocumentPartitioners.get(partitioning); | |
129 | 1765 if (partitioner instanceof IDocumentPartitionerExtension3) { |
134 | 1766 IDocumentPartitionerExtension3 extension= cast(IDocumentPartitionerExtension3) partitioner; |
129 | 1767 extension.stopRewriteSession(session); |
1768 event.setPartitionChange(partitioning, 0, getLength()); | |
1769 } | |
1770 } | |
1771 if (!event.isEmpty()) | |
1772 fireDocumentPartitioningChanged(event); | |
1773 } | |
1774 } | |
1775 | |
1776 /* | |
1777 * @see dwtx.jface.text.IDocumentExtension4#addDocumentRewriteSessionListener(dwtx.jface.text.IDocumentRewriteSessionListener) | |
1778 * @since 3.1 | |
1779 */ | |
1780 public void addDocumentRewriteSessionListener(IDocumentRewriteSessionListener listener) { | |
1781 Assert.isNotNull(listener); | |
1782 if (! fDocumentRewriteSessionListeners.contains(listener)) | |
1783 fDocumentRewriteSessionListeners.add(listener); | |
1784 } | |
1785 | |
1786 /* | |
1787 * @see dwtx.jface.text.IDocumentExtension4#removeDocumentRewriteSessionListener(dwtx.jface.text.IDocumentRewriteSessionListener) | |
1788 * @since 3.1 | |
1789 */ | |
1790 public void removeDocumentRewriteSessionListener(IDocumentRewriteSessionListener listener) { | |
1791 Assert.isNotNull(listener); | |
1792 fDocumentRewriteSessionListeners.remove(listener); | |
1793 } | |
1794 | |
1795 /** | |
1796 * Checks the state for the given partitioner and stops the | |
1797 * active rewrite session. | |
1798 * | |
1799 * @param partitioner the document partitioner to be checked | |
1800 * @param partitioning the document partitioning the partitioner is registered for | |
1801 * @since 3.1 | |
1802 */ | |
1803 protected final void checkStateOfPartitioner(IDocumentPartitioner partitioner, String partitioning) { | |
1804 if (!(partitioner instanceof IDocumentPartitionerExtension3)) | |
1805 return; | |
1806 | |
134 | 1807 IDocumentPartitionerExtension3 extension= cast(IDocumentPartitionerExtension3) partitioner; |
129 | 1808 DocumentRewriteSession session= extension.getActiveRewriteSession(); |
1809 if (session !is null) { | |
1810 extension.stopRewriteSession(session); | |
1811 | |
134 | 1812 if cast(DEBUG) |
129 | 1813 System.out.println("AbstractDocument: Flushing rewrite session for partition type: " + partitioning); //$NON-NLS-1$ |
1814 | |
1815 DocumentPartitioningChangedEvent event= new DocumentPartitioningChangedEvent(this); | |
1816 event.setPartitionChange(partitioning, 0, getLength()); | |
1817 fireDocumentPartitioningChanged(event); | |
1818 } | |
1819 } | |
1820 | |
1821 /** | |
1822 * Returns all positions of the given category that are inside the given region. | |
1823 * | |
1824 * @param category the position category | |
1825 * @param offset the start position of the region, must be >= 0 | |
1826 * @param length the length of the region, must be >= 0 | |
1827 * @param canStartBefore if <code>true</code> then positions are included | |
1828 * which start before the region if they end at or after the regions start | |
1829 * @param canEndAfter if <code>true</code> then positions are included | |
1830 * which end after the region if they start at or before the regions end | |
1831 * @return all positions inside the region of the given category | |
1832 * @throws BadPositionCategoryException if category is undefined in this document | |
1833 * @since 3.4 | |
1834 */ | |
1835 public Position[] getPositions(String category, int offset, int length, bool canStartBefore, bool canEndAfter) throws BadPositionCategoryException { | |
1836 if (canStartBefore && canEndAfter || (!canStartBefore && !canEndAfter)) { | |
1837 List documentPositions; | |
1838 if (canStartBefore && canEndAfter) { | |
1839 if (offset < getLength() / 2) { | |
1840 documentPositions= getStartingPositions(category, 0, offset + length); | |
1841 } else { | |
1842 documentPositions= getEndingPositions(category, offset, getLength() - offset + 1); | |
1843 } | |
1844 } else { | |
1845 documentPositions= getStartingPositions(category, offset, length); | |
1846 } | |
1847 | |
1848 ArrayList list= new ArrayList(documentPositions.size()); | |
1849 | |
1850 Position region= new Position(offset, length); | |
1851 | |
1852 for (Iterator iterator= documentPositions.iterator(); iterator.hasNext();) { | |
134 | 1853 Position position= cast(Position) iterator.next(); |
129 | 1854 if (isWithinRegion(region, position, canStartBefore, canEndAfter)) { |
1855 list.add(position); | |
1856 } | |
1857 } | |
1858 | |
1859 Position[] positions= new Position[list.size()]; | |
1860 list.toArray(positions); | |
1861 return positions; | |
1862 } else if (canStartBefore) { | |
1863 List list= getEndingPositions(category, offset, length); | |
1864 Position[] positions= new Position[list.size()]; | |
1865 list.toArray(positions); | |
1866 return positions; | |
1867 } else { | |
1868 Assert.isLegal(canEndAfter && !canStartBefore); | |
1869 | |
1870 List list= getStartingPositions(category, offset, length); | |
1871 Position[] positions= new Position[list.size()]; | |
1872 list.toArray(positions); | |
1873 return positions; | |
1874 } | |
1875 } | |
1876 | |
1877 /* | |
1878 * @since 3.4 | |
1879 */ | |
1880 private bool isWithinRegion(Position region, Position position, bool canStartBefore, bool canEndAfter) { | |
1881 if (canStartBefore && canEndAfter) { | |
1882 return region.overlapsWith(position.getOffset(), position.getLength()); | |
1883 } else if (canStartBefore) { | |
1884 return region.includes(position.getOffset() + position.getLength() - 1); | |
1885 } else if (canEndAfter) { | |
1886 return region.includes(position.getOffset()); | |
1887 } else { | |
1888 int start= position.getOffset(); | |
1889 return region.includes(start) && region.includes(start + position.getLength() - 1); | |
1890 } | |
1891 } | |
1892 | |
1893 /** | |
1894 * A list of positions in the given category with an offset inside the given | |
1895 * region. The order of the positions is arbitrary. | |
1896 * | |
1897 * @param category the position category | |
1898 * @param offset the offset of the region | |
1899 * @param length the length of the region | |
1900 * @return a list of the positions in the region | |
1901 * @throws BadPositionCategoryException if category is undefined in this document | |
1902 * @since 3.4 | |
1903 */ | |
1904 private List getStartingPositions(String category, int offset, int length) throws BadPositionCategoryException { | |
134 | 1905 List positions= cast(List) fPositions.get(category); |
129 | 1906 if (positions is null) |
1907 throw new BadPositionCategoryException(); | |
1908 | |
1909 int indexStart= computeIndexInPositionList(positions, offset, true); | |
1910 int indexEnd= computeIndexInPositionList(positions, offset + length, true); | |
1911 | |
1912 return positions.subList(indexStart, indexEnd); | |
1913 } | |
1914 | |
1915 /** | |
1916 * A list of positions in the given category with an end position inside | |
1917 * the given region. The order of the positions is arbitrary. | |
1918 * | |
1919 * @param category the position category | |
1920 * @param offset the offset of the region | |
1921 * @param length the length of the region | |
1922 * @return a list of the positions in the region | |
1923 * @throws BadPositionCategoryException if category is undefined in this document | |
1924 * @since 3.4 | |
1925 */ | |
1926 private List getEndingPositions(String category, int offset, int length) throws BadPositionCategoryException { | |
134 | 1927 List positions= cast(List) fEndPositions.get(category); |
129 | 1928 if (positions is null) |
1929 throw new BadPositionCategoryException(); | |
1930 | |
1931 int indexStart= computeIndexInPositionList(positions, offset, false); | |
1932 int indexEnd= computeIndexInPositionList(positions, offset + length, false); | |
1933 | |
1934 return positions.subList(indexStart, indexEnd); | |
1935 } | |
1936 | |
1937 | |
1938 } |