blob: d703d65fa575baed2043e5fadc8e73645459b5fb [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 mx.preloaders
{
import flash.display.DisplayObject;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.utils.Timer;
import flash.utils.getDefinitionByName;
import flash.utils.getTimer;
import mx.events.FlexEvent;
import mx.events.RSLEvent;
import mx.geom.RoundedRectangle;
import mx.graphics.RectangularDropShadow;
/**
* The DownloadProgressBar class displays download progress.
* It is used by the Preloader control to provide user feedback
* while the application is downloading and loading.
*
* <p>The download progress bar displays information about
* two different phases of the application:
* the download phase and the initialization phase. </p>
*
* <p>In the Application container, use the
* the <code>preloader</code> property to specify the name of your subclass.</p>
*
* <p>You can implement a custom download progress bar component
* by creating a subclass of the DownloadProgressBar class.
* Do not implement a download progress bar as an MXML component
* because it loads too slowly.</p>
*
* @see mx.core.Application
* @see mx.preloaders.IPreloaderDisplay
* @see mx.preloaders.Preloader
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public class DownloadProgressBar extends Sprite implements IPreloaderDisplay
{
include "../core/Version.as";
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function DownloadProgressBar()
{
super();
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
/**
* The minimum number of milliseconds
* that the display should appear visible.
* If the downloading and initialization of the application
* takes less time than this value, then Flex pauses for this amount
* of time before dispatching the <code>complete</code> event.
*
* @default 0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var MINIMUM_DISPLAY_TIME:uint = 0;
/**
* The percentage of the progress bar that the downloading phase
* fills when the SWF file is fully downloaded.
* The rest of the progress bar is filled during the initializing phase.
* This should be a value from 0 to 100.
*
* @default 60
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var DOWNLOAD_PERCENTAGE:uint = 60;
/**
* @private
*/
private var _showProgressBar:Boolean = true;
/**
* @private
* Cached Rectangle returned by the labelRect getter.
*/
private var _labelRect:Rectangle = labelRect;
/**
* @private
* Cached Rectangle returned by the percentRect getter.
*/
private var _percentRect:Rectangle = percentRect;
/**
* @private
* Cached RoundedRectangle returned by the borderRect getter.
*/
private var _borderRect:RoundedRectangle = borderRect;
/**
* @private
* Cached RoundedRectangle returned by the barFrameRect getter.
*/
private var _barFrameRect:RoundedRectangle = barFrameRect;
/**
* @private
* Cached RoundedRectangle returned by the barRect getter.
*/
private var _barRect:RoundedRectangle = barRect;
/**
* @private
*/
private var _xOffset:Number = 20;
/**
* @private
*/
private var _yOffset:Number = 20;
/**
* @private
*/
private var _maximum:Number = 0;
/**
* @private
*/
private var _value:Number = 0;
/**
* @private
*/
private var _barSprite:Sprite;
/**
* @private
*/
private var _barFrameSprite:Sprite;
/**
* @private
*/
private var _labelObj:TextField;
/**
* @private
*/
private var _percentObj:TextField;
/**
* @private
*/
private var _startTime:int;
/**
* @private
*/
private var _displayTime:int;
/**
* @private
*/
private var _startedLoading:Boolean = false;
/**
* @private
*/
private var _startedInit:Boolean = false;
/**
* @private
*/
private var _showingDisplay:Boolean = false;
/**
* @private
*/
private var _displayStartCount:uint = 0;
/**
* @private
*/
private var _initProgressCount:uint = 0;
/**
* The total number of validation events you expect to get
* in the initializing phase. This should be an integer
* greater or equal to 4 (and note that if it is greater than 4
* you might have an inefficiency in your initialization code)
*
* @default 6
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 4
*/
protected var initProgressTotal:uint = 6;
//--------------------------------------------------------------------------
//
// Overridden properties
//
//--------------------------------------------------------------------------
//----------------------------------
// visible
//----------------------------------
/**
* @private
* Storage for the visible property.
*/
private var _visible:Boolean = false;
/**
* Specifies whether the download progress bar is visible.
*
* <p>When the Preloader control determines that the progress bar should be displayed,
* it sets this value to <code>true</code>. When the Preloader control determines that
* the progress bar should be hidden, it sets the value to <code>false</code>.</p>
*
* <p>A subclass of the DownloadProgressBar class should never modify this property.
* Instead, you can override the setter method to recognize when
* the Preloader control modifies it, and perform any necessary actions. </p>
*
* @default false
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
override public function get visible():Boolean
{
return _visible;
}
/**
* @private
*/
override public function set visible(value:Boolean):void
{
if (!_visible && value)
show();
else if (_visible && !value )
hide();
_visible = value;
}
//--------------------------------------------------------------------------
//
// Properties: IPreloaderDisplay
//
//--------------------------------------------------------------------------
//----------------------------------
// backgroundAlpha
//----------------------------------
/**
* @private
* Storage for the backgroundAlpha property.
*/
private var _backgroundAlpha:Number = 1;
/**
* Alpha level of the SWF file or image defined by
* the <code>backgroundImage</code> property, or the color defined by
* the <code>backgroundColor</code> property.
* Valid values range from 0 to 1.0.
*
* <p>You can specify either a <code>backgroundColor</code>
* or a <code>backgroundImage</code>, but not both.</p>
*
* @default 1.0
*
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get backgroundAlpha():Number
{
if (!isNaN(_backgroundAlpha))
return _backgroundAlpha;
else
return 1;
}
/**
* @private
*/
public function set backgroundAlpha(value:Number):void
{
_backgroundAlpha = value;
}
//----------------------------------
// backgroundColor
//----------------------------------
/**
* @private
* Storage for the backgroundColor property.
*/
private var _backgroundColor:uint;
/**
* Background color of a download progress bar.
* You can have either a <code>backgroundColor</code> or a
* <code>backgroundImage</code>, but not both.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get backgroundColor():uint
{
return _backgroundColor;
}
/**
* @private
*/
public function set backgroundColor(value:uint):void
{
_backgroundColor = value;
}
//----------------------------------
// backgroundImage
//----------------------------------
/**
* @private
* Storage for the backgroundImage property.
*/
private var _backgroundImage:Object;
/**
* The background image of the application,
* which is passed in by the preloader.
* You can specify either a <code>backgroundColor</code>
* or a <code>backgroundImage</code>, but not both.
*
* <p>A value of null means "not set".
* If this style and the <code>backgroundColor</code> style are undefined,
* the component has a transparent background.</p>
*
* <p>The preloader does not display embedded images.
* You can only use images loaded at runtime.</p>
*
* @default null
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get backgroundImage():Object
{
return _backgroundImage;
}
/**
* @private
*/
public function set backgroundImage(value:Object):void
{
_backgroundImage = value;
}
//----------------------------------
// backgroundSize
//----------------------------------
/**
* @private
* Storage for the backgroundSize property.
*/
private var _backgroundSize:String = "";
/**
* Scales the image specified by <code>backgroundImage</code>
* to different percentage sizes.
* A value of <code>"100%"</code> stretches the image
* to fit the entire component.
* To specify a percentage value, you must include the percent sign (%).
* A value of <code>"auto"</code>, maintains
* the original size of the image.
*
* @default "auto"
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get backgroundSize():String
{
return _backgroundSize;
}
/**
* @private
*/
public function set backgroundSize(value:String):void
{
_backgroundSize = value;
}
//----------------------------------
// preloader
//----------------------------------
/**
* @private
* Storage for the preloader property.
*/
private var _preloader:Sprite;
/**
* The Preloader class passes in a reference to itself to the display class
* so that it can listen for events from the preloader.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function set preloader(value:Sprite):void
{
_preloader = value;
value.addEventListener(ProgressEvent.PROGRESS, progressHandler);
value.addEventListener(Event.COMPLETE, completeHandler);
value.addEventListener(RSLEvent.RSL_PROGRESS, rslProgressHandler);
value.addEventListener(RSLEvent.RSL_COMPLETE, rslCompleteHandler);
value.addEventListener(RSLEvent.RSL_ERROR, rslErrorHandler);
value.addEventListener(FlexEvent.INIT_PROGRESS, initProgressHandler);
value.addEventListener(FlexEvent.INIT_COMPLETE, initCompleteHandler);
}
//----------------------------------
// stageHeight
//----------------------------------
/**
* @private
* Storage for the stageHeight property.
*/
private var _stageHeight:Number = 375;
/**
* The height of the stage,
* which is passed in by the Preloader class.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get stageHeight():Number
{
return _stageHeight;
}
/**
* @private
*/
public function set stageHeight(value:Number):void
{
_stageHeight = value;
}
//----------------------------------
// stageWidth
//----------------------------------
/**
* @private
* Storage for the stageHeight property.
*/
private var _stageWidth:Number = 500;
/**
* The width of the stage,
* which is passed in by the Preloader class.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get stageWidth():Number
{
return _stageWidth;
}
/**
* @private
*/
public function set stageWidth(value:Number):void
{
_stageWidth = value;
}
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// barFrameRect
//----------------------------------
/**
* The dimensions of the progress bar border.
* This is a read-only property which you must override
* if you need to change it.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get barFrameRect():RoundedRectangle
{
return new RoundedRectangle(14, 40, 154, 4);
}
//----------------------------------
// barRect
//----------------------------------
/**
* The dimensions of the progress bar.
* This is a read-only property which you must override
* if you need to change it.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get barRect():RoundedRectangle
{
return new RoundedRectangle(14, 39, 154, 6, 0);
}
//----------------------------------
// borderRect
//----------------------------------
/**
* The dimensions of the border of the display.
* This is a read-only property which you must override
* if you need to change it.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get borderRect():RoundedRectangle
{
return new RoundedRectangle(0, 0, 182, 60, 4);
}
//----------------------------------
// downloadingLabel
//----------------------------------
/**
* @private
* Storage for the downloadingLabel property.
*/
private var _downloadingLabel:String = "Loading";
/**
* The string to display as the label while in the downloading phase.
*
* @default "Loading"
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get downloadingLabel():String
{
return _downloadingLabel;
}
/**
* @private
*/
protected function set downloadingLabel(value:String):void
{
_downloadingLabel = value;
}
//----------------------------------
// initializingLabel
//----------------------------------
/**
* @private
* Storage for the initializingLabel property.
*/
private static var _initializingLabel:String = "Initializing";
/**
* The string to display as the label while in the initializing phase.
*
* @default "Initializing"
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public static function get initializingLabel():String
{
return _initializingLabel;
}
/**
* @private
*/
public static function set initializingLabel(value:String):void
{
_initializingLabel = value;
}
//----------------------------------
// label
//----------------------------------
/**
* @private
* Storage for the label property.
*/
private var _label:String = "";
/**
* Text to display when the progress bar is active.
* The Preloader class sets this value
* before displaying the progress bar.
* Implementing this property in a subclass is optional.
*
* @default ""
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get label():String
{
return _label;
}
/**
* @private
*/
protected function set label(value:String):void
{
if (!(value is Function))
_label = value;
draw();
}
//----------------------------------
// labelFormat
//----------------------------------
/**
* The TextFormat object of the TextField component of the label.
* This is a read-only property which you must override
* if you need to change it.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get labelFormat():TextFormat
{
var tf:TextFormat = new TextFormat();
tf.color = 0x333333;
tf.font = "Verdana";
tf.size = 10;
return tf;
}
//----------------------------------
// labelRect
//----------------------------------
/**
* The dimensions of the TextField component for the label.
* This is a read-only property which you must override
* if you need to change it.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get labelRect():Rectangle
{
return new Rectangle(14, 17, 100, 16);
}
//----------------------------------
// percentFormat
//----------------------------------
/**
* The TextFormat of the TextField component for displaying the percent.
* This is a read-only property which you must override
* if you need to change it.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get percentFormat():TextFormat
{
var tf:TextFormat = new TextFormat();
tf.align = "right";
tf.color = 0x000000;
tf.font = "Verdana";
tf.size = 10;
return tf;
}
//----------------------------------
// percentRect
//----------------------------------
/**
* The dimensions of the TextField component for displaying the percent.
* This is a read-only property which you must override
* if you need to change it.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get percentRect():Rectangle
{
return new Rectangle(108, 4, 34, 16);
}
//----------------------------------
// showLabel
//----------------------------------
/**
* @private
* Storage for the showLabel property.
*/
private var _showLabel:Boolean = true;
/**
* Controls whether to display the label, <code>true</code>,
* or not, <code>false</code>.
*
* @default true
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get showLabel():Boolean
{
return _showLabel;
}
/**
* @private
*/
protected function set showLabel(value:Boolean):void
{
_showLabel = value;
draw();
}
//----------------------------------
// showPercentage
//----------------------------------
/**
* @private
* Storage for the showPercentage property.
*/
private var _showPercentage:Boolean = false;
/**
* Controls whether to display the percentage, <code>true</code>,
* or not, <code>false</code>.
*
* @default true
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get showPercentage():Boolean
{
return _showPercentage;
}
/**
* @private
*/
protected function set showPercentage(value:Boolean):void
{
_showPercentage = value;
draw();
}
//--------------------------------------------------------------------------
//
// Methods:IPreloaderDisplay
//
//--------------------------------------------------------------------------
/**
* Called by the Preloader after the download progress bar
* has been added as a child of the Preloader.
* This should be the starting point for configuring your download progress bar.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function initialize():void
{
_startTime = getTimer();
center(stageWidth, stageHeight);
}
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
/**
* Centers the download progress bar based on the passed in dimensions.
*
* @param width The width of the area in which to center the download progress bar.
*
* @param height The height of the area in which to center the download progress bar.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function center(width:Number, height:Number):void
{
_xOffset = Math.floor((width - _borderRect.width) / 2);
_yOffset = Math.floor((height - _borderRect.height) / 2);
}
/**
* @private
* Updates the display.
*/
private function draw():void
{
var percentage:Number;
if (_startedLoading)
{
if (!_startedInit)
{
// 0 to MaxDL Percentage
percentage = Math.round(getPercentLoaded(_value, _maximum) *
DOWNLOAD_PERCENTAGE / 100);
}
else
{
// MaxDL percentage to 100
percentage = Math.round((getPercentLoaded(_value, _maximum) *
(100 - DOWNLOAD_PERCENTAGE) / 100) +
DOWNLOAD_PERCENTAGE);
}
}
else
{
percentage = getPercentLoaded(_value, _maximum);
}
if (_labelObj)
_labelObj.text = _label;
if (_percentObj)
{
if (!_showPercentage)
{
_percentObj.visible = false;
_percentObj.text = "";
}
else
{
_percentObj.text = String(percentage) + "%";
}
}
if (_barSprite && _barFrameSprite)
{
if (!_showProgressBar)
{
_barSprite.visible = false;
_barFrameSprite.visible = false;
}
else
{
drawProgressBar(percentage);
}
}
}
/**
* Creates the subcomponents of the display.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function createChildren():void
{
var g:Graphics = graphics;
var labelObj:TextField;
var percentObj:TextField;
// Draw the background first
// Same value as StyleManager.NOT_A_COLOR. However, we don't want to bring in StyleManager at this point.
if (backgroundColor != 0xFFFFFFFF)
{
g.beginFill(backgroundColor, backgroundAlpha);
g.drawRect(0, 0, stageWidth, stageHeight);
}
if (backgroundImage != null)
loadBackgroundImage(backgroundImage);
_barFrameSprite = new Sprite();
_barSprite = new Sprite();
addChild(_barFrameSprite);
addChild(_barSprite);
// Draw the outside border and fill.
g.beginFill(0xCCCCCC, 0.4);
g.drawRoundRect(calcX(_borderRect.x),
calcY(_borderRect.y),
_borderRect.width,
_borderRect.height,
_borderRect.cornerRadius * 2,
_borderRect.cornerRadius * 2);
g.drawRoundRect(calcX(_borderRect.x + 1),
calcY(_borderRect.y + 1),
_borderRect.width - 2,
_borderRect.height - 2,
_borderRect.cornerRadius - 1 * 2,
_borderRect.cornerRadius - 1 * 2);
g.endFill();
g.beginFill(0xCCCCCC,0.4);
g.drawRoundRect(calcX(_borderRect.x + 1),
calcY(_borderRect.y + 1),
_borderRect.width - 2,
_borderRect.height - 2,
_borderRect.cornerRadius - 1 * 2,
_borderRect.cornerRadius - 1 * 2);
g.endFill();
var frame_g:Graphics = _barFrameSprite.graphics;
// Draw the bar frame border and fill
var matrix:Matrix = new Matrix();
matrix.createGradientBox(_barFrameRect.width, _barFrameRect.height,
Math.PI / 2, calcX(_barFrameRect.x), calcY(_barFrameRect.y));
frame_g.beginGradientFill(GradientType.LINEAR,
[ 0x5C6266, 0xB5B8BA ],
[ 1.0, 1.0 ],
[ 0, 0xFF ],
matrix);
frame_g.drawRoundRect(calcX(_barFrameRect.x),
calcY(_barFrameRect.y),
_barFrameRect.width,
_barFrameRect.height,
_barFrameRect.cornerRadius * 2,
_barFrameRect.cornerRadius * 2);
frame_g.drawRoundRect(calcX(_barFrameRect.x + 1),
calcY(_barFrameRect.y + 1),
_barFrameRect.width - 2,
_barFrameRect.height - 2,
_barFrameRect.cornerRadius * 2,
_barFrameRect.cornerRadius * 2);
frame_g.endFill();
// Attach the label TextField.
_labelObj = new TextField();
_labelObj.x = calcX(_labelRect.x);
_labelObj.y = calcY(_labelRect.y);
_labelObj.width = _labelRect.width;
_labelObj.height = _labelRect.height;
_labelObj.selectable = false;
_labelObj.defaultTextFormat = labelFormat;
addChild(_labelObj);
// Attach the percentage TextField.
_percentObj = new TextField();
_percentObj.x = calcX(_percentRect.x);
_percentObj.y = calcY(_percentRect.y);
_percentObj.width = _percentRect.width;
_percentObj.height = _percentRect.height;
_percentObj.selectable = false;
_percentObj.defaultTextFormat = percentFormat;
addChild(_percentObj);
// Create dropshadow
var ds:RectangularDropShadow = new RectangularDropShadow();
ds.color = 0x000000;
ds.angle = 90;
ds.alpha = .6;
ds.distance = 2;
ds.tlRadius = ds.trRadius = ds.blRadius = ds.brRadius = _borderRect.cornerRadius;
ds.drawShadow(g,
calcX(_borderRect.x),
calcY(_borderRect.y),
_borderRect.width,
_borderRect.height);
// Draw the top line
g.lineStyle(1,0xFFFFFF, .3);
g.moveTo(calcX(_borderRect.x) + _borderRect.cornerRadius, calcY(_borderRect.y));
g.lineTo(calcX(_borderRect.x) - _borderRect.cornerRadius + _borderRect.width, calcY(_borderRect.y));
}
/**
* @private
* Draws the progress bar.
*/
private function drawProgressBar(percentage:Number):void
{
var g:Graphics = _barSprite.graphics;
g.clear();
var colors:Array = [ 0xFFFFFF, 0xFFFFFF ];
var ratios:Array = [ 0, 0xFF ];
var matrix:Matrix = new Matrix();
// Middle
var barWidth:Number = _barRect.width * percentage / 100;
var barWidthSplit:Number = barWidth / 2;
var barHeight:Number = _barRect.height-4;
var barX:Number = calcX(_barRect.x);
var barY:Number = calcY(_barRect.y) + 2;
var barY2:Number;
matrix.createGradientBox(barWidthSplit, barHeight,
0, barX, barY);
g.beginGradientFill(GradientType.LINEAR, colors, [ .39, .85],
ratios, matrix);
g.drawRect(barX, barY, barWidthSplit, barHeight);
matrix.createGradientBox(barWidthSplit, barHeight,
0, barX + barWidthSplit, barY);
g.beginGradientFill(GradientType.LINEAR, colors, [.85, 1.0],
ratios, matrix);
g.drawRect(barX + barWidthSplit, barY, barWidthSplit, barHeight);
// Outer highlight
barWidthSplit = barWidth / 3;
barHeight = _barRect.height;
barY = calcY(_barRect.y);
barY2 = barY + barHeight - 1;
matrix.createGradientBox(barWidthSplit, barHeight,
0, barX, barY);
g.beginGradientFill(GradientType.LINEAR, colors, [ .05, .15],
ratios, matrix);
g.drawRect(barX, barY, barWidthSplit, 1);
g.drawRect(barX, barY2, barWidthSplit, 1);
matrix.createGradientBox(barWidthSplit, barHeight,
0, barX + barWidthSplit, barY);
g.beginGradientFill(GradientType.LINEAR, colors, [ .15, .25],
ratios, matrix);
g.drawRect(barX + barWidthSplit, barY, barWidthSplit, 1);
g.drawRect(barX + barWidthSplit, barY2, barWidthSplit, 1);
matrix.createGradientBox(barWidthSplit, barHeight,
0, barX + barWidthSplit * 2, barY);
g.beginGradientFill(GradientType.LINEAR, colors, [ .25, .1],
ratios, matrix);
g.drawRect(barX + barWidthSplit * 2, barY, barWidthSplit, 1);
g.drawRect(barX + barWidthSplit * 2, barY2, barWidthSplit, 1);
// Inner highlight
barWidthSplit = barWidth / 3;
barHeight = _barRect.height;
barY = calcY(_barRect.y) + 1;
barY2 = calcY(_barRect.y) + barHeight - 2;
matrix.createGradientBox(barWidthSplit, barHeight,
0, barX, barY);
g.beginGradientFill(GradientType.LINEAR, colors, [ .15, .30],
ratios, matrix);
g.drawRect(barX, barY, barWidthSplit, 1);
g.drawRect(barX, barY2, barWidthSplit, 1);
matrix.createGradientBox(barWidthSplit, barHeight,
0, barX + barWidthSplit, barY);
g.beginGradientFill(GradientType.LINEAR, colors, [ .30, .40],
ratios, matrix);
g.drawRect(barX + barWidthSplit, barY, barWidthSplit, 1);
g.drawRect(barX + barWidthSplit, barY2, barWidthSplit, 1);
matrix.createGradientBox(barWidthSplit, barHeight,
0, barX + barWidthSplit * 2, barY);
g.beginGradientFill(GradientType.LINEAR, colors, [ .40, .25],
ratios, matrix);
g.drawRect(barX + barWidthSplit * 2, barY, barWidthSplit, 1);
g.drawRect(barX + barWidthSplit * 2, barY2, barWidthSplit, 1);
}
/**
* Updates the display of the download progress bar
* with the current download information.
* A typical implementation divides the loaded value by the total value
* and displays a percentage.
* If you do not implement this method, you should create
* a progress bar that displays an animation to indicate to the user
* that a download is occurring.
*
* <p>The <code>setProgress()</code> method is only called
* if the application is being downloaded from a remote server
* and the application is not in the browser cache.</p>
*
* @param completed Number of bytes of the application SWF file
* that have been downloaded.
*
* @param total Size of the application SWF file in bytes.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function setProgress(completed:Number, total:Number):void
{
if (!isNaN(completed) &&
!isNaN(total) &&
completed >= 0 &&
total > 0)
{
_value = Number(completed);
_maximum = Number(total);
draw();
}
}
/**
* Returns the percentage value of the application loaded.
*
* @param loaded Number of bytes of the application SWF file
* that have been downloaded.
*
* @param total Size of the application SWF file in bytes.
*
* @return The percentage value of the loaded application.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function getPercentLoaded(loaded:Number, total:Number):Number
{
var perc:Number;
if (loaded == 0 || total == 0 || isNaN(total) || isNaN(loaded))
return 0;
else
perc = 100 * loaded/total;
if (isNaN(perc) || perc <= 0)
return 0;
else if (perc > 99)
return 99;
else
return Math.round(perc);
}
/**
* @private
* Make the display class visible.
*/
private function show():void
{
_showingDisplay = true;
calcScale();
draw();
_displayTime = getTimer(); // Time when the display is shown.
}
/**
* @private
*/
private function hide():void
{
}
/**
* @private
*/
private function calcX(base:Number):Number
{
return base + _xOffset;
}
/**
* @private
*/
private function calcY(base:Number):Number
{
return base + _yOffset;
}
/**
* @private
* Figure out the scale for the display class based on the stage size.
* Then creates the children subcomponents.
*/
private function calcScale():void
{
if (stageWidth < 160 || stageHeight < 120)
{
scaleX = 1.0;
scaleY = 1.0;
}
else if (stageWidth < 240 || stageHeight < 150)
{
// Scale to appropriate size
createChildren();
var scale:Number = Math.min(stageWidth / 240.0,
stageHeight / 150.0);
scaleX = scale;
scaleY = scale;
}
else
{
createChildren();
}
}
/**
* Defines the algorithm for determining whether to show
* the download progress bar while in the download phase.
*
* @param elapsedTime number of milliseconds that have elapsed
* since the start of the download phase.
*
* @param event The ProgressEvent object that contains
* the <code>bytesLoaded</code> and <code>bytesTotal</code> properties.
*
* @return If the return value is <code>true</code>, then show the
* download progress bar.
* The default behavior is to show the download progress bar
* if more than 700 milliseconds have elapsed
* and if Flex has downloaded less than half of the bytes of the SWF file.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function showDisplayForDownloading(elapsedTime:int,
event:ProgressEvent):Boolean
{
return elapsedTime > 700 &&
event.bytesLoaded < event.bytesTotal / 2;
}
/**
* Defines the algorithm for determining whether to show the download progress bar
* while in the initialization phase, assuming that the display
* is not currently visible.
*
* @param elapsedTime number of milliseconds that have elapsed
* since the start of the download phase.
*
* @param count number of times that the <code>initProgress</code> event
* has been received from the application.
*
* @return If <code>true</code>, then show the download progress bar.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function showDisplayForInit(elapsedTime:int, count:int):Boolean
{
return elapsedTime > 300 && count == 2;
}
/**
* @private
*/
private function loadBackgroundImage(classOrString:Object):void
{
var cls:Class;
// The "as" operator checks to see if classOrString
// can be coerced to a Class
if (classOrString && classOrString as Class)
{
// Load background image given a class pointer
cls = Class(classOrString);
initBackgroundImage(new cls());
}
else if (classOrString && classOrString is String)
{
try
{
cls = Class(getDefinitionByName(String(classOrString)));
}
catch(e:Error)
{
// ignore
}
if (cls)
{
var newStyleObj:DisplayObject = new cls();
initBackgroundImage(newStyleObj);
}
else
{
// Loading the image is slightly different
// than in Loader.loadContent()... is this on purpose?
// Load background image from external URL
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(
Event.COMPLETE, loader_completeHandler);
loader.contentLoaderInfo.addEventListener(
IOErrorEvent.IO_ERROR, loader_ioErrorHandler);
var loaderContext:LoaderContext = new LoaderContext();
loaderContext.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);
loader.load(new URLRequest(String(classOrString)), loaderContext);
}
}
}
/**
* @private
*/
private function initBackgroundImage(image:DisplayObject):void
{
addChildAt(image,0);
var backgroundImageWidth:Number = image.width;
var backgroundImageHeight:Number = image.height;
// Scale according to backgroundSize
var percentage:Number = calcBackgroundSize();
if (isNaN(percentage))
{
var sX:Number = 1.0;
var sY:Number = 1.0;
}
else
{
var scale:Number = percentage * 0.01;
sX = scale * stageWidth / backgroundImageWidth;
sY = scale * stageHeight / backgroundImageHeight;
}
image.scaleX = sX;
image.scaleY = sY;
// Center everything.
// Use a scrollRect to position and clip the image.
var offsetX:Number =
Math.round(0.5 * (stageWidth - backgroundImageWidth * sX));
var offsetY:Number =
Math.round(0.5 * (stageHeight - backgroundImageHeight * sY));
image.x = offsetX;
image.y = offsetY;
// Adjust alpha to match backgroundAlpha
if (!isNaN(backgroundAlpha))
image.alpha = backgroundAlpha;
}
/**
* @private
*/
private function calcBackgroundSize():Number
{
var percentage:Number = NaN;
if (backgroundSize)
{
var index:int = backgroundSize.indexOf("%");
if (index != -1)
percentage = Number(backgroundSize.substr(0, index));
}
return percentage;
}
//--------------------------------------------------------------------------
//
// Event handlers
//
//--------------------------------------------------------------------------
/**
* Event listener for the <code>ProgressEvent.PROGRESS</code> event.
* This implementation updates the progress bar
* with the percentage of bytes downloaded.
*
* @param event The event object.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function progressHandler(event:ProgressEvent):void
{
var loaded:uint = event.bytesLoaded;
var total:uint = event.bytesTotal;
var elapsedTime:int = getTimer() - _startTime;
// Only show the Loading phase if it will appear for awhile.
if (_showingDisplay || showDisplayForDownloading(elapsedTime, event))
{
if (!_startedLoading)
{
show();
label = downloadingLabel;
_startedLoading = true;
}
setProgress(event.bytesLoaded, event.bytesTotal);
}
}
/**
* Event listener for the <code>Event.COMPLETE</code> event.
* The default implementation does nothing.
*
* @param event The event object.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function completeHandler(event:Event):void
{
}
/**
* Event listener for the <code>RSLEvent.RSL_PROGRESS</code> event.
* The default implementation does nothing.
*
* @param event The event object.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function rslProgressHandler(event:RSLEvent):void
{
}
/**
* Event listener for the <code>RSLEvent.RSL_COMPLETE</code> event.
*
* @param event The event object.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function rslCompleteHandler(event:RSLEvent):void
{
var word:String = "library";
if (event.isResourceModule)
word = "module";
label = "Loaded " + word + " " + event.rslIndex + " of " + event.rslTotal;
}
/**
* Event listener for the <code>RSLEvent.RSL_ERROR</code> event.
* This event listner handles any errors detected when downloading an RSL.
*
* @param event The event object.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function rslErrorHandler(event:RSLEvent):void
{
_preloader.removeEventListener(ProgressEvent.PROGRESS,
progressHandler);
_preloader.removeEventListener(Event.COMPLETE,
completeHandler);
_preloader.removeEventListener(RSLEvent.RSL_PROGRESS,
rslProgressHandler);
_preloader.removeEventListener(RSLEvent.RSL_COMPLETE,
rslCompleteHandler);
_preloader.removeEventListener(RSLEvent.RSL_ERROR,
rslErrorHandler);
_preloader.removeEventListener(FlexEvent.INIT_PROGRESS,
initProgressHandler);
_preloader.removeEventListener(FlexEvent.INIT_COMPLETE,
initCompleteHandler);
if (!_showingDisplay)
{
show();
_showingDisplay = true;
}
label = "RSL Error " + (event.rslIndex + 1) + " of " + event.rslTotal;
var errorField:ErrorField = new ErrorField(this);
errorField.show(event.errorText);
}
/**
* @private
* Helper function that dispatches the Complete event to the preloader.
*
* @param event The event object.
*/
private function timerHandler(event:Event = null):void
{
dispatchEvent(new Event(Event.COMPLETE));
}
/**
* Event listener for the <code>FlexEvent.INIT_PROGRESS</code> event.
* This implementation updates the progress bar
* each time the event is dispatched, and changes the text of the label.
*
* @param event The event object.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function initProgressHandler(event:Event):void
{
var elapsedTime:int = getTimer() - _startTime;
_initProgressCount++;
if (!_showingDisplay &&
showDisplayForInit(elapsedTime, _initProgressCount))
{
_displayStartCount = _initProgressCount;
show();
}
if (_showingDisplay)
{
if (!_startedInit)
{
// First init progress event.
_startedInit = true;
label = initializingLabel;
}
var loaded:Number = 100 * _initProgressCount /
(initProgressTotal - _displayStartCount);
setProgress(Math.min(loaded, 100), 100);
}
}
/**
* Event listener for the <code>FlexEvent.INIT_COMPLETE</code> event.
*
* @param event The event object.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function initCompleteHandler(event:Event):void
{
var elapsedTime:int = getTimer() - _displayTime;
if (_showingDisplay && elapsedTime < MINIMUM_DISPLAY_TIME)
{
var timer:Timer = new Timer(MINIMUM_DISPLAY_TIME - elapsedTime, 1);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
}
else
{
timerHandler();
}
}
/**
* @private
*/
private function loader_completeHandler(event:Event):void
{
var target:DisplayObject = DisplayObject(LoaderInfo(event.target).loader);
initBackgroundImage(target);
}
private function loader_ioErrorHandler(event:IOErrorEvent):void
{
// Swallow the error
}
}
}
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.system.Capabilities;
import flash.text.TextFieldAutoSize;
import flash.display.DisplayObjectContainer;
import flash.display.Stage;
import mx.preloaders.DownloadProgressBar;
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* @private
*
* Area to display error messages to help debug startup problems.
*
*/
class ErrorField extends Sprite
{
private var downloadProgressBar:DownloadProgressBar;
private const MIN_WIDTH_INCHES:int = 2; // min width of error message in inches
private const MAX_WIDTH_INCHES:int = 6; // max width of error message in inches
private const TEXT_MARGIN_PX:int = 10;
//----------------------------------
// labelFormat
//----------------------------------
/**
* The TextFormat object of the TextField component of the label.
* This is a read-only property which you must override
* if you need to change it.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get labelFormat():TextFormat
{
var tf:TextFormat = new TextFormat();
tf.color = 0x000000;
tf.font = "Verdana";
tf.size = 10;
return tf;
}
/**
* @private
*
* @param - parent - parent of the error field.
*/
public function ErrorField(downloadProgressBar:DownloadProgressBar)
{
super();
this.downloadProgressBar = downloadProgressBar;
}
/**
* Create and show the error message.
*
* @param errorText - text for error message.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function show(errorText:String):void
{
if (errorText == null || errorText.length == 0)
return;
var screenWidth:Number = downloadProgressBar.stageWidth;
var screenHeight:Number = downloadProgressBar.stageHeight;
// create the text field for the message and
// add it to the parent.
var textField:TextField = new TextField();
textField.autoSize = TextFieldAutoSize.LEFT;
textField.multiline = true;
textField.wordWrap = true;
textField.background = true;
textField.defaultTextFormat = labelFormat;
textField.text = errorText;
textField.width = Math.max(MIN_WIDTH_INCHES * Capabilities.screenDPI, screenWidth - (TEXT_MARGIN_PX * 2));
textField.width = Math.min(MAX_WIDTH_INCHES * Capabilities.screenDPI, textField.width);
textField.y = Math.max(0, screenHeight - TEXT_MARGIN_PX - textField.height);
// center field horizontally
textField.x = (screenWidth - textField.width) / 2;
downloadProgressBar.parent.addChild(this);
this.addChild(textField);
}
}