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 }