001 package com.croftsoft.apps.ads;
002
003 import java.applet.Applet;
004 import java.awt.*;
005 import java.io.*;
006 import java.net.*;
007 import java.util.*;
008
009 /*********************************************************************
010 * Rotating ad banner applet.
011 *
012 * @version
013 * 2001-07-18
014 * @since
015 * 1997
016 * @author
017 * <a href="http://croftsoft.com/">David Wallace Croft</a>
018 *********************************************************************/
019
020 public final class Ads extends Applet implements Runnable
021 //////////////////////////////////////////////////////////////////////
022 //////////////////////////////////////////////////////////////////////
023 {
024
025 private static final String APPLET_TITLE
026 = "Ads \u00A9 2001 David Wallace Croft";
027
028 private static final String APPLET_INFO
029 = "\n" + APPLET_TITLE + "\n"
030 + "croft@alumni.caltech.edu\n"
031 + "http://www.alumni.caltech.edu/~croft/\n"
032 + "Version 2001-07-18\n";
033
034 private static final String PARAM_DATA_FILENAME = "dataFilename";
035
036 /**
037 * Modify to redirect control of what ads are displayed.
038 *
039 * The link is relative to the CodeBase although this may be modified
040 * as well.
041 */
042 private static final String DEFAULT_DATA_FILENAME = "ads.dat";
043
044 /**
045 * How long each image is displayed, in milliseconds.
046 */
047 private static final long AIR_TIME = 15000;
048
049 //
050
051 private static Random random = new Random ( );
052
053 //
054
055 private String dataFilename;
056
057 private Vector imageURL_StringVector;
058
059 private Vector site_URL_StringVector;
060
061 private Hashtable imageUrlStringToImageHashtable;
062
063 private Graphics g;
064
065 private Dimension size;
066
067 private Image offscreenImage;
068
069 private Graphics offscreenGraphics;
070
071 private boolean shouldRun;
072
073 private Thread thread;
074
075 private int index;
076
077 //////////////////////////////////////////////////////////////////////
078 //////////////////////////////////////////////////////////////////////
079
080 public String getAppletInfo ( )
081 //////////////////////////////////////////////////////////////////////
082 {
083 return APPLET_INFO;
084 }
085
086 public synchronized void init ( )
087 //////////////////////////////////////////////////////////////////////
088 {
089 setCursor ( Cursor.getPredefinedCursor ( Cursor.HAND_CURSOR ) );
090
091 imageURL_StringVector = new Vector ( );
092
093 site_URL_StringVector = new Vector ( );
094
095 imageUrlStringToImageHashtable = new Hashtable ( );
096
097 dataFilename = getParameter ( PARAM_DATA_FILENAME );
098
099 if ( dataFilename == null )
100 {
101 dataFilename = DEFAULT_DATA_FILENAME;
102 }
103
104 loadData ( );
105 }
106
107 public synchronized void destroy ( )
108 //////////////////////////////////////////////////////////////////////
109 {
110 if ( g != null )
111 {
112 g.dispose ( );
113 }
114
115 if ( offscreenGraphics != null )
116 {
117 offscreenGraphics.dispose ( );
118 }
119 }
120
121 public synchronized void start ( )
122 //////////////////////////////////////////////////////////////////////
123 {
124 g = getGraphics ( );
125
126 size = size ( );
127
128 offscreenImage = createImage ( size.width, size.height );
129
130 offscreenGraphics = offscreenImage.getGraphics ( );
131
132 shouldRun = true;
133
134 ( thread = new Thread ( this ) ).start ( );
135 }
136
137 public synchronized void stop ( )
138 //////////////////////////////////////////////////////////////////////
139 {
140 shouldRun = false;
141
142 if ( thread != null )
143 {
144 thread.interrupt ( );
145 }
146 }
147
148 public void run ( )
149 //////////////////////////////////////////////////////////////////////
150 {
151 int count = imageURL_StringVector.size ( );
152
153 while ( shouldRun )
154 {
155 int [ ] random_order = random_order_list ( count );
156
157 for ( int i = 0; shouldRun && i < count; i++ )
158 {
159 index = random_order [ i ];
160
161 try
162 {
163 String imageUrlString
164 = ( String ) imageURL_StringVector.elementAt ( index );
165
166 Image image = ( Image )
167 imageUrlStringToImageHashtable.get ( imageUrlString );
168
169 if ( image == null )
170 {
171 image = getImage (
172 new URL ( getCodeBase ( ), imageUrlString ) );
173
174 imageUrlStringToImageHashtable.put ( imageUrlString, image );
175 }
176
177 if ( prepareImage ( image, size.width, size.height, this ) )
178 {
179 offscreenGraphics.drawImage (
180 image, 0, 0, size.width, size.height, this );
181
182 paint ( g );
183 }
184 }
185 catch ( Exception e )
186 {
187 e.printStackTrace ( );
188
189 showStatus ( e.getMessage ( ) );
190 }
191
192 try
193 {
194 thread.sleep ( AIR_TIME );
195 }
196 catch ( InterruptedException e ) { }
197 }
198 }
199 }
200
201 public boolean imageUpdate (
202 Image image, int flags, int x, int y, int w, int h )
203 //////////////////////////////////////////////////////////////////////
204 {
205 if ( flags == 32 )
206 {
207 offscreenGraphics.drawImage (
208 image, 0, 0, size.width, size.height, this );
209
210 paint ( g );
211 }
212
213 return super.imageUpdate ( image, flags, x, y, w, h );
214 }
215
216 public boolean mouseMove ( Event evt, int x, int y )
217 //////////////////////////////////////////////////////////////////////
218 {
219 if ( site_URL_StringVector == null ) return true;
220
221 if ( site_URL_StringVector.size ( ) <= index ) return true;
222
223 showStatus ( ( String ) site_URL_StringVector.elementAt ( index ) );
224
225 return true;
226 }
227
228 public boolean mouseUp ( Event evt, int x, int y )
229 //////////////////////////////////////////////////////////////////////
230 {
231 if ( site_URL_StringVector == null ) return true;
232
233 if ( site_URL_StringVector.size ( ) <= index ) return true;
234
235 try
236 {
237 getAppletContext ( ).showDocument ( new URL (
238 ( String ) site_URL_StringVector.elementAt ( index ) ) );
239
240 }
241 catch ( MalformedURLException e )
242 {
243 e.printStackTrace ( );
244
245 showStatus ( e.getMessage ( ) );
246 }
247
248 return true;
249 }
250
251 public void paint ( Graphics graphics )
252 //////////////////////////////////////////////////////////////////////
253 {
254 if ( offscreenImage == null ) return;
255
256 graphics.drawImage ( offscreenImage, 0, 0, this );
257 }
258
259 public void update ( Graphics graphics )
260 //////////////////////////////////////////////////////////////////////
261 {
262 paint ( graphics );
263 }
264
265 public void repaint ( )
266 //////////////////////////////////////////////////////////////////////
267 {
268 paint ( g );
269 }
270
271 //////////////////////////////////////////////////////////////////////
272 // private methods
273 //////////////////////////////////////////////////////////////////////
274
275 private synchronized boolean loadData ( )
276 //////////////////////////////////////////////////////////////////////
277 {
278 try
279 {
280 URL dataURL = new URL ( getCodeBase ( ), dataFilename );
281
282 InputStream conn = dataURL.openStream ( );
283
284 DataInputStream data = new DataInputStream ( conn );
285
286 while ( true )
287 {
288 String line = data.readLine ( );
289
290 if ( line == null ) break;
291
292 imageURL_StringVector.addElement ( line );
293
294 site_URL_StringVector.addElement ( data.readLine ( ) );
295
296 if ( data.readLine ( ) == null ) break;
297 }
298 }
299 catch ( Exception e )
300 {
301 e.printStackTrace ( );
302
303 showStatus ( e.getMessage ( ) );
304
305 return false;
306 }
307
308 return true;
309 }
310
311 private static int [ ] random_order_list ( int count ) {
312 //////////////////////////////////////////////////////////////////////
313 Vector vector = new Vector ( count );
314 for ( int i = 0; i < count; i++ ) {
315 vector.addElement ( new Integer ( i ) );
316 }
317 int [ ] random_order = new int [ count ];
318 for ( int i = 0; i < count; i++ ) {
319 Integer lucky = ( Integer ) vector.elementAt (
320 ( int ) roll ( 1, count - i, -1 ) );
321 vector.removeElement ( lucky );
322 random_order [ i ] = lucky.intValue ( );
323 }
324 return random_order;
325 }
326
327 private static long roll (
328 long multiplier,
329 long base,
330 long offset )
331 //////////////////////////////////////////////////////////////////////
332 {
333 long temp = 0;
334
335 for ( long index_roll = 0; index_roll < multiplier; index_roll++ )
336 {
337 temp += 1 + Math.round (
338 ( double ) ( base - 1 ) * random.nextDouble ( ) );
339 }
340
341 return temp + offset;
342 }
343
344 //////////////////////////////////////////////////////////////////////
345 //////////////////////////////////////////////////////////////////////
346 }