comparison dwtx/jface/text/IDocument.d @ 129:eb30df5ca28b

Added JFace Text sources
author Frank Benoit <benoit@tionex.de>
date Sat, 23 Aug 2008 19:10:48 +0200
parents
children c4fb132a086c
comparison
equal deleted inserted replaced
128:8df1d4193877 129:eb30df5ca28b
1 /*******************************************************************************
2 * Copyright (c) 2000, 2007 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13
14 module dwtx.jface.text.IDocument;
15
16 import dwt.dwthelper.utils;
17
18
19 /**
20 * An <code>IDocument</code> represents text providing support for
21 * <ul>
22 * <li> text manipulation
23 * <li> positions
24 * <li> partitions
25 * <li> line information
26 * <li> document change listeners
27 * <li> document partition change listeners
28 * </ul>
29 *
30 * A document allows to set its content and to manipulate it. For manipulation
31 * a document provides the <code>replace</code> method which substitutes a given
32 * string for a specified text range in the document. On each document change, all
33 * registered document listeners are informed exactly once.
34 * <p>
35 * Positions are stickers to the document's text that are updated when the
36 * document is changed. Positions are updated by {@link dwtx.jface.text.IPositionUpdater}s. Position
37 * updaters are managed as a list. The list defines the sequence in which position
38 * updaters are invoked. This way, position updaters may rely on each other.
39 * Positions are grouped into categories. A category is a ordered list of positions.
40 * the document defines the order of position in a category based on the position's offset
41 * based on the implementation of the method <code>computeIndexInCategory</code>.
42 * Each document must support a default position category whose name is specified by this
43 * interface.</p>
44 * <p>
45 * A document can be considered consisting of a sequence of not overlapping partitions.
46 * A partition is defined by its offset, its length, and its type. Partitions are
47 * updated on every document manipulation and ensured to be up-to-date when the document
48 * listeners are informed. A document uses an <code>IDocumentPartitioner</code> to
49 * manage its partitions. A document may be unpartitioned which happens when there is no
50 * partitioner. In this case, the document is considered as one single partition of a
51 * default type. The default type is specified by this interface. If a document change
52 * changes the document's partitioning all registered partitioning listeners are
53 * informed exactly once. The extension interface {@link dwtx.jface.text.IDocumentExtension3}
54 * introduced in version 3.0 extends the concept of partitions and allows a document to
55 * not only manage one but multiple partitioning. Each partitioning has an id which must
56 * be used to refer to a particular partitioning.</p>
57 * <p>
58 * An <code>IDocument</code> provides methods to map line numbers and character
59 * positions onto each other based on the document's line delimiters. When moving text
60 * between documents using different line delimiters, the text must be converted to
61 * use the target document's line delimiters.</p>
62 * <p>
63 * An <code>IDocument</code> does not care about mixed line delimiters. Clients who
64 * want to ensure a single line delimiter in their document should use the line
65 * delimiter returned by {@link dwtx.jface.text.TextUtilities#getDefaultLineDelimiter(IDocument)}.</p>
66 * <p>
67 * <code>IDocument</code> throws <code>BadLocationException</code> if the parameters of
68 * queries or manipulation requests are not inside the bounds of the document. The purpose
69 * of this style of exception handling is
70 * <ul>
71 * <li> prepare document for multi-thread access
72 * <li> allow clients to implement backtracking recovery methods
73 * <li> prevent clients from up-front contract checking when dealing with documents.
74 * </ul></p>
75 * <p>
76 * A document support for searching has deprecated since version 3.0. The recommended way
77 * for searching is to use a {@link dwtx.jface.text.FindReplaceDocumentAdapter}.</p>
78 * <p>
79 * In order to provide backward compatibility for clients of <code>IDocument</code>, extension
80 * interfaces are used to provide a means of evolution. The following extension interfaces
81 * exist:
82 * <ul>
83 * <li> {@link dwtx.jface.text.IDocumentExtension} since version 2.0 introducing the concept
84 * of post notification replaces in order to allow document listeners to manipulate the document
85 * while receiving a document change notification </li>
86 * <li> {@link dwtx.jface.text.IDocumentExtension2} since version 2.1 introducing configuration
87 * methods for post notification replaces and document change notification. </li>
88 * <li> {@link dwtx.jface.text.IDocumentExtension3} since version 3.0 replacing the original
89 * partitioning concept by allowing multiple partitionings at the same time and introducing zero-
90 * length partitions in conjunction with the distinction between open and closed partitions. </li>
91 * <li> {@link dwtx.jface.text.IDocumentExtension4} since version 3.1 introducing the
92 * concept of rewrite sessions. A rewrite session is a sequence of document replace operations
93 * that form a semantic unit. It also introduces a modification stamp and the ability to
94 * set the initial line delimiter and to query the default line delimiter.</li>
95 * </ul></p>
96 * <p>
97 * Clients may implement this interface and its extension interfaces or use the default
98 * implementation provided by <code>AbstractDocument</code> and <code>Document</code>.</p>
99 *
100 * @see dwtx.jface.text.IDocumentExtension
101 * @see dwtx.jface.text.IDocumentExtension2
102 * @see dwtx.jface.text.IDocumentExtension3
103 * @see dwtx.jface.text.IDocumentExtension4
104 * @see dwtx.jface.text.Position
105 * @see dwtx.jface.text.IPositionUpdater
106 * @see dwtx.jface.text.IDocumentPartitioner
107 * @see dwtx.jface.text.ILineTracker
108 * @see dwtx.jface.text.IDocumentListener
109 * @see dwtx.jface.text.IDocumentPartitioningListener
110 */
111 public interface IDocument {
112
113
114 /**
115 * The identifier of the default position category.
116 */
117 final static String DEFAULT_CATEGORY= "__dflt_position_category"; //$NON-NLS-1$
118
119 /**
120 * The identifier of the default partition content type.
121 */
122 final static String DEFAULT_CONTENT_TYPE= "__dftl_partition_content_type"; //$NON-NLS-1$
123
124
125
126
127 /* --------------- text access and manipulation --------------------------- */
128
129 /**
130 * Returns the character at the given document offset in this document.
131 *
132 * @param offset a document offset
133 * @return the character at the offset
134 * @exception BadLocationException if the offset is invalid in this document
135 */
136 char getChar(int offset) throws BadLocationException;
137
138 /**
139 * Returns the number of characters in this document.
140 *
141 * @return the number of characters in this document
142 */
143 int getLength();
144
145 /**
146 * Returns this document's complete text.
147 *
148 * @return the document's complete text
149 */
150 String get();
151
152 /**
153 * Returns this document's text for the specified range.
154 *
155 * @param offset the document offset
156 * @param length the length of the specified range
157 * @return the document's text for the specified range
158 * @exception BadLocationException if the range is invalid in this document
159 */
160 String get(int offset, int length) throws BadLocationException;
161
162 /**
163 * Replaces the content of the document with the given text.
164 * Sends a <code>DocumentEvent</code> to all registered <code>IDocumentListener</code>.
165 * This method is a convenience method for <code>replace(0, getLength(), text)</code>.
166 *
167 * @param text the new content of the document
168 *
169 * @see DocumentEvent
170 * @see IDocumentListener
171 */
172 void set(String text);
173
174 /**
175 * Substitutes the given text for the specified document range.
176 * Sends a <code>DocumentEvent</code> to all registered <code>IDocumentListener</code>.
177 *
178 * @param offset the document offset
179 * @param length the length of the specified range
180 * @param text the substitution text
181 * @exception BadLocationException if the offset is invalid in this document
182 *
183 * @see DocumentEvent
184 * @see IDocumentListener
185 */
186 void replace(int offset, int length, String text) throws BadLocationException;
187
188 /**
189 * Registers the document listener with the document. After registration
190 * the IDocumentListener is informed about each change of this document.
191 * If the listener is already registered nothing happens.<p>
192 * An <code>IDocumentListener</code> may call back to this method
193 * when being inside a document notification.
194 *
195 * @param listener the listener to be registered
196 */
197 void addDocumentListener(IDocumentListener listener);
198
199 /**
200 * Removes the listener from the document's list of document listeners.
201 * If the listener is not registered with the document nothing happens.<p>
202 * An <code>IDocumentListener</code> may call back to this method
203 * when being inside a document notification.
204 *
205 * @param listener the listener to be removed
206 */
207 void removeDocumentListener(IDocumentListener listener);
208
209 /**
210 * Adds the given document listener as one which is notified before
211 * those document listeners added with <code>addDocumentListener</code>
212 * are notified. If the given listener is also registered using
213 * <code>addDocumentListener</code> it will be notified twice.
214 * If the listener is already registered nothing happens.<p>
215 *
216 * This method is not for public use.
217 *
218 * @param documentAdapter the listener to be added as pre-notified document listener
219 *
220 * @see #removePrenotifiedDocumentListener(IDocumentListener)
221 */
222 void addPrenotifiedDocumentListener(IDocumentListener documentAdapter);
223
224 /**
225 * Removes the given document listener from the document's list of
226 * pre-notified document listeners. If the listener is not registered
227 * with the document nothing happens. <p>
228 *
229 * This method is not for public use.
230 *
231 * @param documentAdapter the listener to be removed
232 *
233 * @see #addPrenotifiedDocumentListener(IDocumentListener)
234 */
235 void removePrenotifiedDocumentListener(IDocumentListener documentAdapter);
236
237
238
239 /* -------------------------- positions ----------------------------------- */
240
241 /**
242 * Adds a new position category to the document. If the position category
243 * already exists nothing happens.
244 *
245 * @param category the category to be added
246 */
247 void addPositionCategory(String category);
248
249 /**
250 * Deletes the position category from the document. All positions
251 * in this category are thus deleted as well.
252 *
253 * @param category the category to be removed
254 * @exception BadPositionCategoryException if category is undefined in this document
255 */
256 void removePositionCategory(String category) throws BadPositionCategoryException;
257
258 /**
259 * Returns all position categories of this document. This
260 * includes the default position category.
261 *
262 * @return the document's position categories
263 */
264 String[] getPositionCategories();
265
266 /**
267 * Checks the presence of the specified position category.
268 *
269 * @param category the category to check
270 * @return <code>true</code> if category is defined
271 */
272 bool containsPositionCategory(String category);
273
274 /**
275 * Adds the position to the document's default position category.
276 * This is a convenience method for <code>addPosition(DEFAULT_CATEGORY, position)</code>.
277 *
278 * @param position the position to be added
279 * @exception BadLocationException if position describes an invalid range in this document
280 */
281 void addPosition(Position position) throws BadLocationException;
282
283 /**
284 * Removes the given position from the document's default position category.
285 * This is a convenience method for <code>removePosition(DEFAULT_CATEGORY, position)</code>.
286 *
287 * @param position the position to be removed
288 */
289 void removePosition(Position position);
290
291 /**
292 * Adds the position to the specified position category of the document.
293 * Positions may be added multiple times. The order of the category is
294 * maintained.
295 * <p>
296 * <strong>Note:</strong> The position is only updated on each change
297 * applied to the document if a {@link IPositionUpdater} has been
298 * registered that handles the given category.
299 * </p>
300 *
301 * @param category the category to which to add
302 * @param position the position to be added
303 * @throws BadLocationException if position describes an invalid range in this document
304 * @throws BadPositionCategoryException if the category is undefined in this document
305 */
306 void addPosition(String category, Position position) throws BadLocationException, BadPositionCategoryException;
307
308 /**
309 * Removes the given position from the specified position category.
310 * If the position is not part of the specified category nothing happens.
311 * If the position has been added multiple times, only the first occurrence is deleted.
312 *
313 * @param category the category from which to delete
314 * @param position the position to be deleted
315 * @exception BadPositionCategoryException if category is undefined in this document
316 */
317 void removePosition(String category, Position position) throws BadPositionCategoryException;
318
319 /**
320 * Returns all positions of the given position category.
321 * The positions are ordered according to the category's order.
322 * Manipulating this list does not affect the document, but manipulating the
323 * position does affect the document.
324 *
325 * @param category the category
326 * @return the list of all positions
327 * @exception BadPositionCategoryException if category is undefined in this document
328 */
329 Position[] getPositions(String category) throws BadPositionCategoryException;
330
331 /**
332 * Determines whether a position described by the parameters is managed by this document.
333 *
334 * @param category the category to check
335 * @param offset the offset of the position to find
336 * @param length the length of the position to find
337 * @return <code>true</code> if position is found
338 */
339 bool containsPosition(String category, int offset, int length);
340
341 /**
342 * Computes the index at which a <code>Position</code> with the
343 * specified offset would be inserted into the given category. As the
344 * ordering inside a category only depends on the offset, the index must be
345 * chosen to be the first of all positions with the same offset.
346 *
347 * @param category the category in which would be added
348 * @param offset the position offset to be considered
349 * @return the index into the category
350 * @exception BadLocationException if offset is invalid in this document
351 * @exception BadPositionCategoryException if category is undefined in this document
352 */
353 int computeIndexInCategory(String category, int offset) throws BadLocationException, BadPositionCategoryException;
354
355 /**
356 * Appends a new position updater to the document's list of position updaters.
357 * Position updaters may be added multiple times.<p>
358 * An <code>IPositionUpdater</code> may call back to this method
359 * when being inside a document notification.
360 *
361 * @param updater the updater to be added
362 */
363 void addPositionUpdater(IPositionUpdater updater);
364
365 /**
366 * Removes the position updater from the document's list of position updaters.
367 * If the position updater has multiple occurrences only the first occurrence is
368 * removed. If the position updater is not registered with this document, nothing
369 * happens.<p>
370 * An <code>IPositionUpdater</code> may call back to this method
371 * when being inside a document notification.
372 *
373 * @param updater the updater to be removed
374 */
375 void removePositionUpdater(IPositionUpdater updater);
376
377 /**
378 * Inserts the position updater at the specified index in the document's
379 * list of position updaters. Positions updaters may be inserted multiple times.<p>
380 * An <code>IPositionUpdater</code> may call back to this method
381 * when being inside a document notification.
382 *
383 * @param updater the updater to be inserted
384 * @param index the index in the document's updater list
385 */
386 void insertPositionUpdater(IPositionUpdater updater, int index);
387
388 /**
389 * Returns the list of position updaters attached to the document.
390 *
391 * @return the list of position updaters
392 */
393 IPositionUpdater[] getPositionUpdaters();
394
395
396
397
398 /* -------------------------- partitions ---------------------------------- */
399
400 /**
401 * Returns the set of legal content types of document partitions.
402 * This set can be empty. The set can contain more content types than
403 * contained by the result of <code>getPartitioning(0, getLength())</code>.
404 * <p>
405 * Use {@link IDocumentExtension3#getLegalContentTypes(String)} when the document
406 * supports multiple partitionings. In that case this method is equivalent to:
407 * <pre>
408 * IDocumentExtension3 extension= (IDocumentExtension3) document;
409 * return extension.getLegalContentTypes(IDocumentExtension3.DEFAULT_PARTITIONING);
410 * </pre>
411 *
412 * @return the set of legal content types
413 */
414 String[] getLegalContentTypes();
415
416 /**
417 * Returns the type of the document partition containing the given offset.
418 * This is a convenience method for <code>getPartition(offset).getType()</code>.
419 * <p>
420 * Use {@link IDocumentExtension3#getContentType(String, int, bool)} when
421 * the document supports multiple partitionings. In that case this method is
422 * equivalent to:
423 * <pre>
424 * IDocumentExtension3 extension= (IDocumentExtension3) document;
425 * return extension.getContentType(IDocumentExtension3.DEFAULT_PARTITIONING, offset, false);
426 * </pre>
427 *
428 * @param offset the document offset
429 * @return the partition type
430 * @exception BadLocationException if offset is invalid in this document
431 */
432 String getContentType(int offset) throws BadLocationException;
433
434 /**
435 * Returns the document partition in which the position is located.
436 * <p>
437 * Use {@link IDocumentExtension3#getPartition(String, int, bool)} when
438 * the document supports multiple partitionings. In that case this method is
439 * equivalent:
440 * <pre>
441 * IDocumentExtension3 extension= (IDocumentExtension3) document;
442 * return extension.getPartition(IDocumentExtension3.DEFAULT_PARTITIONING, offset, false);
443 * </pre>
444 *
445 * @param offset the document offset
446 * @return a specification of the partition
447 * @exception BadLocationException if offset is invalid in this document
448 */
449 ITypedRegion getPartition(int offset) throws BadLocationException;
450
451 /**
452 * Computes the partitioning of the given document range using the
453 * document's partitioner.
454 * <p>
455 * Use {@link IDocumentExtension3#computePartitioning(String, int, int, bool)} when
456 * the document supports multiple partitionings. In that case this method is
457 * equivalent:
458 * <pre>
459 * IDocumentExtension3 extension= (IDocumentExtension3) document;
460 * return extension.computePartitioning(IDocumentExtension3.DEFAULT_PARTITIONING, offset, length, false);
461 * </pre>
462 *
463 * @param offset the document offset at which the range starts
464 * @param length the length of the document range
465 * @return a specification of the range's partitioning
466 * @exception BadLocationException if the range is invalid in this document
467 */
468 ITypedRegion[] computePartitioning(int offset, int length) throws BadLocationException;
469
470 /**
471 * Registers the document partitioning listener with the document. After registration
472 * the document partitioning listener is informed about each partition change
473 * cause by a document manipulation or by changing the document's partitioner.
474 * If a document partitioning listener is also
475 * a document listener, the following notification sequence is guaranteed if a
476 * document manipulation changes the document partitioning:
477 * <ul>
478 * <li>listener.documentAboutToBeChanged(DocumentEvent);
479 * <li>listener.documentPartitioningChanged();
480 * <li>listener.documentChanged(DocumentEvent);
481 * </ul>
482 * If the listener is already registered nothing happens.<p>
483 * An <code>IDocumentPartitioningListener</code> may call back to this method
484 * when being inside a document notification.
485 *
486 * @param listener the listener to be added
487 */
488 void addDocumentPartitioningListener(IDocumentPartitioningListener listener);
489
490 /**
491 * Removes the listener from this document's list of document partitioning
492 * listeners. If the listener is not registered with the document nothing
493 * happens.<p>
494 * An <code>IDocumentPartitioningListener</code> may call back to this method
495 * when being inside a document notification.
496 *
497 * @param listener the listener to be removed
498 */
499 void removeDocumentPartitioningListener(IDocumentPartitioningListener listener);
500
501 /**
502 * Sets this document's partitioner. The caller of this method is responsible for
503 * disconnecting the document's old partitioner from the document and to
504 * connect the new partitioner to the document. Informs all document partitioning
505 * listeners about this change.
506 * <p>
507 * Use {@link IDocumentExtension3#setDocumentPartitioner(String, IDocumentPartitioner)} when
508 * the document supports multiple partitionings. In that case this method is equivalent to:
509 * <pre>
510 * IDocumentExtension3 extension= (IDocumentExtension3) document;
511 * extension.setDocumentPartitioner(IDocumentExtension3.DEFAULT_PARTITIONING, partitioner);
512 * </pre>
513 *
514 * @param partitioner the document's new partitioner
515 *
516 * @see IDocumentPartitioningListener
517 */
518 void setDocumentPartitioner(IDocumentPartitioner partitioner);
519
520 /**
521 * Returns this document's partitioner.
522 * <p>
523 * Use {@link IDocumentExtension3#getDocumentPartitioner(String)} when
524 * the document supports multiple partitionings. In that case this method is
525 * equivalent to:
526 * <pre>
527 * IDocumentExtension3 extension= (IDocumentExtension3) document;
528 * return extension.getDocumentPartitioner(IDocumentExtension3.DEFAULT_PARTITIONING);
529 * </pre>
530 *
531 * @return this document's partitioner
532 */
533 IDocumentPartitioner getDocumentPartitioner();
534
535
536
537 /* ---------------------- line information -------------------------------- */
538
539 /**
540 * Returns the length of the given line including the line's delimiter.
541 *
542 * @param line the line of interest
543 * @return the length of the line
544 * @exception BadLocationException if the line number is invalid in this document
545 */
546 int getLineLength(int line) throws BadLocationException;
547
548 /**
549 * Returns the number of the line at which the character of the specified position is located.
550 * The first line has the line number 0. A new line starts directly after a line
551 * delimiter. <code>(offset is document length)</code> is a valid argument although there is no
552 * corresponding character.
553 *
554 * @param offset the document offset
555 * @return the number of the line
556 * @exception BadLocationException if the offset is invalid in this document
557 */
558 int getLineOfOffset(int offset) throws BadLocationException;
559
560 /**
561 * Determines the offset of the first character of the given line.
562 *
563 * @param line the line of interest
564 * @return the document offset
565 * @exception BadLocationException if the line number is invalid in this document
566 */
567 int getLineOffset(int line) throws BadLocationException;
568
569 /**
570 * Returns a description of the specified line. The line is described by its
571 * offset and its length excluding the line's delimiter.
572 *
573 * @param line the line of interest
574 * @return a line description
575 * @exception BadLocationException if the line number is invalid in this document
576 */
577 IRegion getLineInformation(int line) throws BadLocationException;
578
579 /**
580 * Returns a description of the line at the given offset.
581 * The description contains the offset and the length of the line
582 * excluding the line's delimiter.
583 *
584 * @param offset the offset whose line should be described
585 * @return a region describing the line
586 * @exception BadLocationException if offset is invalid in this document
587 */
588 IRegion getLineInformationOfOffset(int offset) throws BadLocationException;
589
590 /**
591 * Returns the number of lines in this document
592 *
593 * @return the number of lines in this document
594 */
595 int getNumberOfLines();
596
597 /**
598 * Returns the number of lines which are occupied by a given text range.
599 *
600 * @param offset the offset of the specified text range
601 * @param length the length of the specified text range
602 * @return the number of lines occupied by the specified range
603 * @exception BadLocationException if specified range is invalid in this tracker
604 */
605 int getNumberOfLines(int offset, int length) throws BadLocationException;
606
607 /**
608 * Computes the number of lines in the given text. For a given
609 * implementer of this interface this method returns the same
610 * result as <code>set(text); getNumberOfLines()</code>.
611 *
612 * @param text the text whose number of lines should be computed
613 * @return the number of lines in the given text
614 */
615 int computeNumberOfLines(String text);
616
617
618 /* ------------------ line delimiter conversion --------------------------- */
619
620 /**
621 * Returns the document's legal line delimiters.
622 *
623 * @return the document's legal line delimiters
624 */
625 String[] getLegalLineDelimiters();
626
627 /**
628 * Returns the line delimiter of that line or <code>null</code> if the
629 * line is not closed with a line delimiter.
630 *
631 * @param line the line of interest
632 * @return the line's delimiter or <code>null</code> if line does not have a delimiter
633 * @exception BadLocationException if the line number is invalid in this document
634 */
635 String getLineDelimiter(int line) throws BadLocationException;
636
637
638 /* ---------------------------- search ------------------------------------ */
639
640 /**
641 * Returns the offset of a given search string in the document based on a set of search criteria.
642 *
643 * @param startOffset document offset at which search starts
644 * @param findString the string to find
645 * @param forwardSearch the search direction
646 * @param caseSensitive indicates whether lower and upper case should be distinguished
647 * @param wholeWord indicates whether the findString should be limited by white spaces as
648 * defined by Character.isWhiteSpace
649 * @return the offset of the first occurrence of findString based on the parameters or -1 if no match is found
650 * @exception BadLocationException if startOffset is an invalid document offset
651 * @deprecated as of 3.0 search is provided by {@link FindReplaceDocumentAdapter}
652 */
653 int search(int startOffset, String findString, bool forwardSearch, bool caseSensitive, bool wholeWord) throws BadLocationException;
654 }