/**********************************************************************************
 *                                                                                *
 *                            Jumping letter Applet                               *
 *                               ( Bounder.java )                                 *
 *                                                         Author : Seiichi Inoue *
 **********************************************************************************/

/********************** << Imported package class definition >> *******************/
import java.applet.Applet;      /* Applet packages                                */
import java.awt.*;              /* All of the Abstract Windowing Toolkit packages */

/************************** <<Oneself of class definition>> ***********************/
//    Class name      : Bounder
//    Access control  : public( Access possibility even from which class )
//    Extends class   : Applet
//    Implements class: Runnable( Use of Thread is enabled )
public  class  Bounder  extends Applet implements Runnable {

/************************* << Class attribute of definition >> ********************/
    Dimension   d;                            /* Display range                    */
    String      s[];                          /* Letter arrangement range         */
    String      param;                        /* Parameter reading                */
    Thread      kicker=null;                  /* Thread(Initial value:suspension) */
    int         xScroll;                      /* Scroll position                  */
    Font        font;                         /* The letter height                */
    int         fontsize;                     /* Font size                        */
    String      fontname;                     /* Font name                        */
    int         strWidth;                     /* The letter line width            */
    int         maxText;                      /* The number of letter block       */
    int         curTextCount = 0;             /* Present letter block             */
    boolean     randomcolor;                  /* Color designated of letter       */
    int         red,blue,green;               /* Letter color                     */
    Color       color;                        /* Letter color                     */
    int         backred,backblue,backgreen;   /* Background color                 */
    Color       backcolor;                    /* Background color                 */
    int         speed;                        /* Display speed                    */
    Image       offs;                         /* Off screen                       */
    Graphics    grf;                          /* Drawing range                    */
    int         bound_y;                      /* The height of bound              */
    double      time;                         /* Progress time (64 bit long data) */
    int         start_speed;                  /* Input initial velocity           */
    int         start_H;                      /* Initial velocity                 */
    int         f_Descent;                    /* Lower distance fm reference point*/

/***************** << Class of method (implementation procedure) >> ***************/
//
/******** Initialization (init) method *********/
    public void init() {
        d = size();                             /* Set display screen size        */
        xScroll = d.width;                      /* Set display start position     */

        offs = createImage(d.width,d.height);   /* Off scr area preparation       */
        grf  = offs.getGraphics();              /* Graphics object extraction     */

        param = getParameter("speed");          /* Input "speed" reading          */
        speed = (param != null)?                /* Input determination            */
            Integer.parseInt(param): 1;
        if(speed < 1 && speed > 5) {            /* Input abnormal determ          */
            speed = 1;                          /* Set 1 at abnormality           */
        }

        param = getParameter("maxText");        /* Text block number reading      */
        maxText = (param != null)?              /* Input determination            */
            Integer.parseInt(param): 1;
        s = new String[maxText];                /* Preparation letter arrange     */

        param = getParameter("fontsize");       /* Font size reading              */
        fontsize = (param != null)?             /* Input determination            */
            Integer.parseInt(param): 30;
        param = getParameter("font");           /* Font reading                   */
        fontname = (param != null)?             /* Input determination            */
            param: "Dialog";

        param = getParameter("randomcolor");    /* Color designation reading      */
        param = (param != null)?                /* Input determination            */
            param: "true";
        if ( "true".equals (param) )            /* Random designate ?             */
            randomcolor = true;                 /* YES: Set random (true)         */
        else
            randomcolor = false;                /* No : Set random (false)        */
        if ( randomcolor ) {}                   /* Random designate ?             */
        else {                                  /* No: Parameter designate        */
            param = getParameter("red");        /* Letter red reading             */
            red = (param != null)?              /* Input determination            */
                Integer.parseInt(param): 0;
            param = getParameter("green");      /* Letter green reading           */
            green = (param != null)?            /* Input determination            */
                Integer.parseInt(param): 0;
            param = getParameter("blue");       /* Letter blue reading            */
            blue = (param != null)?             /* Input determination            */
                Integer.parseInt(param): 0;
            color = new Color(red,green,blue);  /* Letter color assembly          */
        }

        param = getParameter("backred");        /* Background red reading         */
        backred = (param != null)?              /* Input determination            */
            Integer.parseInt(param): 255;
        param = getParameter("backgreen");      /* Background green reading       */
        backgreen = (param != null)?            /* Input determination            */
            Integer.parseInt(param): 255;
        param = getParameter("backblue");       /* Background blue reading        */
        backblue = (param != null)?             /* Input determination            */
            Integer.parseInt(param): 255;
        backcolor = new Color(backred,backgreen,backblue); /* Color assembly      */

        param = getParameter("start_speed");    /* Initial velocity reading       */
        start_speed = (param != null)?          /* Input determination            */
            Integer.parseInt(param): 40;

        param = getParameter("fonttype");       /* Font type reading              */
        if ( "BOLD".equals (param) )                            /* BOLD ?     */
            font = new Font(fontname,Font.BOLD,fontsize);       /* Set BOLD       */
        else {
            if ( "ITALIC".equals (param) )                      /* ITALIC ?    */
                font = new Font(fontname,Font.ITALIC,fontsize); /* Set ITALIC     */
            else
                font = new Font(fontname,Font.PLAIN,fontsize);  /* Set PLAIN      */
        }
        f_Descent  = (getFontMetrics(font)).getDescent(); /* Get descend of letter*/

        int i=0;                                /* Loop counting initial          */
        do {                                    /* DO loop                        */
            param = getParameter("text" + (i+1)); /* i+1st text reading           */
            if(param != null) {                 /* Text presence determ           */
                s[i] = new String(param);       /* Yes( Text setting )            */
            } else {                            /* No                             */
                if( i==0 ) {                    /* No text ?                      */
                    s[i] = "Text Erorr";        /* Set text abnormal              */
                }
                    maxText = i + 1;            /* Set text block number          */
                }
        } while(param != null && ++i != maxText); /* DO loop completion determ    */

    }                                           /* End of initial method          */

/******** Implementation (run) method **********/
    public void run() {
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY-3);
        while (kicker != null) {              /* Repeat until kicker becomes null */
            repaint();                          /* Drawing                        */
            try {                               /* Interruption confirmation      */
                Thread.sleep( 20 );             /* Wait 20 milli seconds set      */
            } catch (InterruptedException e) {} /* Interruption processing        */
        }
        kicker = null;
    }                                           /* End of run method              */


/********** Renewal (update) method ************/
    public void update(Graphics g) {            /* Lost of screen flickering      */
        paint(g);                               /* Drawing                        */
    }                                           /* End of update method           */


/*********** Drawing (paint) method ************/
    public void paint(Graphics g) {
        grf.setFont(font);                      /* Set display font               */
        grf.setColor(backcolor);                /* Set display back color         */
        grf.fillRect(0, 0, d.width, d.height);  /* Display range is applied       */
        if (xScroll == d.width) {               /* Display position is top?       */
            curTextCount ++ ;
            if (curTextCount > maxText) {       /* Letter block over ?            */
                curTextCount = 1;               /* YES: the first block set       */
            }
            strWidth = (getFontMetrics(font)).  /* Read width of letter line      */
                        stringWidth(s[curTextCount - 1]);
            start_H = start_speed;              /* Set initial velocity           */
            time = 0.1;                         /* Set initial progress time      */
            if ( randomcolor ) {                    /* Letter color random ?      */
                red = (int)(Math.random() * 256);   /* Random red setting         */
                green = (int)(Math.random() * 256); /* Random green setting       */
                blue = (int)(Math.random() * 256);  /* Random blue setting        */
                color = new Color(red,green,blue);  /* Letter color assembly      */
            }
        }

        grf.setColor(color);                    /* Set display color              */
        xScroll -= speed;                       /* Calculate of the move position */
        bound_y = (int)(start_H * time - 5.0 * time * time); /* Calculate height  */
        time += 0.5;                            /* Addition of progress time      */
        if ( bound_y < 0 ) {                    /* Height is negative?            */
            bound_y = 0;                        /* To Zero of the height setting  */
            time = 0.1;                         /* Set initial progress time      */
            start_H -= 3;                       /* Reduction of initial velocity  */
            if ( start_H < 0 ) {                /* Initial velocity is negative?  */
                bound_y = 0;                    /* It does not jump               */
            }
        }
        if(xScroll < -strWidth)  {              /* Display end determination      */
           xScroll = d.width;                   /* Initialize display position    */
        }
        grf.drawString(s[curTextCount-1],xScroll,/* Display letter                */
            d.height - f_Descent - bound_y );
        g.drawImage(offs, 0, 0, this);          /* Image display                  */
    }                                           /* End of drawing method          */

/************* Start (start) method ************/
    public void start() {
        if ( kicker == null ) {                 /* Kicker is null? ( Suspension? )*/
            kicker = new Thread(this);          /* YES: kicker setting            */
            kicker.start();                     /* Setting of start               */
        }
    }                                           /* End of start method            */

/************ Stop (stop) method ***************/
    public void stop() {
        if( kicker != null ) {                  /* Kicker is not null?( action? ) */
            kicker.stop();                      /* Set kicker to suspension       */
            kicker = null;                      /* Set kicker suspension condition*/
        }
    }                                           /* End of stop method             */

}                                               /* End of class setting           */

/**********************************************************************************
 *                          End of Jumping letter Applet                          *
 **********************************************************************************/