aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing/text/GlyphView.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/javax/swing/text/GlyphView.java')
-rw-r--r--libjava/classpath/javax/swing/text/GlyphView.java1333
1 files changed, 0 insertions, 1333 deletions
diff --git a/libjava/classpath/javax/swing/text/GlyphView.java b/libjava/classpath/javax/swing/text/GlyphView.java
deleted file mode 100644
index 3f4ccf9..0000000
--- a/libjava/classpath/javax/swing/text/GlyphView.java
+++ /dev/null
@@ -1,1333 +0,0 @@
-/* GlyphView.java -- A view to render styled text
- Copyright (C) 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package javax.swing.text;
-
-import gnu.classpath.SystemProperties;
-
-import java.awt.Color;
-import java.awt.Container;
-import java.awt.Font;
-import java.awt.FontMetrics;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.Shape;
-import java.awt.Toolkit;
-import java.awt.font.FontRenderContext;
-import java.awt.font.TextHitInfo;
-import java.awt.font.TextLayout;
-import java.awt.geom.Rectangle2D;
-
-import javax.swing.SwingConstants;
-import javax.swing.event.DocumentEvent;
-import javax.swing.text.Position.Bias;
-
-/**
- * Renders a run of styled text. This {@link View} subclass paints the
- * characters of the <code>Element</code> it is responsible for using
- * the style information from that <code>Element</code>.
- *
- * @author Roman Kennke (roman@kennke.org)
- */
-public class GlyphView extends View implements TabableView, Cloneable
-{
-
- /**
- * An abstract base implementation for a glyph painter for
- * <code>GlyphView</code>.
- */
- public abstract static class GlyphPainter
- {
- /**
- * Creates a new <code>GlyphPainer</code>.
- */
- public GlyphPainter()
- {
- // Nothing to do here.
- }
-
- /**
- * Returns the ascent of the font that is used by this glyph painter.
- *
- * @param v the glyph view
- *
- * @return the ascent of the font that is used by this glyph painter
- */
- public abstract float getAscent(GlyphView v);
-
- /**
- * Returns the descent of the font that is used by this glyph painter.
- *
- * @param v the glyph view
- *
- * @return the descent of the font that is used by this glyph painter
- */
- public abstract float getDescent(GlyphView v);
-
- /**
- * Returns the full height of the rendered text.
- *
- * @return the full height of the rendered text
- */
- public abstract float getHeight(GlyphView view);
-
- /**
- * Determines the model offset, so that the text between <code>p0</code>
- * and this offset fits within the span starting at <code>x</code> with
- * the length of <code>len</code>.
- *
- * @param v the glyph view
- * @param p0 the starting offset in the model
- * @param x the start location in the view
- * @param len the length of the span in the view
- */
- public abstract int getBoundedPosition(GlyphView v, int p0, float x,
- float len);
-
- /**
- * Paints the glyphs.
- *
- * @param view the glyph view to paint
- * @param g the graphics context to use for painting
- * @param a the allocation of the glyph view
- * @param p0 the start position (in the model) from which to paint
- * @param p1 the end position (in the model) to which to paint
- */
- public abstract void paint(GlyphView view, Graphics g, Shape a, int p0,
- int p1);
-
- /**
- * Maps a position in the document into the coordinate space of the View.
- * The output rectangle usually reflects the font height but has a width
- * of zero.
- *
- * @param view the glyph view
- * @param pos the position of the character in the model
- * @param a the area that is occupied by the view
- * @param b either {@link Position.Bias#Forward} or
- * {@link Position.Bias#Backward} depending on the preferred
- * direction bias. If <code>null</code> this defaults to
- * <code>Position.Bias.Forward</code>
- *
- * @return a rectangle that gives the location of the document position
- * inside the view coordinate space
- *
- * @throws BadLocationException if <code>pos</code> is invalid
- * @throws IllegalArgumentException if b is not one of the above listed
- * valid values
- */
- public abstract Shape modelToView(GlyphView view, int pos, Position.Bias b,
- Shape a)
- throws BadLocationException;
-
- /**
- * Maps a visual position into a document location.
- *
- * @param v the glyph view
- * @param x the X coordinate of the visual position
- * @param y the Y coordinate of the visual position
- * @param a the allocated region
- * @param biasRet filled with the bias of the model location on method exit
- *
- * @return the model location that represents the specified view location
- */
- public abstract int viewToModel(GlyphView v, float x, float y, Shape a,
- Position.Bias[] biasRet);
-
- /**
- * Determine the span of the glyphs from location <code>p0</code> to
- * location <code>p1</code>. If <code>te</code> is not <code>null</code>,
- * then TABs are expanded using this <code>TabExpander</code>.
- * The parameter <code>x</code> is the location at which the view is
- * located (this is important when using TAB expansion).
- *
- * @param view the glyph view
- * @param p0 the starting location in the document model
- * @param p1 the end location in the document model
- * @param te the tab expander to use
- * @param x the location at which the view is located
- *
- * @return the span of the glyphs from location <code>p0</code> to
- * location <code>p1</code>, possibly using TAB expansion
- */
- public abstract float getSpan(GlyphView view, int p0, int p1,
- TabExpander te, float x);
-
-
- /**
- * Returns the model location that should be used to place a caret when
- * moving the caret through the document.
- *
- * @param v the glyph view
- * @param pos the current model location
- * @param b the bias for <code>p</code>
- * @param a the allocated region for the glyph view
- * @param direction the direction from the current position; Must be one of
- * {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
- * {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
- * @param biasRet filled with the bias of the resulting location when method
- * returns
- *
- * @return the location within the document that should be used to place the
- * caret when moving the caret around the document
- *
- * @throws BadLocationException if <code>pos</code> is an invalid model
- * location
- * @throws IllegalArgumentException if <code>d</code> is invalid
- */
- public int getNextVisualPositionFrom(GlyphView v, int pos, Position.Bias b,
- Shape a, int direction,
- Position.Bias[] biasRet)
- throws BadLocationException
-
- {
- int result = pos;
- switch (direction)
- {
- case SwingConstants.EAST:
- result = pos + 1;
- break;
- case SwingConstants.WEST:
- result = pos - 1;
- break;
- case SwingConstants.NORTH:
- case SwingConstants.SOUTH:
- default:
- // This should be handled in enclosing view, since the glyph view
- // does not layout vertically.
- break;
- }
- return result;
- }
-
- /**
- * Returns a painter that can be used to render the specified glyph view.
- * If this glyph painter is stateful, then it should return a new instance.
- * However, if this painter is stateless it should return itself. The
- * default behaviour is to return itself.
- *
- * @param v the glyph view for which to create a painter
- * @param p0 the start offset of the rendered area
- * @param p1 the end offset of the rendered area
- *
- * @return a painter that can be used to render the specified glyph view
- */
- public GlyphPainter getPainter(GlyphView v, int p0, int p1)
- {
- return this;
- }
- }
-
- /**
- * A GlyphPainter implementation based on TextLayout. This should give
- * better performance in Java2D environments.
- */
- private static class J2DGlyphPainter
- extends GlyphPainter
- {
-
- /**
- * The text layout.
- */
- TextLayout textLayout;
-
- /**
- * Creates a new J2DGlyphPainter.
- *
- * @param str the string
- * @param font the font
- * @param frc the font render context
- */
- J2DGlyphPainter(String str, Font font, FontRenderContext frc)
- {
- textLayout = new TextLayout(str, font, frc);
- }
-
- /**
- * Returns null so that GlyphView.checkPainter() creates a new instance.
- */
- public GlyphPainter getPainter(GlyphView v, int p0, int p1)
- {
- return null;
- }
-
- /**
- * Delegates to the text layout.
- */
- public float getAscent(GlyphView v)
- {
- return textLayout.getAscent();
- }
-
- /**
- * Delegates to the text layout.
- */
- public int getBoundedPosition(GlyphView v, int p0, float x, float len)
- {
- int pos;
- TextHitInfo hit = textLayout.hitTestChar(len, 0);
- if (hit.getCharIndex() == -1 && ! textLayout.isLeftToRight())
- pos = v.getEndOffset();
- else
- {
- pos = hit.isLeadingEdge() ? hit.getInsertionIndex()
- : hit.getInsertionIndex() - 1;
- pos += v.getStartOffset();
- }
- return pos;
- }
-
- /**
- * Delegates to the text layout.
- */
- public float getDescent(GlyphView v)
- {
- return textLayout.getDescent();
- }
-
- /**
- * Delegates to the text layout.
- */
- public float getHeight(GlyphView view)
- {
- return textLayout.getAscent() + textLayout.getDescent()
- + textLayout.getLeading();
- }
-
- /**
- * Delegates to the text layout.
- */
- public float getSpan(GlyphView v, int p0, int p1, TabExpander te, float x)
- {
- float span;
- if (p0 == v.getStartOffset() && p1 == v.getEndOffset())
- span = textLayout.getAdvance();
- else
- {
- int start = v.getStartOffset();
- int i0 = p0 - start;
- int i1 = p1 - start;
- TextHitInfo hit0 = TextHitInfo.afterOffset(i0);
- TextHitInfo hit1 = TextHitInfo.afterOffset(i1);
- float x0 = textLayout.getCaretInfo(hit0)[0];
- float x1 = textLayout.getCaretInfo(hit1)[0];
- span = Math.abs(x1 - x0);
- }
- return span;
- }
-
- /**
- * Delegates to the text layout.
- */
- public Shape modelToView(GlyphView v, int pos, Bias b, Shape a)
- throws BadLocationException
- {
- int offs = pos - v.getStartOffset();
- // Create copy here to protect original shape.
- Rectangle2D bounds = a.getBounds2D();
- TextHitInfo hit =
- b == Position.Bias.Forward ? TextHitInfo.afterOffset(offs)
- : TextHitInfo.beforeOffset(offs);
- float[] loc = textLayout.getCaretInfo(hit);
- bounds.setRect(bounds.getX() + loc[0], bounds.getY(), 1,
- bounds.getHeight());
- return bounds;
- }
-
- /**
- * Delegates to the text layout.
- */
- public void paint(GlyphView view, Graphics g, Shape a, int p0, int p1)
- {
- // Can't paint this with plain graphics.
- if (g instanceof Graphics2D)
- {
- Graphics2D g2d = (Graphics2D) g;
- Rectangle2D b = a instanceof Rectangle2D ? (Rectangle2D) a
- : a.getBounds2D();
- float x = (float) b.getX();
- float y = (float) b.getY() + textLayout.getAscent()
- + textLayout.getLeading();
- // TODO: Try if clipping makes things faster for narrow views.
- textLayout.draw(g2d, x, y);
- }
- }
-
- /**
- * Delegates to the text layout.
- */
- public int viewToModel(GlyphView v, float x, float y, Shape a,
- Bias[] biasRet)
- {
- Rectangle2D bounds = a instanceof Rectangle2D ? (Rectangle2D) a
- : a.getBounds2D();
- TextHitInfo hit = textLayout.hitTestChar(x - (float) bounds.getX(), 0);
- int pos = hit.getInsertionIndex();
- biasRet[0] = hit.isLeadingEdge() ? Position.Bias.Forward
- : Position.Bias.Backward;
- return pos + v.getStartOffset();
- }
-
- }
-
- /**
- * The default <code>GlyphPainter</code> used in <code>GlyphView</code>.
- */
- static class DefaultGlyphPainter extends GlyphPainter
- {
- FontMetrics fontMetrics;
-
- /**
- * Returns the full height of the rendered text.
- *
- * @return the full height of the rendered text
- */
- public float getHeight(GlyphView view)
- {
- updateFontMetrics(view);
- float height = fontMetrics.getHeight();
- return height;
- }
-
- /**
- * Paints the glyphs.
- *
- * @param view the glyph view to paint
- * @param g the graphics context to use for painting
- * @param a the allocation of the glyph view
- * @param p0 the start position (in the model) from which to paint
- * @param p1 the end position (in the model) to which to paint
- */
- public void paint(GlyphView view, Graphics g, Shape a, int p0,
- int p1)
- {
- updateFontMetrics(view);
- Rectangle r = a instanceof Rectangle ? (Rectangle) a : a.getBounds();
- TabExpander tabEx = view.getTabExpander();
- Segment txt = view.getText(p0, p1);
-
- // Find out the X location at which we have to paint.
- int x = r.x;
- int p = view.getStartOffset();
- if (p != p0)
- {
- int width = Utilities.getTabbedTextWidth(txt, fontMetrics,x, tabEx,
- p);
- x += width;
- }
- // Find out Y location.
- int y = r.y + fontMetrics.getHeight() - fontMetrics.getDescent();
-
- // Render the thing.
- g.setFont(fontMetrics.getFont());
- Utilities.drawTabbedText(txt, x, y, g, tabEx, p0);
-
- }
-
- /**
- * Maps a position in the document into the coordinate space of the View.
- * The output rectangle usually reflects the font height but has a width
- * of zero.
- *
- * @param view the glyph view
- * @param pos the position of the character in the model
- * @param a the area that is occupied by the view
- * @param b either {@link Position.Bias#Forward} or
- * {@link Position.Bias#Backward} depending on the preferred
- * direction bias. If <code>null</code> this defaults to
- * <code>Position.Bias.Forward</code>
- *
- * @return a rectangle that gives the location of the document position
- * inside the view coordinate space
- *
- * @throws BadLocationException if <code>pos</code> is invalid
- * @throws IllegalArgumentException if b is not one of the above listed
- * valid values
- */
- public Shape modelToView(GlyphView view, int pos, Position.Bias b,
- Shape a)
- throws BadLocationException
- {
- updateFontMetrics(view);
- Element el = view.getElement();
- Segment txt = view.getText(el.getStartOffset(), pos);
- Rectangle bounds = a instanceof Rectangle ? (Rectangle) a
- : a.getBounds();
- TabExpander expander = view.getTabExpander();
- int width = Utilities.getTabbedTextWidth(txt, fontMetrics, bounds.x,
- expander,
- view.getStartOffset());
- int height = fontMetrics.getHeight();
- Rectangle result = new Rectangle(bounds.x + width, bounds.y,
- 0, height);
- return result;
- }
-
- /**
- * Determine the span of the glyphs from location <code>p0</code> to
- * location <code>p1</code>. If <code>te</code> is not <code>null</code>,
- * then TABs are expanded using this <code>TabExpander</code>.
- * The parameter <code>x</code> is the location at which the view is
- * located (this is important when using TAB expansion).
- *
- * @param view the glyph view
- * @param p0 the starting location in the document model
- * @param p1 the end location in the document model
- * @param te the tab expander to use
- * @param x the location at which the view is located
- *
- * @return the span of the glyphs from location <code>p0</code> to
- * location <code>p1</code>, possibly using TAB expansion
- */
- public float getSpan(GlyphView view, int p0, int p1,
- TabExpander te, float x)
- {
- updateFontMetrics(view);
- Segment txt = view.getText(p0, p1);
- int span = Utilities.getTabbedTextWidth(txt, fontMetrics, (int) x, te,
- p0);
- return span;
- }
-
- /**
- * Returns the ascent of the text run that is rendered by this
- * <code>GlyphPainter</code>.
- *
- * @param v the glyph view
- *
- * @return the ascent of the text run that is rendered by this
- * <code>GlyphPainter</code>
- *
- * @see FontMetrics#getAscent()
- */
- public float getAscent(GlyphView v)
- {
- updateFontMetrics(v);
- return fontMetrics.getAscent();
- }
-
- /**
- * Returns the descent of the text run that is rendered by this
- * <code>GlyphPainter</code>.
- *
- * @param v the glyph view
- *
- * @return the descent of the text run that is rendered by this
- * <code>GlyphPainter</code>
- *
- * @see FontMetrics#getDescent()
- */
- public float getDescent(GlyphView v)
- {
- updateFontMetrics(v);
- return fontMetrics.getDescent();
- }
-
- /**
- * Determines the model offset, so that the text between <code>p0</code>
- * and this offset fits within the span starting at <code>x</code> with
- * the length of <code>len</code>.
- *
- * @param v the glyph view
- * @param p0 the starting offset in the model
- * @param x the start location in the view
- * @param len the length of the span in the view
- */
- public int getBoundedPosition(GlyphView v, int p0, float x, float len)
- {
- updateFontMetrics(v);
- TabExpander te = v.getTabExpander();
- Segment txt = v.getText(p0, v.getEndOffset());
- int pos = Utilities.getTabbedTextOffset(txt, fontMetrics, (int) x,
- (int) (x + len), te, p0, false);
- return pos + p0;
- }
-
- /**
- * Maps a visual position into a document location.
- *
- * @param v the glyph view
- * @param x the X coordinate of the visual position
- * @param y the Y coordinate of the visual position
- * @param a the allocated region
- * @param biasRet filled with the bias of the model location on method exit
- *
- * @return the model location that represents the specified view location
- */
- public int viewToModel(GlyphView v, float x, float y, Shape a,
- Bias[] biasRet)
- {
- Rectangle r = a instanceof Rectangle ? (Rectangle) a : a.getBounds();
- int p0 = v.getStartOffset();
- int p1 = v.getEndOffset();
- TabExpander te = v.getTabExpander();
- Segment s = v.getText(p0, p1);
- int offset = Utilities.getTabbedTextOffset(s, fontMetrics, r.x, (int) x,
- te, p0);
- int ret = p0 + offset;
- if (ret == p1)
- ret--;
- biasRet[0] = Position.Bias.Forward;
- return ret;
- }
-
- private void updateFontMetrics(GlyphView v)
- {
- Font font = v.getFont();
- if (fontMetrics == null || ! font.equals(fontMetrics.getFont()))
- {
- Container c = v.getContainer();
- FontMetrics fm;
- if (c != null)
- fm = c.getFontMetrics(font);
- else
- fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
- fontMetrics = fm;
- }
- }
- }
-
- /**
- * The GlyphPainer used for painting the glyphs.
- */
- GlyphPainter glyphPainter;
-
- /**
- * The start offset within the document for this view.
- */
- private int offset;
-
- /**
- * The end offset within the document for this view.
- */
- private int length;
-
- /**
- * The x location against which the tab expansion is done.
- */
- private float tabX;
-
- /**
- * The tab expander that is used in this view.
- */
- private TabExpander tabExpander;
-
- /**
- * Creates a new <code>GlyphView</code> for the given <code>Element</code>.
- *
- * @param element the element that is rendered by this GlyphView
- */
- public GlyphView(Element element)
- {
- super(element);
- offset = 0;
- length = 0;
- }
-
- /**
- * Returns the <code>GlyphPainter</code> that is used by this
- * <code>GlyphView</code>. If no <code>GlyphPainer</code> has been installed
- * <code>null</code> is returned.
- *
- * @return the glyph painter that is used by this
- * glyph view or <code>null</code> if no glyph painter has been
- * installed
- */
- public GlyphPainter getGlyphPainter()
- {
- return glyphPainter;
- }
-
- /**
- * Sets the {@link GlyphPainter} to be used for this <code>GlyphView</code>.
- *
- * @param painter the glyph painter to be used for this glyph view
- */
- public void setGlyphPainter(GlyphPainter painter)
- {
- glyphPainter = painter;
- }
-
- /**
- * Checks if a <code>GlyphPainer</code> is installed. If this is not the
- * case, a default painter is installed.
- */
- protected void checkPainter()
- {
- if (glyphPainter == null)
- {
- if ("true".equals(
- SystemProperties.getProperty("gnu.javax.swing.noGraphics2D")))
- {
- glyphPainter = new DefaultGlyphPainter();
- }
- else
- {
- Segment s = getText(getStartOffset(), getEndOffset());
- glyphPainter = new J2DGlyphPainter(s.toString(), getFont(),
- new FontRenderContext(null,
- false,
- false));
- }
- }
- }
-
- /**
- * Renders the <code>Element</code> that is associated with this
- * <code>View</code>.
- *
- * @param g the <code>Graphics</code> context to render to
- * @param a the allocated region for the <code>Element</code>
- */
- public void paint(Graphics g, Shape a)
- {
- checkPainter();
- int p0 = getStartOffset();
- int p1 = getEndOffset();
-
- Rectangle r = a instanceof Rectangle ? (Rectangle) a : a.getBounds();
- Container c = getContainer();
-
- Color fg = getForeground();
- JTextComponent tc = null;
- if (c instanceof JTextComponent)
- {
- tc = (JTextComponent) c;
- if (! tc.isEnabled())
- fg = tc.getDisabledTextColor();
- }
- Color bg = getBackground();
- if (bg != null)
- {
- g.setColor(bg);
- g.fillRect(r.x, r.y, r.width, r.height);
- }
-
-
- // Paint layered highlights if there are any.
- if (tc != null)
- {
- Highlighter h = tc.getHighlighter();
- if (h instanceof LayeredHighlighter)
- {
- LayeredHighlighter lh = (LayeredHighlighter) h;
- lh.paintLayeredHighlights(g, p0, p1, a, tc, this);
- }
- }
-
- g.setColor(fg);
- glyphPainter.paint(this, g, a, p0, p1);
- boolean underline = isUnderline();
- boolean striked = isStrikeThrough();
- if (underline || striked)
- {
- View parent = getParent();
- // X coordinate.
- if (parent != null && parent.getEndOffset() == p1)
- {
- // Strip whitespace.
- Segment s = getText(p0, p1);
- while (s.count > 0 && Character.isWhitespace(s.array[s.count - 1]))
- {
- p1--;
- s.count--;
- }
- }
- int x0 = r.x;
- int p = getStartOffset();
- TabExpander tabEx = getTabExpander();
- if (p != p0)
- x0 += (int) glyphPainter.getSpan(this, p, p0, tabEx, x0);
- int x1 = x0 + (int) glyphPainter.getSpan(this, p0, p1, tabEx, x0);
- // Y coordinate.
- int y = r.y + r.height - (int) glyphPainter.getDescent(this);
- if (underline)
- {
- int yTmp = y;
- yTmp += 1;
- g.drawLine(x0, yTmp, x1, yTmp);
- }
- if (striked)
- {
- int yTmp = y;
- yTmp -= (int) glyphPainter.getAscent(this);
- g.drawLine(x0, yTmp, x1, yTmp);
- }
- }
- }
-
-
- /**
- * Returns the preferred span of the content managed by this
- * <code>View</code> along the specified <code>axis</code>.
- *
- * @param axis the axis
- *
- * @return the preferred span of this <code>View</code>.
- */
- public float getPreferredSpan(int axis)
- {
- float span = 0;
- checkPainter();
- GlyphPainter painter = getGlyphPainter();
- switch (axis)
- {
- case X_AXIS:
- TabExpander tabEx = null;
- View parent = getParent();
- if (parent instanceof TabExpander)
- tabEx = (TabExpander) parent;
- span = painter.getSpan(this, getStartOffset(), getEndOffset(),
- tabEx, 0.F);
- break;
- case Y_AXIS:
- span = painter.getHeight(this);
- if (isSuperscript())
- span += span / 3;
- break;
- default:
- throw new IllegalArgumentException("Illegal axis");
- }
- return span;
- }
-
- /**
- * Maps a position in the document into the coordinate space of the View.
- * The output rectangle usually reflects the font height but has a width
- * of zero.
- *
- * @param pos the position of the character in the model
- * @param a the area that is occupied by the view
- * @param b either {@link Position.Bias#Forward} or
- * {@link Position.Bias#Backward} depending on the preferred
- * direction bias. If <code>null</code> this defaults to
- * <code>Position.Bias.Forward</code>
- *
- * @return a rectangle that gives the location of the document position
- * inside the view coordinate space
- *
- * @throws BadLocationException if <code>pos</code> is invalid
- * @throws IllegalArgumentException if b is not one of the above listed
- * valid values
- */
- public Shape modelToView(int pos, Shape a, Position.Bias b)
- throws BadLocationException
- {
- GlyphPainter p = getGlyphPainter();
- return p.modelToView(this, pos, b, a);
- }
-
- /**
- * Maps coordinates from the <code>View</code>'s space into a position
- * in the document model.
- *
- * @param x the x coordinate in the view space
- * @param y the y coordinate in the view space
- * @param a the allocation of this <code>View</code>
- * @param b the bias to use
- *
- * @return the position in the document that corresponds to the screen
- * coordinates <code>x, y</code>
- */
- public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
- {
- checkPainter();
- GlyphPainter painter = getGlyphPainter();
- return painter.viewToModel(this, x, y, a, b);
- }
-
- /**
- * Return the {@link TabExpander} to use.
- *
- * @return the {@link TabExpander} to use
- */
- public TabExpander getTabExpander()
- {
- return tabExpander;
- }
-
- /**
- * Returns the preferred span of this view for tab expansion.
- *
- * @param x the location of the view
- * @param te the tab expander to use
- *
- * @return the preferred span of this view for tab expansion
- */
- public float getTabbedSpan(float x, TabExpander te)
- {
- checkPainter();
- TabExpander old = tabExpander;
- tabExpander = te;
- if (tabExpander != old)
- {
- // Changing the tab expander will lead to a relayout in the X_AXIS.
- preferenceChanged(null, true, false);
- }
- tabX = x;
- return getGlyphPainter().getSpan(this, getStartOffset(),
- getEndOffset(), tabExpander, x);
- }
-
- /**
- * Returns the span of a portion of the view. This is used in TAB expansion
- * for fragments that don't contain TABs.
- *
- * @param p0 the start index
- * @param p1 the end index
- *
- * @return the span of the specified portion of the view
- */
- public float getPartialSpan(int p0, int p1)
- {
- checkPainter();
- return glyphPainter.getSpan(this, p0, p1, tabExpander, tabX);
- }
-
- /**
- * Returns the start offset in the document model of the portion
- * of text that this view is responsible for.
- *
- * @return the start offset in the document model of the portion
- * of text that this view is responsible for
- */
- public int getStartOffset()
- {
- Element el = getElement();
- int offs = el.getStartOffset();
- if (length > 0)
- offs += offset;
- return offs;
- }
-
- /**
- * Returns the end offset in the document model of the portion
- * of text that this view is responsible for.
- *
- * @return the end offset in the document model of the portion
- * of text that this view is responsible for
- */
- public int getEndOffset()
- {
- Element el = getElement();
- int offs;
- if (length > 0)
- offs = el.getStartOffset() + offset + length;
- else
- offs = el.getEndOffset();
- return offs;
- }
-
- private Segment cached = new Segment();
-
- /**
- * Returns the text segment that this view is responsible for.
- *
- * @param p0 the start index in the document model
- * @param p1 the end index in the document model
- *
- * @return the text segment that this view is responsible for
- */
- public Segment getText(int p0, int p1)
- {
- try
- {
- getDocument().getText(p0, p1 - p0, cached);
- }
- catch (BadLocationException ex)
- {
- AssertionError ae;
- ae = new AssertionError("BadLocationException should not be "
- + "thrown here. p0 = " + p0 + ", p1 = " + p1);
- ae.initCause(ex);
- throw ae;
- }
-
- return cached;
- }
-
- /**
- * Returns the font for the text run for which this <code>GlyphView</code>
- * is responsible.
- *
- * @return the font for the text run for which this <code>GlyphView</code>
- * is responsible
- */
- public Font getFont()
- {
- Document doc = getDocument();
- Font font = null;
- if (doc instanceof StyledDocument)
- {
- StyledDocument styledDoc = (StyledDocument) doc;
- font = styledDoc.getFont(getAttributes());
- }
- else
- {
- Container c = getContainer();
- if (c != null)
- font = c.getFont();
- }
- return font;
- }
-
- /**
- * Returns the foreground color which should be used to paint the text.
- * This is fetched from the associated element's text attributes using
- * {@link StyleConstants#getForeground}.
- *
- * @return the foreground color which should be used to paint the text
- */
- public Color getForeground()
- {
- Element el = getElement();
- AttributeSet atts = el.getAttributes();
- return StyleConstants.getForeground(atts);
- }
-
- /**
- * Returns the background color which should be used to paint the text.
- * This is fetched from the associated element's text attributes using
- * {@link StyleConstants#getBackground}.
- *
- * @return the background color which should be used to paint the text
- */
- public Color getBackground()
- {
- Element el = getElement();
- AttributeSet atts = el.getAttributes();
- // We cannot use StyleConstants.getBackground() here, because that returns
- // BLACK as default (when background == null). What we need is the
- // background setting of the text component instead, which is what we get
- // when background == null anyway.
- return (Color) atts.getAttribute(StyleConstants.Background);
- }
-
- /**
- * Determines whether the text should be rendered strike-through or not. This
- * is determined using the method
- * {@link StyleConstants#isStrikeThrough(AttributeSet)} on the element of
- * this view.
- *
- * @return whether the text should be rendered strike-through or not
- */
- public boolean isStrikeThrough()
- {
- Element el = getElement();
- AttributeSet atts = el.getAttributes();
- return StyleConstants.isStrikeThrough(atts);
- }
-
- /**
- * Determines whether the text should be rendered as subscript or not. This
- * is determined using the method
- * {@link StyleConstants#isSubscript(AttributeSet)} on the element of
- * this view.
- *
- * @return whether the text should be rendered as subscript or not
- */
- public boolean isSubscript()
- {
- Element el = getElement();
- AttributeSet atts = el.getAttributes();
- return StyleConstants.isSubscript(atts);
- }
-
- /**
- * Determines whether the text should be rendered as superscript or not. This
- * is determined using the method
- * {@link StyleConstants#isSuperscript(AttributeSet)} on the element of
- * this view.
- *
- * @return whether the text should be rendered as superscript or not
- */
- public boolean isSuperscript()
- {
- Element el = getElement();
- AttributeSet atts = el.getAttributes();
- return StyleConstants.isSuperscript(atts);
- }
-
- /**
- * Determines whether the text should be rendered as underlined or not. This
- * is determined using the method
- * {@link StyleConstants#isUnderline(AttributeSet)} on the element of
- * this view.
- *
- * @return whether the text should be rendered as underlined or not
- */
- public boolean isUnderline()
- {
- Element el = getElement();
- AttributeSet atts = el.getAttributes();
- return StyleConstants.isUnderline(atts);
- }
-
- /**
- * Creates and returns a shallow clone of this GlyphView. This is used by
- * the {@link #createFragment} and {@link #breakView} methods.
- *
- * @return a shallow clone of this GlyphView
- */
- protected final Object clone()
- {
- try
- {
- return super.clone();
- }
- catch (CloneNotSupportedException ex)
- {
- AssertionError err = new AssertionError("CloneNotSupportedException "
- + "must not be thrown here");
- err.initCause(ex);
- throw err;
- }
- }
-
- /**
- * Tries to break the view near the specified view span <code>len</code>.
- * The glyph view can only be broken in the X direction. For Y direction it
- * returns itself.
- *
- * @param axis the axis for breaking, may be {@link View#X_AXIS} or
- * {@link View#Y_AXIS}
- * @param p0 the model location where the fragment should start
- * @param pos the view position along the axis where the fragment starts
- * @param len the desired length of the fragment view
- *
- * @return the fragment view, or <code>this</code> if breaking was not
- * possible
- */
- public View breakView(int axis, int p0, float pos, float len)
- {
- View brokenView = this;
- if (axis == X_AXIS)
- {
- checkPainter();
- int end = glyphPainter.getBoundedPosition(this, p0, pos, len);
- int breakLoc = getBreakLocation(p0, end);
- if (breakLoc != -1)
- end = breakLoc;
- if (p0 != getStartOffset() || end != getEndOffset())
- {
- brokenView = createFragment(p0, end);
- if (brokenView instanceof GlyphView)
- ((GlyphView) brokenView).tabX = pos;
- }
- }
- return brokenView;
- }
-
- /**
- * Determines how well the specified view location is suitable for inserting
- * a line break. If <code>axis</code> is <code>View.Y_AXIS</code>, then
- * this method forwards to the superclass, if <code>axis</code> is
- * <code>View.X_AXIS</code> then this method returns
- * {@link View#ExcellentBreakWeight} if there is a suitable break location
- * (usually whitespace) within the specified view span, or
- * {@link View#GoodBreakWeight} if not.
- *
- * @param axis the axis along which the break weight is requested
- * @param pos the starting view location
- * @param len the length of the span at which the view should be broken
- *
- * @return the break weight
- */
- public int getBreakWeight(int axis, float pos, float len)
- {
- int weight;
- if (axis == Y_AXIS)
- weight = super.getBreakWeight(axis, pos, len);
- else
- {
- checkPainter();
- int start = getStartOffset();
- int end = glyphPainter.getBoundedPosition(this, start, pos, len);
- if (end == 0)
- weight = BadBreakWeight;
- else
- {
- if (getBreakLocation(start, end) != -1)
- weight = ExcellentBreakWeight;
- else
- weight = GoodBreakWeight;
- }
- }
- return weight;
- }
-
- private int getBreakLocation(int start, int end)
- {
- int loc = -1;
- Segment s = getText(start, end);
- for (char c = s.last(); c != Segment.DONE && loc == -1; c = s.previous())
- {
- if (Character.isWhitespace(c))
- {
- loc = s.getIndex() - s.getBeginIndex() + 1 + start;
- }
- }
- return loc;
- }
-
- /**
- * Receives notification that some text attributes have changed within the
- * text fragment that this view is responsible for. This calls
- * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
- * both width and height.
- *
- * @param e the document event describing the change; not used here
- * @param a the view allocation on screen; not used here
- * @param vf the view factory; not used here
- */
- public void changedUpdate(DocumentEvent e, Shape a, ViewFactory vf)
- {
- preferenceChanged(null, true, true);
- }
-
- /**
- * Receives notification that some text has been inserted within the
- * text fragment that this view is responsible for. This calls
- * {@link View#preferenceChanged(View, boolean, boolean)} for the
- * direction in which the glyphs are rendered.
- *
- * @param e the document event describing the change; not used here
- * @param a the view allocation on screen; not used here
- * @param vf the view factory; not used here
- */
- public void insertUpdate(DocumentEvent e, Shape a, ViewFactory vf)
- {
- preferenceChanged(null, true, false);
- }
-
- /**
- * Receives notification that some text has been removed within the
- * text fragment that this view is responsible for. This calls
- * {@link View#preferenceChanged(View, boolean, boolean)} on the parent for
- * width.
- *
- * @param e the document event describing the change; not used here
- * @param a the view allocation on screen; not used here
- * @param vf the view factory; not used here
- */
- public void removeUpdate(DocumentEvent e, Shape a, ViewFactory vf)
- {
- preferenceChanged(null, true, false);
- }
-
- /**
- * Creates a fragment view of this view that starts at <code>p0</code> and
- * ends at <code>p1</code>.
- *
- * @param p0 the start location for the fragment view
- * @param p1 the end location for the fragment view
- *
- * @return the fragment view
- */
- public View createFragment(int p0, int p1)
- {
- checkPainter();
- Element el = getElement();
- GlyphView fragment = (GlyphView) clone();
- fragment.offset = p0 - el.getStartOffset();
- fragment.length = p1 - p0;
- fragment.glyphPainter = glyphPainter.getPainter(fragment, p0, p1);
- return fragment;
- }
-
- /**
- * Returns the alignment of this view along the specified axis. For the Y
- * axis this is <code>(height - descent) / height</code> for the used font,
- * so that it is aligned along the baseline.
- * For the X axis the superclass is called.
- */
- public float getAlignment(int axis)
- {
- checkPainter();
- float align;
- if (axis == Y_AXIS)
- {
- GlyphPainter painter = getGlyphPainter();
- float height = painter.getHeight(this);
- float descent = painter.getDescent(this);
- float ascent = painter.getAscent(this);
- if (isSuperscript())
- align = 1.0F;
- else if (isSubscript())
- align = height > 0 ? (height - (descent + (ascent / 2))) / height
- : 0;
- else
- align = height > 0 ? (height - descent) / height : 0;
- }
- else
- align = super.getAlignment(axis);
-
- return align;
- }
-
- /**
- * Returns the model location that should be used to place a caret when
- * moving the caret through the document.
- *
- * @param pos the current model location
- * @param bias the bias for <code>p</code>
- * @param a the allocated region for the glyph view
- * @param direction the direction from the current position; Must be one of
- * {@link SwingConstants#EAST}, {@link SwingConstants#WEST},
- * {@link SwingConstants#NORTH} or {@link SwingConstants#SOUTH}
- * @param biasRet filled with the bias of the resulting location when method
- * returns
- *
- * @return the location within the document that should be used to place the
- * caret when moving the caret around the document
- *
- * @throws BadLocationException if <code>pos</code> is an invalid model
- * location
- * @throws IllegalArgumentException if <code>d</code> is invalid
- */
- public int getNextVisualPositionFrom(int pos, Position.Bias bias, Shape a,
- int direction, Position.Bias[] biasRet)
- throws BadLocationException
- {
- checkPainter();
- GlyphPainter painter = getGlyphPainter();
- return painter.getNextVisualPositionFrom(this, pos, bias, a, direction,
- biasRet);
- }
-}