advertisement
javaboutique
Search Tips
Articles  |   Tutorials  |   Reviews  |   Tools  |   by Category  |   by Date  |   by Name  |   Submit  |   Source  |   Forums  |  
javaboutique
Browse DevX


Partners & Affiliates











advertisement

NewsScroller: NewsScroller.java


package crackers.Scroller;

/**
* An applet that reads "news" from a text file with headlines and URLs and
* presents the information in a vertical scroll. Each message may have,
* independent of the others, a URL (and optional target) to jump to when it is
* clicked upon.
* <P>
* This program is copyrighted 1999 by the author under the GNU Public License
* (GPL). Full text of this license is available at
* <A HREF="http://www.gnu.org">GNU.org</A>.
* <P>
* For full usage information, see
* <A HREF="http://www.io.com/~crackers">my web pages</A>.
*
* @author E. A. Graham, Jr. (crackers@io.com)
* @version 2.0
* @see WebBase
*/

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.*;
import java.io.*;
import java.net.URL;
import java.net.MalformedURLException;

public class NewsScroller extends WebBase implements MouseListener
{
	/**
	* The font to use for headlines.
	*/
	private Font fontHeadline;
	/**
	* The font to use for the message body.
	*/
	private Font fontMessage;
	/**
	* The color used for "clickable" messages.
	*/
	private Color clickColor;
	/**
	* The color used for headlines.
	*/
	private Color headColor;
	/**
	* The current "top" message: used for pausing.
	*/
	private NewsMessage msgTop = null;
	/**
	* The file (actually a URL) to read the news items from.
	*/
	private String fileName = null;
	/**
	* Contains all of the currently loaded news items.
	*/
	private Vector vMessages = new Vector();
	/**
	* Contains all of the newly read news items.
	*/
	private Vector vNewMessages = null;
	/**
	* The gap, in pixels, between messages. This hardcoded value seems
	* adequate.
	*/
	private int gap = 15;
	/**
	* Flag to indicate that scrolling should stop when the mouse is over the
	* applet.
	*/
	private boolean mouse_pause = false;
	/**
	* Flag to indicate that the scrolling should stop (mouse is over the
	* applet).
	*/
	private boolean pause_now = false;
	/**
	* The duration in milliseconds that scrolling should stop when a message
	* reaches the top of the applet.
	*/
	private long top_pause = 0;

	/**
	* Applet initialization.
	*/
	public void init()
	{
		// a lot of the parameters and such are read in the base class, so do
		// that setup first (required)
		super.init();

		String  sp;

		// Retrieve the PARAMs specific for this applet incarnation or set to
		// the defaults.
		fileName = readParam("DATAFILE","news.txt");
		clickColor = readColor("CLICKCOLOR",Color.blue);
		headColor = readColor("HEADCOLOR",Color.red);
		mouse_pause = (readParam("MOUSEPAUSE") != null);
		top_pause = readLong("TOPPAUSE",0);
		int fontSize = readInteger("FONTSIZE",12);
		String fontName = readParam("FONT","Serif");

		// listen myself for the mouse
		addMouseListener(this);

		// Create the fonts, dropping back to the defaults if they can't be
		// created.
		try
		{
			fontMessage = new Font(fontName,Font.PLAIN,fontSize);
		}
		catch (Exception e)
		{
			fontMessage = new Font("Serif",Font.PLAIN,fontSize);
		}
		try
		{
			fontHeadline = new Font(fontName,Font.BOLD,fontSize);
		}
		catch (Exception e)
		{
			fontMessage = new Font("Serif",Font.BOLD,fontSize);
		}
	}

	/**
	* Called when the applet starts. Over-rides the base class, but also calls
	* the base start to initialize the animation. Does the initial load of
	* messages.
	*/
	public void start()
	{
		super.start();
		updateNews();
	}

	/**
	* Draws the messages onto the off-screen image and places the off-screen
	* image onto the on-screen image (double-buffering).
	*/
	public synchronized void update(Graphics g)
	{
		if(!loaded) return;

		// The base class as a couple of things to do, like painting the background
		super.update(g);

		// Loop over the loaded news items and draw them onto the off-screen
		// image. Note that we're being somewhat sloppy and letting the
		// clipping of the image contexts take care of where we run over the
		// size of the image.
		for (Enumeration e = vMessages.elements() ; e.hasMoreElements() ;)
		{
			((NewsMessage)e.nextElement()).draw(appGC,borderWidth,headColor,foreColor,clickColor);
		}

		// Draw the border
		drawBorder();

		// Transfer to the visible image context
		g.drawImage(appImage,0,0,this);
	}

	/**
	* Required method for MouseListener: fired when the mouse button is
	* released. Not used.
	* @see mouseClicked
	*/
	public void mouseReleased(MouseEvent e)
	{
	}
	/**
	* Required method for MouseListener: fired when the mouse leaves the
	* applet. Sets mouse-over paused to false.
	*/
	public void mouseExited(MouseEvent e)
	{
		pause_now = false;
	}
	/**
	* Required method for MouseListener: fired when the mouse button is clicked
	* (up and down). Check the message at the location of the event and, if there's a
	* URL to jump to, do so.
	*/
	public void mouseClicked(MouseEvent event)
	{
		for (Enumeration e = vMessages.elements() ; e.hasMoreElements() ;)
		{
			NewsMessage m = (NewsMessage)e.nextElement();
			URL clicked = m.click(event.getY());
			if (clicked != null)
			{
				getAppletContext().showDocument(clicked,m.getTarget());
				break;
			}
		}
	}
	/**
	* Required method for MouseListener: fired when the mouse enters the
	* applet. If mouse-over pausing is enabled, set the flag to stop the
	* scrolling.
	*/
	public void mouseEntered(MouseEvent e)
	{
		if (mouse_pause) pause_now = true;
	}
	/**
	* Required method for MouseListener: fired when the mouse button is pressed
	* down. Not used.
	* @see mouseClicked
	*/
	public void mousePressed(MouseEvent e)
	{
	}

	/**
	* (Re)read the data file. We're trusting that the data file is not too huge
	* as this could be time consuming otherwise.
	*/
	private synchronized void updateNews()
	{
		// No data? shouldn't happen but it never hurts to make sure.
		if (fileName==null) return;

		// First, assume we're running in a browser, so construct the input
		// stream based on a URL. Note the nested try-catch to grab possible
		// errors along the way.
		InputStream inStream = null;
		try				// <-- catch IO problems
		{
			try			// <-- catch bad URL
			{
				URL theURL = null;
				// A specific URL was specified.
				// Note: applets can only read data in this fashion from the web
				// server that they were served from.
				if (fileName.indexOf("http://") >= 0 )
				{
					theURL = new URL(fileName);
				}
				// Not a specific URL, so assume it's relative to the HTML page the
				// applet is on.
				else
				{
					theURL = new URL(getDocumentBase(),fileName);
				}
				inStream = theURL.openStream();
			}
			// the URL was bad, so try to make it a "local" file
			catch (MalformedURLException eUrl)
			{
				inStream = new FileInputStream(fileName);
			}

			// If we've made it this far, we can probably read the data file.
			BufferedReader reader =
					new BufferedReader(new InputStreamReader(inStream));

			// We expect the data to be in a certain format, with the tags in a
			// specific order. The "mode" flag is used to allow/disallow
			// certain lines from being processed, depending upon what has
			// preceeded the line being read.
			int	mode = 0;
			vNewMessages = new Vector();

			// This variable keeps track of the location of the last message in
			// terms of pixels. Start with all the messages basically off the
			// screen.
			int lastbottom = maxHeight;

			NewsMessage m = null;
			String  line;
			// width to calc line wrapping
			int width = maxWidth - (2 * borderWidth);

			// Read until there ain't no more...
			while( (line=reader.readLine()) != null)
			{
				// Ignore comment lines.
				if (line.startsWith("#")) continue;
				// if the line is empty
				if (line.length() < 4)
				{
					// if not in headline or body modes, skip it
					if (m != null)
					{
						if (mode == 1) m.addHeadLine(line);
						if (mode == 2) m.addMessageLine(line);
					}
					continue;
				}

				// "@END" always ends a message, even if it's never been started.
				if (line.substring(0,4).equalsIgnoreCase("@END")) {
					if (m!=null) {
						if (m.getTarget()==null) m.setTarget(frameTarget);
						lastbottom = m.getBottom() + gap;
						vNewMessages.addElement(m);
					}
					mode = 0;
					continue;
				}

				// What "mode" are we in?
				switch (mode)
				{
					// Looking for a "@HEAD" tag - throw out anything else
					case 0:
						if (line.substring(0,5).equalsIgnoreCase("@HEAD")) {
							// Change to next mode; create a new message
							mode = 1;
							m = new NewsMessage(lastbottom,width,appGC,fontHeadline,fontMessage);
							m.addHeadLine(line.substring(5));
						}
						break;
					// The HEAD has been read: accept "@URL","@FRAME", or "@MSG"
					case 1:
						if (line.substring(0,4).equalsIgnoreCase("@URL"))
						{
							m.setLink(getDocumentBase(),line.substring(4));
							break;
						}
						if (line.substring(0,6).equalsIgnoreCase("@FRAME"))
						{
							m.setTarget(line.substring(6));
							break;
						}
						// Found the start of the message! Time to switch modes
						// again...
						if (line.substring(0,4).equalsIgnoreCase("@MSG")) {
							mode = 2;
							m.addMessageLine(line.substring(4));
						}
						// Don't know what else it could be, so add it to the
						// header.
						else
							m.addHeadLine(line);
						break;
					// Anything else gets added to the message body
					default:
						m.addMessageLine(line);
						break;
				}
			}		// end of line reading-loop
			// Close up shop.
			reader.close();
			inStream.close();
		}
		// Something blew up big time in stream creation or reading. Abort
		// all operations.
		catch (IOException e){
			System.err.println("IO Exception on the data file: " +
								e.getMessage());
			e.printStackTrace();
			stop();
		}
	}

	/**
	* This method, required by the base class, implements the animation/timing
	* of the applet. Basically, it updates each message's location (Y) by the
	* given amount.
	*/
	protected synchronized void doAppThing()
	{
		// the sizes of the current and new message vectors
		int	sizeCurrent = vMessages.size();
		int sizeNew = (vNewMessages == null ? 0 : vNewMessages.size());
		// the position of the last current message, in pixels
		int lastBottom;
		// beginning and end of the current messages
		NewsMessage first,last;

		// There are no current messages (initial load).
		if (sizeCurrent == 0)
		{
			if (sizeNew > 0)
			{
				vMessages = vNewMessages;
				vNewMessages = null;
			}
			else
				return;
		}

		// Check the position of the current first message: if it's moved off
		// of the visible area, put it at the end to acheive the continuous
		// effect.
		first = (NewsMessage)vMessages.firstElement();
		last = (NewsMessage)vMessages.lastElement();
		if (first.getBottom() + scrollUnit <= 0)
		{
			vMessages.removeElement(first);
			lastBottom = last.getBottom() + gap;
			first.resetTop(lastBottom);
			vMessages.addElement(first);
		}

		// Check for the mouse pause condition: if set, don't update the
		// message positions.
		if (pause_now) return;

		// Update all of the message positions.
		for (Enumeration e = vMessages.elements() ; e.hasMoreElements() ;)
		{
			first = (NewsMessage)e.nextElement();
			first.movePosition(scrollUnit);
		}

		// If the "pause at top" feature is enabled (non-zero) and the current
		// first message is at the top of the applet, freeze for the specified
		// time.
		if (top_pause > 0)
		{
			first = (NewsMessage)vMessages.firstElement();
			// If it's at the top and it's not the same message (because we
			// don't want to get stuck in an infinite loop vis-a-vis the
			// mouse-over pause), go to sleep. Note that in this case, we're
			// ignoring any exceptions because it simply doesn't matter all
			// that much.
			if (first.getTop() <= (Math.abs(borderWidth)+1) && !first.equals(msgTop)) {
				try
				{
					Thread.sleep(top_pause);
					msgTop = first;
				}
				catch (InterruptedException e) {}
			}
		}
	}
}


Index

How to Add Java Applets to Your Site

New on the Java Boutique:

New Review:

Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling API boasts simplicity, ease-of-integration, a well-rounded feature set, and it's free!

New Applet:

Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA sequences into three useful formats.

Elsewhere on internet.com:

WebDeveloper Java
Lots of Java information on webdeveloper.com

WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.

ScriptSearch Java
Hundreds of free Java code files to download.

jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.

 Microsoft RIA Development Center
 IBM Rational Resource Center
 Destination .NET
XML error: not well-formed (invalid token) at line 33
advertisement
Receive Articles via our XML/RSS feed
Receive Articles via our XML/RSS feed

JavaBytes
Internet Cyclone
This powerful, easy-to-use, internet optimizer is for Windows 95, 98, ME, NT, 2000 and XP. It's designed to automatically optimize your Windows settings, boosting your Internet connection up to 200%.

Linux Player Xandros Grabs Storied Rival Linspire
Hey Enterprise: Here Comes the 3G iPhone
MySpace Opens Profile Portability API
Microsoft Jumps Into Virtualization Fray
Eclipse Ganymede Makes It Easier for Devs
Open Source Nokia a Threat to Microsoft, Google?
Salesforce, Google Head for 2nd on Apps
HP Open Sources Unix File System for Linux
Red Hat Opens Its Network to Space
Novell: openSUSE for All Linux Users

Beyond XML and JSON: YAML for Java Developers
Mastering the Windows Mobile Emulators
Avaya AE Services Provide Rapid Telephony Integration with Facebook
Featured Algorithm: Intel Threading Building Blocks: parallel_reduce
Getting Started with Windows Live Admin Center
Eight Key Practices for ASP.NET Deployment
Java ME User Interfaces: Do It with LWUIT!
Talking VPro: Transcript
Bringing Semantic Technology to the Enterprise
Persisting Data in Your Windows Mobile Device

Advertising Info  |   Member Services  |   Contact Us  |   Help  |   Feedback  |   Site Map  |   Network Map  |   About



JupiterOnlineMedia

internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info


Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers

Solutions
Whitepapers and eBooks
IBM eBook: Planning a Service Oriented Architecture
IBM eBook: Choosing the Right Architecture--What It Means for You and Your Business
Microsoft Article: Will Hyper-V Make VMware This Decade's Netscape?
Avaya Article: Using Intelligent Presence to Create Smarter Business Applications
Intel Go Parallel Article: Getting Started with TBB on Windows
Microsoft Article: 7.0, Microsoft's Lucky Version?
Avaya Article: How to Feed Data into the Avaya Event Processor
IBM Article: Developing a Software Policy for Your Organization
Microsoft Article: Managing Virtual Machines with Microsoft System Center
Intel Go Parallel Article: Intel Threading Tools and OpenMP
HP eBook: Storage Networking , Part 1
Microsoft Article: Solving Data Center Complexity with Microsoft System Center Configuration Manager 2007
MORE WHITEPAPERS, EBOOKS, AND ARTICLES
Webcasts
HP Video: StorageWorks EVA4400 and Oracle
HP Webcast: Storage Is Changing Fast - Be Ready or Be Left Behind
Microsoft Silverlight Video: Creating Fading Controls with Expression Design and Expression Blend 2
MORE WEBCASTS, PODCASTS, AND VIDEOS
Downloads and eKits
Red Gate Download: SQL Toolbelt and free High-Performance SQL Code eBook
Iron Speed Designer Application Generator
MORE DOWNLOADS, EKITS, AND FREE TRIALS
Tutorials and Demos
Silverlight 2 App and Walkthrough: Leverage Silverlight 2 with SQL Server and XML
IBM Article: Enterprise Search--Do You Know What's Out There?
HP Demo: StorageWorks EVA4400
Microsoft Article: The Progress and Promise of Deep Zoom
Microsoft How-to Article: Get Going with Silverlight and Windows Live
MORE TUTORIALS, DEMOS AND STEP-BY-STEP GUIDES