2 * (C) Copyright IBM Corp. 1998-2004. All Rights Reserved.
\r
4 * The program is provided "as is" without any warranty express or
\r
5 * implied, including the warranty of non-infringement and the implied
\r
6 * warranties of merchantibility and fitness for a particular purpose.
\r
7 * IBM will not be liable for any damages suffered by you as a result
\r
8 * of using the Program. In no event will IBM be liable for any
\r
9 * special, indirect or consequential damages or lost profits even if
\r
10 * IBM has been advised of the possibility of their occurrence. IBM
\r
11 * will not be liable for any third party claims against you.
\r
13 package com.ibm.richtext.styledtext;
\r
15 import com.ibm.richtext.textlayout.attributes.AttributeMap;
\r
16 import java.text.CharacterIterator;
\r
17 import java.awt.datatransfer.DataFlavor;
\r
20 * MConstText is a base class for text with multiple character and
\r
21 * paragraph styles. The text is a sequence of Unicode characters,
\r
22 * represented by <code>char</code>. Character and paragraph
\r
23 * styles are represented by the <code>AttributeMap</code> class.
\r
25 * Characters in the text are accessed with an integer index using the
\r
26 * <code>at</code> method.
\r
27 * Valid indices are between 0 and (length-1), where length is the number
\r
28 * of characters in the text. Additionally, the
\r
29 * characters in the text may be accessed through a
\r
30 * <code>java.text.CharacterIterator</code>.
\r
32 * Every character in the text has a character style associated with it,
\r
33 * represented by the <code>AttributeMap</code> class. The character
\r
34 * style for a particular character can be obtained using the
\r
35 * <code>characterStyleAt</code> method.
\r
37 * Each character in the text is contained in a paragraph. A paragraph
\r
38 * is a range of text including and terminated by a
\r
39 * paragraph separator (either <code>\n</code> or <code>U+2029</code>).
\r
41 * paragraph has a paragraph style associated with it, represented
\r
42 * by the <code>AttributeMap</code> class. Paragraph boundaries and
\r
43 * styles can be obtained from the MConstText.
\r
45 * This class does not have methods for modifying the text or styles.
\r
46 * However, subclasses may add this capability, so it is not safe to
\r
47 * assume that an MConstText instance is immutable. In particular,
\r
48 * the MText class adds modification protocol to this class. Clients
\r
49 * can detect whether an MConstText has changed by keeping track of its
\r
52 * A DataFlavor for clipboard content is defined in this class. Using
\r
53 * this DataFlavor insures that all clients will recognize MConstText
\r
54 * content on the clipboard.
\r
57 * @see java.text.CharacterIterator
\r
58 * @see java.awt.datatransfer.DataFlavor
\r
60 public abstract class MConstText {
\r
62 static final String COPYRIGHT =
\r
63 "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
\r
65 * The DataFlavor for MConstText clipboard content. Used to
\r
66 * indicate that clipboard data has an MConstText representation.
\r
68 public static final DataFlavor styledTextFlavor =
\r
69 new DataFlavor(MConstText.class, "Styled Text");
\r
71 protected MConstText() {
\r
74 //========================================================
\r
76 //========================================================
\r
78 * Return the character at offset <code>pos</code>.
\r
79 * @param pos a valid offset into the text
\r
80 * @return the character at offset <code>pos</code>
\r
82 public abstract char at(int pos);
\r
85 * Copy the characters in the range [<code>start</code>, <code>limit</code>)
\r
86 * into the array <code>dst</code>, beginning at <code>dstStart</code>.
\r
87 * @param start offset of first character which will be copied into the array
\r
88 * @param limit offset immediately after the last character which will be copied into the array
\r
89 * @param dst array in which to copy characters. The length of <code>dst</code> must be at least
\r
90 * (<code>dstStart + limit - start</code>).
\r
92 public abstract void extractChars(int start, int limit, char[] dst, int dstStart);
\r
95 * Create an MConstText containing the characters and styles in the range
\r
96 * [<code>start</code>, <code>limit</code>).
\r
97 * @param start offset of first character in the new text
\r
98 * @param limit offset immediately after the last character in the new text
\r
99 * @return an MConstText object containing the characters and styles in the given range
\r
101 public abstract MConstText extract(int start, int limit);
\r
104 * Create a <code>java.text.CharacterIterator</code> over all
\r
105 * of the characters in the text. Default implementation calls
\r
106 * <code>createCharacterIterator(0, length())</code>
\r
107 * @return a <code>java.text.CharacterIterator</code> over all
\r
108 * of the characters in the text
\r
110 public CharacterIterator createCharacterIterator() {
\r
112 return createCharacterIterator(0, length());
\r
116 * Create a <code>java.text.CharacterIterator</code> over the
\r
117 * given range of characters in the text.
\r
118 * @param start the first index in the iteration range
\r
119 * @param limit the index after the last character in the iteration range
\r
120 * @return a <code>java.text.CharacterIterator</code> over the
\r
123 public abstract CharacterIterator createCharacterIterator(int start,
\r
127 //========================================================
\r
129 //========================================================
\r
131 * Return the length of the MConstText object. The length is the number of characters in the text.
\r
132 * @return the length of the MConstText object
\r
134 public abstract int length();
\r
136 //========================================================
\r
137 // Character styles
\r
138 //========================================================
\r
141 * Return the index of the first character in the character style run
\r
142 * containing pos. All characters in a style run have the same character
\r
144 * @return the style at offset <code>pos</code>
\r
146 public abstract int characterStyleStart(int pos);
\r
149 * Return the index after the last character in the character style run
\r
150 * containing pos. All characters in a style run have the same character
\r
152 * @return the style at offset <code>pos</code>
\r
154 public abstract int characterStyleLimit(int pos);
\r
157 * Return the style applied to the character at offset <code>pos</code>.
\r
158 * @param pos a valid offset into the text
\r
159 * @return the style at offset <code>pos</code>
\r
161 public abstract AttributeMap characterStyleAt(int pos);
\r
163 //========================================================
\r
164 // PARAGRAPH BOUNDARIES
\r
165 //========================================================
\r
167 * Return the start of the paragraph containing the character at offset <code>pos</code>.
\r
168 * @param pos a valid offset into the text
\r
169 * @return the start of the paragraph containing the character at offset <code>pos</code>
\r
171 public abstract int paragraphStart(int pos);
\r
174 * Return the limit of the paragraph containing the character at offset <code>pos</code>.
\r
175 * @param pos a valid offset into the text
\r
176 * @return the limit of the paragraph containing the character at offset <code>pos</code>
\r
178 public abstract int paragraphLimit(int pos);
\r
181 * Return the paragraph style applied to the paragraph containing offset <code>pos</code>.
\r
182 * @param pos a valid offset into the text
\r
183 * @return the paragraph style in effect at <code>pos</code>
\r
185 public abstract AttributeMap paragraphStyleAt(int pos);
\r
188 * Return the current time stamp. The time stamp is
\r
189 * incremented whenever the contents of the MConstText changes.
\r
190 * @return the current paragraph style time stamp
\r
192 public abstract int getTimeStamp();
\r
195 * Return the start of the damaged range. If the start is not less
\r
196 * than the the limit of the damaged range, then the damaged range
\r
198 * @return the start of the damaged range
\r
199 * @see #damagedRangeLimit
\r
200 * @see MText#resetDamagedRange
\r
202 public abstract int damagedRangeStart();
\r
205 * Return the limit of the damaged range. If the start is not less
\r
206 * than the the limit of the damaged range, then the damaged range
\r
208 * @return the start of the damaged range
\r
209 * @see #damagedRangeStart
\r
210 * @see MText#resetDamagedRange
\r
212 public abstract int damagedRangeLimit();
\r
214 //========================================================
\r
215 // Equality and hashCode
\r
216 //========================================================
\r
218 * Compare this to another Object for equality. This is
\r
219 * equal to rhs if rhs is an MConstText which is equal
\r
221 * @param rhs Object to compare to
\r
222 * @return true if this equals <code>rhs</code>
\r
224 public final boolean equals(Object rhs) {
\r
226 MConstText otherText;
\r
229 otherText = (MConstText) rhs;
\r
231 catch(ClassCastException e) {
\r
235 return equals(otherText);
\r
239 * Compare this to another MConstText for equality. This is
\r
240 * equal to rhs if the characters and styles in rhs are the
\r
241 * same as this. Subclasses may override this implementation
\r
242 * for efficiency, but they should preserve these semantics.
\r
243 * Determining that two MConstText instances are equal may be
\r
244 * an expensive operation, since every character and style must
\r
246 * @param rhs Object to compare to
\r
247 * @return true if this equals <code>rhs</code>
\r
249 public boolean equals(MConstText rhs) {
\r
259 if (hashCode() != rhs.hashCode()) {
\r
263 int length = length();
\r
264 if (length != rhs.length()) {
\r
268 for (int i=0; i < length; i++) {
\r
269 if (i < length && at(i) != rhs.at(i)) {
\r
274 for (int start = 0; start < length;) {
\r
275 if (!characterStyleAt(start).equals(rhs.characterStyleAt(start))) {
\r
278 int limit = characterStyleLimit(start);
\r
279 if (limit != rhs.characterStyleLimit(start)) {
\r
285 for (int start = 0; start < length;) {
\r
287 if (!paragraphStyleAt(start).equals(rhs.paragraphStyleAt(start))) {
\r
290 start = paragraphLimit(start);
\r
293 return paragraphStyleAt(length).equals(rhs.paragraphStyleAt(length));
\r
297 * Return the hashCode for this MConstText. An empty MConstText
\r
298 * has hashCode 0; a nonempty MConstText's hashCode is
\r
299 * <blockquote><pre>
\r
301 * at(length/2)*31^1 +
\r
302 * at(length-1)*31^2 +
\r
303 * characterStyleAt(0).hashCode()*31^3 +
\r
304 * paragraphStyleAt(length-1).hashCode()*31^4
\r
305 * </pre></blockquote>
\r
306 * where <code>^</code> is exponentiation (not bitwise XOR).
\r
308 public final int hashCode() {
\r
311 int length = length();
\r
314 hashCode = paragraphStyleAt(length-1).hashCode();
\r
315 hashCode = hashCode*31 + characterStyleAt(0).hashCode();
\r
316 hashCode = hashCode*31 + at(length-1);
\r
317 hashCode = hashCode*31 + at(length/2);
\r
318 hashCode = hashCode*31 + at(0);
\r