PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/axiis/src/org/axiis/DataCanvas.as

http://axiis.googlecode.com/
ActionScript | 389 lines | 190 code | 73 blank | 126 comment | 27 complexity | d473bf9a40f95ddee4d505ce8aa759d7 MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) 2009 Team Axiis
  3. //
  4. // Permission is hereby granted, free of charge, to any person
  5. // obtaining a copy of this software and associated documentation
  6. // files (the "Software"), to deal in the Software without
  7. // restriction, including without limitation the rights to use,
  8. // copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following
  11. // conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. // OTHER DEALINGS IN THE SOFTWARE.
  24. ///////////////////////////////////////////////////////////////////////////////
  25. package org.axiis
  26. {
  27. import com.degrafa.IGeometryComposition;
  28. import flash.display.Sprite;
  29. import flash.events.Event;
  30. import flash.events.MouseEvent;
  31. import mx.containers.Canvas;
  32. import mx.core.IFactory;
  33. import org.axiis.core.AbstractLayout;
  34. import org.axiis.core.AxiisSprite;
  35. import org.axiis.events.LayoutItemEvent;
  36. import org.axiis.managers.IDataTipManager;
  37. import org.axiis.ui.DataTip;
  38. /**
  39. * DataCanvas manages the placement and the rendering of layouts.
  40. */
  41. public class DataCanvas extends Canvas
  42. {
  43. [Bindable]
  44. /**
  45. * A placeholder for fills. Modifying this property has no
  46. * effect on the rendering of the DataCanvas.
  47. */
  48. public var fills:Array = [];
  49. [Bindable]
  50. /**
  51. * A placeholder for strokes. Modifying this property has no
  52. * effect on the rendering of the DataCanvas.
  53. */
  54. public var strokes:Array = [];
  55. [Bindable]
  56. /**
  57. * A placeholder for palettes. Modifying this property has no
  58. * effect on the rendering of the DataCanvas.
  59. */
  60. public var palettes:Array = [];
  61. /**
  62. * Constructor.
  63. */
  64. public function DataCanvas()
  65. {
  66. super();
  67. }
  68. //TODO Do we need this on the DataCanvas level
  69. /**
  70. * @private
  71. */
  72. public var labelFunction:Function;
  73. //TODO Do we need this on the DataCanvas level
  74. /**
  75. * @private
  76. */
  77. public var dataFunction:Function;
  78. /**
  79. * Whether or not data tips should be shown when rolling the mouse over
  80. * items in the DataCanvas's layouts
  81. */
  82. public var showDataTips:Boolean = true;
  83. // TODO This is currently unused
  84. /**
  85. * @private
  86. */
  87. public var toolTipClass:IFactory;
  88. /**
  89. * @private
  90. */
  91. public var hitRadius:Number = 0;
  92. private var toolTips:Array = [];
  93. // TODO This isn't doing anything. We should cut it.
  94. [Bindable(event="dataProviderChange")]
  95. /**
  96. * A placeholder for data used by layouts managed by this DataCanvas.
  97. * Setting this value re-renders the layouts.
  98. */
  99. public function get dataProvider():Object
  100. {
  101. return _dataProvider;
  102. }
  103. public function set dataProvider(value:Object):void
  104. {
  105. if(value != _dataProvider)
  106. {
  107. _dataProvider = value;
  108. invalidateDisplayList();
  109. dispatchEvent(new Event("dataProviderChange"));
  110. }
  111. }
  112. private var _dataProvider:Object;
  113. /**
  114. * An Array of ILayouts that this DataCanvas should render. Layouts
  115. * appearing later in the array will render on top of earlier layouts.
  116. */
  117. public var layouts:Array;
  118. /**
  119. * An array of geometries that should be rendered behind the layouts.
  120. */
  121. public var backgroundGeometries:Array;
  122. /**
  123. * An array of geometries that should be rendered in front of the
  124. * layouts.
  125. */
  126. public var foregroundGeometries:Array;
  127. private var invalidatedLayouts:Array = [];
  128. private var _backgroundSprites:Array = [];
  129. private var _foregroundSprites:Array = [];
  130. private var _background:AxiisSprite;
  131. private var _foreground:AxiisSprite;
  132. /**
  133. * @private
  134. */
  135. override protected function createChildren():void
  136. {
  137. super.createChildren();
  138. _background=new AxiisSprite();
  139. this.rawChildren.addChild(_background);
  140. for each(var layout:AbstractLayout in layouts)
  141. {
  142. layout.registerOwner(this);
  143. var sprite:Sprite = layout.getSprite(this);
  144. this.rawChildren.addChild(sprite);
  145. layout.addEventListener("layoutInvalidate",handleLayoutInvalidate);
  146. layout.addEventListener("itemDataTip",onItemDataTip);
  147. invalidatedLayouts.push(layout);
  148. }
  149. _foreground=new AxiisSprite();
  150. this.rawChildren.addChild(_foreground);
  151. }
  152. /**
  153. * @private
  154. */
  155. override protected function commitProperties():void
  156. {
  157. super.commitProperties();
  158. var s:AxiisSprite;
  159. var i:int;
  160. if (backgroundGeometries && _backgroundSprites.length < backgroundGeometries.length) {
  161. for (i = _backgroundSprites.length-1; i<backgroundGeometries.length; i++) {
  162. s=new AxiisSprite();
  163. _backgroundSprites.push(s);
  164. _background.addChild(s);
  165. }
  166. }
  167. if (foregroundGeometries && _foregroundSprites.length < foregroundGeometries.length ) {
  168. for (i=_foregroundSprites.length-1; i<foregroundGeometries.length; i++) {
  169. s=new AxiisSprite();
  170. _foregroundSprites.push(s);
  171. _foreground.addChild(s);
  172. }
  173. }
  174. }
  175. private var _invalidated:Boolean=false;
  176. /**
  177. * @private
  178. */
  179. override public function invalidateDisplayList():void
  180. {
  181. if (!_invalidated)
  182. invalidateAllLayouts();
  183. _invalidated = true;
  184. }
  185. /**
  186. * @private
  187. */
  188. override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
  189. {
  190. super.updateDisplayList(unscaledWidth,unscaledHeight);
  191. //Render layouts first, as they may autoadjust Scales, etc that the background/foreground rely upon
  192. while(invalidatedLayouts.length > 0)
  193. {
  194. var layout:AbstractLayout = AbstractLayout(invalidatedLayouts.pop());
  195. layout.render();
  196. }
  197. _background.graphics.clear();
  198. var i:int=0;
  199. for each (var bg:Object in backgroundGeometries) {
  200. _backgroundSprites[i].graphics.clear();
  201. if (bg is AbstractLayout) {
  202. AbstractLayout(bg).render(_backgroundSprites[i])
  203. }
  204. else if (bg is IGeometryComposition) {
  205. bg.preDraw();
  206. bg.draw(_backgroundSprites[i].graphics,bg.bounds);
  207. }
  208. i++;
  209. }
  210. i=0;
  211. _foreground.graphics.clear();
  212. for each (var fg:Object in foregroundGeometries) {
  213. _foregroundSprites[i].graphics.clear();
  214. if (fg is AbstractLayout) {
  215. AbstractLayout(fg).render(_foregroundSprites[i])
  216. }
  217. else if (fg is IGeometryComposition) {
  218. fg.preDraw();
  219. fg.draw(_foregroundSprites[i].graphics,fg.bounds);
  220. }
  221. i++;
  222. }
  223. /* this.graphics.clear();
  224. this.graphics.beginFill(0xff,.1);
  225. this.graphics.drawRect(0,0,width,height);
  226. this.graphics.endFill(); */
  227. _invalidated = false;
  228. }
  229. /**
  230. * Handler for when a layout's layoutInvalidated event has been caught.
  231. * Invalidates the display list so the layout can be re-rendered.
  232. */
  233. protected function handleLayoutInvalidate(event:Event):void
  234. {
  235. var layout:AbstractLayout = event.target as AbstractLayout;
  236. if(invalidatedLayouts.indexOf(layout) == -1)
  237. {
  238. invalidatedLayouts.push(layout);
  239. super.invalidateDisplayList();
  240. }
  241. }
  242. /**
  243. * Invalidates all layouts that this DataCanvas managers.
  244. */
  245. protected function invalidateAllLayouts():void
  246. {
  247. for each(var layout:AbstractLayout in layouts)
  248. {
  249. invalidatedLayouts.push(layout);
  250. }
  251. super.invalidateDisplayList();
  252. }
  253. /**
  254. * @private
  255. */
  256. private function onItemDataTip(e:LayoutItemEvent):void
  257. {
  258. var dataTips:Array=new Array();
  259. //var axiisSprite:AxiisSprite = AxiisSprite(targetObject);
  260. var axiisSprite:AxiisSprite = e.item;
  261. if(axiisSprite.layout == null)
  262. return;
  263. var axiisSprites:Array=getHitSiblings(axiisSprite);
  264. for each (var a:AxiisSprite in axiisSprites) {
  265. var dataTip:DataTip = new DataTip();
  266. dataTip.data = axiisSprite.data;
  267. if(axiisSprite.layout.dataTipLabelFunction != null)
  268. dataTip.label = axiisSprite.layout.dataTipLabelFunction(axiisSprite);
  269. else
  270. dataTip.label = axiisSprite.label;
  271. dataTip.value = axiisSprite.value;
  272. dataTip.index = axiisSprite.index;
  273. dataTip.backgroundFill=e.item.layout.dataTipFill;
  274. dataTip.backgroundStroke=e.item.layout.dataTipStroke;
  275. dataTip.contentComponent = axiisSprite.layout.dataTipContentComponent;
  276. //This seems weird, why does axxisSprite need to know about the dataTipContent class?
  277. //Not sure a factory pattern is what we want here
  278. dataTip.contentFactory = axiisSprite.dataTipContentClass;
  279. dataTips.push(dataTip);
  280. }
  281. var dataTipManager:IDataTipManager=axiisSprite.layout.dataTipManager;
  282. dataTipManager.createDataTip(dataTips,this,axiisSprite);
  283. }
  284. /**
  285. * @private
  286. */
  287. public function onItemMouseOut(e:MouseEvent):void
  288. {
  289. var axiisSprite:AxiisSprite = e.target as AxiisSprite;
  290. if(!axiisSprite)
  291. return;
  292. }
  293. private function getHitSiblings(axiisSprite:AxiisSprite):Array
  294. {
  295. var toReturn:Array = [];
  296. toReturn.push(axiisSprite);
  297. /*
  298. var s:Sprite = new Sprite();
  299. s.graphics.clear();
  300. s.graphics.beginFill(0,0);
  301. s.graphics.drawCircle(mouseX,mouseY,hitRadius);
  302. s.graphics.endFill();
  303. addChild(s);
  304. */
  305. /*var siblings:Array = axiisSprite.layout.childSprites;
  306. for each(var sibling:AxiisSprite in siblings)
  307. {
  308. if(sibling.hitTestObject(s))
  309. {
  310. toReturn.push(sibling);
  311. }
  312. }*/
  313. return toReturn;
  314. }
  315. }
  316. }