//SoundWin.java -- by tsaiwn@csie.nctu.edu.tw
// Test Open a URL window, playing Song in Applet
//  javac -encoding Big5 -target 1.1 SoundWin.java
/************************
 <br>
 <applet code="SoundWin.class" width=380 height=268>
 </applet>
 <! More Files need:
    howcome.au, laugh.au, welcome.au  and gigi.jpg , gigib.jpg
   ---------------------------------------------------------->
 </body>
 </html>
************************/

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.text.*;
import javax.swing.ImageIcon;
import javax.swing.JButton;

public class SoundWin extends Applet implements ActionListener{
      static final int width=258, height=168;
      static int msgLength;   // msg is on the last part
      String songName = "howcome.au",  laughName = "laugh.au";
      String kimoLocation = "http://tw.yahoo.com/";
      String songLocation = "http://www.csie.nctu.edu.tw/~tsaiwn/audir/";
      String flashLocation =
       "http://www.csie.nctu.edu.tw/~tsaiwn/flash/" +
            "movie%ad%ec%a9l%c0%c9/4-%af%ab%c0J%abL%abQ/4.swf";
      String swfAry[ ] = {  // array for .swf flash file
          "http://www.csie.nctu.edu.tw/~tsaiwn/flash/" +
              "movie%ad%ec%a9l%c0%c9/4-%af%ab%c0J%abL%abQ/4.swf",
          "http://www.csie.nctu.edu.tw/~tsaiwn/flash/" +
              "movie%ad%ec%a9l%c0%c9/2-%ad%b8%b5%be%a4%a7%b9%da/2.swf",
          "http://www.csie.nctu.edu.tw/~tsaiwn/flash/02-GGL-fun/GGL_02.swf",
          "http://www.csie.nctu.edu.tw/~tsaiwn/mouse/catch_cursor.htm",
          "http://www.csie.nctu.edu.tw/~tsaiwn/flash/" +
              "movie%ad%ec%a9l%c0%c9/3-%b1%a1%b8%d6/3.swf",
          "http://www.csie.nctu.edu.tw/~tsaiwn/flash/" +
              "effect%ad%ec%a9l%c0%c9/36-%b7%cf%a4%f5%a4@/36.swf",
          "http://www.csie.nctu.edu.tw/~tsaiwn/flash/" +
              "effect%ad%ec%a9l%c0%c9/25-3Dengine/25.swf",
          "http://www.csie.nctu.edu.tw/~tsaiwn/flash/" +
              "effect%ad%ec%a9l%c0%c9/61-%b7%c6%b9%ab%afS%ae%c4%a4Q/61.swf",
          "http://www.csie.nctu.edu.tw/~tsaiwn/course/introcs/ghost/" };

      String giGiFileName = "gigi.jpg";
      String giGiBFileName = "gigib.jpg";
      Toolkit toolkit;
      Frame f;
      Applet ap=null;
      Image giGiImage, giGiImage2;
      ImageIcon giGiIcon;
      JButton bGiGi = new JButton("Ha大笑");
      AudioClip song; 
      Button bWeb = new Button("連到奇摩");
      Button bSong = new Button("點唱 情字這條路");
      Button bLaugh = new Button("Ha大笑");
      Button bQuit = new Button("STOP");
      Button bFlash = new Button("FLASH");
      static int visitCount = 0;
      Font myFont = new Font("標楷體", Font.BOLD, 18);
      protected Hinter hinter;  // a thread to flash the hint message
      String status = "---";

   public static void main( String s[]) {   // for Application only
      Frame f = new Frame("Window 2004");
      SoundWin a = new SoundWin( ); a.ap = a; a.f = f;
      a.init( ); a.start( );  // simulate Applet behavior
      f.add(a, BorderLayout.CENTER); f.setSize(width+20, height+12);
      f.setVisible(true); f.validate( );
   }

   public SoundWin( ) {  // Constructor
      if(ap==null) ap = this;   // it is Applet and thus ap is null
   }

   private void decorateFrame( ) {
      Label b2a = new Label("假"); Label b2b = new Label("做");
      Label b2c = new Label("真"); Label b2d = new Label("時");
      b2a.setFont(new Font("標楷體", Font.BOLD, 18));
      b2b.setFont(myFont); b2c.setFont(myFont); b2d.setFont(myFont);
      Label bx = new Label("　"), by = new Label("　"), bz = new Label("　");
      bx.setFont(myFont); by.setFont(myFont); bz.setFont(myFont);
      Panel pRight = new Panel(new GridLayout(5,2, 1,1));
      pRight.setLocale(java.util.Locale.CHINESE);
      pRight.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
      Label ya = new Label("真"); Label yb = new Label("亦");
      Label yc = new Label("假");
      ya.setFont(myFont); yb.setFont(myFont); yc.setFont(myFont);

      pRight.add(b2a); pRight.add(bx); pRight.add(b2b); pRight.add(by);
      pRight.add(b2c); pRight.add(ya);
      pRight.add(b2d); pRight.add(yb);
      pRight.add(bz); pRight.add(yc);
      ap.add(pRight, BorderLayout.EAST);
     //
      Panel pWin = new Panel(); pWin.add(bSong);
      pWin.add(bWeb); pWin.add(bFlash); 
      ap.add(pWin,"South");
     //
      Panel pLaugh = new Panel(new GridLayout(2,1,5,28));
      pLaugh.add(bGiGi); pLaugh.add(bQuit);
      ap.add(pLaugh, "West"); 
   } // decorateFrame

   public void init( ) {
      toolkit = Toolkit.getDefaultToolkit();
      bGiGi = new JButton("HaHa大笑");
      try {
         giGiImage = getImage(new URL( getCodeBase()+ giGiFileName));
         giGiIcon = new ImageIcon(giGiImage);
         bGiGi = new JButton(giGiIcon);
         giGiImage2 = getImage(new URL( getCodeBase()+ giGiBFileName));
      } catch (Exception e) { ; }
      bGiGi.setCursor( new Cursor(Cursor.HAND_CURSOR) );
      bQuit.setCursor( new Cursor(Cursor.HAND_CURSOR) );
      //ap.setLayout(new BorderLayout( ) );
      setLayout(new BorderLayout( ) );
      decorateFrame( );
     ///
      bQuit.setBackground(Color.red);
      bQuit.setFont( new Font("Ludica Console", Font.BOLD, 20) );
      bSong.setBackground(Color.pink);
      bWeb.setBackground(Color.green);
     ////
      bWeb.addActionListener(this);  // register with ActionListener
      bFlash.addActionListener(this);
      bSong.addActionListener(this);
      bGiGi.addActionListener(this);
      bGiGi.addMouseListener(new Amigo( ));
      bQuit.addMouseListener(new Amigo( ) );
      bQuit.addActionListener(this); 
      ap.setSize(width, height);
      ap.setVisible(true);
      status = "...Press the Button to test ..";  repaint( );
     /// for Application
      if( f != null) {
         f.setSize(width+20, height+12);
         f.setVisible(true); f.validate( );
      }
      msgLength = msg.length( );
      hinter = new Hinter( );  // is a Thread acts as a timer
      hinter.start( );  // start the Timer thread to toggle hint message
   } // init()

   public void start( ) { super.start( ); }

   public void paint(Graphics g) { // we should NOT call paint directly
      g.setColor(Color.red);
      g.setFont( new Font("標楷體", Font.BOLD, 14) );
      g.drawString( status + "      ", 88, 128);
      if(hintMode) { // is in hintMode
         switch( (int)hinter.showFlag%8/2 ) {
            case 0:
               g.drawString( "/  ..按 FLASH 每次不同喔 !", 108, 228);
               bFlash.setBackground(Color.orange);
               break;
            case 1:
               g.drawString( "-                     !! ", 108, 228);
               bFlash.setBackground(Color.pink); break;
            case 2:
               g.drawString( "\\  ..按 FLASH 每次不同喔 !", 108, 228);
               bFlash.setBackground(Color.magenta); break;
            case 3:
               g.drawString( "|                    !! ", 108, 228);
               bFlash.setBackground(Color.white); break;
         } // switch
         if( hinter.showFlag <= 18 )
               g.drawString( "   ..按 FLASH 每次不同喔 !", 108, 228);
      }
      rollMessage(g);
   }

   private void rollMessage(Graphics g) {
       int showLen = 18;
       int len = msgLength;
       int p = (int) (hinter.showFlag % msgLength);
       int pEnd = p + showLen -1;
       String s;
       if(pEnd < msgLength ){
         s = msg.substring(p, pEnd);
       }else{
         int pLen  = msgLength - p;
         s = msg.substring(p, msgLength-1) + msg.substring(0, showLen-pLen);
       }
       g.drawString( s, 108, 58);
   }

   public void actionPerformed (ActionEvent evt){
      Object who = evt.getSource( );
      if(who == bWeb) {
          bWeb.setBackground(Color.red);
          openKimo( );
          //f.validate( );  // so that Layout Manager ...
      }
      else if(who == bSong) playSong( ); //play
      else if(who == bGiGi) makeLaugh( ); //play laugh.au
      else if(who == bFlash) { openFlashURL( ); }
      else if(who == bQuit) {
          if(song != null) song.stop( );  // stop playing the song
          status = "...Press the Button to test ..";  repaint( );
          System.exit(0);
      } //
   } // actionPerformed()

   void openKimo( ) {
       try {
          URL url = new URL(kimoLocation);
          getAppletContext().showDocument(url, "_blank"); 
                         // _blank means in New Window
       } catch (Exception e) {; }
   }

   void openFlashURL( ) {
       int n = (int)(Math.random( ) * 100);
       n = n% swfAry.length;
       if( visitCount++ == 0 ) n = 0;   // first visit, show swfAry[0]
       if( visitCount == 2 ) n = 2;  // GGL
       if( visitCount == 3 ) n = 3;  // play_hand_mouse
       if( visitCount >= 4 )if( n == 0 ) n = visitCount % swfAry.length;
       try {
          flashLocation = swfAry[n];
       } catch (Exception e) { n=2; }
       try {
          URL url = new URL( flashLocation ); // a file in ~tsaiwn/...
          getAppletContext().showDocument(url, "_blank"); 
       } catch (Exception e) {; }
   }

   void openSong( ) {
       try {
           URL url = new URL( (songLocation + songName).trim() );
           getAppletContext().showDocument(url, "_blank"); 
       } catch (Exception e) {; }
   }

   void playSong( ) {
       try {
         //System.err.print("CodeBase= " + getCodeBase() ); 
         status = "...Loading " + songName;  repaint( );
         showStatus("...Loading " + songName);
         song = null;
         song = getAudioClip(getDocumentBase(), songName); 
       } catch ( Exception e ) {
           //System.out.println("Fail "+e);
           try{
              showStatus(".. " + songLocation + songName);
              song = getAudioClip( new URL(songLocation + songName) );
              status = ".. " + songLocation + songName + "     ";
              if(song==null) { openSong(); return;  }  // try my best
           } catch (Exception e2){
           //System.out.println("Fail "+e);
              try{
                song = getAudioClip( new URL("./welcome.au") );
                status = "..   ./welcome.au == === ===" +  "     ";
              } catch (Exception e3){ ; }
           }
       } ; //
        // Play the sound if we got the AudioClip
       try {
          try{System.err.println("Playing.." + songName);}catch(Exception e){}
          if(song!=null) {
             song.play(); 
             status = "...Playing " + songName;
          }
          repaint( );
          showStatus(" " + status );
       } catch ( Exception e ) { return; }
   } // playSong()

   void makeLaugh( ) {
       try {
          song = getAudioClip(getDocumentBase(), "laugh.au"); 
          song.play( );
          status = "...Laugh .." + laughName;  repaint( );
       } catch (Exception e) {; }
   }

   protected boolean hintMode = false;   // control toggle display hint

 // an inner class to act as a Timer to show hint message
 class Hinter extends Thread {
    protected volatile boolean shouldDie = false;  // instead of stop( );
    protected long showFlag = 0;
    final private static int showInterval = 588;
    public void run( ) {  // Thread should implements the run( ) method
       while( ! shouldDie) { // Loop forever till the Master wants me to die
          try { showFlag++; } catch (Exception e){;}
          hintMode = true;
          repaint( );    // call it every showInterval milli-seconds
          hintMode = false; // so that won't affect other's call to paint
          try {sleep(showInterval); } catch(InterruptedException e){;}
       } // while
    } // run
 } // MyTimer

 // another inner class Amigo to handle Mouse events
 //這個 Amigo 有能力處理部份 Mouse event
 class Amigo extends MouseAdapter {
    public void mouseEntered(MouseEvent e){
        Object who = e.getSource( );   /* 查哪零件觸發 Mouse event? */
        if(who == bGiGi) {
          status = "... 按我就會大笑喔:-)";
          giGiIcon.setImage(giGiImage2);  bGiGi.updateUI();
        }
        if(who == bQuit) {
          status = "... 按 STOP 停止大笑或唱歌 ! ";
        }
        repaint( );
    }
    public void mouseExited(MouseEvent e){ 
        Object who = e.getSource( );   /* 查哪零件觸發 Mouse event? */
        if(who == bGiGi || who == bQuit) {
          status = " ... Press Buttons to Test"; repaint( );
        }
        if(who == bGiGi) {
          giGiIcon.setImage(giGiImage); bGiGi.updateUI();
        }
        repaint( );
    }
 } // class Amigo == means friend in spanish
 ///// end of inner class Amigo

     static final String msg = " Dear ..  My Dear  . . " +
        "我答應妳再也不會  打擾妳的生活 .. " +
        "捨不得妳  所以才會騙了妳也騙自己 .. " +
        "捨不得妳  雖然明知我的愛妳不珍惜 .. " +
        " - - - . . .  每當我最需要你  最想念你" +
        " 你總是缺席 ...   " +
        "能不能讓我   陪著妳走  既然妳說   留不住妳  " +
        "回去的路   有些黑暗  擔心讓妳   一個人走" +
        " . . .  . .     .  .      ..      " +
        "如果你要離開我  . .  我想我不會太難過 " +
        " 也許會有一點點難過 ...  至少不會在你的面前難過 " +
        " 也許會在你的面前難過 ..  至少不會在你的面前流淚 " +
        " 也許會在你的面前流淚 . . 至少不會在你的面前哭出聲 " +
        " . . .        .  .      .   ..    ";
}
