//---------------------------------------------------------------------- // From BDK example beans //---------------------------------------------------------------------- package aima.examples; //package sunw.demo.buttons; import java.awt.*; import java.awt.event.*; import java.beans.*; import java.io.Serializable; import java.util.Vector; /** * A simple Java Beans button. OurButton is a "from-scratch" * GUI component that's derived from Canvas. It's a good example of * how to implement bound properties and support for event listeners. * * Parts of the source are derived from sun.awt.tint.TinyButtonPeer. */ public class OurButton extends Canvas implements Serializable, MouseListener, MouseMotionListener { /** * Constructs a Button with the a default label. */ public OurButton() { this("press"); } /** * Constructs a Button with the specified label. * @param label the label of the button */ public OurButton(String label) { super(); this.label = label; setFont(new Font("Dialog", Font.PLAIN, 12)); setBackground(Color.lightGray); addMouseListener(this); addMouseMotionListener(this); } //---------------------------------------------------------------------- /** * Paint the button: the label is centered in both dimensions. * */ public synchronized void paint(Graphics g) { int width = getSize().width; int height = getSize().height; g.setColor(getBackground()); g.fill3DRect(0, 0, width - 1, height - 1, !down); g.setColor(getForeground()); g.setFont(getFont()); g.drawRect(2, 2, width - 4, height - 4); FontMetrics fm = g.getFontMetrics(); g.drawString(label, (width - fm.stringWidth(label)) / 2, (height + fm.getMaxAscent() - fm.getMaxDescent()) / 2); } //---------------------------------------------------------------------- // Mouse listener methods. public void mouseClicked(MouseEvent evt) { } public void mousePressed(MouseEvent evt) { if (!isEnabled()) { return; } down = true; repaint(); } public void mouseReleased(MouseEvent evt) { if (!isEnabled()) { return; } if (down) { fireAction(); down = false; repaint(); } } public void mouseEntered(MouseEvent evt) { } public void mouseExited(MouseEvent evt) { } public void mouseDragged(MouseEvent evt) { if (!isEnabled()) { return; } // Has the mouse been dragged outside the button? int x = evt.getX(); int y = evt.getY(); int width = getSize().width; int height = getSize().height; if (x < 0 || x > width || y < 0 || y > height) { // Yes, we should deactivate any pending click. if (down) { down = false; repaint(); } } else if (!down) { down = true; repaint(); } } public void mouseMoved(MouseEvent evt) { } //---------------------------------------------------------------------- // Methods for registering/deregistering event listeners /** * The specified ActionListeners actionPerformed method will * be called each time the button is clicked. The ActionListener * object is added to a list of ActionListeners managed by * this button, it can be removed with removeActionListener. * Note: the JavaBeans specification does not require ActionListeners * to run in any particular order. * * @see #removeActionListener * @param l the ActionListener */ public synchronized void addActionListener(ActionListener l) { pushListeners.addElement(l); } /** * Remove this ActionListener from the buttons internal list. If the * ActionListener isn't on the list, silently do nothing. * * @see #addActionListener * @param l the ActionListener */ public synchronized void removeActionListener(ActionListener l) { pushListeners.removeElement(l); } /** * The specified PropertyChangeListeners propertyChange method will * be called each time the value of any bound property is changed. * The PropertyListener object is addded to a list of PropertyChangeListeners * managed by this button, it can be removed with removePropertyChangeListener. * Note: the JavaBeans specification does not require PropertyChangeListeners * to run in any particular order. * * @see #removePropertyChangeListener * @param l the PropertyChangeListener */ public void addPropertyChangeListener(PropertyChangeListener l) { changes.addPropertyChangeListener(l); } /** * Remove this PropertyChangeListener from the buttons internal list. * If the PropertyChangeListener isn't on the list, silently do nothing. * * @see #addPropertyChangeListener * @param l the PropertyChangeListener */ public void removePropertyChangeListener(PropertyChangeListener l) { changes.removePropertyChangeListener(l); } //---------------------------------------------------------------------- /** * This method has the same effect as pressing the button. * * @see #addActionListener */ public void fireAction() { if (debug) { System.err.println("Button " + getLabel() + " pressed."); } Vector targets; synchronized (this) { targets = (Vector) pushListeners.clone(); } ActionEvent actionEvt = new ActionEvent(this, 0, null); for (int i = 0; i < targets.size(); i++) { ActionListener target = (ActionListener)targets.elementAt(i); target.actionPerformed(actionEvt); } } /** * Enable debugging output. Currently a message is printed each time * the button is clicked. This is a bound property. * * @see #getDebug * @see #addPropertyChangeListener */ public void setDebug(boolean x) { boolean old = debug; debug = x; changes.firePropertyChange("debug", new Boolean(old), new Boolean(x)); } /** * Returns true if debugging output is enabled. * * @see #setDebug */ public boolean getDebug() { return debug; } /** * Set the font size to 18 if true, 12 otherwise. This property overrides * the value specified with setFontSize. This is a bound property. * * @see #isLargeFont * @see #addPropertyChangeListener */ public void setLargeFont(boolean b) { if (isLargeFont() == b) { return; } int size = 12; if (b) { size = 18; } Font old = getFont(); setFont(new Font(old.getName(), old.getStyle(), size)); changes.firePropertyChange("largeFont", new Boolean(!b), new Boolean(b)); } /** * Returns true if the font is "large" in the sense defined by setLargeFont. * * @see #setLargeFont * @see #setFont */ public boolean isLargeFont() { if (getFont().getSize() >= 18) { return true; } else { return false; } } /** * Set the point size of the current font. This is a bound property. * * @see #getFontSize * @see #setFont * @see #setLargeFont * @see #addPropertyChangeListener */ public void setFontSize(int x) { Font old = getFont(); setFont(new Font(old.getName(), old.getStyle(), x)); changes.firePropertyChange("fontSize", new Integer(old.getSize()), new Integer(x)); } /** * Return the current font point size. * * @see #setFontSize */ public int getFontSize() { return getFont().getSize(); } /** * Set the current font and change its size to fit. This is a * bound property. * * @see #setFontSize * @see #setLargeFont */ public void setFont(Font f) { Font old = getFont(); super.setFont(f); sizeToFit(); changes.firePropertyChange("font", old, f); } /** * Set the buttons label and change it's size to fit. This is a * bound property. * * @see #getLabel */ public void setLabel(String newLabel) { String oldLabel = label; label = newLabel; sizeToFit(); changes.firePropertyChange("label", oldLabel, newLabel); } /** * Returns the buttons label. * * @see #setLabel */ public String getLabel() { return label; } public Dimension getPreferredSize() { FontMetrics fm = getFontMetrics(getFont()); return new Dimension(fm.stringWidth(label) + TEXT_XPAD, fm.getMaxAscent() + fm.getMaxDescent() + TEXT_YPAD); } /** * @deprecated provided for backward compatibility with old layout managers. */ public Dimension preferredSize() { return getPreferredSize(); } public Dimension getMinimumSize() { return getPreferredSize(); } /** * @deprecated provided for backward compatibility with old layout managers. */ public Dimension minimumSize() { return getMinimumSize(); } private void sizeToFit() { Dimension d = getPreferredSize(); setSize(d.width, d.height); Component p = getParent(); if (p != null) { p.invalidate(); p.doLayout(); } } /** * Set the color the buttons label is drawn with. This is a bound property. */ public void setForeground(Color c) { Color old = getForeground(); super.setForeground(c); changes.firePropertyChange("foreground", old, c); } /** * Set the color the buttons background is drawn with. This is a bound property. */ public void setBackground(Color c) { Color old = getBackground(); super.setBackground(c); changes.firePropertyChange("background", old, c); } private boolean debug; private PropertyChangeSupport changes = new PropertyChangeSupport(this); private Vector pushListeners = new Vector(); private String label; private boolean down; private boolean sized; static final int TEXT_XPAD = 12; static final int TEXT_YPAD = 8; }