/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package javax.swing;
import java.awt.
Component;
import java.awt.
Font;
import java.awt.
Image;
import java.awt.*;
import java.text.*;
import java.awt.geom.*;
import java.beans.
Transient;
import java.io.
ObjectOutputStream;
import java.io.
ObjectInputStream;
import java.io.
IOException;
import javax.swing.plaf.
LabelUI;
import javax.accessibility.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.swing.plaf.basic.*;
import java.util.*;
/**
* A display area for a short text string or an image,
* or both.
* A label does not react to input events.
* As a result, it cannot get the keyboard focus.
* A label can, however, display a keyboard alternative
* as a convenience for a nearby component
* that has a keyboard alternative but can't display it.
* <p>
* A <code>JLabel</code> object can display
* either text, an image, or both.
* You can specify where in the label's display area
* the label's contents are aligned
* by setting the vertical and horizontal alignment.
* By default, labels are vertically centered
* in their display area.
* Text-only labels are leading edge aligned, by default;
* image-only labels are horizontally centered, by default.
* <p>
* You can also specify the position of the text
* relative to the image.
* By default, text is on the trailing edge of the image,
* with the text and image vertically aligned.
* <p>
* A label's leading and trailing edge are determined from the value of its
* {@link java.awt.ComponentOrientation} property. At present, the default
* ComponentOrientation setting maps the leading edge to left and the trailing
* edge to right.
*
* <p>
* Finally, you can use the <code>setIconTextGap</code> method
* to specify how many pixels
* should appear between the text and the image.
* The default is 4 pixels.
* <p>
* See <a href="https://docs.oracle.com/javase/tutorial/uiswing/components/label.html">How to Use Labels</a>
* in <em>The Java Tutorial</em>
* for further documentation.
* <p>
* <strong>Warning:</strong> Swing is not thread safe. For more
* information see <a
* href="package-summary.html#threading">Swing's Threading
* Policy</a>.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing. As of 1.4, support for long term storage
* of all JavaBeans™
* has been added to the <code>java.beans</code> package.
* Please see {@link java.beans.XMLEncoder}.
*
* @beaninfo
* attribute: isContainer false
* description: A component that displays a short string and an icon.
*
* @author Hans Muller
*/
@
SuppressWarnings("serial")
public class
JLabel extends
JComponent implements
SwingConstants,
Accessible
{
/**
* @see #getUIClassID
* @see #readObject
*/
private static final
String uiClassID = "LabelUI";
private int
mnemonic = '\0';
private int
mnemonicIndex = -1;
private
String text = ""; // "" rather than null, for BeanBox
private
Icon defaultIcon = null;
private
Icon disabledIcon = null;
private boolean
disabledIconSet = false;
private int
verticalAlignment =
CENTER;
private int
horizontalAlignment =
LEADING;
private int
verticalTextPosition =
CENTER;
private int
horizontalTextPosition =
TRAILING;
private int
iconTextGap = 4;
protected
Component labelFor = null;
/**
* Client property key used to determine what label is labeling the
* component. This is generally not used by labels, but is instead
* used by components such as text areas that are being labeled by
* labels. When the labelFor property of a label is set, it will
* automatically set the LABELED_BY_PROPERTY of the component being
* labelled.
*
* @see #setLabelFor
*/
static final
String LABELED_BY_PROPERTY = "labeledBy";
/**
* Creates a <code>JLabel</code> instance with the specified
* text, image, and horizontal alignment.
* The label is centered vertically in its display area.
* The text is on the trailing edge of the image.
*
* @param text The text to be displayed by the label.
* @param icon The image to be displayed by the label.
* @param horizontalAlignment One of the following constants
* defined in <code>SwingConstants</code>:
* <code>LEFT</code>,
* <code>CENTER</code>,
* <code>RIGHT</code>,
* <code>LEADING</code> or
* <code>TRAILING</code>.
*/
public
JLabel(
String text,
Icon icon, int
horizontalAlignment) {
setText(
text);
setIcon(
icon);
setHorizontalAlignment(
horizontalAlignment);
updateUI();
setAlignmentX(
LEFT_ALIGNMENT);
}
/**
* Creates a <code>JLabel</code> instance with the specified
* text and horizontal alignment.
* The label is centered vertically in its display area.
*
* @param text The text to be displayed by the label.
* @param horizontalAlignment One of the following constants
* defined in <code>SwingConstants</code>:
* <code>LEFT</code>,
* <code>CENTER</code>,
* <code>RIGHT</code>,
* <code>LEADING</code> or
* <code>TRAILING</code>.
*/
public
JLabel(
String text, int
horizontalAlignment) {
this(
text, null,
horizontalAlignment);
}
/**
* Creates a <code>JLabel</code> instance with the specified text.
* The label is aligned against the leading edge of its display area,
* and centered vertically.
*
* @param text The text to be displayed by the label.
*/
public
JLabel(
String text) {
this(
text, null,
LEADING);
}
/**
* Creates a <code>JLabel</code> instance with the specified
* image and horizontal alignment.
* The label is centered vertically in its display area.
*
* @param image The image to be displayed by the label.
* @param horizontalAlignment One of the following constants
* defined in <code>SwingConstants</code>:
* <code>LEFT</code>,
* <code>CENTER</code>,
* <code>RIGHT</code>,
* <code>LEADING</code> or
* <code>TRAILING</code>.
*/
public
JLabel(
Icon image, int
horizontalAlignment) {
this(null,
image,
horizontalAlignment);
}
/**
* Creates a <code>JLabel</code> instance with the specified image.
* The label is centered vertically and horizontally
* in its display area.
*
* @param image The image to be displayed by the label.
*/
public
JLabel(
Icon image) {
this(null,
image,
CENTER);
}
/**
* Creates a <code>JLabel</code> instance with
* no image and with an empty string for the title.
* The label is centered vertically
* in its display area.
* The label's contents, once set, will be displayed on the leading edge
* of the label's display area.
*/
public
JLabel() {
this("", null,
LEADING);
}
/**
* Returns the L&F object that renders this component.
*
* @return LabelUI object
*/
public
LabelUI getUI() {
return (
LabelUI)
ui;
}
/**
* Sets the L&F object that renders this component.
*
* @param ui the LabelUI L&F object
* @see UIDefaults#getUI
* @beaninfo
* bound: true
* hidden: true
* attribute: visualUpdate true
* description: The UI object that implements the Component's LookAndFeel.
*/
public void
setUI(
LabelUI ui) {
super.setUI(
ui);
// disabled icon is generated by LF so it should be unset here
if (!
disabledIconSet &&
disabledIcon != null) {
setDisabledIcon(null);
}
}
/**
* Resets the UI property to a value from the current look and feel.
*
* @see JComponent#updateUI
*/
public void
updateUI() {
setUI((
LabelUI)
UIManager.
getUI(this));
}
/**
* Returns a string that specifies the name of the l&f class
* that renders this component.
*
* @return String "LabelUI"
*
* @see JComponent#getUIClassID
* @see UIDefaults#getUI
*/
public
String getUIClassID() {
return
uiClassID;
}
/**
* Returns the text string that the label displays.
*
* @return a String
* @see #setText
*/
public
String getText() {
return
text;
}
/**
* Defines the single line of text this component will display. If
* the value of text is null or empty string, nothing is displayed.
* <p>
* The default value of this property is null.
* <p>
* This is a JavaBeans bound property.
*
* @see #setVerticalTextPosition
* @see #setHorizontalTextPosition
* @see #setIcon
* @beaninfo
* preferred: true
* bound: true
* attribute: visualUpdate true
* description: Defines the single line of text this component will display.
*/
public void
setText(
String text) {
String oldAccessibleName = null;
if (
accessibleContext != null) {
oldAccessibleName =
accessibleContext.
getAccessibleName();
}
String oldValue = this.
text;
this.
text =
text;
firePropertyChange("text",
oldValue,
text);
setDisplayedMnemonicIndex(
SwingUtilities.
findDisplayedMnemonicIndex(
text,
getDisplayedMnemonic()));
if ((
accessibleContext != null)
&& (
accessibleContext.
getAccessibleName() !=
oldAccessibleName)) {
accessibleContext.
firePropertyChange(
AccessibleContext.
ACCESSIBLE_VISIBLE_DATA_PROPERTY,
oldAccessibleName,
accessibleContext.
getAccessibleName());
}
if (
text == null ||
oldValue == null || !
text.
equals(
oldValue)) {
revalidate();
repaint();
}
}
/**
* Returns the graphic image (glyph, icon) that the label displays.
*
* @return an Icon
* @see #setIcon
*/
public
Icon getIcon() {
return
defaultIcon;
}
/**
* Defines the icon this component will display. If
* the value of icon is null, nothing is displayed.
* <p>
* The default value of this property is null.
* <p>
* This is a JavaBeans bound property.
*
* @see #setVerticalTextPosition
* @see #setHorizontalTextPosition
* @see #getIcon
* @beaninfo
* preferred: true
* bound: true
* attribute: visualUpdate true
* description: The icon this component will display.
*/
public void
setIcon(
Icon icon) {
Icon oldValue =
defaultIcon;
defaultIcon =
icon;
/* If the default icon has really changed and we had
* generated the disabled icon for this component
* (in other words, setDisabledIcon() was never called), then
* clear the disabledIcon field.
*/
if ((
defaultIcon !=
oldValue) && !
disabledIconSet) {
disabledIcon = null;
}
firePropertyChange("icon",
oldValue,
defaultIcon);
if ((
accessibleContext != null) && (
oldValue !=
defaultIcon)) {
accessibleContext.
firePropertyChange(
AccessibleContext.
ACCESSIBLE_VISIBLE_DATA_PROPERTY,
oldValue,
defaultIcon);
}
/* If the default icon has changed and the new one is
* a different size, then revalidate. Repaint if the
* default icon has changed.
*/
if (
defaultIcon !=
oldValue) {
if ((
defaultIcon == null) ||
(
oldValue == null) ||
(
defaultIcon.
getIconWidth() !=
oldValue.
getIconWidth()) ||
(
defaultIcon.
getIconHeight() !=
oldValue.
getIconHeight())) {
revalidate();
}
repaint();
}
}
/**
* Returns the icon used by the label when it's disabled.
* If no disabled icon has been set this will forward the call to
* the look and feel to construct an appropriate disabled Icon.
* <p>
* Some look and feels might not render the disabled Icon, in which
* case they will ignore this.
*
* @return the <code>disabledIcon</code> property
* @see #setDisabledIcon
* @see javax.swing.LookAndFeel#getDisabledIcon
* @see ImageIcon
*/
@
Transient
public
Icon getDisabledIcon() {
if (!
disabledIconSet &&
disabledIcon == null &&
defaultIcon != null) {
disabledIcon =
UIManager.
getLookAndFeel().
getDisabledIcon(this,
defaultIcon);
if (
disabledIcon != null) {
firePropertyChange("disabledIcon", null,
disabledIcon);
}
}
return
disabledIcon;
}
/**
* Set the icon to be displayed if this JLabel is "disabled"
* (JLabel.setEnabled(false)).
* <p>
* The default value of this property is null.
*
* @param disabledIcon the Icon to display when the component is disabled
* @see #getDisabledIcon
* @see #setEnabled
* @beaninfo
* bound: true
* attribute: visualUpdate true
* description: The icon to display if the label is disabled.
*/
public void
setDisabledIcon(
Icon disabledIcon) {
Icon oldValue = this.
disabledIcon;
this.
disabledIcon =
disabledIcon;
disabledIconSet = (
disabledIcon != null);
firePropertyChange("disabledIcon",
oldValue,
disabledIcon);
if (
disabledIcon !=
oldValue) {
if (
disabledIcon == null ||
oldValue == null ||
disabledIcon.
getIconWidth() !=
oldValue.
getIconWidth() ||
disabledIcon.
getIconHeight() !=
oldValue.
getIconHeight()) {
revalidate();
}
if (!
isEnabled()) {
repaint();
}
}
}
/**
* Specify a keycode that indicates a mnemonic key.
* This property is used when the label is part of a larger component.
* If the labelFor property of the label is not null, the label will
* call the requestFocus method of the component specified by the
* labelFor property when the mnemonic is activated.
*
* @see #getLabelFor
* @see #setLabelFor
* @beaninfo
* bound: true
* attribute: visualUpdate true
* description: The mnemonic keycode.
*/
public void
setDisplayedMnemonic(int
key) {
int
oldKey =
mnemonic;
mnemonic =
key;
firePropertyChange("displayedMnemonic",
oldKey,
mnemonic);
setDisplayedMnemonicIndex(
SwingUtilities.
findDisplayedMnemonicIndex(
getText(),
mnemonic));
if (
key !=
oldKey) {
revalidate();
repaint();
}
}
/**
* Specifies the displayedMnemonic as a char value.
*
* @param aChar a char specifying the mnemonic to display
* @see #setDisplayedMnemonic(int)
*/
public void
setDisplayedMnemonic(char
aChar) {
int
vk = java.awt.event.
KeyEvent.
getExtendedKeyCodeForChar(
aChar);
if (
vk != java.awt.event.
KeyEvent.
VK_UNDEFINED) {
setDisplayedMnemonic(
vk);
}
}
/**
* Return the keycode that indicates a mnemonic key.
* This property is used when the label is part of a larger component.
* If the labelFor property of the label is not null, the label will
* call the requestFocus method of the component specified by the
* labelFor property when the mnemonic is activated.
*
* @return int value for the mnemonic key
*
* @see #getLabelFor
* @see #setLabelFor
*/
public int
getDisplayedMnemonic() {
return
mnemonic;
}
/**
* Provides a hint to the look and feel as to which character in the
* text should be decorated to represent the mnemonic. Not all look and
* feels may support this. A value of -1 indicates either there is no
* mnemonic, the mnemonic character is not contained in the string, or
* the developer does not wish the mnemonic to be displayed.
* <p>
* The value of this is updated as the properties relating to the
* mnemonic change (such as the mnemonic itself, the text...).
* You should only ever have to call this if
* you do not wish the default character to be underlined. For example, if
* the text was 'Save As', with a mnemonic of 'a', and you wanted the 'A'
* to be decorated, as 'Save <u>A</u>s', you would have to invoke
* <code>setDisplayedMnemonicIndex(5)</code> after invoking
* <code>setDisplayedMnemonic(KeyEvent.VK_A)</code>.
*
* @since 1.4
* @param index Index into the String to underline
* @exception IllegalArgumentException will be thrown if <code>index</code>
* is >= length of the text, or < -1
*
* @beaninfo
* bound: true
* attribute: visualUpdate true
* description: the index into the String to draw the keyboard character
* mnemonic at
*/
public void
setDisplayedMnemonicIndex(int
index)
throws
IllegalArgumentException {
int
oldValue =
mnemonicIndex;
if (
index == -1) {
mnemonicIndex = -1;
} else {
String text =
getText();
int
textLength = (
text == null) ? 0 :
text.
length();
if (
index < -1 ||
index >=
textLength) { // index out of range
throw new
IllegalArgumentException("index == " +
index);
}
}
mnemonicIndex =
index;
firePropertyChange("displayedMnemonicIndex",
oldValue,
index);
if (
index !=
oldValue) {
revalidate();
repaint();
}
}
/**
* Returns the character, as an index, that the look and feel should
* provide decoration for as representing the mnemonic character.
*
* @since 1.4
* @return index representing mnemonic character
* @see #setDisplayedMnemonicIndex
*/
public int
getDisplayedMnemonicIndex() {
return
mnemonicIndex;
}
/**
* Verify that key is a legal value for the horizontalAlignment properties.
*
* @param key the property value to check
* @param message the IllegalArgumentException detail message
* @exception IllegalArgumentException if key isn't LEFT, CENTER, RIGHT,
* LEADING or TRAILING.
* @see #setHorizontalTextPosition
* @see #setHorizontalAlignment
*/
protected int
checkHorizontalKey(int
key,
String message) {
if ((
key ==
LEFT) ||
(
key ==
CENTER) ||
(
key ==
RIGHT) ||
(
key ==
LEADING) ||
(
key ==
TRAILING)) {
return
key;
}
else {
throw new
IllegalArgumentException(
message);
}
}
/**
* Verify that key is a legal value for the
* verticalAlignment or verticalTextPosition properties.
*
* @param key the property value to check
* @param message the IllegalArgumentException detail message
* @exception IllegalArgumentException if key isn't TOP, CENTER, or BOTTOM.
* @see #setVerticalAlignment
* @see #setVerticalTextPosition
*/
protected int
checkVerticalKey(int
key,
String message) {
if ((
key ==
TOP) || (
key ==
CENTER) || (
key ==
BOTTOM)) {
return
key;
}
else {
throw new
IllegalArgumentException(
message);
}
}
/**
* Returns the amount of space between the text and the icon
* displayed in this label.
*
* @return an int equal to the number of pixels between the text
* and the icon.
* @see #setIconTextGap
*/
public int
getIconTextGap() {
return
iconTextGap;
}
/**
* If both the icon and text properties are set, this property
* defines the space between them.
* <p>
* The default value of this property is 4 pixels.
* <p>
* This is a JavaBeans bound property.
*
* @see #getIconTextGap
* @beaninfo
* bound: true
* attribute: visualUpdate true
* description: If both the icon and text properties are set, this
* property defines the space between them.
*/
public void
setIconTextGap(int
iconTextGap) {
int
oldValue = this.
iconTextGap;
this.
iconTextGap =
iconTextGap;
firePropertyChange("iconTextGap",
oldValue,
iconTextGap);
if (
iconTextGap !=
oldValue) {
revalidate();
repaint();
}
}
/**
* Returns the alignment of the label's contents along the Y axis.
*
* @return The value of the verticalAlignment property, one of the
* following constants defined in <code>SwingConstants</code>:
* <code>TOP</code>,
* <code>CENTER</code>, or
* <code>BOTTOM</code>.
*
* @see SwingConstants
* @see #setVerticalAlignment
*/
public int
getVerticalAlignment() {
return
verticalAlignment;
}
/**
* Sets the alignment of the label's contents along the Y axis.
* <p>
* The default value of this property is CENTER.
*
* @param alignment One of the following constants
* defined in <code>SwingConstants</code>:
* <code>TOP</code>,
* <code>CENTER</code> (the default), or
* <code>BOTTOM</code>.
*
* @see SwingConstants
* @see #getVerticalAlignment
* @beaninfo
* bound: true
* enum: TOP SwingConstants.TOP
* CENTER SwingConstants.CENTER
* BOTTOM SwingConstants.BOTTOM
* attribute: visualUpdate true
* description: The alignment of the label's contents along the Y axis.
*/
public void
setVerticalAlignment(int
alignment) {
if (
alignment ==
verticalAlignment) return;
int
oldValue =
verticalAlignment;
verticalAlignment =
checkVerticalKey(
alignment, "verticalAlignment");
firePropertyChange("verticalAlignment",
oldValue,
verticalAlignment);
repaint();
}
/**
* Returns the alignment of the label's contents along the X axis.
*
* @return The value of the horizontalAlignment property, one of the
* following constants defined in <code>SwingConstants</code>:
* <code>LEFT</code>,
* <code>CENTER</code>,
* <code>RIGHT</code>,
* <code>LEADING</code> or
* <code>TRAILING</code>.
*
* @see #setHorizontalAlignment
* @see SwingConstants
*/
public int
getHorizontalAlignment() {
return
horizontalAlignment;
}
/**
* Sets the alignment of the label's contents along the X axis.
* <p>
* This is a JavaBeans bound property.
*
* @param alignment One of the following constants
* defined in <code>SwingConstants</code>:
* <code>LEFT</code>,
* <code>CENTER</code> (the default for image-only labels),
* <code>RIGHT</code>,
* <code>LEADING</code> (the default for text-only labels) or
* <code>TRAILING</code>.
*
* @see SwingConstants
* @see #getHorizontalAlignment
* @beaninfo
* bound: true
* enum: LEFT SwingConstants.LEFT
* CENTER SwingConstants.CENTER
* RIGHT SwingConstants.RIGHT
* LEADING SwingConstants.LEADING
* TRAILING SwingConstants.TRAILING
* attribute: visualUpdate true
* description: The alignment of the label's content along the X axis.
*/
public void
setHorizontalAlignment(int
alignment) {
if (
alignment ==
horizontalAlignment) return;
int
oldValue =
horizontalAlignment;
horizontalAlignment =
checkHorizontalKey(
alignment,
"horizontalAlignment");
firePropertyChange("horizontalAlignment",
oldValue,
horizontalAlignment);
repaint();
}
/**
* Returns the vertical position of the label's text,
* relative to its image.
*
* @return One of the following constants
* defined in <code>SwingConstants</code>:
* <code>TOP</code>,
* <code>CENTER</code>, or
* <code>BOTTOM</code>.
*
* @see #setVerticalTextPosition
* @see SwingConstants
*/
public int
getVerticalTextPosition() {
return
verticalTextPosition;
}
/**
* Sets the vertical position of the label's text,
* relative to its image.
* <p>
* The default value of this property is CENTER.
* <p>
* This is a JavaBeans bound property.
*
* @param textPosition One of the following constants
* defined in <code>SwingConstants</code>:
* <code>TOP</code>,
* <code>CENTER</code> (the default), or
* <code>BOTTOM</code>.
*
* @see SwingConstants
* @see #getVerticalTextPosition
* @beaninfo
* bound: true
* enum: TOP SwingConstants.TOP
* CENTER SwingConstants.CENTER
* BOTTOM SwingConstants.BOTTOM
* expert: true
* attribute: visualUpdate true
* description: The vertical position of the text relative to it's image.
*/
public void
setVerticalTextPosition(int
textPosition) {
if (
textPosition ==
verticalTextPosition) return;
int
old =
verticalTextPosition;
verticalTextPosition =
checkVerticalKey(
textPosition,
"verticalTextPosition");
firePropertyChange("verticalTextPosition",
old,
verticalTextPosition);
revalidate();
repaint();
}
/**
* Returns the horizontal position of the label's text,
* relative to its image.
*
* @return One of the following constants
* defined in <code>SwingConstants</code>:
* <code>LEFT</code>,
* <code>CENTER</code>,
* <code>RIGHT</code>,
* <code>LEADING</code> or
* <code>TRAILING</code>.
*
* @see SwingConstants
*/
public int
getHorizontalTextPosition() {
return
horizontalTextPosition;
}
/**
* Sets the horizontal position of the label's text,
* relative to its image.
*
* @param textPosition One of the following constants
* defined in <code>SwingConstants</code>:
* <code>LEFT</code>,
* <code>CENTER</code>,
* <code>RIGHT</code>,
* <code>LEADING</code>, or
* <code>TRAILING</code> (the default).
* @exception IllegalArgumentException
*
* @see SwingConstants
* @beaninfo
* expert: true
* bound: true
* enum: LEFT SwingConstants.LEFT
* CENTER SwingConstants.CENTER
* RIGHT SwingConstants.RIGHT
* LEADING SwingConstants.LEADING
* TRAILING SwingConstants.TRAILING
* attribute: visualUpdate true
* description: The horizontal position of the label's text,
* relative to its image.
*/
public void
setHorizontalTextPosition(int
textPosition) {
int
old =
horizontalTextPosition;
this.
horizontalTextPosition =
checkHorizontalKey(
textPosition,
"horizontalTextPosition");
firePropertyChange("horizontalTextPosition",
old,
horizontalTextPosition);
revalidate();
repaint();
}
/**
* This is overridden to return false if the current Icon's Image is
* not equal to the passed in Image <code>img</code>.
*
* @see java.awt.image.ImageObserver
* @see java.awt.Component#imageUpdate(java.awt.Image, int, int, int, int, int)
*/
public boolean
imageUpdate(
Image img, int
infoflags,
int
x, int
y, int
w, int
h) {
// Don't use getDisabledIcon, will trigger creation of icon if icon
// not set.
if (!
isShowing() ||
!
SwingUtilities.
doesIconReferenceImage(
getIcon(),
img) &&
!
SwingUtilities.
doesIconReferenceImage(
disabledIcon,
img)) {
return false;
}
return super.imageUpdate(
img,
infoflags,
x,
y,
w,
h);
}
/**
* See readObject() and writeObject() in JComponent for more
* information about serialization in Swing.
*/
private void
writeObject(
ObjectOutputStream s) throws
IOException {
s.
defaultWriteObject();
if (
getUIClassID().
equals(
uiClassID)) {
byte
count =
JComponent.
getWriteObjCounter(this);
JComponent.
setWriteObjCounter(this, --
count);
if (
count == 0 &&
ui != null) {
ui.
installUI(this);
}
}
}
/**
* Returns a string representation of this JLabel. This method
* is intended to be used only for debugging purposes, and the
* content and format of the returned string may vary between
* implementations. The returned string may be empty but may not
* be <code>null</code>.
*
* @return a string representation of this JLabel.
*/
protected
String paramString() {
String textString = (
text != null ?
text : "");
String defaultIconString = ((
defaultIcon != null)
&& (
defaultIcon != this) ?
defaultIcon.
toString() : "");
String disabledIconString = ((
disabledIcon != null)
&& (
disabledIcon != this) ?
disabledIcon.
toString() : "");
String labelForString = (
labelFor != null ?
labelFor.
toString() : "");
String verticalAlignmentString;
if (
verticalAlignment ==
TOP) {
verticalAlignmentString = "TOP";
} else if (
verticalAlignment ==
CENTER) {
verticalAlignmentString = "CENTER";
} else if (
verticalAlignment ==
BOTTOM) {
verticalAlignmentString = "BOTTOM";
} else
verticalAlignmentString = "";
String horizontalAlignmentString;
if (
horizontalAlignment ==
LEFT) {
horizontalAlignmentString = "LEFT";
} else if (
horizontalAlignment ==
CENTER) {
horizontalAlignmentString = "CENTER";
} else if (
horizontalAlignment ==
RIGHT) {
horizontalAlignmentString = "RIGHT";
} else if (
horizontalAlignment ==
LEADING) {
horizontalAlignmentString = "LEADING";
} else if (
horizontalAlignment ==
TRAILING) {
horizontalAlignmentString = "TRAILING";
} else
horizontalAlignmentString = "";
String verticalTextPositionString;
if (
verticalTextPosition ==
TOP) {
verticalTextPositionString = "TOP";
} else if (
verticalTextPosition ==
CENTER) {
verticalTextPositionString = "CENTER";
} else if (
verticalTextPosition ==
BOTTOM) {
verticalTextPositionString = "BOTTOM";
} else
verticalTextPositionString = "";
String horizontalTextPositionString;
if (
horizontalTextPosition ==
LEFT) {
horizontalTextPositionString = "LEFT";
} else if (
horizontalTextPosition ==
CENTER) {
horizontalTextPositionString = "CENTER";
} else if (
horizontalTextPosition ==
RIGHT) {
horizontalTextPositionString = "RIGHT";
} else if (
horizontalTextPosition ==
LEADING) {
horizontalTextPositionString = "LEADING";
} else if (
horizontalTextPosition ==
TRAILING) {
horizontalTextPositionString = "TRAILING";
} else
horizontalTextPositionString = "";
return super.paramString() +
",defaultIcon=" +
defaultIconString +
",disabledIcon=" +
disabledIconString +
",horizontalAlignment=" +
horizontalAlignmentString +
",horizontalTextPosition=" +
horizontalTextPositionString +
",iconTextGap=" +
iconTextGap +
",labelFor=" +
labelForString +
",text=" +
textString +
",verticalAlignment=" +
verticalAlignmentString +
",verticalTextPosition=" +
verticalTextPositionString;
}
/**
* --- Accessibility Support ---
*/
/**
* Get the component this is labelling.
*
* @return the Component this is labelling. Can be null if this
* does not label a Component. If the displayedMnemonic
* property is set and the labelFor property is also set, the label
* will call the requestFocus method of the component specified by the
* labelFor property when the mnemonic is activated.
*
* @see #getDisplayedMnemonic
* @see #setDisplayedMnemonic
*/
public
Component getLabelFor() {
return
labelFor;
}
/**
* Set the component this is labelling. Can be null if this does not
* label a Component. If the displayedMnemonic property is set
* and the labelFor property is also set, the label will
* call the requestFocus method of the component specified by the
* labelFor property when the mnemonic is activated.
*
* @param c the Component this label is for, or null if the label is
* not the label for a component
*
* @see #getDisplayedMnemonic
* @see #setDisplayedMnemonic
*
* @beaninfo
* bound: true
* description: The component this is labelling.
*/
public void
setLabelFor(
Component c) {
Component oldC =
labelFor;
labelFor =
c;
firePropertyChange("labelFor",
oldC,
c);
if (
oldC instanceof
JComponent) {
((
JComponent)
oldC).
putClientProperty(
LABELED_BY_PROPERTY, null);
}
if (
c instanceof
JComponent) {
((
JComponent)
c).
putClientProperty(
LABELED_BY_PROPERTY, this);
}
}
/**
* Get the AccessibleContext of this object
*
* @return the AccessibleContext of this object
* @beaninfo
* expert: true
* description: The AccessibleContext associated with this Label.
*/
public
AccessibleContext getAccessibleContext() {
if (
accessibleContext == null) {
accessibleContext = new
AccessibleJLabel();
}
return
accessibleContext;
}
/**
* The class used to obtain the accessible role for this object.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing. As of 1.4, support for long term storage
* of all JavaBeans™
* has been added to the <code>java.beans</code> package.
* Please see {@link java.beans.XMLEncoder}.
*/
@
SuppressWarnings("serial")
protected class
AccessibleJLabel extends
AccessibleJComponent
implements
AccessibleText,
AccessibleExtendedComponent {
/**
* Get the accessible name of this object.
*
* @return the localized name of the object -- can be null if this
* object does not have a name
* @see AccessibleContext#setAccessibleName
*/
public
String getAccessibleName() {
String name =
accessibleName;
if (
name == null) {
name = (
String)
getClientProperty(
AccessibleContext.
ACCESSIBLE_NAME_PROPERTY);
}
if (
name == null) {
name =
JLabel.this.
getText();
}
if (
name == null) {
name = super.getAccessibleName();
}
return
name;
}
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
* @see AccessibleRole
*/
public
AccessibleRole getAccessibleRole() {
return
AccessibleRole.
LABEL;
}
/**
* Get the AccessibleIcons associated with this object if one
* or more exist. Otherwise return null.
* @since 1.3
*/
public
AccessibleIcon []
getAccessibleIcon() {
Icon icon =
getIcon();
if (
icon instanceof
Accessible) {
AccessibleContext ac =
((
Accessible)
icon).
getAccessibleContext();
if (
ac != null &&
ac instanceof
AccessibleIcon) {
return new
AccessibleIcon[] { (
AccessibleIcon)
ac };
}
}
return null;
}
/**
* Get the AccessibleRelationSet associated with this object if one
* exists. Otherwise return null.
* @see AccessibleRelation
* @since 1.3
*/
public
AccessibleRelationSet getAccessibleRelationSet() {
// Check where the AccessibleContext's relation
// set already contains a LABEL_FOR relation.
AccessibleRelationSet relationSet
= super.getAccessibleRelationSet();
if (!
relationSet.
contains(
AccessibleRelation.
LABEL_FOR)) {
Component c =
JLabel.this.
getLabelFor();
if (
c != null) {
AccessibleRelation relation
= new
AccessibleRelation(
AccessibleRelation.
LABEL_FOR);
relation.
setTarget(
c);
relationSet.
add(
relation);
}
}
return
relationSet;
}
/* AccessibleText ---------- */
public
AccessibleText getAccessibleText() {
View view = (
View)
JLabel.this.
getClientProperty("html");
if (
view != null) {
return this;
} else {
return null;
}
}
/**
* Given a point in local coordinates, return the zero-based index
* of the character under that Point. If the point is invalid,
* this method returns -1.
*
* @param p the Point in local coordinates
* @return the zero-based index of the character under Point p; if
* Point is invalid returns -1.
* @since 1.3
*/
public int
getIndexAtPoint(
Point p) {
View view = (
View)
JLabel.this.
getClientProperty("html");
if (
view != null) {
Rectangle r =
getTextRectangle();
if (
r == null) {
return -1;
}
Rectangle2D.
Float shape =
new
Rectangle2D.
Float(
r.
x,
r.
y,
r.
width,
r.
height);
Position.
Bias bias[] = new
Position.
Bias[1];
return
view.
viewToModel(
p.
x,
p.
y,
shape,
bias);
} else {
return -1;
}
}
/**
* Returns the bounding box of the character at the given
* index in the string. The bounds are returned in local
* coordinates. If the index is invalid, <code>null</code> is returned.
*
* @param i the index into the String
* @return the screen coordinates of the character's bounding box.
* If the index is invalid, <code>null</code> is returned.
* @since 1.3
*/
public
Rectangle getCharacterBounds(int
i) {
View view = (
View)
JLabel.this.
getClientProperty("html");
if (
view != null) {
Rectangle r =
getTextRectangle();
if (
r == null) {
return null;
}
Rectangle2D.
Float shape =
new
Rectangle2D.
Float(
r.
x,
r.
y,
r.
width,
r.
height);
try {
Shape charShape =
view.
modelToView(
i,
shape,
Position.
Bias.
Forward);
return
charShape.
getBounds();
} catch (
BadLocationException e) {
return null;
}
} else {
return null;
}
}
/**
* Return the number of characters (valid indicies)
*
* @return the number of characters
* @since 1.3
*/
public int
getCharCount() {
View view = (
View)
JLabel.this.
getClientProperty("html");
if (
view != null) {
Document d =
view.
getDocument();
if (
d instanceof
StyledDocument) {
StyledDocument doc = (
StyledDocument)
d;
return
doc.
getLength();
}
}
return
accessibleContext.
getAccessibleName().
length();
}
/**
* Return the zero-based offset of the caret.
*
* Note: That to the right of the caret will have the same index
* value as the offset (the caret is between two characters).
* @return the zero-based offset of the caret.
* @since 1.3
*/
public int
getCaretPosition() {
// There is no caret.
return -1;
}
/**
* Returns the String at a given index.
*
* @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
* or AccessibleText.SENTENCE to retrieve
* @param index an index within the text >= 0
* @return the letter, word, or sentence,
* null for an invalid index or part
* @since 1.3
*/
public
String getAtIndex(int
part, int
index) {
if (
index < 0 ||
index >=
getCharCount()) {
return null;
}
switch (
part) {
case
AccessibleText.
CHARACTER:
try {
return
getText(
index, 1);
} catch (
BadLocationException e) {
return null;
}
case
AccessibleText.
WORD:
try {
String s =
getText(0,
getCharCount());
BreakIterator words =
BreakIterator.
getWordInstance(
getLocale());
words.
setText(
s);
int
end =
words.
following(
index);
return
s.
substring(
words.
previous(),
end);
} catch (
BadLocationException e) {
return null;
}
case
AccessibleText.
SENTENCE:
try {
String s =
getText(0,
getCharCount());
BreakIterator sentence =
BreakIterator.
getSentenceInstance(
getLocale());
sentence.
setText(
s);
int
end =
sentence.
following(
index);
return
s.
substring(
sentence.
previous(),
end);
} catch (
BadLocationException e) {
return null;
}
default:
return null;
}
}
/**
* Returns the String after a given index.
*
* @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
* or AccessibleText.SENTENCE to retrieve
* @param index an index within the text >= 0
* @return the letter, word, or sentence, null for an invalid
* index or part
* @since 1.3
*/
public
String getAfterIndex(int
part, int
index) {
if (
index < 0 ||
index >=
getCharCount()) {
return null;
}
switch (
part) {
case
AccessibleText.
CHARACTER:
if (
index+1 >=
getCharCount()) {
return null;
}
try {
return
getText(
index+1, 1);
} catch (
BadLocationException e) {
return null;
}
case
AccessibleText.
WORD:
try {
String s =
getText(0,
getCharCount());
BreakIterator words =
BreakIterator.
getWordInstance(
getLocale());
words.
setText(
s);
int
start =
words.
following(
index);
if (
start ==
BreakIterator.
DONE ||
start >=
s.
length()) {
return null;
}
int
end =
words.
following(
start);
if (
end ==
BreakIterator.
DONE ||
end >=
s.
length()) {
return null;
}
return
s.
substring(
start,
end);
} catch (
BadLocationException e) {
return null;
}
case
AccessibleText.
SENTENCE:
try {
String s =
getText(0,
getCharCount());
BreakIterator sentence =
BreakIterator.
getSentenceInstance(
getLocale());
sentence.
setText(
s);
int
start =
sentence.
following(
index);
if (
start ==
BreakIterator.
DONE ||
start >
s.
length()) {
return null;
}
int
end =
sentence.
following(
start);
if (
end ==
BreakIterator.
DONE ||
end >
s.
length()) {
return null;
}
return
s.
substring(
start,
end);
} catch (
BadLocationException e) {
return null;
}
default:
return null;
}
}
/**
* Returns the String before a given index.
*
* @param part the AccessibleText.CHARACTER, AccessibleText.WORD,
* or AccessibleText.SENTENCE to retrieve
* @param index an index within the text >= 0
* @return the letter, word, or sentence, null for an invalid index
* or part
* @since 1.3
*/
public
String getBeforeIndex(int
part, int
index) {
if (
index < 0 ||
index >
getCharCount()-1) {
return null;
}
switch (
part) {
case
AccessibleText.
CHARACTER:
if (
index == 0) {
return null;
}
try {
return
getText(
index-1, 1);
} catch (
BadLocationException e) {
return null;
}
case
AccessibleText.
WORD:
try {
String s =
getText(0,
getCharCount());
BreakIterator words =
BreakIterator.
getWordInstance(
getLocale());
words.
setText(
s);
int
end =
words.
following(
index);
end =
words.
previous();
int
start =
words.
previous();
if (
start ==
BreakIterator.
DONE) {
return null;
}
return
s.
substring(
start,
end);
} catch (
BadLocationException e) {
return null;
}
case
AccessibleText.
SENTENCE:
try {
String s =
getText(0,
getCharCount());
BreakIterator sentence =
BreakIterator.
getSentenceInstance(
getLocale());
sentence.
setText(
s);
int
end =
sentence.
following(
index);
end =
sentence.
previous();
int
start =
sentence.
previous();
if (
start ==
BreakIterator.
DONE) {
return null;
}
return
s.
substring(
start,
end);
} catch (
BadLocationException e) {
return null;
}
default:
return null;
}
}
/**
* Return the AttributeSet for a given character at a given index
*
* @param i the zero-based index into the text
* @return the AttributeSet of the character
* @since 1.3
*/
public
AttributeSet getCharacterAttribute(int
i) {
View view = (
View)
JLabel.this.
getClientProperty("html");
if (
view != null) {
Document d =
view.
getDocument();
if (
d instanceof
StyledDocument) {
StyledDocument doc = (
StyledDocument)
d;
Element elem =
doc.
getCharacterElement(
i);
if (
elem != null) {
return
elem.
getAttributes();
}
}
}
return null;
}
/**
* Returns the start offset within the selected text.
* If there is no selection, but there is
* a caret, the start and end offsets will be the same.
*
* @return the index into the text of the start of the selection
* @since 1.3
*/
public int
getSelectionStart() {
// Text cannot be selected.
return -1;
}
/**
* Returns the end offset within the selected text.
* If there is no selection, but there is
* a caret, the start and end offsets will be the same.
*
* @return the index into the text of the end of the selection
* @since 1.3
*/
public int
getSelectionEnd() {
// Text cannot be selected.
return -1;
}
/**
* Returns the portion of the text that is selected.
*
* @return the String portion of the text that is selected
* @since 1.3
*/
public
String getSelectedText() {
// Text cannot be selected.
return null;
}
/*
* Returns the text substring starting at the specified
* offset with the specified length.
*/
private
String getText(int
offset, int
length)
throws
BadLocationException {
View view = (
View)
JLabel.this.
getClientProperty("html");
if (
view != null) {
Document d =
view.
getDocument();
if (
d instanceof
StyledDocument) {
StyledDocument doc = (
StyledDocument)
d;
return
doc.
getText(
offset,
length);
}
}
return null;
}
/*
* Returns the bounding rectangle for the component text.
*/
private
Rectangle getTextRectangle() {
String text =
JLabel.this.
getText();
Icon icon = (
JLabel.this.
isEnabled()) ?
JLabel.this.
getIcon() :
JLabel.this.
getDisabledIcon();
if ((
icon == null) && (
text == null)) {
return null;
}
Rectangle paintIconR = new
Rectangle();
Rectangle paintTextR = new
Rectangle();
Rectangle paintViewR = new
Rectangle();
Insets paintViewInsets = new
Insets(0, 0, 0, 0);
paintViewInsets =
JLabel.this.
getInsets(
paintViewInsets);
paintViewR.
x =
paintViewInsets.
left;
paintViewR.
y =
paintViewInsets.
top;
paintViewR.
width =
JLabel.this.
getWidth() - (
paintViewInsets.
left +
paintViewInsets.
right);
paintViewR.
height =
JLabel.this.
getHeight() - (
paintViewInsets.
top +
paintViewInsets.
bottom);
String clippedText =
SwingUtilities.
layoutCompoundLabel(
(
JComponent)
JLabel.this,
getFontMetrics(
getFont()),
text,
icon,
JLabel.this.
getVerticalAlignment(),
JLabel.this.
getHorizontalAlignment(),
JLabel.this.
getVerticalTextPosition(),
JLabel.this.
getHorizontalTextPosition(),
paintViewR,
paintIconR,
paintTextR,
JLabel.this.
getIconTextGap());
return
paintTextR;
}
// ----- AccessibleExtendedComponent
/**
* Returns the AccessibleExtendedComponent
*
* @return the AccessibleExtendedComponent
*/
AccessibleExtendedComponent getAccessibleExtendedComponent() {
return this;
}
/**
* Returns the tool tip text
*
* @return the tool tip text, if supported, of the object;
* otherwise, null
* @since 1.4
*/
public
String getToolTipText() {
return
JLabel.this.
getToolTipText();
}
/**
* Returns the titled border text
*
* @return the titled border text, if supported, of the object;
* otherwise, null
* @since 1.4
*/
public
String getTitledBorderText() {
return super.getTitledBorderText();
}
/**
* Returns key bindings associated with this object
*
* @return the key bindings, if supported, of the object;
* otherwise, null
* @see AccessibleKeyBinding
* @since 1.4
*/
public
AccessibleKeyBinding getAccessibleKeyBinding() {
int
mnemonic =
JLabel.this.
getDisplayedMnemonic();
if (
mnemonic == 0) {
return null;
}
return new
LabelKeyBinding(
mnemonic);
}
class
LabelKeyBinding implements
AccessibleKeyBinding {
int
mnemonic;
LabelKeyBinding(int
mnemonic) {
this.
mnemonic =
mnemonic;
}
/**
* Returns the number of key bindings for this object
*
* @return the zero-based number of key bindings for this object
*/
public int
getAccessibleKeyBindingCount() {
return 1;
}
/**
* Returns a key binding for this object. The value returned is an
* java.lang.Object which must be cast to appropriate type depending
* on the underlying implementation of the key. For example, if the
* Object returned is a javax.swing.KeyStroke, the user of this
* method should do the following:
* <nf><code>
* Component c = <get the component that has the key bindings>
* AccessibleContext ac = c.getAccessibleContext();
* AccessibleKeyBinding akb = ac.getAccessibleKeyBinding();
* for (int i = 0; i < akb.getAccessibleKeyBindingCount(); i++) {
* Object o = akb.getAccessibleKeyBinding(i);
* if (o instanceof javax.swing.KeyStroke) {
* javax.swing.KeyStroke keyStroke = (javax.swing.KeyStroke)o;
* <do something with the key binding>
* }
* }
* </code></nf>
*
* @param i zero-based index of the key bindings
* @return a javax.lang.Object which specifies the key binding
* @exception IllegalArgumentException if the index is
* out of bounds
* @see #getAccessibleKeyBindingCount
*/
public java.lang.
Object getAccessibleKeyBinding(int
i) {
if (
i != 0) {
throw new
IllegalArgumentException();
}
return
KeyStroke.
getKeyStroke(
mnemonic, 0);
}
}
} // AccessibleJComponent
}