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         }