//HAHAHA.java  -- Graphics Hanoi, by tsaiwn@cs.nctu.edu.tw
//javac HAHAHA.java
//java HAHAHA
//HTML: <applet code="HAHAHA.class" width=508 height=500>
import java.io.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.*;

public class HAHAHA extends Applet {
   static Frame f = null;
   static boolean isApplet = true;
   gHanoiOK ghok = null;
   ControlPanel cp = null;

   public static void main(String xxx[ ]) {
      isApplet = false;  // from Java application
      f = new Frame("Tower of Hanoi");
      HAHAHA hhh = new HAHAHA( );
      f.add("Center", hhh); 
      f.setSize(gHanoiOK.X_SIZE+10, gHanoiOK.Y_SIZE+50);  //510,550
      f.setVisible(true); f.addWindowListener(new WCC( ));
      //Then, Simulate the Applet behavior
      hhh.init( );
      hhh.start( );
   }//main

   public void init( ) {
      ghok = new gHanoiOK(f);
      cp = new ControlPanel(ghok);
      setLayout(new BorderLayout( ) );
      add("Center", ghok);
      add("South", cp);   // the Control Panel
      if(f!=null) { f.validate( ); f.setVisible(true); }
      ghok.init( );
      ghok.start( );
   }//init(
   public void start( ) {
      if(!isApplet) ghok.main( );  // is application
      else  ghok.winHanoi(5);   // isApplet
   }//start(

   public HAHAHA( ) {
   }// HAHAHA constructor
}//class HAHAHA

class gHanoiOK extends Panel implements MouseListener {
  //some constants for later use
  public static final int X_SIZE=500, Y_SIZE=500;
  public static final int Y_TOP = 28;
  public static final Color bgColor = Color.white;
  public static final int DELAY_TIME = 50; // 50/1000 second
  public static final int MOVE_STEP = 58; // 58 points
  public static final int MIN_STEP = 6; // 6 points
  public static final int MAX_STEP = 158; // 88 points
  public static final int MAX_DELAY = 88; // 88 milli sec
  public static final int MIN_DELAY = 1; 

  public static Color haColor = Color.red;   // variable
  public static boolean speedUp = false;  // speed up?
  public static int delayTime = DELAY_TIME; 
  public static int step = MOVE_STEP;
  int kkk=0;  // used in paint(
  boolean  alreadyDone = false;  // used in Applet mode
  boolean  isRunning = false; // doing Hanoi ?

  ///
  int nDisks = 0;  // number of Disks
  int nPeg[ ] = new int[3];    // height of the 3 piles
  int xPosition[ ] = new int[3];  // central position of 3 pegs
  int aX=38, aY= (Y_SIZE - 50);
  int bX=(aX+(X_SIZE-50)/3), bY=aY;
  int cX=(bX+(X_SIZE-50)/3), cY=aY;

  int thick=22; // for disk thick
  int width=33; // for disk width
  int wUnit=2;  // 128/nDisks == 2

  Graphics bufferGraphics=null;  // 用來畫在記憶體的圖  
  Image img=null;  // The image that will contain everything that ..
              /// .. has been drawn on bufferGraphics.
              /// .. will be used in paint( ) 
  Dimension dim=null;  // To get the width and height of the applet. 

  PrintStream cout=null;      // 使其類似 C++ 的 <iostream>
  BufferedReader cin = null;

   public void init( ) {
      addMouseListener(this); // handle MouseEvent
      if(f==null) cout = System.out;   // from Applet
   }//init(

   public void start( ) {
       prepareIO( );
       prepareImagePaper( );
   }//start

   Frame f=null;
  //Panel myPanel;

   public static void main(String xxx[ ]) {
      Frame f = new Frame("Tower of Hanoi");
      gHanoiOK gok = new gHanoiOK(f);
      f.add("Center", gok); 
      f.setSize(X_SIZE, Y_SIZE);  //500,500
      f.setVisible(true); 
      gok.init( );  // simulate Applet
      gok.start( );
      gok.repaint( ); // force to initilize img
      gok.prepareIO( );
      gok.main( );
   }//main

  // constructors, one for from main(
 public gHanoiOK( Frame f ) {
    this.f = f;
    addMouseListener(this); // handle MouseEvent
    if(f==null) cout = System.out;   // from Applet
 }// gHanoiOK

 public gHanoiOK( ) {   // for Applet to call this
     addMouseListener(this); // handle MouseEvent
 }

 void prepareIO( ){
    try{
       cout = System.out;
       if(f==null) return;  // is Applet
       cin = new BufferedReader(
               new InputStreamReader(System.in) );
    }catch(Exception e) { System.exit(38); }
 }//prepareIO(



  void prepareImagePaper( ) {
      // Create an offscreen image to draw on , same size
      setVisible(true);
      dim = getSize( );  // obtain the width and height
      if(dim.width == 0) return;  // not ready, maybe later
      img = createImage(dim.width, dim.height); 
      bufferGraphics = img.getGraphics( );  
      // use Graphics methods to draw, this is double buffer
      return;
  }// prepareImagePaper

// hanoi.c  -- Hanoi tower, @CopyLeft by tsaiwn@csie.nctu.edu.tw
//Hanoi Tower(河內之塔) -- 神奇的 Recursive -- 自己叫自己 !
//關於 Hanoi Tower, 請用 http://gogle.com 打入 "hanoi tower"  查詢
//注意用雙引號夾住如 "hanoi tower" 查到的才是你要的 :-)
//或是直接看這  http://en.wikipedia.org/wiki/Tower_of_Hanoi
/// C/C++ requires declaraction before use the function
//void moveOne(int px, int py, int ); //3rd parameter is the disk#
void hanoi(int n, int pa, int pc, int pb) {
    if(n==0) return;    // there is no disk
    if(shouldDie) return;  // my Master want me to die :-(
    hanoi(n-1, pa, pb, pc);  // 先幫我把上面 n-1 disks 搬走
    moveOne(pa, pc, n);   /// move the n-th disk from pa to pc
    hanoi(n-1, pb, pc, pa); // move n-1 disks from pb to pc
} // hanoi
void moveOne(int px, int py, int n ) {  // the n-th disk
   moveG(px, py, n);  // Graphics version
   String p123[ ] = {"th", "st", "nd", "rd"}; // -th, Fir-st, 
                               // .. Seco-nd, 3-rd
   int k = n%10;
   if(k!=1  && k!=2 && k!=3) k = 0;  // -th
   cout.printf("Move %d-%s disk from %c  to  %c \n", 
                               n,  p123[k],   px, py);
}//moveOne(

int getInt( ) {   // static char buf[99];
   String buf = null;
   int ans=0;
   // fgets(buf, sizeof(buf), stdin); ans=atoi(buf);
   try {
      buf = cin.readLine( );
      ans = Integer.parseInt(buf);
   }catch(Exception e) { ans = 3; }
    // 如果把 ans = 3; 改為 ans = 64; 你認為會做多久? ? ?
   return ans;  // 若一秒只能搬一個動作, 
                //  ..則需約 600 billion(六千億) (580+) years
}// getInt(

void haInit(int n) {
    nDisks = n; if(n==0) n=2;
    nPeg[0] = n; // initially all Disks on Peg-0
    nPeg[1] = nPeg[2] = 0;   // no Disks on Peg-1 and Peg-2
    thick = (Y_SIZE -50)/n;   // thick of each Disk
    if(thick > 20) thick = 20; // disk thick limit
    wUnit = 128/n;      // Disk width = wUnit * Disk#number
    if(wUnit < 2) wUnit=2;   // minimum 2 points
    xPosition[0] = aX + 64;   // central position aX + 128/2
    xPosition[1] = bX + 64;
    xPosition[2] = cX + 64;
    //
    clearTower( );
    if(f != null) { f.validate( ); f.setVisible(true); }
    initDisks( );  // draw the initial Disks
    if(f != null)  f.setVisible(true);  // f.show( );
}// haInit(



void doHanoi(int n) {
    if(dim == null  || img==null || bufferGraphics == null) {
         prepareImagePaper( );  //  create img paper
         if( bufferGraphics == null) return;  // give up
         System.out.println("doHanoi..");
    }
    if(n >= 65) return;
    shouldDie = false; isRunning = true; pause=false;
    haInit(n); 
    hanoi(n, 'A', 'C', 'B'); // move n disks on peg 'A' to peg 'C'
    isRunning = false;
}// doHanoi(


int main( ) {  // original main program in C Language
    int n;  int firstRun = 1;
    while(true) {
       if(firstRun != 0) {
            firstRun = 0;
            f.setVisible(false);  // hide the window
       }//if
       cout.print(" n=? ");
       n = getInt( );  // read an int into n
       if(n<0) break;
       f.setVisible(true);  //f.requestFocus(true);
       doHanoi(n);
        try{Thread.sleep(58);}catch(Exception e) {  }
       //f.toBack( ); //f.setVisible(false);  // hide the window
    }//while
    f.dispose( ); cout.println("Bye bye...");
    System.exit(0); return 0;
}// int main( )
//////////////////////////

  void winHanoi(int n) {   // do hanoi from Applet/Window
      if(alreadyDone) return;  // run only once
      alreadyDone = true; pause=false; shouldDie=false;
      System.out.println("applet paint...");
      //doHanoi(n);  // 不要這樣做, 會陷入很久的 ...
      //啟動另一個 thread Sister 去做才不會被卡住
      new Sister(this, n).start( );
           // this 就是目前這 class 的物件 ( gHanoiOK )
  }// winHanoi(

  void clearTower( ){  //initial status
     if(dim == null  || img==null || bufferGraphics == null) {
         repaint( ); // force to prepare img/bufgraphics
         if(dim==null) repaint( );  // try to prepare img again
         if(img==null) repaint( );
         if(img==null) return;  // still not READY yet
     }
     setBackground(Color.white);
     bufferGraphics.clearRect(0,0,dim.width,dim.width);
     bufferGraphics.setColor(Color.pink); 
     bufferGraphics.fillRect(aX-3, aY, 128+6, 18); 
     bufferGraphics.fillRect(bX-3, bY, 128+6, 18);
     bufferGraphics.fillRect(cX-3, cY, 128+6, 18);
     bufferGraphics.setColor(new Color(99, 58, 233));
     bufferGraphics.setFont(new Font("Courier", Font.BOLD, 18) );
     bufferGraphics.drawString(
        "Tower of Hanoi, by tsaiwn@csie.nctu.edu.tw",20,20);
     repaint( );  // have paint( ) to draw the image to screen
     try{ Thread.sleep(delayTime); }catch(Exception e){ }
  }//clearTower




  // rewrite update( ) : 
  //    Always required for good double-buffering.
  // This will cause the Applet not to first wipe off previous 
  // ..drawings but to immediately repaint. 
  // The wiping off  may also causes flickering. 
  // Update is called automatically when repaint( ) is called. 

  // comment out the update( ) function then try to run again
  public void update(Graphics g) { paint(g); }  // 直接叫 paint( )

  public void paint(Graphics g) {
     if(dim == null  || img==null || bufferGraphics == null) {
        // This is the first call to here.
        //System.out.println("paint...img null...");
        prepareImagePaper( );
        return;
     }//if
     g.drawImage(img, 0, 0, this);   // 此時才畫到螢幕
     //System.out.println(" paint "+ ++kkk); //for debug
  }//paint(

  void initDisks( ) {   // draw the original Disks
    if( img==null || bufferGraphics == null) return;
    int x, y;
    for(int n= nDisks; n>=1; --n) {
        bufferGraphics.setColor(haColor); 
        x = xPosition[0] - wUnit*n/2;
        y = aY - (nDisks -n+1)*thick;
        bufferGraphics.fillRect(x, y, wUnit*n, thick);
    }//for
    repaint( );
    try{Thread.sleep(delayTime);}catch(Exception e){ }
   }

  void moveG(int px, int py, int n ) {  // the n-th disk
     if(shouldDie) return;
     //if(img==null) return;  // not ready yet
     if(dim == null  || img==null || bufferGraphics == null){
         repaint( );
         if(dim == null  || img==null ) repaint( );
         if(bufferGraphics == null) repaint( );
         if(bufferGraphics == null) return;  // give up :-)
     }
     int from = px - 'A';
     int to = py - 'A';
     width = wUnit * n;   // width of n-th disk
     if(width > 128) width = 128;  // limit the width
     moveYUp(from, to, n);   // 編號 n 的 Disk
     moveX(from, to, n);
     moveYDown(from, to, n);
     --nPeg[from];  // from == 0? 1? 2?
     ++nPeg[to];
     //System.out.print("moveG--- ");
  }//moveG(

  void moveThere(int xs, int ys, int xt, int yt, 
             int width, int thick) {
     if(shouldDie && dieIM) return;  // my Master want me to die :-(
     checkPause( );
     bufferGraphics.setColor(Color.white);    // 擦掉 
     bufferGraphics.fillRect(xs, ys, width, thick); 
     bufferGraphics.setColor(haColor);    // 然後畫新的 
     bufferGraphics.fillRect(xt, yt, width, thick); 
     repaint( );  // 顯示到螢幕 
     try{Thread.sleep(delayTime);}catch(Exception e){ }
  }//moveThere


  void moveYUp(int fm, int to, int n ) {  // the n-th disk
     // fm, to : 0, 1, 2
     int x,y, y1, y2;
     x = xPosition[fm] - width/2;
     y2 = Y_TOP;
     y1 = aY - nPeg[fm]*thick;  // y-position of n-th disk
     // move y from y1 to y2
     y = y1;
     while(y > y2+step) { 
        int y0 = y;
        y -= step;
        moveThere(x, y0, x, y, width, thick);
     }//while(
     moveThere(x, y, x, y2, width, thick);   //提起到正上方 
  }//moveYUp

  void moveX(int fm, int to, int n ) {  // the n-th disk
     int x,y, x1, x2;
     y = Y_TOP;
     x1 = xPosition[fm]  - width/2;  
     x2 = xPosition[to]  - width/2;;
     //boolean toRight = true;   // move from Left to Right
     int rightLeft = 1;  // 往右 ; fm ==> to
     if(x2 < x1)  rightLeft = -1;   // 往左  to <== fm
     x = x1;  // move x from x1 to x2
     while( 38==38 ) {  //  BUG fixed
        int xtemp = x + step * rightLeft;  // 向右走向左走?
        if(rightLeft == 1) {     // fm ====>  to
           if(xtemp > x2) break;
        }else{    // to <====== fm
           if(xtemp < x2) break;
        } 
        int x0 = x;
        x = xtemp;   // 注意我們用臨時的 xtemp
        moveThere(x0, y, x, y, width, thick);
     }//while(
     moveThere(x, y, x2, y, width, thick);  // 到目的堆正上方 
  }//moveX

  void moveYDown(int fm, int to, int n ) {  // the n-th disk
     int x,y, y1, y2;
     x = xPosition[to]  - width/2;;
     y1 = Y_TOP;
     y2 = aY - (nPeg[to]+1)*thick;    // destination
     y = y1;   // move y from y1 to y2
     while(y < y2-step) {
        int y0 = y;
        y += step;
        moveThere(x, y0, x, y, width, thick);
     }//while(
     moveThere(x, y, x, y2, width, thick);  // 到定位
  }// moveYDown


  void checkPause( ) { 
      while(true) {    // Loop untill "Continue"
          if( !pause ) break;
          try{ Thread.sleep(18); }catch(Exception e){ }
      }//while
  }//checkPause(

 //////////////////////////////////////////////////////////
/// handling MouseEvent
  public void mousePressed(MouseEvent e) { }

  public void mouseReleased(MouseEvent e) { }


  public void mouseEntered(MouseEvent e) {
     step = MAX_STEP + 25;
     delayTime = MIN_DELAY;
  }

  public void mouseExited(MouseEvent e) { 
     step = MIN_STEP;
     delayTime = DELAY_TIME;   // in milli seconds
  }

  public void mouseClicked(MouseEvent e) { 
     if(e.getButton( ) == MouseEvent.BUTTON3) { // Right Button
         step = 1+(step/3); delayTime = delayTime*2;
         speedUp = !speedUp;  // toggle
     }//if
     if(speedUp){
          faster( );
     }else{
          slower( );
     }//if(
  }//mouseClicked

  public void faster( ) {   // moving faster
      ++step; if(step > MAX_STEP) step = MAX_STEP;
      --delayTime; if(delayTime < MIN_DELAY)  delayTime = MIN_DELAY;
      if(delayTime == MIN_DELAY && step==MAX_STEP) speedUp = false;
  }//faster

  public void slower( ) {   // moving slower
      --step; if(step < MIN_STEP) step = MIN_STEP;
      ++delayTime; if(delayTime > MAX_DELAY) delayTime = MAX_DELAY;
      if(delayTime == MAX_DELAY && step==MIN_STEP) speedUp = true;
  }//slower
  boolean pause = false;      // "Pause/Continue" ?
  boolean shouldDie = false;     // "Stop" pressed
  boolean dieIM = false;     // "StopIM" pressed
} // class gHanoiOK
////////////////////////////////////////////////////////////


class ControlPanel extends Panel 
                 implements ItemListener, ActionListener {
    gHanoiOK  target;
    int nDisks = 2;

    public ControlPanel(gHanoiOK target) {
        this.target = target;
        target.setBackground(Color.white);
        target.setForeground(Color.red);
        //
        setLayout(new FlowLayout());
        setBackground(Color.yellow);
        MyTimeBTN tm; add(tm=new MyTimeBTN( ));  // for showing time
        new Thread(tm).start( ); // start my Timer
        addColorSelector( );
        addStartButton( );
        addChoices( );
        addMoreButtons( );
    }// ControlPanel(

    void addStartButton( ) {
        Button b = new Button("Start");
        b.setBackground(Color.pink);
        b.setForeground(Color.black);
        add(b);
        b.addActionListener(this);  // "Start" Button
    }// addStartButton( 



    void addChoices( ) {
        Choice shapes = new Choice();  // choice List
        shapes.addItemListener(this);
        shapes.addItem("1"); shapes.addItem("2");
        shapes.addItem("3"); shapes.addItem("5");
        shapes.addItem("8"); shapes.addItem("16");
        shapes.addItem("24"); shapes.addItem("32");
        shapes.addItem("50"); shapes.addItem("64");
        shapes.setBackground(Color.lightGray);
        shapes.select("5"); nDisks = 5;
        add(shapes);
    }//

    static Button bFast=null, bSlower=null;
    void addMoreButtons( ) {
        Button bq = new Button("Quit");
        bq.setForeground(Color.red);
        add(bq);
        bq.addActionListener(this);
        Panel p = new Panel( );
         p.add(bFast = new Button("+"));  //  Faster
         bFast.addActionListener(this);
         p.add(bSlower = new Button("-"));  //  Slower
         bSlower.addActionListener(this);
        add(p); p.setBackground(new Color(238,168,158));
         //p.setBackground(bFast.getBackground( ));
        Button bStop = new Button("Stop");
        bStop.setForeground(Color.red);
        bStop.addActionListener(this);
        add(bStop);
        bStop = new Button(STOP_IM);
        bStop.setFont(new Font("Courier", Font.BOLD, 12) );
        bStop.setForeground(Color.blue);
        bStop.addActionListener(this);
        add(bStop);
        bStop = new Button(PAUSE_M);
        bStop.setFont(new Font("Courier", Font.BOLD, 10) );
        bStop.setForeground(Color.red);
        bStop.addActionListener(this);
        add(bStop);
    }//  addMoreButtons( 

    void addColorSelector( ) {
        Panel p = null;
        CheckboxGroup group = new CheckboxGroup();
        Checkbox b;
        p = new Panel( );
          p.add(b = new Checkbox(null, group, true));
          b.addItemListener(this);
          b.setForeground(Color.red);
          add(p); p.setBackground(Color.red);
        p = new Panel( );
          p.add(b = new Checkbox(null, group, false));
          b.addItemListener(this);
          b.setForeground(Color.green);
          add(p); p.setBackground(Color.green);
        p = new Panel( );
          p.add(b = new Checkbox(null, group, false));
          b.addItemListener(this);
          b.setForeground(Color.blue);
          add(p); p.setBackground(Color.blue);
        ///
        target.haColor = Color.red;   // initial color
    }// addColorSelector( 


    public void paint(Graphics g) {
        Rectangle r = getBounds();
        g.setColor(Color.lightGray);
        g.draw3DRect(0, 0, r.width, r.height, true);
        int n = getComponentCount( );
        for(int i=0; i<n; i++) {
            Component comp = getComponent(i);
            if (comp instanceof Checkbox) {
                Point loc = comp.getLocation();
                Dimension d = comp.getSize();
                g.setColor(comp.getForeground());
                g.drawRect(loc.x-1, loc.y-1, d.width+1, d.height+1);
            }//if
        }//for
    }//paint(

  public void itemStateChanged(ItemEvent e) {
    if (e.getSource() instanceof Checkbox) {
       Color ccc = ((Component)e.getSource()).getForeground( );
       if(ccc == Color.green) ccc = new Color(33, 168, 33);
       target.haColor = ccc;  // user wants this color :-)
       new Sister(target, nDisks, true).start( ); // initDisks
    } else if (e.getSource() instanceof Choice) {
       String choice = (String) e.getItem();
       try{  nDisks = Integer.parseInt(choice);
       }catch(Exception e22) { nDisks = 3; }
    }//else if :: Choice
  }// itemStateChanged

  public void actionPerformed(ActionEvent e) {
      if (e.getSource() == bFast) target.faster( );
      if (e.getSource() == bSlower) target.slower( );
      if(nDisks >= 65 ) nDisks = 8;
      String acCommand = e.getActionCommand( );
      if(acCommand.equals("Quit") ) System.exit(0);
      else if(acCommand.equals("Start") ) pbStart( );
      else if(acCommand.equals("Stop") ) pbStop( );
      else if(acCommand.equals(STOP_IM) ) pbStopIM( );
      else if(acCommand.equals(PAUSE_M) ) pbPause(e);
      else if(acCommand.equals(CONTINUE_M) ) pbContinue(e);
  }//actionPerformed

  private void pbStart( ) { 
      //target.doHanoi(nDisks);  // not work to triger event
      Sister hanoi = new Sister(target, nDisks);
      hanoi.start( ); // 啟動另一個 Thread 去做 hanoi(nDisks)
      // event handler 結束後其他 event 才有用
  } // pbStart( 

  private void pbStop( ) { 
      target.pause = false;
      target.shouldDie = true; target.dieIM = false;
  }// pbStop( 

  private void pbStopIM( ) { 
      target.pause = false;
      target.shouldDie = target.dieIM = true;
      //try{Thread.sleep(8);}catch(Exception ee) { }
  }// pbStopIM( 

  private void pbPause(ActionEvent e) { 
      if( !target.isRunning ) return;  // 沒在 Run
      target.shouldDie  =  target.dieIM = false;
      target.pause = true;
      ((Button)e.getSource()).setLabel(CONTINUE_M);
  }// pbStopIM( 


  private void pbContinue(ActionEvent e) { 
      //if( !target.isRunning ) return;  // 沒在 Run
      target.shouldDie =  target.dieIM = false;
      if(target.speedUp) target.faster( ); else target.slower( );
      //try{Thread.sleep(8);}catch(Exception ee) { }
      target.pause = false;
      ((Button)e.getSource()).setLabel(PAUSE_M);
  }// pbStopIM( 

  public final String STOP_IM = "立即停";  // "StopIM"
  public final String PAUSE_M = "Pause";  // "暫停"
  public final String CONTINUE_M = "Continue";  // "繼續"
}//class ControlPanel

  // 這個 Thread 用來執行 gHanoiOK 的 doHanoi(nDisks);
class Sister extends Thread {
     gHanoiOK  target;
     int nDisks = 3;
     boolean putOnly = false;
     static Sister him=null;   // static variable is shared

   Sister( gHanoiOK  target, int nDisks){
      this.target = target;
      this.nDisks = nDisks;
   }//Sister
   // 注意 Thread 的啟動點是 run( ), 要用 .start( ) 啟動!
   public void run( ) {
      int cnt = activeCount( );
      //if(him!=null && him.isAlive()) return;  //do nothing
      // 只允許一個 Thread 做 hanoi, 不然會亂七八糟糕 
      if( target.isRunning ) return; // ignore it when moving
      if(him == null) {   // 若 user 一直按 Start ?
         him = this;
         target.delayTime = 3;  target.step = 2;
         target.isRunning = true; target.pause = false; 
         target.shouldDie = target.dieIM = false;
         if(putOnly) target.haInit(nDisks); // doNot move
         else target.doHanoi(nDisks);
         target.isRunning = false;
         him = null;  // 讓下次又可做 doHanoi( )
      }// if
   }//run(
   Sister( gHanoiOK  target, int nDisks, boolean putOnly){
      // new this constructor will initialize Disks ONLY
      this.target = target; this.nDisks = nDisks; this.putOnly = true;
   }//Sister
}//class Sister

class WCC extends WindowAdapter{   // 用來關閉窗 Only
   public void windowClosing(WindowEvent e){System.exit(0);}
}

class MyTimeBTN extends Canvas implements Runnable {
    MyTimeBTN( ) { setSize(50,15); setVisible(true);  }
    public void paint(Graphics g) {
       String t = "" + new Date( );
       g.drawString(t.substring(10,19), 0, 12);
    }
    public void run( ) {
        while (true) {
            try { Thread.sleep(58); } catch (Exception e) { }
            repaint();
        }
    }//run(
}//MyTimeBTN
