diff options
Diffstat (limited to 'libjava/classpath/javax/swing/text/GlyphView.java')
-rw-r--r-- | libjava/classpath/javax/swing/text/GlyphView.java | 1333 |
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); - } -} |