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