//
//    Dragon
//    Applet Source Name [Dragon.java]
//                                    1996.2
//                 Source [ Junzo hagimoto ]
//                                    1998.5
//                 Author [Shigemitsu Shin ]

import java.applet.*;          //アプレットパッケージ(java.applet)を利用する
import java.awt.*;             //抽象ウィンドウツールキットパッケージ(java.awt)を利用する

//DragonクラスがJavaシステムで標準的に提供されるAppletクラスから継承されるサブクラスであることを宣言する
//publicで宣言すると、Dragonクラスは他のパッケージからも参照可能になる
//このDragonクラスはRunnableというインタフェース(runメソッドを実装する)を継承する

public  class  Dragon  extends Applet implements Runnable {

//以下はDragonクラスの属性

    Dimension d;                //Dimensionクラスの変数dは文字データの幅と高さを管理する                                     
    String s[];                 //HTMLから読み込んだ文字データを格納するために、Stringクラスのsインスタンスを作る
    Thread kicker = null;                                
    int    xScroll;             //xScrollは文字列を表示域の右端から左端へスクロールさせるためのX座標を管理する
    int    y_Point;             //文字列の表示位置のY座標 
    Font   font;                //Fontクラスはフォント(font)を管理する                                         
    int    strHeight,strWidth;  //文字列の幅と高さの変数                           
    int    maxText;             //表示する文字列の数                                      
    int    curTextCount=0 ;     //現在描画対象となる文字列の配列添え字(配列の何番目の要素かを示すインデックス番号)を示す

	String fontcolor;           //HTMLから読み込んだフォントの色を格納するために、Stringクラスのfontcolorインスタンスを作る
    Color  color;               //Colorクラスはフォントの色(color)を管理する                                        
	int    red,green,blue;      //フォントの色を格納する変数
	int    rgb;
	int    random = 0;          //フォントの色をランダムに表示するかどうかを決める変数
	String background;          //HTMLから読み込んだ背景色を格納するために、Stringクラスのbackgroundインスタンスを作る
	Color  bgcolor;             //Colorクラスは背景色(bgcolor)を管理する
    int    bgred,bggreen,bgblue;//背景色を格納する変数
    int    bgrgb;
	
	int    speed;               //文字列がスクロールする速度
    Image  offs;                //Imageクラスのインスタンスoffsを用意する                                         
    Graphics grf;               //Imageインスタンスに描画するためにGraphicsクラスのインスタンスgrfを用意する                                        
    char separated[];           //separatedはchrの配列(すなわち文字列の文字)を格納するためのもの                                    
    int    charWidth;           //chrWidthは文字列中のカレント文字のサイズである、プロポーショナルフォントの場合は文字ごとに文字幅が異なるのでこの変数が必要となる
    float  f[];                 //float配列は次の初期化処理(initメソッド)で実行される座標の計算結果を格納するためのもの                         // ADD
    int    maxFloatArray= (int)(3.1415 * 10 * 2) ;   //maxFloatArrayはfloat配列の数
     
//initメソッドはアプレットに対応しているWebページ(HTML)がアクティブになったとき、アプレットを初期化するために使うメソッド

    public void init() {
       d = size();         //変数dをsize()によって初期化する、またsize()はアプレットの表示域をHTMLから取得する
       xScroll = d.width;   //xScrollを表示域の幅d.widthで初期化する                 

       offs = createImage( d.width, d.height);  //表示域と同じサイズのビットイメージを確保する                     
       grf  = offs.getGraphics();               //ビットイメージに描画を行うためにGraphicsインスタンスを取得する                   

       f  = new float[maxFloatArray];                  //X座標の初期値
       double  x = 3.1;                                //X座標のxが3.1から-3.1までのsin(x)・・・をY座標(高さ)として求め、float配列に格納する
       for(int i=0; i < maxFloatArray; i++ ){          
	   f[i]  = (float)Math.sin(x)*(float)Math.cos(x)*(float)Math.exp(x) ;               
//           f[i]  = (float)Math.sin(x)*(float)Math.cos(x)*(float)Math.exp(x)*(float)Math.log(x) ;       
           x -= 0.1;          
	   }
        String param = getParameter( "speed" );                  //paramはnameとvalueで構成され、Javaソース(アプレットソース)の中からgetParameterでname(この場合はspeed)を引数にすることで、HTMLのvalueにかかれた内容をStringインスタンスとして取得する                   
        speed = (param != null) ? Integer.parseInt(param) : 2;   //もし対応するnameがHTML中に記載されていない場合はnullを返し、その値(value)はdefault値として1をとります  
        if(speed < 1 || speed > 5 ){                             //またspeedのvalueが1より小さいか5より大きい場合もspeedの値は1をとります                               
          speed = 2;                                            
        }                                                          

        param = getParameter( "maxText" );                          //maxTextのvalue値は文字列の数                   
        maxText = (param != null) ? Integer.parseInt(param) : 1;    //getParameter()が返す値はString値なので、それを数値に変換する、またHTMLに文字列数が定義されていない場合はdefault値として1を返す    
        s = new String[maxText];                                    //文字列配列s[]に実際の配列を文字列数だけ生成する、newはStringインスタンスの配列をメモリに格納することを意味する
        int i=0;                                    //maxTextの数だけ文字列を取得し、Stringインスタンスをnewして、文字列配列に文字列を格納する               
        do{                                                         
            param = getParameter( "text"+ (i+1) );                  
            if(param != null ){                                     
                s[i] = new String(param);                           
             }else{                                                  
                if( i==0 ){                                         
                    s[i] = "Java";                  //default値はJavaとする                                    
                }                                                   
            maxText = i+1;                                      
            }                                                       
        }while( param != null && ++i != maxText );                  
//////////////////////////////////////////////////////////////////////////
//        font  = new Font("TimesRoman",Font.BOLD,fontsize);
        font= initFont();
        setFont(font);
//////////////////////////////////////////////////////////////////////////
        strHeight  =(getFontMetrics(font)).getLeading() ;      
        strHeight -=(getFontMetrics(font)).getDescent() ;      
        strHeight +=(getFontMetrics(font)).getAscent() ;       
        y_Point    = (d.height + strHeight
                   - (getFontMetrics(font)).getDescent() ) / 2;

        fontcolor = getParameter("fontcolor");
		if(fontcolor == null){
			fontcolor = "black";
		}
		if(fontcolor.equals("setcolor")){
			param = getParameter("rgb");
			int nLen_rgb = param.length();
			try{
				if(nLen_rgb == 6){
				    rgb = Integer.parseInt(param,16);
				}
			    else{
				    rgb = Integer.parseInt("000000",16);
				} 
			}
			catch (NumberFormatException e){
				rgb = Integer.parseInt("000000",16);
			}
			color = new Color(rgb);
        }
        else{
			if(fontcolor.equals("black")){red = 0;    green = 0;    blue = 0;}
            else if(fontcolor.equals("blue")){red = 0;    green = 0;    blue = 255;}
			else if(fontcolor.equals("cyan")){red = 0;    green = 255;  blue = 255;}
			else if(fontcolor.equals("darkgray")){red = 169;  green = 169;  blue = 169;}
			else if(fontcolor.equals("gray")){red = 128;  green = 128;  blue = 128;}
			else if(fontcolor.equals("green")){red = 0;    green = 255;  blue = 0;}
			else if(fontcolor.equals("lightgray")){red = 211;  green = 211;  blue = 211;}
			else if(fontcolor.equals("magenta")){red = 255;  green = 0;    blue = 255;}
			else if(fontcolor.equals("orange")){red = 255;  green = 165;  blue = 0;}
			else if(fontcolor.equals("pink")){red = 255;  green = 192;  blue = 203;}
			else if(fontcolor.equals("red")){red = 255;  green = 0;    blue = 0;}
			else if(fontcolor.equals("white")){red = 255;  green = 255;  blue = 255;}
			else if(fontcolor.equals("yellow")){red = 255;  green = 255;  blue = 0;}
		    else if(fontcolor.equals("random")){random = 1; red = 0;    green = 0;    blue = 0;}
			else{red = 0;  green = 0;  blue = 0;}
			color = new Color(red,green,blue);
		}
		background = getParameter("background");
		if(background == null){
			background = "white";
		}
		if(background.equals("setcolor")){
			param = getParameter("bgrgb");
			int nLen_bgrgb = param.length();
			try{
				if(nLen_bgrgb == 6){
				    bgrgb = Integer.parseInt(param,16);
				}
			    else{
				    bgrgb = Integer.parseInt("ffffff",16);
				} 
			}
			catch (NumberFormatException e){
				bgrgb = Integer.parseInt("ffffff",16);
			}
			bgcolor = new Color(bgrgb);
        }
        else{
			if(background.equals("black")){bgred = 0;    bggreen = 0;    bgblue = 0;}
            else if(background.equals("blue")){bgred = 0;    bggreen = 0;    bgblue = 255;}
			else if(background.equals("cyan")){bgred = 0;    bggreen = 255;  bgblue = 255;}
			else if(background.equals("darkgray")){bgred = 169;  bggreen = 169;  bgblue = 169;}
			else if(background.equals("gray")){bgred = 128;  bggreen = 128;  bgblue = 128;}
			else if(background.equals("green")){bgred = 0;    bggreen = 255;  bgblue = 0;}
			else if(background.equals("lightgray")){bgred = 211;  bggreen = 211;  bgblue = 211;}
			else if(background.equals("magenta")){bgred = 255;  bggreen = 0;    bgblue = 255;}
			else if(background.equals("orange")){bgred = 255;  bggreen = 165;  bgblue = 0;}
			else if(background.equals("pink")){bgred = 255;  bggreen = 192;  bgblue = 203;}
			else if(background.equals("red")){bgred = 255;  bggreen = 0;    bgblue = 0;}
			else if(background.equals("white")){bgred = 255;  bggreen = 255;  bgblue = 255;}
			else if(background.equals("yellow")){bgred = 255;  bggreen = 255;  bgblue = 0;}
			else{bgred = 255;  bggreen = 255;  bgblue = 255;}
    	    bgcolor = new Color(bgred,bggreen,bgblue);
		}
    }

    public Font initFont(){
        String fontname;
        String stylestring;
        int fontstyle = -1;
        int fontsize;
	    String sizestring;
        Font font;
        Font defaultfont;
        defaultfont = getFont();

        fontname = getParameter("fontname");
        if(fontname == null)
            fontname = defaultfont.getName();
        stylestring = getParameter("fontstyle");
        if(stylestring == null)
            fontstyle = defaultfont.getStyle();
// Get the Font
        if(fontname.equalsIgnoreCase("Courier")  ||
           fontname.equalsIgnoreCase("Dialog")   ||
		   fontname.equalsIgnoreCase("Helvetica")   ||
           fontname.equalsIgnoreCase("TimesRoman") )
           {
// Nothing to do the fontname is supported
           }
        else{
           fontname = defaultfont.getName();
        }
        if(fontstyle == -1) {
// Get the Font Style
            if(stylestring.equalsIgnoreCase("PLAIN"))
                fontstyle = Font.PLAIN;
            else if(stylestring.equalsIgnoreCase("BOLD"))
                fontstyle = Font.BOLD;
			else if(stylestring.equalsIgnoreCase("ITALIC"))
                fontstyle = Font.ITALIC;
			else if(stylestring.equalsIgnoreCase("PLAIN_ITALIC"))
                fontstyle = Font.ITALIC|Font.PLAIN;
            else if(stylestring.equalsIgnoreCase("BOLD_ITALIC"))
                fontstyle = Font.ITALIC|Font.BOLD;
            else
                fontstyle = Font.BOLD;
        }
// Get the Font Size
        sizestring = getParameter("fontsize");
        if(sizestring == null)
            fontsize = defaultfont.getSize();
        else {
            try {
                fontsize = Integer.parseInt(sizestring);
            } 
            catch (NumberFormatException e) {
                fontsize = defaultfont.getSize();
            }
        }
        font = new Font(fontname, fontstyle, fontsize);
        return font;
    }

//startメソッドの中で作成された描画用スレッドがスタートすると呼び出され、Webページが開かれている間、描画を繰り返すためのループを実行する

    public void run() {
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY-3);
        while (kicker != null) {
            repaint();
            try {
                Thread.sleep( 20 );                         
            } catch (InterruptedException e) {}
       }
          kicker=null;
    }

    public void update(Graphics g) {                        
           paint(g);                                        
    }

//再描画が必要となったときにJavaシステムから呼び出されたり、runメソッドのrepaint()呼び出しの結果、システムから間接的に呼び出されるメソッドで、アプレットの表示に関する処理を行う
	
    public void paint(Graphics g) {
//        grf.setFont( font );
        grf.setFont(font);                                  
        grf.setColor(bgcolor);
        grf.fillRect(0, 0, d.width, d.height);

		if(xScroll == d.width){                                       
            if(random == 1){
				red   = (int)(Math.random() * 256);                       
                blue  = (int)(Math.random() * 256);                       
                green = (int)(Math.random() * 256);
                color = new Color(red,green,blue);
			}
            curTextCount++;                                           
            if(curTextCount > maxText){                               
                curTextCount=1;                                     
            }                                                         
            strWidth = (getFontMetrics(font)).stringWidth(s[curTextCount-1]);
            separated =  new char [ s[curTextCount-1].length() ];      
            s[curTextCount-1].getChars(0,                              
                      s[curTextCount-1].length(),separated,0);     
		}                                                             
            grf.setColor(color);
            xScroll -= speed;
            int _xOffset=0;                                             //_floatdx配列の添え字として使用する、配列の0番目は表示域の右端に対応する
            int _width = d.height -  y_Point;
            for(int i=0;i < s[curTextCount-1].length();i++){  
    	    	 int _floatIdx=0;                             
                 int _y;                                      
	    		 _xOffset += (i != 0)?                                      
                 (getFontMetrics(font)).charWidth(separated[i-1]) : 0;  
                                                                   
                 if( xScroll + _xOffset  < d.width ){                  
				      if( d.width - xScroll - i >= 0 ){             
                          _floatIdx = (d.width - xScroll - i) % maxFloatArray; 
					  }
					  else{                                                     
                           _floatIdx = 0;                                       
					  }                                                      
				 }                                                          
                 _y =  (int)(f[ _floatIdx ] * _width * 0.9);                
                 grf.drawChars(separated, i,1 ,xScroll +  _xOffset,    
                 y_Point + _y );                                 
			}
            if(xScroll < -strWidth ){                           
                xScroll = d.width;                 
			}
         g.drawImage(offs, 0, 0, this);                               
    }

//アプレットに対応しているWebページが開かれた直後にJavaシステムから自動的に呼び出され、描画用スレッドを作成してスタートさせる

	public void start() {
        if (kicker == null) {
           kicker = new Thread(this);
           kicker.start();
        }
    }

//実行中のアプレットを埋め込んだWebページが他のページへ切り替わるとき、Javaシステムから自動的に呼び出され、描画用スレッドを停止すると同時に、runのwhileループを脱出するためにkickerにnullを入れる

	public void stop() {
        if (kicker != null) {
            kicker.stop();
            kicker = null;
        }
    }
}
//