1 /*
   2  * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package javax.swing.text;
  26 
  27 import java.awt.*;
  28 import javax.swing.event.*;
  29 
  30 /**
  31  * A <code>LabelView</code> is a styled chunk of text
  32  * that represents a view mapped over an element in the
  33  * text model.  It caches the character level attributes
  34  * used for rendering.
  35  *
  36  * @author Timothy Prinzing
  37  */
  38 public class LabelView extends GlyphView implements TabableView {
  39 
  40     /**
  41      * Constructs a new view wrapped on an element.
  42      *
  43      * @param elem the element
  44      */
  45     public LabelView(Element elem) {
  46         super(elem);
  47     }
  48 
  49     /**
  50      * Synchronize the view's cached values with the model.
  51      * This causes the font, metrics, color, etc to be
  52      * re-cached if the cache has been invalidated.
  53      */
  54     final void sync() {
  55         if (font == null) {
  56             setPropertiesFromAttributes();
  57         }
  58     }
  59 
  60     /**
  61      * Sets whether or not the view is underlined.
  62      * Note that this setter is protected and is really
  63      * only meant if you need to update some additional
  64      * state when set.
  65      *
  66      * @param u true if the view is underlined, otherwise
  67      *          false
  68      * @see #isUnderline
  69      */
  70     protected void setUnderline(boolean u) {
  71         underline = u;
  72     }
  73 
  74     /**
  75      * Sets whether or not the view has a strike/line
  76      * through it.
  77      * Note that this setter is protected and is really
  78      * only meant if you need to update some additional
  79      * state when set.
  80      *
  81      * @param s true if the view has a strike/line
  82      *          through it, otherwise false
  83      * @see #isStrikeThrough
  84      */
  85     protected void setStrikeThrough(boolean s) {
  86         strike = s;
  87     }
  88 
  89 
  90     /**
  91      * Sets whether or not the view represents a
  92      * superscript.
  93      * Note that this setter is protected and is really
  94      * only meant if you need to update some additional
  95      * state when set.
  96      *
  97      * @param s true if the view represents a
  98      *          superscript, otherwise false
  99      * @see #isSuperscript
 100      */
 101     protected void setSuperscript(boolean s) {
 102         superscript = s;
 103     }
 104 
 105     /**
 106      * Sets whether or not the view represents a
 107      * subscript.
 108      * Note that this setter is protected and is really
 109      * only meant if you need to update some additional
 110      * state when set.
 111      *
 112      * @param s true if the view represents a
 113      *          subscript, otherwise false
 114      * @see #isSubscript
 115      */
 116     protected void setSubscript(boolean s) {
 117         subscript = s;
 118     }
 119 
 120     /**
 121      * Sets the background color for the view. This method is typically
 122      * invoked as part of configuring this <code>View</code>. If you need
 123      * to customize the background color you should override
 124      * <code>setPropertiesFromAttributes</code> and invoke this method. A
 125      * value of null indicates no background should be rendered, so that the
 126      * background of the parent <code>View</code> will show through.
 127      *
 128      * @param bg background color, or null
 129      * @see #setPropertiesFromAttributes
 130      * @since 1.5
 131      */
 132     protected void setBackground(Color bg) {
 133         this.bg = bg;
 134     }
 135 
 136     /**
 137      * Sets the cached properties from the attributes.
 138      */
 139     protected void setPropertiesFromAttributes() {
 140         AttributeSet attr = getAttributes();
 141         if (attr != null) {
 142             Document d = getDocument();
 143             if (d instanceof StyledDocument) {
 144                 StyledDocument doc = (StyledDocument) d;
 145                 font = doc.getFont(attr);
 146                 fg = doc.getForeground(attr);
 147                 if (attr.isDefined(StyleConstants.Background)) {
 148                     bg = doc.getBackground(attr);
 149                 } else {
 150                     bg = null;
 151                 }
 152                 setUnderline(StyleConstants.isUnderline(attr));
 153                 setStrikeThrough(StyleConstants.isStrikeThrough(attr));
 154                 setSuperscript(StyleConstants.isSuperscript(attr));
 155                 setSubscript(StyleConstants.isSubscript(attr));
 156             } else {
 157                 throw new StateInvariantError("LabelView needs StyledDocument");
 158             }
 159         }
 160      }
 161 
 162     /**
 163      * Fetches the <code>FontMetrics</code> used for this view.
 164      * @return the <code>FontMetrics</code> used for this view
 165      * @deprecated FontMetrics are not used for glyph rendering
 166      *  when running in the JDK.
 167      */
 168     @Deprecated
 169     protected FontMetrics getFontMetrics() {
 170         sync();
 171         Container c = getContainer();
 172         return (c != null) ? c.getFontMetrics(font) :
 173             Toolkit.getDefaultToolkit().getFontMetrics(font);
 174     }
 175 
 176     /**
 177      * Fetches the background color to use to render the glyphs.
 178      * This is implemented to return a cached background color,
 179      * which defaults to <code>null</code>.
 180      *
 181      * @return the cached background color
 182      * @since 1.3
 183      */
 184     public Color getBackground() {
 185         sync();
 186         return bg;
 187     }
 188 
 189     /**
 190      * Fetches the foreground color to use to render the glyphs.
 191      * This is implemented to return a cached foreground color,
 192      * which defaults to <code>null</code>.
 193      *
 194      * @return the cached foreground color
 195      * @since 1.3
 196      */
 197     public Color getForeground() {
 198         sync();
 199         return fg;
 200     }
 201 
 202     /**
 203      * Fetches the font that the glyphs should be based upon.
 204      * This is implemented to return a cached font.
 205      *
 206      * @return the cached font
 207      */
 208      public Font getFont() {
 209         sync();
 210         return font;
 211     }
 212 
 213     /**
 214      * Determines if the glyphs should be underlined.  If true,
 215      * an underline should be drawn through the baseline.  This
 216      * is implemented to return the cached underline property.
 217      *
 218      * <p>When you request this property, <code>LabelView</code>
 219      * re-syncs its state with the properties of the
 220      * <code>Element</code>'s <code>AttributeSet</code>.
 221      * If <code>Element</code>'s <code>AttributeSet</code>
 222      * does not have this property set, it will revert to false.
 223      *
 224      * @return the value of the cached
 225      *     <code>underline</code> property
 226      * @since 1.3
 227      */
 228     public boolean isUnderline() {
 229         sync();
 230         return underline;
 231     }
 232 
 233     /**
 234      * Determines if the glyphs should have a strikethrough
 235      * line.  If true, a line should be drawn through the center
 236      * of the glyphs.  This is implemented to return the
 237      * cached <code>strikeThrough</code> property.
 238      *
 239      * <p>When you request this property, <code>LabelView</code>
 240      * re-syncs its state with the properties of the
 241      * <code>Element</code>'s <code>AttributeSet</code>.
 242      * If <code>Element</code>'s <code>AttributeSet</code>
 243      * does not have this property set, it will revert to false.
 244      *
 245      * @return the value of the cached
 246      *     <code>strikeThrough</code> property
 247      * @since 1.3
 248      */
 249     public boolean isStrikeThrough() {
 250         sync();
 251         return strike;
 252     }
 253 
 254     /**
 255      * Determines if the glyphs should be rendered as superscript.
 256      * @return the value of the cached subscript property
 257      *
 258      * <p>When you request this property, <code>LabelView</code>
 259      * re-syncs its state with the properties of the
 260      * <code>Element</code>'s <code>AttributeSet</code>.
 261      * If <code>Element</code>'s <code>AttributeSet</code>
 262      * does not have this property set, it will revert to false.
 263      *
 264      * @return the value of the cached
 265      *     <code>subscript</code> property
 266      * @since 1.3
 267      */
 268     public boolean isSubscript() {
 269         sync();
 270         return subscript;
 271     }
 272 
 273     /**
 274      * Determines if the glyphs should be rendered as subscript.
 275      *
 276      * <p>When you request this property, <code>LabelView</code>
 277      * re-syncs its state with the properties of the
 278      * <code>Element</code>'s <code>AttributeSet</code>.
 279      * If <code>Element</code>'s <code>AttributeSet</code>
 280      * does not have this property set, it will revert to false.
 281      *
 282      * @return the value of the cached
 283      *     <code>superscript</code> property
 284      * @since 1.3
 285      */
 286     public boolean isSuperscript() {
 287         sync();
 288         return superscript;
 289     }
 290 
 291     // --- View methods ---------------------------------------------
 292 
 293     /**
 294      * Gives notification from the document that attributes were changed
 295      * in a location that this view is responsible for.
 296      *
 297      * @param e the change information from the associated document
 298      * @param a the current allocation of the view
 299      * @param f the factory to use to rebuild if the view has children
 300      * @see View#changedUpdate
 301      */
 302     public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) {
 303         font = null;
 304         super.changedUpdate(e, a, f);
 305     }
 306 
 307     // --- variables ------------------------------------------------
 308 
 309     private Font font;
 310     private Color fg;
 311     private Color bg;
 312     private boolean underline;
 313     private boolean strike;
 314     private boolean superscript;
 315     private boolean subscript;
 316 
 317 }