Jump to content

Grinding5.java

From EDM2
Revision as of 16:30, 20 December 2017 by Ak120 (talk | contribs) (Ak120 moved page Grinding Java - Enhancing the AWT:grinding5.java to Grinding5.java)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
package GUITools;
import java.AWT.*;
import java.AWT.event.*;
import java.AWT.image.*;

/**
 * Image button class written by Shai Almog 1996.
 * The sorce is in the public domain and may be modified and used freely.
 * It is not a requirment but I would consider it good manners if you credit me
 * and EDM/2 (www.edm2.com) in applications in which this code was used ;-)
 * The ImageButton class is a class that presents a button with an image on it.
 * It has several features which are not common with most ImageButtons:
 * 1. It's fully compatible with java.AWT.Button since it derives from it.
 * 2. It has 3 modes Image/Text (regular button)/Text and Image.
 * 3. It has 2 types regular and toggle (toggle stays pressed).
 * 4. It can be constructed with 1 to 3 images. If you give it only one image it
 *  will use the class ImageButtonDrawingEngine to draw the up and down states.
 * 5. It has a disabled mode.
**/
public class ImageButton extends Button implements ImageObserver, MouseListener
{
    public ImageButton()
    {
      initImageButton();
    }

    /**
     * This constructor takes the label of the button as a parameter.
    **/
    public ImageButton(String caption)
    {
      initImageButton();
      setCaption(caption);
    }

    /**
     * This constructor takes an Image object as a parameter.
    **/
    public ImageButton(Image imageInstance)
    {
      initImageButton();
      buttonUp = imageInstance; // Setting the images for the buttons.
      buttonDown = buttonUp;    // They are all identical since there is only one picture.
      buttonDisabled = buttonUp;
      waitForImage(buttonUp);   // If the image did not finish loading then wait for it.
    }

    /**
     * This constructor takes both the label and the Image as a parameters.
    **/
    public ImageButton(String caption, Image imageInstance)
    {
      initImageButton();
      setCaption(caption);
      buttonUp = imageInstance; // Setting the images for the buttons.
      buttonDown = buttonUp;    // They are all identical since there is only one picture.
      buttonDisabled = buttonUp;
      waitForImage(buttonUp);   // If the image did not finish loading then wait for it.
    }

    /**
     * This constructor takes both the label and the image name as a parameters.
    **/
    public ImageButton(String caption, String imageName)
    {
      Toolkit Tk = getToolkit();
      buttonUp = Tk.getImage(imageName); // Loading the image from disk.
      initImageButton();
      setCaption(caption);
      buttonDown = buttonUp; // Setting the images for the buttons.
      buttonDisabled = buttonUp; // They are all identical since there is only one picture.
      waitForImage(buttonUp); // If the image did not finish loading then wait for it.
    }

    /**
     * This constructor takes both the label and three image name's as a parameters.
     * These are used for button up/down/disabled states.
    **/
    public ImageButton(String caption, String imageNameButtonUp, String
                       imageNameButtonDown, String imageNameButtonDisabled)
    {

      Toolkit Tk = getToolkit();
      buttonUp = Tk.getImage(imageNameButtonUp); // Loading the image's from disk.
      buttonDown = Tk.getImage(imageNameButtonDown);
      buttonDisabled = Tk.getImage(imageNameButtonDisabled);
      initImageButton();
      setCaption(caption);
      waitForImage(buttonUp);// If the image did not finish loading then wait for it.
        // The reason I only wait for button up is that this class is designed
        // to run localy so there will not be a significant delay.
    }

    public void setUpImage(Image imageInstance) // Sets the image displayed
    { // when the button is up.
      buttonUp = imageInstance;
    }

    public void setDownImage(Image imageInstance)  // Sets the image displayed
    { // when the button is down.
      buttonDown = imageInstance;
    }

    public void setDisabledImage(Image imageInstance)  // Sets the image displayed
    { // when the button is disabled.
      buttonDisabled = imageInstance;
    }

    public void setToggleOn() // Turns the toggle mode on.
    {
      buttonMode = BUTTON_MODE_TOGGLE;
    }

    public void setToggleOff() // Turns the toggle mode off.
    {
      buttonMode = BUTTON_MODE_NORMAL;
      repaint();
    }

    public void setTextX(int x) // Sets the x in which the text on an Image & Text button shows.
    {
      textOnImageButtonX = x;
      repaint();
    }

    public void setTextY(int y) // Sets the y in which the text on an Image & Text button shows.
    {
      textOnImageButtonX = y;
      repaint();
    }

    public void setImageMode() // Sets the button to show as an image button.
    {
      buttonType = BUTTON_TYPE_IMAGE;
      repaint();
    }

    public void setTextMode() // Sets the button to show as a regular button.
    {
      buttonType = BUTTON_TYPE_TEXT;
      repaint();
    }

    /**
     *  Sets the button to show as an image button with text too.
    **/
    public void setTextAndImageMode()
    {
      buttonType = BUTTON_TYPE_TEXT_AND_IMAGE;
      repaint();
    }

    public void setColorOfTextOnButton(Color colorOfTextOnButton) // This will set the color
    { // of the text on the button in case this is an image button with text too.
          this.colorOfTextOnButton = colorOfTextOnButton;
    }

    /**
     * Toggles the button bettwean disabled and enabled mode.
    **/
    public void setEnabled(boolean mode)
    {
      super.setEnabled(mode);
      if (mode)
      {
        buttonState = BUTTON_STATE_UP;
      }
      else
      {
        buttonState = BUTTON_STATE_DISABLED;
      }
    }

    public void setCaption(String caption)
    {
      this.caption = caption;
    }

    public void paint(Graphics g)
    {
      if (BUTTON_TYPE_TEXT == buttonType)
      { // Using the default Java button.
        super.paint(g);
        return;
      }
      switch (buttonState)
      {
        case BUTTON_STATE_UP:
        {
            drawButtonUp(g); // Draws the button up.
            if(BUTTON_TYPE_TEXT_AND_IMAGE == buttonType)
            {
              g.setColor(colorOfTextOnButton);
              // Set the text color to the buttons text color.
              g.drawString(caption,textOnImageButtonX,
                          textOnImageButtonY);
              // Draw the string on the button.
            }
            break;
        }
        case BUTTON_STATE_DOWN :
        {
            drawButtonDown(g); // Draws the button down.
            if(BUTTON_TYPE_TEXT_AND_IMAGE == buttonType)
            {
              g.setColor(colorOfTextOnButton);
              g.drawString(caption,textOnImageButtonX,
                           textOnImageButtonY);
            }
            break;
        }
        case BUTTON_STATE_DISABLED :
        {
            drawButtonDisabled(g); // Draws the button disabled.
            if(BUTTON_TYPE_TEXT_AND_IMAGE == buttonType)
            {
              g.setColor(colorOfTextOnButton);
              g.drawString(caption,textOnImageButtonX,
                           textOnImageButtonY);
            }
            break;
        }
      }

    }

    /**
     * This method is part of the ImageObserver interface, it's called by Image
     * producers to inform us of new information regarding the image.
     * I use this method to wait for the image to compleately load and is sets
     * imageReady to true the moment the image is ready.
    **/
    public boolean ImageUpdate(Image i,int flags, int x,int y,int height, int width)
    {
      imageReady = imageReady || ((flags & ALLBITS) == 0);
      return(true);
    }

    /**
     * This action will cause the button to be pressed.
     * The reason I did not use the action event was that it does not send events
     * for both press and release, we need to know both so we can draw the button
     * correctly.
    **/
    public void mousePressed(MouseEvent e)
    {
      if (buttonMode != BUTTON_MODE_TOGGLE)
        if(buttonState == BUTTON_STATE_UP)
        {
            buttonState = BUTTON_STATE_DOWN;
            repaint();
        }
    }

    public void mouseClicked(MouseEvent e)
    {
      // This method is needed by the mouse listener interface.
    }

    /**
     * This action will cause the button to be released.
     * The reason I did not use the action event was that it does not send events
     * for both press and release, we need to know both so we can draw the button
     * correctly.
    **/
    public void mouseReleased(MouseEvent e)
    {
      if (buttonMode != BUTTON_MODE_TOGGLE)
      {
        if(buttonState == BUTTON_STATE_DOWN)
        {
            buttonState = BUTTON_STATE_UP;
            repaint();
        }
      }
      else
      {
        if(buttonState == BUTTON_STATE_DOWN)
        {
            buttonState = BUTTON_STATE_UP;
        }
        else
        {
            buttonState = BUTTON_STATE_DOWN;
        }
        repaint();
      }
    }

    public void mouseEntered(MouseEvent e)
    {
   // This methods is needed by the mouse listener interface.
    }

    public void mouseExited(MouseEvent e)
    {
   // This methods is needed by the mouse listener interface.
    }

    /**
     * This method draws the button down.
    **/
    private void drawButtonDown(Graphics g)
    {
      Dimension buttonSize = getSize();
      if (buttonDown == buttonUp) // If the same image is used for all the buttons.
      { // Then call the ImageButtonDrawingEngine to redraw the frame.
        ImageButtonDrawingEngine.drawButtonDown(g);
        g.drawImage(buttonDown
           , 0 + ImageButtonDrawingEngine.X_SPACE
           , 0 + ImageButtonDrawingEngine.Y_SPACE
           , buttonSize.width + ImageButtonDrawingEngine.X_SPACE
           , buttonSize.height + ImageButtonDrawingEngine.Y_SPACE
           , this);
      }
      // Otherwize simply draw the correct image.
      else g.drawImage(buttonDown,0,0,buttonSize.width,buttonSize.height,this);
    }

    /**
     * This method draws the button down.
    **/
    private void drawButtonUp(Graphics g)
    {
      Dimension buttonSize = getSize();
      if (buttonDown == buttonUp) // If the same image is used for all the buttons.
      { // Then call the ImageButtonDrawingEngine to redraw the frame.
        ImageButtonDrawingEngine.drawButtonUp(g);
        g.drawImage(buttonUp
           , 0 + ImageButtonDrawingEngine.X_SPACE
           , 0 +ImageButtonDrawingEngine.Y_SPACE
           , buttonSize.width + ImageButtonDrawingEngine.X_SPACE
           , buttonSize.height + ImageButtonDrawingEngine.Y_SPACE
           , this);
      }
      // Otherwize simply draw the correct image.
      else g.drawImage(buttonUp,0,0,buttonSize.width,buttonSize.height,this);
    }

    /**
     * This method draws the button down.
    **/
    private void drawButtonDisabled(Graphics g)
    {
      Dimension buttonSize = getSize();
      if (buttonDown == buttonUp) // If the same image is used for all the buttons.
      { // Then call the ImageButtonDrawingEngine to redraw the frame.
        ImageButtonDrawingEngine.drawButtonDisabled(g);
        g.drawImage(buttonDisabled
           , 0 + ImageButtonDrawingEngine.X_SPACE
           , 0 + ImageButtonDrawingEngine.Y_SPACE
           , buttonSize.width + ImageButtonDrawingEngine.X_SPACE
           , buttonSize.height + ImageButtonDrawingEngine.Y_SPACE
           , this);
      }
      // Otherwise simply draw the correct image.
      else g.drawImage(buttonDisabled,0,0,buttonSize.width,buttonSize.height,this);
    }

    /**
   * This method is closely related to the ImageUpdate method.
   * This method waits for ImageUpdate to set a switch that the image is ready,
   * thus we can know that the image is in fact in memory. This is due to the
   * Image producer - consumer - observer concept.
    **/
    private void waitForImage(Image imageToWaitFor)
    {
      Dimension buttonSize = getSize();
      Toolkit Tk = getToolkit();
      if (!Tk.prepareImage(buttonUp,buttonSize.width,buttonSize.height,this))
        while (!imageReady);
      repaint();
    }

    /**
     * This method initializes the button and is called by all the constructors.
    **/
    private void initImageButton()
    {
      addMouseListener(this); // Listen to mouse related events.
    }

    private static final int BUTTON_TYPE_IMAGE = 0; // These are reuqired
    private static final int BUTTON_TYPE_TEXT = 1;  // to toggle the button
    private static final int BUTTON_TYPE_TEXT_AND_IMAGE = 2; // to image
    private int buttonType = BUTTON_TYPE_IMAGE;// and text modes.
    private int textOnImageButtonX; // These determin where the text in a
    private int textOnImageButtonY; // BUTTON_TYPE_TEXT_AND_IMAGE will sit.
    private Color colorOfTextOnButton = Color.black;

    private static final int BUTTON_MODE_NORMAL = 0; // These are required to
    private static final int BUTTON_MODE_TOGGLE = 1; // toggle the button to toggle
    private int buttonMode = BUTTON_MODE_NORMAL; // mode where it stays pressed.

    private static final int BUTTON_STATE_UP = 0; // These constants reflect the
    private static final int BUTTON_STATE_DOWN = 1; // state of the button.
    private static final int BUTTON_STATE_DISABLED = 2;
    private int buttonState = BUTTON_STATE_UP; // This variable contains one
                                               // of the three constants above.

    private boolean imageReady = false; // This variable is used by the ImageUpdate method.

    private Image buttonUp,// The Image of the button when it's up.
      buttonDown, // The Image of the button when it's down.
      buttonDisabled; // The Image of the button when it's disbaled.
    private String caption; // The text on the button.
}


/**
  * This class was built with the purpose of separating the engine that draws
  * the button pressed and normal from the rest of the code so it can be
  * replaced easily.
  */
class ImageButtonDrawingEngine
{
        public static void drawButtonDown(Graphics g)
        {
               Rectangle bounds = g.getClipBounds();
               g.draw3DRect(0,0,bounds.width,bounds.height,false);
        }
        public static void drawButtonUp(Graphics g)
        {
               Rectangle bounds = g.getClipBounds();
               g.draw3DRect(0,0,bounds.width,bounds.height,false);
        }
        public static void drawButtonDisabled(Graphics g)
        {
               Rectangle bounds = g.getClipBounds();
               g.draw3DRect(0,0,bounds.width,bounds.height,false);
        }
        public static int X_SPACE = 2;
        public static int Y_SPACE = 2;
}