mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1334 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1334 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* 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);
 | |
|   }
 | |
| }
 |