components/visual-panels/core/src/java/util/com/oracle/solaris/vp/util/swing/HyperlinkLabel.java
changeset 827 0944d8c0158b
equal deleted inserted replaced
826:c6aad84d2493 827:0944d8c0158b
       
     1 /*
       
     2  * CDDL HEADER START
       
     3  *
       
     4  * The contents of this file are subject to the terms of the
       
     5  * Common Development and Distribution License (the "License").
       
     6  * You may not use this file except in compliance with the License.
       
     7  *
       
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
     9  * or http://www.opensolaris.org/os/licensing.
       
    10  * See the License for the specific language governing permissions
       
    11  * and limitations under the License.
       
    12  *
       
    13  * When distributing Covered Code, include this CDDL HEADER in each
       
    14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    15  * If applicable, add the following below this CDDL HEADER, with the
       
    16  * fields enclosed by brackets "[]" replaced with your own identifying
       
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    18  *
       
    19  * CDDL HEADER END
       
    20  */
       
    21 
       
    22 /*
       
    23  * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
       
    24  */
       
    25 
       
    26 package com.oracle.solaris.vp.util.swing;
       
    27 
       
    28 import java.awt.*;
       
    29 import java.awt.event.*;
       
    30 import java.awt.font.TextAttribute;
       
    31 import java.util.HashMap;
       
    32 import javax.swing.*;
       
    33 import javax.swing.border.Border;
       
    34 import com.oracle.solaris.vp.util.swing.event.ActionListeners;
       
    35 
       
    36 @SuppressWarnings({"serial"})
       
    37 public class HyperlinkLabel extends JLabel {
       
    38     //
       
    39     // Enums
       
    40     //
       
    41 
       
    42     public enum UnderlinePolicy {
       
    43 	ALWAYS,
       
    44 	NEVER,
       
    45 
       
    46 	// Underline only when hovering over link
       
    47 	HOVER,
       
    48 
       
    49 	// Underline only when not hovering over link
       
    50 	NOHOVER,
       
    51     };
       
    52 
       
    53     //
       
    54     // Static data
       
    55     //
       
    56 
       
    57     public static final String KEY_UNVISITED = "HyperlinkLabel.unvisited";
       
    58     public static final String KEY_VISITED = "HyperlinkLabel.visited";
       
    59     public static final String KEY_UNDERLINE_POLICY = "HyperlinkLabel.upolicy";
       
    60 
       
    61     static {
       
    62 	if (UIManager.getColor(KEY_UNVISITED) == null) {
       
    63 	    UIManager.put(KEY_UNVISITED, new Color(0, 0, 204));
       
    64 	}
       
    65 	if (UIManager.getColor(KEY_VISITED) == null) {
       
    66 	    UIManager.put(KEY_VISITED, new Color(128, 0, 128));
       
    67 	}
       
    68 	if (UIManager.get(KEY_UNDERLINE_POLICY) == null) {
       
    69 	    UIManager.put(KEY_UNDERLINE_POLICY, UnderlinePolicy.HOVER);
       
    70 	}
       
    71     }
       
    72 
       
    73     //
       
    74     // Instance data
       
    75     //
       
    76 
       
    77     private ActionListeners listeners = new ActionListeners();
       
    78     private boolean visited;
       
    79     private boolean underline;
       
    80     private boolean active;
       
    81     private Color unvisitedColor = UIManager.getColor(KEY_UNVISITED);
       
    82     private Color visitedColor = UIManager.getColor(KEY_VISITED);
       
    83     private UnderlinePolicy policy;
       
    84 
       
    85     private FocusListener focusListener =
       
    86 	new FocusListener() {
       
    87 	    @Override
       
    88 	    public void focusGained(FocusEvent e) {
       
    89 		repaint();
       
    90 	    }
       
    91 
       
    92 	    public void focusLost(FocusEvent e) {
       
    93 		repaint();
       
    94 	    }
       
    95 	};
       
    96 
       
    97     private MouseListener mouseFocusListener =
       
    98 	new MouseAdapter() {
       
    99 	    public void mousePressed(MouseEvent e) {
       
   100 		requestFocusInWindow();
       
   101 	    }
       
   102 	};
       
   103 
       
   104     private Border focusBorder;
       
   105 
       
   106     //
       
   107     // Constructors
       
   108     //
       
   109 
       
   110     public HyperlinkLabel(String title, UnderlinePolicy policy) {
       
   111 	super(title);
       
   112 
       
   113 	setUnderlinePolicy(policy);
       
   114 	setVisited(false);
       
   115 	setFocusable(true);
       
   116 	setActive(true);
       
   117 
       
   118 	Action clickAction =
       
   119 	    new AbstractAction() {
       
   120 		@Override
       
   121 		public void actionPerformed(ActionEvent e) {
       
   122 		    click();
       
   123 		}
       
   124 	    };
       
   125 
       
   126 	GUIUtil.installKeyBinding(this, JComponent.WHEN_FOCUSED,
       
   127 	    "clicked", clickAction, KeyEvent.VK_ENTER, KeyEvent.VK_SPACE);
       
   128 
       
   129 	final MouseListener mListener = new MouseAdapter() {
       
   130 	    @Override
       
   131 	    public void mouseClicked(MouseEvent e) {
       
   132 		click();
       
   133 	    }
       
   134 
       
   135 	    @Override
       
   136 	    public void mouseEntered(MouseEvent e) {
       
   137 		// Set underlining depending on policy
       
   138 		underline = true;
       
   139 		switch (getUnderlinePolicy()) {
       
   140 		    case NEVER:
       
   141 		    case NOHOVER:
       
   142 			underline = false;
       
   143 		}
       
   144 		setFont(getFont());
       
   145 	    }
       
   146 
       
   147 	    @Override
       
   148 	    public void mouseExited(MouseEvent e) {
       
   149 		// Set underlining depending on policy
       
   150 		underline = false;
       
   151 		switch (getUnderlinePolicy()) {
       
   152 		    case ALWAYS:
       
   153 		    case NOHOVER:
       
   154 			underline = true;
       
   155 		}
       
   156 		setFont(getFont());
       
   157 	    }
       
   158 	};
       
   159 	addMouseListener(mListener);
       
   160 
       
   161 	// Set initial underline state
       
   162 	mListener.mouseExited(null);
       
   163 
       
   164 	addHierarchyListener(
       
   165 	    new HierarchyListener() {
       
   166 		@Override
       
   167 		public void hierarchyChanged(HierarchyEvent e) {
       
   168 		    if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED)
       
   169 			!= 0 && !isShowing()) {
       
   170 			mListener.mouseExited(null);
       
   171 		    }
       
   172 		}
       
   173 	    });
       
   174     }
       
   175 
       
   176     public HyperlinkLabel(String title) {
       
   177 	this(title, (UnderlinePolicy)UIManager.get(KEY_UNDERLINE_POLICY));
       
   178     }
       
   179 
       
   180     public HyperlinkLabel() {
       
   181 	this("");
       
   182     }
       
   183 
       
   184     //
       
   185     // Component methods
       
   186     //
       
   187 
       
   188     @Override
       
   189     public void setFocusable(boolean focusable) {
       
   190 	removeFocusListener(focusListener);
       
   191 	removeMouseListener(mouseFocusListener);
       
   192 	if (focusable) {
       
   193 	    addFocusListener(focusListener);
       
   194 	    addMouseListener(mouseFocusListener);
       
   195 	}
       
   196 
       
   197 	super.setFocusable(focusable);
       
   198     }
       
   199 
       
   200     @Override
       
   201     public void setFont(Font font) {
       
   202 	if (font != null) {
       
   203 	    HashMap<TextAttribute, Object> attrs =
       
   204 		new HashMap<TextAttribute, Object>();
       
   205 	    attrs.put(TextAttribute.UNDERLINE, underline && active ?
       
   206 		TextAttribute.UNDERLINE_ON : -1);
       
   207 
       
   208 	    font = font.deriveFont(attrs);
       
   209 	}
       
   210 
       
   211 	super.setFont(font);
       
   212     }
       
   213 
       
   214     //
       
   215     // JComponent methods
       
   216     //
       
   217 
       
   218     @Override
       
   219     public void setBorder(Border border) {
       
   220 	if (focusBorder == null) {
       
   221 	    focusBorder = new FocusBorder();
       
   222 	}
       
   223 
       
   224 	Border compound = border == null ? focusBorder :
       
   225 	    BorderFactory.createCompoundBorder(border, focusBorder);
       
   226 
       
   227 	super.setBorder(compound);
       
   228     }
       
   229 
       
   230     //
       
   231     // HyperlinkLabel methods
       
   232     //
       
   233 
       
   234     public void addActionListener(ActionListener listener) {
       
   235 	listeners.add(listener);
       
   236     }
       
   237 
       
   238     protected void fireActionPerformed(ActionEvent e) {
       
   239 	listeners.actionPerformed(e);
       
   240     }
       
   241 
       
   242     public boolean getActive() {
       
   243 	return active;
       
   244     }
       
   245 
       
   246     public UnderlinePolicy getUnderlinePolicy() {
       
   247 	return policy;
       
   248     }
       
   249 
       
   250     public Color getUnvisitedColor() {
       
   251 	return unvisitedColor;
       
   252     }
       
   253 
       
   254     public boolean getVisited() {
       
   255 	return visited;
       
   256     }
       
   257 
       
   258     public Color getVisitedColor() {
       
   259 	return visitedColor;
       
   260     }
       
   261 
       
   262     public boolean removeActionListener(ActionListener listener) {
       
   263 	return listeners.remove(listener);
       
   264     }
       
   265 
       
   266     public void setActive(boolean active) {
       
   267 	this.active = active;
       
   268 	setCursor(active ? Cursor.getPredefinedCursor(Cursor.HAND_CURSOR) :
       
   269 	    null);
       
   270 	setFocusable(active);
       
   271 	setFont(getFont());
       
   272 	setForeground();
       
   273     }
       
   274 
       
   275     public void setColor(Color color) {
       
   276 	unvisitedColor = visitedColor = color;
       
   277 	setForeground();
       
   278     }
       
   279 
       
   280     public void setUnderlinePolicy(UnderlinePolicy policy) {
       
   281 	this.policy = policy;
       
   282     }
       
   283 
       
   284     public void setUnvisitedColor(Color unvisitedColor) {
       
   285 	this.unvisitedColor = unvisitedColor;
       
   286 	setForeground();
       
   287     }
       
   288 
       
   289     public void setVisited(boolean visited) {
       
   290 	this.visited = visited;
       
   291 	setForeground();
       
   292     }
       
   293 
       
   294     public void setVisitedColor(Color visitedColor) {
       
   295 	this.visitedColor = visitedColor;
       
   296 	setForeground();
       
   297     }
       
   298 
       
   299     //
       
   300     // Private methods
       
   301     //
       
   302 
       
   303     private void click() {
       
   304 	if (active) {
       
   305 	    ActionEvent e = new ActionEvent(HyperlinkLabel.this,
       
   306 		ActionEvent.ACTION_PERFORMED, null);
       
   307 	    fireActionPerformed(e);
       
   308 	    setVisited(true);
       
   309 	}
       
   310     }
       
   311 
       
   312     private void setForeground() {
       
   313 	setForeground(visited ? getVisitedColor() : getUnvisitedColor());
       
   314     }
       
   315 }