import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import java.util.*;
import java.awt.image.*;

public class ScrollBannerText extends Applet implements AdjustmentListener 
{
 Bar ver, hor;

 Image image[]         = new Image[1]; 
 Image image_bar_ver[] = new Image[1]; 
 Image image_bar_hor[] = new Image[1]; 
 Image filter_image[]  = new Image[1];
 
 Color bgcolor[]          = new Color[1];
 Color scroll_linecolor[] = new Color[1];
 Color bordercolor[]      = new Color[1];

 boolean boolean_max_h = false, boolean_max_w = false;

 int bordersize;

 String text[] = new String[1];
 int style[] = new int[1];
 Color font_color[] = new Color[1];
 Font font[] = new Font[1]; 
  
 int x, y, X, Y; 
 int min_y, max_y, z, max_x, max_h, max_w, max_image_h, max_image_w;
 int index = 1;

 MediaTracker tracker;

 Rectangle ver_rect, hor_rect, image_rect;

 Vector vec_style      = new Vector();
 Vector vec_font_color = new Vector();
 Vector vec_font       = new Vector();
 Vector vec_text       = new Vector();
 

 String[] lines;           
 int[] linewidths;
 int numlines;
 StringTokenizer t;

 Image upd;
 Graphics gr;

 public void init()
 {
  upd = createImage(getSize().width, getSize().height);
  gr = upd.getGraphics();

  tracker = new MediaTracker(this);
/******************************   B G I M A G E   *************************************/
  StringTokenizer st0 = new StringTokenizer(getParameter("bgimage"), ",#");
  image_rect = new Rectangle(Integer.parseInt(st0.nextToken()), Integer.parseInt(st0.nextToken()), 
                             Integer.parseInt(st0.nextToken()), Integer.parseInt(st0.nextToken()));
 
  image[0] = getImage(getDocumentBase(), st0.nextToken());
  tracker.addImage(image[0], 0);
                        
  filter_image[0] = createImage(new FilteredImageSource(image[0].getSource(), new R2Filter()));
  tracker.addImage(filter_image[0], 1);

/******************************   V E R T I C A L   *************************************/
  StringTokenizer st1 = new StringTokenizer(getParameter("scroll_ver"), ",#");
  ver_rect = new Rectangle(Integer.parseInt(st1.nextToken()), Integer.parseInt(st1.nextToken()), 
                           Integer.parseInt(st1.nextToken()), Integer.parseInt(st1.nextToken()));
 
   
  image_bar_ver[0] = getImage(getDocumentBase(), st1.nextToken());
  tracker.addImage(image_bar_ver[0], 2);

/****************************** H O R I Z O N T A L *************************************/

  StringTokenizer st2 = new StringTokenizer(getParameter("scroll_hor"), ",#");
  hor_rect = new Rectangle(Integer.parseInt(st2.nextToken()), Integer.parseInt(st2.nextToken()), 
                           Integer.parseInt(st2.nextToken()), Integer.parseInt(st2.nextToken()));
 
  image_bar_hor[0] = getImage(getDocumentBase(), st2.nextToken());
  tracker.addImage(image_bar_hor[0], 3);

  try { tracker.waitForAll(); } catch (Exception e) {}

/******************************   B G C O L O R   *************************************/

  StringTokenizer st3 = new StringTokenizer(getParameter("bgcolor"), ",");
  bgcolor[0] = new Color(Integer.parseInt(st3.nextToken()),
                         Integer.parseInt(st3.nextToken()), 
                         Integer.parseInt(st3.nextToken()));

  

/******************************   L I N E C O L O R   *************************************/

  StringTokenizer st4 = new StringTokenizer(getParameter("scroll_linecolor"), ",");
  scroll_linecolor[0] = new Color(Integer.parseInt(st4.nextToken()),
                                  Integer.parseInt(st4.nextToken()), 
                                  Integer.parseInt(st4.nextToken()));


/******************************   B O R D E R   *************************************/

  StringTokenizer st5 = new StringTokenizer(getParameter("border"), ",#");
  bordersize = Integer.parseInt(st5.nextToken());

  bordercolor[0] = new Color(Integer.parseInt(st5.nextToken()),
                             Integer.parseInt(st5.nextToken()), 
                             Integer.parseInt(st5.nextToken()));

  max_image_h = ((image_rect.y+image_rect.height)-(2*bordersize));
  max_image_w = ((image_rect.x+image_rect.width)-(2*bordersize));

/**************************************************************************************/

  ver = new Bar(Adjustable.VERTICAL, image_bar_ver[0], bgcolor[0], scroll_linecolor[0]);
  hor = new Bar(Adjustable.HORIZONTAL, image_bar_hor[0], bgcolor[0], scroll_linecolor[0]);

  ver.setMaximum(1000);
  hor.setMaximum(1000);

  ver.addAdjustmentListener(this);
  hor.addAdjustmentListener(this); 

    add(ver); ver.setBounds(ver_rect.x, ver_rect.y, ver_rect.width, ver_rect.height); 
    add(hor); hor.setBounds(hor_rect.x, hor_rect.y, hor_rect.width, hor_rect.height);
    setLayout(new BorderLayout());

 setBackground(bgcolor[0]);

 StringTokenizer st10 = new StringTokenizer(getParameter("text"), "|#");
    while(st10.hasMoreTokens())
    {
     style[0] = Integer.parseInt(st10.nextToken());
     String tt = String.valueOf(style[0]);
     vec_style.addElement(tt); 
                                
     font_color[0] = new Color(Integer.parseInt(st10.nextToken()), 
                            Integer.parseInt(st10.nextToken()), 
                            Integer.parseInt(st10.nextToken()));
     vec_font_color.addElement(font_color[0]);     

     font[0] = new Font(st10.nextToken(), Integer.parseInt(st10.nextToken()), 
                                       Integer.parseInt(st10.nextToken()));
     vec_font.addElement(font[0]);
    
     text[0] = st10.nextToken();
     vec_text.addElement(text[0]);
   }
}

  

  public void adjustmentValueChanged(AdjustmentEvent evt) 
  {

   Adjustable a = evt.getAdjustable();

   if (a.getOrientation() == Adjustable.VERTICAL) 
     {
      if(max_h > max_image_h)   { Y = -((MaxH()*a.getValue())/a.getMaximum()); }
     
     } else 
           {
            if(boolean_max_w)   { X = -((max_image_w*a.getValue())/a.getMaximum()); }
           
           }
       
      repaint();
      
  }


  public void paint(Graphics g) 
  {
   update(g);
  }

  public void update(Graphics g) 
  {
   gr.setColor(getBackground());
   gr.fillRect(0, 0, getSize().width, getSize().height);

   gr.drawImage(filter_image[0], image_rect.x, image_rect.y, image_rect.width, image_rect.height, this);

   gr.setColor(bordercolor[0]);

   for(int u = 0; u < bordersize; u++)
   {
    gr.draw3DRect(image_rect.x+u, image_rect.y+u, image_rect.width-(2*u)-1, image_rect.height-(2*u)-1, u<bordersize/2);
   }

    gr.setClip(image_rect.x+bordersize, image_rect.y+bordersize, image_rect.width-(2*bordersize)-1, image_rect.height-(2*bordersize)-1);

    readText(g);

    max_y = Y+image_rect.y+bordersize; // update
     
   g.drawImage(upd, 0, 0, getSize().width, getSize().height, this);
  }

  public void readText(Graphics g)
  { 
    // Tämä nopeutta tuntuvasti Netscapea
    for(Enumeration e1 = vec_style.elements(), e2 = vec_font_color.elements(), 
                    e3 = vec_font.elements(), e4 = vec_text.elements(); 
 e1.hasMoreElements() && e2.hasMoreElements()  && e3.hasMoreElements()  && e4.hasMoreElements();)
   {
     String tt       = (String) e1.nextElement(); 
     style[0]        = Integer.parseInt(tt); 
     font_color[0]   = (Color)     e2.nextElement();
     font[0]         = (Font) e3.nextElement();
     text[0]         = (String) e4.nextElement();

     z = (Y+(image_rect.y+bordersize)) * index;

     min_y = z+MaxY();
      
     if(style[0] == 4 || style[0] == 5) setText45(style[0], gr, text[0], font_color[0], font[0], min_y);

     else                         setText(style[0], gr, text[0], font_color[0], font[0], min_y);
     index = 0;
    }

  }

  public int MaxY() { return max_y; } 

  public int MaxX() { return max_x; }

  public int MaxH() { return max_h-max_image_h; }

  //public int MaxW() { return max_w-max_image_w; }

  public void setText(int style, Graphics g, String text, Color fontcolor, Font f, int s)
  {
   t = new StringTokenizer(text, getParameter("enter_text"));
   numlines = t.countTokens();
   lines = new String[numlines]; 
   linewidths = new int[numlines];

   y = s+getFontMetrics(f).getAscent();

   g.setColor(fontcolor);

   for(int i = 0; i < numlines; i++, y += getFontMetrics(f).getAscent())
   {
    lines[i] = t.nextToken();
    g.setFont(f);
    linewidths[i] = getFontMetrics(f).stringWidth(lines[i]);
    if(style == 1) x = image_rect.x + (image_rect.width - linewidths[i])/2; // center
    if(style == 2) x = image_rect.x + bordersize + 20;			    // space+left
    if(style == 3) x = image_rect.x + bordersize + 5;			    // left
    
    g.drawString(lines[i], X+x, y);
    
    max_y = y;
    max_x = x+linewidths[i];
   
    if(ver.H()) max_h = y;

    if(ver.W() && max_x > max_image_w) { boolean_max_w = true; }
              
   }
  
 }

 public void setText45(int style, Graphics g, String text, Color fontcolor, Font f, int s) 
 {
   t = new StringTokenizer(text, getParameter("enter_text")); 
   numlines = t.countTokens();
   lines = new String[numlines]; 
   linewidths = new int[numlines];

   y = s;
   g.setColor(fontcolor);

   for(int i = 0; i < numlines; i++, y += getFontMetrics(f).getAscent())
   {
    lines[i] = t.nextToken();
    g.setFont(f);
    linewidths[i] = getFontMetrics(f).stringWidth(lines[i]);

    if(style == 5) x = image_rect.x + image_rect.width-(2*bordersize)-1-linewidths[i];  // right    
    else           x = MaxX();

    g.drawString(lines[i], X+x, y);
    
    max_y = y;
    max_x = x+linewidths[i];
   
    if(ver.H()) max_h = y;

    if(ver.W() && max_x > max_image_w) { boolean_max_w = true; }
   }

 }

}

   class Bar extends Canvas implements Adjustable, MouseListener, MouseMotionListener  
   {
    int orient;
    int min = 0;
    int max = 100;
    int unitInc = 1;
    int blockInc = 10;
    int visible = 0;
    int value = 0;

    AdjustmentListener adjustmentListener;

    Point locPt = new Point(0, 0);
    Point downPt;
    Image image;
    int ballW, ballH;

    Image bbuf;

    boolean boolean_max_h = true, boolean_max_w = true; 

    Color bgcolor, linecolor; 
    
    Bar(int o, Image image, Color bgcolor, Color linecolor) 
              {
               orient = o;
               this.image     = image;
               this.bgcolor   = bgcolor;
               this.linecolor = linecolor;
         
               setSize(ballW = image.getWidth(this), ballH = image.getHeight(this));

               addMouseListener(this);
               addMouseMotionListener(this);
               
               setBackground(bgcolor);
             }

    public void paint(Graphics g) {
        update(g);
    }

    public boolean H() { return boolean_max_h; }

    public boolean W() { return boolean_max_w; } 

    public void update(Graphics g) {
        int w = getSize().width;
        int h = getSize().height;

         bbuf = createImage(w, h);
       
        Graphics bbufG = bbuf.getGraphics();
        
        bbufG.setColor(bgcolor);
        bbufG.fillRect(0, 0, w, h);

      
        bbufG.setColor(linecolor);
         if (orient == Adjustable.VERTICAL) {
            bbufG.fillRoundRect(w/2-1, ballH/2, 3, h - ballH, 5, 5);
        } else {
            bbufG.fillRoundRect(ballW/2, h/2-1, w - ballW, 3, 5, 5);
        }

        
        bbufG.drawImage(image, locPt.x, locPt.y, this);

       
        g.drawImage(bbuf, 0, 0, this);
        bbufG.dispose();
    }

    public void invalidate() {
        super.invalidate();

        setValues(value, min, max);
    }

   
    public int getOrientation() {
        return orient;
    }

    public int getValue() {
        return value;
    }

    public int getMinimum() {
        return min;
    }

    public int getMaximum() {
        return max;
    }

    public int getVisibleAmount() {
        return 0;
    }

    public int getUnitIncrement() {
        return unitInc;
    }

    public int getBlockIncrement() {
        return blockInc;
    }

    
    void setValues(int va, int mn, int mx) {
        value = va;
        min = mn;
        max = mx;
        if (max <= min) {
            max = min + 1;
        }
        if (value < min) {
            value = min;
        }
        if (value > max) {
            value = max;
        }

        
        if (orient == Adjustable.VERTICAL) {
            locPt.y = (value-min) * (getSize().height-ballH) 
                / (max-min);
        } else {
            locPt.x = (value-min) * (getSize().width-ballW) 
                / (max-min);
        }

        
       //inc(AdjustmentEvent.TRACK, 0);
        repaint();
    }

    public void setValue(int v) { setValues(v, min, max); }

    public void setMinimum(int m) { setValues(value, m, max); }

    public void setMaximum(int m) { setValues(value, min, m); }

    public void setVisibleAmount(int v) {}

    public void setUnitIncrement(int u) { unitInc = u; }

    public void setBlockIncrement(int b) { blockInc = b; }

        
    protected void processEvent(AWTEvent evt) {
        if (evt instanceof AdjustmentEvent) {
            processAdjustmentEvent((AdjustmentEvent)evt);
            return;
        }
        super.processEvent(evt);
    }

   
    protected void processAdjustmentEvent(AdjustmentEvent evt) {
        if (adjustmentListener != null) {
            adjustmentListener.adjustmentValueChanged(evt);
        }
    }

    void inc(int type, int inc) {
        if (inc != 0) {
            setValues(value + inc, min, max);
        }
        if (adjustmentListener != null) {
            processEvent(new AdjustmentEvent(this,
                AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED, type, value));
        }
    }

    public void addAdjustmentListener(AdjustmentListener l) {
        adjustmentListener = AWTEventMulticaster.add(adjustmentListener, l);
    }

    public void removeAdjustmentListener(AdjustmentListener l) {
        adjustmentListener = AWTEventMulticaster.remove(adjustmentListener, l);
    }


     public void mousePressed(MouseEvent evt) {
     boolean_max_h = false; boolean_max_w = false;
 
            switch (onBall(evt)) {
              case -1:
                inc(AdjustmentEvent.BLOCK_DECREMENT, -blockInc);
                break;
              case 0:
                (downPt = evt.getPoint()).translate(-locPt.x, -locPt.y);
                break;
              case 1:
                inc(AdjustmentEvent.BLOCK_INCREMENT, blockInc);
                break;
            } 
            requestFocus();
        }

      public void mouseReleased(MouseEvent evt) {
            downPt = null;
        }

      public void mouseEntered(MouseEvent evt) {
            if (onBall(evt) == 0) {
                setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
            }
        }

     public void mouseExited(MouseEvent evt) {
            setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        }
   
     public void mouseClicked(MouseEvent evt) {}
    
     public void mouseDragged(MouseEvent evt) {
            if (downPt != null) {
                if (orient == Adjustable.VERTICAL) {
                    setValues(evt.getY() * (max-min) 
                        / (getSize().height-ballH) + min, min, max);


                } else {
                    setValues(evt.getX() * (max-min) 
                        / (getSize().width-ballW) + min, min, max);


                }
                inc(AdjustmentEvent.TRACK, 0);
            }
        }
        public void mouseMoved(MouseEvent evt) {
            if (onBall(evt) == 0) {
                setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
            } 
        }


  int onBall(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();

        if (orient == Adjustable.VERTICAL) {
            if (y < locPt.y) {
                return -1;
            } else if (y > locPt.y+ballH) {
                return 1;
            }
        } else {
            if (x < locPt.x) {
                return -1;
            } else if (x > locPt.x+ballW) {
                return 1;
            }
        }
        return 0;
    }

}

class R2Filter extends RGBImageFilter
{
  int width, height;
  float[] hsb = new float[3];
    
  public void setDimensions(int w, int h) 
  {
   super.setDimensions(w, h);
    width = w;
    height = h;
  
  }

   public void filterRGBPixels(int x, int y, int w, int h,
                                int pixels[], int offset, int scansize) 
   {
        int i = offset;

        for (int cy = 0; cy < h; cy++)
        {
         hsb [1] += 0.5f - (float) x / height;

       
         for (int cx = 0; cx < w; cx++)
         {  
          Color c = new Color(pixels[i]);
          Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), hsb);

          hsb [0] += 0.5f - (float) y / width;
          hsb [2] = Math.max(0.0f, Math.min(1.0f, hsb[2]));

          pixels[i] = Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]);                   
	  i++;			
                   
          }
         i += scansize - w;
        }
        consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(),
                           pixels, offset, scansize);
    }
    
    public int filterRGB(int x, int y, int pixel) { return 0; }
}





