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 */
25package javax.swing.text;
26
27import java.awt.*;
28import 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 */
38public 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}
318