001 package com.croftsoft.core.animation.component;
002
003 import java.awt.EventQueue;
004 import java.awt.Graphics;
005 import java.awt.Graphics2D;
006 import java.awt.Rectangle;
007 import java.awt.event.ComponentAdapter;
008 import java.awt.event.ComponentEvent;
009 import java.awt.image.VolatileImage;
010 import java.lang.reflect.InvocationTargetException;
011
012 import com.croftsoft.core.animation.AnimatedComponent;
013 import com.croftsoft.core.animation.AnimationFactory;
014 import com.croftsoft.core.animation.ComponentAnimator;
015 import com.croftsoft.core.animation.RepaintCollector;
016 import com.croftsoft.core.animation.factory.DefaultAnimationFactory;
017 import com.croftsoft.core.awt.image.NullVolatileImage;
018 import com.croftsoft.core.util.ArrayLib;
019 import com.croftsoft.core.util.loop.LoopGovernor;
020
021 /*********************************************************************
022 * Triple-buffered animated Swing component.
023 *
024 * @deprecated
025 * Does not seem to work in Java 5.
026 * @version
027 * $Date: 2006/05/27 07:01:43 $
028 * @since
029 * 2002-03-04
030 * @author
031 * <a href="http://www.CroftSoft.com/">David Wallace Croft</a>
032 *********************************************************************/
033
034 public class BufferedAnimatedComponent
035 extends AnimatedComponent
036 //////////////////////////////////////////////////////////////////////
037 //////////////////////////////////////////////////////////////////////
038 {
039
040 private boolean doReset;
041
042 private VolatileImage activeImage;
043
044 private VolatileImage updateImage;
045
046 private Graphics2D activeGraphics;
047
048 private Graphics2D updateGraphics;
049
050 private int oldCount;
051
052 private Rectangle [ ] oldRepaintRegions;
053
054 private Rectangle [ ] newRepaintRegions;
055
056 //////////////////////////////////////////////////////////////////////
057 // constructor methods
058 //////////////////////////////////////////////////////////////////////
059
060 /*********************************************************************
061 * Main constructor.
062 *********************************************************************/
063 public BufferedAnimatedComponent (
064 ComponentAnimator componentAnimator,
065 RepaintCollector repaintCollector,
066 LoopGovernor loopGovernor )
067 //////////////////////////////////////////////////////////////////////
068 {
069 super (
070 componentAnimator,
071 repaintCollector,
072 loopGovernor );
073
074 setDoubleBuffered ( false );
075
076 activeImage = NullVolatileImage.INSTANCE;
077 }
078
079 /*********************************************************************
080 * Convenience constructor.
081 *
082 * @param frequency
083 *
084 * The targeted update frequency in loops per second.
085 *********************************************************************/
086 public BufferedAnimatedComponent (
087 ComponentAnimator componentAnimator,
088 AnimationFactory animationFactory,
089 double frequency )
090 //////////////////////////////////////////////////////////////////////
091 {
092 this (
093 componentAnimator,
094 animationFactory.createRepaintCollector ( ),
095 animationFactory.createLoopGovernor ( frequency ) );
096 }
097
098 /*********************************************************************
099 * Convenience constructor.
100 *********************************************************************/
101 public BufferedAnimatedComponent (
102 ComponentAnimator componentAnimator,
103 AnimationFactory animationFactory )
104 //////////////////////////////////////////////////////////////////////
105 {
106 this (
107 componentAnimator,
108 animationFactory.createRepaintCollector ( ),
109 animationFactory.createLoopGovernor ( ) );
110 }
111
112 /*********************************************************************
113 * Convenience constructor.
114 *
115 * @param frequency
116 *
117 * The targeted update frequency in loops per second.
118 *********************************************************************/
119 public BufferedAnimatedComponent (
120 ComponentAnimator componentAnimator,
121 double frequency )
122 //////////////////////////////////////////////////////////////////////
123 {
124 this (
125 componentAnimator,
126 DefaultAnimationFactory.INSTANCE,
127 frequency );
128 }
129
130 /*********************************************************************
131 * Convenience constructor.
132 *********************************************************************/
133 public BufferedAnimatedComponent (
134 ComponentAnimator componentAnimator )
135 //////////////////////////////////////////////////////////////////////
136 {
137 this (
138 componentAnimator,
139 DefaultAnimationFactory.INSTANCE );
140 }
141
142 //////////////////////////////////////////////////////////////////////
143 // interface Lifecycle methods
144 //////////////////////////////////////////////////////////////////////
145
146 public void init ( )
147 //////////////////////////////////////////////////////////////////////
148 {
149 super.init ( );
150
151 addComponentListener (
152 new ComponentAdapter ( )
153 {
154 public void componentResized ( ComponentEvent componentEvent )
155 {
156 doReset = true;
157 }
158 } );
159
160 oldRepaintRegions = new Rectangle [ ] { };
161
162 newRepaintRegions = new Rectangle [ ] { };
163 }
164
165 //////////////////////////////////////////////////////////////////////
166 // overridden JComponent methods
167 //////////////////////////////////////////////////////////////////////
168
169 public void paintComponent ( Graphics graphics )
170 //////////////////////////////////////////////////////////////////////
171 {
172 graphics.drawImage ( activeImage, 0, 0, null );
173 }
174
175 //////////////////////////////////////////////////////////////////////
176 // protected methods
177 //////////////////////////////////////////////////////////////////////
178
179 protected void loop ( )
180 //////////////////////////////////////////////////////////////////////
181 {
182 doReset = true;
183
184 while ( animationThread != null )
185 {
186 try
187 {
188 animateOffscreen ( );
189
190 if ( doReset )
191 {
192 continue;
193 }
194
195 EventQueue.invokeAndWait ( animationRunner );
196
197 loopGovernor.govern ( );
198
199 if ( stopRequested )
200 {
201 synchronized ( this )
202 {
203 while ( stopRequested )
204 {
205 wait ( );
206 }
207 }
208 }
209 }
210 catch ( InterruptedException ex )
211 {
212 }
213 catch ( InvocationTargetException ex )
214 {
215 ex.getCause ( ).printStackTrace ( );
216 }
217 }
218
219 if ( activeImage != null )
220 {
221 activeImage.flush ( );
222
223 activeImage = null;
224 }
225
226 if ( updateImage != null )
227 {
228 updateImage.flush ( );
229
230 updateImage = null;
231 }
232
233 if ( updateGraphics != null )
234 {
235 updateGraphics.dispose ( );
236
237 updateGraphics = null;
238 }
239
240 if ( activeGraphics != null )
241 {
242 activeGraphics.dispose ( );
243
244 activeGraphics = null;
245 }
246 }
247
248 protected void animateOffscreen ( )
249 //////////////////////////////////////////////////////////////////////
250 {
251 if ( doReset )
252 {
253 if ( activeGraphics != null )
254 {
255 activeGraphics.dispose ( );
256 }
257
258 if ( updateGraphics != null )
259 {
260 updateGraphics.dispose ( );
261 }
262
263 if ( updateImage != null )
264 {
265 updateImage.flush ( );
266 }
267
268 int width = getWidth ( );
269
270 int height = getHeight ( );
271
272 VolatileImage oldActiveImage = activeImage;
273
274 VolatileImage newActiveImage
275 = createVolatileImage ( width, height );
276
277 if ( newActiveImage == null )
278 {
279 return;
280 }
281
282 activeGraphics = newActiveImage.createGraphics ( );
283
284 if ( oldActiveImage != null )
285 {
286 activeGraphics.drawImage ( oldActiveImage, 0, 0, null );
287
288 oldActiveImage.flush ( );
289 }
290
291 activeImage = newActiveImage;
292
293 updateImage = createVolatileImage ( width, height );
294
295 if ( updateImage == null )
296 {
297 return;
298 }
299
300 updateGraphics = updateImage.createGraphics ( );
301
302 activeGraphics.setFont ( getFont ( ) );
303
304 updateGraphics.setFont ( getFont ( ) );
305
306 repaintCollector.repaint ( );
307
308 doReset = false;
309 }
310
311 if ( stopRequested || animationThread == null )
312 {
313 return;
314 }
315
316 componentAnimator.update ( this );
317
318 int count = repaintCollector.getCount ( );
319
320 Rectangle [ ] repaintRegions
321 = repaintCollector.getRepaintRegions ( );
322
323 for ( int i = 0; i < count; i++ )
324 {
325 if ( i == newRepaintRegions.length )
326 {
327 newRepaintRegions = ( Rectangle [ ] ) ArrayLib.append (
328 newRepaintRegions, new Rectangle ( repaintRegions [ i ] ) );
329 }
330 else
331 {
332 newRepaintRegions [ i ].setBounds ( repaintRegions [ i ] );
333 }
334 }
335
336 for ( int i = 0; i < oldCount; i++ )
337 {
338 Rectangle oldRepaintRegion = oldRepaintRegions [ i ];
339
340 repaintCollector.repaint (
341 oldRepaintRegion.x,
342 oldRepaintRegion.y,
343 oldRepaintRegion.width,
344 oldRepaintRegion.height );
345 }
346
347 oldCount = count;
348
349 Rectangle [ ] tempRepaintRegions = oldRepaintRegions;
350
351 oldRepaintRegions = newRepaintRegions;
352
353 newRepaintRegions = tempRepaintRegions;
354
355 count = repaintCollector.getCount ( );
356
357 repaintRegions = repaintCollector.getRepaintRegions ( );
358
359 for ( int i = 0; i < count; i++ )
360 {
361 if ( doReset || stopRequested || animationThread == null )
362 {
363 return;
364 }
365
366 updateGraphics.setClip ( repaintRegions [ i ] );
367
368 componentAnimator.paint ( this, updateGraphics );
369 }
370
371 if ( updateImage.contentsLost ( ) )
372 {
373 doReset = true;
374 }
375 }
376
377 protected void animate ( )
378 //////////////////////////////////////////////////////////////////////
379 {
380 VolatileImage tempImage = activeImage;
381
382 activeImage = updateImage;
383
384 updateImage = tempImage;
385
386 Graphics2D tempGraphics = activeGraphics;
387
388 activeGraphics = updateGraphics;
389
390 updateGraphics = tempGraphics;
391
392 int count = repaintCollector.getCount ( );
393
394 Rectangle [ ] repaintRegions
395 = repaintCollector.getRepaintRegions ( );
396
397 for ( int i = 0; i < count; i++ )
398 {
399 paintImmediately ( repaintRegions [ i ] );
400 }
401
402 repaintCollector.reset ( );
403 }
404
405 //////////////////////////////////////////////////////////////////////
406 //////////////////////////////////////////////////////////////////////
407 }