// Name : Java Stock Ticker // Author : Terrence Ma // Email : terrence@terrence.com // Web : http://www.terrence.com // Date : 02/06/2001 // Modified : http://www.3quarks.com/Applets/TickerLine/ /* * TickerLine * * Copyright (c) 1999, 2000 by Rüdiger Appel, All Rights Reserved. * * Permission to use, copy, modify, and distribute this software * and its documentation for NON-COMMERCIAL purposes and without * fee is hereby granted provided that this copyright notice * appears in all copies. * * http://www.3quarks.com * */ import java.applet.*; import java.awt.*; import java.awt.image.*; import java.net.*; import java.io.*; import java.util.*; public class TickerLine extends Applet implements Runnable { private Thread timer = null; private Thread loader = null; private boolean allLoaded = false; private boolean running = true; private Image buffer = null; private Image background = null; private Rectangle tickerRect = null; private Vector textLines = new Vector (); private int textIndex; private int lineIndex; private int repetition = 0; private int charWidth; private int charHeight; private int[] fontPixels = null; private int[] backPixels = null; private int[] linePixels = null; private Image lineBuffer = null; private int queueLength; private int queueIndex; private int[] queueColor = null; private char[] queueChar = null; private int charDelay = 200; private int lineDelay = 1000; private boolean playSound = true; private AudioClip charSound = null; private AudioClip spaceSound = null; private AudioClip returnSound = null; private int currentColor; private char currentSign; public TickerLine () { // write applet info System.out.println (getAppletInfo ()); } public String getAppletInfo () { // return my copyright notice return "TickerLine, Version 1.0" + System.getProperty ("line.separator") + "Copyright (c) 1999, 2000 by Rüdiger Appel, All Rights Reserved" + System.getProperty ("line.separator") + "http://www.3quarks.com"; } public void init () { // get audio settings String setSound = getParameter ("EnableSound"); if ((setSound != null) && setSound.trim ().equalsIgnoreCase ("yes")) playSound = true; else if ((setSound != null) && setSound.trim ().equalsIgnoreCase ("no")) playSound = false; else playSound = !(System.getProperty ("os.name").equalsIgnoreCase ("Windows 95") || System.getProperty ("os.name").equalsIgnoreCase ("Windows 98")); // set background color try { StringTokenizer tokenizer = new StringTokenizer (getParameter ("BackgroundColor"), ","); if (tokenizer.countTokens () == 1) { String value = tokenizer.nextToken ().trim (); setBackground (new Color (Integer.parseInt (value.substring (1, 3), 16), Integer.parseInt (value.substring (3, 5), 16), Integer.parseInt (value.substring (5, 7), 16))); } else setBackground (new Color (Integer.parseInt (tokenizer.nextToken ().trim ()), Integer.parseInt (tokenizer.nextToken ().trim ()), Integer.parseInt (tokenizer.nextToken ().trim ()))); } catch (Exception exception) {} } public void update (Graphics graphics) { paint (graphics); } public void paint (Graphics graphics) { // get applet size int width = size ().width; int height = size ().height; // create buffer if not exist if (buffer == null) buffer = createImage (width, height); // get buffer graphics Graphics bufferGraphics = buffer.getGraphics (); // fill background bufferGraphics.setColor (getBackground ()); bufferGraphics.fillRect (0, 0, width, height); // draw background if (background != null) bufferGraphics.drawImage (background, (width - background.getWidth (this)) / 2, (height - background.getHeight (this)) / 2, this); // draw ticker line if (lineBuffer != null) bufferGraphics.drawImage (lineBuffer, tickerRect.x, tickerRect.y, tickerRect.width, tickerRect.height, this); // paint buffer graphics.drawImage (buffer, 0, 0, this); } private void drawLine () { // draw line characters for (int index = 0; index < queueLength; index++) drawChar (index); // create new buffer image Image image = createImage (new MemoryImageSource (tickerRect.width, tickerRect.height, linePixels, 0, tickerRect.width)); lineBuffer = image; } private void drawChar (int index) { int alpha; int red; int green; int blue; // get character index and color int charIndex = queueChar[index] - 32; int charColor = queueColor[index]; // set line and buffer index int i = index * charWidth; // set font index int j = (charIndex / 32) * charHeight * charWidth * 32 + (charIndex % 32) * charWidth; // set all character pixels for (int y = 0; y < charHeight; y++) { for (int x = 0; x < charWidth; x++) { // get alpha value alpha = fontPixels[j] & 0x000000ff; // set line pixel if (alpha == 0) linePixels[i] = backPixels[i]; else { // compute new color values red = (((backPixels[i] >> 16) & 0xff) * alpha + ((charColor >> 16) & 0xff) * (255 - alpha)) >> 8; green = (((backPixels[i] >> 8) & 0xff) * alpha + ((charColor >> 8) & 0xff) * (255 - alpha)) >> 8; blue = ((backPixels[i] & 0xff) * alpha + (charColor & 0xff) * (255 - alpha)) >> 8; linePixels[i] = 0xff000000 | (red & 0xff) << 16 | (green & 0xff) << 8 | (blue & 0xff); } // pixel increments i++; j++; } // line increments i += charWidth * (queueLength - 1); j += charWidth * 31; } } public void enableSound (boolean enable) { // set sound flag playSound = enable; } public boolean isSoundEnabled () { // return sound flag return playSound; } public void start () { if (allLoaded) { // initialize ticker tickerInit (); // start timer timer = new Thread (this); timer.start (); } else { // start loader loader = new Thread (this); loader.start (); } } public void stop () { // stop loader if (loader != null) { loader.stop (); loader = null; } // stop timer if (timer != null) { timer.stop (); timer = null; } } public void run () { // loader thread if (Thread.currentThread () == loader) { // create media tracker MediaTracker tracker = new MediaTracker (this); // load background image background = loadImage (tracker, "BackgroundImage", 0); if (background != null) repaint (); // load font image Image fontImage = loadImage (tracker, "TickerFont", 1); // get ticker rectangle try { StringTokenizer tokenizer = new StringTokenizer (getParameter ("TickerRect"), ","); tickerRect = new Rectangle (Integer.parseInt (tokenizer.nextToken ().trim ()), Integer.parseInt (tokenizer.nextToken ().trim ()), Integer.parseInt (tokenizer.nextToken ().trim ()), Integer.parseInt (tokenizer.nextToken ().trim ())); } catch (Exception exception) { tickerRect = new Rectangle (size ()); } // prepare font if (fontImage != null) { // get font size int fontWidth = fontImage.getWidth (this); int fontHeight = fontImage.getHeight (this); // get character size charWidth = fontWidth / 32; charHeight = fontHeight / 3; // recalculate ticker rectangle int width = charWidth * (tickerRect.width / charWidth); tickerRect.y += (tickerRect.height - charHeight) / 2; tickerRect.height = charHeight; tickerRect.x += (tickerRect.width - width) / 2; tickerRect.width = width; // create array for font pixels fontPixels = new int [fontWidth * fontHeight]; // grab font pixels PixelGrabber grabber = new PixelGrabber (fontImage, 0, 0, fontWidth, fontHeight, fontPixels, 0, fontWidth); try { grabber.grabPixels (); } catch (Exception exception) {} // check grabber status if ((grabber.status () & ImageObserver.ABORT) != 0) fontPixels = null; } // create array for background pixels backPixels = new int [tickerRect.width * tickerRect.height]; // fill background pixels if (background == null) { int size = tickerRect.width * tickerRect.height; int value = getBackground ().getRGB (); for (int i = 0; i < size; i++) backPixels[i] = value; } else { // grab background pixels PixelGrabber grabber = new PixelGrabber (background, tickerRect.x, tickerRect.y, tickerRect.width, tickerRect.height, backPixels, 0, tickerRect.width); try { grabber.grabPixels (); } catch (Exception exception) {} // check grabber status if ((grabber.status () & ImageObserver.ABORT) != 0) backPixels = null; } // create line buffer lineBuffer = createImage (tickerRect.width, tickerRect.height); linePixels = new int [tickerRect.width * tickerRect.height]; // create ticker queue queueLength = tickerRect.width / charWidth; queueChar = new char [queueLength]; queueColor = new int [queueLength]; // load ticker text loadText (); // get text repeat value try { repetition = Integer.parseInt (getParameter ("Repetition").trim ()); } catch (Exception exception) {} // get char and line delay try { StringTokenizer tokenizer = new StringTokenizer (getParameter ("TickerDelay"), ","); charDelay = Integer.parseInt (tokenizer.nextToken ().trim ()); lineDelay = Integer.parseInt (tokenizer.nextToken ().trim ()); } catch (Exception exception) {} // load audio clips charSound = loadAudioClip ("CharSound"); spaceSound = loadAudioClip ("SpaceSound"); returnSound = loadAudioClip ("ReturnSound"); // check all needed objects if ((fontPixels != null) && (backPixels != null) && (linePixels != null) && (lineBuffer != null) && (queueChar != null) && (queueColor != null) && !textLines.isEmpty ()) { // initialize ticker tickerInit (); // set loaded flag allLoaded = true; // start timer timer = new Thread (this); timer.start (); } } // timer thread if (Thread.currentThread () == timer) { while (running) { // next ticker step tickerStep (); // handle end of line if (currentSign == 0) { // play line sound if (playSound && (returnSound != null)) returnSound.play (); // wait a moment try { timer.sleep (lineDelay); } catch (InterruptedException exception) {} } // draw new line drawLine (); // repaint applet repaint (); // play sound if (playSound && (currentSign != 0)) { if ((currentSign == ' ') && (spaceSound != null)) spaceSound.play (); else if (charSound != null) charSound.play (); } // wait a moment try { timer.sleep (charDelay); } catch (InterruptedException exception) {} } } } private Image loadImage (MediaTracker tracker, String name, int identifier) { try { // load an image Image image = getImage (getCodeBase (), getParameter (name).trim ()); tracker.addImage (image, identifier); tracker.waitForID (identifier); if (!tracker.isErrorID (identifier)) return image; } catch (Exception exception) {} return null; } private AudioClip loadAudioClip (String name) { // get the audio clip try { return getAudioClip (getCodeBase (), getParameter (name)); } catch (Exception exception) {} return null; } private void loadText () { // get ticker text from parameter String line = getParameter ("TickerText"); if (line != null) { addTextLine (line); return; } // get ticker url String url = getParameter ("TickerUrl"); if (url == null) { addTextLine ("TickerLine, Version 1.0"); addTextLine ("Copyright (c) 1999 by Rüdiger Appel, All Rights Reserved"); addTextLine ("See also: http://www.3quarks.com"); return; } // get ticker text from url try { URL textURL = new URL (getCodeBase (), url); DataInputStream textInput = new DataInputStream (textURL.openStream ()); while ((line = textInput.readLine ()) != null) addTextLine (line); textInput.close (); } catch (Exception exception) {} } private void addTextLine (String line) { // verify ticker text and expand umlaute StringBuffer buffer = new StringBuffer (); for (int index = 0; index < line.length (); index++) { char sign = line.charAt (index); if ((sign >= 32) && (sign <= 128)) buffer.append (sign); else { if (sign == 'ä') buffer.append ("ae"); else if (sign == 'ö') buffer.append ("oe"); else if (sign == 'ü') buffer.append ("ue"); else if (sign == 'Ä') buffer.append ("Ae"); else if (sign == 'Ö') buffer.append ("Oe"); else if (sign == 'Ü') buffer.append ("Ue"); else if (sign == 'ß') buffer.append ("ss"); } } // add text line textLines.addElement (buffer.toString ()); } private void tickerInit () { // fill queue with spaces for (int i = 0; i < queueLength; i++) queueChar[i] = ' '; // reset variables queueIndex = 0; textIndex = 0; lineIndex = 0; currentColor = 0xff000000; } private void tickerStep () { // get next sign currentSign = getNextSign (); // handle new line if (currentSign == 0) { // clear queue for (int i = 0; i < queueLength; i++) queueChar[i] = ' '; // reset queue index queueIndex = 0; return; } // update queue if (queueIndex < queueLength) { queueChar [queueIndex] = currentSign; queueColor[queueIndex] = currentColor; queueIndex++; } else { // shift queue for (int i = 0; i < (queueLength - 1); i++) { queueChar [i] = queueChar [i + 1]; queueColor[i] = queueColor[i + 1]; } queueChar [queueLength - 1] = currentSign; queueColor[queueLength - 1] = currentColor; } } private char getNextSign () { // get current line String line = (String) textLines.elementAt (lineIndex); // check end of line if (textIndex >= line.length ()) { // check for max repeat if (lineIndex == (textLines.size () - 1)) if (repetition == 1) running = false; else repetition--; textIndex = 0; lineIndex = (lineIndex + 1) % textLines.size (); return 0; } // get current sign char sign = line.charAt (textIndex++); if (sign == '#') { // check end of line if (textIndex >= line.length ()) return getNextSign (); // get next sign sign = line.charAt (textIndex++); // check for color value if (sign != '#') { try { // parse color value String value = line.substring (textIndex - 1, textIndex + 5); if (value.equalsIgnoreCase ("random")) currentColor = 0xff000000 | new Random ().nextInt (); else currentColor = new Color (Integer.parseInt (value.substring (0, 2), 16), Integer.parseInt (value.substring (2, 4), 16), Integer.parseInt (value.substring (4, 6), 16)).getRGB (); } catch (Exception exception) {} // increment text index textIndex += 5; return getNextSign (); } } return sign; } }