import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.border.*; public class Incdec extends JPanel implements ActionListener, Adjustable { //*1 Catches ActionListener, Sends Adjustable /** * Our internal components that we need to remember */ protected JButton upButton, downButton; protected JLabel label; /** * Our data, initialized inline here */ protected int value = 0; protected int min = 0; protected int max = 100; protected int incr = 1; public Incdec () { // Put a border on our JPanel // default color, user can modify later setBorder (new LineBorder(Color.RED, 1)); // Use vertical grid layout to hold our buttons and stuff setLayout (new GridLayout (3, 1)); // Our internal widgets: // Our up button upButton = new JButton ("+"); upButton.addActionListener (this); //*2 Our internal callbacks add (upButton); // Our label widget label = new JLabel (); label.setHorizontalAlignment (JLabel.CENTER); refreshLabel (); add (label); // Our down button downButton = new JButton ("-"); downButton.addActionListener (this); //*2 add (downButton); } /** * Common callback for both internal buttons, * we use ivar to disambiguate. * Then we fire the result to *our* listeners. */ public void actionPerformed (ActionEvent e) { //*2 int type = 0; if (e.getSource()==upButton) { //*3 Create and fire our event (listenerList mechanism is inherited from JComponent) value += incr; //*3 type = AdjustmentEvent.UNIT_INCREMENT; //*3 } else if (e.getSource()==downButton) { value -= incr; type = AdjustmentEvent.UNIT_DECREMENT; } // Clamp at bounds if (value > max) value = max; if (value < min) value = min; // Update our label widget to match refreshLabel (); // Make a new event with our new data AdjustmentEvent event = new AdjustmentEvent (this, //*3 AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, type, value); //*3 // Send it to each of *our* listeners for (AdjustmentListener l: //*3 listenerList.getListeners (AdjustmentListener.class)) { //*3 l.adjustmentValueChanged (event); //*3 } //*3 } /** * Common code fragment, extracted to here */ protected void refreshLabel() { label.setText (String.valueOf (value)); } /** * Just as an example, we let user customize border color here */ public void setBorderColor (Color color) { setBorder (new LineBorder(color, 1)); } /** * Methods required by Adjustable, * listenerList is an ivar of JComponent, we access it here */ public void addAdjustmentListener(AdjustmentListener l) { //*4 Required by Adjustable, add/remove listener listenerList.add (AdjustmentListener.class, l); //*4 } public void removeAdjustmentListener(AdjustmentListener l) { //*4 listenerList.remove (AdjustmentListener.class, l); //*4 } /** * Methods required by Adjustable, * though block vs. unit and visibleAmount don't really make sense for us */ public int getValue() { return value; } //*5 Required by Adjustable, do something reasonable public int getMaximum() { return max; } //*5 public int getMinimum() { return min; } //*5 public int getOrientation() { return VERTICAL; } //*5 public int getUnitIncrement() { return incr; } //*5 public int getBlockIncrement () { return incr; } //*5 public int getVisibleAmount() { return 0; } //*5 public void setBlockIncrement(int b) { incr = b; } //*5 public void setMaximum(int max) { this.max = max; } //*5 public void setMinimum(int min) { this.min = min; } //*5 public void setUnitIncrement(int u) { incr = u; } //*5 public void setVisibleAmount(int v) { } //*5 public void setValue(int v) { //*5 value = v; //*5 refreshLabel (); //*5 } }