/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package blackberry.web.widget.loadingScreen;
import net.rim.device.api.system.GIFEncodedImage;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
/**
* A field that displays an animated GIF
*/
public class AnimatedGIFField extends BitmapField {
private GIFEncodedImage _image; // The image to draw.
private int _currentFrame; // The current frame in the animation sequence.
// private int _width; // The width of the image (background frame).
// private int _height; // The height of the image (background frame).
private AnimatorThread _animatorThread;
/**
* Create a new animated GIF field. The animation <b>will not start</b>
* until startAnimation() is called.
*
* @param image The image to be displayed
*/
public AnimatedGIFField( GIFEncodedImage image ) {
this( image, 0 );
}
/**
* Create a new animated GIF field. The animation <b>will not start</b>
* until startAnimation() is called.
*
* @param image The image to be displayed
* @param style Style flag(s) for the field
*/
public AnimatedGIFField( GIFEncodedImage image, long style ) {
// Call super to setup the field with the specified style.
// The image is passed in as well for the field to
// configure its required size.
super( image.getBitmap(), style );
// Store the image and it's dimensions.
_image = image;
// _width = image.getWidth();
// _height = image.getHeight();
}
/**
* Start the animation.
*/
public synchronized void startAnimation() {
if (_animatorThread != null) {
return; // Thread already created
}
_animatorThread = new AnimatorThread( this );
_animatorThread.start();
}
protected void paint( Graphics graphics ) {
// Call super.paint. This will draw the first background
// frame and handle any required focus drawing.
super.paint( graphics );
// Don't redraw the background if this is the first frame.
if( _currentFrame != 0 ) {
// Draw the animation frame.
graphics.drawImage( _image.getFrameLeft( _currentFrame ), _image.getFrameTop( _currentFrame ), _image
.getFrameWidth( _currentFrame ), _image.getFrameHeight( _currentFrame ), _image, _currentFrame, 0, 0 );
}
}
// Stop the animation thread when the screen the field is on is
// popped off of the display stack.
protected synchronized void onUndisplay() {
_animatorThread.stopAnimation();
super.onUndisplay();
}
protected synchronized void onDisplay() {
_animatorThread.startAnimation();
super.onUndisplay();
}
// A thread to handle the animation.
private class AnimatorThread extends Thread {
private AnimatedGIFField _theField;
private boolean _keepGoing = false;
// The total number of frames in the image
private int _totalFrames;
// The number of times the animation has looped( completed)
private int _loopCount;
// The number of times the animation should loop (set in the image)
private int _totalLoops;
public AnimatorThread( AnimatedGIFField theField ) {
_theField = theField;
_totalFrames = _image.getFrameCount();
_totalLoops = _image.getIterations();
}
public void stopAnimation() {
_keepGoing = false;
}
public void startAnimation() {
_keepGoing = true;
}
public void run() {
while( true ) {
while( _keepGoing ) {
// Invalidate the field so that it is redrawn.
UiApplication.getUiApplication().invokeAndWait( new Runnable() {
public void run() {
_theField.invalidate();
}
} );
try {
// Sleep for the current frame delay before
// the next frame is drawn.
sleep( _image.getFrameDelay( _currentFrame ) * 10 );
} catch( InterruptedException ignore ) {
} // Couldn't sleep.
// Increment the frame.
++_currentFrame;
if( _currentFrame == _totalFrames ) {
// Reset back to frame 0 if we have reached the end.
_currentFrame = 0;
++_loopCount;
// Check if the animation should continue.
if( _loopCount == _totalLoops ) {
_keepGoing = false;
}
}
}
try {
Thread.sleep( 100 );
} catch( InterruptedException ignore ) {
}
}
}
}
}