author | prr |
Fri, 23 May 2014 09:05:24 -0700 | |
changeset 24567 | a0ebe5fd56ff |
parent 5506 | 202f599c92aa |
permissions | -rw-r--r-- |
2 | 1 |
/* |
5506 | 2 |
* Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
package javax.swing.text; |
|
26 |
||
27 |
import java.util.*; |
|
28 |
import java.awt.*; |
|
29 |
import java.text.AttributedCharacterIterator; |
|
30 |
import java.text.BreakIterator; |
|
31 |
import java.awt.font.*; |
|
32 |
import java.awt.geom.AffineTransform; |
|
3976 | 33 |
import javax.swing.JComponent; |
2 | 34 |
import javax.swing.event.DocumentEvent; |
35 |
import sun.font.BidiUtils; |
|
36 |
||
37 |
/** |
|
38 |
* A flow strategy that uses java.awt.font.LineBreakMeasureer to |
|
39 |
* produce java.awt.font.TextLayout for i18n capable rendering. |
|
40 |
* If the child view being placed into the flow is of type |
|
41 |
* GlyphView and can be rendered by TextLayout, a GlyphPainter |
|
42 |
* that uses TextLayout is plugged into the GlyphView. |
|
43 |
* |
|
44 |
* @author Timothy Prinzing |
|
45 |
*/ |
|
46 |
class TextLayoutStrategy extends FlowView.FlowStrategy { |
|
47 |
||
48 |
/** |
|
49 |
* Constructs a layout strategy for paragraphs based |
|
50 |
* upon java.awt.font.LineBreakMeasurer. |
|
51 |
*/ |
|
52 |
public TextLayoutStrategy() { |
|
53 |
text = new AttributedSegment(); |
|
54 |
} |
|
55 |
||
56 |
// --- FlowStrategy methods -------------------------------------------- |
|
57 |
||
58 |
/** |
|
59 |
* Gives notification that something was inserted into the document |
|
60 |
* in a location that the given flow view is responsible for. The |
|
61 |
* strategy should update the appropriate changed region (which |
|
62 |
* depends upon the strategy used for repair). |
|
63 |
* |
|
64 |
* @param e the change information from the associated document |
|
65 |
* @param alloc the current allocation of the view inside of the insets. |
|
66 |
* This value will be null if the view has not yet been displayed. |
|
67 |
* @see View#insertUpdate |
|
68 |
*/ |
|
69 |
public void insertUpdate(FlowView fv, DocumentEvent e, Rectangle alloc) { |
|
70 |
sync(fv); |
|
71 |
super.insertUpdate(fv, e, alloc); |
|
72 |
} |
|
73 |
||
74 |
/** |
|
75 |
* Gives notification that something was removed from the document |
|
76 |
* in a location that the given flow view is responsible for. |
|
77 |
* |
|
78 |
* @param e the change information from the associated document |
|
79 |
* @param alloc the current allocation of the view inside of the insets. |
|
80 |
* @see View#removeUpdate |
|
81 |
*/ |
|
82 |
public void removeUpdate(FlowView fv, DocumentEvent e, Rectangle alloc) { |
|
83 |
sync(fv); |
|
84 |
super.removeUpdate(fv, e, alloc); |
|
85 |
} |
|
86 |
||
87 |
/** |
|
88 |
* Gives notification from the document that attributes were changed |
|
89 |
* in a location that this view is responsible for. |
|
90 |
* |
|
91 |
* @param changes the change information from the associated document |
|
92 |
* @param a the current allocation of the view |
|
93 |
* @param f the factory to use to rebuild if the view has children |
|
94 |
* @see View#changedUpdate |
|
95 |
*/ |
|
96 |
public void changedUpdate(FlowView fv, DocumentEvent e, Rectangle alloc) { |
|
97 |
sync(fv); |
|
98 |
super.changedUpdate(fv, e, alloc); |
|
99 |
} |
|
100 |
||
101 |
/** |
|
102 |
* Does a a full layout on the given View. This causes all of |
|
103 |
* the rows (child views) to be rebuilt to match the given |
|
104 |
* constraints for each row. This is called by a FlowView.layout |
|
105 |
* to update the child views in the flow. |
|
106 |
* |
|
1287
a04aca99c77a
6722802: Code improvement and warnings removing from the javax.swing.text package
rupashka
parents:
2
diff
changeset
|
107 |
* @param fv the view to reflow |
2 | 108 |
*/ |
109 |
public void layout(FlowView fv) { |
|
110 |
super.layout(fv); |
|
111 |
} |
|
112 |
||
113 |
/** |
|
114 |
* Creates a row of views that will fit within the |
|
115 |
* layout span of the row. This is implemented to execute the |
|
116 |
* superclass functionality (which fills the row with child |
|
117 |
* views or view fragments) and follow that with bidi reordering |
|
118 |
* of the unidirectional view fragments. |
|
119 |
* |
|
120 |
* @param row the row to fill in with views. This is assumed |
|
121 |
* to be empty on entry. |
|
122 |
* @param pos The current position in the children of |
|
123 |
* this views element from which to start. |
|
124 |
* @return the position to start the next row |
|
125 |
*/ |
|
126 |
protected int layoutRow(FlowView fv, int rowIndex, int p0) { |
|
127 |
int p1 = super.layoutRow(fv, rowIndex, p0); |
|
128 |
View row = fv.getView(rowIndex); |
|
129 |
Document doc = fv.getDocument(); |
|
130 |
Object i18nFlag = doc.getProperty(AbstractDocument.I18NProperty); |
|
131 |
if ((i18nFlag != null) && i18nFlag.equals(Boolean.TRUE)) { |
|
132 |
int n = row.getViewCount(); |
|
133 |
if (n > 1) { |
|
134 |
AbstractDocument d = (AbstractDocument)fv.getDocument(); |
|
135 |
Element bidiRoot = d.getBidiRootElement(); |
|
136 |
byte[] levels = new byte[n]; |
|
137 |
View[] reorder = new View[n]; |
|
138 |
||
139 |
for( int i=0; i<n; i++ ) { |
|
140 |
View v = row.getView(i); |
|
141 |
int bidiIndex =bidiRoot.getElementIndex(v.getStartOffset()); |
|
142 |
Element bidiElem = bidiRoot.getElement( bidiIndex ); |
|
143 |
levels[i] = (byte)StyleConstants.getBidiLevel(bidiElem.getAttributes()); |
|
144 |
reorder[i] = v; |
|
145 |
} |
|
146 |
||
147 |
BidiUtils.reorderVisually( levels, reorder ); |
|
148 |
row.replace(0, n, reorder); |
|
149 |
} |
|
150 |
} |
|
151 |
return p1; |
|
152 |
} |
|
153 |
||
154 |
/** |
|
155 |
* Adjusts the given row if possible to fit within the |
|
156 |
* layout span. Since all adjustments were already |
|
157 |
* calculated by the LineBreakMeasurer, this is implemented |
|
158 |
* to do nothing. |
|
159 |
* |
|
160 |
* @param r the row to adjust to the current layout |
|
161 |
* span. |
|
162 |
* @param desiredSpan the current layout span >= 0 |
|
163 |
* @param x the location r starts at. |
|
164 |
*/ |
|
165 |
protected void adjustRow(FlowView fv, int rowIndex, int desiredSpan, int x) { |
|
166 |
} |
|
167 |
||
168 |
/** |
|
169 |
* Creates a unidirectional view that can be used to represent the |
|
170 |
* current chunk. This can be either an entire view from the |
|
171 |
* logical view, or a fragment of the view. |
|
172 |
* |
|
173 |
* @param fv the view holding the flow |
|
174 |
* @param startOffset the start location for the view being created |
|
175 |
* @param spanLeft the about of span left to fill in the row |
|
176 |
* @param rowIndex the row the view will be placed into |
|
177 |
*/ |
|
178 |
protected View createView(FlowView fv, int startOffset, int spanLeft, int rowIndex) { |
|
179 |
// Get the child view that contains the given starting position |
|
180 |
View lv = getLogicalView(fv); |
|
181 |
View row = fv.getView(rowIndex); |
|
182 |
boolean requireNextWord = (viewBuffer.size() == 0) ? false : true; |
|
183 |
int childIndex = lv.getViewIndex(startOffset, Position.Bias.Forward); |
|
184 |
View v = lv.getView(childIndex); |
|
185 |
||
186 |
int endOffset = getLimitingOffset(v, startOffset, spanLeft, requireNextWord); |
|
187 |
if (endOffset == startOffset) { |
|
188 |
return null; |
|
189 |
} |
|
190 |
||
191 |
View frag; |
|
192 |
if ((startOffset==v.getStartOffset()) && (endOffset == v.getEndOffset())) { |
|
193 |
// return the entire view |
|
194 |
frag = v; |
|
195 |
} else { |
|
196 |
// return a unidirectional fragment. |
|
197 |
frag = v.createFragment(startOffset, endOffset); |
|
198 |
} |
|
199 |
||
200 |
if ((frag instanceof GlyphView) && (measurer != null)) { |
|
201 |
// install a TextLayout based renderer if the view is responsible |
|
202 |
// for glyphs. If the view represents a tab, the default |
|
203 |
// glyph painter is used (may want to handle tabs differently). |
|
204 |
boolean isTab = false; |
|
205 |
int p0 = frag.getStartOffset(); |
|
206 |
int p1 = frag.getEndOffset(); |
|
207 |
if ((p1 - p0) == 1) { |
|
208 |
// check for tab |
|
209 |
Segment s = ((GlyphView)frag).getText(p0, p1); |
|
210 |
char ch = s.first(); |
|
211 |
if (ch == '\t') { |
|
212 |
isTab = true; |
|
213 |
} |
|
214 |
} |
|
215 |
TextLayout tl = (isTab) ? null : |
|
216 |
measurer.nextLayout(spanLeft, text.toIteratorIndex(endOffset), |
|
217 |
requireNextWord); |
|
218 |
if (tl != null) { |
|
219 |
((GlyphView)frag).setGlyphPainter(new GlyphPainter2(tl)); |
|
220 |
} |
|
221 |
} |
|
222 |
return frag; |
|
223 |
} |
|
224 |
||
225 |
/** |
|
226 |
* Calculate the limiting offset for the next view fragment. |
|
227 |
* At most this would be the entire view (i.e. the limiting |
|
228 |
* offset would be the end offset in that case). If the range |
|
229 |
* contains a tab or a direction change, that will limit the |
|
230 |
* offset to something less. This value is then fed to the |
|
231 |
* LineBreakMeasurer as a limit to consider in addition to the |
|
232 |
* remaining span. |
|
233 |
* |
|
234 |
* @param v the logical view representing the starting offset. |
|
235 |
* @param startOffset the model location to start at. |
|
236 |
*/ |
|
237 |
int getLimitingOffset(View v, int startOffset, int spanLeft, boolean requireNextWord) { |
|
238 |
int endOffset = v.getEndOffset(); |
|
239 |
||
240 |
// check for direction change |
|
241 |
Document doc = v.getDocument(); |
|
242 |
if (doc instanceof AbstractDocument) { |
|
243 |
AbstractDocument d = (AbstractDocument) doc; |
|
244 |
Element bidiRoot = d.getBidiRootElement(); |
|
245 |
if( bidiRoot.getElementCount() > 1 ) { |
|
246 |
int bidiIndex = bidiRoot.getElementIndex( startOffset ); |
|
247 |
Element bidiElem = bidiRoot.getElement( bidiIndex ); |
|
248 |
endOffset = Math.min( bidiElem.getEndOffset(), endOffset ); |
|
249 |
} |
|
250 |
} |
|
251 |
||
252 |
// check for tab |
|
253 |
if (v instanceof GlyphView) { |
|
254 |
Segment s = ((GlyphView)v).getText(startOffset, endOffset); |
|
255 |
char ch = s.first(); |
|
256 |
if (ch == '\t') { |
|
257 |
// if the first character is a tab, create a dedicated |
|
258 |
// view for just the tab |
|
259 |
endOffset = startOffset + 1; |
|
260 |
} else { |
|
261 |
for (ch = s.next(); ch != Segment.DONE; ch = s.next()) { |
|
262 |
if (ch == '\t') { |
|
263 |
// found a tab, don't include it in the text |
|
264 |
endOffset = startOffset + s.getIndex() - s.getBeginIndex(); |
|
265 |
break; |
|
266 |
} |
|
267 |
} |
|
268 |
} |
|
269 |
} |
|
270 |
||
271 |
// determine limit from LineBreakMeasurer |
|
272 |
int limitIndex = text.toIteratorIndex(endOffset); |
|
273 |
if (measurer != null) { |
|
274 |
int index = text.toIteratorIndex(startOffset); |
|
275 |
if (measurer.getPosition() != index) { |
|
276 |
measurer.setPosition(index); |
|
277 |
} |
|
278 |
limitIndex = measurer.nextOffset(spanLeft, limitIndex, requireNextWord); |
|
279 |
} |
|
280 |
int pos = text.toModelPosition(limitIndex); |
|
281 |
return pos; |
|
282 |
} |
|
283 |
||
284 |
/** |
|
285 |
* Synchronize the strategy with its FlowView. Allows the strategy |
|
286 |
* to update its state to account for changes in that portion of the |
|
287 |
* model represented by the FlowView. Also allows the strategy |
|
288 |
* to update the FlowView in response to these changes. |
|
289 |
*/ |
|
290 |
void sync(FlowView fv) { |
|
291 |
View lv = getLogicalView(fv); |
|
292 |
text.setView(lv); |
|
293 |
||
294 |
Container container = fv.getContainer(); |
|
295 |
FontRenderContext frc = sun.swing.SwingUtilities2. |
|
296 |
getFontRenderContext(container); |
|
297 |
BreakIterator iter; |
|
298 |
Container c = fv.getContainer(); |
|
299 |
if (c != null) { |
|
300 |
iter = BreakIterator.getLineInstance(c.getLocale()); |
|
301 |
} else { |
|
302 |
iter = BreakIterator.getLineInstance(); |
|
303 |
} |
|
304 |
||
3976 | 305 |
Object shaper = null; |
306 |
if (c instanceof JComponent) { |
|
307 |
shaper = ((JComponent) c).getClientProperty( |
|
308 |
TextAttribute.NUMERIC_SHAPING); |
|
309 |
} |
|
310 |
text.setShaper(shaper); |
|
311 |
||
2 | 312 |
measurer = new LineBreakMeasurer(text, iter, frc); |
313 |
||
314 |
// If the children of the FlowView's logical view are GlyphViews, they |
|
315 |
// need to have their painters updated. |
|
316 |
int n = lv.getViewCount(); |
|
317 |
for( int i=0; i<n; i++ ) { |
|
318 |
View child = lv.getView(i); |
|
319 |
if( child instanceof GlyphView ) { |
|
320 |
int p0 = child.getStartOffset(); |
|
321 |
int p1 = child.getEndOffset(); |
|
322 |
measurer.setPosition(text.toIteratorIndex(p0)); |
|
323 |
TextLayout layout |
|
324 |
= measurer.nextLayout( Float.MAX_VALUE, |
|
325 |
text.toIteratorIndex(p1), false ); |
|
326 |
((GlyphView)child).setGlyphPainter(new GlyphPainter2(layout)); |
|
327 |
} |
|
328 |
} |
|
329 |
||
330 |
// Reset measurer. |
|
331 |
measurer.setPosition(text.getBeginIndex()); |
|
332 |
||
333 |
} |
|
334 |
||
335 |
// --- variables ------------------------------------------------------- |
|
336 |
||
337 |
private LineBreakMeasurer measurer; |
|
338 |
private AttributedSegment text; |
|
339 |
||
340 |
/** |
|
341 |
* Implementation of AttributedCharacterIterator that supports |
|
342 |
* the GlyphView attributes for rendering the glyphs through a |
|
343 |
* TextLayout. |
|
344 |
*/ |
|
345 |
static class AttributedSegment extends Segment implements AttributedCharacterIterator { |
|
346 |
||
347 |
AttributedSegment() { |
|
348 |
} |
|
349 |
||
350 |
View getView() { |
|
351 |
return v; |
|
352 |
} |
|
353 |
||
354 |
void setView(View v) { |
|
355 |
this.v = v; |
|
356 |
Document doc = v.getDocument(); |
|
357 |
int p0 = v.getStartOffset(); |
|
358 |
int p1 = v.getEndOffset(); |
|
359 |
try { |
|
360 |
doc.getText(p0, p1 - p0, this); |
|
361 |
} catch (BadLocationException bl) { |
|
362 |
throw new IllegalArgumentException("Invalid view"); |
|
363 |
} |
|
364 |
first(); |
|
365 |
} |
|
366 |
||
367 |
/** |
|
368 |
* Get a boundary position for the font. |
|
369 |
* This is implemented to assume that two fonts are |
|
370 |
* equal if their references are equal (i.e. that the |
|
371 |
* font came from a cache). |
|
372 |
* |
|
373 |
* @return the location in model coordinates. This is |
|
374 |
* not the same as the Segment coordinates. |
|
375 |
*/ |
|
376 |
int getFontBoundary(int childIndex, int dir) { |
|
377 |
View child = v.getView(childIndex); |
|
378 |
Font f = getFont(childIndex); |
|
379 |
for (childIndex += dir; (childIndex >= 0) && (childIndex < v.getViewCount()); |
|
380 |
childIndex += dir) { |
|
381 |
Font next = getFont(childIndex); |
|
382 |
if (next != f) { |
|
383 |
// this run is different |
|
384 |
break; |
|
385 |
} |
|
386 |
child = v.getView(childIndex); |
|
387 |
} |
|
388 |
return (dir < 0) ? child.getStartOffset() : child.getEndOffset(); |
|
389 |
} |
|
390 |
||
391 |
/** |
|
392 |
* Get the font at the given child index. |
|
393 |
*/ |
|
394 |
Font getFont(int childIndex) { |
|
395 |
View child = v.getView(childIndex); |
|
396 |
if (child instanceof GlyphView) { |
|
397 |
return ((GlyphView)child).getFont(); |
|
398 |
} |
|
399 |
return null; |
|
400 |
} |
|
401 |
||
402 |
int toModelPosition(int index) { |
|
403 |
return v.getStartOffset() + (index - getBeginIndex()); |
|
404 |
} |
|
405 |
||
406 |
int toIteratorIndex(int pos) { |
|
407 |
return pos - v.getStartOffset() + getBeginIndex(); |
|
408 |
} |
|
409 |
||
3976 | 410 |
private void setShaper(Object shaper) { |
411 |
this.shaper = shaper; |
|
412 |
} |
|
413 |
||
2 | 414 |
// --- AttributedCharacterIterator methods ------------------------- |
415 |
||
416 |
/** |
|
417 |
* Returns the index of the first character of the run |
|
418 |
* with respect to all attributes containing the current character. |
|
419 |
*/ |
|
420 |
public int getRunStart() { |
|
421 |
int pos = toModelPosition(getIndex()); |
|
422 |
int i = v.getViewIndex(pos, Position.Bias.Forward); |
|
423 |
View child = v.getView(i); |
|
424 |
return toIteratorIndex(child.getStartOffset()); |
|
425 |
} |
|
426 |
||
427 |
/** |
|
428 |
* Returns the index of the first character of the run |
|
429 |
* with respect to the given attribute containing the current character. |
|
430 |
*/ |
|
431 |
public int getRunStart(AttributedCharacterIterator.Attribute attribute) { |
|
432 |
if (attribute instanceof TextAttribute) { |
|
433 |
int pos = toModelPosition(getIndex()); |
|
434 |
int i = v.getViewIndex(pos, Position.Bias.Forward); |
|
435 |
if (attribute == TextAttribute.FONT) { |
|
436 |
return toIteratorIndex(getFontBoundary(i, -1)); |
|
437 |
} |
|
438 |
} |
|
439 |
return getBeginIndex(); |
|
440 |
} |
|
441 |
||
442 |
/** |
|
443 |
* Returns the index of the first character of the run |
|
444 |
* with respect to the given attributes containing the current character. |
|
445 |
*/ |
|
446 |
public int getRunStart(Set<? extends Attribute> attributes) { |
|
447 |
int index = getBeginIndex(); |
|
448 |
Object[] a = attributes.toArray(); |
|
449 |
for (int i = 0; i < a.length; i++) { |
|
450 |
TextAttribute attr = (TextAttribute) a[i]; |
|
451 |
index = Math.max(getRunStart(attr), index); |
|
452 |
} |
|
453 |
return Math.min(getIndex(), index); |
|
454 |
} |
|
455 |
||
456 |
/** |
|
457 |
* Returns the index of the first character following the run |
|
458 |
* with respect to all attributes containing the current character. |
|
459 |
*/ |
|
460 |
public int getRunLimit() { |
|
461 |
int pos = toModelPosition(getIndex()); |
|
462 |
int i = v.getViewIndex(pos, Position.Bias.Forward); |
|
463 |
View child = v.getView(i); |
|
464 |
return toIteratorIndex(child.getEndOffset()); |
|
465 |
} |
|
466 |
||
467 |
/** |
|
468 |
* Returns the index of the first character following the run |
|
469 |
* with respect to the given attribute containing the current character. |
|
470 |
*/ |
|
471 |
public int getRunLimit(AttributedCharacterIterator.Attribute attribute) { |
|
472 |
if (attribute instanceof TextAttribute) { |
|
473 |
int pos = toModelPosition(getIndex()); |
|
474 |
int i = v.getViewIndex(pos, Position.Bias.Forward); |
|
475 |
if (attribute == TextAttribute.FONT) { |
|
476 |
return toIteratorIndex(getFontBoundary(i, 1)); |
|
477 |
} |
|
478 |
} |
|
479 |
return getEndIndex(); |
|
480 |
} |
|
481 |
||
482 |
/** |
|
483 |
* Returns the index of the first character following the run |
|
484 |
* with respect to the given attributes containing the current character. |
|
485 |
*/ |
|
486 |
public int getRunLimit(Set<? extends Attribute> attributes) { |
|
487 |
int index = getEndIndex(); |
|
488 |
Object[] a = attributes.toArray(); |
|
489 |
for (int i = 0; i < a.length; i++) { |
|
490 |
TextAttribute attr = (TextAttribute) a[i]; |
|
491 |
index = Math.min(getRunLimit(attr), index); |
|
492 |
} |
|
493 |
return Math.max(getIndex(), index); |
|
494 |
} |
|
495 |
||
496 |
/** |
|
497 |
* Returns a map with the attributes defined on the current |
|
498 |
* character. |
|
499 |
*/ |
|
1287
a04aca99c77a
6722802: Code improvement and warnings removing from the javax.swing.text package
rupashka
parents:
2
diff
changeset
|
500 |
public Map<Attribute, Object> getAttributes() { |
2 | 501 |
Object[] ka = keys.toArray(); |
1287
a04aca99c77a
6722802: Code improvement and warnings removing from the javax.swing.text package
rupashka
parents:
2
diff
changeset
|
502 |
Hashtable<Attribute, Object> h = new Hashtable<Attribute, Object>(); |
2 | 503 |
for (int i = 0; i < ka.length; i++) { |
504 |
TextAttribute a = (TextAttribute) ka[i]; |
|
505 |
Object value = getAttribute(a); |
|
506 |
if (value != null) { |
|
507 |
h.put(a, value); |
|
508 |
} |
|
509 |
} |
|
510 |
return h; |
|
511 |
} |
|
512 |
||
513 |
/** |
|
514 |
* Returns the value of the named attribute for the current character. |
|
515 |
* Returns null if the attribute is not defined. |
|
516 |
* @param attribute the key of the attribute whose value is requested. |
|
517 |
*/ |
|
518 |
public Object getAttribute(AttributedCharacterIterator.Attribute attribute) { |
|
519 |
int pos = toModelPosition(getIndex()); |
|
520 |
int childIndex = v.getViewIndex(pos, Position.Bias.Forward); |
|
521 |
if (attribute == TextAttribute.FONT) { |
|
522 |
return getFont(childIndex); |
|
523 |
} else if( attribute == TextAttribute.RUN_DIRECTION ) { |
|
524 |
return |
|
525 |
v.getDocument().getProperty(TextAttribute.RUN_DIRECTION); |
|
3976 | 526 |
} else if (attribute == TextAttribute.NUMERIC_SHAPING) { |
527 |
return shaper; |
|
2 | 528 |
} |
529 |
return null; |
|
530 |
} |
|
531 |
||
532 |
/** |
|
533 |
* Returns the keys of all attributes defined on the |
|
534 |
* iterator's text range. The set is empty if no |
|
535 |
* attributes are defined. |
|
536 |
*/ |
|
1287
a04aca99c77a
6722802: Code improvement and warnings removing from the javax.swing.text package
rupashka
parents:
2
diff
changeset
|
537 |
public Set<Attribute> getAllAttributeKeys() { |
2 | 538 |
return keys; |
539 |
} |
|
540 |
||
541 |
View v; |
|
542 |
||
1287
a04aca99c77a
6722802: Code improvement and warnings removing from the javax.swing.text package
rupashka
parents:
2
diff
changeset
|
543 |
static Set<Attribute> keys; |
2 | 544 |
|
545 |
static { |
|
1287
a04aca99c77a
6722802: Code improvement and warnings removing from the javax.swing.text package
rupashka
parents:
2
diff
changeset
|
546 |
keys = new HashSet<Attribute>(); |
2 | 547 |
keys.add(TextAttribute.FONT); |
548 |
keys.add(TextAttribute.RUN_DIRECTION); |
|
3976 | 549 |
keys.add(TextAttribute.NUMERIC_SHAPING); |
2 | 550 |
} |
551 |
||
3976 | 552 |
private Object shaper = null; |
2 | 553 |
} |
554 |
||
555 |
} |