001//******************************************************************************
002// BinaryClockApp.java:    Applet
003//
004//******************************************************************************
005package ca.bc.webarts.tools;
006
007import java.applet.*;
008import java.awt.*;
009import java.util.Calendar;
010//import BinaryClockAppFrame;
011
012//==============================================================================
013// Main Class for applet BinaryClockApp
014//
015//==============================================================================
016/**
017 *  Description of the Class
018 *
019 * @author    TGutwin
020 */
021public class BinaryClockApp extends Applet implements Runnable
022{
023  /**  Description of the Field */
024  public boolean showText = false;
025  /**  Description of the Field */
026  private boolean leftToRight = false;
027  /**  The colour of an on bit. */
028  private Color onColour = Color.BLUE.darker();
029  /**  The colour of an on bit. */
030  private Color offColour = Color.cyan;//Color.BLUE.darker();
031  /**  Description of the Field */
032  int x;
033  /**  Description of the Field */
034  int y;
035  /**  Description of the Field */
036  private Calendar now, newnow;
037  /**  Description of the Field */
038  private Image backBuffer;
039  /**  Description of the Field */
040  private Graphics bg;
041  /**  Description of the Field */
042  private Font font;
043  /**  Description of the Field */
044  private String decimalTime;
045
046  // THREAD SUPPORT:
047  // m_BinclockApp        is the Thread object for the applet
048  //--------------------------------------------------------------------------
049  /**  Description of the Field */
050  private Thread clockThread = null;
051
052  // STANDALONE APPLICATION SUPPORT:
053  // m_fStandAlone will be set to true if applet is run standalone
054  //--------------------------------------------------------------------------
055  /**  Description of the Field */
056  private boolean m_fStandAlone = false;
057
058  // BinclockApp Class Constructor
059  //--------------------------------------------------------------------------
060  /**  Constructor for the BinaryClockApp object */
061  public BinaryClockApp() { }
062
063  // STANDALONE APPLICATION SUPPORT
064  // The main() method acts as the applet's entry point when it is run
065  // as a standalone application. It is ignored if the applet is run from
066  // within an HTML page.
067  //--------------------------------------------------------------------------
068
069  /**
070   *  STANDALONE APPLICATION SUPPORT
071   * The main() meth;
072    int height= 10od acts as the applet's entry point when it is run
073   * as a standalone application. It is ignored if the applet is run from
074   * within an HTML page.
075   *
076   * @param  args  Description of the Parameter
077   */
078  public static void main(String args[])
079  {
080    // Create Toplevel Window to contain applet BinclockApp
081    //----------------------------------------------------------------------
082    BinaryClockAppFrame frame = new BinaryClockAppFrame("Binary Clock");
083
084    // The following code starts the applet running within the frame window.
085    // It also calls GetParameters() to retrieve parameter values from the
086    // command line, and sets m_fStandAlone to true to prevent init() from
087    // trying to get them from the HTML page.
088    //----------------------------------------------------------------------
089    BinaryClockApp applet_BinclockApp = new BinaryClockApp();
090
091    if (applet_BinclockApp.showText)
092    {
093      frame.setBounds(100, 100, 260, 180);
094    }
095    else
096    {
097      frame.setBounds(100, 100, 134, 90);
098    }
099
100    // Must show Frame before we size it so getInset() will return valid values
101    //----------------------------------------------------------------------
102    frame.show();
103
104    frame.add("Center", applet_BinclockApp);
105    applet_BinclockApp.m_fStandAlone = true;
106
107    applet_BinclockApp.init();
108    applet_BinclockApp.start();
109    frame.show();
110  }
111
112  // APPLET INFO SUPPORT:
113  // The getAppletInfo() method returns a string describing the applet's
114  // author, copyright date, or miscellaneous information.
115  //--------------------------------------------------------------------------
116  /**
117   *  Gets the appletInfo attribute of the BinaryClockApp object
118   *
119   * @return    The appletInfo value
120   */
121  public String getAppletInfo()
122  {
123    return "Name: BinaryClock\r\n" +
124        "Author: David Binard (mailto:binard@california.com)\n" +
125        "Date: 08/20/98\n" +
126        "Description: Binary Clock Animation\n";
127  }
128
129
130  // The init() method is called by the AWT when an applet is first loaded or
131  // reloaded.  Override this method to perform whatever initialization your
132  // applet needs, such as initializing data structures, loading images or
133  // fonts, creating frame windows, setting the layout manager, or adding UI
134  // components.
135  //--------------------------------------------------------------------------
136  /**  Description of the Method */
137  public void init()
138  {
139    // If you use a ResourceWizard-generated "control creator" class to
140    // arrange controls in your applet, you may want to call its
141    // CreateControls() method from within this method. Remove the following
142    // call to setSize() before adding the call to CreateControls();
143    // CreateControls() does its own resizing.
144    //----------------------------------------------------------------------
145    setSize(getSize().width, getSize().height);
146    font = new Font("Helvetica", Font.PLAIN, 11);
147    try
148    {
149      backBuffer = createImage(getSize().width, getSize().height);
150      bg = backBuffer.getGraphics();
151    }
152    catch (Exception e)
153    {
154      bg = null;
155    }
156    ;
157
158    // TODO: Place additional initialization code here
159  }
160
161  // Place additional applet clean up code here.  destroy() is called when
162  // when you applet is terminating and being unloaded.
163  //-------------------------------------------------------------------------
164  /**  Description of the Method */
165  public void destroy()
166  {
167    // TODO: Place applet cleanup code here
168  }
169
170
171  // The start() method is called when the page containing the applet
172  // first appears on the screen. The AppletWizard's initial implementation
173  // of this method starts execution of the applet's thread.
174  //--------------------------------------------------------------------------
175  /**  Description of the Method */
176  public void start()
177  {
178    now = Calendar.getInstance();
179    newnow = Calendar.getInstance();
180    if (clockThread == null)
181    {
182      clockThread = new Thread(this, "Binclock");
183      clockThread.start();
184    }
185    // TODO: Place additional applet start code here
186  }
187
188  // The stop() method is called when the page containing the applet is
189  // no longer on the screen. The AppletWizard's initial implementation of
190  // this method stops execution of the applet's thread.
191  //--------------------------------------------------------------------------
192  /**  Description of the Method */
193  public void stop()
194  {
195    if (clockThread != null)
196    {
197      clockThread.stop();
198      clockThread = null;
199    }
200
201    // TODO: Place additional applet stop code here
202  }
203
204  // THREAD SUPPORT
205  // The run() method is called when the applet's thread is started. If
206  // your applet performs any ongoing activities without waiting for user
207  // input, the code for implementing that behavior typically goes here. For
208  // example, for an applet that performs animation, the run() method controls
209  // the display of images.
210  //--------------------------------------------------------------------------
211  /**  Main processing method for the BinaryClockApp object */
212  public void run()
213  {
214    // loop terminates when clockThread is set to null in stop()
215    while (Thread.currentThread() == clockThread)
216    {
217      repaint();
218      // loop until the time changes by one second
219      // the sleeps are here to reduce CPU usage
220      while (now.get(Calendar.SECOND) == newnow.get(Calendar.SECOND))
221      {
222        try
223        {
224          clockThread.sleep(200);
225        }
226        catch (Exception e)
227        {
228        }
229        ;
230        newnow = Calendar.getInstance();
231      }
232    }
233  }
234
235
236  /**
237   *  Description of the Method
238   *
239   * @param  g  Description of the Parameter
240   */
241  public void update(Graphics g)
242  {
243    if (bg == null)
244    {// no backgound buffer
245      repaintClock(g);
246    }
247    else
248    {
249      repaintClock(bg);
250      g.drawImage(backBuffer, 0, 0, this);
251      showStatus("Decimal time: " + decimalTime);
252    }
253  }
254
255
256  /**
257   *  Description of the Method
258   *
259   * @param  value  Description of the Parameter
260   * @return        Description of the Return Value
261   */
262  public String calc_bits(int value)
263  {
264    int bit;
265    int filter = 32;
266    StringBuffer bitString = new StringBuffer("00");
267    for (bit = 3; bit <= 8; bit++)
268    {
269      if (value >= filter)
270      {
271        bitString.append('1');
272        value -= filter;
273      }
274      else
275      {
276        bitString.append('0');
277      }
278      filter = filter - (filter / 2);
279    }
280    return bitString.toString();
281  }
282
283
284  /**
285   *  Description of the Method
286   *
287   * @param  value  Description of the Parameter
288   * @return        Description of the Return Value
289   */
290  public String lpad(int value)
291  {
292    String mystring = "00";
293    if (value <= 9)
294    {
295      mystring = "0" + Integer.toString(value);
296    }
297    else
298    {
299      mystring = Integer.toString(value);
300    }
301    return mystring;
302  }
303
304
305  /**
306   *  Description of the Method
307   *
308   * @param  value  Description of the Parameter
309   * @return        Description of the Return Value
310   */
311  public String to_octal(int value)
312  {
313    String octal = (value / 8) + "" + (value % 8);
314    return octal;
315  }
316
317
318  /**
319   *  Description of the Method
320   *
321   * @param  value  Description of the Parameter
322   * @return        Description of the Return Value
323   */
324  public String to_alpha_hex(int value)
325  {
326    if (value < 10)
327    {
328      return Integer.toString(value);
329    }
330    else if (value == 10)
331    {
332      return "A";
333    }
334    else if (value == 11)
335    {
336      return "B";
337    }
338    else if (value == 12)
339    {
340      return "C";
341    }
342    else if (value == 13)
343    {
344      return "D";
345    }
346    else if (value == 14)
347    {
348      return "E";
349    }
350    else if (value == 15)
351    {
352      return "F";
353    }
354    else
355    {
356      return "0";
357    }
358  }
359
360
361  /**
362   *  Description of the Method
363   *
364   * @param  value  Description of the Parameter
365   * @return        Description of the Return Value
366   */
367  public String to_hex(int value)
368  {
369    String hex = to_alpha_hex(value / 16) + "" + to_alpha_hex(value % 16);
370    return hex;
371  }
372
373  // TODO: Place additional applet code here
374
375  /**
376   *  Description of the Method
377   *
378   * @param  g  Description of the Parameter
379   */
380  private void repaintClock(Graphics g)
381  {
382    now = Calendar.getInstance();
383    int hours = now.get(Calendar.HOUR_OF_DAY);
384    int mins = now.get(Calendar.MINUTE);
385    int secs = now.get(Calendar.SECOND);
386    decimalTime = lpad(hours) + ":" + lpad(mins) + ":" + lpad(secs);
387    String hourBits = calc_bits(hours);
388    String minBits = calc_bits(mins);
389    String secBits = calc_bits(secs);
390    // Clear Background
391    g.setColor(Color.LIGHT_GRAY);
392    g.fillRect(0, 0, getSize().width, getSize().height);
393
394    if (showText)
395    {
396      // Draw text Clock
397      g.setFont(font);
398      g.setColor(Color.black);
399      x = 0;
400      y = 80;
401      g.drawString("Hours", x + 80, y);
402      g.drawString("Minutes", x + 135, y);
403      g.drawString("Seconds", x + 192, y);
404      y += 15;
405      g.drawString("Decimal time", x, y);
406      y += 15;
407      g.drawString("Octal time", x, y);
408      y += 15;
409      g.drawString("Hex time", x, y);
410      y += 15;
411      g.drawString("Binary time", x, y);
412      g.setColor(Color.blue);
413      y -= 45;
414      g.drawString(lpad(hours), x + 88, y);
415      g.drawString(lpad(mins), x + 148, y);
416      g.drawString(lpad(secs), x + 208, y);
417      y += 15;
418      g.drawString(to_octal(hours), x + 88, y);
419      g.drawString(to_octal(mins), x + 148, y);
420      g.drawString(to_octal(secs), x + 208, y);
421      y += 15;
422      g.drawString(to_hex(hours), x + 88, y);
423      g.drawString(to_hex(mins), x + 148, y);
424      g.drawString(to_hex(secs), x + 208, y);
425      y += 15;
426      g.drawString(hourBits, x + 70, y);
427      g.drawString(minBits, x + 130, y);
428      g.drawString(secBits, x + 190, y);
429    }
430
431    int spacing = 5;
432    int width= 10;
433    int height= 15;
434    if (leftToRight)
435    {
436      x = spacing;
437      y = spacing;
438      drawBits(hourBits, g, x, y);
439      y += height + spacing;
440      drawBits(minBits, g, x, y);
441      y += height + spacing;
442      drawBits(secBits, g, x, y);
443      //y += 20;
444    }
445    else
446    {
447      x = spacing;
448      y = spacing;
449      drawBits(hourBits, g, x, y, 10, 15, spacing, true );
450      x += width + spacing;
451      drawBits(minBits, g, x, y, 10, 15, spacing, true);
452      x += width + spacing;
453      drawBits(secBits, g, x, y, 10, 15, spacing, true);
454    }
455  }
456
457
458  /**
459   *  Draws rectangles 10 wide and 15 high representing the bit pattern passed in
460   *
461   * @param  bits  the bit pattern to draw
462   * @param  g     Description of the Parameter
463   * @param  x     the start x position
464   * @param  y     the start y position
465   */
466  private void drawBits(String bits, Graphics g, int x, int y)
467  {
468    drawBits(bits, g, x, y, 10, 15, 5, false);
469  }
470
471
472  /**
473   *  Draws rectangles representing the bit pattern passed in
474   *
475   * @param  bits  the bit pattern to draw
476   * @param  g     Description of the Parameter
477   * @param  x     the start x position
478   * @param  y     the start y position
479   * @param  dx    delta x
480   * @param  dy    delta y
481   * @param  spacing    the distance between the blocks
482   */
483  private void drawBits(String bits, Graphics g, int x, int y, int dx, int dy, int spacing, boolean vertical)
484  {
485    for (int i = 0; i < 8; i++)
486    {
487      if (bits.charAt(i) == '0')
488      {
489        g.setColor(offColour);
490      }
491      else
492      {
493        g.setColor(onColour);
494      }
495      g.fillRect(x, y, dx, dy);
496      if (vertical)
497        y += dy + spacing;
498      else
499        x += dx + spacing;
500    }
501  }
502}
503