Merge from mainline
[official-gcc.git] / libjava / classpath / javax / swing / text / GlyphView.java
blob47deb50d03ab320d2aa01b2143bfa02c28de96e0
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)
9 any later version.
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
19 02110-1301 USA.
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.
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;
42 import java.awt.Font;
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;
54 /**
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
64 /**
65 * An abstract base implementation for a glyph painter for
66 * <code>GlyphView</code>.
68 public abstract static class GlyphPainter
70 /**
71 * Creates a new <code>GlyphPainer</code>.
73 public GlyphPainter()
75 // Nothing to do here.
78 /**
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);
87 /**
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);
96 /**
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,
114 float len);
117 * Paints the glyphs.
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,
126 int p1);
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
131 * of zero.
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
146 * valid values
148 public abstract Shape modelToView(GlyphView view, int pos, Position.Bias b,
149 Shape a)
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
198 * returns
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
204 * location
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
213 int result = pos;
214 switch (direction)
216 case SwingConstants.EAST:
217 result = pos + 1;
218 break;
219 case SwingConstants.WEST:
220 result = pos - 1;
221 break;
222 case SwingConstants.NORTH:
223 case SwingConstants.SOUTH:
224 default:
225 // This should be handled in enclosing view, since the glyph view
226 // does not layout vertically.
227 break;
229 return result;
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)
246 return this;
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();
265 return height;
269 * Paints the glyphs.
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,
278 int p1)
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,
302 txt.offset);
303 else if (view.isSubscript())
304 // TODO: Adjust font for subscripting.
305 Utilities.drawTabbedText(txt, bounds.x, bounds.y + height / 2, g, tabEx,
306 txt.offset);
307 else
308 Utilities.drawTabbedText(txt, bounds.x, bounds.y, g, tabEx,
309 txt.offset);
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
328 * of zero.
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
343 * valid values
345 public Shape modelToView(GlyphView view, int pos, Position.Bias b,
346 Shape a)
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);
358 return result;
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);
385 return span;
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);
442 return pos;
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,
457 Bias[] biasRet)
459 Rectangle b = a.getBounds();
460 int pos = getBoundedPosition(v, v.getStartOffset(), b.x, x - b.x);
461 return pos;
466 * The GlyphPainer used for painting the glyphs.
468 GlyphPainter glyphPainter;
471 * The start offset within the document for this view.
473 int startOffset;
476 * The end offset within the document for this view.
478 int endOffset;
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)
487 super(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
499 * installed
501 public GlyphPainter getGlyphPainter()
503 return glyphPainter;
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
528 * <code>View</code>.
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();
536 checkPainter();
537 getGlyphPainter().paint(this, g, a, el.getStartOffset(),
538 el.getEndOffset());
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)
552 float span = 0;
553 checkPainter();
554 GlyphPainter painter = getGlyphPainter();
555 if (axis == X_AXIS)
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(),
563 tabEx, 0.F);
565 else
566 span = painter.getHeight(this);
567 return span;
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
573 * of zero.
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
587 * valid values
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)
610 checkPainter();
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;
628 return te;
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)
666 AssertionError ae;
667 ae = new AssertionError("BadLocationException must not be thrown "
668 + "here");
669 ae.initCause(ex);
670 throw ae;
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()
685 return startOffset;
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()
697 return endOffset;
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)
717 AssertionError ae;
718 ae = new AssertionError("BadLocationException should not be "
719 + "thrown here. p0 = " + p0 + ", p1 = " + p1);
720 ae.initCause(ex);
721 throw ae;
724 return txt;
728 * Returns the font for the text run for which this <code>GlyphView</code>
729 * is responsible.
731 * @return the font for the text run for which this <code>GlyphView</code>
732 * is responsible
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))
742 style |= Font.BOLD;
743 if (StyleConstants.isItalic(atts))
744 style |= Font.ITALIC;
745 Font font = new Font(family, style, size);
746 return font;
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
781 * this view.
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
796 * this view.
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
811 * this view.
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
826 * this view.
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");
853 err.initCause(ex);
854 throw err;
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
861 * returns itself.
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
870 * possible
872 public View breakView(int axis, int p0, float pos, float len)
874 if (axis == Y_AXIS)
875 return this;
877 checkPainter();
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.");
891 err.initCause(ex);
892 throw err;
894 lineBreaker.setText(txt);
895 int goodBreakLocation = lineBreaker.previous();
896 if (goodBreakLocation != BreakIterator.DONE)
897 breakLocation = goodBreakLocation;
899 View brokenView = createFragment(p0, breakLocation);
900 return brokenView;
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)
920 int weight;
921 if (axis == Y_AXIS)
922 weight = super.getBreakWeight(axis, pos, len);
923 else
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;
940 else
941 weight = View.ExcellentBreakWeight;
943 return weight;
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
965 * width.
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
980 * width.
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;
1005 return fragment;
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)
1016 float align;
1017 if (axis == Y_AXIS)
1019 checkPainter();
1020 GlyphPainter painter = getGlyphPainter();
1021 float height = painter.getHeight(this);
1022 float descent = painter.getDescent(this);
1023 align = (height - descent) / height;
1025 else
1026 align = super.getAlignment(axis);
1028 return align;
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
1042 * returns
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
1048 * location
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
1055 checkPainter();
1056 GlyphPainter painter = getGlyphPainter();
1057 return painter.getNextVisualPositionFrom(this, pos, bias, a, direction,
1058 biasRet);