Source for javax.swing.text.PlainView

   1: /* PlainView.java -- 
   2:    Copyright (C) 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing.text;
  40: 
  41: import java.awt.Color;
  42: import java.awt.Component;
  43: import java.awt.Font;
  44: import java.awt.FontMetrics;
  45: import java.awt.Graphics;
  46: import java.awt.Rectangle;
  47: import java.awt.Shape;
  48: 
  49: public class PlainView extends View
  50:   implements TabExpander
  51: {
  52:   Color selectedColor;
  53:   Color unselectedColor;
  54:   Font font;
  55:   
  56:   protected FontMetrics metrics;
  57: 
  58:   public PlainView(Element elem)
  59:   {
  60:     super(elem);
  61:   }
  62: 
  63:   /**
  64:    * @since 1.4
  65:    */
  66:   protected void updateMetrics()
  67:   {
  68:     Component component = getContainer();
  69:     Font font = component.getFont();
  70: 
  71:     if (this.font != font)
  72:       {
  73:     this.font = font;
  74:     metrics = component.getFontMetrics(font);
  75:       }
  76:   }
  77:   
  78:   /**
  79:    * @since 1.4
  80:    */
  81:   protected Rectangle lineToRect(Shape a, int line)
  82:   {
  83:     // Ensure metrics are up-to-date.
  84:     updateMetrics();
  85:     
  86:     Rectangle rect = a.getBounds();
  87:     int fontHeight = metrics.getHeight();
  88:     return new Rectangle(rect.x, rect.y + (line * fontHeight),
  89:              rect.width, fontHeight);
  90:   }
  91: 
  92:   public Shape modelToView(int position, Shape a, Position.Bias b)
  93:     throws BadLocationException
  94:   {
  95:     // Ensure metrics are up-to-date.
  96:     updateMetrics();
  97:     
  98:     Document document = getDocument();
  99: 
 100:     // Get rectangle of the line containing position.
 101:     int lineIndex = getElement().getElementIndex(position);
 102:     Rectangle rect = lineToRect(a, lineIndex);
 103: 
 104:     // Get the rectangle for position.
 105:     Element line = getElement().getElement(lineIndex);
 106:     int lineStart = line.getStartOffset();
 107:     Segment segment = new Segment();
 108:     document.getText(lineStart, position - lineStart, segment);
 109:     int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x,
 110:                            this, lineStart);
 111: 
 112:     // Calc the real rectangle.
 113:     rect.x += xoffset;
 114:     rect.width = 1;
 115:     rect.height = metrics.getHeight();
 116: 
 117:     return rect;
 118:   }
 119:   
 120:   protected void drawLine(int lineIndex, Graphics g, int x, int y)
 121:   {
 122:     try
 123:       {
 124:     metrics = g.getFontMetrics();
 125:     // FIXME: Selected text are not drawn yet.
 126:     Element line = getElement().getElement(lineIndex);
 127:     drawUnselectedText(g, x, y, line.getStartOffset(), line.getEndOffset());
 128:     //drawSelectedText(g, , , , );
 129:       }
 130:     catch (BadLocationException e)
 131:       {
 132:     // This should never happen.
 133:       }
 134:   }
 135: 
 136:   protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1)
 137:     throws BadLocationException
 138:   {
 139:     g.setColor(selectedColor);
 140:     Segment segment = new Segment();
 141:     getDocument().getText(p0, p1 - p0, segment);
 142:     return Utilities.drawTabbedText(segment, x, y, g, this, 0);
 143:   }
 144: 
 145:   protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1)
 146:     throws BadLocationException
 147:   {
 148:     g.setColor(unselectedColor);
 149:     Segment segment = new Segment();
 150:     getDocument().getText(p0, p1 - p0, segment);
 151:     return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);
 152:   }
 153: 
 154:   public void paint(Graphics g, Shape s)
 155:   {
 156:     // Ensure metrics are up-to-date.
 157:     updateMetrics();
 158:     
 159:     JTextComponent textComponent = (JTextComponent) getContainer();
 160: 
 161:     g.setFont(textComponent.getFont());
 162:     selectedColor = textComponent.getSelectedTextColor();
 163:     unselectedColor = textComponent.getForeground();
 164:     
 165:     Rectangle rect = s.getBounds();
 166: 
 167:     // FIXME: Text may be scrolled.
 168:     Document document = textComponent.getDocument();
 169:     Element root = document.getDefaultRootElement();
 170:     int y = rect.y;
 171:     
 172:     for (int i = 0; i < root.getElementCount(); i++)
 173:       {
 174:     drawLine(i, g, rect.x, y);
 175:     y += metrics.getHeight();
 176:       }
 177:   }
 178: 
 179:   protected int getTabSize()
 180:   {
 181:     return 8;
 182:   }
 183: 
 184:   /**
 185:    * Returns the next tab stop position after a given reference position.
 186:    *
 187:    * This implementation ignores the <code>tabStop</code> argument.
 188:    * 
 189:    * @param x the current x position in pixels
 190:    * @param tabStop the position within the text stream that the tab occured at
 191:    */
 192:   public float nextTabStop(float x, int tabStop)
 193:   {
 194:     float tabSizePixels = getTabSize() + metrics.charWidth('m');
 195:     return (float) (Math.floor(x / tabSizePixels) + 1) * tabSizePixels;
 196:   }
 197: 
 198:   public float getPreferredSpan(int axis)
 199:   {
 200:     if (axis != X_AXIS && axis != Y_AXIS)
 201:       throw new IllegalArgumentException();
 202: 
 203:     // make sure we have the metrics
 204:     updateMetrics();
 205: 
 206:     float span = 0;
 207:     Element el = getElement();
 208:     Document doc = el.getDocument();
 209:     Segment seg = new Segment();
 210: 
 211:     switch (axis)
 212:       {
 213:       case X_AXIS:
 214:         // calculate the maximum of the line's widths
 215:         for (int i = 0; i < el.getElementCount(); i++)
 216:           {
 217:             Element child = el.getElement(i);
 218:             int start = child.getStartOffset();
 219:             int end = child.getEndOffset();
 220:             try {
 221:               doc.getText(start, start + end, seg);
 222:             }
 223:             catch (BadLocationException ex)
 224:               {
 225:                 // throw new ClasspathAssertionError
 226:                 // ("no BadLocationException should be thrown here");
 227:               }
 228:             int width = metrics.charsWidth(seg.array, seg.offset, seg.count);
 229:             span = Math.max(span, width);
 230:           }
 231:         break;
 232:       case Y_AXIS:
 233:       default:
 234:         span = metrics.getHeight() * el.getElementCount();
 235:         break;
 236:       }
 237: 
 238:     return span;
 239:   }
 240: }