home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / Java++ / VJ / SAMPLES / JAVANOW / CHAP15 / STOCK3 / STOCK.JAVA < prev    next >
Encoding:
Java Source  |  1996-06-18  |  7.9 KB  |  309 lines

  1. // Stock3 - this version of the Stock applet uses
  2. //          double buffering to avoid the flickers.
  3. //          it is much faster than Stock2 and just
  4. //          as easy to write as Stock1.
  5. import java.applet.*;
  6. import java.awt.*;
  7. import java.util.Random;
  8.  
  9. public class Stock extends Applet implements Runnable
  10. {
  11.     Thread     m_Stock = null;
  12.  
  13.     int m_fps = 10;
  14.  
  15.     final String PARAM_fps = "fps";
  16.  
  17.     // use the random object to create stock movements
  18.     private Random  m_r = new Random();
  19.  
  20.     // m_dValue[] - contains the closing price of the stock
  21.     //              for day that is visible. [0] is today
  22.     //              day, [1] yesterday, etc.
  23.     private double[] m_dValue;
  24.     private int m_nSize;  // length of value array
  25.     private int m_nMax;   // maximum value in value array
  26.  
  27.     // double buffering image
  28.     private Image m_image;// offscreen image
  29.     private Graphics m_g; // associated graphics object
  30.     Dimension m_dimImage; // size of offscreen image
  31.  
  32.     public Stock()
  33.     {
  34.     }
  35.  
  36.     public void finalize()
  37.     {
  38.     }
  39.  
  40.     public String getAppletInfo()
  41.     {
  42.         return "Name: Stock\r\n" +
  43.                "Author: Stephan R. Davis\r\n" +
  44.                "Created for Learn Java Now (c)";
  45.     }
  46.  
  47.     public String[][] getParameterInfo()
  48.     {
  49.         String[][] info =
  50.         {
  51.             { PARAM_fps, "int", "Frame rate" },
  52.         };
  53.         return info;        
  54.     }
  55.  
  56.     public void init()
  57.     {
  58.         String param;
  59.  
  60.         param = getParameter(PARAM_fps);
  61.         if (param != null)
  62.             m_fps = Integer.parseInt(param);
  63.  
  64.         // resize(600, 240);
  65.  
  66.         // initialize the m_dValue array to the current
  67.         // width of the window
  68.         Dimension dim = size();
  69.         int m_nSize = XToIndex(dim.width);
  70.         m_dValue = new double[m_nSize];
  71.         m_nMax = 100;
  72.     }
  73.  
  74.     public void destroy()
  75.     {
  76.     }
  77.  
  78.     public void paint(Graphics g)
  79.     {
  80.         // repaint existing image
  81.         if (m_image != null)
  82.         {
  83.             g.drawImage(m_image, 0, 0, null);
  84.         }
  85.     }
  86.  
  87.     public void update(Graphics g)
  88.     {
  89.         // make sure that the image is the same size as
  90.         // the applet's window
  91.         ResizeImage();
  92.  
  93.         // clear the off-screen image (not the on-screen one)
  94.         Color colFG = getForeground();
  95.         Color colBG = getBackground();
  96.         m_g.setColor(colBG);
  97.         m_g.fillRect(0, 0, m_dimImage.width, m_dimImage.height);
  98.         m_g.setColor(colFG);
  99.  
  100.         // paint the frame
  101.         PaintFrame(m_g);
  102.  
  103.         // then repaint the data
  104.         PaintData(m_g);
  105.  
  106.         // now repaint the image
  107.         paint(g);
  108.     }
  109.  
  110.     private void PaintFrame(Graphics g)
  111.     {
  112.         // get the dimensions of the window
  113.         Dimension d = size();
  114.         int nWidth  = d.width;
  115.         int nHeight = d.height;
  116.  
  117.         // put up axis along the left and bottom
  118.         g.drawString(Integer.toString(m_nMax), 5, 10);
  119.         g.drawString("0", 5, d.height - 10);
  120.         g.drawLine(0, nHeight - 1, nWidth, nHeight - 1);
  121.         g.drawLine(0, nHeight - 1, 0, 0);
  122.         int nMark = 50;
  123.         while (nMark < m_nMax)
  124.         {
  125.             int nL = 3;
  126.             if ((nMark % 100) == 0)
  127.             {
  128.                  nL = 6;
  129.             }
  130.             int nH = ValueToY(nHeight, nMark);
  131.             g.drawLine(0, nH, nL, nH);
  132.             nMark += 50;
  133.         }
  134.     }
  135.  
  136.     synchronized private void PaintData(Graphics g)
  137.     {
  138.         // get the dimensions of the window
  139.         Dimension d = size();
  140.         int nWidth = d.width;
  141.         int nHeight = d.height;
  142.  
  143.         // check to see if the array needs resizing
  144.         ResizeArray(d.width);
  145.  
  146.         // repaint the data
  147.         for (int i = 0; i < m_nSize; i++)
  148.         {
  149.             int x = IndexToX(nWidth, i);
  150.             int y = ValueToY(nHeight, m_dValue[i]);
  151.             g.drawLine(x - 1, y, x + 1, y);
  152.             g.drawLine(x, y - 1, x, y + 1);
  153.         }
  154.     }
  155.  
  156.     public void start()
  157.     {
  158.         if (m_Stock == null)
  159.         { 
  160.             m_Stock = new Thread(this);
  161.             m_Stock.start();
  162.         }
  163.     }
  164.     
  165.     public void stop()
  166.     {
  167.         if (m_Stock != null)
  168.         {
  169.             m_Stock.stop();
  170.             m_Stock = null;
  171.         }
  172.     }
  173.  
  174.     public void run()
  175.     {
  176.         // calculate the proper time to delay
  177.         int nSleepTime = 1000 / m_fps;
  178.  
  179.         // start with the first value stored.
  180.         // if it's zero then this must be
  181.         // the first time into the applet -
  182.         // start with an initial value of 50.
  183.         double dValue = m_dValue[0];
  184.         if (dValue == 0.0)
  185.         {
  186.             dValue = 50.0;
  187.         }
  188.  
  189.         while (true)
  190.         {
  191.             try
  192.             {
  193.                 // create a new stock value
  194.                 // this is the part that's random
  195.                 // (here I assume that movement of plus
  196.                 // or minus two points a day or so is
  197.                 // reasonable - the 0.2 offset gives it
  198.                 // a slight upward drift)
  199.                 dValue += 2 * m_r.nextGaussian() + 0.2;
  200.                 AddValue(dValue);
  201.                 
  202.                 // now repaint the window
  203.                 repaint();
  204.  
  205.                 // repaint at the fps speed
  206.                 Thread.sleep(nSleepTime);
  207.             }
  208.             catch (InterruptedException e)
  209.             {
  210.                 stop();
  211.             }
  212.         }
  213.     }
  214.  
  215.     // ResizeImage - resize the off-screen image (if necessary)
  216.     private void ResizeImage()
  217.     {
  218.         // get the size of the applet's window
  219.         Dimension dim = size();
  220.         int nWidth = dim.width;
  221.         int nHeight= dim.height;
  222.  
  223.         // compare that to the size of our image;
  224.         // if it hasn't changed...
  225.         if (m_dimImage != null &&
  226.             m_dimImage.width == nWidth &&
  227.             m_dimImage.height== nHeight)
  228.         {
  229.             // ...don't do anything
  230.             return;
  231.         }
  232.  
  233.         // create a graphics image to paint to
  234.         m_dimImage = new Dimension(nWidth, nHeight);
  235.         m_image = createImage(nWidth, nHeight);
  236.         m_g = m_image.getGraphics();
  237.     }
  238.  
  239.     // ResizeArray - resize the array of stock prices
  240.     //               (if necessary)
  241.     private void ResizeArray(int nWidth)
  242.     {
  243.         // if the window is the same size...
  244.         int nNumPts = XToIndex(nWidth);
  245.         if (nNumPts == m_nSize)
  246.         {
  247.             // ...then ignore it
  248.             return;
  249.         }
  250.  
  251.         // otherwise, we need to resize the array:
  252.         // allocate room
  253.         double[] dNewArray = new double[nNumPts];
  254.  
  255.         // now copy the points from the old, smaller
  256.         // array to the new, larger array
  257.         int nNumToCopy = Math.min(nNumPts, m_nSize);
  258.         for (int i = 0; i < nNumToCopy; i++)
  259.         {
  260.             dNewArray[i] = m_dValue[i];
  261.         }
  262.  
  263.         // finally, make the new array our own
  264.         m_dValue = dNewArray;
  265.         m_nSize = nNumPts;
  266.     }
  267.  
  268.     // AddValue - add a value to the array
  269.     synchronized private void AddValue(double dValue)
  270.     {
  271.         // move everything over one to make
  272.         // room for the new data item
  273.         for (int i = m_nSize - 1; i > 0; i--)
  274.         {
  275.             m_dValue[i] = m_dValue[i - 1];
  276.         }
  277.  
  278.         // add the new data item as the
  279.         // the first entry
  280.         m_dValue[0] = dValue;
  281.  
  282.         // make sure to keep track of the max
  283.         while (dValue >= m_nMax)
  284.         {
  285.             m_nMax += 50;
  286.         }
  287.     }
  288.  
  289.     // XToIndex - convert the display window dimension
  290.     //            to the corresponding array index
  291.     private static final int m_PIXELS_PER_POINT = 3;
  292.     static private int XToIndex(int nWidth)
  293.     {
  294.         return nWidth / m_PIXELS_PER_POINT;
  295.     }
  296.     // IndexToX - convert the array index to the window
  297.     //            x offset
  298.     static private int IndexToX(int nWidth, int nIndex)
  299.     {
  300.         return (nWidth - 1) - (m_PIXELS_PER_POINT * nIndex);
  301.     }
  302.     // ValueToY - convert the stock value to the y
  303.     //            offset in the window to plot the point
  304.     private int ValueToY(int nHeight, double dValue)
  305.     {
  306.         return nHeight - ((int)dValue * nHeight) / m_nMax;
  307.     }
  308. }
  309.