// Copyright 1996, Marimba Inc. All Rights Reserved.

// @(#)ButtonWidget.java, 1.29, 11/28/96



package marimba.gui;



import java.awt.*;

import marimba.persist.*;



/**

 * A button widget. This is the base class for all

 * button-like widgets.

 *

 * @author	Arthur van Hoff

 * @version 	1.29, 11/28/96

 */

public abstract class ButtonWidget extends Widget {

    public boolean  down;

    public boolean  value;

    public String  group;



    /**

     * The label that is displayed on the button.

     * @see #getText

     * @see #setText

     */

    public String  label = "";



    /**

     * Get the properties of this widget.

     */

    public void getProperties(PropertyList list) {

	super.getProperties(list);

	list.setBoolean("disabled", disabled, false);

	list.setBoolean("value", value, false);

	list.setString("group", group, null);

	list.setString("label", label, "");

    }



    /**

     * Set the properties of this widget.

     */

    public void setProperties(PropertyList list) {

	super.setProperties(list);

	disabled = list.getBoolean("disabled", false);

	value = list.getBoolean("value", false);

	group = list.getString("group", null);

	label = list.getString("label", "");

    }



    /**

     * Get the group.

     */

    public String getGroup() {

	return group;

    }



    /**

     * Set the group.

     */

    public void setGroup(String group) {

	this.group = group;

    }



    /**

     * Get the next button in the same group that is not disabled.

     * @see #getPrevious

     * @see #getCurrent

     * @see #groupCount

     * @return	This button if no group has been specified or this is the last button in the group, otherwise the next button.

     */

    public ButtonWidget getNext() {

	ButtonWidget  result = this;

	if (group != null) {

	    // search for this button

	    int  index;

	    for (index = 0; index < parent.nwidgets; index++) {

		Widget w = parent.widgets[index];

		if (w == this) {

		    break;

		}

	    }

	    // search for next button

	    for (int i = index+1; i < parent.nwidgets; i++) {

		Widget w = parent.widgets[i];

		if (w instanceof ButtonWidget) {

		    ButtonWidget b = (ButtonWidget)w;

		    if (!b.disabled && group.equals(b.group)) {

			result = b;

			break;

		    }

		}

	    }

	}

	return result;

    }



    /**

     * Get the previous button in the same group that is not disabled.

     * @see #getNext

     * @see #getCurrent

     * @see #groupCount

     * @return	This button if no group has been specified or this is the first button in the group, otherwise the previous button.

     */

    public ButtonWidget getPrevious() {

	ButtonWidget  result = this;

	if (group != null) {

	    // search for this button

	    int  index;

	    for (index = 0; index < parent.nwidgets; index++) {

		Widget w = parent.widgets[index];

		if (w == this) {

		    break;

		}

	    }

	    // search for previous button

	    for (int i = index-1; i >= 0; i--) {

		Widget w = parent.widgets[i];

		if (w instanceof ButtonWidget) {

		    ButtonWidget b = (ButtonWidget)w;

		    if (!b.disabled && group.equals(b.group)) {

			result = b;

			break;

		    }

		}

	    }

	}

	return result;

    }



    /**

     * Get the current button with the value in the group.

     * @see #getNext

     * @see #getPrevious

     * @see #groupCount

     */

    public ButtonWidget getCurrent() {

	ButtonWidget  result = this;

	if (group != null) {

	    // search for this button

	    int  index;

	    for (index = 0; index < parent.nwidgets; index++) {

		Widget w = parent.widgets[index];

		if (w instanceof ButtonWidget) {

		    ButtonWidget b = (ButtonWidget)w;

		    if (group.equals(b.group) && b.value) {

			result = b;

			break;

		    }

		}

	    }

	}

	return result;

    }



    /**

     * Count the number of widgets in this group.

     * @see #getNext

     * @see #getPrevious

     * @see #getCurrent

     */

    public int groupCount() {

	int  result = 1;

	if (group != null) {

	    for (int index = 0; index < parent.nwidgets; index++) {

		Widget  w = parent.widgets[index];

		if (w != this && w instanceof ButtonWidget) {

		    ButtonWidget b = (ButtonWidget)w;

		    if (group.equals(b.group)) {

			result++;

		    }

		}

	    }

	}

	return result;

    }



    /**

     * Get the value as a boolean.

     */

    public boolean getBooleanValue() {

	return value;

    }



    /**

     * Get the value.

     */

    public Object getValue() {

	return new Boolean(getBooleanValue());

    }



    /**

     * Set the value.

     */

    public void setValue(Object value) {

	if (value instanceof Boolean) {

	    setValue(((Boolean)value).booleanValue());

	} else if (value instanceof String) {

	    setValue(value.equals("true"));

	} else if (value instanceof Number) {

	    setValue(((Number)value).intValue() != 0);

	} else {

	    setValue(value != null);

	}

    }



    /**

     * Set the value of the button.

     */

    public void setValue(boolean value) {

	if (this.value != value) {

	    if (value && (group != null)) {

		for (int i = parent.nwidgets ; i-- > 0 ;) {

		    Widget w = parent.widgets[i];

		    if (w instanceof ButtonWidget) {

			ButtonWidget b = (ButtonWidget)w;

			if (b.value && group.equals(b.group)) {

			    b.value = false;

			    b.repaint();

			}

		    }

		}

	    }

	    this.value = value;

	    repaint();

	}

    }



    /**

     * Get the label of the button.

     * @see #label

     * @see #getLabel

     */

    public String getText() {

	return label;

    }



    /**

     * Set the label of the button.

     * @see #label

     * @see #setLabel

     */

    public void setText(String label) {

	if ((label != null) && !this.label.equals(label)) {

	    this.label = label;

	    repaint();

	}

    }



    /**

     * Get the label.

     * @see #label

     */

    public String getLabel() {

	return getText();

    }



    /**

     * Set the label.

     * @see #label

     */

    public void setLabel(String label) {

	setText(label);

    }



    /**

     * Get the sticky-ness.

     */

    public boolean getSticky() {

	return true;

    }



    /**

     * Set the sticky-ness. This functions does nothing here, but is overridden in subclasses when necessary.

     */

    public void setSticky(boolean sticky) {

    }



    /**

     * Paint the button label.

     */

    public void paintLabel(Graphics g) {

    }



    /**

     * Paint the button itself.

     */

    public void paintButton(Graphics g) {

    }



    /**

     * Paint the button.

     */

    public void paint(Graphics g) {

	paintButton(g);

	paintLabel(g);

    }



    /**

     * Handle mouse events.

     */

    public boolean handleEvent(Event evt) {

	if (!disabled) {

	    switch (evt.id) {

	      case Event.MOUSE_DOWN:

	      case Event.MOUSE_DRAG:

		if (down != ((evt.x >= 0) && (evt.x < width) && (evt.y >= 0) && (evt.y < height))) {

		    down = !down;

		    requestFocus();

		    repaint();

		}

		return false;

		

	      case Event.MOUSE_UP:

		if (down) {

		    down = false;

		    if (getSticky() && ((group == null) || !value)) {

			setValue(!value);

		    }

		    repaint();

		    action();

		}

		return true;



	    case Event.KEY_ACTION:

		switch (evt.key) {

		    case Event.LEFT:

		    case Event.UP:

			getPrevious().requestFocus();

			return true;



		    case Event.RIGHT:

		    case Event.DOWN:

			getNext().requestFocus();

			return true;

		}

		break;



	      case Event.KEY_PRESS:

		switch (evt.key) {

		  case ' ':

		    down = true;

		    repaint();

		    return true;

		}

		break;



	      case Event.KEY_RELEASE:

		switch(evt.key) {

		  case ' ':

		    down = false;

		    if (getSticky() && ((group == null) || !value)) {

			setValue(!value);

		    }

		    repaint();

		    action();

		    return true;

		}

		break;

	    }

	}

	return super.handleEvent(evt);

    }



    /**

     * All buttons supports input focus.

     */

    public boolean focusInterest() {

	return !disabled;

    }



    /**

     * Debugging.

     */

    public void paramString(StringBuffer buf) {

	super.paramString(buf);

	buf.append(",label=");

	buf.append(label);

	buf.append(",value=");

	buf.append(value);

	if (group != null) {

	    buf.append(",group=");

	    buf.append(group);

	}

	if (getSticky()) {

	    buf.append(",sticky");

	}

    }

}

