/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2008-2009 Sun Microsystems, Inc.
* Portions Copyright 2014-2015 ForgeRock AS
*/
package org.opends.guitools.controlpanel.ui.components;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import org.forgerock.i18n.LocalizableMessage;
import org.opends.guitools.controlpanel.datamodel.Action;
import org.opends.guitools.controlpanel.datamodel.Category;
import org.opends.guitools.controlpanel.ui.ColorAndFontConstants;
/**
* A basic extension of a button that changes its rendering so that the looks
* are more similar to a row in a list. It is used in the actions on the left
* of the main Control Center dialog (in actions like 'Manage Entries...',
* 'Import from LDIF...' etc.
*/
public class ActionButton extends JButton
{
private static final long serialVersionUID = -1898192406268037714L;
private static final Border buttonBorder;
private static final Border focusBorder;
private final Action action;
private boolean isBeingPressed;
private boolean hasMouseOver;
static
{
//Calculate border based on category settings
Category cat = new Category();
cat.setName(LocalizableMessage.EMPTY);
CategoryButton b = new CategoryButton(cat);
int n = b.getIconTextGap() + b.getIcon().getIconWidth() +
b.getBorder().getBorderInsets(b).left;
buttonBorder = new EmptyBorder(5, n, 5, 25);
Border highlightBorder =
UIManager.getBorder("List.focusCellHighlightBorder");
// This is required (see issue
// https://opends.dev.java.net/issues/show_bug.cgi?id=4400)
// since in OpenJDK the CompoundBorder class does not handle properly
// null insets.
if (highlightBorder != null)
{
try
{
b.setBorder(BorderFactory.createCompoundBorder(
highlightBorder, buttonBorder));
}
catch (Throwable t)
{
highlightBorder = null;
}
}
if (highlightBorder == null)
{
highlightBorder =
new javax.swing.plaf.BorderUIResource.LineBorderUIResource(
ColorAndFontConstants.pressedForeground, 1);
}
focusBorder = BorderFactory.createCompoundBorder(
highlightBorder, buttonBorder);
}
private static final Color defaultBackground =
ColorAndFontConstants.background;
private static final Color defaultForeground =
ColorAndFontConstants.foreground;
private static final Color mouseOverBackground =
ColorAndFontConstants.mouseOverBackground;
private static final Color mouseOverForeground =
ColorAndFontConstants.mouseOverForeground;
private static final Color pressedBackground =
ColorAndFontConstants.pressedBackground;
private static final Color pressedForeground =
ColorAndFontConstants.pressedForeground;
private static final Font actionFont = ColorAndFontConstants.defaultFont;
/**
* Creates a button associated with the provided action.
* @param action the action.
*/
public ActionButton(Action action) {
super();
this.action = action;
setText(action.getName().toString());
setIconTextGap(0);
setHorizontalTextPosition(SwingConstants.TRAILING);
setHorizontalAlignment(SwingConstants.LEADING);
setOpaque(true);
setBorder(buttonBorder);
setFont(actionFont);
setFocusPainted(true);
setContentAreaFilled(false);
setToolTipText(action.getName().toString());
setRolloverEnabled(false);
Dimension d1 = getPreferredSize();
setBorder(focusBorder);
Dimension d2 = getPreferredSize();
setPreferredSize(new Dimension(Math.max(d1.width,d2.width),
Math.max(d1.height, d2.height)));
setBorder(buttonBorder);
}
/**
* Callback when an action has been performed.
*
* @param ev
* the action event
*/
public void actionPerformed(ActionEvent ev)
{
isBeingPressed = true;
final boolean[] hadMouseOver = {hasMouseOver};
hasMouseOver = true;
repaint();
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
isBeingPressed = false;
hasMouseOver = hadMouseOver[0];
repaint();
}
});
}
/**
* Callback when a mouse button has been pressed.
*
* @param e
* the mouse event
*/
public void mousePressed(MouseEvent e)
{
isBeingPressed = true;
}
/**
* Callback when a mouse button has been released.
*
* @param e
* the mouse event
*/
public void mouseReleased(MouseEvent e)
{
isBeingPressed = false;
}
/**
* Callback when mouse exited a component.
*
* @param e
* the mouse event
*/
public void mouseExited(MouseEvent e)
{
hasMouseOver = false;
repaint();
}
/**
* Callback when mouse entered a component.
*
* @param e
* the mouse event
*/
public void mouseEntered(MouseEvent e)
{
hasMouseOver = true;
repaint();
}
/** {@inheritDoc} */
@Override
public void updateUI() {
super.updateUI();
// some look and feels replace our border, so take it back
setBorder(buttonBorder);
}
/** {@inheritDoc} */
@Override
protected void paintComponent(Graphics g) {
setBorder(hasFocus() ? focusBorder : buttonBorder);
if (isBeingPressed && hasMouseOver)
{
setColors(g, pressedBackground, pressedForeground);
}
else if (hasMouseOver)
{
setColors(g, mouseOverBackground, mouseOverForeground);
}
else {
setColors(g, defaultBackground, defaultForeground);
}
super.paintComponent(g);
}
private void setColors(Graphics g, Color backgroundColor, Color foregroundColor)
{
setBackground(backgroundColor);
g.setColor(backgroundColor);
Dimension size = getSize();
g.fillRect(0, 0, size.width, size.height);
setForeground(foregroundColor);
}
/**
* Returns the action associated with this button.
* @return the action associated with this button.
*/
public Action getActionObject() {
return action;
}
}