Home » openjdk-7 » javax » swing » text » [javadoc | source]

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   /**
   18    * @author Alexey A. Ivanov
   19    */
   20   package javax.swing.text;
   21   
   22   import java.awt.BasicStroke;
   23   import java.awt.Color;
   24   import java.awt.Component;
   25   import java.awt.Font;
   26   import java.awt.FontMetrics;
   27   import java.awt.Graphics;
   28   import java.awt.Graphics2D;
   29   import java.awt.Rectangle;
   30   import java.awt.Shape;
   31   import java.awt.Stroke;
   32   import java.awt.Toolkit;
   33   import java.awt.font.LineMetrics;
   34   import java.util.Arrays;
   35   import java.util.Iterator;
   36   import java.util.List;
   37   
   38   import javax.swing.text.GlyphView.GlyphPainter;
   39   import javax.swing.text.Position.Bias;
   40   import javax.swing.text.TextInterval.TextIntervalPainter;
   41   
   42   import org.apache.harmony.awt.text.TextKit;
   43   import org.apache.harmony.awt.text.TextUtils;
   44   
   45   import org.apache.harmony.x.swing.internal.nls.Messages;
   46   
   47   /**
   48    * Default GlyphPainter which is used when a GlyphView needs a painter but
   49    * none was set.
   50    */
   51   final class DefaultGlyphPainter extends GlyphPainter {
   52   
   53       private final class TextPainter implements TextIntervalPainter {
   54           final GlyphView view;
   55           final Rectangle bounds;
   56           final Font font;
   57           final boolean advanced;
   58   
   59           TextPainter(final GlyphView view,
   60                       final Rectangle bounds, final Font font,
   61                       final boolean advanced) {
   62               this.view = view;
   63               this.bounds = bounds;
   64               this.font = font;
   65               this.advanced = advanced;
   66           }
   67   
   68           public int paintSelected(final Graphics g,
   69                                    final int start, final int end,
   70                                    final int x, final int y)
   71               throws BadLocationException {
   72   
   73               return drawSelectedText(this, g, start, end, x, y);
   74           }
   75   
   76           public int paintUnselected(final Graphics g,
   77                                      final int start, final int end,
   78                                      final int x, final int y)
   79               throws BadLocationException {
   80   
   81               return drawUnselectedText(this, g, start, end, x, y);
   82           }
   83   
   84           public int paintComposed(final Graphics g,
   85                                    final int start, final int end,
   86                                    final int x, final int y)
   87               throws BadLocationException {
   88   
   89               if (true) {
   90                   throw new UnsupportedOperationException(Messages.getString("swing.87")); //$NON-NLS-1$
   91               }
   92               return x;
   93           }
   94       }
   95   
   96       private static GlyphPainter defaultPainter;
   97   
   98       public float getSpan(final GlyphView v,
   99                            final int startOffset, final int endOffset,
  100                            final TabExpander tabExpander, final float x) {
  101           final Segment text = v.getText(startOffset, endOffset);
  102           final FontMetrics metrics = getFontMetrics(v);
  103           return TextUtils.getTabbedTextWidth(text, metrics, (int)x, tabExpander,
  104                                               startOffset);
  105       }
  106   
  107       public float getHeight(final GlyphView v) {
  108           return getFontMetrics(v).getHeight();
  109       }
  110   
  111       public float getAscent(final GlyphView v) {
  112           return getFontMetrics(v).getAscent();
  113       }
  114   
  115       public float getDescent(final GlyphView v) {
  116           return getFontMetrics(v).getDescent();
  117       }
  118   
  119       public void paint(final GlyphView v, final Graphics g, final Shape alloc,
  120                         final int startOffset, final int endOffset) {
  121           final TextKit textKit = v.getTextKit();
  122           textKit.paintLayeredHighlights(g, startOffset, endOffset, alloc, v);
  123   
  124           final Rectangle bounds = alloc.getBounds();
  125           final Font font = v.getFont();
  126           final TextPainter painter = new TextPainter(v, bounds, font,
  127                                                       g instanceof Graphics2D
  128                                                       && v.isUnderline()
  129                                                          || v.isStrikeThrough());
  130           final UnselectedTextInterval ui =
  131               new UnselectedTextInterval(v.getStartOffset(), v.getEndOffset(),
  132                                          painter);
  133           final SelectedTextInterval si =
  134               new SelectedTextInterval(textKit.getSelectionStart(),
  135                                        textKit.getSelectionEnd(), painter);
  136           final List intervals = Arrays.asList(ui.dissect(si));
  137   
  138           Color oldColor = g.getColor();
  139           Font oldFont = g.getFont();
  140   
  141           g.setFont(font);
  142           final FontMetrics metrics = getFontMetrics(v, font);
  143           try {
  144               int x = bounds.x;
  145               final int y = bounds.y + metrics.getAscent();
  146               for (Iterator it = intervals.iterator(); it.hasNext();) {
  147                   TextInterval interval = (TextInterval)it.next();
  148                   x = interval.paint(g, x, y);
  149               }
  150           } catch (BadLocationException e) { }
  151   
  152           g.setFont(oldFont);
  153           g.setColor(oldColor);
  154       }
  155   
  156       public Shape modelToView(final GlyphView v,
  157                                final int offset, final Bias bias,
  158                                final Shape alloc)
  159           throws BadLocationException {
  160   
  161           if (offset < v.getStartOffset() || offset > v.getEndOffset()) {
  162               throw new BadLocationException(Messages.getString("swing.88", offset), offset); //$NON-NLS-1$
  163           }
  164   
  165           final Segment text = v.getText(v.getStartOffset(), offset);
  166           final FontMetrics metrics = getFontMetrics(v);
  167           final Rectangle bounds = alloc.getBounds();
  168           return new Rectangle(TextUtils.getTabbedTextWidth(text, metrics,
  169                                                             bounds.x,
  170                                                             v.getTabExpander(),
  171                                                             offset) + bounds.x,
  172                                bounds.y, 0, metrics.getHeight());
  173       }
  174   
  175       public int viewToModel(final GlyphView v,
  176                              final float x, final float y,
  177                              final Shape alloc, final Bias[] biasReturn) {
  178           biasReturn[0] = Bias.Forward;
  179   
  180           final Rectangle bounds = alloc.getBounds();
  181           if (x < bounds.x || y < bounds.y) {
  182               return v.getStartOffset();
  183           }
  184           if (x > bounds.x + bounds.width || y > bounds.y + bounds.height) {
  185               return v.getEndOffset() - 1;
  186           }
  187           final Segment text = v.getText(v.getStartOffset(), v.getEndOffset());
  188           final FontMetrics fm = getFontMetrics(v);
  189           return v.getStartOffset()
  190                  + TextUtils.getTabbedTextOffset(text, fm, bounds.x, (int)x,
  191                                                  v.getTabExpander(),
  192                                                  v.getStartOffset());
  193       }
  194   
  195       public int getBoundedPosition(final GlyphView v,
  196                                     final int startOffset,
  197                                     final float x, final float len) {
  198           final Segment text = v.getText(startOffset, v.getEndOffset());
  199           final FontMetrics fm = getFontMetrics(v);
  200           return startOffset
  201                  + TextUtils.getTabbedTextOffset(text, fm, (int)x, (int)(x + len),
  202                                                  v.getTabExpander(),
  203                                                  startOffset, false);
  204       }
  205   
  206       static GlyphPainter getDefaultPainter() {
  207           if (defaultPainter == null) {
  208               defaultPainter = new DefaultGlyphPainter();
  209           }
  210           return defaultPainter;
  211       }
  212   
  213       static FontMetrics getFontMetrics(final GlyphView v) {
  214           return getFontMetrics(v, v.getFont());
  215       }
  216   
  217       static FontMetrics getFontMetrics(final GlyphView v, final Font font) {
  218           Component c = v.getComponent();
  219           return c != null ? c.getFontMetrics(font)
  220                            : Toolkit.getDefaultToolkit().getFontMetrics(font);
  221       }
  222   
  223       int drawText(final GlyphView v, final Graphics g,
  224                    final int start, final int end,
  225                    final int x, final int y) throws BadLocationException {
  226           return TextUtils.drawTabbedText(v.getText(start, end), x, y,
  227                                           g, v.getTabExpander(), start);
  228       }
  229   
  230       int drawSelectedText(final TextPainter tp, final Graphics g,
  231                            final int start, final int end,
  232                            final int x, final int y) throws BadLocationException {
  233           g.setColor(tp.view.getTextKit().getSelectedTextColor());
  234           final int result = drawText(tp.view, g, start, end, x, y);
  235           if (tp.advanced) {
  236               paintAdvancedStyles(tp.view, start, end, (Graphics2D)g, tp.font,
  237                                   tp.view.modelToView(start, Bias.Forward,
  238                                                       end, Bias.Backward,
  239                                                       tp.bounds).getBounds());
  240           }
  241           return result;
  242       }
  243   
  244       int drawUnselectedText(final TextPainter tp, final Graphics g,
  245                              final int start, final int end,
  246                              final int x, final int y)
  247           throws BadLocationException {
  248   
  249           Rectangle r = null;
  250           try {
  251               r = tp.view.modelToView(start, Bias.Forward,
  252                                 end, Bias.Backward, tp.bounds).getBounds();
  253           } catch (BadLocationException e) { }
  254   
  255           Color back = tp.view.getBackground();
  256           if (back != null && r != null) {
  257               g.setColor(back);
  258               g.fillRect(r.x, r.y, r.width, r.height);
  259           }
  260   
  261           g.setColor(tp.view.getForeground());
  262           final int result = drawText(tp.view, g, start, end, x, y);
  263           if (tp.advanced) {
  264               paintAdvancedStyles(tp.view, start, end, (Graphics2D)g, tp.font, r);
  265           }
  266           return result;
  267       }
  268   
  269       private void paintAdvancedStyles(final GlyphView v,
  270                                        final int start, final int end,
  271                                        final Graphics2D g,
  272                                        final Font font, final Rectangle bounds) {
  273           final Segment text = v.getText(start, end);
  274           final LineMetrics lm = font.getLineMetrics(text.array, text.offset,
  275                                                      text.offset + text.count,
  276                                                      g.getFontRenderContext());
  277           int baseline = bounds.y + Math.round(lm.getAscent());
  278   
  279           if (v.isStrikeThrough()) {
  280               int offset = Math.round(lm.getStrikethroughOffset()) + baseline;
  281               BasicStroke stroke =
  282                   new BasicStroke(lm.getStrikethroughThickness());
  283               Stroke oldStroke = g.getStroke();
  284               g.setStroke(stroke);
  285               g.drawLine(bounds.x, offset, bounds.x + bounds.width, offset);
  286               g.setStroke(oldStroke);
  287           }
  288   
  289           if (v.isUnderline()) {
  290               int offset = Math.round(lm.getUnderlineOffset()) + baseline;
  291               BasicStroke stroke = new BasicStroke(lm.getUnderlineThickness());
  292               Stroke oldStroke = g.getStroke();
  293               g.setStroke(stroke);
  294               g.drawLine(bounds.x, offset, bounds.x + bounds.width, offset);
  295               g.setStroke(oldStroke);
  296           }
  297       }
  298   }

Home » openjdk-7 » javax » swing » text » [javadoc | source]