]>
Commit | Line | Data |
---|---|---|
a1f4e5ed | 1 | /* AttributedString.java -- Models text with attributes |
1ce9c63d | 2 | Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc. |
a1f4e5ed TT |
3 | |
4 | This file is part of GNU Classpath. | |
5 | ||
6 | GNU Classpath is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2, or (at your option) | |
9 | any later version. | |
10 | ||
11 | GNU Classpath is distributed in the hope that it will be useful, but | |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GNU Classpath; see the file COPYING. If not, write to the | |
18 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
19 | 02111-1307 USA. | |
20 | ||
92aaa246 MW |
21 | Linking this library statically or dynamically with other modules is |
22 | making a combined work based on this library. Thus, the terms and | |
23 | conditions of the GNU General Public License cover the whole | |
24 | combination. | |
25 | ||
26 | As a special exception, the copyright holders of this library give you | |
27 | permission to link this library with independent modules to produce an | |
28 | executable, regardless of the license terms of these independent | |
29 | modules, and to copy and distribute the resulting executable under | |
30 | terms of your choice, provided that you also meet, for each linked | |
31 | independent module, the terms and conditions of the license of that | |
32 | module. An independent module is a module which is not derived from | |
33 | or based on this library. If you modify this library, you may extend | |
34 | this exception to your version of the library, but you are not | |
35 | obligated to do so. If you do not wish to do so, delete this | |
36 | exception statement from your version. */ | |
a1f4e5ed TT |
37 | |
38 | ||
39 | package java.text; | |
40 | ||
31e632d3 | 41 | import java.util.Arrays; |
e2ab6d12 | 42 | import java.util.ArrayList; |
1ce9c63d | 43 | import java.util.HashMap; |
a1f4e5ed | 44 | import java.util.Hashtable; |
f32c742c | 45 | import java.util.Iterator; |
a1f4e5ed TT |
46 | import java.util.Map; |
47 | import java.util.Set; | |
48 | ||
49 | /** | |
50 | * This class models a <code>String</code> with attributes over various | |
51 | * subranges of the string. It allows applications to access this | |
52 | * information via the <code>AttributedCharcterIterator</code> interface. | |
53 | * | |
54 | * @version 0.0 | |
55 | * | |
56 | * @author Aaron M. Renn (arenn@urbanophile.com) | |
57 | */ | |
58 | public class AttributedString | |
59 | { | |
60 | ||
61 | /*************************************************************************/ | |
62 | ||
63 | /* | |
64 | * Inner Classes | |
65 | */ | |
66 | ||
67 | /** | |
68 | * This class contains the attributes and ranges of text over which | |
69 | * that attributes apply. | |
70 | */ | |
71 | final class AttributeRange | |
72 | { | |
73 | ||
74 | /* | |
75 | * Instance Variables | |
76 | */ | |
77 | ||
78 | /** | |
79 | * A Map of the attributes | |
80 | */ | |
81 | Map attribs; | |
82 | ||
83 | /** | |
84 | * The beginning index of the attributes | |
85 | */ | |
86 | int begin_index; | |
87 | ||
88 | /** | |
89 | * The ending index of the attributes | |
90 | */ | |
91 | int end_index; | |
92 | ||
93 | /*************************************************************************/ | |
94 | ||
95 | /* | |
96 | * Constructors | |
97 | */ | |
98 | ||
99 | AttributeRange(Map attribs, int begin_index, int end_index) | |
100 | { | |
101 | this.attribs = attribs; | |
102 | this.begin_index = begin_index; | |
103 | this.end_index = end_index; | |
104 | } | |
105 | ||
106 | } // Inner class AttributeRange | |
107 | ||
108 | /*************************************************************************/ | |
109 | ||
110 | /* | |
111 | * Instance Variables | |
112 | */ | |
113 | ||
114 | /** | |
115 | * This object holds the string we are representing. | |
116 | */ | |
117 | private StringCharacterIterator sci; | |
118 | ||
119 | /** | |
120 | * This is the attribute information | |
121 | */ | |
122 | private AttributeRange[] attribs; | |
123 | ||
124 | /*************************************************************************/ | |
125 | ||
126 | /* | |
127 | * Constructors | |
128 | */ | |
129 | ||
130 | /** | |
131 | * This method initializes a new instance of <code>AttributedString</code> | |
132 | * that represents the specified <code>String</code> with no attributes. | |
133 | * | |
134 | * @param str The <code>String</code> to be attributed. | |
135 | */ | |
136 | public | |
137 | AttributedString(String str) | |
138 | { | |
139 | sci = new StringCharacterIterator(str); | |
140 | attribs = new AttributeRange[0]; | |
141 | } | |
142 | ||
143 | /*************************************************************************/ | |
144 | ||
145 | /** | |
146 | * This method initializes a new instance of <code>AttributedString</code> | |
147 | * that represents that specified <code>String</code> with the specified | |
148 | * attributes over the entire length of the <code>String</code>. | |
149 | * | |
150 | * @param str The <code>String</code> to be attributed. | |
151 | * @param attributes The attribute list. | |
152 | */ | |
153 | public | |
154 | AttributedString(String str, Map attributes) | |
155 | { | |
156 | this(str); | |
157 | ||
158 | attribs = new AttributeRange[1]; | |
159 | attribs[0] = new AttributeRange(attributes, 0, str.length()); | |
160 | } | |
161 | ||
162 | /*************************************************************************/ | |
163 | ||
164 | /** | |
165 | * This method initializes a new instance of <code>AttributedString</code> | |
166 | * that will use the text and attribute information from the specified | |
167 | * <code>AttributedCharacterIterator</code>. | |
168 | * | |
169 | * @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information. | |
170 | */ | |
171 | public | |
172 | AttributedString(AttributedCharacterIterator aci) | |
173 | { | |
174 | this(aci, aci.getBeginIndex(), aci.getEndIndex(), null); | |
175 | } | |
176 | ||
177 | /*************************************************************************/ | |
178 | ||
179 | /** | |
180 | * This method initializes a new instance of <code>AttributedString</code> | |
181 | * that will use the text and attribute information from the specified | |
182 | * subrange of the specified <code>AttributedCharacterIterator</code>. | |
183 | * | |
184 | * @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information. | |
185 | * @param begin_index The beginning index of the text subrange. | |
186 | * @param end_index The ending index of the text subrange. | |
187 | */ | |
188 | public | |
189 | AttributedString(AttributedCharacterIterator aci, int begin_index, | |
190 | int end_index) | |
191 | { | |
192 | this(aci, begin_index, end_index, null); | |
193 | } | |
194 | ||
195 | /*************************************************************************/ | |
196 | ||
197 | /** | |
198 | * This method initializes a new instance of <code>AttributedString</code> | |
199 | * that will use the text and attribute information from the specified | |
200 | * subrange of the specified <code>AttributedCharacterIterator</code>. | |
201 | * Only attributes from the source iterator that are present in the | |
202 | * specified array of attributes will be included in the attribute list | |
203 | * for this object. | |
204 | * | |
205 | * @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information. | |
206 | * @param begin_index The beginning index of the text subrange. | |
207 | * @param end_index The ending index of the text subrange. | |
208 | * @param attributes A list of attributes to include from the iterator, or <code>null</code> to include all attributes. | |
209 | */ | |
210 | public | |
211 | AttributedString(AttributedCharacterIterator aci, int begin_index, | |
212 | int end_index, AttributedCharacterIterator.Attribute[] attributes) | |
213 | { | |
214 | // Validate some arguments | |
215 | if ((begin_index < 0) || (end_index < begin_index)) | |
216 | throw new IllegalArgumentException("Bad index values"); | |
217 | ||
218 | StringBuffer sb = new StringBuffer(""); | |
219 | ||
220 | // Get the valid attribute list | |
221 | Set all_attribs = aci.getAllAttributeKeys(); | |
222 | if (attributes != null) | |
31e632d3 | 223 | all_attribs.retainAll(Arrays.asList(attributes)); |
a1f4e5ed TT |
224 | |
225 | // Loop through and extract the attributes | |
226 | char c = aci.setIndex(begin_index); | |
227 | ||
e2ab6d12 | 228 | ArrayList accum = new ArrayList(); |
a1f4e5ed TT |
229 | do |
230 | { | |
231 | sb.append(c); | |
232 | ||
233 | Iterator iter = all_attribs.iterator(); | |
234 | while(iter.hasNext()) | |
235 | { | |
236 | Object obj = iter.next(); | |
237 | ||
238 | // What should we do if this is not true? | |
239 | if (!(obj instanceof AttributedCharacterIterator.Attribute)) | |
240 | continue; | |
241 | ||
242 | AttributedCharacterIterator.Attribute attrib = | |
243 | (AttributedCharacterIterator.Attribute)obj; | |
244 | ||
245 | // Make sure the attribute is defined. | |
246 | int rl = aci.getRunLimit(attrib); | |
247 | if (rl == -1) | |
248 | continue; | |
249 | if (rl > end_index) | |
250 | rl = end_index; | |
251 | rl -= begin_index; | |
252 | ||
253 | // Check to see if we already processed this one | |
254 | int rs = aci.getRunStart(attrib); | |
255 | if ((rs < aci.getIndex()) && (aci.getIndex() != begin_index)) | |
256 | continue; | |
257 | ||
258 | // If the attribute run starts before the beginning index, we | |
259 | // need to junk it if it is an Annotation. | |
260 | Object attrib_obj = aci.getAttribute(attrib); | |
261 | if (rs < begin_index) | |
262 | { | |
263 | if (attrib_obj instanceof Annotation) | |
264 | continue; | |
265 | ||
266 | rs = begin_index; | |
267 | } | |
268 | else | |
269 | { | |
270 | rs -= begin_index; | |
271 | } | |
272 | ||
273 | // Create a map object. Yes this will only contain one attribute | |
274 | Map new_map = new Hashtable(); | |
275 | new_map.put(attrib, attrib_obj); | |
276 | ||
e2ab6d12 TT |
277 | // Add it to the attribute list. |
278 | accum.add(new AttributeRange(new_map, rs, rl)); | |
a1f4e5ed TT |
279 | } |
280 | ||
281 | c = aci.next(); | |
282 | } | |
283 | while(c != CharacterIterator.DONE); | |
284 | ||
e2ab6d12 TT |
285 | attribs = new AttributeRange[accum.size()]; |
286 | attribs = (AttributeRange[]) accum.toArray(attribs); | |
287 | ||
a1f4e5ed TT |
288 | sci = new StringCharacterIterator(sb.toString()); |
289 | } | |
290 | ||
291 | /*************************************************************************/ | |
292 | ||
293 | /* | |
294 | * Instance Methods | |
295 | */ | |
296 | ||
297 | /** | |
298 | * This method adds a new attribute that will cover the entire string. | |
299 | * | |
300 | * @param attrib The attribute to add. | |
301 | * @param value The value of the attribute. | |
302 | */ | |
303 | public void | |
304 | addAttribute(AttributedCharacterIterator.Attribute attrib, Object value) | |
305 | { | |
31e632d3 | 306 | addAttribute(attrib, value, 0, sci.getEndIndex()); |
a1f4e5ed TT |
307 | } |
308 | ||
309 | /*************************************************************************/ | |
310 | ||
311 | /** | |
312 | * This method adds a new attribute that will cover the specified subrange | |
313 | * of the string. | |
314 | * | |
315 | * @param attrib The attribute to add. | |
1ce9c63d | 316 | * @param value The value of the attribute, which may be null. |
a1f4e5ed TT |
317 | * @param begin_index The beginning index of the subrange. |
318 | * @param end_index The ending index of the subrange. | |
319 | * | |
320 | * @exception IllegalArgumentException If attribute is <code>null</code> or the subrange is not valid. | |
321 | */ | |
322 | public void | |
323 | addAttribute(AttributedCharacterIterator.Attribute attrib, Object value, | |
324 | int begin_index, int end_index) | |
325 | { | |
326 | if (attrib == null) | |
327 | throw new IllegalArgumentException("null attribute"); | |
328 | ||
1ce9c63d MK |
329 | HashMap hm = new HashMap(); |
330 | hm.put(attrib, value); | |
a1f4e5ed | 331 | |
1ce9c63d | 332 | addAttributes(hm, begin_index, end_index); |
a1f4e5ed TT |
333 | } |
334 | ||
335 | /*************************************************************************/ | |
336 | ||
337 | /** | |
338 | * This method adds all of the attributes in the specified list to the | |
339 | * specified subrange of the string. | |
340 | * | |
341 | * @param attributes The list of attributes. | |
342 | * @param begin_index The beginning index. | |
343 | * @param end_index The ending index | |
344 | * | |
345 | * @param IllegalArgumentException If the list is <code>null</code> or the subrange is not valid. | |
346 | */ | |
347 | public void | |
348 | addAttributes(Map attributes, int begin_index, int end_index) | |
349 | { | |
350 | if (attributes == null) | |
351 | throw new IllegalArgumentException("null attribute"); | |
352 | ||
353 | if ((begin_index < 0) || (end_index > sci.getEndIndex()) || | |
354 | (end_index < begin_index)) | |
355 | throw new IllegalArgumentException("bad range"); | |
356 | ||
357 | AttributeRange[] new_list = new AttributeRange[attribs.length + 1]; | |
358 | System.arraycopy(attribs, 0, new_list, 0, attribs.length); | |
359 | attribs = new_list; | |
360 | attribs[attribs.length - 1] = new AttributeRange(attributes, begin_index, | |
361 | end_index); | |
362 | } | |
363 | ||
364 | /*************************************************************************/ | |
365 | ||
366 | /** | |
367 | * This method returns an <code>AttributedCharacterIterator</code> that | |
368 | * will iterate over the entire string. | |
369 | * | |
370 | * @return An <code>AttributedCharacterIterator</code> for the entire string. | |
371 | */ | |
372 | public AttributedCharacterIterator | |
373 | getIterator() | |
374 | { | |
31e632d3 | 375 | return(new AttributedStringIterator(sci, attribs, 0, sci.getEndIndex(), null)); |
a1f4e5ed TT |
376 | } |
377 | ||
378 | /*************************************************************************/ | |
379 | ||
380 | /** | |
381 | * This method returns an <code>AttributedCharacterIterator</code> that | |
382 | * will iterate over the entire string. This iterator will return information | |
383 | * about the list of attributes in the specified array. Attributes not in | |
384 | * the array may or may not be returned by the iterator. If the specified | |
385 | * array is <code>null</code>, all attributes will be returned. | |
386 | * | |
387 | * @param attributes A list of attributes to include in the returned iterator. | |
388 | * | |
389 | * @return An <code>AttributedCharacterIterator</code> for this string. | |
390 | */ | |
391 | public AttributedCharacterIterator | |
392 | getIterator(AttributedCharacterIterator.Attribute[] attributes) | |
393 | { | |
31e632d3 | 394 | return(getIterator(attributes, 0, sci.getEndIndex())); |
a1f4e5ed TT |
395 | } |
396 | ||
397 | /*************************************************************************/ | |
398 | ||
399 | /** | |
400 | * This method returns an <code>AttributedCharacterIterator</code> that | |
401 | * will iterate over the specified subrange. This iterator will return information | |
402 | * about the list of attributes in the specified array. Attributes not in | |
403 | * the array may or may not be returned by the iterator. If the specified | |
404 | * array is <code>null</code>, all attributes will be returned. | |
405 | * | |
406 | * @param attributes A list of attributes to include in the returned iterator. | |
407 | * @param begin_index The beginning index of the subrange. | |
408 | * @param end_index The ending index of the subrange. | |
409 | * | |
410 | * @return An <code>AttributedCharacterIterator</code> for this string. | |
411 | */ | |
412 | public AttributedCharacterIterator | |
413 | getIterator(AttributedCharacterIterator.Attribute[] attributes, | |
414 | int begin_index, int end_index) | |
415 | { | |
416 | if ((begin_index < 0) || (end_index > sci.getEndIndex()) || | |
417 | (end_index < begin_index)) | |
418 | throw new IllegalArgumentException("bad range"); | |
419 | ||
420 | return(new AttributedStringIterator(sci, attribs, begin_index, end_index, | |
421 | attributes)); | |
422 | } | |
423 | ||
424 | } // class AttributedString | |
425 |