home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / Source.bin / ImageButton.java < prev    next >
Text File  |  1998-03-18  |  18KB  |  613 lines

  1. package symantec.itools.awt;
  2.  
  3. import java.awt.AWTException;
  4. import java.awt.Color;
  5. import java.awt.Dimension;
  6. import java.awt.Event;
  7. import java.awt.Graphics;
  8. import java.awt.Image;
  9. import java.awt.MediaTracker;
  10. import java.awt.image.FilteredImageSource;
  11. import java.net.URL;
  12. import java.beans.PropertyVetoException;
  13. import java.beans.PropertyChangeListener;
  14. import java.beans.VetoableChangeListener;
  15. import java.beans.PropertyChangeEvent;
  16. import java.text.MessageFormat;
  17. import java.util.ResourceBundle;
  18.  
  19. //    01/18/97    RKM    Changed setImageURL to handle getImage returning null, added call to invalidate
  20. //    01/29/97    TWB    Integrated changes from Macintosh
  21. //    05/29/97    MSH    Updated to support Java 1.1
  22. //     07/08/97    LAB    Changed the way the button is drawn.  Now it uses the offscreen
  23. //                    Image.  Cleaned up the drawing code to be more universal.
  24. //                    Added pressed and disabled images for those states.
  25. //                    Changed data member url to imageURL.
  26. //                    Added a preferedSize() method.
  27. //    07/13/97    RKM    Fixed misspelling of prefered
  28. //  07/30/97    CAR marked fields transient as needed
  29. //                  implemented readObject
  30. //     08/05/97    LAB    Added a call to clipRect in the updateButtonImage method to clip subsequent
  31. //                    drawings to the internal button area (sans border and bevel). This should be
  32. //                    removed when the VM interprets the base class' call to clipRect correctly.
  33. //                    removed scale and center protected data members.  Added imageStyle protected
  34. //                    data member.  Added public data members to define ImageStyles.  Deprecated
  35. //                    setScaleMode, isScaleMode, setCenterMode, and isCenterMode.  Added
  36. //                    ImageStyle property.
  37. //     08/06/97    LAB    Removed the call to clipRect; now uses the base classes buttonImageGraphics
  38. //                    Graphics to draw with, which inherits the clipping.
  39. //  08/28/97    CAR "erase" image if Image URL is set to null
  40.  
  41. /**
  42.  * The ImageButton component is similar to a regular button except that it
  43.  * displays an image on the button's face. The image to use is specified with
  44.  * a URL.
  45.  * <p>
  46.  * Use an ImageButton to:
  47.  * <UL>
  48.  * <DT>╖ Display an image in a button instead of text.</DT>
  49.  * <DT>╖ Generate a train of action events while the user presses the button.</DT>
  50.  * </UL>
  51.  * <p>
  52.  * @version 1.1, August 5, 1997
  53.  * @author Symantec
  54.  */
  55. public class ImageButton extends ButtonBase
  56. {
  57.     /**
  58.      * A constant indicating the image is to be tiled in the size of this component.
  59.      */
  60.     public static final int IMAGE_TILED = 0;
  61.     /**
  62.      * A constant indicating the image is to be centered in the size of this component.
  63.      */
  64.     public static final int IMAGE_CENTERED = 1;
  65.     /**
  66.      * A constant indicating the image is to be scaled to fit the size of this component.
  67.      */
  68.     public static final int IMAGE_SCALED_TO_FIT = 2;
  69.     /**
  70.      * A constant indicating the image is to be drawn normally in the upper left corner.
  71.      */
  72.     public static final int IMAGE_NORMAL = 3;
  73.  
  74.     /**
  75.      * Constructs a new default ImageButton. Image scaling is off and center mode on.
  76.      */
  77.     public ImageButton()
  78.     {
  79.         try
  80.         {
  81.             setImageStyle(IMAGE_CENTERED);
  82.         }
  83.         catch (PropertyVetoException exc) {}
  84.     }
  85.  
  86.     /**
  87.      * Sets the URL of the image to display in the button.
  88.      * @param u the URL of the image to display
  89.      * @see #getImageURL
  90.      * @exception PropertyVetoException
  91.      * if the specified property value is unacceptable
  92.      */
  93.     public void setImageURL(URL u) throws PropertyVetoException
  94.     {
  95.         URL oldValue = imageURL;
  96.  
  97.         vetos.fireVetoableChange( "ImageURL", oldValue, u );
  98.  
  99.         // Remove old images
  100.         enabledImage = null;
  101.         if (disabledImage != null)
  102.             disabledImage.flush();
  103.         disabledImage = null;
  104.         if (pressedImage != null)
  105.             pressedImage.flush();
  106.         pressedImage = null;
  107.  
  108.         // Load new image
  109.  
  110.         imageURL = u;
  111.         if (imageURL != null) {
  112.             Image image = getToolkit().getImage(imageURL);
  113.             if (image != null)
  114.             {
  115.                 MediaTracker mt = new MediaTracker(this);
  116.                 if (mt != null)
  117.                 {
  118.                     try
  119.                     {
  120.                         mt.addImage(image, 0);
  121.                         mt.waitForAll();
  122.                     }
  123.                     catch (InterruptedException ie)
  124.                     {
  125.                     }
  126.  
  127.                     if (mt.isErrorAny())
  128.                     {
  129.                         Object[] args = { image.toString() };
  130.                         System.err.println(MessageFormat.format(errors.getString("ErrorLoadingImage"), args));
  131.                         return;
  132.                     }
  133.  
  134.                     enabledImage    = image;
  135.                     disabledImage    = createImage(new FilteredImageSource(image.getSource(), new symantec.itools.awt.image.FadeFilter(0.333)));
  136.                     pressedImage    = createImage(new FilteredImageSource(image.getSource(), new symantec.itools.awt.image.DarkenFilter(0.250)));
  137.  
  138.                     changes.firePropertyChange( "ImageURL", oldValue, u );
  139.                 }
  140.             }
  141.         }
  142.         repaint();
  143.     }
  144.  
  145.     /**
  146.      * Returns the URL of the image being displayed in the button.
  147.      * @see #setImageURL
  148.      */
  149.     public URL getImageURL()
  150.     {
  151.         return imageURL;
  152.     }
  153.  
  154.     /**
  155.      * Sets the new panel image style.
  156.      * @param newStyle the new panel image style, one of
  157.      * IMAGE_TILED, IMAGE_CENTERED, IMAGE_SCALED_TO_FIT, or IMAGE_NORMAL.
  158.      * @exception PropertyVetoException
  159.      * if the specified property value is unacceptable
  160.      * @see #getImageStyle
  161.      * @see #IMAGE_TILED
  162.      * @see #IMAGE_CENTERED
  163.      * @see #IMAGE_SCALED_TO_FIT
  164.      * @see #IMAGE_NORMAL
  165.      */
  166.     public void setImageStyle(int newStyle) throws PropertyVetoException
  167.     {
  168.         if (newStyle != imageStyle)
  169.         {
  170.             Integer oldValue = new Integer(imageStyle);
  171.             Integer newValue = new Integer(newStyle);
  172.  
  173.             vetos.fireVetoableChange("ImageStyle", oldValue, newValue);
  174.  
  175.             imageStyle = newStyle;
  176.             repaint();
  177.  
  178.             changes.firePropertyChange("ImageStyle", oldValue, newValue);
  179.         }
  180.     }
  181.  
  182.     /**
  183.      * Gets the current panel image style.
  184.      * @return the current panel image style, one of
  185.      * IMAGE_TILED, IMAGE_CENTERED, IMAGE_SCALED_TO_FIT, or IMAGE_NORMAL.
  186.      * @see #setImageStyle
  187.      * @see #IMAGE_TILED
  188.      * @see #IMAGE_CENTERED
  189.      * @see #IMAGE_SCALED_TO_FIT
  190.      */
  191.     public int getImageStyle()
  192.     {
  193.         return imageStyle;
  194.     }
  195.  
  196.     /**
  197.      * @deprecated
  198.      * @see #setImageStyle
  199.      * @exception PropertyVetoException
  200.      * if the specified property value is unacceptable
  201.      */
  202.     public void setScaleMode(boolean flag) throws PropertyVetoException
  203.     {
  204.         if (flag)
  205.         {
  206.             setImageStyle(IMAGE_SCALED_TO_FIT);
  207.         }
  208.         else
  209.         {
  210.             setImageStyle(IMAGE_NORMAL);
  211.         }
  212.     }
  213.  
  214.     /**
  215.      * @deprecated
  216.      * @see #getImageStyle
  217.      */
  218.     public boolean isScaleMode()
  219.     {
  220.         return (getImageStyle() == IMAGE_SCALED_TO_FIT);
  221.     }
  222.  
  223.     /**
  224.      * @deprecated
  225.      * @see #isScaleMode
  226.      */
  227.     public boolean getScaleMode()
  228.     {
  229.         return isScaleMode();
  230.     }
  231.  
  232.     /**
  233.      * @deprecated
  234.      * @see #setImageStyle
  235.      * @exception PropertyVetoException
  236.      * if the specified property value is unacceptable
  237.      */
  238.     public void setCenterMode(boolean flag) throws PropertyVetoException
  239.     {
  240.         if (flag)
  241.         {
  242.             setImageStyle(IMAGE_CENTERED);
  243.         }
  244.         else
  245.         {
  246.             setImageStyle(IMAGE_NORMAL);
  247.         }
  248.     }
  249.  
  250.     /**
  251.      * @deprecated
  252.      * @see #getImageStyle
  253.      */
  254.     public boolean isCenterMode()
  255.     {
  256.         return (getImageStyle() == IMAGE_CENTERED);
  257.     }
  258.  
  259.     /**
  260.      * @deprecated
  261.      * @see #isCenterMode
  262.      */
  263.     public boolean getCenterMode()
  264.     {
  265.         return isCenterMode();
  266.     }
  267.  
  268.     /**
  269.      * Is the given image style valid for this button.
  270.      * @param i the given image style
  271.      * @return true if the given image style is acceptable, false if not.
  272.      */
  273.     public boolean isValidImageStyle(int i)
  274.     {
  275.         switch(i)
  276.         {
  277.                case IMAGE_TILED:
  278.             case IMAGE_CENTERED:
  279.             case IMAGE_SCALED_TO_FIT:
  280.             case IMAGE_NORMAL:
  281.                 return true;
  282.             default:
  283.                 return false;
  284.         }
  285.     }
  286.  
  287.     /**
  288.      * Returns the recommended dimensions to properly display this component.
  289.      * This is a standard Java AWT method which gets called to determine
  290.      * the recommended size of this component.
  291.      */
  292.     public Dimension getPreferredSize()
  293.     {
  294.         Dimension defaultSize = super.getPreferredSize();
  295.  
  296.         if (enabledImage == null)
  297.             return defaultSize;
  298.  
  299.         return new Dimension(defaultSize.width + enabledImage.getWidth(this), defaultSize.height + enabledImage.getHeight(this));
  300.     }
  301.  
  302.     /**
  303.      * Tells this component that it has been added to a container.
  304.      * This is a standard Java AWT method which gets called by the AWT when
  305.      * this component is added to a container. Typically, it is used to
  306.      * create this component's peer.
  307.      *
  308.      * It has been overridden here to hook-up event listeners.
  309.      *
  310.      * @see #removeNotify
  311.      */
  312.     public synchronized void addNotify()
  313.     {
  314.         super.addNotify();
  315.         errors = ResourceBundle.getBundle("symantec.itools.resources.ErrorsBundle");
  316.  
  317.         //Hook up listeners
  318.         if (styleVeto == null)
  319.         {
  320.             styleVeto = new StyleVeto();
  321.             addImageStyleListener(styleVeto);
  322.         }
  323.     }
  324.  
  325.     /**
  326.      * Tells this component that it is being removed from a container.
  327.      * This is a standard Java AWT method which gets called by the AWT when
  328.      * this component is removed from a container. Typically, it is used to
  329.      * destroy the peers of this component and all its subcomponents.
  330.      *
  331.      * It has been overridden here to unhook event listeners.
  332.      *
  333.      * @see #addNotify
  334.      */
  335.     public synchronized void removeNotify()
  336.     {
  337.         //Unhook listeners
  338.         if (styleVeto != null)
  339.         {
  340.             removeImageStyleListener(styleVeto);
  341.             styleVeto = null;
  342.         }
  343.  
  344.         super.removeNotify();
  345.     }
  346.  
  347.     /**
  348.      * Adds a listener for all event changes.
  349.      * @param listener the listener to add.
  350.      * @see #removePropertyChangeListener
  351.      */
  352.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  353.     {
  354.         super.addPropertyChangeListener(listener);
  355.         changes.addPropertyChangeListener(listener);
  356.     }
  357.  
  358.     /**
  359.      * Removes a listener for all event changes.
  360.      * @param listener the listener to remove.
  361.      * @see #addPropertyChangeListener
  362.      */
  363.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  364.     {
  365.         super.removePropertyChangeListener(listener);
  366.         changes.removePropertyChangeListener(listener);
  367.     }
  368.  
  369.     /**
  370.      * Adds a vetoable listener for all event changes.
  371.      * @param listener the listener to add.
  372.      * @see #removeVetoableChangeListener
  373.      */
  374.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
  375.     {
  376.         super.addVetoableChangeListener(listener);
  377.         vetos.addVetoableChangeListener(listener);
  378.     }
  379.  
  380.     /**
  381.      * Removes a vetoable listener for all event changes.
  382.      * @param listener the listener to remove.
  383.      * @see #addVetoableChangeListener
  384.      */
  385.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
  386.     {
  387.         super.removeVetoableChangeListener(listener);
  388.         vetos.removeVetoableChangeListener(listener);
  389.     }
  390.  
  391.     /**
  392.      * Adds a listener for the ImageStyle property changes.
  393.      * @param listener the listener to add.
  394.      * @see #removeImageStyleListener(java.beans.PropertyChangeListener)
  395.      */
  396.     public synchronized void addImageStyleListener(PropertyChangeListener listener)
  397.     {
  398.         changes.addPropertyChangeListener("ImageStyle", listener);
  399.     }
  400.  
  401.     /**
  402.      * Removes a listener for the ImageStyle property changes.
  403.      * @param listener the listener to remove.
  404.      * @see #addImageStyleListener(java.beans.PropertyChangeListener)
  405.      */
  406.     public synchronized void removeImageStyleListener(PropertyChangeListener listener)
  407.     {
  408.         changes.removePropertyChangeListener("ImageStyle", listener);
  409.     }
  410.  
  411.     /**
  412.      * Adds a vetoable listener for the ImageStyle property changes.
  413.      * @param listener the listener to add.
  414.      * @see #removeImageStyleListener(java.beans.VetoableChangeListener)
  415.      */
  416.     public synchronized void addImageStyleListener(VetoableChangeListener listener)
  417.     {
  418.         vetos.addVetoableChangeListener("ImageStyle", listener);
  419.     }
  420.  
  421.     /**
  422.      * Removes a vetoable listener for the ImageStyle property changes.
  423.      * @param listener the listener to remove.
  424.      * @see #addImageStyleListener(java.beans.VetoableChangeListener)
  425.      */
  426.     public synchronized void removeImageStyleListener(VetoableChangeListener listener)
  427.     {
  428.         vetos.removeVetoableChangeListener("ImageStyle", listener);
  429.     }
  430.  
  431.     /**
  432.      * This is the PropertyChangeEvent handling inner class for the constrained ImageStyle property.
  433.      * Handles vetoing BevelHeights that are not valid.
  434.      */
  435.     class StyleVeto implements java.beans.VetoableChangeListener, java.io.Serializable
  436.     {
  437.         /**
  438.          * This method gets called when an attempt to change the constrained ImageStyle property is made.
  439.          * Ensures the given image style is valid for this button.
  440.          *
  441.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  442.          *             event source and the property that has changed.
  443.          * @exception PropertyVetoException if the recipient wishes the property
  444.          *              change to be rolled back.
  445.          */
  446.         public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
  447.         {
  448.             int i = ((Integer)e.getNewValue()).intValue();
  449.             if (!isValidImageStyle(i))
  450.             {
  451.                 throw new PropertyVetoException(errors.getString("InvalidImageStyle") + i, e);
  452.             }
  453.         }
  454.     }
  455.  
  456.     /**
  457.      * Draws the button in the buttonImage offscreen image.
  458.      * @see symantec.itools.awt.ButtonBase#updateButtonImage
  459.      */
  460.     protected void updateButtonImage()
  461.     {
  462.         super.updateButtonImage();
  463.  
  464.         Image img;
  465.  
  466.         if(pressed)
  467.             img = pressedImage;
  468.         else
  469.             img = isEnabled() ? enabledImage : disabledImage;
  470.  
  471.  
  472.         Dimension s        = size();
  473.         int x            = bevel + 1 + pressedAdjustment;
  474.           int y            = bevel + 1 + pressedAdjustment;
  475.         int w            = s.width    - bevel - bevel - 2;
  476.         int h            = s.height    - bevel - bevel - 2;
  477.  
  478.         if (img == null) {
  479.             buttonImageGraphics.clearRect(x, y, w, h);
  480.             return;
  481.         }
  482.  
  483.         int imageWidth    = img.getWidth(this);
  484.         int imageHeight    = img.getHeight(this);
  485.  
  486.         switch(imageStyle)
  487.         {
  488.             case IMAGE_CENTERED:
  489.             default:
  490.             {
  491.                 buttonImageGraphics.drawImage
  492.                     (img, x + ((w - imageWidth) / 2), y + ((h - imageHeight) / 2), this);
  493.  
  494.                 break;
  495.             }
  496.             case IMAGE_TILED:
  497.             {
  498.                 //Calculate number of images that should be drawn horizontally
  499.                 int numHImages = w / imageWidth;
  500.  
  501.                 //Don't forget remainders
  502.                 if (w % imageWidth != 0)
  503.                     numHImages++;
  504.  
  505.                 //Calculate number of images that should be drawn vertically
  506.                 int numVImages = h / imageHeight;
  507.  
  508.                 //Don't forget remainders
  509.                 if (h % imageHeight != 0)
  510.                     numVImages++;
  511.  
  512.                 int hOff;
  513.                 int vOff = y;
  514.                 for (int vCount = 0; vCount < numVImages; vCount++)
  515.                 {
  516.                     hOff = x;
  517.                     for (int hCount = 0; hCount < numHImages; hCount++)
  518.                     {
  519.                         buttonImageGraphics.drawImage(img, hOff, vOff, imageWidth, imageHeight, this);
  520.  
  521.                         //Increment to next column
  522.                         hOff += imageWidth;
  523.                     }
  524.  
  525.                     //Increment to next row
  526.                     vOff += imageHeight;
  527.                 }
  528.                 break;
  529.             }
  530.             case IMAGE_SCALED_TO_FIT:
  531.             {
  532.                 buttonImageGraphics.drawImage(img, x, y, w, h, this);
  533.                 break;
  534.             }
  535.             case IMAGE_NORMAL:
  536.             {
  537.                 buttonImageGraphics.drawImage(img, x, y, this);
  538.                 break;
  539.             }
  540.         }
  541.     }
  542.  
  543.     private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException
  544.     {
  545.         in.defaultReadObject();
  546.  
  547.         if (imageURL != null) {
  548.             Image image = getToolkit().getImage(imageURL);
  549.             if (image != null)
  550.             {
  551.                 MediaTracker mt = new MediaTracker(this);
  552.                 if (mt != null)
  553.                 {
  554.                     try
  555.                     {
  556.                         mt.addImage(image, 0);
  557.                         mt.waitForAll();
  558.                     }
  559.                     catch (InterruptedException ie)
  560.                     {
  561.                     }
  562.  
  563.                     if (mt.isErrorAny())
  564.                     {
  565.                         Object[] args = { image.toString() };
  566.                         System.err.println(MessageFormat.format(errors.getString("ErrorLoadingImage"), args));
  567.                         return;
  568.                     }
  569.  
  570.                     enabledImage    = image;
  571.                     disabledImage    = createImage(new FilteredImageSource(image.getSource(), new symantec.itools.awt.image.FadeFilter(0.333)));
  572.                     pressedImage    = createImage(new FilteredImageSource(image.getSource(), new symantec.itools.awt.image.DarkenFilter(0.250)));
  573.                 }
  574.             }
  575.         }
  576.  
  577.     }
  578.  
  579.     /**
  580.      * Determines how to draw the image.
  581.      */
  582.     protected int imageStyle;
  583.  
  584.     /**
  585.      * The URL for the button's image
  586.      */
  587.     protected URL imageURL = null;
  588.  
  589.     /**
  590.      * The normally displayed image
  591.      */
  592.     transient protected Image enabledImage = null;
  593.  
  594.     /**
  595.      * The image displayed when the button is disabled
  596.      */
  597.     transient protected Image disabledImage    = null;
  598.  
  599.     /**
  600.      * The image displayed when the button is pressed
  601.      */
  602.     transient protected Image pressedImage = null;
  603.     /**
  604.      * Error strings.
  605.      */
  606.     transient protected ResourceBundle errors;
  607.  
  608.     private StyleVeto styleVeto = null;
  609.     private symantec.itools.beans.VetoableChangeSupport vetos   = new symantec.itools.beans.VetoableChangeSupport(this);
  610.     private symantec.itools.beans.PropertyChangeSupport changes = new symantec.itools.beans.PropertyChangeSupport(this);
  611.  
  612. }
  613.