home *** CD-ROM | disk | FTP | other *** search
/ Symantec Visual Cafe for Java 2.5 / symantec-visual-cafe-2.5-database-dev-edition.iso / VCafe / Source.bin / ImageButton.java < prev    next >
Encoding:
Java Source  |  1998-09-14  |  17.9 KB  |  617 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.         
  316.         try
  317.         {
  318.             errors = ResourceBundle.getBundle("symantec.itools.resources.ErrorsBundle");
  319.         }
  320.         catch(Throwable ex)
  321.         {
  322.             errors = new symantec.itools.resources.ErrorsBundle();
  323.         }
  324.  
  325.         //Hook up listeners
  326.         if (styleVeto == null)
  327.         {
  328.             styleVeto = new StyleVeto();
  329.             addImageStyleListener(styleVeto);
  330.         }
  331.     }
  332.  
  333.     /**
  334.      * Tells this component that it is being removed from a container.
  335.      * This is a standard Java AWT method which gets called by the AWT when
  336.      * this component is removed from a container. Typically, it is used to
  337.      * destroy the peers of this component and all its subcomponents.
  338.      *
  339.      * It has been overridden here to unhook event listeners.
  340.      *
  341.      * @see #addNotify
  342.      */
  343.     public synchronized void removeNotify()
  344.     {
  345.         //Unhook listeners
  346.         if (styleVeto != null)
  347.         {
  348.             removeImageStyleListener(styleVeto);
  349.             styleVeto = null;
  350.         }
  351.  
  352.         super.removeNotify();
  353.     }
  354.  
  355.     /**
  356.      * Adds a listener for all event changes.
  357.      * @param listener the listener to add.
  358.      * @see #removePropertyChangeListener
  359.      */
  360.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  361.     {
  362.         super.addPropertyChangeListener(listener);
  363.         changes.addPropertyChangeListener(listener);
  364.     }
  365.  
  366.     /**
  367.      * Removes a listener for all event changes.
  368.      * @param listener the listener to remove.
  369.      * @see #addPropertyChangeListener
  370.      */
  371.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  372.     {
  373.         super.removePropertyChangeListener(listener);
  374.         changes.removePropertyChangeListener(listener);
  375.     }
  376.  
  377.     /**
  378.      * Adds a vetoable listener for all event changes.
  379.      * @param listener the listener to add.
  380.      * @see #removeVetoableChangeListener
  381.      */
  382.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
  383.     {
  384.         super.addVetoableChangeListener(listener);
  385.         vetos.addVetoableChangeListener(listener);
  386.     }
  387.  
  388.     /**
  389.      * Removes a vetoable listener for all event changes.
  390.      * @param listener the listener to remove.
  391.      * @see #addVetoableChangeListener
  392.      */
  393.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
  394.     {
  395.         super.removeVetoableChangeListener(listener);
  396.         vetos.removeVetoableChangeListener(listener);
  397.     }
  398.  
  399.     /**
  400.      * Adds a listener for the ImageStyle property changes.
  401.      * @param listener the listener to add.
  402.      * @see #removeImageStyleListener(java.beans.PropertyChangeListener)
  403.      */
  404.     public synchronized void addImageStyleListener(PropertyChangeListener listener)
  405.     {
  406.         changes.addPropertyChangeListener("ImageStyle", listener);
  407.     }
  408.  
  409.     /**
  410.      * Removes a listener for the ImageStyle property changes.
  411.      * @param listener the listener to remove.
  412.      * @see #addImageStyleListener(java.beans.PropertyChangeListener)
  413.      */
  414.     public synchronized void removeImageStyleListener(PropertyChangeListener listener)
  415.     {
  416.         changes.removePropertyChangeListener("ImageStyle", listener);
  417.     }
  418.  
  419.     /**
  420.      * Adds a vetoable listener for the ImageStyle property changes.
  421.      * @param listener the listener to add.
  422.      * @see #removeImageStyleListener(java.beans.VetoableChangeListener)
  423.      */
  424.     public synchronized void addImageStyleListener(VetoableChangeListener listener)
  425.     {
  426.         vetos.addVetoableChangeListener("ImageStyle", listener);
  427.     }
  428.  
  429.     /**
  430.      * Removes a vetoable listener for the ImageStyle property changes.
  431.      * @param listener the listener to remove.
  432.      * @see #addImageStyleListener(java.beans.VetoableChangeListener)
  433.      */
  434.     public synchronized void removeImageStyleListener(VetoableChangeListener listener)
  435.     {
  436.         vetos.removeVetoableChangeListener("ImageStyle", listener);
  437.     }
  438.  
  439.     /**
  440.      * This is the PropertyChangeEvent handling inner class for the constrained ImageStyle property.
  441.      * Handles vetoing BevelHeights that are not valid.
  442.      */
  443.     class StyleVeto implements java.beans.VetoableChangeListener, java.io.Serializable
  444.     {
  445.         /**
  446.          * This method gets called when an attempt to change the constrained ImageStyle property is made.
  447.          * Ensures the given image style is valid for this button.
  448.          *
  449.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  450.          *             event source and the property that has changed.
  451.          * @exception PropertyVetoException if the recipient wishes the property
  452.          *              change to be rolled back.
  453.          */
  454.         public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
  455.         {
  456.             int i = ((Integer)e.getNewValue()).intValue();
  457.             if (!isValidImageStyle(i))
  458.             {
  459.                 throw new PropertyVetoException(errors.getString("InvalidImageStyle") + i, e);
  460.             }
  461.         }
  462.     }
  463.  
  464.     /**
  465.      * Draws the button in the buttonImage offscreen image.
  466.      * @see symantec.itools.awt.ButtonBase#updateButtonImage
  467.      */
  468.     protected void updateButtonImage()
  469.     {
  470.         super.updateButtonImage();
  471.  
  472.         Image img;
  473.  
  474.         if(pressed)
  475.             img = pressedImage;
  476.         else
  477.             img = isEnabled() ? enabledImage : disabledImage;
  478.  
  479.  
  480.         Dimension s        = size();
  481.         int x            = bevel + 1 + pressedAdjustment;
  482.           int y            = bevel + 1 + pressedAdjustment;
  483.         int w            = s.width    - bevel - bevel - 2;
  484.         int h            = s.height    - bevel - bevel - 2;
  485.  
  486.         if (img == null) {
  487.             buttonImageGraphics.clearRect(x, y, w, h);
  488.             return;
  489.         }
  490.  
  491.         int imageWidth    = img.getWidth(this);
  492.         int imageHeight    = img.getHeight(this);
  493.  
  494.         switch(imageStyle)
  495.         {
  496.             case IMAGE_CENTERED:
  497.             default:
  498.             {
  499.                 buttonImageGraphics.drawImage
  500.                     (img, x + ((w - imageWidth) / 2), y + ((h - imageHeight) / 2), this);
  501.  
  502.                 break;
  503.             }
  504.             case IMAGE_TILED:
  505.             {
  506.                 //Calculate number of images that should be drawn horizontally
  507.                 int numHImages = w / imageWidth;
  508.  
  509.                 //Don't forget remainders
  510.                 if (w % imageWidth != 0)
  511.                     numHImages++;
  512.  
  513.                 //Calculate number of images that should be drawn vertically
  514.                 int numVImages = h / imageHeight;
  515.  
  516.                 //Don't forget remainders
  517.                 if (h % imageHeight != 0)
  518.                     numVImages++;
  519.  
  520.                 int hOff;
  521.                 int vOff = y;
  522.                 for (int vCount = 0; vCount < numVImages; vCount++)
  523.                 {
  524.                     hOff = x;
  525.                     for (int hCount = 0; hCount < numHImages; hCount++)
  526.                     {
  527.                         buttonImageGraphics.drawImage(img, hOff, vOff, imageWidth, imageHeight, this);
  528.  
  529.                         //Increment to next column
  530.                         hOff += imageWidth;
  531.                     }
  532.  
  533.                     //Increment to next row
  534.                     vOff += imageHeight;
  535.                 }
  536.                 break;
  537.             }
  538.             case IMAGE_SCALED_TO_FIT:
  539.             {
  540.                 buttonImageGraphics.drawImage(img, x, y, w, h, this);
  541.                 break;
  542.             }
  543.             case IMAGE_NORMAL:
  544.             {
  545.                 buttonImageGraphics.drawImage(img, x, y, this);
  546.                 break;
  547.             }
  548.         }
  549.     }
  550.  
  551.     private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException
  552.     {
  553.         in.defaultReadObject();
  554.  
  555.         if (imageURL != null) {
  556.             Image image = getToolkit().getImage(imageURL);
  557.             if (image != null)
  558.             {
  559.                 MediaTracker mt = new MediaTracker(this);
  560.                 if (mt != null)
  561.                 {
  562.                     try
  563.                     {
  564.                         mt.addImage(image, 0);
  565.                         mt.waitForAll();
  566.                     }
  567.                     catch (InterruptedException ie)
  568.                     {
  569.                     }
  570.  
  571.                     if (mt.isErrorAny())
  572.                     {
  573.                         Object[] args = { image.toString() };
  574.                         System.err.println(MessageFormat.format(errors.getString("ErrorLoadingImage"), args));
  575.                         return;
  576.                     }
  577.  
  578.                     enabledImage    = image;
  579.                     disabledImage    = createImage(new FilteredImageSource(image.getSource(), new symantec.itools.awt.image.FadeFilter(0.333)));
  580.                     pressedImage    = createImage(new FilteredImageSource(image.getSource(), new symantec.itools.awt.image.DarkenFilter(0.250)));
  581.                 }
  582.             }
  583.         }
  584.  
  585.     }
  586.  
  587.     /**
  588.      * Determines how to draw the image.
  589.      */
  590.     protected int imageStyle;
  591.  
  592.     /**
  593.      * The URL for the button's image
  594.      */
  595.     protected URL imageURL = null;
  596.  
  597.     /**
  598.      * The normally displayed image
  599.      */
  600.     transient protected Image enabledImage = null;
  601.  
  602.     /**
  603.      * The image displayed when the button is disabled
  604.      */
  605.     transient protected Image disabledImage    = null;
  606.  
  607.     /**
  608.      * The image displayed when the button is pressed
  609.      */
  610.     transient protected Image pressedImage = null;
  611.     transient protected ResourceBundle errors;
  612.  
  613.     private StyleVeto styleVeto = null;
  614.     private symantec.itools.beans.VetoableChangeSupport vetos   = new symantec.itools.beans.VetoableChangeSupport(this);
  615.     private symantec.itools.beans.PropertyChangeSupport changes = new symantec.itools.beans.PropertyChangeSupport(this);
  616.  
  617. }