/*===================================================================
 *
 * Author : Bryan Harianto
 * Title  : StringWalk.java
 * Date   : November, 2001
 *
 * Fields : 1. caption   ( e.g. caption0 )
 *          2. url       ( e.g. URL0 )
 *          3. target    ( e.g. _self, _parent, _top, _blank, name )
 *          4. fontface  ( e.g. TimesRoman )
 *          5. fontstyle ( e.g. plain, bold, italic )
 *          6. fontsize  ( e.g. 12 )
 *          7. bgcolor   ( e.g. 255,255,255 )
 *          8. fgcolor   ( e.g. 000,000,000 )
 *          9. accolor   ( e.g. 255,000,000 )
 *
 *===================================================================*/

import java.awt.*;
import java.applet.*;
import java.net.URL;

public class StringWalk extends Applet implements Runnable {

  /*=======================
   * Variable Declarations
   *=======================*/

  final static int MAX_SIZE   = 100;
  final static Cursor HAND    = new Cursor(Cursor.HAND_CURSOR);
  final static Cursor DEFAULT = new Cursor(Cursor.DEFAULT_CURSOR);

  boolean isMoving;
  int xx;          // text location
  int ntext;       // number of text
  int text_width;  // text width
  int width;       // applet width
  int height;      // applet height
  int fontsize;    // size of font
  int mouse_x;     // mouse x coordinate
  int mouse_y;     // mouse y coordinate
  int selected;    // selected caption

  String[] s;      // captions
  String[] url;    // urls
  String[] target; // targets

  Font font;       // font face
  FontMetrics fm;  // font metrics
  Thread runner;
  Color fgcolor, bgcolor, accolor;

  Image offscrImg; // double buffer image
  Graphics offscr; // double buffer graphics

  /*===========================
   * Set Font and Color Method
   *===========================*/

  public void setFont() {

    String fontface = getParameter("fontface");
    if (fontface == null)
      fontface = "Times Roman";

    try { fontsize = Integer.parseInt(getParameter("fontsize")); }
    catch (Exception e) { fontsize = 12; }

    String fontstyle = getParameter("fontstyle");
    if (fontstyle == null || fontstyle.equals("plain"))
      font = new Font(fontface, Font.PLAIN, fontsize);
    else if (fontstyle.equals("bold"))
      font = new Font(fontface, Font.BOLD, fontsize);
    else
      font = new Font(fontface, Font.ITALIC, fontsize);

    fm = offscr.getFontMetrics(font);
  }

  public void setColor() {
    String c1 = getParameter("bgcolor");
    String c2 = getParameter("fgcolor");
    String c3 = getParameter("accolor");

    if (c1 == null) c1 = "255,255,255";
    if (c2 == null) c2 = "000,000,000";
    if (c3 == null) c3 = "255,000,000";

    bgcolor   = new Color(Integer.parseInt(c1.substring(0,3)),
                          Integer.parseInt(c1.substring(4,7)),
                          Integer.parseInt(c1.substring(8,11)));
    fgcolor   = new Color(Integer.parseInt(c2.substring(0,3)),
                          Integer.parseInt(c2.substring(4,7)),
                          Integer.parseInt(c2.substring(8,11)));
    accolor   = new Color(Integer.parseInt(c3.substring(0,3)),
                          Integer.parseInt(c3.substring(4,7)),
                          Integer.parseInt(c3.substring(8,11)));
  }

  /*===================
   * Initialize Method
   *===================*/

  public void init() {
    isMoving  = true;
    runner    = new Thread(this);
    width     = getSize().width;
    height    = getSize().height;
    s         = new String[MAX_SIZE];
    url       = new String[MAX_SIZE];
    target    = new String[MAX_SIZE];

    offscrImg = createImage(width, height);
    offscr    = offscrImg.getGraphics();

    runner.start();
    setFont();
    setColor();

    String text;
    ntext = text_width = xx = 0;
    while ((text = getParameter("caption" + ntext)) != null) {
      s[ntext]      = text;
      url[ntext]    = getParameter("url" + ntext);
      target[ntext] = getParameter("target" + ntext);
      if (target[ntext] == null)
        target[ntext] = "_blank";

      text_width   += fm.stringWidth(s[ntext]) + 20;
      ntext++;
    }
    mouse_x = mouse_y = -text_width;

    setSize(width,height);
    offscr.setFont(font);
  }

  /*=========================
   * Paint and Update Method
   *=========================*/

  public void paint(Graphics g) {
    int c     = 0;
    int i     = xx;
    int h     = (height + fontsize) / 2;
    selected  = -1;
    boolean f = false;

    while (s[c] != null && i < width) {
      int w = fm.stringWidth(s[c]);
      offscr.setColor(fgcolor);
      if (mouse_x >= i && mouse_x <= i + w 
       && mouse_y <= h && mouse_y >= h - fontsize) {
        offscr.setColor(accolor);
        offscr.drawLine(i, h + 2, i + w, h + 2);
        f        = true;
        selected = c;
      }
      offscr.drawString(s[c], i, h);

      i += w + 20;
      if (++c >= ntext)
        c = 0;
    }
    if (f)
      setCursor(HAND);
    else
      setCursor(DEFAULT);

    g.drawImage(offscrImg, 0, 0, this);
    offscr.setColor(bgcolor);
    offscr.fillRect(0, 0, size().width, size().height);

    if (isMoving)
      xx--;
    if (i < -text_width)
      xx = 0;
  }

  public void update(Graphics g) {
    paint(g);
  }

  /*==============
   * Mouse Method
   *==============*/

  public boolean mouseEnter(Event evt, int x, int y) {
    isMoving = false;
    return true;
  }

  public boolean mouseExit(Event evt, int x, int y) {
    isMoving = true;
    mouse_x  = -text_width;
    mouse_y  = -text_width;
    return true;
  }

  public boolean mouseMove(Event evt, int x, int y) {
    mouse_x = x;
    mouse_y = y;
    return true;
  }

  public boolean mouseUp(Event evt, int x, int y) {
    if (selected != -1 && url[selected] != null) {
      try {
        getAppletContext().showDocument(new URL(url[selected]), target[selected]);
      }
      catch (Exception e) { }
    }
    return true;
  }

  /*===============
   * Thread Method
   *===============*/

  public void run() {
    while(true) {
      try { runner.sleep(10); }
      catch (Exception e) { }
      repaint();
    }
  }
}
