package example; import java.awt.*; import java.awt.event.*; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; /** * Source code for Tutorial 1. * Simple arrow button that fires one event when first clicked, then sends a * stream of events while held down. */ public class ArrowButton extends JPanel { /** Directions. */ public static final String LEFT = "LEFT", RIGHT = "RIGHT", UP = "UP", DOWN = "DOWN"; private String direction; private String lastPaintedDirection; private static ArrowRoller roller; private boolean down; private boolean in; private ActionListener listeners; private static final int SIZE = 12; private static final int BORDER = 2; private static class ArrowRoller extends Thread { /** How long to wait before repeating. */ private static final int DELAY_MS = 400; /** How long between repeated firings. */ private static final int REPEAT_MS = 100; private boolean die = false; private ArrowButton target; private int state; ArrowRoller () { super ("ArrowRoller"); setDaemon(true); } synchronized void abort () { die = true; notify (); target = null; ++ state; } synchronized void addListener (ArrowButton t) { target = t; ++ state; notify (); } synchronized void removeListener (ArrowButton t) { if (target == t) { target = null; ++ state; } } public void run () { while (!die) { try { ArrowButton target; int state; synchronized (this) { while ((target = this.target) == null) wait (); state = this.state; } sleep (DELAY_MS); while (state == this.state) { target.fireActionEvent (); sleep (REPEAT_MS); } } catch (InterruptedException ex) { } } } } public ArrowButton () { this(LEFT); } public ArrowButton (String direction) { enableEvents (AWTEvent.MOUSE_EVENT_MASK); setBorder(new EmptyBorder(BORDER, BORDER, BORDER, BORDER)); lastPaintedDirection = direction; setDirection(direction); } public void setDirection (String d) { if (d.equals(LEFT)) direction = LEFT; else if (d.equals(RIGHT)) direction = RIGHT; else if (d.equals(UP)) direction = UP; else direction = DOWN; repaint(); } public String getDirection () { return direction; } public Dimension getMinimumSize () { return getPreferredSize (); } public Dimension getPreferredSize () { return new Dimension (SIZE, SIZE); } public Dimension getMaximumSize () { return getPreferredSize (); } public void update (Graphics g) { if (lastPaintedDirection == direction) { paint (g); } else { super.update (g); lastPaintedDirection = direction; } } public void paint (Graphics g) { super.paint(g); int w = getSize ().width, h = getSize ().height; g.setColor ((in && down) ? getBackground ().brighter () : getBackground ().darker ()); if (direction == LEFT) { g.drawLine (w - 2, 2, w - 2, h - 2); g.drawLine (w - 2, h - 2, 2, (h - 2) / 2); g.setColor ((in && down) ? getBackground ().darker () : getBackground().brighter()); g.drawLine (2, (h - 2) / 2, w - 2, 2); } else if (direction == RIGHT) { g.drawLine (2, 2, w - 2, (h - 2) / 2); g.drawLine (2, h - 2, w - 2, (h - 2) / 2); g.setColor ((in && down) ? getBackground ().darker () : getBackground().brighter()); g.drawLine (2, 2, 2, h - 2); } else if (direction == UP){ g.drawLine (2, h - 2, w - 2, h - 2); g.drawLine (w - 2, h - 2, (w - 2) / 2, 2); g.setColor ((in && down) ? getBackground ().darker () : getBackground().brighter()); g.drawLine (2, h - 2, (w - 2) / 2, 2); } else { g.drawLine ((w - 2) / 2, h - 2, w - 2, 2); g.setColor ((in && down) ? getBackground ().darker () : getBackground().brighter()); g.drawLine (2, 2, (w - 2) / 2, h - 2); g.drawLine (2, 2, w - 2, 2); } } protected synchronized ArrowRoller getRoller () { if (roller == null) { roller = new ArrowRoller (); roller.start(); } return roller; } public synchronized void destroyRoller () { roller.abort (); roller = null; } protected void processMouseEvent(MouseEvent e) { ArrowRoller roller = getRoller(); switch (e.getID ()) { case MouseEvent.MOUSE_PRESSED: fireActionEvent (); roller.addListener (this); down = in = true; repaint (); break; case MouseEvent.MOUSE_RELEASED: roller.removeListener (this); down = in = false; repaint (); break; case MouseEvent.MOUSE_ENTERED: in = true; if (down) { roller.addListener (this); repaint (); } break; case MouseEvent.MOUSE_EXITED: in = false; if (down) { roller.removeListener (this); repaint (); } break; } super.processMouseEvent (e); } public void addActionListener (ActionListener l) { listeners = AWTEventMulticaster.add (l, listeners); } public void removeActionListener (ActionListener l) { listeners = AWTEventMulticaster.remove (l, listeners); } protected void fireActionEvent () { if (listeners != null){ ActionEvent ev = new ActionEvent (this, ActionEvent.ACTION_PERFORMED, direction); listeners.actionPerformed (ev); } } }