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