1/*
2 * Copyright (c) 1995, 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 java.awt;
26
27import java.awt.peer.LabelPeer;
28import java.io.IOException;
29import java.io.ObjectInputStream;
30import javax.accessibility.*;
31
32/**
33 * A {@code Label} object is a component for placing text in a
34 * container. A label displays a single line of read-only text.
35 * The text can be changed by the application, but a user cannot edit it
36 * directly.
37 * <p>
38 * For example, the code&nbsp;.&nbsp;.&nbsp;.
39 *
40 * <hr><blockquote><pre>
41 * setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
42 * add(new Label("Hi There!"));
43 * add(new Label("Another Label"));
44 * </pre></blockquote><hr>
45 * <p>
46 * produces the following labels:
47 * <p>
48 * <img src="doc-files/Label-1.gif" alt="Two labels: 'Hi There!' and 'Another label'"
49 * style="float:center; margin: 7px 10px;">
50 *
51 * @author      Sami Shaio
52 * @since       1.0
53 */
54public class Label extends Component implements Accessible {
55
56    static {
57        /* ensure that the necessary native libraries are loaded */
58        Toolkit.loadLibraries();
59        if (!GraphicsEnvironment.isHeadless()) {
60            initIDs();
61        }
62    }
63
64    /**
65     * Indicates that the label should be left justified.
66     */
67    public static final int LEFT        = 0;
68
69    /**
70     * Indicates that the label should be centered.
71     */
72    public static final int CENTER      = 1;
73
74    /**
75     * Indicates that the label should be right justified.
76     */
77    public static final int RIGHT       = 2;
78
79    /**
80     * The text of this label.
81     * This text can be modified by the program
82     * but never by the user.
83     *
84     * @serial
85     * @see #getText()
86     * @see #setText(String)
87     */
88    String text;
89
90    /**
91     * The label's alignment.  The default alignment is set
92     * to be left justified.
93     *
94     * @serial
95     * @see #getAlignment()
96     * @see #setAlignment(int)
97     */
98    int    alignment = LEFT;
99
100    private static final String base = "label";
101    private static int nameCounter = 0;
102
103    /*
104     * JDK 1.1 serialVersionUID
105     */
106     private static final long serialVersionUID = 3094126758329070636L;
107
108    /**
109     * Constructs an empty label.
110     * The text of the label is the empty string {@code ""}.
111     * @exception HeadlessException if GraphicsEnvironment.isHeadless()
112     * returns true.
113     * @see java.awt.GraphicsEnvironment#isHeadless
114     */
115    public Label() throws HeadlessException {
116        this("", LEFT);
117    }
118
119    /**
120     * Constructs a new label with the specified string of text,
121     * left justified.
122     * @param text the string that the label presents.
123     *        A {@code null} value
124     *        will be accepted without causing a NullPointerException
125     *        to be thrown.
126     * @exception HeadlessException if GraphicsEnvironment.isHeadless()
127     * returns true.
128     * @see java.awt.GraphicsEnvironment#isHeadless
129     */
130    public Label(String text) throws HeadlessException {
131        this(text, LEFT);
132    }
133
134    /**
135     * Constructs a new label that presents the specified string of
136     * text with the specified alignment.
137     * Possible values for {@code alignment} are {@code Label.LEFT},
138     * {@code Label.RIGHT}, and {@code Label.CENTER}.
139     * @param text the string that the label presents.
140     *        A {@code null} value
141     *        will be accepted without causing a NullPointerException
142     *        to be thrown.
143     * @param     alignment   the alignment value.
144     * @exception HeadlessException if GraphicsEnvironment.isHeadless()
145     * returns true.
146     * @see java.awt.GraphicsEnvironment#isHeadless
147     */
148    public Label(String text, int alignment) throws HeadlessException {
149        GraphicsEnvironment.checkHeadless();
150        this.text = text;
151        setAlignment(alignment);
152    }
153
154    /**
155     * Read a label from an object input stream.
156     * @exception HeadlessException if
157     * {@code GraphicsEnvironment.isHeadless()} returns
158     * {@code true}
159     * @serial
160     * @since 1.4
161     * @see java.awt.GraphicsEnvironment#isHeadless
162     */
163    private void readObject(ObjectInputStream s)
164        throws ClassNotFoundException, IOException, HeadlessException {
165        GraphicsEnvironment.checkHeadless();
166        s.defaultReadObject();
167    }
168
169    /**
170     * Construct a name for this component.  Called by getName() when the
171     * name is {@code null}.
172     */
173    String constructComponentName() {
174        synchronized (Label.class) {
175            return base + nameCounter++;
176        }
177    }
178
179    /**
180     * Creates the peer for this label.  The peer allows us to
181     * modify the appearance of the label without changing its
182     * functionality.
183     */
184    public void addNotify() {
185        synchronized (getTreeLock()) {
186            if (peer == null)
187                peer = getComponentFactory().createLabel(this);
188            super.addNotify();
189        }
190    }
191
192    /**
193     * Gets the current alignment of this label. Possible values are
194     * {@code Label.LEFT}, {@code Label.RIGHT}, and
195     * {@code Label.CENTER}.
196     * @return the alignment of this label
197     * @see java.awt.Label#setAlignment
198     */
199    public int getAlignment() {
200        return alignment;
201    }
202
203    /**
204     * Sets the alignment for this label to the specified alignment.
205     * Possible values are {@code Label.LEFT},
206     * {@code Label.RIGHT}, and {@code Label.CENTER}.
207     * @param      alignment    the alignment to be set.
208     * @exception  IllegalArgumentException if an improper value for
209     *                          {@code alignment} is given.
210     * @see        java.awt.Label#getAlignment
211     */
212    public synchronized void setAlignment(int alignment) {
213        switch (alignment) {
214          case LEFT:
215          case CENTER:
216          case RIGHT:
217            this.alignment = alignment;
218            LabelPeer peer = (LabelPeer)this.peer;
219            if (peer != null) {
220                peer.setAlignment(alignment);
221            }
222            return;
223        }
224        throw new IllegalArgumentException("improper alignment: " + alignment);
225    }
226
227    /**
228     * Gets the text of this label.
229     * @return     the text of this label, or {@code null} if
230     *             the text has been set to {@code null}.
231     * @see        java.awt.Label#setText
232     */
233    public String getText() {
234        return text;
235    }
236
237    /**
238     * Sets the text for this label to the specified text.
239     * @param      text the text that this label displays. If
240     *             {@code text} is {@code null}, it is
241     *             treated for display purposes like an empty
242     *             string {@code ""}.
243     * @see        java.awt.Label#getText
244     */
245    public void setText(String text) {
246        boolean testvalid = false;
247        synchronized (this) {
248            if (text != this.text && (this.text == null ||
249                                      !this.text.equals(text))) {
250                this.text = text;
251                LabelPeer peer = (LabelPeer)this.peer;
252                if (peer != null) {
253                    peer.setText(text);
254                }
255                testvalid = true;
256            }
257        }
258
259        // This could change the preferred size of the Component.
260        if (testvalid) {
261            invalidateIfValid();
262        }
263    }
264
265    /**
266     * Returns a string representing the state of this {@code Label}.
267     * This method is intended to be used only for debugging purposes, and the
268     * content and format of the returned string may vary between
269     * implementations. The returned string may be empty but may not be
270     * {@code null}.
271     *
272     * @return     the parameter string of this label
273     */
274    protected String paramString() {
275        String align = "";
276        switch (alignment) {
277            case LEFT:   align = "left"; break;
278            case CENTER: align = "center"; break;
279            case RIGHT:  align = "right"; break;
280        }
281        return super.paramString() + ",align=" + align + ",text=" + text;
282    }
283
284    /**
285     * Initialize JNI field and method IDs
286     */
287    private static native void initIDs();
288
289
290/////////////////
291// Accessibility support
292////////////////
293
294
295    /**
296     * Gets the AccessibleContext associated with this Label.
297     * For labels, the AccessibleContext takes the form of an
298     * AccessibleAWTLabel.
299     * A new AccessibleAWTLabel instance is created if necessary.
300     *
301     * @return an AccessibleAWTLabel that serves as the
302     *         AccessibleContext of this Label
303     * @since 1.3
304     */
305    public AccessibleContext getAccessibleContext() {
306        if (accessibleContext == null) {
307            accessibleContext = new AccessibleAWTLabel();
308        }
309        return accessibleContext;
310    }
311
312    /**
313     * This class implements accessibility support for the
314     * {@code Label} class.  It provides an implementation of the
315     * Java Accessibility API appropriate to label user-interface elements.
316     * @since 1.3
317     */
318    protected class AccessibleAWTLabel extends AccessibleAWTComponent
319    {
320        /*
321         * JDK 1.3 serialVersionUID
322         */
323        private static final long serialVersionUID = -3568967560160480438L;
324
325        /**
326         * Constructor for the accessible label.
327         */
328        public AccessibleAWTLabel() {
329            super();
330        }
331
332        /**
333         * Get the accessible name of this object.
334         *
335         * @return the localized name of the object -- can be null if this
336         * object does not have a name
337         * @see AccessibleContext#setAccessibleName
338         */
339        public String getAccessibleName() {
340            if (accessibleName != null) {
341                return accessibleName;
342            } else {
343                if (getText() == null) {
344                    return super.getAccessibleName();
345                } else {
346                    return getText();
347                }
348            }
349        }
350
351        /**
352         * Get the role of this object.
353         *
354         * @return an instance of AccessibleRole describing the role of the object
355         * @see AccessibleRole
356         */
357        public AccessibleRole getAccessibleRole() {
358            return AccessibleRole.LABEL;
359        }
360
361    } // inner class AccessibleAWTLabel
362
363}
364