1 /* GlyphView.java -- A view to render styled text
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA
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
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. */
39 package javax
.swing
.text
;
41 import java
.awt
.Color
;
43 import java
.awt
.FontMetrics
;
44 import java
.awt
.Graphics
;
45 import java
.awt
.Rectangle
;
46 import java
.awt
.Shape
;
47 import java
.awt
.Toolkit
;
48 import java
.text
.BreakIterator
;
50 import javax
.swing
.SwingConstants
;
51 import javax
.swing
.event
.DocumentEvent
;
52 import javax
.swing
.text
.Position
.Bias
;
55 * Renders a run of styled text. This {@link View} subclass paints the
56 * characters of the <code>Element</code> it is responsible for using
57 * the style information from that <code>Element</code>.
59 * @author Roman Kennke (roman@kennke.org)
61 public class GlyphView
extends View
implements TabableView
, Cloneable
65 * An abstract base implementation for a glyph painter for
66 * <code>GlyphView</code>.
68 public abstract static class GlyphPainter
71 * Creates a new <code>GlyphPainer</code>.
75 // Nothing to do here.
79 * Returns the ascent of the font that is used by this glyph painter.
81 * @param v the glyph view
83 * @return the ascent of the font that is used by this glyph painter
85 public abstract float getAscent(GlyphView v
);
88 * Returns the descent of the font that is used by this glyph painter.
90 * @param v the glyph view
92 * @return the descent of the font that is used by this glyph painter
94 public abstract float getDescent(GlyphView v
);
97 * Returns the full height of the rendered text.
99 * @return the full height of the rendered text
101 public abstract float getHeight(GlyphView view
);
104 * Determines the model offset, so that the text between <code>p0</code>
105 * and this offset fits within the span starting at <code>x</code> with
106 * the length of <code>len</code>.
108 * @param v the glyph view
109 * @param p0 the starting offset in the model
110 * @param x the start location in the view
111 * @param len the length of the span in the view
113 public abstract int getBoundedPosition(GlyphView v
, int p0
, float x
,
119 * @param view the glyph view to paint
120 * @param g the graphics context to use for painting
121 * @param a the allocation of the glyph view
122 * @param p0 the start position (in the model) from which to paint
123 * @param p1 the end position (in the model) to which to paint
125 public abstract void paint(GlyphView view
, Graphics g
, Shape a
, int p0
,
129 * Maps a position in the document into the coordinate space of the View.
130 * The output rectangle usually reflects the font height but has a width
133 * @param view the glyph view
134 * @param pos the position of the character in the model
135 * @param a the area that is occupied by the view
136 * @param b either {@link Position.Bias#Forward} or
137 * {@link Position.Bias#Backward} depending on the preferred
138 * direction bias. If <code>null</code> this defaults to
139 * <code>Position.Bias.Forward</code>
141 * @return a rectangle that gives the location of the document position
142 * inside the view coordinate space
144 * @throws BadLocationException if <code>pos</code> is invalid
145 * @throws IllegalArgumentException if b is not one of the above listed
148 public abstract Shape
modelToView(GlyphView view
, int pos
, Position
.Bias b
,
150 throws BadLocationException
;
153 * Maps a visual position into a document location.
155 * @param v the glyph view
156 * @param x the X coordinate of the visual position
157 * @param y the Y coordinate of the visual position
158 * @param a the allocated region
159 * @param biasRet filled with the bias of the model location on method exit
161 * @return the model location that represents the specified view location
163 public abstract int viewToModel(GlyphView v
, float x
, float y
, Shape a
,
164 Position
.Bias
[] biasRet
);
167 * Determine the span of the glyphs from location <code>p0</code> to
168 * location <code>p1</code>. If <code>te</code> is not <code>null</code>,
169 * then TABs are expanded using this <code>TabExpander</code>.
170 * The parameter <code>x</code> is the location at which the view is
171 * located (this is important when using TAB expansion).
173 * @param view the glyph view
174 * @param p0 the starting location in the document model
175 * @param p1 the end location in the document model
176 * @param te the tab expander to use
177 * @param x the location at which the view is located
179 * @return the span of the glyphs from location <code>p0</code> to
180 * location <code>p1</code>, possibly using TAB expansion
182 public abstract float getSpan(GlyphView view
, int p0
, int p1
,
183 TabExpander te
, float x
);
187 * Returns the model location that should be used to place a caret when
188 * moving the caret through the document.
190 * @param v the glyph view
191 * @param pos the current model location
192 * @param b the bias for <code>p</code>
193 * @param a the allocated region for the glyph view
194 * @param direction the direction from the current position; Must be one of
195 * {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
196 * {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
197 * @param biasRet filled with the bias of the resulting location when method
200 * @return the location within the document that should be used to place the
201 * caret when moving the caret around the document
203 * @throws BadLocationException if <code>pos</code> is an invalid model
205 * @throws IllegalArgumentException if <code>d</code> is invalid
207 public int getNextVisualPositionFrom(GlyphView v
, int pos
, Position
.Bias b
,
208 Shape a
, int direction
,
209 Position
.Bias
[] biasRet
)
210 throws BadLocationException
216 case SwingConstants
.EAST
:
219 case SwingConstants
.WEST
:
222 case SwingConstants
.NORTH
:
223 case SwingConstants
.SOUTH
:
225 // This should be handled in enclosing view, since the glyph view
226 // does not layout vertically.
233 * Returns a painter that can be used to render the specified glyph view.
234 * If this glyph painter is stateful, then it should return a new instance.
235 * However, if this painter is stateless it should return itself. The
236 * default behaviour is to return itself.
238 * @param v the glyph view for which to create a painter
239 * @param p0 the start offset of the rendered area
240 * @param p1 the end offset of the rendered area
242 * @return a painter that can be used to render the specified glyph view
244 public GlyphPainter
getPainter(GlyphView v
, int p0
, int p1
)
251 * The default <code>GlyphPainter</code> used in <code>GlyphView</code>.
253 static class DefaultGlyphPainter
extends GlyphPainter
256 * Returns the full height of the rendered text.
258 * @return the full height of the rendered text
260 public float getHeight(GlyphView view
)
262 Font font
= view
.getFont();
263 FontMetrics metrics
= Toolkit
.getDefaultToolkit().getFontMetrics(font
);
264 float height
= metrics
.getHeight();
271 * @param view the glyph view to paint
272 * @param g the graphics context to use for painting
273 * @param a the allocation of the glyph view
274 * @param p0 the start position (in the model) from which to paint
275 * @param p1 the end position (in the model) to which to paint
277 public void paint(GlyphView view
, Graphics g
, Shape a
, int p0
,
280 int height
= (int) getHeight(view
);
281 Segment txt
= view
.getText(p0
, p1
);
282 Rectangle bounds
= a
.getBounds();
284 TabExpander tabEx
= null;
285 View parent
= view
.getParent();
286 if (parent
instanceof TabExpander
)
287 tabEx
= (TabExpander
) parent
;
289 // Fill the background of the text run.
290 Color background
= view
.getBackground();
291 g
.setColor(background
);
292 int width
= Utilities
.getTabbedTextWidth(txt
, g
.getFontMetrics(),
293 bounds
.x
, tabEx
, txt
.offset
);
294 g
.fillRect(bounds
.x
, bounds
.y
, width
, height
);
296 // Draw the actual text.
297 g
.setColor(view
.getForeground());
298 g
.setFont(view
.getFont());
299 if (view
.isSuperscript())
300 // TODO: Adjust font for superscripting.
301 Utilities
.drawTabbedText(txt
, bounds
.x
, bounds
.y
- height
/ 2, g
, tabEx
,
303 else if (view
.isSubscript())
304 // TODO: Adjust font for subscripting.
305 Utilities
.drawTabbedText(txt
, bounds
.x
, bounds
.y
+ height
/ 2, g
, tabEx
,
308 Utilities
.drawTabbedText(txt
, bounds
.x
, bounds
.y
, g
, tabEx
,
311 if (view
.isStikeThrough())
313 int strikeHeight
= (int) (getAscent(view
) / 2);
314 g
.drawLine(bounds
.x
, bounds
.y
+ strikeHeight
, bounds
.height
+ width
,
315 bounds
.y
+ strikeHeight
);
317 if (view
.isUnderline())
319 int lineHeight
= (int) getAscent(view
);
320 g
.drawLine(bounds
.x
, bounds
.y
+ lineHeight
, bounds
.height
+ width
,
321 bounds
.y
+ lineHeight
);
326 * Maps a position in the document into the coordinate space of the View.
327 * The output rectangle usually reflects the font height but has a width
330 * @param view the glyph view
331 * @param pos the position of the character in the model
332 * @param a the area that is occupied by the view
333 * @param b either {@link Position.Bias#Forward} or
334 * {@link Position.Bias#Backward} depending on the preferred
335 * direction bias. If <code>null</code> this defaults to
336 * <code>Position.Bias.Forward</code>
338 * @return a rectangle that gives the location of the document position
339 * inside the view coordinate space
341 * @throws BadLocationException if <code>pos</code> is invalid
342 * @throws IllegalArgumentException if b is not one of the above listed
345 public Shape
modelToView(GlyphView view
, int pos
, Position
.Bias b
,
347 throws BadLocationException
349 Element el
= view
.getElement();
350 Font font
= view
.getFont();
351 FontMetrics fm
= view
.getContainer().getFontMetrics(font
);
352 Segment txt
= view
.getText(el
.getStartOffset(), pos
);
353 int width
= fm
.charsWidth(txt
.array
, txt
.offset
, txt
.count
);
354 int height
= fm
.getHeight();
355 Rectangle bounds
= a
.getBounds();
356 Rectangle result
= new Rectangle(bounds
.x
+ width
, bounds
.y
,
357 bounds
.x
+ width
, height
);
362 * Determine the span of the glyphs from location <code>p0</code> to
363 * location <code>p1</code>. If <code>te</code> is not <code>null</code>,
364 * then TABs are expanded using this <code>TabExpander</code>.
365 * The parameter <code>x</code> is the location at which the view is
366 * located (this is important when using TAB expansion).
368 * @param view the glyph view
369 * @param p0 the starting location in the document model
370 * @param p1 the end location in the document model
371 * @param te the tab expander to use
372 * @param x the location at which the view is located
374 * @return the span of the glyphs from location <code>p0</code> to
375 * location <code>p1</code>, possibly using TAB expansion
377 public float getSpan(GlyphView view
, int p0
, int p1
,
378 TabExpander te
, float x
)
380 Element el
= view
.getElement();
381 Font font
= view
.getFont();
382 FontMetrics fm
= Toolkit
.getDefaultToolkit().getFontMetrics(font
);
383 Segment txt
= view
.getText(p0
, p1
);
384 int span
= Utilities
.getTabbedTextWidth(txt
, fm
, (int) x
, te
, p0
);
389 * Returns the ascent of the text run that is rendered by this
390 * <code>GlyphPainter</code>.
392 * @param v the glyph view
394 * @return the ascent of the text run that is rendered by this
395 * <code>GlyphPainter</code>
397 * @see FontMetrics#getAscent()
399 public float getAscent(GlyphView v
)
401 Font font
= v
.getFont();
402 FontMetrics fm
= v
.getContainer().getFontMetrics(font
);
403 return fm
.getAscent();
407 * Returns the descent of the text run that is rendered by this
408 * <code>GlyphPainter</code>.
410 * @param v the glyph view
412 * @return the descent of the text run that is rendered by this
413 * <code>GlyphPainter</code>
415 * @see FontMetrics#getDescent()
417 public float getDescent(GlyphView v
)
419 Font font
= v
.getFont();
420 FontMetrics fm
= v
.getContainer().getFontMetrics(font
);
421 return fm
.getDescent();
425 * Determines the model offset, so that the text between <code>p0</code>
426 * and this offset fits within the span starting at <code>x</code> with
427 * the length of <code>len</code>.
429 * @param v the glyph view
430 * @param p0 the starting offset in the model
431 * @param x the start location in the view
432 * @param len the length of the span in the view
434 public int getBoundedPosition(GlyphView v
, int p0
, float x
, float len
)
436 TabExpander te
= v
.getTabExpander();
437 Segment txt
= v
.getText(p0
, v
.getEndOffset());
438 Font font
= v
.getFont();
439 FontMetrics fm
= v
.getContainer().getFontMetrics(font
);
440 int pos
= Utilities
.getTabbedTextOffset(txt
, fm
, (int) x
,
441 (int) (x
+ len
), te
, p0
, false);
446 * Maps a visual position into a document location.
448 * @param v the glyph view
449 * @param x the X coordinate of the visual position
450 * @param y the Y coordinate of the visual position
451 * @param a the allocated region
452 * @param biasRet filled with the bias of the model location on method exit
454 * @return the model location that represents the specified view location
456 public int viewToModel(GlyphView v
, float x
, float y
, Shape a
,
459 Rectangle b
= a
.getBounds();
460 int pos
= getBoundedPosition(v
, v
.getStartOffset(), b
.x
, x
- b
.x
);
466 * The GlyphPainer used for painting the glyphs.
468 GlyphPainter glyphPainter
;
471 * The start offset within the document for this view.
476 * The end offset within the document for this view.
481 * Creates a new <code>GlyphView</code> for the given <code>Element</code>.
483 * @param element the element that is rendered by this GlyphView
485 public GlyphView(Element element
)
488 startOffset
= element
.getStartOffset();
489 endOffset
= element
.getEndOffset();
493 * Returns the <code>GlyphPainter</code> that is used by this
494 * <code>GlyphView</code>. If no <code>GlyphPainer</code> has been installed
495 * <code>null</code> is returned.
497 * @return the glyph painter that is used by this
498 * glyph view or <code>null</code> if no glyph painter has been
501 public GlyphPainter
getGlyphPainter()
507 * Sets the {@link GlyphPainter} to be used for this <code>GlyphView</code>.
509 * @param painter the glyph painter to be used for this glyph view
511 public void setGlyphPainter(GlyphPainter painter
)
513 glyphPainter
= painter
;
517 * Checks if a <code>GlyphPainer</code> is installed. If this is not the
518 * case, a default painter is installed.
520 protected void checkPainter()
522 if (glyphPainter
== null)
523 glyphPainter
= new DefaultGlyphPainter();
527 * Renders the <code>Element</code> that is associated with this
530 * @param g the <code>Graphics</code> context to render to
531 * @param a the allocated region for the <code>Element</code>
533 public void paint(Graphics g
, Shape a
)
535 Element el
= getElement();
537 getGlyphPainter().paint(this, g
, a
, el
.getStartOffset(),
543 * Returns the preferred span of the content managed by this
544 * <code>View</code> along the specified <code>axis</code>.
546 * @param axis the axis
548 * @return the preferred span of this <code>View</code>.
550 public float getPreferredSpan(int axis
)
554 GlyphPainter painter
= getGlyphPainter();
557 Element el
= getElement();
558 TabExpander tabEx
= null;
559 View parent
= getParent();
560 if (parent
instanceof TabExpander
)
561 tabEx
= (TabExpander
) parent
;
562 span
= painter
.getSpan(this, getStartOffset(), getEndOffset(),
566 span
= painter
.getHeight(this);
571 * Maps a position in the document into the coordinate space of the View.
572 * The output rectangle usually reflects the font height but has a width
575 * @param pos the position of the character in the model
576 * @param a the area that is occupied by the view
577 * @param b either {@link Position.Bias#Forward} or
578 * {@link Position.Bias#Backward} depending on the preferred
579 * direction bias. If <code>null</code> this defaults to
580 * <code>Position.Bias.Forward</code>
582 * @return a rectangle that gives the location of the document position
583 * inside the view coordinate space
585 * @throws BadLocationException if <code>pos</code> is invalid
586 * @throws IllegalArgumentException if b is not one of the above listed
589 public Shape
modelToView(int pos
, Shape a
, Position
.Bias b
)
590 throws BadLocationException
592 GlyphPainter p
= getGlyphPainter();
593 return p
.modelToView(this, pos
, b
, a
);
597 * Maps coordinates from the <code>View</code>'s space into a position
598 * in the document model.
600 * @param x the x coordinate in the view space
601 * @param y the y coordinate in the view space
602 * @param a the allocation of this <code>View</code>
603 * @param b the bias to use
605 * @return the position in the document that corresponds to the screen
606 * coordinates <code>x, y</code>
608 public int viewToModel(float x
, float y
, Shape a
, Position
.Bias
[] b
)
611 GlyphPainter painter
= getGlyphPainter();
612 return painter
.viewToModel(this, x
, y
, a
, b
);
616 * Return the {@link TabExpander} to use.
618 * @return the {@link TabExpander} to use
620 public TabExpander
getTabExpander()
622 TabExpander te
= null;
623 View parent
= getParent();
625 if (parent
instanceof TabExpander
)
626 te
= (TabExpander
) parent
;
632 * Returns the preferred span of this view for tab expansion.
634 * @param x the location of the view
635 * @param te the tab expander to use
637 * @return the preferred span of this view for tab expansion
639 public float getTabbedSpan(float x
, TabExpander te
)
641 Element el
= getElement();
642 return getGlyphPainter().getSpan(this, el
.getStartOffset(),
643 el
.getEndOffset(), te
, x
);
647 * Returns the span of a portion of the view. This is used in TAB expansion
648 * for fragments that don't contain TABs.
650 * @param p0 the start index
651 * @param p1 the end index
653 * @return the span of the specified portion of the view
655 public float getPartialSpan(int p0
, int p1
)
657 Element el
= getElement();
658 Document doc
= el
.getDocument();
659 Segment seg
= new Segment();
662 doc
.getText(p0
, p1
- p0
, seg
);
664 catch (BadLocationException ex
)
667 ae
= new AssertionError("BadLocationException must not be thrown "
672 FontMetrics fm
= null; // Fetch font metrics somewhere.
673 return Utilities
.getTabbedTextWidth(seg
, fm
, 0, null, p0
);
677 * Returns the start offset in the document model of the portion
678 * of text that this view is responsible for.
680 * @return the start offset in the document model of the portion
681 * of text that this view is responsible for
683 public int getStartOffset()
689 * Returns the end offset in the document model of the portion
690 * of text that this view is responsible for.
692 * @return the end offset in the document model of the portion
693 * of text that this view is responsible for
695 public int getEndOffset()
701 * Returns the text segment that this view is responsible for.
703 * @param p0 the start index in the document model
704 * @param p1 the end index in the document model
706 * @return the text segment that this view is responsible for
708 public Segment
getText(int p0
, int p1
)
710 Segment txt
= new Segment();
713 getDocument().getText(p0
, p1
- p0
, txt
);
715 catch (BadLocationException ex
)
718 ae
= new AssertionError("BadLocationException should not be "
719 + "thrown here. p0 = " + p0
+ ", p1 = " + p1
);
728 * Returns the font for the text run for which this <code>GlyphView</code>
731 * @return the font for the text run for which this <code>GlyphView</code>
734 public Font
getFont()
736 Element el
= getElement();
737 AttributeSet atts
= el
.getAttributes();
738 String family
= StyleConstants
.getFontFamily(atts
);
739 int size
= StyleConstants
.getFontSize(atts
);
740 int style
= Font
.PLAIN
;
741 if (StyleConstants
.isBold(atts
))
743 if (StyleConstants
.isItalic(atts
))
744 style
|= Font
.ITALIC
;
745 Font font
= new Font(family
, style
, size
);
750 * Returns the foreground color which should be used to paint the text.
751 * This is fetched from the associated element's text attributes using
752 * {@link StyleConstants#getForeground}.
754 * @return the foreground color which should be used to paint the text
756 public Color
getForeground()
758 Element el
= getElement();
759 AttributeSet atts
= el
.getAttributes();
760 return StyleConstants
.getForeground(atts
);
764 * Returns the background color which should be used to paint the text.
765 * This is fetched from the associated element's text attributes using
766 * {@link StyleConstants#getBackground}.
768 * @return the background color which should be used to paint the text
770 public Color
getBackground()
772 Element el
= getElement();
773 AttributeSet atts
= el
.getAttributes();
774 return StyleConstants
.getBackground(atts
);
778 * Determines whether the text should be rendered strike-through or not. This
779 * is determined using the method
780 * {@link StyleConstants#isStrikeThrough(AttributeSet)} on the element of
783 * @return whether the text should be rendered strike-through or not
785 public boolean isStikeThrough()
787 Element el
= getElement();
788 AttributeSet atts
= el
.getAttributes();
789 return StyleConstants
.isStrikeThrough(atts
);
793 * Determines whether the text should be rendered as subscript or not. This
794 * is determined using the method
795 * {@link StyleConstants#isSubscript(AttributeSet)} on the element of
798 * @return whether the text should be rendered as subscript or not
800 public boolean isSubscript()
802 Element el
= getElement();
803 AttributeSet atts
= el
.getAttributes();
804 return StyleConstants
.isSubscript(atts
);
808 * Determines whether the text should be rendered as superscript or not. This
809 * is determined using the method
810 * {@link StyleConstants#isSuperscript(AttributeSet)} on the element of
813 * @return whether the text should be rendered as superscript or not
815 public boolean isSuperscript()
817 Element el
= getElement();
818 AttributeSet atts
= el
.getAttributes();
819 return StyleConstants
.isSuperscript(atts
);
823 * Determines whether the text should be rendered as underlined or not. This
824 * is determined using the method
825 * {@link StyleConstants#isUnderline(AttributeSet)} on the element of
828 * @return whether the text should be rendered as underlined or not
830 public boolean isUnderline()
832 Element el
= getElement();
833 AttributeSet atts
= el
.getAttributes();
834 return StyleConstants
.isUnderline(atts
);
838 * Creates and returns a shallow clone of this GlyphView. This is used by
839 * the {@link #createFragment} and {@link #breakView} methods.
841 * @return a shallow clone of this GlyphView
843 protected final Object
clone()
847 return super.clone();
849 catch (CloneNotSupportedException ex
)
851 AssertionError err
= new AssertionError("CloneNotSupportedException "
852 + "must not be thrown here");
859 * Tries to break the view near the specified view span <code>len</code>.
860 * The glyph view can only be broken in the X direction. For Y direction it
863 * @param axis the axis for breaking, may be {@link View#X_AXIS} or
864 * {@link View#Y_AXIS}
865 * @param p0 the model location where the fragment should start
866 * @param pos the view position along the axis where the fragment starts
867 * @param len the desired length of the fragment view
869 * @return the fragment view, or <code>this</code> if breaking was not
872 public View
breakView(int axis
, int p0
, float pos
, float len
)
878 GlyphPainter painter
= getGlyphPainter();
879 int breakLocation
= painter
.getBoundedPosition(this, p0
, pos
, len
);
880 // Try to find a suitable line break.
881 BreakIterator lineBreaker
= BreakIterator
.getLineInstance();
882 Segment txt
= new Segment();
885 getDocument().getText(getStartOffset(), getEndOffset(), txt
);
887 catch (BadLocationException ex
)
889 AssertionError err
= new AssertionError("BadLocationException must not "
890 + "be thrown here.");
894 lineBreaker
.setText(txt
);
895 int goodBreakLocation
= lineBreaker
.previous();
896 if (goodBreakLocation
!= BreakIterator
.DONE
)
897 breakLocation
= goodBreakLocation
;
899 View brokenView
= createFragment(p0
, breakLocation
);
904 * Determines how well the specified view location is suitable for inserting
905 * a line break. If <code>axis</code> is <code>View.Y_AXIS</code>, then
906 * this method forwards to the superclass, if <code>axis</code> is
907 * <code>View.X_AXIS</code> then this method returns
908 * {@link View#ExcellentBreakWeight} if there is a suitable break location
909 * (usually whitespace) within the specified view span, or
910 * {@link View#GoodBreakWeight} if not.
912 * @param axis the axis along which the break weight is requested
913 * @param pos the starting view location
914 * @param len the length of the span at which the view should be broken
916 * @return the break weight
918 public int getBreakWeight(int axis
, float pos
, float len
)
922 weight
= super.getBreakWeight(axis
, pos
, len
);
925 // Determine the model locations at pos and pos + len.
926 int spanX
= (int) getPreferredSpan(X_AXIS
);
927 int spanY
= (int) getPreferredSpan(Y_AXIS
);
928 Rectangle dummyAlloc
= new Rectangle(0, 0, spanX
, spanY
);
929 Position
.Bias
[] biasRet
= new Position
.Bias
[1];
930 int offset1
= viewToModel(pos
, spanY
/ 2, dummyAlloc
, biasRet
);
931 int offset2
= viewToModel(pos
, spanY
/ 2, dummyAlloc
, biasRet
);
932 Segment txt
= getText(offset1
, offset2
);
933 BreakIterator lineBreaker
= BreakIterator
.getLineInstance();
934 lineBreaker
.setText(txt
);
935 int breakLoc
= lineBreaker
.previous();
936 if (breakLoc
== offset1
)
937 weight
= View
.BadBreakWeight
;
938 else if(breakLoc
== BreakIterator
.DONE
)
939 weight
= View
.GoodBreakWeight
;
941 weight
= View
.ExcellentBreakWeight
;
947 * Receives notification that some text attributes have changed within the
948 * text fragment that this view is responsible for. This calls
949 * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
950 * both width and height.
952 * @param e the document event describing the change; not used here
953 * @param a the view allocation on screen; not used here
954 * @param vf the view factory; not used here
956 public void changedUpdate(DocumentEvent e
, Shape a
, ViewFactory vf
)
958 getParent().preferenceChanged(this, true, true);
962 * Receives notification that some text has been inserted within the
963 * text fragment that this view is responsible for. This calls
964 * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
967 * @param e the document event describing the change; not used here
968 * @param a the view allocation on screen; not used here
969 * @param vf the view factory; not used here
971 public void insertUpdate(DocumentEvent e
, Shape a
, ViewFactory vf
)
973 getParent().preferenceChanged(this, true, false);
977 * Receives notification that some text has been removed within the
978 * text fragment that this view is responsible for. This calls
979 * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
982 * @param e the document event describing the change; not used here
983 * @param a the view allocation on screen; not used here
984 * @param vf the view factory; not used here
986 public void removeUpdate(DocumentEvent e
, Shape a
, ViewFactory vf
)
988 getParent().preferenceChanged(this, true, false);
992 * Creates a fragment view of this view that starts at <code>p0</code> and
993 * ends at <code>p1</code>.
995 * @param p0 the start location for the fragment view
996 * @param p1 the end location for the fragment view
998 * @return the fragment view
1000 public View
createFragment(int p0
, int p1
)
1002 GlyphView fragment
= (GlyphView
) clone();
1003 fragment
.startOffset
= p0
;
1004 fragment
.endOffset
= p1
;
1009 * Returns the alignment of this view along the specified axis. For the Y
1010 * axis this is <code>(height - descent) / height</code> for the used font,
1011 * so that it is aligned along the baseline.
1012 * For the X axis the superclass is called.
1014 public float getAlignment(int axis
)
1020 GlyphPainter painter
= getGlyphPainter();
1021 float height
= painter
.getHeight(this);
1022 float descent
= painter
.getDescent(this);
1023 align
= (height
- descent
) / height
;
1026 align
= super.getAlignment(axis
);
1032 * Returns the model location that should be used to place a caret when
1033 * moving the caret through the document.
1035 * @param pos the current model location
1036 * @param bias the bias for <code>p</code>
1037 * @param a the allocated region for the glyph view
1038 * @param direction the direction from the current position; Must be one of
1039 * {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
1040 * {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
1041 * @param biasRet filled with the bias of the resulting location when method
1044 * @return the location within the document that should be used to place the
1045 * caret when moving the caret around the document
1047 * @throws BadLocationException if <code>pos</code> is an invalid model
1049 * @throws IllegalArgumentException if <code>d</code> is invalid
1051 public int getNextVisualPositionFrom(int pos
, Position
.Bias bias
, Shape a
,
1052 int direction
, Position
.Bias
[] biasRet
)
1053 throws BadLocationException
1056 GlyphPainter painter
= getGlyphPainter();
1057 return painter
.getNextVisualPositionFrom(this, pos
, bias
, a
, direction
,