/* * ScrollText.java - Scrolling text widget (super charged version) * * This class presents a text message that scrolls through rectangular area * from right to left. Double buffering is used to smooth the animation. * * @author Philip Meese * @version 1.1, 3/18/96 Java Tutor, Second Column * * v1.101 Adds double buffering, text centering, drop shadow */ import java.awt.*; public class ScrollText extends Canvas implements Runnable{ private Thread _thread; private String _message; private int _speed=50; // medium speed default private Font _font; private int _msgWidth; private Rectangle _rect; private int _msgX, _msgY; private Image _ibuffer=null; // image buffer /** * Constructor which sets message, width and height of display area * * @arg message_ The message to be displayed * @arg width_ The initial width of the display area * @arg height_ The initial height of the display area */ public ScrollText(String message_, int width_, int height_){ _message=message_; _font=new Font("TimesRoman", Font.BOLD, 56); _rect=new Rectangle(0, 0, width_, height_); reshape(0, 0, width_, height_); _msgX=width_; // offscreen, right _thread=new Thread(this); } /** * Sets the scrolling speed * * @arg speed_ A value between 0 and 100 (slowest to fastest) */ public void speed(int speed_){ if(speed_ > 0 && speed_ < 100) _speed=speed_; } /** * Creates the Image block of a text message. * Once this image is created, it is moved about within the text * display area, giving it the appearance of "scrolling" like a * stock ticker. */ private void createTextImage(){ Toolkit tk=Toolkit.getDefaultToolkit(); FontMetrics fontMetrics=tk.getFontMetrics(_font); _msgWidth=fontMetrics.stringWidth(_message) + 4; _ibuffer=createImage(_msgWidth, _rect.height); Graphics ibg = _ibuffer.getGraphics(); ibg.setFont(_font); _msgY=(int)((double)_rect.height/2.0 + (double)fontMetrics.getAscent()/2.0 - fontMetrics.getDescent()); ibg.setColor(Color.blue); ibg.fillRect(0, 0, _msgWidth, _rect.height); paintMessage(ibg, Color.yellow, 1, _msgY); } /** * Your standard update function: called by the AWT in response * to a repaint() request or when the image area has been "damaged". * * @arg g_ The Graphics object to draw on */ public void update(Graphics g_){ Rectangle rect=bounds(); if(_ibuffer == null || !rect.equals(_rect)){ // startup and resize _rect=rect; createTextImage(); } paintBackground(g_, Color.blue); g_.drawImage(_ibuffer, _msgX, 0, this); } /** * Painter's helper: paints the message and it's drop shadow (!) * * @arg g_ The Graphics object to draw on * @arg c_ The color to render the font in * @arg x_ The X origin for font rendering * @arg y_ The Y origin for font rendering */ private void paintMessage(Graphics g_, Color c_, int x_, int y_){ g_.setColor(Color.black); g_.drawString(_message, x_+2, y_+2); // drop shadow g_.setColor(c_); g_.drawString(_message, x_, y_); } /** * Another painter's helper * Fills background area not occupied by text image. Given that the text * image is shorter than the scrolling message area, there is potentially * a leading area AND a trailing area. Both need to be filled with the * background color. * * @arg g_ The Graphics object to draw on * @arg c_ The Color to draw with */ private void paintBackground(Graphics g_, Color c_){ int tail; g_.setColor(c_); if(_msgX > 0) g_.fillRect(0, 0, _msgX, _rect.height); if((tail=_msgX + _msgWidth) < _rect.width) g_.fillRect(tail, 0, _rect.width - tail, _rect.height); } /** * The thread runner: called in response to _thread.start() */ public void run(){ while(true){ // forever (or a very long time) try{ _thread.sleep(100 - _speed); // pause that refreshes _msgX -= 1; // move left if(_msgX <= -1 * _msgWidth) // message wrap _msgX = _rect.width; repaint(); } catch(InterruptedException e) { break; } } } public void start(){ _thread.start(); } public void suspend(){ _thread.suspend(); } public void resume(){ _thread.resume(); } public void stop(){ _thread.stop(); } } // end class ScrollText