package de.fuhagen.sttp.gui;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
/**
* This class implements a flat three state toggle button.
*
* @author thomas
*
*/
public class FlatTrippleButton extends JButton implements ActionListener,
MouseListener, MouseMotionListener {
/**
* Serial version UID.
*/
private static final long serialVersionUID = 978315958250216807L;
/**
* Possible states of switch.
*
* @author thomas
*
*/
public enum STATE {
OFF, MIDDLE, ON
};
/**
* Current state of the button.
*/
private STATE buttonState;
/**
* On action.
*/
private Action onAction;
/**
* Off action.
*/
private Action offAction;
/**
* Middle action.
*/
private Action middleAction;
/**
* Current drag point.
*/
private Point mousePoint = null;
/**
* Is the button dragged at the moment?
*/
private boolean dragmode = false;
/**
* Cache for last state.
*/
private STATE lastState = STATE.MIDDLE;
/**
* This constructor builds a new three state button.
*
* @param on
* on action
* @param off
* off action
* @param middle
* middle action
* @param buttonWidth
* width of button
* @param buttonHeight
* height of button
*/
public FlatTrippleButton(Action on, Action off, Action middle,
int buttonWidth, int buttonHeight) {
super(middle);
onAction = on;
offAction = off;
middleAction = middle;
setIcon(null);
Dimension size = new Dimension(buttonWidth, buttonHeight);
setSize(size);
setPreferredSize(size);
setMinimumSize(size);
setFocusPainted(false);
setContentAreaFilled(false);
Border line = new LineBorder(Color.BLACK, 3, true);
Border empty = new EmptyBorder(5, 5, 5, 5);
Border compound = new CompoundBorder(line, empty);
setBorder(compound);
buttonState = STATE.OFF;
setToolTipText(middleAction.getValue(Action.SHORT_DESCRIPTION)
.toString());
addActionListener(this);
addMouseListener(this);
addMouseMotionListener(this);
}
/**
* This method returns the on action.
*
* @return the onAction
*/
public Action getOnAction() {
return onAction;
}
/**
* This method returns the off action.
*
* @return the offAction
*/
public Action getOffAction() {
return offAction;
}
/**
* This method returns the middle action.
*
* @return the offAction
*/
public Action getMiddleAction() {
return middleAction;
}
/**
* This method returns the current state.
*
* @return the on
*/
public STATE getState() {
return buttonState;
}
/**
* This method sets the current state of the button.
*
* @param on the on to set
*/
public void setState(STATE state) {
lastState = buttonState;
buttonState = state;
if (state == STATE.OFF || state == STATE.ON) {
setAction(middleAction);
setToolTipText(middleAction.getValue(Action.SHORT_DESCRIPTION)
.toString());
setIcon(null);
} else {
if (lastState == STATE.OFF) {
setAction(onAction);
setToolTipText(onAction.getValue(Action.SHORT_DESCRIPTION)
.toString());
setIcon(null);
} else {
setAction(offAction);
setToolTipText(offAction.getValue(Action.SHORT_DESCRIPTION)
.toString());
setIcon(null);
}
}
invalidate();
repaint();
}
@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
super.paintComponent(g2d);
g2d.setStroke(new BasicStroke(3));
int width = getWidth() - 10;
int min = 5;
int middle = (getHeight() - width) / 2;
int max = getHeight() - 5 - width;
int y = max;
if (dragmode) {
y = mousePoint.y - (width / 2);
if (y < min) {
y = min;
} else if (y > max) {
y = max;
}
} else if (buttonState == STATE.ON) {
y = min;
} else if (buttonState == STATE.MIDDLE) {
y = middle;
}
g2d.setColor(Color.BLACK);
g2d.fillRoundRect(5, y, width, width, 5, 5);
}
@Override
public void actionPerformed(ActionEvent e) {
switch (buttonState) {
case ON:
case OFF:
setState(STATE.MIDDLE);
break;
default:
if (lastState == STATE.OFF) {
setState(STATE.ON);
} else {
setState(STATE.OFF);
}
break;
}
}
@Override
public void mouseDragged(MouseEvent e) {
dragmode = true;
setEnabled(false);
Point lastPoint = mousePoint;
mousePoint = e.getPoint();
STATE lastState = null;
STATE currentState = null;
if (lastPoint.y <= getHeight() / 3) {
lastState = STATE.ON;
} else if (lastPoint.y > 2 * getHeight() / 3) {
lastState = STATE.OFF;
} else {
lastState = STATE.MIDDLE;
}
if (mousePoint.y <= getHeight() / 3) {
currentState = STATE.ON;
} else if (mousePoint.y > 2 * getHeight() / 3) {
currentState = STATE.OFF;
} else {
currentState = STATE.MIDDLE;
}
if (lastState != currentState) {
ActionEvent event = new ActionEvent(this, 0, "mouse dragged",
System.currentTimeMillis(), 0);
switch (currentState) {
case ON:
getOnAction().actionPerformed(event);
break;
case MIDDLE:
getMiddleAction().actionPerformed(event);
break;
default:
getOffAction().actionPerformed(event);
break;
}
setState(currentState);
}
invalidate();
repaint();
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
mousePoint = e.getPoint();
}
@Override
public void mouseReleased(MouseEvent e) {
if (dragmode) {
setEnabled(true);
}
mousePoint = null;
dragmode = false;
invalidate();
repaint();
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}