/*************************************************************************** Copyright (c) 1996 by Wong Ting Sieong Permission to use, copy, and distribute this software for NON-COMMERCIAL and COMMERCIAL purposes and without fee is hereby granted provided that this copyright notice appears in all copies. The FlexScroll class is written to allow implementation either through html document or to be imported(hard-coded) to run in any program. The later option allows a more flexible and feature-rich implementation. ***************************************************************************/ import java.util.*; import java.awt.*; import java.awt.Event; import java.applet.Applet; import java.awt.MediaTracker; class FlexScroll { FS appl; // Application using the class FS String label; // The message // States in each instantiation of FlexScroll permit an instance to start // based on the states of other instances. static final int START = 0; static final int STOP = 1; int state = STOP; // Scrolling types for the message static final int LEFT = 0; // Going left static final int RIGHT = 1; // " right static final int UP = 2; // " up static final int DOWN = 3; // " down static final int DIAGONAL = 4; // " top-left to bottom-right static final int BOUNCE = 5; // Bouncing effect int scrolltype = LEFT; // The selected scrolling type Color fground; // Message foreground colour boolean toChangeColor=false; // Want to change colour? Font font; // Message font FontMetrics fm; // Message font metrics int x, y; // x and y position of the message int dx=1, dy=1; // Distance of x/y to change for every step int startx, starty; // The starting x and y position of the message int stopx, stopy; // The x and y position for the message to stop boolean toResetXY=false; // Want to reset after the message stopped // ---------- Bounce Section ---------- // Bouncing sequence with changing value for y simulating a sinusodial // function int bounceSequence[] = { 2, 4, 5, 7, 9,10,11,13,14,15, 13,11, 9, 7, 4, 3, 2, 1, 0, 1, 2, 4, 5, 6, 7, 9,10,11,12, 9, 8, 7, 6, 5, 4, 3, 2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0 }; int numSequence = 85; // Number of bouncing sequence int sequence = 0; // The current sequence boolean toBounce = false; // Want to bounce? boolean doneBounce = true; // Flag to signal end of bounce sequence // Constructor public FlexScroll(FS appl, String label, int scrolltype, Font font) { this.appl = appl; this.label = label; this.scrolltype = scrolltype; this.font = font; fm = appl.getFontMetrics(font); SetDefaultStartPoint(scrolltype); SetDefaultStopPoint(scrolltype); } // Setting default starting point of a particular scrolling type void SetDefaultStartPoint(int scrolltype) { switch(scrolltype) { case LEFT: SetStartPoint(appl.size().width+fm.stringWidth(label), appl.size().height/2); break; case RIGHT: SetStartPoint(-fm.stringWidth(label),appl.size().height/2); break; case UP: SetStartPoint(appl.size().width/2, appl.size().height+fm.getHeight()); break; case DOWN: SetStartPoint(appl.size().width/2,0); break; case DIAGONAL: SetStartPoint(0,0); break; } } // Setting the starting point for the message void SetStartPoint(int startx, int starty) { x = this.startx = startx; y = this.starty = starty; } // Setting the default stopping point for a particular scrolling type void SetDefaultStopPoint(int scrolltype) { switch(scrolltype) { case LEFT: SetStopPoint(-fm.stringWidth(label), appl.size().height/2); break; case RIGHT: SetStopPoint(appl.size().width+fm.stringWidth(label), appl.size().height/2); break; case UP: SetStopPoint(appl.size().width/2,-fm.getHeight()); break; case DOWN: SetStopPoint(appl.size().width/2, appl.size().height); break; case DIAGONAL: SetStopPoint(appl.size().width,appl.size().height); break; } } // Setting the message starting point on the x axis void SetStartX(int startx) { x = this.startx = startx; } // Setting the message starting point on the y axis void SetStartY(int starty) { y = this.starty = starty; } // Setting the message stopping value for a particular scroll type void SetStopPoint(int stopx, int stopy) { switch (this.scrolltype) { case LEFT: this.stopx = stopx; break; case RIGHT: this.stopx = stopx; case UP: this.stopy = stopy; break; case DOWN: this.stopy = stopy; break; case DIAGONAL: this.stopx = stopx; this.stopy = stopy; break; } } // Setting the message stopping value on the y axis void SetStopX(int stopx) { this.stopx = stopx; } // Setting the message stopping value on the y axis void SetStopY(int stopy) { this.stopy = stopy; } // Setting the change on the x-axis for every repaint void SetDX(int dx) { this.dx = dx; } // Setting the change on the y-axis for every repaint void SetDY(int dy) { this.dy = dy; } // Setting the message to start scrolling void Start() { state = START; } // Setting the message to stop scrolling void Stop() { state = STOP; } // Procedure to set font for the message void SetFont(String typeface, int style, int ptsize) { font = new Font(typeface, style, ptsize); } // Overloading the above procedure void SetFont(String typeface, int ptsize) { font = new Font(typeface, Font.PLAIN, ptsize); } // Setting the foreground colour for the message void SetColor(int fred, int fgreen, int fblue) { fground = new Color(fred,fgreen,fblue); toChangeColor = true; } // Flagging to signal the resetting of the scrolling void SetResetOn() { toResetXY = true; } // Resetting the message starting position after reaching its stopping position void ResetXY() { if(toResetXY) { SetStartPoint(startx,starty); } } // Changing the x and y position to display a message for a particular // scroll type void MoveText() { switch(scrolltype) { case LEFT: x -= dx; break; case RIGHT: x += dx; break; case UP: y -= dy; break; case DOWN: y += dy; break; case DIAGONAL: x += dx; y += dy; break; } } // Flagging to signal the bouncing of a going DOWN message when it hits // the stopping point void SetBounce() { toBounce = true; doneBounce = false; SetResetOn(); } // Changing the y position of the message through the bouncing sequence // to stimulate a bouncing effect int BounceText(int pos) { if(sequence= stopx) stop = true; break; case UP: if(y <= stopy) stop = true; break; case DOWN: if(y >= stopy) stop = true; break; case DIAGONAL: if((x>=stopx) && (y>=stopy)) stop = true; break; } return stop; } // Paint the message public void paint(Graphics g) { if(toChangeColor) { g.setColor(fground); } g.setFont(font); if (state == START) { if(!isStopPoint()) { MoveText(); g.drawString(label,x,y); } else { if(!doneBounce) { g.drawString(label,x,BounceText(y)); } else { if(toBounce) { doneBounce=false; } ResetXY(); g.drawString(label,x,y); } } } } } /*-------------------------------------------------------------------*/ public class FS extends Applet implements Runnable { // Objects for updating graphics off-screen private Image osImage; private Graphics osGraphics; private Dimension osSize; Font font; // Default font int ptsize=25; // Default font point size int fred=0, fblue=0, fgreen=0; // Default foreground colour int bred=255, bblue=255, bgreen=255; // Default background colour int delay =10; // Default delay time between each repaint Thread scroll =null; boolean suspended =false; Vector Flex = null; // Vector to store pointers to multiple FlexScroll instances static final int MaxFlexScroll = 20; // Maximum vector size int numFlex; // Number of FlexScroll instances FlexScroll tmp; // A temporary FlexScroll MediaTracker tracker; // MediaTracker to maintain a proper sequence in loading of images Image bgimage; // An optional background image public void init() { initParameters(); font = new Font("TimesRoman",Font.PLAIN,ptsize); // setting the default font } // Getting parameters from the html document calling this applet. // Simplicity is of utmost importance in this section to guarantee future // extensibility. void initParameters() { String s, parname; String label; int scrolltype; String typeface; int style; int ptsize; int fred, fgreen, fblue; int startx, starty; int stopx, stopy; int dx, dy; tracker = new MediaTracker(this); s = getParameter("bgimage"); if(s!=null) { bgimage = getImage(getDocumentBase(),s); tracker.addImage(bgimage,0); } s = getParameter("delay"); delay = (s == null) ? 100 : (Integer.valueOf(s).intValue()); numFlex = 0; Flex = new Vector(MaxFlexScroll); for (int i=1; i<=MaxFlexScroll; i++) { parname = "label" + i; s = getParameter(parname); label = (s==null) ? "FlexText" : s; if(s==null) break; parname = "scrolltype" + i; s = getParameter(parname); if (s == null) scrolltype = FlexScroll.LEFT; else if (s.equalsIgnoreCase("LEFT")) scrolltype = FlexScroll.LEFT; else if (s.equalsIgnoreCase("RIGHT")) scrolltype = FlexScroll.RIGHT; else if (s.equalsIgnoreCase("UP")) scrolltype = FlexScroll.UP; else if (s.equalsIgnoreCase("DOWN")) scrolltype = FlexScroll.DOWN; else if (s.equalsIgnoreCase("DIAGONAL")) scrolltype = FlexScroll.DIAGONAL; else scrolltype = FlexScroll.LEFT; parname = "typeface" + i; s = getParameter(parname); if (s == null) typeface = "TimesRoman"; else if (s.equalsIgnoreCase("TimesRoman")) typeface = "TimesRoman"; else if (s.equalsIgnoreCase("Courier")) typeface = "Courier"; else if (s.equalsIgnoreCase("Helvetica")) typeface = "Helvetica"; else if (s.equalsIgnoreCase("Dialog")) typeface = "Dialog"; else typeface = "TimesRoman"; parname = "style" + i; s = getParameter(parname); if (s == null) style = Font.PLAIN; else if (s.equalsIgnoreCase("PLAIN")) style = Font.PLAIN; else if (s.equalsIgnoreCase("BOLD")) style = Font.BOLD; else if (s.equalsIgnoreCase("ITALIC")) style = Font.ITALIC; else style = Font.PLAIN; parname = "ptsize" + i; s = getParameter(parname); ptsize = (s == null) ? 25 : (Integer.valueOf(s).intValue()); parname = "fred" + i; s = getParameter(parname); fred = (s == null) ? 255 : (Integer.valueOf(s).intValue()); parname = "fgreen" + i; s = getParameter(parname); fgreen = (s == null) ? 0 : (Integer.valueOf(s).intValue()); parname = "fblue" + i; s = getParameter(parname); fblue = (s == null) ? 0 : (Integer.valueOf(s).intValue()); Flex.addElement(new FlexScroll(this, label,scrolltype, new Font(typeface,style,ptsize))); tmp = (FlexScroll)(Flex.elementAt(numFlex)); tmp.Start(); tmp.SetColor(fred,fgreen,fblue); parname = "bounce" + i; s = getParameter(parname); if (s!=null) { tmp.SetBounce(); } parname = "reset" + i; s = getParameter(parname); if (s!=null) { tmp.SetResetOn(); } parname = "startx" + i; s = getParameter(parname); if (s != null) { startx = Integer.valueOf(s).intValue(); tmp.SetStartX(startx); } parname = "starty" + i; s = getParameter(parname); if (s != null) { starty = Integer.valueOf(s).intValue(); tmp.SetStartY(starty); } parname = "stopx" + i; s = getParameter(parname); if (s != null) { stopx = Integer.valueOf(s).intValue(); tmp.SetStopX(stopx); } parname = "stopy" + i; s = getParameter(parname); if (s != null) { stopy = Integer.valueOf(s).intValue(); tmp.SetStopY(stopy); } parname = "dx" + i; s = getParameter(parname); if (s != null) { dx = Integer.valueOf(s).intValue(); tmp.SetDX(dx); } parname = "dy" + i; s = getParameter(parname); if (s != null) { dy = Integer.valueOf(s).intValue(); tmp.SetDY(dy); } numFlex++; } // The default message if none is included in the html document. if(numFlex==0) { Flex.addElement(new FlexScroll(this,"Thank you for using FlexScroll", FlexScroll.DOWN,new Font("Arial",Font.BOLD,30))); tmp = (FlexScroll)(Flex.elementAt(numFlex)); tmp.Start(); tmp.SetColor(0,0,255); tmp.SetBounce(); tmp.SetStartX(0); numFlex++; } } public void paint(Graphics g) { g.setColor(new Color(bred,bgreen,bblue)); g.fillRect(0,0,size().width,size().height); g.setFont(font); if(bgimage!=null) { g.drawImage(bgimage,0,0,this); } if(tracker.checkID(0)) { for(int i=0; i