1/*
2 * Copyright (c) 2002, 2013, 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
26package javax.swing.plaf.synth;
27
28import javax.swing.*;
29import javax.swing.plaf.*;
30import javax.swing.plaf.basic.*;
31import javax.swing.text.View;
32import java.awt.Dimension;
33import java.awt.Rectangle;
34import java.awt.Insets;
35import java.awt.Graphics;
36import java.awt.FontMetrics;
37import java.beans.PropertyChangeEvent;
38
39/**
40 * Provides the Synth L&F UI delegate for
41 * {@link javax.swing.JLabel}.
42 *
43 * @author Scott Violet
44 * @since 1.7
45 */
46public class SynthLabelUI extends BasicLabelUI implements SynthUI {
47    private SynthStyle style;
48
49    /**
50     * Returns the LabelUI implementation used for the skins look and feel.
51     *
52     * @param c component to create UI object for
53     * @return the UI object
54     */
55    public static ComponentUI createUI(JComponent c){
56        return new SynthLabelUI();
57    }
58
59    /**
60     * {@inheritDoc}
61     */
62    @Override
63    protected void installDefaults(JLabel c) {
64        updateStyle(c);
65    }
66
67    void updateStyle(JLabel c) {
68        SynthContext context = getContext(c, ENABLED);
69        style = SynthLookAndFeel.updateStyle(context, this);
70    }
71
72    /**
73     * {@inheritDoc}
74     */
75    @Override
76    protected void uninstallDefaults(JLabel c){
77        SynthContext context = getContext(c, ENABLED);
78
79        style.uninstallDefaults(context);
80        style = null;
81    }
82
83    /**
84     * {@inheritDoc}
85     */
86    @Override
87    public SynthContext getContext(JComponent c) {
88        return getContext(c, getComponentState(c));
89    }
90
91    private SynthContext getContext(JComponent c, int state) {
92        return SynthContext.getContext(c, style, state);
93    }
94
95    private int getComponentState(JComponent c) {
96        int state = SynthLookAndFeel.getComponentState(c);
97        if (SynthLookAndFeel.getSelectedUI() == this &&
98                        state == SynthConstants.ENABLED) {
99            state = SynthLookAndFeel.getSelectedUIState() | SynthConstants.ENABLED;
100        }
101        return state;
102    }
103
104    /**
105     * {@inheritDoc}
106     */
107    @Override
108    public int getBaseline(JComponent c, int width, int height) {
109        if (c == null) {
110            throw new NullPointerException("Component must be non-null");
111        }
112        if (width < 0 || height < 0) {
113            throw new IllegalArgumentException(
114                    "Width and height must be >= 0");
115        }
116        JLabel label = (JLabel)c;
117        String text = label.getText();
118        if (text == null || "".equals(text)) {
119            return -1;
120        }
121        Insets i = label.getInsets();
122        Rectangle viewRect = new Rectangle();
123        Rectangle textRect = new Rectangle();
124        Rectangle iconRect = new Rectangle();
125        viewRect.x = i.left;
126        viewRect.y = i.top;
127        viewRect.width = width - (i.right + viewRect.x);
128        viewRect.height = height - (i.bottom + viewRect.y);
129
130        // layout the text and icon
131        SynthContext context = getContext(label);
132        FontMetrics fm = context.getComponent().getFontMetrics(
133            context.getStyle().getFont(context));
134        context.getStyle().getGraphicsUtils(context).layoutText(
135            context, fm, label.getText(), label.getIcon(),
136            label.getHorizontalAlignment(), label.getVerticalAlignment(),
137            label.getHorizontalTextPosition(), label.getVerticalTextPosition(),
138            viewRect, iconRect, textRect, label.getIconTextGap());
139        View view = (View)label.getClientProperty(BasicHTML.propertyKey);
140        int baseline;
141        if (view != null) {
142            baseline = BasicHTML.getHTMLBaseline(view, textRect.width,
143                                                 textRect.height);
144            if (baseline >= 0) {
145                baseline += textRect.y;
146            }
147        }
148        else {
149            baseline = textRect.y + fm.getAscent();
150        }
151        return baseline;
152    }
153
154    /**
155     * Notifies this UI delegate to repaint the specified component.
156     * This method paints the component background, then calls
157     * the {@link #paint(SynthContext,Graphics)} method.
158     *
159     * <p>In general, this method does not need to be overridden by subclasses.
160     * All Look and Feel rendering code should reside in the {@code paint} method.
161     *
162     * @param g the {@code Graphics} object used for painting
163     * @param c the component being painted
164     * @see #paint(SynthContext,Graphics)
165     */
166    @Override
167    public void update(Graphics g, JComponent c) {
168        SynthContext context = getContext(c);
169
170        SynthLookAndFeel.update(context, g);
171        context.getPainter().paintLabelBackground(context,
172                          g, 0, 0, c.getWidth(), c.getHeight());
173        paint(context, g);
174    }
175
176    /**
177     * Paints the specified component according to the Look and Feel.
178     * <p>This method is not used by Synth Look and Feel.
179     * Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
180     *
181     * @param g the {@code Graphics} object used for painting
182     * @param c the component being painted
183     * @see #paint(SynthContext,Graphics)
184     */
185    @Override
186    public void paint(Graphics g, JComponent c) {
187        SynthContext context = getContext(c);
188
189        paint(context, g);
190    }
191
192    /**
193     * Paints the specified component.
194     *
195     * @param context context for the component being painted
196     * @param g the {@code Graphics} object used for painting
197     * @see #update(Graphics,JComponent)
198     */
199    protected void paint(SynthContext context, Graphics g) {
200        JLabel label = (JLabel)context.getComponent();
201        Icon icon = (label.isEnabled()) ? label.getIcon() :
202                                          label.getDisabledIcon();
203
204        g.setColor(context.getStyle().getColor(context,
205                                               ColorType.TEXT_FOREGROUND));
206        g.setFont(style.getFont(context));
207        context.getStyle().getGraphicsUtils(context).paintText(
208            context, g, label.getText(), icon,
209            label.getHorizontalAlignment(), label.getVerticalAlignment(),
210            label.getHorizontalTextPosition(), label.getVerticalTextPosition(),
211            label.getIconTextGap(), label.getDisplayedMnemonicIndex(), 0);
212    }
213
214    /**
215     * {@inheritDoc}
216     */
217    @Override
218    public void paintBorder(SynthContext context, Graphics g, int x,
219                            int y, int w, int h) {
220        context.getPainter().paintLabelBorder(context, g, x, y, w, h);
221    }
222
223    /**
224     * {@inheritDoc}
225     */
226    @Override
227    public Dimension getPreferredSize(JComponent c) {
228        JLabel label = (JLabel)c;
229        Icon icon = (label.isEnabled()) ? label.getIcon() :
230                                          label.getDisabledIcon();
231        SynthContext context = getContext(c);
232        Dimension size = context.getStyle().getGraphicsUtils(context).
233            getPreferredSize(
234               context, context.getStyle().getFont(context), label.getText(),
235               icon, label.getHorizontalAlignment(),
236               label.getVerticalAlignment(), label.getHorizontalTextPosition(),
237               label.getVerticalTextPosition(), label.getIconTextGap(),
238               label.getDisplayedMnemonicIndex());
239
240        return size;
241    }
242
243    /**
244     * {@inheritDoc}
245     */
246    @Override
247    public Dimension getMinimumSize(JComponent c) {
248        JLabel label = (JLabel)c;
249        Icon icon = (label.isEnabled()) ? label.getIcon() :
250                                          label.getDisabledIcon();
251        SynthContext context = getContext(c);
252        Dimension size = context.getStyle().getGraphicsUtils(context).
253            getMinimumSize(
254               context, context.getStyle().getFont(context), label.getText(),
255               icon, label.getHorizontalAlignment(),
256               label.getVerticalAlignment(), label.getHorizontalTextPosition(),
257               label.getVerticalTextPosition(), label.getIconTextGap(),
258               label.getDisplayedMnemonicIndex());
259
260        return size;
261    }
262
263    /**
264     * {@inheritDoc}
265     */
266    @Override
267    public Dimension getMaximumSize(JComponent c) {
268        JLabel label = (JLabel)c;
269        Icon icon = (label.isEnabled()) ? label.getIcon() :
270                                          label.getDisabledIcon();
271        SynthContext context = getContext(c);
272        Dimension size = context.getStyle().getGraphicsUtils(context).
273               getMaximumSize(
274               context, context.getStyle().getFont(context), label.getText(),
275               icon, label.getHorizontalAlignment(),
276               label.getVerticalAlignment(), label.getHorizontalTextPosition(),
277               label.getVerticalTextPosition(), label.getIconTextGap(),
278               label.getDisplayedMnemonicIndex());
279
280        return size;
281    }
282
283    /**
284     * {@inheritDoc}
285     */
286    @Override
287    public void propertyChange(PropertyChangeEvent e) {
288        super.propertyChange(e);
289        if (SynthLookAndFeel.shouldUpdateStyle(e)) {
290            updateStyle((JLabel)e.getSource());
291        }
292    }
293}
294