home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / desvs7nu / src / jannebutton.java < prev    next >
Encoding:
Java Source  |  1996-08-14  |  13.3 KB  |  512 lines

  1. /*
  2.  * Copyright (c) 1996 by Jan Andersson, Torpa Konsult AB.
  3.  *
  4.  * Permission to use, copy, and distribute this software for
  5.  * NON-COMMERCIAL purposes and without fee is hereby granted
  6.  * provided that this copyright notice appears in all copies.
  7.  *
  8.  */
  9. import java.awt.image.*;
  10. import java.awt.*;
  11.  
  12. /**
  13.  * A class that implements an image and/or string labelled button.
  14.  * No fancy animations are supported. It's just a simple button with
  15.  * image support. <p>
  16.  *
  17.  * It is (supposed to be) compatible with the awt.Button class, regarding
  18.  * generated actions event etc. Image does not have to be preloaded and
  19.  * the button is sized when the image size is known.<p>
  20.  *
  21.  * Note: not using preloaded images may cause problems with the layout,
  22.  * depending on the layout manager used for the parent of the button.
  23.  * When the image size is know the layout() function of the parent is
  24.  * called. You might have to resize and/or reshape the parent when
  25.  * the layout() function is called. See how this is done in the class
  26.  * JanneToolbar.
  27.  *
  28.  * Sub-class of Canvas due to the awt design.
  29.  *
  30.  *
  31.  * @version     1.8 96/02/21
  32.  * @author      Jan Andersson, Torpa Konsult AB. (janne@torpa.se)
  33.  */
  34.  
  35. public class JanneButton extends Canvas {
  36.    /**
  37.     * The image 
  38.     */
  39.    protected Image image = null;
  40.  
  41.    /**
  42.     * Flag to keep track of if image size (yet) known  
  43.     */
  44.    protected boolean imageSizeKnown = false;
  45.    
  46.    /**
  47.     * The label string (also used in action event for image buttons)
  48.     */
  49.    protected String label;
  50.  
  51.    /**
  52.     * Flag to keep track if image loaded
  53.     */
  54.    protected boolean imageLoaded = false;
  55.  
  56.    /**
  57.     * Button shadow border width
  58.     */
  59.    protected int shadow = 2;
  60.  
  61.    /**
  62.     * Button border width
  63.     */
  64.    protected int border = 2;
  65.    
  66.    /**
  67.     * The button state.
  68.     */
  69.    protected boolean selected = false;
  70.  
  71.    /**
  72.     * Resize image to actual size of button.
  73.     */
  74.    protected boolean resizeImage = true;
  75.  
  76.    /**
  77.     * Show label as well as image
  78.     */
  79.    protected boolean showLabel = true;
  80.  
  81.    /**
  82.     * Constructs a Button with a string label and/or an image.
  83.     * @param image the button image
  84.     * @param label the button label (used in action events)
  85.     * @param shadow the button shadow width
  86.     * @param border the button border width
  87.     * @param resizeImage true if image to be resized to actual width
  88.     * of button.
  89.     * @param showLabel if label to be displayed as well as image.
  90.     */
  91.    public JanneButton(Image image, String label,
  92.               int shadow, int border,
  93.               boolean resizeImage,
  94.               boolean showLabel) {
  95.       this.image = image;
  96.       if (image == null)
  97.      imageSizeKnown = true;    // kind of ;-)
  98.       this.label = label;
  99.       this.shadow = shadow;
  100.       this.border = border;
  101.       this.resizeImage = resizeImage;
  102.       this.showLabel = showLabel;
  103.    }
  104.  
  105.    /**
  106.     * Constructs a Button with a string label and an image.
  107.     * @param image the button image
  108.     * @param label the button label (used in action events)
  109.     * @param resizeImage true if image to be resized to actual width
  110.     * @param showLabel if label to be displayed as well as image.
  111.     * of button.
  112.     */
  113.    public JanneButton(Image image, String label,
  114.               boolean resizeImage,
  115.               boolean showLabel) {
  116.       this(image, label, 2, 2, resizeImage, showLabel);
  117.    }
  118.  
  119.    /**
  120.     * Constructs a Button with an image.
  121.     * @param image the button image
  122.     * @param label the button label (only used in action events)
  123.     */
  124.    public JanneButton(Image image, String label) {
  125.       this(image, label, 2, 2, false, false);
  126.    }
  127.  
  128.    /**
  129.     * Constructs a Button with an string label.
  130.     * @param label the button label
  131.     */
  132.    public JanneButton(String label) {
  133.       this(null, label, 2, 2, false, true);
  134.    }
  135.    
  136.    /**
  137.     * Gets the string label of the button.
  138.     * @see #setLabel
  139.     */
  140.    public String getLabel() {
  141.         return label;
  142.     }
  143.    
  144.    /**
  145.     * Sets the string label of the button.
  146.     * @param label the label to set the button with
  147.     * @see #getLabel
  148.     */
  149.    public void setLabel(String label) {
  150.       this.label = label;
  151.       layoutParent();
  152.       repaint();
  153.     }
  154.  
  155.    /**
  156.     * Gets the image of the button.
  157.     * @see #setImage
  158.     */
  159.    public Image getImage() {
  160.       return image;
  161.    }
  162.    
  163.    /**
  164.     * Sets the image of the button.
  165.     * @param image the image to set the button with
  166.     * @see #getImage
  167.     */
  168.    public void setImage(Image image) {
  169.       this.image = image;
  170.       layoutParent();
  171.       repaint();
  172.    }
  173.  
  174.    /**
  175.     * Gets the resizeImage flag of the button.
  176.     * @see #setResizeImage
  177.     */
  178.    public boolean getResizeImage() {
  179.       return resizeImage;
  180.    }
  181.    
  182.    /**
  183.     * Sets the resizeImage flag of the button.
  184.     * @param resizeImage true if image to be resized to actual width
  185.     * of button.
  186.     */
  187.    public void setResizeImage(boolean resizeImage) {
  188.       this.resizeImage = resizeImage;
  189.       layoutParent();
  190.       repaint();
  191.    }
  192.  
  193.    /**
  194.     * Gets the showLabel flag of the button.
  195.     * @see #setShowLabel
  196.     */
  197.    public boolean getShowLabel() {
  198.       return showLabel;
  199.    }
  200.    
  201.    /**
  202.     * Sets the showLabel flag of the button.
  203.     * @param showLabel true if label to be displayed as well as image.
  204.     */
  205.    public void setShowLabel(boolean showLabel) {
  206.       this.showLabel = showLabel;
  207.       layoutParent();
  208.       repaint();
  209.    }
  210.  
  211.    /**
  212.     * Check if image size (yet) known
  213.     */
  214.    public boolean imageSizeKnown() {
  215.       return imageSizeKnown;
  216.    }
  217.  
  218.    /**
  219.     * Returns the parameter String of this button.
  220.     */
  221.    protected String paramString() {
  222.       return super.paramString() + ",label=" + label;
  223.    }
  224.    
  225.    /**
  226.     * Repaints the button when the image has changed.
  227.     * Set flag if some bits loaded.
  228.     * @return true if image has changed; false otherwise.
  229.     */
  230.    public boolean imageUpdate(Image img, int flags,
  231.                   int x, int y, int w, int h) {
  232.       if ((flags & SOMEBITS) != 0) {
  233.      // part of the image is loaded; start painting
  234.      imageLoaded = true;
  235.       }
  236.       if ((flags & (HEIGHT|WIDTH)) != 0) {
  237.      // got the size; make sure we (re-) layout parent.
  238.      imageSizeKnown = true;
  239.      layoutParent();
  240.       }
  241.       return super.imageUpdate(img, flags, x, y, w, h);
  242.    }
  243.    
  244.    /**
  245.     * Re-layout parent. Called when a button changes image,
  246.     * size etc.
  247.     */
  248.    protected void layoutParent() {
  249.       Container parent = getParent();
  250.       if (parent != null) {
  251.      parent.layout();
  252.       }
  253.    }
  254.  
  255.    /** 
  256.     * Paints the button.
  257.     * @param g the specified Graphics window
  258.     */
  259.    public void paint(Graphics g) {
  260.       Dimension size = size();
  261.       if (isVisible()) {
  262.      if (isEnabled()) {
  263.         if (selected)
  264.            paintSelected(g, size);
  265.         else
  266.            paintUnSelected(g, size);
  267.      }
  268.      else if (!isEnabled())
  269.         paintDisabled(g, size);
  270.       }
  271.    }
  272.  
  273.    /** 
  274.     * Paints the button when selected.
  275.     * @param g the specified Graphics window
  276.     * @param size the button size
  277.     * @see #paint
  278.     */
  279.    protected void paintSelected(Graphics g, Dimension size) {
  280.       Color c = getBackground();
  281.       g.setColor(c);
  282.       draw3DRect(g, 0, 0, size.width, size.height, false);
  283.       drawBody(g, size);
  284.    }
  285.  
  286.    /** 
  287.     * Paints the button when not selected.
  288.     * @param g the specified Graphics window
  289.     * @param size the button size
  290.     * @see #paint
  291.     */
  292.    protected void paintUnSelected(Graphics g, Dimension size) {
  293.       Color c = getBackground();
  294.       g.setColor(c);
  295.       g.fillRect(0, 0, size.width, size.height);
  296.       draw3DRect(g, 0, 0, size.width, size.height, true);
  297.       drawBody(g, size);
  298.    }
  299.    
  300.    /** 
  301.     * Paints the button when disabled.
  302.     * @param g the specified Graphics window
  303.     * @param size the button size
  304.     * @see #paint
  305.     */
  306.    protected void paintDisabled(Graphics g, Dimension size) {
  307.       Color c = getBackground();
  308.       g.setColor(c);
  309.       g.fillRect(0, 0, size.width, size.height);
  310.       draw3DRect(g, 0, 0, size.width, size.height, true);
  311.  
  312.       // BUG ALERT: we should really do something "smart" to indicate
  313.       // that an image is disabled here...
  314.  
  315.       // use a gray foreground for string label
  316.       Color fg = getForeground();
  317.       setForeground(Color.gray);
  318.       drawBody(g, size);
  319.       setForeground(fg);
  320.    }
  321.  
  322.    /** 
  323.     * Draw a 3D Rectangle.
  324.     * @param g the specified Graphics window
  325.     * @param x, y, width, height
  326.     * @param raised - true if border should be painted as raised.
  327.     * @see #paint
  328.     */
  329.    public void draw3DRect(Graphics g, int x, int y, int width, int height,
  330.               boolean raised) {
  331.       Color c = g.getColor();
  332.       Color brighter = c.brighter();
  333.       Color darker = c.darker();
  334.  
  335.       // upper left corner
  336.       g.setColor(raised ? brighter : darker);
  337.       for (int i=0; i<shadow; i++) {
  338.      g.drawLine(x+i, y+i, x+width-1-i, y+i);
  339.      g.drawLine(x+i, y+i, x+i, y+height-1-i);
  340.       }
  341.       // lower right corner
  342.       g.setColor(raised ? darker : brighter);
  343.       for (int i=0; i<shadow; i++) {
  344.      g.drawLine(x+i, y+height-1-i, x+width-1-i, y+height-1-i);
  345.      g.drawLine(x+width-1-i, y+height-1-i, x+width-1-i, y+i);
  346.       }
  347.       g.setColor(c);
  348.    }    
  349.  
  350.    /** 
  351.     * Draw body of button. I.e image and/or label string
  352.     * @param g the specified Graphics window
  353.     * @param size the button size
  354.     * @see #paint
  355.     */
  356.    protected void drawBody(Graphics g, Dimension size) {
  357.       int selOff = selected ? 1 : 0;
  358.       int labelX = 0;
  359.       int labelY = 0;
  360.       int labelW = 0;
  361.       int labelH = 0;
  362.       FontMetrics fm = null;
  363.       if (image == null || showLabel) {
  364.      // calculate size and x/y pos. of label string
  365.      Font f = getFont();
  366.      fm = getFontMetrics(f);
  367.      labelH = fm.getAscent() + fm.getDescent();
  368.      labelW = fm.stringWidth(label);
  369.      labelX = size.width/2 - labelW/2 + selOff;
  370.      labelY = size.height/2 - labelH/2 + fm.getAscent() + selOff;
  371.       }
  372.       if (image != null) {
  373.      // draw image
  374.      int x, y, w, h;
  375.      if (resizeImage) {
  376.         // image resized to actual button size
  377.         x = shadow + border + selOff;
  378.         y = shadow + border + selOff;
  379.         w = size.width - 2*(shadow+border) - selOff;
  380.         h = size.height - 2*(shadow+border) - selOff;
  381.         if (showLabel)
  382.            h -= (labelH + border);
  383.      }
  384.      else {
  385.         // image centered in button
  386.         Dimension d = new Dimension();
  387.         d.width = image.getWidth(this);
  388.         d.height = image.getHeight(this);
  389.         if (d.width > 0 && d.height > 0)
  390.            imageSizeKnown = true;
  391.         w = d.width - selOff;
  392.         h = d.height - selOff;
  393.         if (showLabel) {
  394.            x = size.width/2 - d.width/2 + selOff;
  395.            y = (size.height - labelH - border - shadow)/2 -
  396.           d.height/2 + selOff;
  397.         }
  398.         else {
  399.            x = size.width/2 - d.width/2 + selOff;
  400.            y = size.height/2 - d.height/2 + selOff;
  401.         }
  402.      }
  403.      g.drawImage(image, x, y, w, h, this);
  404.      if (showLabel) {
  405.         // draw label string, below image
  406.         g.setColor(getForeground());
  407.         labelY = size.height - fm.getDescent() -
  408.            border - shadow - selOff;
  409.         g.drawString(label, labelX, labelY);
  410.      }
  411.       }
  412.       else {
  413.      // no image; draw label string
  414.      g.setColor(getForeground());
  415.      g.drawString(label,  labelX, labelY);
  416.       }
  417.    }
  418.  
  419.    /** 
  420.     * Returns the preferred size of this component.
  421.     * @see #minimumSize
  422.     * @see LayoutManager
  423.     */
  424.    public Dimension preferredSize() {
  425.       return minimumSize();
  426.    }
  427.    
  428.    /**
  429.     * Returns the minimum size of this component.
  430.     * @see #preferredSize
  431.     * @see LayoutManager
  432.     */
  433.    public synchronized Dimension minimumSize() {
  434.       Dimension d = new Dimension();
  435.       Dimension labelDimension = new Dimension();
  436.       if (image == null || showLabel) {
  437.      // get size of label
  438.      FontMetrics fm = getFontMetrics(getFont());
  439.      labelDimension.width = fm.stringWidth(label) + 2*(shadow+border);
  440.      labelDimension.height = fm.getAscent() + fm.getDescent() +
  441.         2*(shadow+border);
  442.      if (image == null)
  443.         d = labelDimension;
  444.       }
  445.       if (image != null) {
  446.      // image used; get image size (If the height is not known
  447.      // yet then the ImageObserver (this) will be notified later
  448.      // and -1 will be returned).
  449.      d.width = image.getWidth(this) ;
  450.      d.height = image.getHeight(this);
  451.      if (d.width > 0 && d.height > 0) {
  452.         // size known; adjust for shadow and border
  453.         d.width += 2*(shadow+border);
  454.         d.height += 2*(shadow+border);
  455.         if (showLabel) {
  456.            // show label as well as image; adjust for label size
  457.            if (labelDimension.width > d.width)
  458.           d.width = labelDimension.width;
  459.            d.height += labelDimension.height - 2*shadow - border;
  460.         }
  461.      }
  462.       }
  463.       return d;
  464.    }
  465.  
  466.    /**
  467.     * Called if the mouse is down.
  468.     * @param evt the event 
  469.     * @param x the x coordinate
  470.     * @param y the y coordinate
  471.     */
  472.    public boolean mouseDown(Event evt, int x, int y) {
  473.       // mark as selected and repaint
  474.       selected = true;
  475.       repaint();
  476.       return true;
  477.    }
  478.    
  479.    /**
  480.     * Called when the mouse exits the button.
  481.     * @param evt the event
  482.     * @param x the x coordinate
  483.     * @param y the y coordinate
  484.     */
  485.    public boolean mouseExit(Event evt, int x, int y) {
  486.       if (selected) {
  487.      // mark as un-selected and repaint
  488.      selected = false;
  489.      repaint();
  490.       }
  491.       return true;
  492.    }
  493.    
  494.    /**
  495.     * Called if the mouse is up.
  496.     * @param evt the event
  497.     * @param x the x coordinate
  498.     * @param y the y coordinate
  499.     */
  500.    public boolean mouseUp(Event evt, int x, int y) {
  501.       if (selected) {
  502.      // mark as un-selected and repaint
  503.      selected = false;
  504.      repaint();
  505.      // generate action event
  506.      Event event = new Event(this, Event.ACTION_EVENT, (Object) label);
  507.      deliverEvent(event);
  508.       }
  509.       return true;
  510.    }
  511. }
  512.