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="https://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 }