PageRenderTime 58ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/examples/FlexDemo/src/framework/display/ElementBase.as

https://github.com/talltyler/ASTRID
ActionScript | 507 lines | 396 code | 53 blank | 58 comment | 113 complexity | ce5afe4f879907449946678eda08c3df MD5 | raw file
  1. /* ,----,
  2. * ,/ .`|
  3. * ,---, .--.--. ,` .' :,-.----. ,---, ,---,
  4. * ' .' \ / / '. ; ; /\ / \ ,`--.' | .' .' `\
  5. * / ; '. | : /`. /.'___,/ ,' ; : \ | : :,---.' \
  6. * : : \ ; | |--` | : | | | .\ : : | '| | .`\ |
  7. * : | /\ \| : ;_ ; |.'; ; . : |: | | : |: : | ' |
  8. * | : ' ;. :\ \ `.`----' | | | | \ : ' ' ;| ' ' ; :
  9. * | | ;/ \ \`----. \ ' : ; | : . / | | |' | ; . |
  10. * ' : | \ \ ,'__ \ \ | | | ' ; | | \ ' : ;| | : | '
  11. * | | ' '--' / /`--' / ' : | | | ;\ \| | '' : | / ;
  12. * | : : '--'. / ; |.' : ' | \.'' : || | '` ,/
  13. * | | ,' `--'---' '---' : : :-' ; |.' ; : .'
  14. * `--'' | |.' '---' | ,.' Tyler
  15. * ActionScript tested rapid iterative dev `---' Copyright2010'---' Larson
  16. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  17. * This program is free software: you can redistribute it and/or modify
  18. * it under the terms of the GNU General Public License as published by
  19. * the Free Software Foundation, either version 3 of the License, or
  20. * (at your option) any later version.
  21. *
  22. * This program is distributed in the hope that it will be useful,
  23. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. * GNU Lesser General Public License for more details.
  26. * http://www.gnu.org/licenses
  27. */
  28. package framework.display
  29. {
  30. import flash.display.DisplayObject;
  31. import flash.display.Sprite;
  32. import flash.events.Event;
  33. import flash.events.EventDispatcher;
  34. import flash.geom.Rectangle;
  35. import flash.geom.Matrix;
  36. import framework.display.graphics.Border;
  37. import framework.display.graphics.Fill;
  38. import framework.display.graphics.Filters;
  39. import framework.utils.ObjectUtils;
  40. import framework.utils.TypeUtils;
  41. import framework.tasks.TasksBase;
  42. import framework.debug.Log;
  43. import framework.components.ScrollBar;
  44. import flash.events.MouseEvent;
  45. public class ElementBase extends Base
  46. {
  47. public static const TOP:String = "top";
  48. public static const MIDDLE:String = "middle";
  49. public static const BOTTOM:String = "bottom";
  50. public static const LEFT:String = "left";
  51. public static const RIGHT:String = "right";
  52. public static const WIDTH:String = "width";
  53. public static const HEIGHT:String = "height";
  54. private const DEFAULT:String = "default";
  55. private const BASE_PROPERTIES:Array = [LEFT,TOP,WIDTH,HEIGHT];
  56. private const BASE_PROPS:Array = [ "alpha","blendMode","buttonMode","cacheAsBitmap","doubleClickEnabled",
  57. "focusRect","mouseChildren","mouseEnabled","opaqueBackground","rotation",
  58. "rotationX","rotationY","rotationZ","scaleX","scaleY","scaleZ","tabEnabled",
  59. "tabIndex","useHandCursor","visible","x","y","z" ];
  60. // ,"height", "width" // it should be draw the width and height so you dont need to define this
  61. public var index:int;
  62. public var event:Object;
  63. public var afterTasks:Array = [];
  64. public var beforeTasks:Array = [];
  65. public var _currentState:String = DEFAULT;
  66. public var _style:Object = {"default":
  67. { left:0, top:0, width:"100%", height:0, position:"auto",
  68. background:{ type:"none", alpha:1 },
  69. border:{ type:"none", shape:"box", left:0, right:0, top:0, bottom:0 },
  70. margin:{ left:0, right:0, top:0, bottom:0 },
  71. padding:{ left:0, right:0, top:0, bottom:0 }}};
  72. public var style:Object = _style[_currentState];
  73. private var _computedStyles:Object;
  74. private var _currentAfterTask:uint = 0;
  75. private var _currentBeforeTask:uint = 0;
  76. private var _scrollbar:ScrollBar;
  77. private var _scrollRect:Rectangle;
  78. private var _rawChildren:Sprite;
  79. private var _components:Sprite;
  80. public function get currentState():String
  81. {
  82. return _currentState;
  83. }
  84. public function set currentState( value:String ):void
  85. {
  86. if( _currentState !== value ) {
  87. _currentState = value;
  88. //style = _style[_currentState];
  89. }
  90. }
  91. public function get computedStyles():Object
  92. {
  93. if( _computedStyles == null ) {
  94. _computedStyles = ObjectUtils.cloneObject( _style[_currentState] );
  95. }
  96. return _computedStyles;
  97. }
  98. public function get totalWidth() : Number
  99. {
  100. if( _computedStyles == null ) {
  101. _computedStyles = computedStyles;
  102. }
  103. var parentPadding:Number = 0;
  104. if( parent && parent.parent && parent.parent is ElementBase ) {
  105. parentPadding = (parent.parent as ElementBase).computedStyles.padding.left + (parent.parent as ElementBase).computedStyles.padding.right;
  106. }
  107. return _computedStyles.width + _computedStyles.margin.left + _computedStyles.margin.right + parentPadding;
  108. }
  109. public function get totalHeight() : Number
  110. {
  111. if( _computedStyles == null ) {
  112. _computedStyles = computedStyles;
  113. }
  114. var parentPadding:Number = 0;
  115. if( parent && parent.parent && parent.parent is ElementBase ) {
  116. parentPadding = (parent.parent as ElementBase).computedStyles.padding.top + (parent.parent as ElementBase).computedStyles.padding.bottom;
  117. }
  118. return _computedStyles.height + _computedStyles.margin.top + _computedStyles.margin.bottom + parentPadding;
  119. }
  120. public function get rawChildren() : Sprite
  121. {
  122. if( _rawChildren == null ){
  123. _rawChildren = new Sprite();
  124. addChildAt( _rawChildren, 0 );
  125. }
  126. return _rawChildren;
  127. }
  128. public function get scrollbar():ScrollBar
  129. {
  130. return _scrollbar;
  131. }
  132. public function ElementBase( styles:Object=null, events:Object=null )
  133. {
  134. super();
  135. // style = new Style( this, styles );
  136. event = events;
  137. // addEventListener(Parser.PARSED, updateDisplayList);
  138. }
  139. public function create( params:Object=null ) : ElementBase
  140. {
  141. if( params.styles ) {
  142. _style = params.styles;
  143. }
  144. event = params.events;
  145. return this;
  146. }
  147. public function kill( state:String=null ):void
  148. {
  149. this.state = state;
  150. runAfterTasks();
  151. }
  152. public function appendChild( child:DisplayObject ):DisplayObject
  153. {
  154. return super.addChild( child );
  155. }
  156. override public function addChild( child:DisplayObject ):DisplayObject
  157. {
  158. rawChildren.addChild( child );
  159. return child;
  160. }
  161. override protected function init():void
  162. {
  163. draw( style );
  164. start();
  165. // stage.addEventListener(Event.RESIZE, resize);
  166. }
  167. private function start( event:Event=null ):void
  168. {
  169. removeEventListener( "content", start );
  170. runBeforeTasks();
  171. }
  172. public function draw( style:Object ):void
  173. {
  174. graphics.clear();
  175. cleanStyle();
  176. Position[ _computedStyles.position||"auto" ]( parent.parent, this );
  177. // Set all of the base sprite properties
  178. for each( var prop:String in BASE_PROPS ) {
  179. if( _computedStyles.hasOwnProperty(prop) ) {
  180. this[prop] = _computedStyles[prop];
  181. } }
  182. x = _computedStyles.left;
  183. y = _computedStyles.top;
  184. if( _computedStyles.hasOwnProperty( "mask" ) ) {
  185. mask = parent.getChildByName( _computedStyles.mask );
  186. }
  187. if( _computedStyles.hasOwnProperty("hitArea") ) {
  188. hitArea = parent.getChildByName( _computedStyles.hitArea ) as Sprite;
  189. }
  190. // Draw eveything
  191. drawBorder();
  192. graphics.endFill()
  193. if( _computedStyles.hasOwnProperty("scrollRect") ){
  194. var scrollArr:Array = _computedStyles.scrollRect.split(",");
  195. scrollRect = new Rectangle(parseFloat(scrollArr[0]),parseFloat(scrollArr[1]),
  196. parseFloat(scrollArr[2]),parseFloat(scrollArr[3]));
  197. }
  198. if( _computedStyles.hasOwnProperty("scale9Grid") ){
  199. var scaleArr:Array = _computedStyles.scale9Grid.split(",");
  200. scale9Grid = new Rectangle(parseFloat(scaleArr[0]),parseFloat(scaleArr[1]),
  201. parseFloat(scaleArr[2]),parseFloat(scaleArr[3]));
  202. }
  203. if( _computedStyles.hasOwnProperty("overflow") &&
  204. _computedStyles.overflow != "visible" && _computedStyles.overflow != "auto" ) {
  205. scrollRect = new Rectangle(0,0,_computedStyles.width,_computedStyles.height);
  206. }
  207. // TODO: Figure out how to define filters in CSS so that they can be parsed
  208. // Filters.applyFilters( this, _computedStyles );
  209. setScroll();
  210. dispatchEvent( new Event( "drawn" ) );
  211. // // Log.debug(name, parent.name, _computedStyles.width, _computedStyles.height);
  212. }
  213. private function drawBorder():void
  214. {
  215. // left right top bottom
  216. var border:Object = _computedStyles.border;
  217. if( border != null ) {
  218. // This only supports solid borders for now
  219. if( border.color == null) {
  220. border.alpha = 0;
  221. }
  222. if( border.color != null && border.color != undefined && border.alpha == undefined ) {
  223. border.alpha = 1;
  224. }
  225. graphics.beginFill( border.color||0, border.alpha );
  226. if( border.top && border.right && border.bottom && border.left ) {
  227. drawShape( 0, 0, _computedStyles.width, _computedStyles.height );
  228. }
  229. // shape
  230. drawBackground();
  231. drawShape( border.left, border.top,
  232. _computedStyles.width - border.left - border.right,
  233. _computedStyles.height - border.top - border.bottom);
  234. }
  235. }
  236. private function drawShape( x:Number, y:Number, width:Number, height:Number ):void
  237. {
  238. if( _computedStyles.border.shape == null || _computedStyles.border.shape == "box" || _computedStyles.border.shape == "Rect" ) {
  239. graphics.drawRect( x, y, width, height );
  240. }else if( _computedStyles.border.shape == "Ellipse" ){
  241. graphics.drawEllipse( x, y, width, height);
  242. }else if( _computedStyles.border.shape == "RoundRect" ){
  243. graphics.drawRoundRect( x, y, width, height, _computedStyles.border.radius, _computedStyles.border.radius);
  244. }else if( _computedStyles.border.shape == "RoundRectComplex" ){
  245. graphics.drawRoundRectComplex( x, y, width, height,
  246. _computedStyles.border.topLeftRadius, _computedStyles.border.topRightRadius,
  247. _computedStyles.border.bottomLeftRadius, _computedStyles.border.bottomRightRadius );
  248. }
  249. }
  250. private function drawBackground():void
  251. {
  252. if( _computedStyles.background == null )
  253. _computedStyles.background = {};
  254. if( _computedStyles.background.type == null || _computedStyles.background.type == "none" ) {
  255. return;
  256. }else if( _computedStyles.background.type == "gradient" ) {
  257. gradient();
  258. //}else if( _computedStyles.background.type == "bitmap" ) {
  259. // image(); // TODO: bitmap
  260. }else{
  261. solid();
  262. }
  263. }
  264. private function solid() :void
  265. {
  266. if( _computedStyles.background.color == null ) {
  267. _computedStyles.background.color = uint(Math.random()*0xFFFFFF)
  268. }
  269. graphics.beginFill( _computedStyles.background.color, _computedStyles.background.alpha||1 );
  270. }
  271. /* The width and height of the gradients matrix are based on percentages not pixels */
  272. private function gradient() :void
  273. {
  274. var _gradient:Object = _computedStyles.background.gradient;
  275. var item:String
  276. for( item in _gradient.colors ) {
  277. _gradient.colors[item] = parseInt(_gradient.colors[item].split("#").join(""),16);
  278. }
  279. if( _gradient.alphas == null ) {
  280. _gradient.alphas = [];
  281. for( item in _gradient.colors ) { _gradient.alphas.push(1); }
  282. }else{
  283. for( item in _gradient.alphas ) {
  284. _gradient.alphas[item] = parseFloat(_gradient.alphas[item]);
  285. }
  286. }
  287. if( _gradient.ratios == null ){
  288. _gradient.ratios = [];
  289. for( var i:String in _gradient.colors ) {
  290. _gradient.ratios.push((255/(_gradient.colors.length-1))*int(i));
  291. }
  292. }else{
  293. for( item in _gradient.ratios ) {
  294. _gradient.ratios[item] = parseInt(_gradient.ratios[item]);
  295. }
  296. }
  297. var matrix:Matrix = new Matrix();
  298. var matrixValues:Array = [0,0,90,100,100];
  299. if( _gradient.matrix == null ){
  300. _gradient.matrix = matrixValues;
  301. }else if( _gradient.matrix.length != 5 ){
  302. var matrixProps:Array = ["x","y","rotation","width","height"];
  303. var count:int = 0;
  304. for each( var prop:String in matrixProps ){
  305. if( _gradient.matrix[prop] == null ) {
  306. _gradient.matrix[prop] = matrixValues[count];
  307. }
  308. count++;
  309. }
  310. }
  311. matrix.createGradientBox(
  312. ( _computedStyles.width*.01 ) * (_gradient.matrix[3]||100),
  313. ( _computedStyles.height*.01 ) * (_gradient.matrix[4]||100),
  314. ( ( _gradient.matrix[2]||90 )/180 )*Math.PI,
  315. _gradient.matrix[0]||0, _gradient.matrix[1]||0 );
  316. graphics.beginGradientFill(
  317. _gradient.kind||"linear",
  318. _gradient.colors,
  319. _gradient.alphas,
  320. _gradient.ratios,
  321. matrix,
  322. _gradient.spreadMethod||"pad",
  323. _gradient.interpolationMethod||"rgb",
  324. parseInt(_gradient.focalPointRatio) );
  325. }
  326. public function redraw():void
  327. {
  328. draw( style );
  329. }
  330. public function updateDisplayList(event:Event=null):void
  331. {
  332. var isChanged:Boolean = false;
  333. var lastChild:ElementBase
  334. if( totalWidth > _computedStyles.width ) {
  335. if( getChildAt(parent.getChildIndex(this)-1) is ElementBase ){
  336. lastChild = getChildAt(parent.getChildIndex(this)-1) as ElementBase
  337. style.width = width + totalWidth - _computedStyles.width + (parent as ElementBase).computedStyles.padding.right +
  338. lastChild.computedStyles.margin.right;
  339. }else{
  340. style.width = totalWidth + (parent as ElementBase).computedStyles.padding.right;
  341. }
  342. _computedStyles.width = style.width;
  343. isChanged = true;
  344. }
  345. if( totalHeight > _computedStyles.height ) {
  346. if( getChildAt(parent.getChildIndex(this)-1) is ElementBase ){
  347. lastChild = getChildAt(parent.getChildIndex(this)-1) as ElementBase;
  348. style.height = height + totalHeight - _computedStyles.height + (parent as ElementBase).computedStyles.padding.bottom +
  349. lastChild.computedStyles.margin.bottom;
  350. }else{
  351. style.height = totalHeight + (parent as ElementBase).computedStyles.padding.bottom;
  352. }
  353. _computedStyles.height = style.height;
  354. isChanged = true;
  355. }
  356. //if( isChanged ) redraw();
  357. }
  358. private function setScroll() : void
  359. {
  360. if( _computedStyles.overflow == "auto" || _computedStyles.overflow == "scroll" || _computedStyles.overflow == "scrollX" || _computedStyles.overflow == "scrollY" ) {
  361. if( !_scrollbar ){
  362. _scrollbar = new ScrollBar( this, rawChildren, _computedStyles, _computedStyles.overflow );
  363. appendChild( _scrollbar );
  364. }
  365. if( stage && _scrollbar ) {
  366. stage.addEventListener(MouseEvent.CLICK, _scrollbar.updateScroller);
  367. }
  368. }
  369. }
  370. public function setProperties() : void
  371. {
  372. const props:Array = ["x", "y", WIDTH, HEIGHT, "alpha","rotation","scaleX","scaleY","visible","cacheAsBitmap","buttonMode",
  373. "mouseChildren","mouseEnabled","focusRect","blendMode","rotationX","rotationY","rotationZ","scaleZ","z"];
  374. const propsLength:int = props.length;
  375. for each(var prop:String in props){
  376. if( style[ prop ] ) {
  377. this[ prop ] = style[ prop ]
  378. }
  379. }
  380. }
  381. /* public function resize( event:Event=null ):void
  382. {
  383. redraw()
  384. }*/
  385. private function runBeforeTasks( event:Event=null ):void
  386. {
  387. if( beforeTasks.length != 0 && _currentBeforeTask != beforeTasks.length ){
  388. var task:TasksBase = beforeTasks[_currentBeforeTask];
  389. task.addEventListener( Event.COMPLETE, runBeforeTasks );
  390. task.start( this );
  391. _currentBeforeTask++;
  392. }else{
  393. _currentBeforeTask = 0;
  394. dispatchEvent( new Event( "running" ) );
  395. }
  396. }
  397. private function runAfterTasks( event:Event=null ):void
  398. {
  399. if( afterTasks.length != 0 && _currentAfterTask != afterTasks.length ){
  400. var task:TasksBase = afterTasks[_currentAfterTask];
  401. task.addEventListener( Event.COMPLETE, runAfterTasks );
  402. task.start( this );
  403. _currentAfterTask++;
  404. }else{
  405. deleted( state );
  406. }
  407. }
  408. private function trash( state:String=null ):void
  409. {
  410. this.state = state;
  411. runAfterTasks();
  412. dispatchEvent(new Event( "trashed" ) );
  413. }
  414. private function deleted( state:String=null ):void
  415. {
  416. destroy();
  417. dispatchEvent(new Event( "deleted" ) );
  418. }
  419. private function cleanStyle(state:String="default") : void
  420. {
  421. _computedStyles = ObjectUtils.cloneObject( _style[_currentState] );
  422. for each( var prop:String in BASE_PROPERTIES ){
  423. if( _computedStyles[prop] is String ){
  424. var w:*;
  425. var h:*;
  426. if( parent.parent is ElementBase ) {
  427. w = ElementBase(parent.parent).computedStyles.width;
  428. h = ElementBase(parent.parent).computedStyles.height;
  429. }else{
  430. w = parent.parent.width;
  431. h = parent.parent.height;
  432. }
  433. //// Log.debug(w,h, name)
  434. if( prop == "x" || prop == WIDTH ){
  435. _computedStyles[prop] = TypeUtils.percentToNumber( _computedStyles[prop], w );
  436. }else{
  437. _computedStyles[prop] = TypeUtils.percentToNumber( _computedStyles[prop], h );
  438. }
  439. }else if( _computedStyles[prop] == null ){
  440. _computedStyles[prop] = 0;
  441. /*
  442. if( prop == LEFT || prop == TOP ){
  443. _computedStyles[prop] = 0;
  444. }else if( prop == WIDTH ){
  445. _computedStyles[prop] = w;
  446. }else{
  447. _computedStyles[prop] = 0;
  448. }
  449. */
  450. }
  451. }
  452. }
  453. }
  454. }