All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jdesktop.swingx.JXHyperlink Maven / Gradle / Ivy

The newest version!
/*
 * $Id: JXHyperlink.java 4162 2012-02-08 16:21:35Z kschaefe $
 *
 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
 * Santa Clara, California 95054, U.S.A. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package org.jdesktop.swingx;

import java.awt.Color;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URI;

import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.plaf.ButtonUI;

import org.jdesktop.beans.JavaBean;
import org.jdesktop.swingx.hyperlink.AbstractHyperlinkAction;
import org.jdesktop.swingx.hyperlink.HyperlinkAction;
import org.jdesktop.swingx.plaf.HyperlinkAddon;
import org.jdesktop.swingx.plaf.LookAndFeelAddons;

/**
 * A hyperlink component that derives from JButton to provide compatibility
 * mostly for binding actions enabled/disabled behavior accessibility i18n etc...
 * 

* * This button has visual state related to a notion of "clicked": * foreground color is unclickedColor or clickedColor depending on * its boolean bound property clicked being false or true, respectively. * If the hyperlink has an action, it guarantees to synchronize its * "clicked" state to an action value with key LinkAction.VISITED_KEY. * Synchronization happens on setAction() and on propertyChange notification * from the action. JXHyperlink accepts any type of action - * {@link AbstractHyperlinkAction} is a convenience implementation to * simplify clicked control. *

* *

 
 *      LinkAction linkAction = new LinkAction("http://swinglabs.org") {
 *            public void actionPerformed(ActionEvent e) {
 *                doSomething(getTarget());
 *                setVisited(true);
 *            }
 *      };
 *      JXHyperlink hyperlink = new JXHyperlink(linkAction);
 *  
* * The hyperlink can be configured to always update its clicked * property after firing the actionPerformed: * *
 
 *      JXHyperlink hyperlink = new JXHyperlink(action);
 *      hyperlink.setOverrulesActionOnClick(true);
 *  
* * By default, this property is false. The hyperlink will * auto-click only if it has no action. Developers can change the * behaviour by overriding {@link JXHyperlink#isAutoSetClicked()}; * * @author Richard Bair * @author Shai Almog * @author Jeanette Winzenburg */ @JavaBean public class JXHyperlink extends JButton { /** * @see #getUIClassID * @see #readObject */ public static final String uiClassID = "HyperlinkUI"; // ensure at least the default ui is registered static { LookAndFeelAddons.contribute(new HyperlinkAddon()); } private boolean hasBeenVisited = false; /** * Color for the hyper link if it has not yet been clicked. This color can * be set both in code, and through the UIManager with the property * "JXHyperlink.unclickedColor". */ private Color unclickedColor; /** * Color for the hyper link if it has already been clicked. This color can * be set both in code, and through the UIManager with the property * "JXHyperlink.clickedColor". */ private Color clickedColor; private boolean overrulesActionOnClick; /** * Creates a new instance of JXHyperlink with default parameters */ public JXHyperlink() { this(null); } /** * Creates a new instance of JHyperLink and configures it from provided Action. * * @param action Action whose parameters will be borrowed to configure newly * created JXHyperLink */ public JXHyperlink(Action action) { super(); setAction(action); init(); } /** * Convenience method to create and install a HyperlinkAction for the given URI. * * @param uri * to uri to create a HyperlinkAction for, maybe null. * @throws HeadlessException * if {@link GraphicsEnvironment#isHeadless()} returns {@code true} * @throws UnsupportedOperationException * if the current platform doesn't support Desktop * * @see HyperlinkAction#createHyperlinkAction(URI) */ public void setURI(URI uri) { setAction(HyperlinkAction.createHyperlinkAction(uri)); } /** * Returns the foreground color for unvisited links. * * @return Color for the hyper link if it has not yet been clicked. */ public Color getUnclickedColor() { return unclickedColor; } /** * Sets the color for the previously visited link. This value will override the one * set by the "JXHyperlink.clickedColor" UIManager property and defaults. * * @param color Color for the hyper link if it has already been clicked. */ public void setClickedColor(Color color) { Color old = getClickedColor(); clickedColor = color; if (isClicked()) { setForeground(getClickedColor()); } firePropertyChange("clickedColor", old, getClickedColor()); } /** * Returns the foreground color for visited links. * * @return Color for the hyper link if it has already been clicked. */ public Color getClickedColor() { return clickedColor; } /** * Sets the color for the previously not visited link. This value will override the one * set by the "JXHyperlink.unclickedColor" UIManager property and defaults. * * @param color Color for the hyper link if it has not yet been clicked. */ public void setUnclickedColor(Color color) { Color old = getUnclickedColor(); unclickedColor = color; if (!isClicked()) { setForeground(getUnclickedColor()); } firePropertyChange("unclickedColor", old, getUnclickedColor()); } /** * Sets the clicked property and updates visual state depending on clicked. * This implementation updated the foreground color. *

* * NOTE: as with all button's visual properties, this will not update the * backing action's "visited" state. * * @param clicked flag to indicate if the button should be regarded as * having been clicked or not. * @see #isClicked() */ public void setClicked(boolean clicked) { boolean old = isClicked(); hasBeenVisited = clicked; setForeground(isClicked() ? getClickedColor() : getUnclickedColor()); firePropertyChange("clicked", old, isClicked()); } /** * Returns a boolean indicating if this link has already been visited. * * @return true if hyper link has already been clicked. * @see #setClicked(boolean) */ public boolean isClicked() { return hasBeenVisited; } /** * Sets the overrulesActionOnClick property. It controls whether this * button should overrule the Action's visited property on actionPerformed.

* * The default value is false. * * @param overrule if true, fireActionPerformed will set clicked to true * independent of action. * * @see #getOverrulesActionOnClick() * @see #setClicked(boolean) */ public void setOverrulesActionOnClick(boolean overrule) { boolean old = getOverrulesActionOnClick(); this.overrulesActionOnClick = overrule; firePropertyChange("overrulesActionOnClick", old, getOverrulesActionOnClick()); } /** * Returns a boolean indicating whether the clicked property should be set * always on clicked. * * @return overrulesActionOnClick false if his button clicked property * respects the Action's visited property. True if the clicked * should be updated on every actionPerformed. * * @see #setOverrulesActionOnClick(boolean) * @see #setClicked(boolean) */ public boolean getOverrulesActionOnClick() { return overrulesActionOnClick; } /** * {@inheritDoc}

* Overridden to respect the overrulesActionOnClick property. */ @Override protected void fireActionPerformed(ActionEvent event) { super.fireActionPerformed(event); if (isAutoSetClicked()) { setClicked(true); } } /** * Returns a boolean indicating whether the clicked property should be set * after firing action events. * Here: true if no action or overrulesAction property is true. * @return true if fireActionEvent should force a clicked, false if not. */ protected boolean isAutoSetClicked() { return getAction() == null || getOverrulesActionOnClick(); } /** * Creates and returns a listener that will watch the changes of the * provided Action and will update JXHyperlink's properties * accordingly. */ @Override protected PropertyChangeListener createActionPropertyChangeListener( final Action a) { final PropertyChangeListener superListener = super .createActionPropertyChangeListener(a); // JW: need to do something better - only weak refs allowed! // no way to hook into super return new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if (AbstractHyperlinkAction.VISITED_KEY.equals(evt.getPropertyName())) { configureClickedPropertyFromAction(a); } else { superListener.propertyChange(evt); } } }; } /** * Read all the essential properties from the provided Action * and apply it to the JXHyperlink */ @Override protected void configurePropertiesFromAction(Action a) { super.configurePropertiesFromAction(a); configureClickedPropertyFromAction(a); } private void configureClickedPropertyFromAction(Action a) { boolean clicked = false; if (a != null) { clicked = Boolean.TRUE.equals(a.getValue(AbstractHyperlinkAction.VISITED_KEY)); } setClicked(clicked); } private void init() { setForeground(isClicked() ? getClickedColor() : getUnclickedColor()); } /** * Returns a string that specifies the name of the L&F class * that renders this component. */ @Override public String getUIClassID() { return uiClassID; } /** * Notification from the UIManager that the L&F has changed. * Replaces the current UI object with the latest version from the UIManager. * * @see javax.swing.JComponent#updateUI */ @Override public void updateUI() { setUI((ButtonUI)LookAndFeelAddons.getUI(this, ButtonUI.class)); } }