PageRenderTime 63ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/Sample/mx/preloaders/DownloadProgressBar.as

https://github.com/ingydotnet/yaml-oscon2009-talk
ActionScript | 1623 lines | 740 code | 224 blank | 659 comment | 67 complexity | d3a37ce81bcb7b7b054035ccab9d7e6e MD5 | raw file
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // ADOBE SYSTEMS INCORPORATED
  4. // Copyright 2003-2007 Adobe Systems Incorporated
  5. // All Rights Reserved.
  6. //
  7. // NOTICE: Adobe permits you to use, modify, and distribute this file
  8. // in accordance with the terms of the license agreement accompanying it.
  9. //
  10. ////////////////////////////////////////////////////////////////////////////////
  11. package mx.preloaders
  12. {
  13. import flash.display.DisplayObject;
  14. import flash.display.GradientType;
  15. import flash.display.Graphics;
  16. import flash.display.Loader;
  17. import flash.display.LoaderInfo;
  18. import flash.display.Sprite;
  19. import flash.events.Event;
  20. import flash.events.IOErrorEvent;
  21. import flash.events.ProgressEvent;
  22. import flash.events.TimerEvent;
  23. import flash.geom.Matrix;
  24. import flash.geom.Rectangle;
  25. import flash.net.URLRequest;
  26. import flash.system.ApplicationDomain;
  27. import flash.system.LoaderContext;
  28. import flash.text.TextField;
  29. import flash.text.TextFormat;
  30. import flash.utils.Timer;
  31. import flash.utils.getDefinitionByName;
  32. import flash.utils.getTimer;
  33. import mx.events.FlexEvent;
  34. import mx.events.RSLEvent;
  35. import mx.graphics.RectangularDropShadow;
  36. import mx.graphics.RoundedRectangle;
  37. /**
  38. * The DownloadProgressBar class displays download progress.
  39. * It is used by the Preloader control to provide user feedback
  40. * while the application is downloading and loading.
  41. *
  42. * <p>The download progress bar displays information about
  43. * two different phases of the application:
  44. * the download phase and the initialization phase. </p>
  45. *
  46. * <p>In the <code>&lt;mx:Application&gt;</code> tag, use the
  47. * the <code>preloader</code> property to specify the name of your subclass.</p>
  48. *
  49. * <p>You can implement a custom download progress bar component
  50. * by creating a subclass of the DownloadProgressBar class.
  51. * Do not implement a download progress bar as an MXML component
  52. * because it loads too slowly.</p>
  53. *
  54. * @see mx.core.Application
  55. * @see mx.preloaders.IPreloaderDisplay
  56. * @see mx.preloaders.Preloader
  57. */
  58. public class DownloadProgressBar extends Sprite implements IPreloaderDisplay
  59. {
  60. include "../core/Version.as";
  61. //--------------------------------------------------------------------------
  62. //
  63. // Constructor
  64. //
  65. //--------------------------------------------------------------------------
  66. /**
  67. * Constructor.
  68. */
  69. public function DownloadProgressBar()
  70. {
  71. super();
  72. }
  73. //--------------------------------------------------------------------------
  74. //
  75. // Variables
  76. //
  77. //--------------------------------------------------------------------------
  78. /**
  79. * The minimum number of milliseconds
  80. * that the display should appear visible.
  81. * If the downloading and initialization of the application
  82. * takes less time than this value, then Flex pauses for this amount
  83. * of time before dispatching the <code>complete</code> event.
  84. *
  85. * @default 0
  86. */
  87. protected var MINIMUM_DISPLAY_TIME:uint = 0;
  88. /**
  89. * The percentage of the progress bar that the downloading phase
  90. * fills when the SWF file is fully downloaded.
  91. * The rest of the progress bar is filled during the initializing phase.
  92. * This should be a value from 0 to 100.
  93. *
  94. * @default 60
  95. */
  96. protected var DOWNLOAD_PERCENTAGE:uint = 60;
  97. /**
  98. * @private
  99. */
  100. private var _showProgressBar:Boolean = true;
  101. /**
  102. * @private
  103. * Cached Rectangle returned by the labelRect getter.
  104. */
  105. private var _labelRect:Rectangle = labelRect;
  106. /**
  107. * @private
  108. * Cached Rectangle returned by the percentRect getter.
  109. */
  110. private var _percentRect:Rectangle = percentRect;
  111. /**
  112. * @private
  113. * Cached RoundedRectangle returned by the borderRect getter.
  114. */
  115. private var _borderRect:RoundedRectangle = borderRect;
  116. /**
  117. * @private
  118. * Cached RoundedRectangle returned by the barFrameRect getter.
  119. */
  120. private var _barFrameRect:RoundedRectangle = barFrameRect;
  121. /**
  122. * @private
  123. * Cached RoundedRectangle returned by the barRect getter.
  124. */
  125. private var _barRect:RoundedRectangle = barRect;
  126. /**
  127. * @private
  128. */
  129. private var _xOffset:Number = 20;
  130. /**
  131. * @private
  132. */
  133. private var _yOffset:Number = 20;
  134. /**
  135. * @private
  136. */
  137. private var _maximum:Number = 0;
  138. /**
  139. * @private
  140. */
  141. private var _value:Number = 0;
  142. /**
  143. * @private
  144. */
  145. private var _barSprite:Sprite;
  146. /**
  147. * @private
  148. */
  149. private var _barFrameSprite:Sprite;
  150. /**
  151. * @private
  152. */
  153. private var _labelObj:TextField;
  154. /**
  155. * @private
  156. */
  157. private var _percentObj:TextField;
  158. /**
  159. * @private
  160. */
  161. private var _startTime:int;
  162. /**
  163. * @private
  164. */
  165. private var _displayTime:int;
  166. /**
  167. * @private
  168. */
  169. private var _startedLoading:Boolean = false;
  170. /**
  171. * @private
  172. */
  173. private var _startedInit:Boolean = false;
  174. /**
  175. * @private
  176. */
  177. private var _showingDisplay:Boolean = false;
  178. /**
  179. * @private
  180. */
  181. private var _displayStartCount:uint = 0;
  182. /**
  183. * @private
  184. */
  185. private var _initProgressCount:uint = 0;
  186. /**
  187. * @private
  188. */
  189. private var _initProgressTotal:uint = 12;
  190. //--------------------------------------------------------------------------
  191. //
  192. // Overridden properties
  193. //
  194. //--------------------------------------------------------------------------
  195. //----------------------------------
  196. // visible
  197. //----------------------------------
  198. /**
  199. * @private
  200. * Storage for the visible property.
  201. */
  202. private var _visible:Boolean = false;
  203. /**
  204. * Specifies whether the download progress bar is visible.
  205. *
  206. * <p>When the Preloader control determines that the progress bar should be displayed,
  207. * it sets this value to <code>true</code>. When the Preloader control determines that
  208. * the progress bar should be hidden, it sets the value to <code>false</code>.</p>
  209. *
  210. * <p>A subclass of the DownloadProgressBar class should never modify this property.
  211. * Instead, you can override the setter method to recognize when
  212. * the Preloader control modifies it, and perform any necessary actions. </p>
  213. *
  214. * @default false
  215. */
  216. override public function get visible():Boolean
  217. {
  218. return _visible;
  219. }
  220. /**
  221. * @private
  222. */
  223. override public function set visible(value:Boolean):void
  224. {
  225. if (!_visible && value)
  226. show();
  227. else if (_visible && !value )
  228. hide();
  229. _visible = value;
  230. }
  231. //--------------------------------------------------------------------------
  232. //
  233. // Properties: IPreloaderDisplay
  234. //
  235. //--------------------------------------------------------------------------
  236. //----------------------------------
  237. // backgroundAlpha
  238. //----------------------------------
  239. /**
  240. * @private
  241. * Storage for the backgroundAlpha property.
  242. */
  243. private var _backgroundAlpha:Number = 1;
  244. /**
  245. * Alpha level of the SWF file or image defined by
  246. * the <code>backgroundImage</code> property, or the color defined by
  247. * the <code>backgroundColor</code> property.
  248. * Valid values range from 0 to 1.0.
  249. *
  250. * <p>You can specify either a <code>backgroundColor</code>
  251. * or a <code>backgroundImage</code>, but not both.</p>
  252. *
  253. * @default 1.0
  254. *
  255. */
  256. public function get backgroundAlpha():Number
  257. {
  258. if (!isNaN(_backgroundAlpha))
  259. return _backgroundAlpha;
  260. else
  261. return 1;
  262. }
  263. /**
  264. * @private
  265. */
  266. public function set backgroundAlpha(value:Number):void
  267. {
  268. _backgroundAlpha = value;
  269. }
  270. //----------------------------------
  271. // backgroundColor
  272. //----------------------------------
  273. /**
  274. * @private
  275. * Storage for the backgroundColor property.
  276. */
  277. private var _backgroundColor:uint;
  278. /**
  279. * Background color of a download progress bar.
  280. * You can have either a <code>backgroundColor</code> or a
  281. * <code>backgroundImage</code>, but not both.
  282. */
  283. public function get backgroundColor():uint
  284. {
  285. return _backgroundColor;
  286. }
  287. /**
  288. * @private
  289. */
  290. public function set backgroundColor(value:uint):void
  291. {
  292. _backgroundColor = value;
  293. }
  294. //----------------------------------
  295. // backgroundImage
  296. //----------------------------------
  297. /**
  298. * @private
  299. * Storage for the backgroundImage property.
  300. */
  301. private var _backgroundImage:Object;
  302. /**
  303. * The background image of the application,
  304. * which is passed in by the preloader.
  305. * You can specify either a <code>backgroundColor</code>
  306. * or a <code>backgroundImage</code>, but not both.
  307. *
  308. * <p>A value of null means "not set".
  309. * If this style and the <code>backgroundColor</code> style are undefined,
  310. * the component has a transparent background.</p>
  311. *
  312. * <p>The preloader does not display embedded images.
  313. * You can only use images loaded at runtime.</p>
  314. *
  315. * @default null
  316. */
  317. public function get backgroundImage():Object
  318. {
  319. return _backgroundImage;
  320. }
  321. /**
  322. * @private
  323. */
  324. public function set backgroundImage(value:Object):void
  325. {
  326. _backgroundImage = value;
  327. }
  328. //----------------------------------
  329. // backgroundSize
  330. //----------------------------------
  331. /**
  332. * @private
  333. * Storage for the backgroundSize property.
  334. */
  335. private var _backgroundSize:String = "";
  336. /**
  337. * Scales the image specified by <code>backgroundImage</code>
  338. * to different percentage sizes.
  339. * A value of <code>"100%"</code> stretches the image
  340. * to fit the entire component.
  341. * To specify a percentage value, you must include the percent sign (%).
  342. * A value of <code>"auto"</code>, maintains
  343. * the original size of the image.
  344. *
  345. * @default "auto"
  346. */
  347. public function get backgroundSize():String
  348. {
  349. return _backgroundSize;
  350. }
  351. /**
  352. * @private
  353. */
  354. public function set backgroundSize(value:String):void
  355. {
  356. _backgroundSize = value;
  357. }
  358. //----------------------------------
  359. // preloader
  360. //----------------------------------
  361. /**
  362. * @private
  363. * Storage for the preloader property.
  364. */
  365. private var _preloader:Sprite;
  366. /**
  367. * The Preloader class passes in a reference to itself to the display class
  368. * so that it can listen for events from the preloader.
  369. */
  370. public function set preloader(value:Sprite):void
  371. {
  372. _preloader = value;
  373. value.addEventListener(ProgressEvent.PROGRESS, progressHandler);
  374. value.addEventListener(Event.COMPLETE, completeHandler);
  375. value.addEventListener(RSLEvent.RSL_PROGRESS, rslProgressHandler);
  376. value.addEventListener(RSLEvent.RSL_COMPLETE, rslCompleteHandler);
  377. value.addEventListener(RSLEvent.RSL_ERROR, rslErrorHandler);
  378. value.addEventListener(FlexEvent.INIT_PROGRESS, initProgressHandler);
  379. value.addEventListener(FlexEvent.INIT_COMPLETE, initCompleteHandler);
  380. }
  381. //----------------------------------
  382. // stageHeight
  383. //----------------------------------
  384. /**
  385. * @private
  386. * Storage for the stageHeight property.
  387. */
  388. private var _stageHeight:Number = 375;
  389. /**
  390. * The height of the stage,
  391. * which is passed in by the Preloader class.
  392. */
  393. public function get stageHeight():Number
  394. {
  395. return _stageHeight;
  396. }
  397. /**
  398. * @private
  399. */
  400. public function set stageHeight(value:Number):void
  401. {
  402. _stageHeight = value;
  403. }
  404. //----------------------------------
  405. // stageWidth
  406. //----------------------------------
  407. /**
  408. * @private
  409. * Storage for the stageHeight property.
  410. */
  411. private var _stageWidth:Number = 500;
  412. /**
  413. * The width of the stage,
  414. * which is passed in by the Preloader class.
  415. */
  416. public function get stageWidth():Number
  417. {
  418. return _stageWidth;
  419. }
  420. /**
  421. * @private
  422. */
  423. public function set stageWidth(value:Number):void
  424. {
  425. _stageWidth = value;
  426. }
  427. //--------------------------------------------------------------------------
  428. //
  429. // Properties
  430. //
  431. //--------------------------------------------------------------------------
  432. //----------------------------------
  433. // barFrameRect
  434. //----------------------------------
  435. /**
  436. * The dimensions of the progress bar border.
  437. * This is a read-only property which you must override
  438. * if you need to change it.
  439. */
  440. protected function get barFrameRect():RoundedRectangle
  441. {
  442. return new RoundedRectangle(14, 40, 154, 4);
  443. }
  444. //----------------------------------
  445. // barRect
  446. //----------------------------------
  447. /**
  448. * The dimensions of the progress bar.
  449. * This is a read-only property which you must override
  450. * if you need to change it.
  451. */
  452. protected function get barRect():RoundedRectangle
  453. {
  454. return new RoundedRectangle(14, 39, 154, 6, 0);
  455. }
  456. //----------------------------------
  457. // borderRect
  458. //----------------------------------
  459. /**
  460. * The dimensions of the border of the display.
  461. * This is a read-only property which you must override
  462. * if you need to change it.
  463. */
  464. protected function get borderRect():RoundedRectangle
  465. {
  466. return new RoundedRectangle(0, 0, 182, 60, 4);
  467. }
  468. //----------------------------------
  469. // downloadingLabel
  470. //----------------------------------
  471. /**
  472. * @private
  473. * Storage for the downloadingLabel property.
  474. */
  475. private var _downloadingLabel:String = "Loading";
  476. /**
  477. * The string to display as the label while in the downloading phase.
  478. *
  479. * @default "Loading"
  480. */
  481. protected function get downloadingLabel():String
  482. {
  483. return _downloadingLabel;
  484. }
  485. /**
  486. * @private
  487. */
  488. protected function set downloadingLabel(value:String):void
  489. {
  490. _downloadingLabel = value;
  491. }
  492. //----------------------------------
  493. // initializingLabel
  494. //----------------------------------
  495. /**
  496. * @private
  497. * Storage for the initializingLabel property.
  498. */
  499. private static var _initializingLabel:String = "Initializing";
  500. /**
  501. * The string to display as the label while in the initializing phase.
  502. *
  503. * @default "Initializing"
  504. */
  505. public static function get initializingLabel():String
  506. {
  507. return _initializingLabel;
  508. }
  509. /**
  510. * @private
  511. */
  512. public static function set initializingLabel(value:String):void
  513. {
  514. _initializingLabel = value;
  515. }
  516. //----------------------------------
  517. // label
  518. //----------------------------------
  519. /**
  520. * @private
  521. * Storage for the label property.
  522. */
  523. private var _label:String = "";
  524. /**
  525. * Text to display when the progress bar is active.
  526. * The Preloader class sets this value
  527. * before displaying the progress bar.
  528. * Implementing this property in a subclass is optional.
  529. *
  530. * @default ""
  531. */
  532. protected function get label():String
  533. {
  534. return _label;
  535. }
  536. /**
  537. * @private
  538. */
  539. protected function set label(value:String):void
  540. {
  541. if (!(value is Function))
  542. _label = value;
  543. draw();
  544. }
  545. //----------------------------------
  546. // labelFormat
  547. //----------------------------------
  548. /**
  549. * The TextFormat object of the TextField component of the label.
  550. * This is a read-only property which you must override
  551. * if you need to change it.
  552. */
  553. protected function get labelFormat():TextFormat
  554. {
  555. var tf:TextFormat = new TextFormat();
  556. tf.color = 0x333333;
  557. tf.font = "Verdana";
  558. tf.size = 10;
  559. return tf;
  560. }
  561. //----------------------------------
  562. // labelRect
  563. //----------------------------------
  564. /**
  565. * The dimensions of the TextField component for the label.
  566. * This is a read-only property which you must override
  567. * if you need to change it.
  568. */
  569. protected function get labelRect():Rectangle
  570. {
  571. return new Rectangle(14, 17, 100, 16);
  572. }
  573. //----------------------------------
  574. // percentFormat
  575. //----------------------------------
  576. /**
  577. * The TextFormat of the TextField component for displaying the percent.
  578. * This is a read-only property which you must override
  579. * if you need to change it.
  580. */
  581. protected function get percentFormat():TextFormat
  582. {
  583. var tf:TextFormat = new TextFormat();
  584. tf.align = "right";
  585. tf.color = 0x000000;
  586. tf.font = "Verdana";
  587. tf.size = 10;
  588. return tf;
  589. }
  590. //----------------------------------
  591. // percentRect
  592. //----------------------------------
  593. /**
  594. * The dimensions of the TextField component for displaying the percent.
  595. * This is a read-only property which you must override
  596. * if you need to change it.
  597. */
  598. protected function get percentRect():Rectangle
  599. {
  600. return new Rectangle(108, 4, 34, 16);
  601. }
  602. //----------------------------------
  603. // showLabel
  604. //----------------------------------
  605. /**
  606. * @private
  607. * Storage for the showLabel property.
  608. */
  609. private var _showLabel:Boolean = true;
  610. /**
  611. * Controls whether to display the label, <code>true</code>,
  612. * or not, <code>false</code>.
  613. *
  614. * @default true
  615. */
  616. protected function get showLabel():Boolean
  617. {
  618. return _showLabel;
  619. }
  620. /**
  621. * @private
  622. */
  623. protected function set showLabel(value:Boolean):void
  624. {
  625. _showLabel = value;
  626. draw();
  627. }
  628. //----------------------------------
  629. // showPercentage
  630. //----------------------------------
  631. /**
  632. * @private
  633. * Storage for the showPercentage property.
  634. */
  635. private var _showPercentage:Boolean = false;
  636. /**
  637. * Controls whether to display the percentage, <code>true</code>,
  638. * or not, <code>false</code>.
  639. *
  640. * @default true
  641. */
  642. protected function get showPercentage():Boolean
  643. {
  644. return _showPercentage;
  645. }
  646. /**
  647. * @private
  648. */
  649. protected function set showPercentage(value:Boolean):void
  650. {
  651. _showPercentage = value;
  652. draw();
  653. }
  654. //--------------------------------------------------------------------------
  655. //
  656. // Methods:IPreloaderDisplay
  657. //
  658. //--------------------------------------------------------------------------
  659. /**
  660. * Called by the Preloader after the download progress bar
  661. * has been added as a child of the Preloader.
  662. * This should be the starting point for configuring your download progress bar.
  663. */
  664. public function initialize():void
  665. {
  666. _startTime = getTimer();
  667. center(stageWidth, stageHeight);
  668. }
  669. //--------------------------------------------------------------------------
  670. //
  671. // Methods
  672. //
  673. //--------------------------------------------------------------------------
  674. /**
  675. * Centers the download progress bar based on the passed in dimensions.
  676. *
  677. * @param width The width of the area in which to center the download progress bar.
  678. *
  679. * @param height The height of the area in which to center the download progress bar.
  680. */
  681. protected function center(width:Number, height:Number):void
  682. {
  683. _xOffset = Math.floor((width - _borderRect.width) / 2);
  684. _yOffset = Math.floor((height - _borderRect.height) / 2);
  685. }
  686. /**
  687. * @private
  688. * Updates the display.
  689. */
  690. private function draw():void
  691. {
  692. var percentage:Number;
  693. if (_startedLoading)
  694. {
  695. if (!_startedInit)
  696. {
  697. // 0 to MaxDL Percentage
  698. percentage = Math.round(getPercentLoaded(_value, _maximum) *
  699. DOWNLOAD_PERCENTAGE / 100);
  700. }
  701. else
  702. {
  703. // MaxDL percentage to 100
  704. percentage = Math.round((getPercentLoaded(_value, _maximum) *
  705. (100 - DOWNLOAD_PERCENTAGE) / 100) +
  706. DOWNLOAD_PERCENTAGE);
  707. }
  708. }
  709. else
  710. {
  711. percentage = getPercentLoaded(_value, _maximum);
  712. }
  713. if (_labelObj)
  714. _labelObj.text = _label;
  715. if (_percentObj)
  716. {
  717. if (!_showPercentage)
  718. {
  719. _percentObj.visible = false;
  720. _percentObj.text = "";
  721. }
  722. else
  723. {
  724. _percentObj.text = String(percentage) + "%";
  725. }
  726. }
  727. if (_barSprite && _barFrameSprite)
  728. {
  729. if (!_showProgressBar)
  730. {
  731. _barSprite.visible = false;
  732. _barFrameSprite.visible = false;
  733. }
  734. else
  735. {
  736. drawProgressBar(percentage);
  737. }
  738. }
  739. }
  740. /**
  741. * Creates the subcomponents of the display.
  742. */
  743. protected function createChildren():void
  744. {
  745. var g:Graphics = graphics;
  746. var labelObj:TextField;
  747. var percentObj:TextField;
  748. // Draw the background first
  749. // Same value as StyleManager.NOT_A_COLOR. However, we don't want to bring in StyleManager at this point.
  750. if (backgroundColor != 0xFFFFFFFF)
  751. {
  752. g.beginFill(backgroundColor, backgroundAlpha);
  753. g.drawRect(0, 0, stageWidth, stageHeight);
  754. }
  755. if (backgroundImage != null)
  756. loadBackgroundImage(backgroundImage);
  757. _barFrameSprite = new Sprite();
  758. _barSprite = new Sprite();
  759. addChild(_barFrameSprite);
  760. addChild(_barSprite);
  761. // Draw the outside border and fill.
  762. g.beginFill(0xCCCCCC, 0.4);
  763. g.drawRoundRect(calcX(_borderRect.x),
  764. calcY(_borderRect.y),
  765. _borderRect.width,
  766. _borderRect.height,
  767. _borderRect.cornerRadius * 2,
  768. _borderRect.cornerRadius * 2);
  769. g.drawRoundRect(calcX(_borderRect.x + 1),
  770. calcY(_borderRect.y + 1),
  771. _borderRect.width - 2,
  772. _borderRect.height - 2,
  773. _borderRect.cornerRadius - 1 * 2,
  774. _borderRect.cornerRadius - 1 * 2);
  775. g.endFill();
  776. g.beginFill(0xCCCCCC,0.4);
  777. g.drawRoundRect(calcX(_borderRect.x + 1),
  778. calcY(_borderRect.y + 1),
  779. _borderRect.width - 2,
  780. _borderRect.height - 2,
  781. _borderRect.cornerRadius - 1 * 2,
  782. _borderRect.cornerRadius - 1 * 2);
  783. g.endFill();
  784. var frame_g:Graphics = _barFrameSprite.graphics;
  785. // Draw the bar frame border and fill
  786. var matrix:Matrix = new Matrix();
  787. matrix.createGradientBox(_barFrameRect.width, _barFrameRect.height,
  788. Math.PI / 2, calcX(_barFrameRect.x), calcY(_barFrameRect.y));
  789. frame_g.beginGradientFill(GradientType.LINEAR,
  790. [ 0x5C6266, 0xB5B8BA ],
  791. [ 1.0, 1.0 ],
  792. [ 0, 0xFF ],
  793. matrix);
  794. frame_g.drawRoundRect(calcX(_barFrameRect.x),
  795. calcY(_barFrameRect.y),
  796. _barFrameRect.width,
  797. _barFrameRect.height,
  798. _barFrameRect.cornerRadius * 2,
  799. _barFrameRect.cornerRadius * 2);
  800. frame_g.drawRoundRect(calcX(_barFrameRect.x + 1),
  801. calcY(_barFrameRect.y + 1),
  802. _barFrameRect.width - 2,
  803. _barFrameRect.height - 2,
  804. _barFrameRect.cornerRadius * 2,
  805. _barFrameRect.cornerRadius * 2);
  806. frame_g.endFill();
  807. // Attach the label TextField.
  808. _labelObj = new TextField();
  809. _labelObj.x = calcX(_labelRect.x);
  810. _labelObj.y = calcY(_labelRect.y);
  811. _labelObj.width = _labelRect.width;
  812. _labelObj.height = _labelRect.height;
  813. _labelObj.selectable = false;
  814. _labelObj.defaultTextFormat = labelFormat;
  815. addChild(_labelObj);
  816. // Attach the percentage TextField.
  817. _percentObj = new TextField();
  818. _percentObj.x = calcX(_percentRect.x);
  819. _percentObj.y = calcY(_percentRect.y);
  820. _percentObj.width = _percentRect.width;
  821. _percentObj.height = _percentRect.height;
  822. _percentObj.selectable = false;
  823. _percentObj.defaultTextFormat = percentFormat;
  824. addChild(_percentObj);
  825. // Create dropshadow
  826. var ds:RectangularDropShadow = new RectangularDropShadow();
  827. ds.color = 0x000000;
  828. ds.angle = 90;
  829. ds.alpha = .6;
  830. ds.distance = 2;
  831. ds.tlRadius = ds.trRadius = ds.blRadius = ds.brRadius = _borderRect.cornerRadius;
  832. ds.drawShadow(g,
  833. calcX(_borderRect.x),
  834. calcY(_borderRect.y),
  835. _borderRect.width,
  836. _borderRect.height);
  837. // Draw the top line
  838. g.lineStyle(1,0xFFFFFF, .3);
  839. g.moveTo(calcX(_borderRect.x) + _borderRect.cornerRadius, calcY(_borderRect.y));
  840. g.lineTo(calcX(_borderRect.x) - _borderRect.cornerRadius + _borderRect.width, calcY(_borderRect.y));
  841. }
  842. /**
  843. * @private
  844. * Draws the progress bar.
  845. */
  846. private function drawProgressBar(percentage:Number):void
  847. {
  848. var g:Graphics = _barSprite.graphics;
  849. g.clear();
  850. var colors:Array = [ 0xFFFFFF, 0xFFFFFF ];
  851. var ratios:Array = [ 0, 0xFF ];
  852. var matrix:Matrix = new Matrix();
  853. // Middle
  854. var barWidth:Number = _barRect.width * percentage / 100;
  855. var barWidthSplit:Number = barWidth / 2;
  856. var barHeight:Number = _barRect.height-4;
  857. var barX:Number = calcX(_barRect.x);
  858. var barY:Number = calcY(_barRect.y) + 2;
  859. var barY2:Number;
  860. matrix.createGradientBox(barWidthSplit, barHeight,
  861. 0, barX, barY);
  862. g.beginGradientFill(GradientType.LINEAR, colors, [ .39, .85],
  863. ratios, matrix);
  864. g.drawRect(barX, barY, barWidthSplit, barHeight);
  865. matrix.createGradientBox(barWidthSplit, barHeight,
  866. 0, barX + barWidthSplit, barY);
  867. g.beginGradientFill(GradientType.LINEAR, colors, [.85, 1.0],
  868. ratios, matrix);
  869. g.drawRect(barX + barWidthSplit, barY, barWidthSplit, barHeight);
  870. // Outer highlight
  871. barWidthSplit = barWidth / 3;
  872. barHeight = _barRect.height;
  873. barY = calcY(_barRect.y);
  874. barY2 = barY + barHeight - 1;
  875. matrix.createGradientBox(barWidthSplit, barHeight,
  876. 0, barX, barY);
  877. g.beginGradientFill(GradientType.LINEAR, colors, [ .05, .15],
  878. ratios, matrix);
  879. g.drawRect(barX, barY, barWidthSplit, 1);
  880. g.drawRect(barX, barY2, barWidthSplit, 1);
  881. matrix.createGradientBox(barWidthSplit, barHeight,
  882. 0, barX + barWidthSplit, barY);
  883. g.beginGradientFill(GradientType.LINEAR, colors, [ .15, .25],
  884. ratios, matrix);
  885. g.drawRect(barX + barWidthSplit, barY, barWidthSplit, 1);
  886. g.drawRect(barX + barWidthSplit, barY2, barWidthSplit, 1);
  887. matrix.createGradientBox(barWidthSplit, barHeight,
  888. 0, barX + barWidthSplit * 2, barY);
  889. g.beginGradientFill(GradientType.LINEAR, colors, [ .25, .1],
  890. ratios, matrix);
  891. g.drawRect(barX + barWidthSplit * 2, barY, barWidthSplit, 1);
  892. g.drawRect(barX + barWidthSplit * 2, barY2, barWidthSplit, 1);
  893. // Inner highlight
  894. barWidthSplit = barWidth / 3;
  895. barHeight = _barRect.height;
  896. barY = calcY(_barRect.y) + 1;
  897. barY2 = calcY(_barRect.y) + barHeight - 2;
  898. matrix.createGradientBox(barWidthSplit, barHeight,
  899. 0, barX, barY);
  900. g.beginGradientFill(GradientType.LINEAR, colors, [ .15, .30],
  901. ratios, matrix);
  902. g.drawRect(barX, barY, barWidthSplit, 1);
  903. g.drawRect(barX, barY2, barWidthSplit, 1);
  904. matrix.createGradientBox(barWidthSplit, barHeight,
  905. 0, barX + barWidthSplit, barY);
  906. g.beginGradientFill(GradientType.LINEAR, colors, [ .30, .40],
  907. ratios, matrix);
  908. g.drawRect(barX + barWidthSplit, barY, barWidthSplit, 1);
  909. g.drawRect(barX + barWidthSplit, barY2, barWidthSplit, 1);
  910. matrix.createGradientBox(barWidthSplit, barHeight,
  911. 0, barX + barWidthSplit * 2, barY);
  912. g.beginGradientFill(GradientType.LINEAR, colors, [ .40, .25],
  913. ratios, matrix);
  914. g.drawRect(barX + barWidthSplit * 2, barY, barWidthSplit, 1);
  915. g.drawRect(barX + barWidthSplit * 2, barY2, barWidthSplit, 1);
  916. }
  917. /**
  918. * Updates the display of the download progress bar
  919. * with the current download information.
  920. * A typical implementation divides the loaded value by the total value
  921. * and displays a percentage.
  922. * If you do not implement this method, you should create
  923. * a progress bar that displays an animation to indicate to the user
  924. * that a download is occurring.
  925. *
  926. * <p>The <code>setProgress()</code> method is only called
  927. * if the application is being downloaded from a remote server
  928. * and the application is not in the browser cache.</p>
  929. *
  930. * @param completed Number of bytes of the application SWF file
  931. * that have been downloaded.
  932. *
  933. * @param total Size of the application SWF file in bytes.
  934. */
  935. protected function setProgress(completed:Number, total:Number):void
  936. {
  937. if (!isNaN(completed) &&
  938. !isNaN(total) &&
  939. completed >= 0 &&
  940. total > 0)
  941. {
  942. _value = Number(completed);
  943. _maximum = Number(total);
  944. draw();
  945. }
  946. }
  947. /**
  948. * Returns the percentage value of the application loaded.
  949. *
  950. * @param loaded Number of bytes of the application SWF file
  951. * that have been downloaded.
  952. *
  953. * @param total Size of the application SWF file in bytes.
  954. *
  955. * @return The percentage value of the loaded application.
  956. */
  957. protected function getPercentLoaded(loaded:Number, total:Number):Number
  958. {
  959. var perc:Number;
  960. if (loaded == 0 || total == 0 || isNaN(total) || isNaN(loaded))
  961. return 0;
  962. else
  963. perc = 100 * loaded/total;
  964. if (isNaN(perc) || perc <= 0)
  965. return 0;
  966. else if (perc > 99)
  967. return 99;
  968. else
  969. return Math.round(perc);
  970. }
  971. /**
  972. * @private
  973. * Make the display class visible.
  974. */
  975. private function show():void
  976. {
  977. _showingDisplay = true;
  978. calcScale();
  979. draw();
  980. _displayTime = getTimer(); // Time when the display is shown.
  981. }
  982. /**
  983. * @private
  984. */
  985. private function hide():void
  986. {
  987. }
  988. /**
  989. * @private
  990. */
  991. private function calcX(base:Number):Number
  992. {
  993. return base + _xOffset;
  994. }
  995. /**
  996. * @private
  997. */
  998. private function calcY(base:Number):Number
  999. {
  1000. return base + _yOffset;
  1001. }
  1002. /**
  1003. * @private
  1004. * Figure out the scale for the display class based on the stage size.
  1005. * Then creates the children subcomponents.
  1006. */
  1007. private function calcScale():void
  1008. {
  1009. if (stageWidth < 160 || stageHeight < 120)
  1010. {
  1011. scaleX = 1.0;
  1012. scaleY = 1.0;
  1013. }
  1014. else if (stageWidth < 240 || stageHeight < 150)
  1015. {
  1016. // Scale to appropriate size
  1017. createChildren();
  1018. var scale:Number = Math.min(stageWidth / 240.0,
  1019. stageHeight / 150.0);
  1020. scaleX = scale;
  1021. scaleY = scale;
  1022. }
  1023. else
  1024. {
  1025. createChildren();
  1026. }
  1027. }
  1028. /**
  1029. * Defines the algorithm for determining whether to show
  1030. * the download progress bar while in the download phase.
  1031. *
  1032. * @param elapsedTime number of milliseconds that have elapsed
  1033. * since the start of the download phase.
  1034. *
  1035. * @param event The ProgressEvent object that contains
  1036. * the <code>bytesLoaded</code> and <code>bytesTotal</code> properties.
  1037. *
  1038. * @return If the return value is <code>true</code>, then show the
  1039. * download progress bar.
  1040. * The default behavior is to show the download progress bar
  1041. * if more than 700 milliseconds have elapsed
  1042. * and if Flex has downloaded less than half of the bytes of the SWF file.
  1043. */
  1044. protected function showDisplayForDownloading(elapsedTime:int,
  1045. event:ProgressEvent):Boolean
  1046. {
  1047. return elapsedTime > 700 &&
  1048. event.bytesLoaded < event.bytesTotal / 2;
  1049. }
  1050. /**
  1051. * Defines the algorithm for determining whether to show the download progress bar
  1052. * while in the initialization phase, assuming that the display
  1053. * is not currently visible.
  1054. *
  1055. * @param elapsedTime number of milliseconds that have elapsed
  1056. * since the start of the download phase.
  1057. *
  1058. * @param count number of times that the <code>initProgress</code> event
  1059. * has been received from the application.
  1060. *
  1061. * @return If <code>true</code>, then show the download progress bar.
  1062. */
  1063. protected function showDisplayForInit(elapsedTime:int, count:int):Boolean
  1064. {
  1065. return elapsedTime > 300 && count == 2;
  1066. }
  1067. /**
  1068. * @private
  1069. */
  1070. private function loadBackgroundImage(classOrString:Object):void
  1071. {
  1072. var cls:Class;
  1073. // The "as" operator checks to see if classOrString
  1074. // can be coerced to a Class
  1075. if (classOrString && classOrString as Class)
  1076. {
  1077. // Load background image given a class pointer
  1078. cls = Class(classOrString);
  1079. initBackgroundImage(new cls());
  1080. }
  1081. else if (classOrString && classOrString is String)
  1082. {
  1083. try
  1084. {
  1085. cls = Class(getDefinitionByName(String(classOrString)));
  1086. }
  1087. catch(e:Error)
  1088. {
  1089. // ignore
  1090. }
  1091. if (cls)
  1092. {
  1093. var newStyleObj:DisplayObject = new cls();
  1094. initBackgroundImage(newStyleObj);
  1095. }
  1096. else
  1097. {
  1098. // Loading the image is slightly different
  1099. // than in Loader.loadContent()... is this on purpose?
  1100. // Load background image from external URL
  1101. var loader:Loader = new Loader();
  1102. loader.contentLoaderInfo.addEventListener(
  1103. Event.COMPLETE, loader_completeHandler);
  1104. loader.contentLoaderInfo.addEventListener(
  1105. IOErrorEvent.IO_ERROR, loader_ioErrorHandler);
  1106. var loaderContext:LoaderContext = new LoaderContext();
  1107. loaderContext.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);
  1108. loader.load(new URLRequest(String(classOrString)), loaderContext);
  1109. }
  1110. }
  1111. }
  1112. /**
  1113. * @private
  1114. */
  1115. private function initBackgroundImage(image:DisplayObject):void
  1116. {
  1117. addChildAt(image,0);
  1118. var backgroundImageWidth:Number = image.width;
  1119. var backgroundImageHeight:Number = image.height;
  1120. // Scale according to backgroundSize
  1121. var percentage:Number = calcBackgroundSize();
  1122. if (isNaN(percentage))
  1123. {
  1124. var sX:Number = 1.0;
  1125. var sY:Number = 1.0;
  1126. }
  1127. else
  1128. {
  1129. var scale:Number = percentage * 0.01;
  1130. sX = scale * stageWidth / backgroundImageWidth;
  1131. sY = scale * stageHeight / backgroundImageHeight;
  1132. }
  1133. image.scaleX = sX;
  1134. image.scaleY = sY;
  1135. // Center everything.
  1136. // Use a scrollRect to position and clip the image.
  1137. var offsetX:Number =
  1138. Math.round(0.5 * (stageWidth - backgroundImageWidth * sX));
  1139. var offsetY:Number =
  1140. Math.round(0.5 * (stageHeight - backgroundImageHeight * sY));
  1141. image.x = offsetX;
  1142. image.y = offsetY;
  1143. // Adjust alpha to match backgroundAlpha
  1144. if (!isNaN(backgroundAlpha))
  1145. image.alpha = backgroundAlpha;
  1146. }
  1147. /**
  1148. * @private
  1149. */
  1150. private function calcBackgroundSize():Number
  1151. {
  1152. var percentage:Number = NaN;
  1153. if (backgroundSize)
  1154. {
  1155. var index:int = backgroundSize.indexOf("%");
  1156. if (index != -1)
  1157. percentage = Number(backgroundSize.substr(0, index));
  1158. }
  1159. return percentage;
  1160. }
  1161. //--------------------------------------------------------------------------
  1162. //
  1163. // Event handlers
  1164. //
  1165. //--------------------------------------------------------------------------
  1166. /**
  1167. * Event listener for the <code>ProgressEvent.PROGRESS</code> event.
  1168. * This implementation updates the progress bar
  1169. * with the percentage of bytes downloaded.
  1170. *
  1171. * @param event The event object.
  1172. */
  1173. protected function progressHandler(event:ProgressEvent):void
  1174. {
  1175. var loaded:uint = event.bytesLoaded;
  1176. var total:uint = event.bytesTotal;
  1177. var elapsedTime:int = getTimer() - _startTime;
  1178. // Only show the Loading phase if it will appear for awhile.
  1179. if (_showingDisplay || showDisplayForDownloading(elapsedTime, event))
  1180. {
  1181. if (!_startedLoading)
  1182. {
  1183. show();
  1184. label = downloadingLabel;
  1185. _startedLoading = true;
  1186. }
  1187. setProgress(event.bytesLoaded, event.bytesTotal);
  1188. }
  1189. }
  1190. /**
  1191. * Event listener for the <code>Event.COMPLETE</code> event.
  1192. * The default implementation does nothing.
  1193. *
  1194. * @param event The event object.
  1195. */
  1196. protected function completeHandler(event:Event):void
  1197. {
  1198. }
  1199. /**
  1200. * Event listener for the <code>RSLEvent.RSL_PROGRESS</code> event.
  1201. * The default implementation does nothing.
  1202. *
  1203. * @param event The event object.
  1204. */
  1205. protected function rslProgressHandler(event:RSLEvent):void
  1206. {
  1207. }
  1208. /**
  1209. * Event listener for the <code>RSLEvent.RSL_COMPLETE</code> event.
  1210. *
  1211. * @param event The event object.
  1212. */
  1213. protected function rslCompleteHandler(event:RSLEvent):void
  1214. {
  1215. label = "Loaded library " + event.rslIndex + " of " + event.rslTotal;
  1216. }
  1217. /**
  1218. * Event listener for the <code>RSLEvent.RSL_ERROR</code> event.
  1219. * This event listner handles any errors detected when downloading an RSL.
  1220. *
  1221. * @param event The event object.
  1222. */
  1223. protected function rslErrorHandler(event:RSLEvent):void
  1224. {
  1225. _preloader.removeEventListener(ProgressEvent.PROGRESS,
  1226. progressHandler);
  1227. _preloader.removeEventListener(Event.COMPLETE,
  1228. completeHandler);
  1229. _preloader.removeEventListener(RSLEvent.RSL_PROGRESS,
  1230. rslProgressHandler);
  1231. _preloader.removeEventListener(RSLEvent.RSL_COMPLETE,
  1232. rslCompleteHandler);
  1233. _preloader.removeEventListener(RSLEvent.RSL_ERROR,
  1234. rslErrorHandler);
  1235. _preloader.removeEventListener(FlexEvent.INIT_PROGRESS,
  1236. initProgressHandler);
  1237. _preloader.removeEventListener(FlexEvent.INIT_COMPLETE,
  1238. initCompleteHandler);
  1239. if (!_showingDisplay)
  1240. {
  1241. show();
  1242. _showingDisplay = true;
  1243. }
  1244. label = "RSL Error " + (event.rslIndex + 1) + " of " + event.rslTotal;
  1245. var errorField:ErrorField = new ErrorField(this);
  1246. errorField.show(event.errorText);
  1247. }
  1248. /**
  1249. * @private
  1250. * Helper function that dispatches the Complete event to the preloader.
  1251. *
  1252. * @param event The event object.
  1253. */
  1254. private function timerHandler(event:Event = null):void
  1255. {
  1256. dispatchEvent(new Event(Event.COMPLETE));
  1257. }
  1258. /**
  1259. * Event listener for the <code>FlexEvent.INIT_PROGRESS</code> event.
  1260. * This implementation updates the progress bar
  1261. * each time the event is dispatched, and changes the text of the label.
  1262. *
  1263. * @param event The event object.
  1264. */
  1265. protected function initProgressHandler(event:Event):void
  1266. {
  1267. var elapsedTime:int = getTimer() - _startTime;
  1268. _initProgressCount++;
  1269. if (!_showingDisplay &&
  1270. showDisplayForInit(elapsedTime, _initProgressCount))
  1271. {
  1272. _displayStartCount = _initProgressCount;
  1273. show();
  1274. }
  1275. else if (_showingDisplay)
  1276. {
  1277. if (!_startedInit)
  1278. {
  1279. // First init progress event.
  1280. _startedInit = true;
  1281. label = initializingLabel;
  1282. }
  1283. var loaded:Number = 100 * _initProgressCount /
  1284. (_initProgressTotal - _displayStartCount);
  1285. setProgress(loaded, 100);
  1286. }
  1287. }
  1288. /**
  1289. * @private
  1290. */
  1291. private function initCompleteHandler(event:Event):void
  1292. {
  1293. var elapsedTime:int = getTimer() - _displayTime;
  1294. if (_showingDisplay && elapsedTime < MINIMUM_DISPLAY_TIME)
  1295. {
  1296. var timer:Timer = new Timer(MINIMUM_DISPLAY_TIME - elapsedTime, 1);
  1297. timer.addEventListener(TimerEvent.TIMER, timerHandler);
  1298. timer.start();
  1299. }
  1300. else
  1301. {
  1302. timerHandler();
  1303. }
  1304. }
  1305. /**
  1306. * @private
  1307. */
  1308. private function loader_completeHandler(event:Event):void
  1309. {
  1310. var target:DisplayObject = DisplayObject(LoaderInfo(event.target).loader);
  1311. initBackgroundImage(target);
  1312. }
  1313. private function loader_ioErrorHandler(event:IOErrorEvent):void
  1314. {
  1315. // Swallow the error
  1316. }
  1317. }
  1318. }
  1319. import flash.display.DisplayObject;
  1320. import flash.display.Sprite;
  1321. import flash.text.TextField;
  1322. import flash.text.TextFormat;
  1323. import flash.system.Capabilities;
  1324. import flash.text.TextFieldAutoSize;
  1325. import flash.display.DisplayObjectContainer;
  1326. import flash.display.Stage;
  1327. import mx.preloaders.DownloadProgressBar;
  1328. //--------------------------------------------------------------------------
  1329. //
  1330. // Constructor
  1331. //
  1332. //--------------------------------------------------------------------------
  1333. /**
  1334. * @private
  1335. *
  1336. * Area to display error messages to help debug startup problems.
  1337. *
  1338. */
  1339. class ErrorField extends Sprite
  1340. {
  1341. private var downloadProgressBar:DownloadProgressBar;
  1342. private const MIN_WIDTH_INCHES:int = 2; // min width of error message in inches
  1343. private const MAX_WIDTH_INCHES:int = 6; // max width of error message in inches
  1344. private const TEXT_MARGIN_PX:int = 10;
  1345. //----------------------------------
  1346. // labelFormat
  1347. //----------------------------------
  1348. /**
  1349. * The TextFormat object of the TextField component of the label.
  1350. * This is a read-only property which you must override
  1351. * if you need to change it.
  1352. */
  1353. protected function get labelFormat():TextFormat
  1354. {
  1355. var tf:TextFormat = new TextFormat();
  1356. tf.color = 0x000000;
  1357. tf.font = "Verdana";
  1358. tf.size = 10;
  1359. return tf;
  1360. }
  1361. /**
  1362. * @private
  1363. *
  1364. * @param - parent - parent of the error field.
  1365. */
  1366. public function ErrorField(downloadProgressBar:DownloadProgressBar)
  1367. {
  1368. super();
  1369. this.downloadProgressBar = downloadProgressBar;
  1370. }
  1371. /**
  1372. * Create and show the error message.
  1373. *
  1374. * @param errorText - text for error message.
  1375. */
  1376. public function show(errorText:String):void
  1377. {
  1378. if (errorText == null || errorText.length == 0)
  1379. return;
  1380. var screenWidth:Number = downloadProgressBar.stageWidth;
  1381. var screenHeight:Number = downloadProgressBar.stageHeight;
  1382. // create the text field for the message and
  1383. // add it to the parent.
  1384. var textField:TextField = new TextField();
  1385. textField.autoSize = TextFieldAutoSize.LEFT;
  1386. textField.multiline = true;
  1387. textField.wordWrap = true;
  1388. textField.background = true;
  1389. textField.defaultTextFormat = labelFormat;
  1390. textField.text = errorText;
  1391. textField.width = Math.max(MIN_WIDTH_INCHES * Capabilities.screenDPI, screenWidth - (TEXT_MARGIN_PX * 2));
  1392. textField.width = Math.min(MAX_WIDTH_INCHES * Capabilities.screenDPI, textField.width);
  1393. textField.y = Math.max(0, screenHeight - TEXT_MARGIN_PX - textField.height);
  1394. // center field horizontally
  1395. textField.x = (screenWidth - textField.width) / 2;
  1396. downloadProgressBar.parent.addChild(this);
  1397. this.addChild(textField);
  1398. }
  1399. }