home *** CD-ROM | disk | FTP | other *** search
/ Symantec Visual Cafe for Java 2.5 / symantec-visual-cafe-2.5-database-dev-edition.iso / VCafe / prosrc.bin / ImageViewer.java < prev    next >
Encoding:
Java Source  |  1998-03-18  |  16.9 KB  |  615 lines

  1. /*
  2.  * @(#ImageViewer.java
  3.  *
  4.  * Copyright (c) 1997 Symantec Corporation. All Rights Reserved.
  5.  *
  6.  */
  7.  
  8.  
  9. package symantec.itools.db.awt;
  10.  
  11. import java.applet.*;
  12. import java.io.*;
  13. import java.net.*;
  14. import java.awt.*;
  15. import java.util.*;
  16. import java.sql.*;
  17. import symantec.itools.net.*;
  18. import symantec.itools.db.pro.*;
  19. import symantec.itools.db.beans.binding.Name;
  20.  
  21. /**
  22.  * A dbAWARE component that displays an image.
  23.  * <p>
  24.  * This component can be "bound" to a projection within a relation view
  25.  * so that it automatically gets the image to display from the database.
  26.  * <p>
  27.  */
  28. public class ImageViewer extends Canvas implements ProjectionBean
  29. {
  30.     Object  m_Value = null;
  31.     boolean m_IsAdded = false;
  32.     Image   m_Image = null;
  33.     int     m_ImageType = StreamImageSource.JPEG;
  34.     byte[]  m_Data = null;
  35.     ByteArrayInputStream    m_InputStream = null;
  36.     ByteArrayOutputStream   m_OutputStream = null;
  37.  
  38.     private boolean     m_displayWhileLoading = false;
  39.     private boolean     m_IsLoaded = false;
  40.  
  41.     private ProjectionBeanHelper m_Helper;
  42.  
  43.     /**
  44.     * The exception message when the data stored in the data base can't be converted
  45.     * into a image file
  46.     */
  47.     private final String INVALID_IMAGE_DATA= "There is not a valid image data";
  48.  
  49.     /**
  50.      * Constructs a default ImageViewer.
  51.      * By default this viewer will not display images while they are loading.
  52.      */
  53.     public ImageViewer() {
  54.         setIsAdded(false);
  55.         m_Helper = new ProjectionBeanHelper(this);
  56.     }
  57.  
  58.     /**
  59.      * Constructs an ImageViewer and specifies the default URL that security
  60.      * checks are performed against.
  61.      * By default this viewer will not display images while they are loading.
  62.      *
  63.      * @param base the default URL that security checks are performed against
  64.      *
  65.      * @see symantec.itools.db.awt.StreamImageSource
  66.      */
  67.     public ImageViewer (URL base) {
  68.         this();
  69.         setBaseUrl(base);
  70.     }
  71.  
  72.  
  73.     /**
  74.      * Sets the default URL that security checks are performed against.
  75.      * @param base the default URL that security checks are performed against
  76.      *
  77.      * @see symantec.itools.db.awt.StreamImageSource
  78.      */
  79.     public static void setBaseUrl(URL base)
  80.     {
  81.         StreamImageSource.setBaseUrl(base);
  82.     }
  83.  
  84.     /**
  85.      * Tells this component that it has been added to a container.
  86.      * <p>
  87.      * This is a standard Java AWT method which gets called by the AWT when
  88.      * this component is added to a container. Typically, it is used to
  89.      * create this component's peer.
  90.      * <p>
  91.      * It is overridden here to set the StreamImage base URL if within an applet.
  92.      *
  93.      * @see java.awt.Component#removeNotify
  94.      */
  95.     public void addNotify() {
  96.         super.addNotify();
  97.         Component parent = null;
  98.         Applet app = null;
  99.  
  100.         parent = this.getParent();
  101.  
  102.         while (parent != null && parent.getParent() != null) {
  103.             if (parent instanceof Applet) {
  104.                 break;
  105.             }
  106.  
  107.             parent = parent.getParent();
  108.         }
  109.  
  110.         if (parent instanceof Applet) {
  111.             app = (Applet) parent;
  112.             StreamImageSource.setBaseUrl(app.getCodeBase());
  113.         }
  114.         setIsAdded(true);
  115.         if (m_Value != null) {
  116.             setData(m_Value);
  117.         }
  118.     }
  119.  
  120.     /**
  121.      * Gets this component's <code>Image</code>.
  122.      * @return the image
  123.      * @see #setImage
  124.      */
  125.     protected Image getImage()
  126.     {
  127.         return m_Image;
  128.     }
  129.  
  130.     /**
  131.      * Sets this component's <code>Image</code>.
  132.      * @param image the new image
  133.      * @see #getImage
  134.      */
  135.     protected void setImage(Image image)
  136.     {
  137.         m_Image = image;
  138.     }
  139.  
  140.     /**
  141.      * Gets the type of image loaded.
  142.      * Currently only GIF and JPEG are supported.
  143.      *
  144.      * @return one of StreamImageSource.JPEG, or StreamImageSource.GIF
  145.      *
  146.      * @see #setImageType
  147.      * @see symantec.itools.db.awt.StreamImageSource#JPEG
  148.      * @see symantec.itools.db.awt.StreamImageSource#GIF
  149.      */
  150.      public int getImageType()
  151.      {
  152.         return m_ImageType;
  153.      }
  154.  
  155.     /**
  156.      * Sets the type of image loaded.
  157.      * Currently only GIF and JPEG are supported.
  158.      *
  159.      * @param type one of StreamImageSource.JPEG, or StreamImageSource.GIF
  160.      *
  161.      * @see #setImageType(byte[])
  162.      * @see #getImageType
  163.      * @see symantec.itools.db.awt.StreamImageSource#JPEG
  164.      * @see symantec.itools.db.awt.StreamImageSource#GIF
  165.      */
  166.     public void setImageType(int type)
  167.     {
  168.         m_ImageType = type;
  169.     }
  170.  
  171.     /**
  172.      * Sets the type of image loaded.
  173.      * Currently only GIF and JPEG are supported.
  174.      *
  175.      * @param data one of "JPG" or "GIF"
  176.      *
  177.      * @see #setImageType(int)
  178.      * @see #getImageType
  179.      */
  180.     protected void setImageType(byte[] data)
  181.     {
  182.         byte buf[] = new byte[3];
  183.         System.arraycopy(data, 0, buf, 0, 3);
  184.         String typeName = new String(buf, 0);
  185.         int type = StreamImageSource.JPEG;
  186.         if (typeName.equals("GIF")) {
  187.             type = StreamImageSource.GIF;
  188.         }
  189.         setImageType(type);
  190.     }
  191.  
  192.     /**
  193.      * Determines whether the image is completely loaded or not.
  194.      * @return true if the image is completely loaded
  195.      */
  196.      public boolean isLoaded()
  197.      {
  198.         return m_IsLoaded;
  199.      }
  200.  
  201.      /**
  202.       * Sets the "is loaded" flag.
  203.       * @param isLoaded the new flag value
  204.       * @see #isLoaded
  205.       */
  206.      protected void setIsLoaded(boolean isLoaded)
  207.      {
  208.         m_IsLoaded = isLoaded;
  209.      }
  210.  
  211.     /**
  212.      * Loads and builds the image at the specified URL then returns an
  213.      * input stream of its image data.
  214.      *
  215.      * @param s the URL string
  216.      * @return the image data stream
  217.      * @exception MalformedURLException
  218.      * if the URL string is invalid
  219.      */
  220.     public ByteArrayInputStream fetchImage(String s)
  221.         throws MalformedURLException
  222.     {
  223.         URL url = new URL(s);
  224.         return fetchImage(url);
  225.     }
  226.  
  227.     /**
  228.      * Helper function for fetchImage() which retrieves the data for an image
  229.      * whose URL is in http format.
  230.      * @param url the URL
  231.      * @return the loaded image data
  232.      * @exception MalformedURLException
  233.      * if the URL is invalid
  234.      * @see #fetchImage
  235.      */
  236.     public ByteArrayInputStream fetchHTTP(URL url)
  237.         throws MalformedURLException
  238.     {
  239.          try {
  240.              InputStream is = url.openStream();
  241.              buildImage(is);
  242.          } catch(Exception ex) {
  243.             ex.printStackTrace();
  244.             throw new MalformedURLException(ex.getMessage());
  245.          }
  246.  
  247.         enable(false);
  248.         m_Helper.notifyInputChanged(m_Data);
  249.         enable(true);
  250.         return getInputStream();
  251.     }
  252.  
  253.     /**
  254.      * Loads and builds the image at the specified URL then returns an
  255.      * input stream of its image data.
  256.      * Double checks to see if it
  257.      * begins with ftp:// even though Java doesn't support that
  258.      * right now.
  259.      *
  260.      * @param s the URL
  261.      * @return the image data stream
  262.      * @exception MalformedURLException
  263.      * if the URL is invalid
  264.      */
  265.     public ByteArrayInputStream fetchImage(URL url)
  266.         throws MalformedURLException
  267.     {
  268.         url.toExternalForm();
  269.         return fetchHTTP(url);
  270.     }
  271.  
  272.     /**
  273.      * Sets whether the image will be displayed while it is loading.
  274.      * Otherwise the image will not be displayed until it finishes loading.
  275.      */
  276.     public void setDisplayOption(boolean dOption)
  277.     {
  278.         if (dOption)
  279.         {
  280.             m_displayWhileLoading = true;
  281.         }
  282.         else
  283.         {
  284.             m_displayWhileLoading = false;
  285.         }
  286.     }
  287.  
  288.     /**
  289.      * Gets the image input stream.
  290.      * @return the input stream
  291.      * @see #setInputStream
  292.      */
  293.     protected ByteArrayInputStream getInputStream()
  294.     {
  295.         return m_InputStream;
  296.     }
  297.  
  298.     /**
  299.      * Sets the image input stream.
  300.      * @param stream the new input stream
  301.      * @see #getInputStream
  302.      */
  303.     protected void setInputStream(ByteArrayInputStream stream)
  304.     {
  305.         m_InputStream = stream;
  306.     }
  307.  
  308.     /**
  309.      * Gets the image output stream.
  310.      * @return the output stream
  311.      */
  312.     protected ByteArrayOutputStream getOutputStream()
  313.     {
  314.         return m_OutputStream;
  315.     }
  316.  
  317.     /**
  318.      * Converts the given input stream to an output stream.
  319.      * @param input the input stream
  320.      * @return the input stream converted to an output sream
  321.      * @exception MalformedURLException if an exception occurs while converting
  322.      */
  323.     protected ByteArrayOutputStream convertInputStreamToOutputStream(InputStream input) throws MalformedURLException
  324.     {
  325.         BufferedInputStream bis = new BufferedInputStream(input);
  326.         ByteArrayOutputStream bos = new ByteArrayOutputStream();
  327.         int b;
  328.         try {
  329.             while((b = bis.read()) != -1) {
  330.                 bos.write(b);
  331.             }
  332.         }
  333.         catch (Exception ex) {
  334.             throw new MalformedURLException(ex.getMessage());
  335.         }
  336.         return bos;
  337.     }
  338.  
  339.     /**
  340.      * Eliminates any current image.
  341.      */
  342.     public void clearImage()
  343.     {
  344.         setIsLoaded(false);
  345.         setImage(null);
  346.         repaint();
  347.         m_Helper.notifyInputChanged(m_Data);
  348.     }
  349.  
  350.     private void buildImage(InputStream img) throws MalformedURLException
  351.     {
  352.         setIsLoaded(false);
  353.         setImage(null);
  354.  
  355.         try {
  356.             if (img != null) {
  357.                 ByteArrayOutputStream stream = convertInputStreamToOutputStream(img);
  358.                 byte[] data = stream.toByteArray();
  359.                 if (data.length > 0) {
  360.                     m_OutputStream = stream;
  361.                     m_Data = data;
  362.                     setInputStream(new ByteArrayInputStream(m_Data));
  363.                     setImageType(m_Data);
  364.  
  365.                     InputStream imgCopy = new ByteArrayInputStream(m_Data);
  366.                     Toolkit tk = getToolkit();
  367.                     StreamImageSource sis = new StreamImageSource(imgCopy, getImageType());
  368.                     setImage(tk.createImage(data));//sis));
  369.                     if (!m_displayWhileLoading) {
  370.                         loadImage(getImage());
  371.                     }
  372.                     setIsLoaded(true);
  373.                 }
  374.  
  375.             }
  376.         }
  377.         catch (Exception e) {
  378.             e.printStackTrace();
  379.             throw new MalformedURLException(e.getMessage());
  380.         }
  381.         finally {
  382.             repaint();
  383.         }
  384.     }
  385.  
  386.     private void loadImage(Image image)
  387.     {
  388.         if (image != null)
  389.         {
  390.             MediaTracker mtracker;
  391.  
  392.             try
  393.             {
  394.                 mtracker = new MediaTracker(this);
  395.                 mtracker.addImage(image, 0);
  396.                 mtracker.waitForID(0);
  397.             }
  398.             catch(InterruptedException e)
  399.             {
  400.             }
  401.         }
  402.     }
  403.  
  404.     /**
  405.      * Paints this component using the given graphics context.
  406.      * <p>
  407.      * This is a standard Java AWT method which typically gets called
  408.      * by the AWT to handle painting this component. It paints this component
  409.      * using the given graphics context. The graphics context clipping region
  410.      * is set to the bounding rectangle of this component and its [0,0]
  411.      * coordinate is this component's top-left corner.
  412.      *
  413.      * @param g the graphics context used for painting
  414.      * @see java.awt.Component#repaint
  415.      * @see java.awt.Component#update
  416.      */
  417.     public void paint(Graphics g) {
  418.         try {
  419.             if (getImage() != null) {
  420.                 g.drawImage(getImage(), 0, 0, this);
  421.             }
  422.             else
  423.             {
  424.                 g.clearRect(0,0,size().width,size().height);
  425.             }
  426.         } catch (Exception e) {
  427.             e.printStackTrace();
  428.             return;
  429.         }
  430.     }
  431.  
  432.     /**
  433.      * Binds this component to a given projection within the specified
  434.      * relation view.
  435.      *
  436.      * @param relView the relation view to bind with
  437.      * @param projection the projection in relView to bind with
  438.      */
  439.     public void setBinding(RelationView relView, String projection)
  440.     {
  441.         m_Helper.setBinding(relView, projection);
  442.     }
  443.  
  444.     /**
  445.      * Returns the projection in the RelationView that this component is bound with.
  446.      * @see #setBinding
  447.      * @see #setProjection
  448.      */
  449.     public String getProjection() {
  450.         return m_Helper.getProjection();
  451.     }
  452.  
  453.     /**
  454.      * Binds this component to the given projection within the RelationView
  455.      * the component is currently bound with.
  456.      * @see #setBinding
  457.      * @see #getProjection
  458.      * @see #getRelationView
  459.      */
  460.     public void setProjection(String projection) {
  461.         m_Helper.setProjection(projection);
  462.     }
  463.  
  464.     /**
  465.      * Gets the RelationView that this component is bound with.
  466.      * @return the RelationView currently bound with
  467.      * @see #setRelationView
  468.      * @see #setBinding
  469.      * @see #getProjection
  470.      */
  471.     public RelationView getRelationView() {
  472.         return m_Helper.getRelationView();
  473.     }
  474.  
  475.     /**
  476.      * Sets the RelationView that this component is bound with.
  477.      * @param value the RelationView to bind with
  478.      * @see #getRelationView
  479.      * @see #setBinding
  480.      * @see #setProjection
  481.      */
  482.     public void setRelationView(RelationView value) {
  483.         m_Helper.setRelationView(value);
  484.     }
  485.  
  486.     /**
  487.      * Specifies how an empty string will be set when updating data on
  488.      * the dbANYWHERE server.
  489.      *
  490.      * @param blank one of "DEFAULT", "NULL", or "BLANK"
  491.      *
  492.      * @see symantec.itools.db.pro.ProjBinder#setValueFromString(java.lang.String, int, int)
  493.      */
  494.     public void setTreatBlankAs(String value) {
  495.         m_Helper.setTreatBlankAsString(value);
  496.     }
  497.  
  498.     /**
  499.      * Indicates when the component commits its changes.
  500.      * @see #setDynamicUpdate
  501.      */
  502.     public boolean getDynamicUpdate() {
  503.         return m_Helper.getDynamicUpdate();
  504.     }
  505.  
  506.     /**
  507.      * Sets when the component commits its changes.
  508.      * @param value the new dynamic update mode value
  509.      * @see #getDynamicUpdate
  510.      */
  511.     public void setDynamicUpdate(boolean value) {
  512.         m_Helper.setDynamicUpdate(value);
  513.     }
  514.  
  515.     /**
  516.      * Sets whether the data value of this component may be modified.
  517.      * @param value <code>true</code> if the value may not be modified,
  518.      * <code>false</code>if the value may be modified
  519.      */
  520.     public void setReadOnly(boolean value) {
  521.     }
  522.  
  523.     /**
  524.      * Gets the value of this component.
  525.      * @return the current component value
  526.      * @see #setData
  527.      */
  528.     public Object getData() {
  529.         return m_OutputStream;
  530.     }
  531.  
  532.     /**
  533.      * Loads the image data from the database this component has been bound to.
  534.      * It then builds and displays the image.
  535.      */
  536.  
  537.     /**
  538.      * Sets the value of this component to the given value.
  539.      * @param value the new component value
  540.      * @see #getData
  541.      */
  542.     public void setData(Object value)
  543.     {
  544.         if (!isAdded()) {
  545.             m_Value = value;
  546.             return;
  547.         }
  548.  
  549.         if (isEnabled()) {
  550.             InputStream input = null;
  551.             if (value != null && value instanceof InputStream) {
  552.                 input = (InputStream)value;
  553.             }
  554.             try {
  555.                 buildImage(input);
  556.             }
  557.             catch(Exception e){}
  558.         }
  559.     }
  560.  
  561.     /**
  562.      * Gets whether this component saves its value as a text String.
  563.      * @return <code>true</code> if the value is saved as text,
  564.      * <code>false</code> otherwise
  565.      */
  566.     public boolean isTextBased() {
  567.         return false;
  568.     }
  569.  
  570.     /**
  571.      * Gets the number of digits to the right of the decimal point for
  572.      * this component's value.
  573.      * @return the number of digits to the right of the decimal point
  574.      */
  575.     public int getScale() {
  576.         return ProjBinder.DEFAULTSCALE;
  577.     }
  578.  
  579.     /**
  580.      * Registers the standard event listener(s) for this component.
  581.      */
  582.     public void registerListeners() {
  583.     }
  584.  
  585.     /**
  586.      * Sets the name of the data item to bind this component to.
  587.      * @param name the data item name, like "MyTable@MyColumn"
  588.      * @see #getDataBinding
  589.      */
  590.     public void setDataBinding(String name)
  591.     {
  592.         m_Helper.setDataBinding(new Name(name));
  593.     }
  594.  
  595.     /**
  596.      * Gets the name of the data item this component is bound to.
  597.      * @returns the data item name, like "MyTable@MyColumn"
  598.      * @see #setDataBinding
  599.      */
  600.     public String getDataBinding()
  601.     {
  602.         return  m_Helper.getDataBinding().getFullName();
  603.     }
  604.  
  605.     private synchronized boolean isAdded()
  606.     {
  607.         return m_IsAdded;
  608.     }
  609.  
  610.     private synchronized void setIsAdded(boolean isAdded)
  611.     {
  612.         m_IsAdded = isAdded;
  613.     }
  614. }
  615.