Sunday, April 11, 2010

How to create a ThreeStateButton in java

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;

/**
 * A Three State Button Class
 * @author Noman Naeem
 * @version 1.0
 */

public class ThreeStateButtonBean extends JComponent implements Serializable{

    private int state = 0;
    private int x = 0;
    private int y = 0;
    private int height = 30;
    private int width = 30;
    private final int MIN_WIDTH = 10;
    private final int MIN_HEIGHT = 10;
    private final int RAISED_OFFSET = -1;
    private transient PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    private boolean isDown = false;
    private transient java.util.Vector actionListeners;
    private boolean hasFocus = false;

    public ThreeStateButtonBean()
    {
    this.setOpaque(true);
    this.enableEvents(AWTEvent.MOUSE_EVENT_MASK);
    this.enableEvents(AWTEvent.KEY_EVENT_MASK);
    this.enableEvents(AWTEvent.FOCUS_EVENT_MASK);
    actionListeners = new java.util.Vector();
    }

    public void processMouseEvent(MouseEvent me)
    {
        switch (me.getID()) {
            case MouseEvent.MOUSE_PRESSED:
         isDown = true;
         this.requestFocus();
         repaint();
         break;
        case MouseEvent.MOUSE_RELEASED:
         isDown = false;
         int s = (state+1)%3;
         setState(s);
         if (actionListeners.size() > 0) {
             ActionEvent ae = new ActionEvent(this,me.getID(),"Mouse Clicked on Button");
             this.fireActionEvent(ae);
         }
             break;
        }
    super.processMouseEvent(me);
    }

    public void processKeyEvent(KeyEvent ke)
    {
        switch (ke.getID()) {
            case KeyEvent.KEY_PRESSED:
        if (ke.getKeyChar() == ' ') {
             isDown = true;
             repaint();
        }
        break;
        case KeyEvent.KEY_RELEASED:
            if (ke.getKeyChar() == ' ') {
             isDown = false;
             int s = (state+1)%3;
             setState(s);
             if (actionListeners.size() > 0) {
                  ActionEvent ae = new ActionEvent(this,ke.getID(),"Space Pressed on Button");
                      this.fireActionEvent(ae);
             }
        }
        break;
    }
    super.processKeyEvent(ke);
    }

    public void processFocusEvent(FocusEvent fe)
    {
        switch (fe.getID()) {
               case FocusEvent.FOCUS_GAINED:
            hasFocus = true;
            repaint();
            break;
           case FocusEvent.FOCUS_LOST:
            hasFocus = false;
            repaint();
            break;
    }
    }

    public synchronized void addPropertyChangeListener(PropertyChangeListener pl)
    {
            pcs.addPropertyChangeListener(pl);
    }

    public synchronized void addActionListener(ActionListener al)
    {
            actionListeners.addElement(al);
    }

    public synchronized void removeActionListener(ActionListener al)
    {
      actionListeners.removeElement(al);
    }

    public synchronized void removePropertyChangeListener(PropertyChangeListener pl)
    {
            pcs.removePropertyChangeListener(pl);
    }

    public boolean isFocusTraversable()
    {
      return true;
    }

    public void fireActionEvent(ActionEvent ae)
    {
      java.util.Vector actionListenersClone;
            synchronized (this) {
              actionListenersClone = (java.util.Vector)actionListeners.clone();
            }
        for (int i=0;i<actionListenersClone.size();i++)
            ((ActionListener)actionListenersClone.elementAt(i)).actionPerformed(ae);
    }

    public void setState(int state)
    {
      PropertyChangeEvent pce = new PropertyChangeEvent(this,"state",new Integer(this.state),new Integer(state));
    pcs.firePropertyChange(pce);
    this.state = state;
    this.repaint();
    }

    public int getState()
    {
        return state;
    }
    public void paint(Graphics g)
    {
        Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setColor(getBackground());
    g2.fillRect(x,y,width,height);

    if (!isDown) {
       if (hasFocus) {
           g2.draw3DRect(x+1,y+1,width-2,height-2,true);
       }
       else {
           javax.swing.border.Border cb = BorderFactory.createEtchedBorder();
           cb.paintBorder(this,g,x,y,width,height);
       }
    }
    else {
       g2.setColor(new Color(160,160,160));
       g2.fillRect(x,y,width,height);
       g2.setColor(Color.white);
       g2.drawRect(x,y,width-1,height-1);
       g2.setColor(new Color(100,100,100));
       g2.drawRect(x,y,width-2,height-2);
    }

    if (state == 1) {
       g2.setStroke(new BasicStroke(width/MIN_WIDTH));
       x = width/16;
       g2.setColor(Color.black);
       g2.drawLine(x+width/5+x/2,y+height/2+height/12,x+width/3,y+height-height/3);
       g2.drawLine(x+width/3,y+height-height/3,x+width-width/3,y+height/3);
       x = 0;
    }
    else if (state == 2) {
       if (!hasFocus)
         x = RAISED_OFFSET;
       g2.setStroke(new BasicStroke(width/MIN_WIDTH));
       g2.setColor(Color.black);
       g2.drawLine(x+width/3,y+height/3,x+width-width/3,y+height-height/3);
       g2.drawLine(x+width-width/3,y+height/3,x+width/3,y+height-height/3);
       x = 0;
    }
    }

    public int getHeight()
    {
        return height;
    }

    public void setHeight(int height)
    {
        if (height > MIN_HEIGHT) {
        setPreferredSize(new Dimension(width,height));
    }
    }

    public int getWidth()
    {
        return width;
    }

    public void setWidth(int width)
    {
        if (width > MIN_WIDTH) {
        setPreferredSize(new Dimension(width,height));
        }
    }

    public Dimension getPreferredSize()
    {
        return new Dimension(width, height);
    }

    public void setPreferredSize(Dimension d)
    {
        super.setPreferredSize(d);
                this.height = d.height;
                this.width = d.width;
                revalidate();
    if (this.getParent() != null)
       this.getParent().repaint();
    }

    private void writeObject(ObjectOutputStream oos) throws IOException
    {
        oos.defaultWriteObject();
    }
    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException
    {
        ois.defaultReadObject();
    actionListeners = new java.util.Vector();
    pcs = new PropertyChangeSupport(this);
    }
}