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


// @(#)CommandButtonWidget.java, 1.65, 12/20/96





package marimba.gui;





import java.awt.*;





import marimba.persist.*;





/**


 * A command button widget.


 *


 * @author	Arthur van Hoff


 * @author	Klaas Waslander


 * @version 	1.65, 12/20/96


 */


public class CommandButtonWidget extends ButtonWidget {


    /**


     * A CommandButton can be invisible, raised, filled, square,


     * rounded and can contain a picture.


     * @see #getMode


     * @see #setMode


     * @see #modeOptions


     */


    public int mode;





    /**


     * The possible options for the mode.


     * @see #getModeOptions()


     * @see #mode


     */


    public static Options modeOptions = new Options();


    static {


	modeOptions.add("invisible", INVISIBLE);


	modeOptions.add("raised", RAISED);


	modeOptions.add("filled", FILLED);


	modeOptions.add("square", SQUARE);


	modeOptions.add("rounded", ROUNDED);


	modeOptions.add("picture", PICTURE);


    }





    /**


     * A sticky button remains down or up after a mouse-click


     * to visualize that the value remains set or unset.


     * @see #isSticky


     * @see #setSticky


     */


    public boolean sticky;





    /**


     * The source-file for the image.


     * @see #getSource


     * @see #setSource


     */


    public String  src;





    /**


     * A button can be the default button.


     * @see #isDefault


     * @see #setDefault


     */


    public boolean  isDefault;





    /**


     * The image that is used for the command button.


     * You can set the image by setting the source


     * and in that way persistify it, or set the image


     * directly.


     * @see #getImage


     * @see #setImage


     */


    public Image  img;








    /**


     * Constructor


     */


    public CommandButtonWidget() {


	this("Button", RAISED);


    }





    /**


     * Constructor


     */


    public CommandButtonWidget(String label) {


	this(label, RAISED);


    }


    /**


     * Constructor


     */


    public CommandButtonWidget(String label, int mode) {


	this.label = label;


	this.mode = mode;


    }





    /**


     * Get the properties of this widget.


     */


    public void getProperties(PropertyList list) {


	super.getProperties(list);


	list.setBoolean("default", isDefault, false);


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


	list.setOption("mode", modeOptions, mode, RAISED);


	list.setURL("src", src, null);


    }





    /**


     * Set the properties of this widget.


     */


    public void setProperties(PropertyList list) {


	super.setProperties(list);


	setDefault(list.getBoolean("default", false));


	setSticky(list.getBoolean("sticky", false));


	mode = list.getOption("mode", modeOptions, RAISED);


	src = list.getURL("src", null);


	transparent = (mode == INVISIBLE) || (mode == RAISED) || (mode == PICTURE);


    }





    /**


     * Get the possible options for the mode.


     * @see #modeOptions


     */


    public Options getModeOptions() {


	return modeOptions;


    }





    /**


     * Check if this commandbutton is the default one.


     * @see #isDefault


     */


    public boolean isDefault() {


	return isDefault;


    }





    /**


     * Set if this button is the default button or not.


     * @see #isDefault


     */


    public void setDefault(boolean isDefault) {


	this.isDefault = isDefault && (!sticky) && (!disabled);


	repaint();


    }





    /**


     * Get the editor.


     */


    public String getEditor() {


	return "marimba.builder.CommandButtonWidgetEditor";


    }





    /**


     * Get the sticky-ness.


     * @see #sticky


     */


    public boolean isSticky() {


	return sticky;


    }





    /**


     * Set the sticky-ness.


     * @see #sticky


     */


    public void setSticky(boolean sticky) {


	if (this.sticky != sticky) {


	    this.sticky = sticky;


	    if (!sticky) {


		down = false;


		value = false;


	    } else {


		isDefault = false;


	    }


	    repaint();


	}


    }





    /**


     * Get the source-file for the image.


     * @see #src


     */


    public String getSource() {


	return src;


    }





    /**


     * Set the source-file for the image.


     * @see #src


     */


    public void setSource(String src) {


	this.src = src;


	img = null;


	if (isShowing()) {


	    start();


	}


	repaint();


    }





    /**


     * The image for the command button.


     */


    public Image getImage() {


	return img;


    }





    /**


     * Set the image for the command button.


     */


    public void setImage(Image img) {


	this.img = img;


	if (img == null) {


	    src = null;


	}


	repaint();


    }





    /**


     * Get the mode of this button.


     * @see #mode


     */


    public int getMode() {


	return mode;


    }





    /**


     * Set the mode for the button.


     * @see #mode


     */


    public void setMode(int mode) {


	this.mode = mode;


	if (mode == PICTURE) {


	    setSource(src);


	}


	repaint();


    }





    /**


     * Start loading the image label (if any)


     */


    public void start() {


	img = null;


	if ((mode == PICTURE) && (src != null)) {


	    Image newimg = getImage(src);


	    if (Toolkit.getDefaultToolkit().prepareImage(newimg, -1, -1, this)) {


		img = newimg;


		repaint();


	    }


	}


    }





    /**


     * Update the image.


     */


    public boolean imageUpdate(Image newimg, int flags, int x, int y, int w, int h) {


	if ((flags & ALLBITS) != 0) {


	    img = newimg;


	    repaint();


	    return false;


	}


	return (flags & ERROR) == 0;


    }





    /**


     * A sticky commandButton cannot request the focus.


     * So when the button is sticky this method won't do anything.


     */


    public void requestFocus() {


	if (!sticky) {


	    super.requestFocus();


	}


    }





    /**


     * Paint the button label.


     */


    public void paintLabel(Graphics g, String str, int x, int y) {


	g.drawString(str, x, y);


    }





    /**


     * Paint the button label.


     */


    public void paintLabel(Graphics g) {


	if (editor == null) {


	    switch (mode) {


	      case PICTURE:


		if (img != null) {


		    int w = img.getWidth(this);


		    int h = img.getHeight(this);


		    if ((w > 0) && (h > 0)) {


			int  lx = (width - w)/2;


			int  ly = (height - h)/2;


			int  clipX = 1;


			int  clipY = 1;


			if (value ^ down) {


			    lx++;


			    ly++;


			    clipX++;


			    clipY++;


			}


			Graphics g2 = g.create();


			try {


			    g2.clipRect(clipX, clipY, width-3, height-3);


			    g2.drawImage(img, lx, ly, this);


			} finally {


			    g2.dispose();


			}


			//g.drawImage(img, lx, ly, this);


		    }


		}


		break;





	      case INVISIBLE:


		break;





	      default:


		FontMetrics fm = g.getFontMetrics();


		int lx = (width - fm.stringWidth(label))/2;


		int ly = (height - fm.getHeight())/2 + fm.getAscent();


		if (value ^ down) {


		    lx += 1;


		    ly += 1;


		}


		if (disabled) {


		    Color back = (mode == RAISED) ? parent.background : background;


		    g.setColor(Bevel.getBrighter(back, true));


		    paintLabel(g, label, lx+1, ly+1);


		    g.setColor(Bevel.getDarker(back, true));


		    paintLabel(g, label, lx, ly);


		} else {


		    g.setColor(foreground);


		    paintLabel(g, label, lx, ly);


		}


	    }


	}


    }





    /**


     * Paint the button.


     */


    public void paintButton(Graphics g) {


	int x = 0;


	int y = 0;


	int width = this.width;


	int height = this.height;


	boolean  drawDefaultRect = false;





	// Draw as default if the button is not sticky and: has the focus or is


	// the default and the focus is held by something which is not a button.


	if (!sticky && (focus || (isDefault && !(currentFocus() instanceof CommandButtonWidget)))) {


	    drawDefaultRect = true;


	    x += 1;


	    y += 1;


	    width -= 2;


	    height -= 2;


	}





	switch (mode) {


	  case INVISIBLE:


	    return;





	  case SQUARE:


	    if (drawDefaultRect) {


	      g.setColor(Color.black);


	      g.drawRect(0, 0, this.width-1, this.height-1);


	    }


	    g.setColor((value ^ down) ? hilite : background);


	    g.fillRect(x + 1, y + 1, width-2, height-2);


	    g.setColor(foreground);


	    g.drawRect(x, y, width-1, height-1);


	    break;





	  case ROUNDED:


	    if (drawDefaultRect) {


	      g.setColor(Color.black);


	      g.drawRoundRect(0, 0, this.width-1, this.height-1, 14, 14);


	    }


	    g.setColor((value ^ down) ? hilite : background);


	    g.fillRoundRect(x, y, width-1, height-1, 14, 14);


	    g.setColor(foreground);


	    g.drawRoundRect(x, y, width-1, height-1, 14, 14);


	    break;





	  case FILLED:


	    if (drawDefaultRect) {


	      g.setColor(Color.black);


	      g.drawRect(0, 0, this.width-1, this.height-1);


	    }


	    g.setColor(background);


	    Bevel.fillBorder(g, x, y, width, height, !(value ^ down));


	    break;





	  default:


	    if (drawDefaultRect) {


	      g.setColor(Color.black);


	      g.drawRect(0, 0, this.width-1, this.height-1);


	    }


	    g.setColor(parent.background);


	    Bevel.drawBorder(g, x, y, width, height, !(value ^ down));


	    break;


	}





	if (!sticky && focus && !disabled) {


	    paintFocus(g);


	}


    }   





    /**


     * Paint something more when focused.


     */


    public void paintFocus(Graphics g) {


	g.setColor(getFocusColor());


	Dash.drawFocusRect(g, 3, 3, this.width - 7, this.height - 7);


    }





    /**


     * Handle keyboard event when pressing return and do


     * some defaultButton operations when it gets the focus.


     */


    public boolean handleEvent(Event evt) {


	if (!disabled) {


	    switch (evt.id) {


	      case Event.KEY_PRESS: {


		  switch (evt.key) {


		    case '\n':


		      down = false;


		      repaint();


		      action();


		      return true;


		  }


		  break;


	      }





	      case Event.LOST_FOCUS:


	      case Event.GOT_FOCUS: {


		  repaint();


		  Widget defaultButton = getDefaultButton();


		  if (defaultButton != null) {


		      defaultButton.repaint();


		  }


		  return true;


	      }


	    }


	}


	return super.handleEvent(evt);


    }





    /**


     * CommandButtons can only support input focus when they


     * are not sticky and their mode is not invisible.


     */


    public boolean focusInterest() {


	if (!getSticky() && mode!=INVISIBLE) {


	    return super.focusInterest();


	} else {


	    return false;


	}


    }





    /**


     * Debugging.


     */


    public void paramString(StringBuffer buf) {


	super.paramString(buf);


	buf.append(",mode=");


	buf.append(modeOptions.get(mode));


    }





    /**


     * This function has been replaced by isSticky().


     * It is only here for backward compatibility but will be


     * removed in a future version.


     * @see #isSticky


     */


    public boolean getSticky() {


	return sticky;


    }


}


