//===================================================================
// Grid.java -- demo Grid Layout with ImageButton -- by tsaiwn@csie.nctu
// This Java program can be run both as Applet and as Application.
// Required the file MyApplet.java
/// This program, Grid.java, and MyApplet.java, as long as all 
//  necessary image files and audio files can be found here:
///
//    http://www.csie.nctu.edu.tw/~tsaiwn/course/java/examples/grid/
/// 
// To run as an Application: java Grid
//////////
/*****  When used as an Applet, embed it in an HTML file as following:
<HTML>
<BODY> Test Grid.class  GridLayout, GridBagLayout
 <br>
 <applet code="Grid.class" WIDTH=588 HEIGHT=368>
 </applet>
 <! Note that More Files needed to be put in the same directory:
     images/...  (put them in the subdirectory image/ ):w
   ---------------------------------------------------------->
 </body>
 </html>
********************************************************************/

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.text.*;
//import javax.swing.ImageIcon;       // for ImageButton
//import javax.swing.JButton;
//import javax.swing.JLabel;
import javax.swing.*;

public class Grid extends MyApplet implements ActionListener, SwingConstants
{
      static final protected int DISPLAY_LENGTH = 38;  // display initial len
      static final private int WIDTH=558, HEIGHT=368;
      static final Font DISPLAY_FONT =
                new Font("Ludica Console", Font.BOLD, 24);
      static final Color DISPLAY_BG_COLOR = new Color(198,188,188) ;
      static final Color DISPLAY_FG_COLOR = new Color(255,58,88) ;
      static final String CAPTION_LAB_MYPIC = "親一下吧";  // for Label
      static final Color COLOR_LAB_MYPIC = Color.red;
      static final String CAPTION_B_MYPIC = "This is a Button";
   ///
      static final String LAUGH_NAME = "images/laugh.au";
      static final Font myFont16 = new Font("標楷體", Font.BOLD, 16);
      static final Font myFont18 = new Font("標楷體", Font.BOLD, 18);
      static final Font myFont24 = new Font("標楷體", Font.BOLD, 24);
      Toolkit toolkit;

      Image imageDigits[ ] = new Image[10];
      ImageIcon iconDigits[ ] = new ImageIcon[10];

      Image imageFun[ ] = new Image[10];
      ImageIcon iconFun[ ] = new ImageIcon[10];

      JButton bDigits[ ] = new JButton[12];
      Button  bABC[ ] = new Button[8];   // ABCDEF+-
      JButton [ ]bFun = new JButton[6];

      static String btnCMD1[ ] = new String[12];  // 0..9, "+/-", .
      final static String btnCMD2[ ] =
                   { "21 A", "22 B", "23 C", "24 D", "25 E", "26 F",
                       "27 +", "28 -"};
      final static String btnCMDFun[ ] =
                   { "31 open",  "32 nextp",  "33 relative",
                               "35 Mouth", "36 vote", "38 MC"};
      final static String funFilename[ ] =
                   { "open.gif",  "nextpage.gif", "relative.gif",
                       "mouth.jpg", "vote_a.gif", ":MC"};  // : means not file

      static {   // do this when the class loaded
         for(int i=0; i<=9; ++i) {
            btnCMD1[i] = "" + i;     //  "0", "1", .. , "9"
         }
         btnCMD1[10] = "11 toggle";  // +/-
         btnCMD1[11] = "12 dot";    // "12" for convinent to process
      }

      Frame f;    // used in Application: a Window to host the Applet
      Applet ap = null;
      JButton bMyPic = null;
      JButton bTaskMgr = null;
      JTextField display = null;
      JButton bWhoAmI = null;
      CommandPad pLog = null; // to show the command
   public Grid( ) {  // Constructor, remember Grid extends Applet
      if(ap==null) ap = this;   // Let ap points to myself first
   }

      static private boolean isApplication = false;  // Application or Applet

   public static void main( String s[ ]) {   // for Application only
      isApplication = true;   // to indicate that this is an Application
                            // an Applet will NOT run this main( ) function
      Frame f = new Frame("Super Calculator 2008");
      Grid a = new Grid( );    // new the Applet (simulate Browser)
      f.add(a, BorderLayout.CENTER);  // put the Applet in the Frame f
      a.ap = a;   // a.ap points to the Applet it self
      a.f = f;  // a.f points to the Frame f created in Application main()

      a.init( );   // simulate Applet behavior
      a.start( );  // simulate Applet behavior
     /// resizing the window for fun
      int szW[ ] = {  988,  58,  88, 888, 98, 108, 128, 149, 58, 28 };
      int szH[ ] = {   58, 888, 666, 888, 18, 28,  38,   58, 16, 38 };
      f.pack( );
      f.setVisible(true);   // necessary to show up
      for(int i=0; i< szW.length; ++i) {  // resize the window for fun
         try {
            try { Thread.sleep(368); } catch (InterruptedException e) {;}
            f.setSize(WIDTH+ szW[i], HEIGHT+ szH[i]);
            f.validate( );
            printFrameSize(a);
            if(szH[i]==888)
               try { Thread.sleep(888); } catch (InterruptedException e) {;}
         } catch(Exception e2) {;}
      } // for
      printf("======== Main program finish ========\n" );
   } // main( ) ends here

   static void printFrameSize(Applet a) {
      printf("Current Applet size = " + a.getSize( ) +"\n" );
      if(isApplication)  // additional message for Application
         printf("  Frame size = " + ((Grid)a).f.getSize( ) +"\n");
   }

   public void init( ) {
      println("= = => init( ) is running...");
      toolkit = Toolkit.getDefaultToolkit( );  // for later use
      if(isApplication) {
         WindowHandler chang3 = new WindowHandler( );
         f.addWindowListener( chang3 );
      }
      Image myImage;
      ImageIcon myIcon;;
      JLabel labMyPic =
          createLabelWithPicture("images/mypic.gif", CAPTION_LAB_MYPIC);
      labMyPic.setForeground(COLOR_LAB_MYPIC);
      bMyPic =
          createButtonWithPicture("images/gigi.jpg", CAPTION_B_MYPIC);

      //bMyPic.setEnabled(false);  // 不准按這 
      bMyPic.setSize(58,58);
      bMyPic.validate( );
      bMyPic.updateUI();
      bMyPic.setCursor( new Cursor(Cursor.HAND_CURSOR) );
    ///
      Panel bigPan = new Panel( );
      setLayout(new BorderLayout() );
      add(bigPan, BorderLayout.CENTER);
      Panel pDisp = new Panel( );
      arrangeDisplay(pDisp);    // use GridBagLayout to arrange display
      add("North", pDisp);     // then, put the panel on North side
     ///
      display.setFont(DISPLAY_FONT);
      display.setBackground(DISPLAY_BG_COLOR);
      display.setForeground(DISPLAY_FG_COLOR);
    ///
      bigPan.setLayout(new GridLayout(2,3));
      bigPan.add(labMyPic);    // my picture on a Label
      bigPan.add(bMyPic);  // pic on a Button
    // //
      Panel p3 = new Panel(new GridLayout(4,3));
      layoutDigitsOnPanel(p3);
      bigPan.add(p3);
      Cursor csr2 = getMyCursor("images/point.gif");
      for(int i=0; i <= 11; ++i) {
         bDigits[i].setCursor( csr2 );
      }
     //
      Panel tmpPan = new Panel(new GridLayout(2,1));
       // put the following two components in a temp Panel
       tmpPan.add( bTaskMgr = new JButton("Run Task Manager") );
       tmpPan.add( pLog = new CommandPad() );
      bigPan.add(tmpPan);    // then, put the tmpPan into our bigPan
     ///
      createFunButtons( );  // use funFilename[]
      Panel p5 = new Panel( );   // prepare to use another GridBag
      arrangeFunBoard(p5);    // use GridBagLayout
      bigPan.add(p5);
      //
     // Set ActionCommand for every Widget, Register to the ActionListener
      setActionCommandAndListener(this);
      bTaskMgr.addActionListener(this);  // to invoke Taskmgr
      bMyPic.addActionListener(this);  // for fun
      bWhoAmI = bFun[3]; // the Mouth
     ///
      PicturePanel p6 =       // PicturePanel is in MyApplet.java
         new PicturePanel("images/funny.jpg", "照片 on Panel", true);
      bigPan.add(p6);  // put the picture into the bigPan with wantResize

      setSize(WIDTH, HEIGHT); validate( );
      setVisible(true);
   } // init( )

   void arrangeDisplay(Panel p) {
       GridBagLayout gb = new GridBagLayout( ); // a manager
       p.setLayout(gb);  // GridBagLayout
       GridBagConstraints c = new GridBagConstraints();
       Label lab = new Label("超級計算器");
       lab.setFont( new Font("Ludica Console", Font.BOLD, 24) );
       lab.setForeground(Color.red);
     /// set the Constraints
        c.fill = GridBagConstraints.NONE;
        c.weightx = 0.72;
        c.gridheight = 1; 
        c.gridwidth = 1;
        gb.setConstraints(lab, c);
       p.add( lab ); 
       display = new JTextField("Welcome to Disney World",DISPLAY_LENGTH);
       displayLength = display.getColumns();
       display.setCaretPosition( display.getText().length() ); // 游標
       display.requestFocus( );   // display.requestFocusInWindow( );
        c.fill = GridBagConstraints.BOTH;
        c.gridwidth = 3;   // hahaha
        c.weightx = 3.98;
        gb.setConstraints( display, c);
       p.add(display);
       JLabel tmp = new JLabel("帥吧");
        tmp.setForeground( new Color(58, 168, 58) ); // light green
        c.fill = GridBagConstraints.NONE;
        c.weightx = 0.5;
        c.gridwidth = GridBagConstraints.REMAINDER; // row end
        gb.setConstraints( tmp, c);
       p.add( tmp);
   }

   void layoutDigitsOnPanel(Panel p3) {
      for(int i=1; i<=9; ++i) {
          bDigits[i] = createButtonWithPicture("images/d"+i+".gif");
          p3.add(bDigits[i]);
      }
      bDigits[0] = createButtonWithPicture("images/d"+0+".gif");
      JButton bPlusMinus = new JButton("+/-");
      bPlusMinus.setFont( new Font("Roman", Font.BOLD, 14) );
      JButton bDot = new JButton("."); bDot.setFont(myFont24);
      bDigits[10] = bPlusMinus;
      bDigits[11] = bDot;
      p3.add(bDigits[0]);
      p3.add(bDigits[10]);   // == bPlusMinus
      p3.add(bDigits[11]);   // == bDot
   }

   void createFunButtons( ) {
      for(int i=0; i< bFun.length; ++i) {
          if(funFilename[i].startsWith(":") ) {
            bFun[i] = new JButton( funFilename[i].substring(1) ); // not file
            continue;
          } else
          bFun[i] =
             createButtonWithPicture("images/"+ funFilename[i] );
      } //for
   }

   void arrangeFunBoard(Panel p) {
       GridBagLayout gb = new GridBagLayout( ); // a manager
       p.setLayout(gb);  // GridBagLayout
       GridBagConstraints c = new GridBagConstraints();
       Font tmpFont = new Font("Ludica Console", Font.BOLD, 12) ;
       Component component = null;
     /// set the Constraints
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1.0;
        c.gridheight = 1; c.gridwidth = 1;
       gb.setConstraints(bFun[0], c);
       p.add( bFun[0] ); 
        c.gridwidth = GridBagConstraints.REMAINDER; // row end
       gb.setConstraints(bFun[1], c);
       p.add( bFun[1] ); 
        c.weightx = 0.0; // reset
        c.gridwidth = GridBagConstraints.REMAINDER; // row end
       gb.setConstraints(bFun[2], c);
       p.add( bFun[2] );             // on one row
        c.weightx = 0.0; // reset
        c.weighty = 1.0;
        c.gridwidth = 1;
        c.gridheight = 2;    // 2 rows
        //c.fill = GridBagConstraints.NONE;
       gb.setConstraints(bFun[3], c);
       p.add( bFun[3] ); 
      ///
        c.weighty = 0.0;  // reset
        c.gridheight = 1; 
        //c.gridwidth = GridBagConstraints.LINE_END;
        c.gridwidth = GridBagConstraints.REMAINDER; // row end
        c.fill = GridBagConstraints.HORIZONTAL;
       gb.setConstraints(bFun[4], c);
       p.add( bFun[4] ); 
       bFun[5].setFont(tmpFont);
        c.fill = GridBagConstraints.BOTH;
       gb.setConstraints(bFun[5], c);
       p.add( bFun[5] ); 
   }

   void setActionCommandAndListener(ActionListener arbian ) {
     // Set ActionCommand, and Register to the ActionListener pass to be
    // for bDigits[ ]
      for(int i=0; i < bDigits.length; ++i) {
         bDigits[i].addActionListener( arbian );
         bDigits[i].setActionCommand(btnCMD1[i]);  // the associated Command
      }
    // for bFun[ ]
      for(int i=0; i < bFun.length; ++i) {
         bFun[i].addActionListener( arbian );
         // also Register to the ActionListener
         bFun[i].setActionCommand(btnCMDFun[i]);
      }
   }


/****
   public void start( ) {
      println("= = => > start( ) is running...");
   }
*****/

   public void stop( ) {
      println("= = =< stop( ) is running...");
      super.stop( );
   }

   public void repaint( ) {
      println("- - - repaint( ) is called...");
      super.repaint( );
   }

   public void update(Graphics g) {
      println("- - -  update(g) is called...");
      super.update(g);
   }

   public void paint(Graphics g) {
      println("- - -   paint(g) is called...");
      super.paint(g);
   }

   public void actionPerformed(ActionEvent ae) {
      String cmd = ae.getActionCommand( );
      Object who = ae.getSource( );
      try {
         print("Command = " +cmd );     // show on Console for Debug
         //print(", by " + who);   // which Component fire this event?
         println("");
      } catch (Exception e) {;}
      if(who == bMyPic) { 
          changeColor(bMyPic);    // for fun
          try {
            printFrameSize(ap);
            playFile("images/laugh.au");    // make Laugh 大笑三聲
          } catch (Exception e2) {;}
      }
      else if(who == bWhoAmI) { showWhoAmI( ); }
      else if(who == bTaskMgr) { runTaskManager( ); }
      processActionCommand(cmd, who);
   } // actionPerformed

   protected int displayLength = DISPLAY_LENGTH;
   void processActionCommand(String cmd, Object who) {
       /// Note:  TextField will fire an ActionEvent when you hit ENTER
      /// Your important to do jobs are here
      int width = display.getSize().width;  // the size of Display field
      //displayLength = width / 12 - 1;    // assume Font size is 24 = 12*2
      displayLength = display.getColumns();
      try {
         showTextOnDisplay(cmd);
      } catch (Exception e) {;}
      try {
         //pLog.writeLog(cmd + " "+width, who);
         pLog.writeLog(cmd, who);
      } catch (Exception e) {;}
   } // processActionCommand

   protected int textCursorPosition = 999;
   void  showTextOnDisplay(String cmd) {
       int p = display.getCaretPosition( );
       int cmdLength = cmd.length();
       String t = display.getText();
       cmd = t.substring(0, p) + cmd + t.substring(p);
       textCursorPosition = p + cmdLength;
       //cmd = "                           " + cmd ;
       //int pos = cmd.length() - displayLength ;   // RIGHT_ALIGNMENT
       //display.setText( cmd.substring(pos) );
       // cmd = cmd.substring(pos);  // simulate RIGHT alignment
        //
       //display.updateUI();  // check? 
       int len = cmd.length();
       display.setHorizontalAlignment(JTextField.RIGHT); // 靠右
/****
****/
       display.setHorizontalAlignment(JTextField.RIGHT); // 靠右
       display.setText( cmd );
       display.setCaretPosition( textCursorPosition);    // 游標維持正確 
       // no display.updateUI(); //?
       display.requestFocus( );   // display.requestFocusInWindow( );
       display.getParent().validate();
   }

   protected int visitChangeColor = 0;   // set Red color at first time
   void changeColor(Component obj) {    // for fun
      if(visitChangeColor++ == 0 ) {
        obj.setBackground(Color.red);  return;
      }
      Color c = obj.getBackground( );
      int r = c.getRed( ), g = c.getGreen(), b = c.getBlue();
      r =  (int)(r+ 168*Math.random() ) %256;
      g =  (int)(r+ 168*Math.random() ) %256;
      b =  (int)(r+ 168*Math.random() ) %256;
      obj.setBackground( new Color(r, g, b) );
   }

   void  showWhoAmI( ) {
       try {
          display.setText( "tsaiwn@csie.nctu.edu.tw");
          println("by 蔡文能 tsaiwn@csie.nctu.edu.tw") ;
       } catch (Exception e) {;}
       try {
          playFile("images/welcome.wav");
          Thread.sleep(568);    // for your eye to see :-)
       } catch (InterruptedException e) {;}
   }

   AudioClip song = null;
   public AudioClip playFile(String filename) {
       try { song = null;
          if(isApplication) {
             //URL base = newCodeBase();
             //song = Applet.newAudioClip(new URL(base+filename)); 
             song = newAudioBoth(filename);
          } else {
             //song = getAudioClip(getCodeBase(), filename);  // Applet's
             song = newAudioBoth(filename);
          } 
          song.play( );
          String status = "...Playing .." + filename; 
          try{ showStatus(status); } catch ( Exception es ) {;}
       } catch (Exception e) {; } // ignore any error
       return song;
   }

//////////////
   Cursor getMyCursor(String filename) {
       if(isApplication) return createMyCursorBoth(filename);
       else return createMyCursorBoth(filename);
       //Image image = getImage(getCodeBase( ), filename); //for Applet
       //return createMyCursor(image);
   }

//an inner class to handle Window events
// inner class 的好處是它看得見 Global 變數, 不必傳參數就可以用
//這個 Handler 有能力處理部份 Window event
 class WindowHandler extends WindowAdapter {  // intead of WindowListener
    public void windowClosing(WindowEvent e) {
         if(!isApplication) return; // forget it
         System.exit(0); 
    } 
 } // WindowHandler
} // class Grid

class CommandPad extends Panel {
    String cmd = "";
    Object who = null;
    public CommandPad( ){
    }
    public void writeLog(String cmd, Object who) {
       this.cmd = cmd;
       this.who = who;
       repaint( );
    }
    public void paint(Graphics g) {
       int xpos = 8, ypos = 78;
       g.setColor(Color.red);
       try {
          ypos = getSize().height - 16;
       }catch(Exception e) {;}
       g.drawString("請開 Java 主控台看看", xpos, ypos);
       g.drawString("Got your ActionCommand:", 8,16);
       g.drawString(cmd, 58,28);
       if(who != null) g.drawString("by "+ who, 8,49);
    }
}

