001 package com.croftsoft.apps.skipper; 002 003 import java.awt.*; 004 import java.awt.event.*; 005 import java.io.*; 006 import java.util.*; 007 import java.util.logging.*; 008 import javax.imageio.*; 009 import javax.swing.*; 010 011 import com.croftsoft.core.animation.ComponentAnimator; 012 import com.croftsoft.core.awt.image.ImageLib; 013 import com.croftsoft.core.lang.NullArgumentException; 014 import com.croftsoft.core.math.MathConstants; 015 016 /*********************************************************************** 017 * Skipper ComponentAnimator. 018 * 019 * Copyright 2007 David Wallace Croft. 020 * 021 * @version 022 * $Date: 2007/07/28 16:57:03 $ $Author: croft $ 023 * @since 024 * 2006-12-19 025 * @author 026 * <a href="https://www.croftsoft.com/">David Wallace Croft</a> 027 ***********************************************************************/ 028 029 public final class SkipperAnimator 030 implements ComponentAnimator 031 //////////////////////////////////////////////////////////////////////// 032 //////////////////////////////////////////////////////////////////////// 033 { 034 035 private static final String CLASS_NAME 036 = SkipperAnimator.class.getName ( ); 037 038 // 039 040 private final Logger logger; 041 042 private final SkipperConfig skipperConfig; 043 044 private final SkipperModel skipperModel; 045 046 private final Rectangle componentBounds; 047 048 private final Random random; 049 050 // 051 052 private boolean skip; 053 054 private long lastTimeNanos; 055 056 private Image image; 057 058 private String imageFilename; 059 060 private int imageIndex; 061 062 //////////////////////////////////////////////////////////////////////// 063 // constructor methods 064 //////////////////////////////////////////////////////////////////////// 065 066 /*********************************************************************** 067 * Main constructor. 068 ***********************************************************************/ 069 public SkipperAnimator ( 070 final SkipperConfig skipperConfig, 071 final SkipperModel skipperModel, 072 final JComponent jComponent ) 073 //////////////////////////////////////////////////////////////////////// 074 { 075 NullArgumentException.checkArgs ( 076 this.skipperConfig = skipperConfig, 077 this.skipperModel = skipperModel, 078 jComponent ); 079 080 logger = Logger.getLogger ( CLASS_NAME ); 081 082 componentBounds = new Rectangle ( ); 083 084 random = new Random ( ); 085 086 jComponent.setOpaque ( true ); 087 088 jComponent.setFont ( skipperConfig.getFont ( ) ); 089 090 jComponent.addKeyListener ( 091 new KeyAdapter ( ) 092 { 093 @Override 094 public void keyPressed ( final KeyEvent keyEvent ) 095 { 096 final int keyCode = keyEvent.getKeyCode ( ); 097 098 if ( keyCode == KeyEvent.VK_SPACE ) 099 { 100 logger.info ( "Spacebar pressed. Skipping..." ); 101 102 skip = true; 103 } 104 } 105 } ); 106 107 jComponent.requestFocus ( ); 108 109 update ( jComponent ); 110 } 111 112 //////////////////////////////////////////////////////////////////////// 113 // interface ComponentAnimator methods 114 //////////////////////////////////////////////////////////////////////// 115 116 public void paint ( 117 final JComponent jComponent, 118 final Graphics2D graphics2D ) 119 //////////////////////////////////////////////////////////////////////// 120 { 121 try 122 { 123 jComponent.getBounds ( componentBounds ); 124 125 graphics2D.setColor ( skipperConfig.getBackgroundColor ( ) ); 126 127 graphics2D.fill ( componentBounds ); 128 129 if ( image != null ) 130 { 131 final Rectangle rectangle = ImageLib.shrinkToFitAndCenter ( 132 image.getWidth ( null ), 133 image.getHeight ( null ), 134 componentBounds.width, 135 componentBounds.height ); 136 137 graphics2D.drawImage ( 138 image, 139 rectangle.x, 140 rectangle.y, 141 rectangle.width, 142 rectangle.height, 143 null ); 144 } 145 146 if ( imageFilename != null ) 147 { 148 Boolean displayingImageFilename 149 = skipperConfig.getDisplayingImageFilename ( ); 150 151 if ( displayingImageFilename == null ) 152 { 153 displayingImageFilename 154 = skipperConfig.getDefaultDisplayingImageFilename ( ); 155 156 skipperConfig.setDisplayingImageFilename ( 157 displayingImageFilename ); 158 } 159 160 if ( displayingImageFilename.booleanValue ( ) ) 161 { 162 graphics2D.setColor ( skipperConfig.getForegroundColor ( ) ); 163 164 graphics2D.drawString ( imageFilename, 20, 20 ); 165 } 166 } 167 } 168 catch ( final Exception ex ) 169 { 170 ex.printStackTrace ( ); 171 172 logger.throwing ( CLASS_NAME, "paint", ex ); 173 } 174 } 175 176 public void update ( final JComponent jComponent ) 177 //////////////////////////////////////////////////////////////////////// 178 { 179 try 180 { 181 final long currentTimeNanos = System.nanoTime ( ); 182 183 final long deltaTimeNanos = currentTimeNanos - lastTimeNanos; 184 185 long displayTime = skipperConfig.getDisplayTime ( ); 186 187 if ( displayTime <= 0 ) 188 { 189 displayTime = skipperConfig.getDefaultDisplayTime ( ); 190 191 skipperConfig.setDisplayTime ( displayTime ); 192 } 193 194 final long displayTimeNanos 195 = displayTime * MathConstants.NANOSECONDS_PER_SECOND; 196 197 final boolean done = deltaTimeNanos >= displayTimeNanos; 198 199 if ( done || skip ) 200 { 201 if ( skip ) 202 { 203 skip = false; 204 205 skipperModel.decreaseProbabilityOfSkipped ( imageIndex ); 206 207 skipperModel.divideEachProbabilityBySum ( ); 208 } 209 210 imageFilename = randomlyChooseSelection ( ); 211 212 if ( imageFilename != null ) 213 { 214 final File imageFile = new File ( imageFilename ); 215 216 image = ImageIO.read ( imageFile ); 217 218 lastTimeNanos = currentTimeNanos; 219 } 220 } 221 222 jComponent.paintImmediately ( componentBounds ); 223 } 224 catch ( final Exception ex ) 225 { 226 ex.printStackTrace ( ); 227 228 logger.throwing ( CLASS_NAME, "update", ex ); 229 } 230 catch ( final OutOfMemoryError error ) 231 { 232 System.err.println ( "Out of memory loading " + imageFilename ); 233 234 logger.throwing ( CLASS_NAME, "update", error ); 235 } 236 } 237 238 //////////////////////////////////////////////////////////////////////// 239 //////////////////////////////////////////////////////////////////////// 240 241 private String randomlyChooseSelection ( ) 242 //////////////////////////////////////////////////////////////////////// 243 { 244 final String [ ] selections = skipperModel.getSelections ( ); 245 246 if ( ( selections == null ) 247 || ( selections.length < 1 ) ) 248 { 249 return null; 250 } 251 252 final double [ ] thresholds 253 = skipperModel.getCumulativeProbabilityThresholds ( ); 254 255 if ( ( thresholds == null ) 256 || ( thresholds.length < 1 ) ) 257 { 258 return selections [ 0 ]; 259 } 260 261 final double roll = random.nextDouble ( ); 262 263 imageIndex = 0; 264 265 for ( int i = 0; i < thresholds.length; i++ ) 266 { 267 if ( roll < thresholds [ i ] ) 268 { 269 break; 270 } 271 272 imageIndex = i; 273 } 274 275 logger.info ( "index = " + imageIndex + ", roll = " + roll ); 276 277 return selections [ imageIndex ]; 278 } 279 280 //////////////////////////////////////////////////////////////////////// 281 //////////////////////////////////////////////////////////////////////// 282 }