0N/A/*
2362N/A * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage javax.swing.plaf.basic;
0N/A
0N/Aimport sun.swing.SwingUtilities2;
0N/Aimport sun.swing.DefaultLookup;
0N/Aimport sun.swing.UIAction;
1859N/Aimport sun.awt.AppContext;
1859N/A
0N/Aimport javax.swing.*;
0N/Aimport javax.swing.plaf.*;
0N/Aimport javax.swing.text.View;
0N/A
0N/Aimport java.awt.event.ActionEvent;
0N/Aimport java.awt.event.ActionListener;
0N/Aimport java.awt.event.KeyEvent;
0N/Aimport java.awt.Component;
0N/Aimport java.awt.Container;
0N/Aimport java.awt.Dimension;
0N/Aimport java.awt.Rectangle;
0N/Aimport java.awt.Insets;
0N/Aimport java.awt.Color;
0N/Aimport java.awt.Graphics;
0N/Aimport java.awt.Font;
0N/Aimport java.awt.FontMetrics;
0N/Aimport java.beans.PropertyChangeEvent;
0N/Aimport java.beans.PropertyChangeListener;
0N/A
0N/A/**
0N/A * A Windows L&F implementation of LabelUI. This implementation
0N/A * is completely static, i.e. there's only one UIView implementation
0N/A * that's shared by all JLabel objects.
0N/A *
0N/A * @author Hans Muller
0N/A */
0N/Apublic class BasicLabelUI extends LabelUI implements PropertyChangeListener
0N/A{
0N/A /**
0N/A * The default <code>BasicLabelUI</code> instance. This field might
0N/A * not be used. To change the default instance use a subclass which
0N/A * overrides the <code>createUI</code> method, and place that class
0N/A * name in defaults table under the key "LabelUI".
0N/A */
0N/A protected static BasicLabelUI labelUI = new BasicLabelUI();
1859N/A private static final Object BASIC_LABEL_UI_KEY = new Object();
0N/A
613N/A private Rectangle paintIconR = new Rectangle();
613N/A private Rectangle paintTextR = new Rectangle();
613N/A
0N/A static void loadActionMap(LazyActionMap map) {
0N/A map.put(new Actions(Actions.PRESS));
0N/A map.put(new Actions(Actions.RELEASE));
0N/A }
0N/A
0N/A /**
0N/A * Forwards the call to SwingUtilities.layoutCompoundLabel().
0N/A * This method is here so that a subclass could do Label specific
0N/A * layout and to shorten the method name a little.
0N/A *
0N/A * @see SwingUtilities#layoutCompoundLabel
0N/A */
0N/A protected String layoutCL(
0N/A JLabel label,
0N/A FontMetrics fontMetrics,
0N/A String text,
0N/A Icon icon,
0N/A Rectangle viewR,
0N/A Rectangle iconR,
0N/A Rectangle textR)
0N/A {
0N/A return SwingUtilities.layoutCompoundLabel(
0N/A (JComponent) label,
0N/A fontMetrics,
0N/A text,
0N/A icon,
0N/A label.getVerticalAlignment(),
0N/A label.getHorizontalAlignment(),
0N/A label.getVerticalTextPosition(),
0N/A label.getHorizontalTextPosition(),
0N/A viewR,
0N/A iconR,
0N/A textR,
0N/A label.getIconTextGap());
0N/A }
0N/A
0N/A /**
0N/A * Paint clippedText at textX, textY with the labels foreground color.
0N/A *
0N/A * @see #paint
0N/A * @see #paintDisabledText
0N/A */
0N/A protected void paintEnabledText(JLabel l, Graphics g, String s, int textX, int textY)
0N/A {
0N/A int mnemIndex = l.getDisplayedMnemonicIndex();
0N/A g.setColor(l.getForeground());
0N/A SwingUtilities2.drawStringUnderlineCharAt(l, g, s, mnemIndex,
0N/A textX, textY);
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Paint clippedText at textX, textY with background.lighter() and then
0N/A * shifted down and to the right by one pixel with background.darker().
0N/A *
0N/A * @see #paint
0N/A * @see #paintEnabledText
0N/A */
0N/A protected void paintDisabledText(JLabel l, Graphics g, String s, int textX, int textY)
0N/A {
0N/A int accChar = l.getDisplayedMnemonicIndex();
0N/A Color background = l.getBackground();
0N/A g.setColor(background.brighter());
0N/A SwingUtilities2.drawStringUnderlineCharAt(l, g, s, accChar,
0N/A textX + 1, textY + 1);
0N/A g.setColor(background.darker());
0N/A SwingUtilities2.drawStringUnderlineCharAt(l, g, s, accChar,
0N/A textX, textY);
0N/A }
0N/A
0N/A /**
1999N/A * Paints the label text with the foreground color, if the label is opaque
1999N/A * then paints the entire background with the background color. The Label
1999N/A * text is drawn by {@link #paintEnabledText} or {@link #paintDisabledText}.
1999N/A * The locations of the label parts are computed by {@link #layoutCL}.
0N/A *
0N/A * @see #paintEnabledText
0N/A * @see #paintDisabledText
0N/A * @see #layoutCL
0N/A */
0N/A public void paint(Graphics g, JComponent c)
0N/A {
0N/A JLabel label = (JLabel)c;
0N/A String text = label.getText();
0N/A Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon();
0N/A
0N/A if ((icon == null) && (text == null)) {
0N/A return;
0N/A }
0N/A
0N/A FontMetrics fm = SwingUtilities2.getFontMetrics(label, g);
0N/A String clippedText = layout(label, fm, c.getWidth(), c.getHeight());
0N/A
0N/A if (icon != null) {
0N/A icon.paintIcon(c, g, paintIconR.x, paintIconR.y);
0N/A }
0N/A
0N/A if (text != null) {
0N/A View v = (View) c.getClientProperty(BasicHTML.propertyKey);
0N/A if (v != null) {
0N/A v.paint(g, paintTextR);
0N/A } else {
0N/A int textX = paintTextR.x;
0N/A int textY = paintTextR.y + fm.getAscent();
0N/A
0N/A if (label.isEnabled()) {
0N/A paintEnabledText(label, g, clippedText, textX, textY);
0N/A }
0N/A else {
0N/A paintDisabledText(label, g, clippedText, textX, textY);
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A private String layout(JLabel label, FontMetrics fm,
0N/A int width, int height) {
613N/A Insets insets = label.getInsets(null);
0N/A String text = label.getText();
0N/A Icon icon = (label.isEnabled()) ? label.getIcon() :
0N/A label.getDisabledIcon();
613N/A Rectangle paintViewR = new Rectangle();
0N/A paintViewR.x = insets.left;
0N/A paintViewR.y = insets.top;
0N/A paintViewR.width = width - (insets.left + insets.right);
0N/A paintViewR.height = height - (insets.top + insets.bottom);
0N/A paintIconR.x = paintIconR.y = paintIconR.width = paintIconR.height = 0;
0N/A paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 0;
0N/A return layoutCL(label, fm, text, icon, paintViewR, paintIconR,
0N/A paintTextR);
0N/A }
0N/A
0N/A public Dimension getPreferredSize(JComponent c)
0N/A {
0N/A JLabel label = (JLabel)c;
0N/A String text = label.getText();
0N/A Icon icon = (label.isEnabled()) ? label.getIcon() :
0N/A label.getDisabledIcon();
613N/A Insets insets = label.getInsets(null);
0N/A Font font = label.getFont();
0N/A
0N/A int dx = insets.left + insets.right;
0N/A int dy = insets.top + insets.bottom;
0N/A
0N/A if ((icon == null) &&
0N/A ((text == null) ||
0N/A ((text != null) && (font == null)))) {
0N/A return new Dimension(dx, dy);
0N/A }
0N/A else if ((text == null) || ((icon != null) && (font == null))) {
0N/A return new Dimension(icon.getIconWidth() + dx,
0N/A icon.getIconHeight() + dy);
0N/A }
0N/A else {
0N/A FontMetrics fm = label.getFontMetrics(font);
613N/A Rectangle iconR = new Rectangle();
613N/A Rectangle textR = new Rectangle();
613N/A Rectangle viewR = new Rectangle();
0N/A
0N/A iconR.x = iconR.y = iconR.width = iconR.height = 0;
0N/A textR.x = textR.y = textR.width = textR.height = 0;
0N/A viewR.x = dx;
0N/A viewR.y = dy;
0N/A viewR.width = viewR.height = Short.MAX_VALUE;
0N/A
0N/A layoutCL(label, fm, text, icon, viewR, iconR, textR);
0N/A int x1 = Math.min(iconR.x, textR.x);
0N/A int x2 = Math.max(iconR.x + iconR.width, textR.x + textR.width);
0N/A int y1 = Math.min(iconR.y, textR.y);
0N/A int y2 = Math.max(iconR.y + iconR.height, textR.y + textR.height);
0N/A Dimension rv = new Dimension(x2 - x1, y2 - y1);
0N/A
0N/A rv.width += dx;
0N/A rv.height += dy;
0N/A return rv;
0N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * @return getPreferredSize(c)
0N/A */
0N/A public Dimension getMinimumSize(JComponent c) {
0N/A Dimension d = getPreferredSize(c);
0N/A View v = (View) c.getClientProperty(BasicHTML.propertyKey);
0N/A if (v != null) {
0N/A d.width -= v.getPreferredSpan(View.X_AXIS) - v.getMinimumSpan(View.X_AXIS);
0N/A }
0N/A return d;
0N/A }
0N/A
0N/A /**
0N/A * @return getPreferredSize(c)
0N/A */
0N/A public Dimension getMaximumSize(JComponent c) {
0N/A Dimension d = getPreferredSize(c);
0N/A View v = (View) c.getClientProperty(BasicHTML.propertyKey);
0N/A if (v != null) {
0N/A d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS);
0N/A }
0N/A return d;
0N/A }
0N/A
0N/A /**
0N/A * Returns the baseline.
0N/A *
0N/A * @throws NullPointerException {@inheritDoc}
0N/A * @throws IllegalArgumentException {@inheritDoc}
0N/A * @see javax.swing.JComponent#getBaseline(int, int)
0N/A * @since 1.6
0N/A */
0N/A public int getBaseline(JComponent c, int width, int height) {
0N/A super.getBaseline(c, width, height);
0N/A JLabel label = (JLabel)c;
0N/A String text = label.getText();
0N/A if (text == null || "".equals(text) || label.getFont() == null) {
0N/A return -1;
0N/A }
0N/A FontMetrics fm = label.getFontMetrics(label.getFont());
0N/A layout(label, fm, width, height);
0N/A return BasicHTML.getBaseline(label, paintTextR.y, fm.getAscent(),
0N/A paintTextR.width, paintTextR.height);
0N/A }
0N/A
0N/A /**
0N/A * Returns an enum indicating how the baseline of the component
0N/A * changes as the size changes.
0N/A *
0N/A * @throws NullPointerException {@inheritDoc}
0N/A * @see javax.swing.JComponent#getBaseline(int, int)
0N/A * @since 1.6
0N/A */
0N/A public Component.BaselineResizeBehavior getBaselineResizeBehavior(
0N/A JComponent c) {
0N/A super.getBaselineResizeBehavior(c);
0N/A if (c.getClientProperty(BasicHTML.propertyKey) != null) {
0N/A return Component.BaselineResizeBehavior.OTHER;
0N/A }
0N/A switch(((JLabel)c).getVerticalAlignment()) {
0N/A case JLabel.TOP:
0N/A return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
0N/A case JLabel.BOTTOM:
0N/A return Component.BaselineResizeBehavior.CONSTANT_DESCENT;
0N/A case JLabel.CENTER:
0N/A return Component.BaselineResizeBehavior.CENTER_OFFSET;
0N/A }
0N/A return Component.BaselineResizeBehavior.OTHER;
0N/A }
0N/A
0N/A
0N/A public void installUI(JComponent c) {
0N/A installDefaults((JLabel)c);
0N/A installComponents((JLabel)c);
0N/A installListeners((JLabel)c);
0N/A installKeyboardActions((JLabel)c);
0N/A }
0N/A
0N/A
0N/A public void uninstallUI(JComponent c) {
0N/A uninstallDefaults((JLabel)c);
0N/A uninstallComponents((JLabel)c);
0N/A uninstallListeners((JLabel)c);
0N/A uninstallKeyboardActions((JLabel)c);
0N/A }
0N/A
0N/A protected void installDefaults(JLabel c){
0N/A LookAndFeel.installColorsAndFont(c, "Label.background", "Label.foreground", "Label.font");
0N/A LookAndFeel.installProperty(c, "opaque", Boolean.FALSE);
0N/A }
0N/A
0N/A protected void installListeners(JLabel c){
0N/A c.addPropertyChangeListener(this);
0N/A }
0N/A
0N/A protected void installComponents(JLabel c){
0N/A BasicHTML.updateRenderer(c, c.getText());
0N/A c.setInheritsPopupMenu(true);
0N/A }
0N/A
0N/A protected void installKeyboardActions(JLabel l) {
0N/A int dka = l.getDisplayedMnemonic();
0N/A Component lf = l.getLabelFor();
0N/A if ((dka != 0) && (lf != null)) {
0N/A LazyActionMap.installLazyActionMap(l, BasicLabelUI.class,
0N/A "Label.actionMap");
0N/A InputMap inputMap = SwingUtilities.getUIInputMap
0N/A (l, JComponent.WHEN_IN_FOCUSED_WINDOW);
0N/A if (inputMap == null) {
0N/A inputMap = new ComponentInputMapUIResource(l);
0N/A SwingUtilities.replaceUIInputMap(l,
0N/A JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap);
0N/A }
0N/A inputMap.clear();
4639N/A inputMap.put(KeyStroke.getKeyStroke(dka, BasicLookAndFeel.getFocusAcceleratorKeyMask(), false), "press");
0N/A }
0N/A else {
0N/A InputMap inputMap = SwingUtilities.getUIInputMap
0N/A (l, JComponent.WHEN_IN_FOCUSED_WINDOW);
0N/A if (inputMap != null) {
0N/A inputMap.clear();
0N/A }
0N/A }
0N/A }
0N/A
0N/A protected void uninstallDefaults(JLabel c){
0N/A }
0N/A
0N/A protected void uninstallListeners(JLabel c){
0N/A c.removePropertyChangeListener(this);
0N/A }
0N/A
0N/A protected void uninstallComponents(JLabel c){
0N/A BasicHTML.updateRenderer(c, "");
0N/A }
0N/A
0N/A protected void uninstallKeyboardActions(JLabel c) {
0N/A SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, null);
0N/A SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_IN_FOCUSED_WINDOW,
0N/A null);
0N/A SwingUtilities.replaceUIActionMap(c, null);
0N/A }
0N/A
0N/A public static ComponentUI createUI(JComponent c) {
0N/A if (System.getSecurityManager() != null) {
1859N/A AppContext appContext = AppContext.getAppContext();
1859N/A BasicLabelUI safeBasicLabelUI =
1859N/A (BasicLabelUI) appContext.get(BASIC_LABEL_UI_KEY);
1859N/A if (safeBasicLabelUI == null) {
1859N/A safeBasicLabelUI = new BasicLabelUI();
1859N/A appContext.put(BASIC_LABEL_UI_KEY, safeBasicLabelUI);
1859N/A }
1859N/A return safeBasicLabelUI;
0N/A }
1859N/A return labelUI;
0N/A }
0N/A
0N/A public void propertyChange(PropertyChangeEvent e) {
0N/A String name = e.getPropertyName();
0N/A if (name == "text" || "font" == name || "foreground" == name) {
0N/A // remove the old html view client property if one
0N/A // existed, and install a new one if the text installed
0N/A // into the JLabel is html source.
0N/A JLabel lbl = ((JLabel) e.getSource());
0N/A String text = lbl.getText();
0N/A BasicHTML.updateRenderer(lbl, text);
0N/A }
0N/A else if (name == "labelFor" || name == "displayedMnemonic") {
0N/A installKeyboardActions((JLabel) e.getSource());
0N/A }
0N/A }
0N/A
0N/A // When the accelerator is pressed, temporarily make the JLabel
0N/A // focusTraversable by registering a WHEN_FOCUSED action for the
0N/A // release of the accelerator. Then give it focus so it can
0N/A // prevent unwanted keyTyped events from getting to other components.
0N/A private static class Actions extends UIAction {
0N/A private static final String PRESS = "press";
0N/A private static final String RELEASE = "release";
0N/A
0N/A Actions(String key) {
0N/A super(key);
0N/A }
0N/A
0N/A public void actionPerformed(ActionEvent e) {
0N/A JLabel label = (JLabel)e.getSource();
0N/A String key = getName();
0N/A if (key == PRESS) {
0N/A doPress(label);
0N/A }
0N/A else if (key == RELEASE) {
0N/A doRelease(label);
0N/A }
0N/A }
0N/A
0N/A private void doPress(JLabel label) {
0N/A Component labelFor = label.getLabelFor();
0N/A if (labelFor != null && labelFor.isEnabled()) {
0N/A InputMap inputMap = SwingUtilities.getUIInputMap(label, JComponent.WHEN_FOCUSED);
0N/A if (inputMap == null) {
0N/A inputMap = new InputMapUIResource();
0N/A SwingUtilities.replaceUIInputMap(label, JComponent.WHEN_FOCUSED, inputMap);
0N/A }
0N/A int dka = label.getDisplayedMnemonic();
4639N/A inputMap.put(KeyStroke.getKeyStroke(dka, BasicLookAndFeel.getFocusAcceleratorKeyMask(), true), RELEASE);
3959N/A // Need this when the sticky keys are enabled
3959N/A inputMap.put(KeyStroke.getKeyStroke(dka, 0, true), RELEASE);
0N/A // Need this if ALT is released before the accelerator
0N/A inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ALT, 0, true), RELEASE);
0N/A label.requestFocus();
0N/A }
0N/A }
0N/A
0N/A private void doRelease(JLabel label) {
0N/A Component labelFor = label.getLabelFor();
0N/A if (labelFor != null && labelFor.isEnabled()) {
0N/A InputMap inputMap = SwingUtilities.getUIInputMap(label, JComponent.WHEN_FOCUSED);
0N/A if (inputMap != null) {
0N/A // inputMap should never be null.
3959N/A int dka = label.getDisplayedMnemonic();
4639N/A inputMap.remove(KeyStroke.getKeyStroke(dka, BasicLookAndFeel.getFocusAcceleratorKeyMask(), true));
3959N/A inputMap.remove(KeyStroke.getKeyStroke(dka, 0, true));
0N/A inputMap.remove(KeyStroke.getKeyStroke(KeyEvent.VK_ALT, 0, true));
0N/A }
0N/A if (labelFor instanceof Container &&
0N/A ((Container) labelFor).isFocusCycleRoot()) {
0N/A labelFor.requestFocus();
0N/A } else {
0N/A SwingUtilities2.compositeRequestFocus(labelFor);
0N/A }
0N/A }
0N/A }
0N/A }
0N/A}