/sandbox/chart/as/com/yahoo/renderers/ImageSkin.as

https://github.com/nonano/yui3 · ActionScript · 363 lines · 227 code · 32 blank · 104 comment · 33 complexity · 03be4fc62e33b3f228fe34fb6688490d MD5 · raw file

  1. package com.yahoo.renderers
  2. {
  3. import flash.display.Loader;
  4. import flash.display.Shape;
  5. import flash.display.Sprite;
  6. import flash.display.BitmapData;
  7. import flash.events.Event;
  8. import flash.events.HTTPStatusEvent;
  9. import flash.events.IOErrorEvent;
  10. import flash.events.ProgressEvent;
  11. import flash.net.URLRequest;
  12. import flash.system.LoaderContext;
  13. import flash.events.SecurityErrorEvent;
  14. import com.yahoo.renderers.Renderer;
  15. import com.yahoo.renderers.events.RendererEvent;
  16. import com.yahoo.renderers.styles.ImageSkinStyles;
  17. /**
  18. * Creates background using externally loaded image.
  19. */
  20. public class ImageSkin extends Renderer
  21. {
  22. /**
  23. * @inheritDoc
  24. */
  25. private static var _styleClass:Class = ImageSkinStyles;
  26. /**
  27. * Constructor
  28. */
  29. public function ImageSkin()
  30. {
  31. super();
  32. this._container = new Sprite();
  33. this.addChild(this._container);
  34. this._mask = new Shape();
  35. this.addChild(this._mask);
  36. this.mask = this._mask;
  37. }
  38. /**
  39. * @inheritDoc
  40. */
  41. override public function getStyleClass():Class
  42. {
  43. return _styleClass;
  44. }
  45. /**
  46. * @private
  47. */
  48. private var _container:Sprite;
  49. /**
  50. * @private
  51. */
  52. private var _mask:Shape;
  53. /**
  54. * @private
  55. * Reference to loader instance
  56. */
  57. private var _loader:Loader;
  58. /**
  59. * @private
  60. * Storage for urlRequest
  61. */
  62. private var _urlRequest:URLRequest;
  63. /**
  64. * URL request object for loader.
  65. */
  66. public function get urlRequest():URLRequest
  67. {
  68. return this._urlRequest;
  69. }
  70. /**
  71. * @private(setter)
  72. */
  73. public function set urlRequest(value:URLRequest):void
  74. {
  75. if(this.urlRequest === value) return;
  76. this._urlRequest = value;
  77. this.url = this._urlRequest.url;
  78. this.setFlag("load");
  79. }
  80. /**
  81. * @private
  82. * Storage for image url
  83. */
  84. private var _url:String;
  85. /**
  86. * Url for the image
  87. */
  88. public function get url():String
  89. {
  90. return this._url;
  91. }
  92. /**
  93. * @private (setter)
  94. */
  95. public function set url(value:String):void
  96. {
  97. if(this._url == value) return;
  98. this._url = value;
  99. this._urlRequest = new URLRequest(value);
  100. this.setFlag("load");
  101. }
  102. /**
  103. * @private
  104. * Storage for loaderContext
  105. */
  106. private var _context:LoaderContext;
  107. /**
  108. * The <code>loaderContext</code> for the loader.
  109. */
  110. public function get context():LoaderContext
  111. {
  112. return this._context;
  113. }
  114. /**
  115. * @private (setter)
  116. */
  117. public function set context(value:LoaderContext):void
  118. {
  119. if(this.context == value) return;
  120. this._context = value;
  121. this.setFlag("load");
  122. }
  123. /**
  124. * @private
  125. * The actual width of the loaded content.
  126. */
  127. private var _contentWidth:Number;
  128. /**
  129. * @private
  130. * The actual height of the loaded content.
  131. */
  132. private var _contentHeight:Number;
  133. /**
  134. * @private (override)
  135. */
  136. override public function setStyles(styles:Object):void
  137. {
  138. if(styles.hasOwnProperty("url"))
  139. {
  140. this.url = styles.url;
  141. }
  142. super.setStyles(styles);
  143. }
  144. /**
  145. * @private (override)
  146. */
  147. override public function setStyle(style:String, value:Object):Boolean
  148. {
  149. if(style === "url")
  150. {
  151. this.url = String(value);
  152. return true;
  153. }
  154. return super.setStyle(style, value);
  155. }
  156. /**
  157. * @inheritDoc
  158. */
  159. override protected function render():void
  160. {
  161. if(this.checkFlag("resize") || this.checkFlag("sizeMode")) this.drawMask();
  162. if(this.checkFlag("load"))
  163. {
  164. this.loadImage();
  165. return;
  166. }
  167. if(this.checkFlag("resize") || this.checkFlag("imageMode") || this.checkFlag("imageLoaded") || this.checkFlag("sizeMode"))
  168. {
  169. var imageMode:String = this.getStyle("imageMode") as String;
  170. var wid:Number = this.width;
  171. var ht:Number = this.height;
  172. switch(imageMode)
  173. {
  174. case "stretch" :
  175. this._container.width = wid;
  176. this._container.height = ht;
  177. if(this._loader) this._loader.visible = true;
  178. break;
  179. case "stretchAndMaintainAspectRatio" :
  180. var containerRatio:Number = wid/ht;
  181. var imageRatio:Number = this._contentWidth/this._contentHeight;
  182. if(containerRatio > imageRatio)
  183. {
  184. this._container.height = wid/imageRatio;
  185. this._container.width = wid;
  186. }
  187. else
  188. {
  189. this._container.height = ht;
  190. this._container.width = ht * imageRatio;
  191. }
  192. if(this._loader) this._loader.visible = true;
  193. break;
  194. default :
  195. var rectWidth:Number = this._contentWidth;
  196. var rectHeight:Number = this._contentHeight;
  197. if(imageMode == "repeat-x")
  198. {
  199. rectWidth = this.width;
  200. }
  201. else if(imageMode == "repeat-y")
  202. {
  203. rectHeight = this.height;
  204. }
  205. else if(imageMode == "repeat")
  206. {
  207. rectHeight = this.height;
  208. rectWidth = this.width;
  209. }
  210. if(this._loader)
  211. {
  212. this._loader.visible = false;
  213. if(this._contentWidth > 0 && this._contentHeight > 0)
  214. {
  215. var bitmapData:BitmapData = new BitmapData(int(this._contentWidth), int(this._contentHeight), true, 0x000000);
  216. bitmapData.draw(this._loader);
  217. this.graphics.lineStyle(0, 0, 0);
  218. this.graphics.beginBitmapFill(bitmapData);
  219. this.graphics.drawRect(0, 0, rectWidth, rectHeight);
  220. this.graphics.endFill();
  221. }
  222. }
  223. break;
  224. }
  225. }
  226. }
  227. /**
  228. * @private
  229. */
  230. private function drawMask():void
  231. {
  232. if(!this._mask || isNaN(this.width) || isNaN(this.height)) return;
  233. this._mask.graphics.clear();
  234. this._mask.graphics.beginFill(0xffffff, 1);
  235. this._mask.graphics.drawRect(0, 0, this.width, this.height);
  236. this._mask.graphics.endFill();
  237. }
  238. /**
  239. * @private
  240. * Sets up loader
  241. */
  242. private function loadImage():void
  243. {
  244. this.unload();
  245. this._loader = new Loader();
  246. this._loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, this.loaderErrorHandler, false, 0, true);
  247. this._loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this.loaderErrorHandler, false, 0, true);
  248. this._loader.contentLoaderInfo.addEventListener(Event.OPEN, this.loaderOpenHandler, false, 0, true);
  249. this._loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, this.loaderProgressHandler, false, 0, true);
  250. this._loader.contentLoaderInfo.addEventListener(Event.COMPLETE, this.loaderCompleteHandler, false, 0, true);
  251. this._loader.contentLoaderInfo.addEventListener(Event.INIT, this.loaderInitHandler, false, 0, true);
  252. this._loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, this.loaderHTTPStatusHandler, false, 0, true);
  253. this._loader.load(this.urlRequest, this.context);
  254. this._container.addChild(this._loader);
  255. this._loader.visible = false;
  256. }
  257. /**
  258. * @private
  259. */
  260. private function unload():void
  261. {
  262. if(this._loader != null)
  263. {
  264. this._loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, this.loaderErrorHandler);
  265. this._loader.contentLoaderInfo.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.loaderErrorHandler);
  266. this._loader.contentLoaderInfo.removeEventListener(Event.OPEN, this.loaderOpenHandler);
  267. this._loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, this.loaderProgressHandler);
  268. this._loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, this.loaderCompleteHandler);
  269. this._loader.contentLoaderInfo.removeEventListener(Event.INIT, this.loaderInitHandler);
  270. this._loader.contentLoaderInfo.removeEventListener(HTTPStatusEvent.HTTP_STATUS, this.loaderHTTPStatusHandler);
  271. this._loader.unload();
  272. this._container.removeChild(this._loader);
  273. this._loader = null;
  274. }
  275. }
  276. /**
  277. * @private
  278. */
  279. private function loaderErrorHandler(event:Event):void
  280. {
  281. //placeholder for error events.
  282. }
  283. /**
  284. * @private
  285. */
  286. private function loaderOpenHandler(event:Event):void
  287. {
  288. //placeholder for open event
  289. }
  290. /**
  291. * @private
  292. */
  293. private function loaderProgressHandler(event:ProgressEvent):void
  294. {
  295. //placeholder for progress event
  296. }
  297. /**
  298. * @private
  299. */
  300. private function loaderCompleteHandler(event:Event):void
  301. {
  302. try
  303. {
  304. this._contentWidth = this._loader.content.width;
  305. this._contentHeight = this._loader.content.height;
  306. this.dispatchEvent(event);
  307. this.setFlag("imageLoaded");
  308. }
  309. catch(e:SecurityError)
  310. {
  311. this.unload();
  312. //handle security error event. I'm thinking will dispatch error events and the application class will listen
  313. //and dispatch out logs
  314. }
  315. }
  316. /**
  317. * @private
  318. */
  319. private function loaderInitHandler(event:Event):void
  320. {
  321. //placeholder for init event
  322. }
  323. /**
  324. * @private
  325. */
  326. private function loaderHTTPStatusHandler(event:HTTPStatusEvent):void
  327. {
  328. //placeholder for HTTPStatus event
  329. }
  330. }
  331. }