PageRenderTime 65ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/axiis/src/com/degrafa/geometry/Geometry.as

http://axiis.googlecode.com/
ActionScript | 1793 lines | 927 code | 292 blank | 574 comment | 164 complexity | 332d58eae4c27a8c42b9696c3fad4e6c MD5 | raw file
  1. ////////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) 2008 The Degrafa Team : http://www.Degrafa.com/team
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. ////////////////////////////////////////////////////////////////////////////////
  22. package com.degrafa.geometry{
  23. import com.degrafa.IGeometryComposition;
  24. import com.degrafa.IGraphic;
  25. import com.degrafa.core.DegrafaObject;
  26. import com.degrafa.core.IDegrafaObject;
  27. import com.degrafa.core.IGraphicSkin;
  28. import com.degrafa.core.IGraphicsFill;
  29. import com.degrafa.core.IGraphicsStroke;
  30. import com.degrafa.core.ITransformablePaint;
  31. import com.degrafa.core.collections.DecoratorCollection;
  32. import com.degrafa.core.collections.DisplayObjectCollection;
  33. import com.degrafa.core.collections.FilterCollection;
  34. import com.degrafa.core.collections.GeometryCollection;
  35. import com.degrafa.events.DegrafaEvent;
  36. import com.degrafa.geometry.command.CommandStack;
  37. import com.degrafa.geometry.layout.LayoutConstraint;
  38. import com.degrafa.states.IDegrafaStateClient;
  39. import com.degrafa.states.State;
  40. import com.degrafa.states.StateManager;
  41. import com.degrafa.transform.ITransform;
  42. import com.degrafa.triggers.ITrigger;
  43. import flash.display.DisplayObject;
  44. import flash.display.Graphics;
  45. import flash.display.Sprite;
  46. import flash.display.Stage;
  47. import flash.events.Event;
  48. import flash.filters.BitmapFilter;
  49. import flash.geom.Matrix;
  50. import flash.geom.Point;
  51. import flash.geom.Rectangle;
  52. import flash.utils.Dictionary;
  53. import mx.binding.utils.ChangeWatcher;
  54. import mx.collections.ArrayCollection;
  55. import mx.core.UIComponent;
  56. import mx.events.FlexEvent;
  57. import mx.events.PropertyChangeEvent;
  58. import mx.styles.ISimpleStyleClient;
  59. [DefaultProperty("geometry")]
  60. [Bindable(event="propertyChange")]
  61. /**
  62. * A geometry object is a type of Degrafa object that enables
  63. * rendering to a graphics context. Degrafa provides a number of
  64. * ready-to-use geometry objects. All geometry objects inherit
  65. * from the Geometry class. All geometry objects have a default data
  66. * property that can be used for short hand property setting.
  67. **/
  68. public class Geometry extends DegrafaObject implements IDegrafaObject,
  69. IGeometryComposition, IDegrafaStateClient, ISimpleStyleClient {
  70. private var _invalidated:Boolean;
  71. /**
  72. * Specifies whether this object is to be re calculated
  73. * on the next cycle. Only property updates which affect the
  74. * computation of this object set this property
  75. **/
  76. public function get invalidated():Boolean{
  77. return _invalidated;
  78. }
  79. public function set invalidated(value:Boolean):void{
  80. if(_invalidated != value){
  81. _invalidated = value;
  82. if(_invalidated && _isRootGeometry){
  83. drawToTargets();
  84. }
  85. }
  86. }
  87. /**
  88. * Returns true if this Geometry object is invalidated
  89. **/
  90. public function get isInvalidated():Boolean{
  91. return _invalidated;
  92. }
  93. private var _data:Object;
  94. /**
  95. * Allows a short hand property setting that is
  96. * specific to and parsed by each geometry object.
  97. * Look at the various geometry objects to learn what
  98. * this setting requires.
  99. **/
  100. public function get data():Object{
  101. return _data;
  102. }
  103. public function set data(value:Object):void{
  104. _data=value;
  105. }
  106. private var _visible:Boolean=true;
  107. /**
  108. * Controls the visibility of this geometry object. If true, the geometry is visible.
  109. *
  110. * When set to false this geometry object will be pre computed nor drawn.
  111. **/
  112. [Inspectable(category="General", enumeration="true,false")]
  113. public function get visible():Boolean{
  114. return _visible;
  115. }
  116. public function set visible(value:Boolean):void{
  117. if(_visible != value){
  118. var oldValue:Boolean=_visible;
  119. _visible=value;
  120. invalidated = true;
  121. //call local helper to dispatch event
  122. initChange("visible",oldValue,_visible,this);
  123. }
  124. }
  125. //Dev Note :: Needed to add this speacial case as the parent in
  126. //DegrafaObject is of type IDegrafaObject for type safty.
  127. /**
  128. * Provides access to the IGraphic object parent in a nested situation.
  129. * Set when this object is at the root of a Degrafa
  130. * IGraphic object such as GeometryGroup.
  131. **/
  132. private var _IGraphicParent:IGraphic;
  133. public function get IGraphicParent():IGraphic{
  134. return _IGraphicParent;
  135. }
  136. public function set IGraphicParent(value:IGraphic):void{
  137. if (parent==null){
  138. if(_IGraphicParent != value){
  139. _IGraphicParent=value;
  140. }
  141. }
  142. }
  143. private var _inheritStroke:Boolean=true;
  144. /**
  145. * If set to true and no stroke is defined and there is a parent object
  146. * then this object will walk up through the parents to retrive a stroke
  147. * object.
  148. **/
  149. [Inspectable(category="General", enumeration="true,false")]
  150. public function get inheritStroke():Boolean{
  151. return _inheritStroke;
  152. }
  153. public function set inheritStroke(value:Boolean):void{
  154. _inheritStroke=value;
  155. }
  156. private var _inheritFill:Boolean=true;
  157. /**
  158. * If set to true and no fill is defined and there is a parent object
  159. * then this object will walk up through the parents to retrive a fill
  160. * object.
  161. **/
  162. [Inspectable(category="General", enumeration="true,false")]
  163. public function get inheritFill():Boolean{
  164. return _inheritFill;
  165. }
  166. public function set inheritFill(value:Boolean):void{
  167. _inheritFill=value;
  168. }
  169. private var _scaleOnLayout:Boolean=true;
  170. /**
  171. * When using layout this flag will determine if you want
  172. * Scale to be applied to fit layout rules
  173. **/
  174. [Inspectable(category="General", enumeration="true,false")]
  175. public function get scaleOnLayout():Boolean{
  176. return _scaleOnLayout;
  177. }
  178. public function set scaleOnLayout(value:Boolean):void{
  179. _scaleOnLayout=value;
  180. }
  181. private var _autoClearGraphicsTarget:Boolean=true;
  182. /**
  183. * When using a graphicsTarget and if this property is set to true
  184. * the draw phase will clear the graphics context before drawing.
  185. **/
  186. [Inspectable(category="General", enumeration="true,false")]
  187. public function get autoClearGraphicsTarget():Boolean{
  188. return _autoClearGraphicsTarget;
  189. }
  190. public function set autoClearGraphicsTarget(value:Boolean):void{
  191. _autoClearGraphicsTarget=value;
  192. }
  193. private var _graphicsTarget:DisplayObjectCollection;
  194. [Inspectable(category="General", arrayType="flash.display.DisplayObject")]
  195. [ArrayElementType("flash.display.DisplayObject")]
  196. /**
  197. * One or more display object's that this Geometry is to be drawn to.
  198. * During the drawing phase this is tested first. If items have been defined
  199. * the drawing of the geometry is done on each item(s) graphics context.
  200. **/
  201. public function get graphicsTarget():Array{
  202. initGraphicsTargetCollection();
  203. return _graphicsTarget.items;
  204. }
  205. public function set graphicsTarget(value:Array):void{
  206. if(!value){return;}
  207. var item:Object;
  208. for each (item in value){
  209. if (!item){return;}
  210. }
  211. //make sure we don't set anything until all target creation is
  212. //complete otherwise we will be getting null items since flex
  213. //has not finished creation of the target items.
  214. initGraphicsTargetCollection();
  215. _graphicsTarget.items = value;
  216. var displayObject:DisplayObject;
  217. for each (displayObject in _graphicsTarget.items ){
  218. //for now this process does not include skins
  219. //to be investigated post b3.
  220. if(!(displayObject is IGraphicSkin)){
  221. //only need to call on first render of each target
  222. //dev note :: does not support runtime addition of targets. To Investigate.
  223. displayObject.addEventListener(Event.RENDER,onTargetRender);
  224. //required for stand alone player.
  225. displayObject.addEventListener(Event.ADDED_TO_STAGE,onTargetRender);
  226. if(displayObject is UIComponent){
  227. displayObject.addEventListener(FlexEvent.UPDATE_COMPLETE,onTargetRender);
  228. }
  229. }
  230. }
  231. _isRootGeometry = true;
  232. }
  233. //Method Queue Work
  234. /**
  235. * NOTE :: All this code can be moved into the DisplayObjectCollection post b3.
  236. * This way only targets that have changed are drawn to.
  237. **/
  238. private function onTargetRender(event:Event):void{
  239. //update local stage property
  240. if(!_stage){
  241. _stage = event.currentTarget.stage;
  242. }
  243. if(_stage){
  244. //remove the event listeners no longer needed
  245. event.currentTarget.removeEventListener(Event.RENDER,onTargetRender);
  246. event.currentTarget.removeEventListener(Event.ADDED_TO_STAGE,onTargetRender);
  247. //we may want to do this only for displayobject containers
  248. if(event.currentTarget is UIComponent){
  249. event.currentTarget.removeEventListener(FlexEvent.UPDATE_COMPLETE,onTargetRender);
  250. }
  251. }
  252. else{
  253. return;
  254. }
  255. //and setup the layoutChange watcher for the target
  256. //Only do this for IContainer. Requires extensive testing.
  257. if(event.currentTarget is UIComponent){
  258. initLayoutChangeWatcher(event.currentTarget as UIComponent);
  259. }
  260. //init the draw que
  261. initDrawQueue();
  262. //make sure we have not missed one draw cycle chance.
  263. //add a draw to the que.
  264. queueDraw(event.currentTarget,event.currentTarget.graphics,null)
  265. }
  266. //target stage refference
  267. private var _stage:Stage;
  268. private var methodQueue:Array=[];
  269. private function initDrawQueue():void{
  270. //add listener to frame change.
  271. _stage.addEventListener(Event.ENTER_FRAME, processMethodQueue);
  272. }
  273. //adds a draw to the queue
  274. private function queueDraw(...args):void{
  275. //make sure we are not already queued up to draw
  276. //to that target otherwise add it
  277. //DEV note: could improve perf here
  278. for each(var item:Object in methodQueue){
  279. //we only want to add it one time
  280. if(item.args[0] == args[0]){
  281. return;
  282. }
  283. }
  284. methodQueue.push({method:drawToTarget, args:args});
  285. if(_stage){
  286. _stage.addEventListener(Event.ENTER_FRAME, processMethodQueue,false,0,true);
  287. }
  288. else{
  289. //could have been added runtime
  290. if(graphicsTarget.length){
  291. if(graphicsTarget[0].stage){
  292. _stage = graphicsTarget[0].stage;
  293. _stage.addEventListener(Event.ENTER_FRAME, processMethodQueue,false,0,true);
  294. }
  295. }
  296. }
  297. }
  298. private function processMethodQueue(event:Event):void{
  299. if(methodQueue.length == 0){return;}
  300. //trace("Queue LENGTH :::" + methodQue.length)
  301. // make local copy so that new calls get through
  302. var queue:Array = methodQueue;
  303. //methodQueue = [];
  304. var len:int = queue.length;
  305. for (var i:int=0;i<len;i++){
  306. //do the draw
  307. queue[i].method.apply(null,[queue[i].args[0]]);
  308. }
  309. methodQueue.length = 0;
  310. queue.length=0;
  311. //no longer needed as all que items have been processed
  312. //will get re added in queDraw() on as needed basis.
  313. if(methodQueue.length==0 && _stage){
  314. _stage.removeEventListener(Event.ENTER_FRAME, processMethodQueue);
  315. }
  316. }
  317. //keep a local dictionary so we can compare bounds to the targets
  318. //enables us to only draw when absolutly required.
  319. //this does not include a graphics clear on the target
  320. //although we could eventually store a original bitmapdata and
  321. //compare.
  322. private var targetDictionary:Dictionary=new Dictionary(true);
  323. //return the data stored for the given target
  324. private function requestTarget(value:UIComponent):Object{
  325. return targetDictionary[value];
  326. }
  327. private function removeTarget(value:UIComponent):void{
  328. delete targetDictionary[value];
  329. }
  330. private function addUpdateTarget(value:UIComponent,data:Object):void{
  331. if(!targetDictionary[value]){
  332. targetDictionary[value] = []
  333. targetDictionary[value].data = data;
  334. }
  335. else{
  336. targetDictionary[value].data = data;
  337. }
  338. }
  339. //this will need to be called in the layout constraint setter as well.
  340. private function initLayoutChangeWatcher(container:UIComponent):void{
  341. //if this root geometry has a constraint based layout
  342. //we have to be aware of changes to the target. In this
  343. //case we only care about width and height for now. We also only care
  344. //if the target is also using a contraint based layout.
  345. var bounds:Rectangle = new Rectangle(container.x,container.y,
  346. container.width,container.height);
  347. //add a watcher for each property
  348. var watchers:Array=[]
  349. //could use some work here to only watch specific items related
  350. //to the current layout post b3.
  351. watchers.push(ChangeWatcher.watch(container,"width",onTargetChange,true));
  352. watchers.push(ChangeWatcher.watch(container,"height",onTargetChange,true));
  353. watchers.push(ChangeWatcher.watch(container,"x",onTargetChange,true));
  354. watchers.push(ChangeWatcher.watch(container,"y",onTargetChange,true));
  355. //only add if not there
  356. if(!requestTarget(container)){
  357. addUpdateTarget(container,{oldbounds:bounds,watchers:watchers})
  358. }
  359. }
  360. private function onTargetChange(event:Event):void{
  361. //see if it's there
  362. var object:Object = requestTarget(event.currentTarget as UIComponent);
  363. var watchers:Array;
  364. if(object){
  365. watchers = object.data.watchers;
  366. }
  367. //if we have no layout on this root object and the
  368. //first render pass is complete we can clean up the
  369. //watchers and exit
  370. if(object){
  371. if(!hasLayout){
  372. var changeWatcher:ChangeWatcher;
  373. for each (changeWatcher in watchers){
  374. changeWatcher.unwatch();
  375. }
  376. removeTarget(event.currentTarget as UIComponent)
  377. return;
  378. }
  379. }
  380. //compare and update the dictionary
  381. if(object){
  382. var container:UIComponent = event.currentTarget as UIComponent;
  383. //compare the 2 testing will show if we need to do this test
  384. //as it may only get the event if it has changed. Though in some cases
  385. //for example a canvas with a border may have been inited with the
  386. //correct bounds
  387. //get the current bounds
  388. var bounds:Rectangle = new Rectangle(container.x,container.y,
  389. container.width,container.height);
  390. //compare
  391. if(!bounds.equals(object.data.oldbounds)){
  392. //trace("Requires Redraw::::");
  393. //update with the new bounds for next compare
  394. addUpdateTarget(container,{oldbounds:bounds,watchers:watchers})
  395. //add a draw to the que.
  396. queueDraw(container,container.graphics,null)
  397. }
  398. }
  399. }
  400. //property that specifies if this is the root geom
  401. //object and no other parent geometries exist. Usually
  402. //the only on with a target array and set in the targets
  403. //setter
  404. private var _isRootGeometry:Boolean=false;
  405. /**
  406. * Returns true if this Geometry object is a root Geometry Object.
  407. **/
  408. public function get isRootGeometry():Boolean{
  409. return _isRootGeometry;
  410. }
  411. /**
  412. * Access to the Degrafa target collection object for this geometry object.
  413. **/
  414. public function get graphicsTargetCollection():DisplayObjectCollection{
  415. initGraphicsTargetCollection();
  416. return _graphicsTarget;
  417. }
  418. /**
  419. * Initialize the target graphics collection by creating it and adding an event listener.
  420. **/
  421. private function initGraphicsTargetCollection():void{
  422. if(!_graphicsTarget){
  423. _graphicsTarget = new DisplayObjectCollection();
  424. //add a listener to the collection
  425. if(enableEvents){
  426. _graphicsTarget.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler);
  427. }
  428. }
  429. }
  430. //draws to a single target
  431. /**
  432. * @private
  433. **/
  434. private function drawToTarget(target:Object):void{
  435. if(target){
  436. if(autoClearGraphicsTarget){
  437. target.graphics.clear();
  438. }
  439. _currentGraphicsTarget = target as Sprite;
  440. draw(target.graphics,null);
  441. }
  442. }
  443. /**
  444. * Clears all graphics targets specified in the graphicsTarget array.
  445. **/
  446. public function clearGraphicsTargets():void{
  447. if(graphicsTarget){
  448. for each (var target:Object in graphicsTarget){
  449. if(target){
  450. target.graphics.clear();
  451. }
  452. }
  453. }
  454. }
  455. /**
  456. * Requests a draw for each graphics target specified in the graphicsTarget array.
  457. **/
  458. public function drawToTargets():void{
  459. if(_graphicsTarget){
  460. for each (var target:Object in _graphicsTarget.items){
  461. queueDraw(target,target.graphics,null)
  462. }
  463. }
  464. _currentGraphicsTarget=null;
  465. }
  466. private var _geometry:GeometryCollection;
  467. [Inspectable(category="General", arrayType="com.degrafa.IGeometryComposition")]
  468. [ArrayElementType("com.degrafa.IGeometryComposition")]
  469. /**
  470. * A array of IGeometryComposition objects.
  471. **/
  472. public function get geometry():Array{
  473. initGeometryCollection();
  474. return _geometry.items;
  475. }
  476. public function set geometry(value:Array):void{
  477. initGeometryCollection();
  478. _geometry.items = value;
  479. }
  480. /**
  481. * Access to the Degrafa geometry collection object for this geometry object.
  482. **/
  483. public function get geometryCollection():GeometryCollection{
  484. initGeometryCollection();
  485. return _geometry;
  486. }
  487. /**
  488. * Initialize the geometry collection by creating it and adding an event listener.
  489. **/
  490. private function initGeometryCollection():void{
  491. if(!_geometry){
  492. _geometry = new GeometryCollection();
  493. //add the parent so it can be managed by the collection
  494. _geometry.parent = this;
  495. //add a listener to the collection
  496. if(enableEvents){
  497. _geometry.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler);
  498. }
  499. }
  500. }
  501. protected var _stroke:IGraphicsStroke;
  502. /**
  503. * Defines the stroke object that will be used for
  504. * rendering this geometry object.
  505. **/
  506. public function get stroke():IGraphicsStroke{
  507. return _stroke;
  508. }
  509. public function set stroke(value:IGraphicsStroke):void{
  510. if(_stroke != value){
  511. var oldValue:Object=_stroke;
  512. if(_stroke){
  513. if(_stroke.hasEventManager){
  514. _stroke.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler);
  515. }
  516. }
  517. _stroke = value;
  518. if(enableEvents && _stroke){
  519. _stroke.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler,false,0,true);
  520. }
  521. //call local helper to dispatch event
  522. initChange("stroke",oldValue,_stroke,this);
  523. }
  524. }
  525. protected var _fill:IGraphicsFill;
  526. /**
  527. * Defines the fill object that will be used for
  528. * rendering this geometry object.
  529. **/
  530. public function get fill():IGraphicsFill{
  531. return _fill;
  532. }
  533. public function set fill(value:IGraphicsFill):void{
  534. if(_fill != value){
  535. var oldValue:Object=_fill;
  536. if(_fill){
  537. if(_fill.hasEventManager){
  538. _fill.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler);
  539. }
  540. }
  541. _fill = value;
  542. if(enableEvents){
  543. _fill.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler,false,0,true);
  544. }
  545. //call local helper to dispatch event
  546. initChange("fill",oldValue,_fill,this);
  547. }
  548. }
  549. /**
  550. * Principle event handler for any property changes to a
  551. * geometry object or it's child objects.
  552. **/
  553. protected function propertyChangeHandler(event:PropertyChangeEvent):void{
  554. if (!parent){
  555. dispatchEvent(event);
  556. drawToTargets();
  557. }
  558. else{
  559. dispatchEvent(event)
  560. }
  561. }
  562. /**
  563. * Ends the draw phase for geometry objects.
  564. *
  565. * @param graphics The current Graphics context being drawn to.
  566. **/
  567. public function endDraw(graphics:Graphics):void {
  568. if (fill) {
  569. //force a null stroke before closing the fill -
  570. //prevents a 'closepath' stroke for unclosed paths
  571. graphics.lineStyle.apply(graphics, null);
  572. fill.end(graphics);
  573. }
  574. //append a null moveTo following a stroke without a fill
  575. //forces a break in continuity with moveTo before the next
  576. //path - if we have the last point coords we could use them
  577. //instead of null, null or perhaps any value
  578. if (stroke && !fill) graphics.moveTo.call(graphics, null, null);
  579. //draw children
  580. if (geometry){
  581. for each (var geometryItem:IGeometryComposition in geometry){
  582. geometryItem.draw(graphics,null);
  583. }
  584. }
  585. CommandStack.unstackAlpha();
  586. dispatchEvent(new DegrafaEvent(DegrafaEvent.RENDER));
  587. }
  588. /**
  589. * Initialise the stroke for this geometry object. Typically only called by draw
  590. *
  591. * @param graphics The current context to draw to.
  592. * @param rc A Rectangle object used for fill bounds.
  593. **/
  594. public function initStroke(graphics:Graphics,rc:Rectangle):void{
  595. //this will only be done one time unless no stroke is found
  596. if(parent){
  597. if(inheritStroke && !_stroke && parent is Geometry){
  598. _stroke = Geometry(parent).stroke;
  599. }
  600. }
  601. //setup the stroke
  602. if (_stroke) {
  603. //same approach as used for fills: it's required for transform inheritance by some strokes
  604. if (_stroke is ITransformablePaint) (_stroke as ITransformablePaint).requester = this;
  605. _stroke.apply(graphics, (rc)? rc:null);
  606. CommandStack.currentStroke = _stroke;
  607. }
  608. else{
  609. graphics.lineStyle();
  610. CommandStack.currentStroke = null;
  611. }
  612. }
  613. /**
  614. * Initialise the fill for this geometry object. Typically only called by draw
  615. *
  616. * @param graphics The current context to draw to.
  617. * @param rc A Rectangle object used for fill bounds.
  618. **/
  619. public function initFill(graphics:Graphics,rc:Rectangle):void{
  620. //this will only be done one time unless no fill is found
  621. if(parent){
  622. if(inheritFill && !_fill && parent is Geometry){
  623. _fill = Geometry(parent).fill;
  624. }
  625. }
  626. //setup the fill
  627. if (_fill)
  628. {
  629. //we can't pass a reference to the requesting Geometry in the method signature with IFill - its required for transform inheritance by some fills
  630. if (_fill is ITransformablePaint) (_fill as ITransformablePaint).requester = this;
  631. _fill.begin(graphics, (rc) ? rc:null);
  632. CommandStack.currentFill = _fill;
  633. } else CommandStack.currentFill = null;
  634. }
  635. /**
  636. * The tight bounds of this element as represented by a Rectangle.
  637. * The value does not include children.
  638. **/
  639. public function get bounds():Rectangle{
  640. return commandStack.bounds;
  641. }
  642. /**
  643. * Returns a transformed version of this objects bounds as
  644. * represented by a Rectangle. If no transform is specified
  645. * bounds is returned. The value does not include children.
  646. **/
  647. public function get transformBounds():Rectangle{
  648. return commandStack.transformBounds;
  649. }
  650. /**
  651. * @private
  652. **/
  653. protected var _layoutRectangle:Rectangle;
  654. /**
  655. * Returns the constraint based layout rectangle for this object
  656. * or bounds if no layout constraint is specified.
  657. **/
  658. public function get layoutRectangle():Rectangle{
  659. return (_layoutRectangle)? _layoutRectangle : bounds;
  660. }
  661. /**
  662. * Returns the point at t(0-1) on this object.
  663. **/
  664. public function pointAt(t:Number):Point{
  665. return commandStack.pathPointAt(t);
  666. }
  667. /**
  668. * Returns the angle of a point t(0-1) on the path.
  669. **/
  670. public function angleAt(t:Number):Number {
  671. return commandStack.pathAngleAt(t);
  672. }
  673. /**
  674. * Returns geometric length of this object. The value does not
  675. * include children.
  676. **/
  677. public function get geometricLength():Number{
  678. return commandStack.pathLength;
  679. }
  680. /**
  681. * Performs any pre calculation that is required to successfully render
  682. * this element. Including bounds calculations and lower level drawing
  683. * command storage. Each geometry object overrides this
  684. * and is responsible for it's own pre calculation cycle.
  685. **/
  686. public function preDraw():void{
  687. //overriden by subclasses
  688. }
  689. private var _commandStack:CommandStack;
  690. /**
  691. * Provides access to the command stack.
  692. **/
  693. public function get commandStack():CommandStack{
  694. if(!_commandStack)
  695. _commandStack = new CommandStack(this);
  696. return _commandStack;
  697. }
  698. public function set commandStack(value:CommandStack):void{
  699. _commandStack=value;
  700. }
  701. /**
  702. * @private
  703. * The current graphics target being rendered to.
  704. **/
  705. public var _currentGraphicsTarget:Sprite;
  706. /**
  707. * Access to the layout matrix if this Geometry has layout.
  708. **/
  709. public var _layoutMatrix:Matrix;
  710. /**
  711. * Performs the layout calculations if required.
  712. * All geometry override this for specifics.
  713. *
  714. * @param childBounds the bounds to be layed out. If not specified a rectangle
  715. * of (0,0,1,1) is used.
  716. **/
  717. public function calculateLayout(childBounds:Rectangle=null):void{
  718. if(_layoutConstraint){
  719. //setup default
  720. if(!childBounds){
  721. childBounds = new Rectangle(0,0,1,1);
  722. }
  723. //either the layout rect of the parent or the bounds
  724. //if no layout depending on the way the nesting is setup.
  725. //so store this as we go through the tests.
  726. var idealParentRectangle:Rectangle;
  727. //if we have a geometry parent then layout to bounds or layout rectangle
  728. //is our first test layoutRectangle call will return either the layout
  729. //rectangle or the bounds if no layout is set.
  730. if(parent && parent is Geometry){
  731. //if no valid rect then walk up the stack and try to find one
  732. //until the parent is null meaning the root geometry.
  733. var currParent:Geometry = Geometry(parent);
  734. var lastParent:Geometry;
  735. while(currParent && !idealParentRectangle){
  736. //CHANGED THE BELOW FROM THIS
  737. if(!Geometry(parent).layoutRectangle.isEmpty()){
  738. //TO THIS
  739. //if(!isNaN(Geometry(parent).layoutRectangle.x) && !isNaN(Geometry(parent).layoutRectangle.y)){
  740. idealParentRectangle = currParent.layoutRectangle;
  741. }
  742. else{
  743. //store the last parent reached for next test step
  744. lastParent = currParent;
  745. currParent = currParent.parent as Geometry;
  746. }
  747. }
  748. }
  749. //this test step will test the last found parent to see if it has a
  750. //IGraphicParent and attemp to use that unless the last parent has a
  751. //_currentGraphicsTarget.
  752. //DEV Note:: should walk the geom groups eventually as well to find the next
  753. //parent if empty bounds.
  754. if(lastParent && !idealParentRectangle){
  755. if(!lastParent._currentGraphicsTarget){
  756. if(lastParent.IGraphicParent){
  757. //we are not the root object and we are not doing the drawing
  758. //so we can try to get the bounds from the IGraphic
  759. var graphicDisplayObject:DisplayObject = lastParent.IGraphicParent as DisplayObject;
  760. var iGraphicsRect:Rectangle = graphicDisplayObject.getRect(graphicDisplayObject);
  761. if(iGraphicsRect.isEmpty()){
  762. if(graphicDisplayObject.width !=0 || graphicDisplayObject.height !=0){
  763. iGraphicsRect.x=graphicDisplayObject.x;
  764. iGraphicsRect.y=graphicDisplayObject.y;
  765. iGraphicsRect.width=graphicDisplayObject.width;
  766. iGraphicsRect.height=graphicDisplayObject.height;
  767. }
  768. }
  769. //test for empty here as even that could have nothing set.
  770. if(!iGraphicsRect.isEmpty()){
  771. idealParentRectangle=iGraphicsRect.clone();
  772. }
  773. }
  774. }
  775. }
  776. //drawing to a _currentGraphicsTarget attempt to use that.
  777. if(_currentGraphicsTarget && !idealParentRectangle){
  778. var graphicsTargetRect:Rectangle = _currentGraphicsTarget.getRect(_currentGraphicsTarget);
  779. //if empty try explicit as the target may not have anything in it
  780. //This can happen when you have a percent width/heigh on a canvas and it has no
  781. //fill nor border in these cases there is no update event.
  782. if(graphicsTargetRect.isEmpty()){
  783. if(_currentGraphicsTarget.width !=0 || _currentGraphicsTarget.height !=0){
  784. graphicsTargetRect.x=_currentGraphicsTarget.x;
  785. graphicsTargetRect.y=_currentGraphicsTarget.y;
  786. graphicsTargetRect.width=_currentGraphicsTarget.width;
  787. graphicsTargetRect.height=_currentGraphicsTarget.height;
  788. }
  789. }
  790. if(graphicsTargetRect){
  791. idealParentRectangle=graphicsTargetRect.clone();
  792. }
  793. }
  794. //add more rules here or above.
  795. //handle skins this way as they will not always follow the above rules.
  796. if(!idealParentRectangle){
  797. var iGraphicsSkinRect:Rectangle = new Rectangle();
  798. if(lastParent){
  799. if(lastParent.graphicsTarget.length!=0){
  800. if (lastParent.graphicsTarget[0] is IGraphicSkin){
  801. iGraphicsSkinRect.x=lastParent.graphicsTarget[0].x;
  802. iGraphicsSkinRect.y=lastParent.graphicsTarget[0].y;
  803. iGraphicsSkinRect.width=lastParent.graphicsTarget[0].width;
  804. iGraphicsSkinRect.height=lastParent.graphicsTarget[0].height;
  805. }
  806. if(iGraphicsSkinRect){
  807. idealParentRectangle=iGraphicsSkinRect.clone();
  808. }
  809. }
  810. }
  811. else{
  812. //if the first graphics taregt is a IGraphicSkin
  813. if(graphicsTarget.length!=0){
  814. if (graphicsTarget[0] is IGraphicSkin){
  815. iGraphicsSkinRect.x=graphicsTarget[0].x;
  816. iGraphicsSkinRect.y=graphicsTarget[0].y;
  817. iGraphicsSkinRect.width=graphicsTarget[0].width;
  818. iGraphicsSkinRect.height=graphicsTarget[0].height;
  819. }
  820. if(iGraphicsSkinRect){
  821. idealParentRectangle=iGraphicsSkinRect.clone();
  822. }
  823. }
  824. }
  825. }
  826. //fall back to the document as a last effort
  827. if(document && !idealParentRectangle){ //Sometimes the document will not be a display object (like a fill described via MXML)
  828. idealParentRectangle = new Rectangle(document.x,
  829. document.y,document.width,document.height);
  830. }
  831. //finally apply it
  832. _layoutConstraint.computeLayoutRectangle(childBounds,idealParentRectangle);
  833. }
  834. }
  835. /**
  836. * Begins the draw phase for geometry objects. All geometry objects
  837. * override this to do their specific rendering.
  838. *
  839. * @param graphics The current context to draw to.
  840. * @param rc A Rectangle object used for fill bounds.
  841. **/
  842. public function draw(graphics:Graphics,rc:Rectangle):void{
  843. //don't draw unless visible
  844. if (!visible) { return; }
  845. //stack the current alpha value
  846. CommandStack.stackAlpha(alpha);
  847. //Exit if no context specified. Calling draw(null, null) on a geometry
  848. //can now be used as a pre calculation phase where the predraw and layout will
  849. //be done but the object will not be rendered. Also avoids the rte when called
  850. //with a graphics of null.
  851. if(!graphics){return;}
  852. //endDraw if not specifically denied from commandStack
  853. if (!commandStack.draw(graphics,rc)) endDraw(graphics);
  854. }
  855. //Decoration related.
  856. /**
  857. * Returns true if this Geometry has decorators.
  858. **/
  859. public var hasDecorators:Boolean;
  860. private var _decorators:DecoratorCollection;
  861. [Inspectable(category="General", arrayType="com.degrafa.decorators.IDecorator")]
  862. [ArrayElementType("com.degrafa.decorators.IDecorator")]
  863. /**
  864. * A array of IDecorator objects to be applied on this Geometry.
  865. **/
  866. public function get decorators():Array{
  867. initDecoratorsCollection();
  868. return _decorators.items;
  869. }
  870. public function set decorators(value:Array):void{
  871. initDecoratorsCollection();
  872. _decorators.items = value;
  873. if(value && value.length!=0){
  874. hasDecorators = true;
  875. }
  876. else{
  877. hasDecorators = false;
  878. }
  879. }
  880. /**
  881. * Access to the Decorator collection object for this Geometry object.
  882. **/
  883. public function get decoratorCollection():DecoratorCollection{
  884. initDecoratorsCollection();
  885. return _decorators;
  886. }
  887. /**
  888. * Initialize the collection by creating it and adding an event listener.
  889. **/
  890. private function initDecoratorsCollection():void{
  891. if(!_decorators){
  892. _decorators = new DecoratorCollection();
  893. //add a listener to the collection
  894. if(enableEvents){
  895. _decorators.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler);
  896. }
  897. }
  898. }
  899. //END Decoration related.
  900. //Transform related.
  901. private var _transformContext:Matrix;
  902. /**
  903. * A reference to the transformation matrix context within which local transforms will be applied.
  904. * Similar in concept to the concatenatedMatrix on a flash DisplayObjects transform property.
  905. */
  906. public function get transformContext():Matrix{
  907. return _transformContext;
  908. }
  909. public function set transformContext(value:Matrix):void{
  910. _transformContext = value;
  911. }
  912. private var _transform:ITransform;
  913. /**
  914. * Defines the transform object that will be used for
  915. * rendering this geometry object.
  916. **/
  917. public function get transform():ITransform{
  918. return _transform;
  919. }
  920. public function set transform(value:ITransform):void
  921. {
  922. //get a reference to the transform hierachy
  923. if (parent && (parent as Geometry).transform)
  924. {
  925. _transformContext = (parent as Geometry).transform.getTransformFor(parent as Geometry);
  926. }
  927. if(_transform != value){
  928. var oldValue:Object=_transform;
  929. if(_transform){
  930. if(_transform.hasEventManager){
  931. _transform.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler);
  932. }
  933. }
  934. _transform = value;
  935. if(enableEvents){
  936. _transform.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler,false,0,true);
  937. }
  938. //call local helper to dispatch event
  939. initChange("transform",oldValue,_transform,this);
  940. }
  941. }
  942. //END Transform related.
  943. //Layout related.
  944. /**
  945. * @private
  946. **/
  947. protected var _layoutConstraint:LayoutConstraint;
  948. /**
  949. * The layout constraint that is used for positioning/sizing this geometry object.
  950. **/
  951. public function get layoutConstraint():LayoutConstraint{
  952. if(!_layoutConstraint){
  953. layoutConstraint= new LayoutConstraint();
  954. }
  955. return _layoutConstraint;
  956. }
  957. public function set layoutConstraint(value:LayoutConstraint):void{
  958. if(_layoutConstraint != value){
  959. var oldValue:Object=_layoutConstraint;
  960. if(_layoutConstraint){
  961. if(_layoutConstraint.hasEventManager){
  962. _layoutConstraint.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler);
  963. }
  964. }
  965. _layoutConstraint = value;
  966. if(enableEvents){
  967. _layoutConstraint.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler,false,0,true);
  968. }
  969. //call local helper to dispatch event
  970. initChange("layoutConstraint",oldValue,_layoutConstraint,this);
  971. hasLayout=true;
  972. }
  973. }
  974. /**
  975. * Returns true if this Geometry has layout.
  976. **/
  977. public var hasLayout:Boolean;
  978. //START LAYOUT PROXY PROPERTIES ::
  979. //The below are proxy properties for contraint based layout. Depending on the
  980. //object some of these are overrideen in the respective Geometry subclass.
  981. //For example width on a RegularRectangle.
  982. //x,y,width,height are different as we need a getter and a setter
  983. [PercentProxy("percentWidth")]
  984. /**
  985. * Defines the width of the layout.
  986. * Once left (or percentLeft) or right (or percentRight)
  987. * is set, the width value no longer applies. If
  988. * percentWidth exists when width is set, percentWidth
  989. * will be overridden and be given a value of NaN. This
  990. * property also accepts a percent value for example 75%.
  991. */
  992. public function get width():Number{
  993. return (hasLayout)? _layoutConstraint.width:NaN;
  994. }
  995. public function set width(value:Number):void{
  996. layoutConstraint.width = value;
  997. }
  998. /**
  999. * When set, the width of the layout will be
  1000. * set as the value of this property multiplied
  1001. * by the containing width.
  1002. * A value of 0 represents 0% and 1 represents 100%
  1003. * a value of 75 represents 75%.
  1004. */
  1005. public function get percentWidth():Number{
  1006. return (hasLayout)? layoutConstraint.percentWidth:NaN;
  1007. }
  1008. public function set percentWidth(value:Number):void{
  1009. layoutConstraint.percentWidth = value;
  1010. }
  1011. /**
  1012. * The maximum width that can be applied
  1013. * to the layout.
  1014. */
  1015. public function get maxWidth():Number{
  1016. return (hasLayout)? layoutConstraint.maxWidth:NaN;
  1017. }
  1018. public function set maxWidth(value:Number):void{
  1019. layoutConstraint.maxWidth = value;
  1020. }
  1021. /**
  1022. * The minimum width that can be applied
  1023. * to the layout.
  1024. */
  1025. public function get minWidth():Number{
  1026. return (hasLayout)? layoutConstraint.minWidth:NaN;
  1027. }
  1028. public function set minWidth(value:Number):void{
  1029. layoutConstraint.minWidth = value;
  1030. }
  1031. [PercentProxy("percentHeight")]
  1032. /**
  1033. * Defines the height of the layout boundary.
  1034. * Once top (or percentTop) or bottom (or percentBottom)
  1035. * is set, the width value no longer applies. If
  1036. * percentWidth exists when width is set, percentWidth
  1037. * will be overridden and be given a value of NaN. This
  1038. * property also accepts a percent value for example 75%.
  1039. */
  1040. public function get height():Number{
  1041. return (hasLayout)? layoutConstraint.height:NaN;
  1042. }
  1043. public function set height(value:Number):void{
  1044. layoutConstraint.height = value;
  1045. }
  1046. /**
  1047. * When set, the height of the layout will be
  1048. * set as the value of this property multiplied
  1049. * by the containing height.
  1050. * A value of 0 represents 0% and 1 represents 100%
  1051. * a value of 75 represents 75%.
  1052. */
  1053. public function get percentHeight():Number{
  1054. return (hasLayout)? layoutConstraint.percentHeight:NaN;
  1055. }
  1056. public function set percentHeight(value:Number):void{
  1057. layoutConstraint.percentHeight = value;
  1058. }
  1059. /**
  1060. * The maximum height that can be applied
  1061. * to the layout.
  1062. */
  1063. public function get maxHeight():Number{
  1064. return (hasLayout)? layoutConstraint.maxHeight:NaN;
  1065. }
  1066. public function set maxHeight(value:Number):void{
  1067. layoutConstraint.maxHeight = value;
  1068. }
  1069. /**
  1070. * The minimum height that can be applied
  1071. * to the layout.
  1072. */
  1073. public function get minHeight():Number{
  1074. return (hasLayout)? layoutConstraint.minHeight:NaN;
  1075. }
  1076. public function set minHeight(value:Number):void{
  1077. layoutConstraint.minHeight = value;
  1078. }
  1079. /**
  1080. * Defines the x location (top left) of the layout.
  1081. */
  1082. public function get x():Number{
  1083. return (hasLayout)? layoutConstraint.x:NaN;
  1084. }
  1085. public function set x(value:Number):void{
  1086. layoutConstraint.x = value;
  1087. }
  1088. /**
  1089. * The maximum x location that can be applied
  1090. * to the layout.
  1091. */
  1092. public function get maxX():Number{
  1093. return (hasLayout)? layoutConstraint.maxX:NaN;
  1094. }
  1095. public function set maxX(value:Number):void{
  1096. layoutConstraint.maxX = value;
  1097. }
  1098. /**
  1099. * The minimum x location that can be applied
  1100. * to the layout.
  1101. */
  1102. public function get minX():Number{
  1103. return (hasLayout)? layoutConstraint.minX:NaN;
  1104. }
  1105. public function set minX(value:Number):void{
  1106. layoutConstraint.minX = value;
  1107. }
  1108. /**
  1109. * Defines the y location (top left) of the layout.
  1110. */
  1111. public function get y():Number{
  1112. return (hasLayout)? layoutConstraint.y:NaN;
  1113. }
  1114. public function set y(value:Number):void{
  1115. layoutConstraint.y = value;
  1116. }
  1117. /**
  1118. * The maximum y location that can be applied
  1119. * to the layout.
  1120. */
  1121. public function get maxY():Number{
  1122. return (hasLayout)? layoutConstraint.maxY:NaN;
  1123. }
  1124. public function set maxY(value:Number):void{
  1125. layoutConstraint.maxY = value;
  1126. }
  1127. /**
  1128. * The minimum y location that can be applied
  1129. * to the layout.
  1130. */
  1131. public function get minY():Number{
  1132. return (hasLayout)? layoutConstraint.minY:NaN;
  1133. }
  1134. public function set minY(value:Number):void{
  1135. layoutConstraint.minY = value;
  1136. }
  1137. /**
  1138. * When set, if left or right is not set, the layout
  1139. * will be centered horizontally offset by the numeric
  1140. * value of this property.
  1141. */
  1142. public function get horizontalCenter():Number{
  1143. return (hasLayout)? layoutConstraint.horizontalCenter:NaN;
  1144. }
  1145. public function set horizontalCenter(value:Number):void{
  1146. layoutConstraint.horizontalCenter = value;
  1147. }
  1148. /**
  1149. * When set, if top or bottom is not set, the layout
  1150. * will be centered vertically offset by the numeric
  1151. * value of this property.
  1152. */
  1153. public function get verticalCenter():Number{
  1154. return (hasLayout)? layoutConstraint.verticalCenter:NaN;
  1155. }
  1156. public function set verticalCenter(value:Number):void{
  1157. layoutConstraint.verticalCenter = value;
  1158. }
  1159. /**
  1160. * When set, the top of the layout will be located
  1161. * offset from the top of it's parent.
  1162. */
  1163. public function get top():Number{
  1164. return (hasLayout)? layoutConstraint.top:NaN;
  1165. }
  1166. public function set top(value:Number):void{
  1167. layoutConstraint.top = value;
  1168. }
  1169. /**
  1170. * When set, the bottom of the layout will be located
  1171. * offset from the bottom of it's parent.
  1172. */
  1173. public function get bottom():Number{
  1174. return (hasLayout)? layoutConstraint.bottom:NaN;
  1175. }
  1176. public function set bottom(value:Number):void{
  1177. layoutConstraint.bottom = value;
  1178. }
  1179. /**
  1180. * When set, the left of the layout will be located
  1181. * offset by the value of this property multiplied
  1182. * by the containing width.
  1183. */
  1184. public function get left():Number{
  1185. return (hasLayout)? layoutConstraint.left:NaN;
  1186. }
  1187. public function set left(value:Number):void{
  1188. layoutConstraint.left = value;
  1189. }
  1190. /**
  1191. * When set, the right of the layout will be located
  1192. * offset by the value of this property multiplied
  1193. * by the containing width.
  1194. */
  1195. public function get right():Number{
  1196. return (hasLayout)? layoutConstraint.right:NaN;
  1197. }
  1198. public function set right(value:Number):void{
  1199. layoutConstraint.right = value;
  1200. }
  1201. [Inspectable(category="General", enumeration="true,false")]
  1202. /**
  1203. * When true, the size of the layout will always
  1204. * maintain an aspect ratio relative to the ratio
  1205. * of the current width and height properties, even
  1206. * if those properties are not in control of the
  1207. * height and width of the layout.
  1208. */
  1209. public function get maintainAspectRatio():Boolean{
  1210. return (hasLayout)? layoutConstraint.maintainAspectRatio:false;
  1211. }
  1212. public function set maintainAspectRatio(value:Boolean):void{
  1213. layoutConstraint.maintainAspectRatio = value;
  1214. }
  1215. /**
  1216. * The display object that defines the coordinate system to use.
  1217. * Dev Note:: Not yet implemented as of Beta 3.
  1218. **/
  1219. public function get targetCoordinateSpace():DisplayObject{
  1220. return (hasLayout)? layoutConstraint.targetCoordinateSpace:null;
  1221. }
  1222. public function set targetCoordinateSpace(value:DisplayObject):void {
  1223. layoutConstraint.targetCoordinateSpace = value;
  1224. }
  1225. //END LAYOUT PROXY PROPERTIES
  1226. //END Layout related.
  1227. //Trigger related.
  1228. /**
  1229. * Returns true if this Geometry has triggers.
  1230. **/
  1231. public var hasTriggers:Boolean;
  1232. private var _triggers:Array= [];
  1233. [Inspectable(arrayType="com.degrafa.triggers.ITrigger")]
  1234. [ArrayElementType("com.degrafa.triggers.ITrigger")]
  1235. /**
  1236. * An array of ITrigger objects that this Geometry object will use.
  1237. **/
  1238. public function get triggers():Array{
  1239. return _triggers;
  1240. }
  1241. public function set triggers(value:Array):void{
  1242. _triggers = value;
  1243. if(_triggers){
  1244. //make sure each item knows about it's manager
  1245. for each (var trigger:ITrigger in _triggers){
  1246. trigger.triggerParent = this;
  1247. }
  1248. }
  1249. if(value && value.length!=0){
  1250. hasTriggers = true;
  1251. }
  1252. else{
  1253. hasTriggers = false;
  1254. }
  1255. }
  1256. //End Trigger related.
  1257. //State related.
  1258. private var _currentState:String="";
  1259. [Bindable("currentStateChange")]
  1260. /**
  1261. * The current view state.
  1262. **/
  1263. public function get currentState():String{
  1264. return (stateManager) ? stateManager.currentState:"";
  1265. }
  1266. public function set currentState(value:String):void{
  1267. stateManager.currentState = value;
  1268. }
  1269. private var stateManager:StateManager;
  1270. /**
  1271. * Returns true if this Geometry has states.
  1272. **/
  1273. public var hasStates:Boolean;
  1274. private var _states:Array= [];
  1275. [Inspectable(arrayType="com.degrafa.states.State")]
  1276. [ArrayElementType("com.degrafa.states.State")]
  1277. /**
  1278. * An array of states defined for this Geometry.
  1279. **/
  1280. public function get states():Array{
  1281. return _states;
  1282. }
  1283. public function set states(value:Array):void{
  1284. _states = value;
  1285. if(value){
  1286. if(!stateManager){
  1287. stateManager = new StateManager(this)
  1288. //make sure each item knows about it's manager
  1289. for each (var state:State in _states){
  1290. state.stateManager = stateManager;
  1291. }
  1292. }
  1293. }
  1294. else{
  1295. stateManager = null;
  1296. }
  1297. if(value && value.length!=0){
  1298. hasStates = true;
  1299. }
  1300. else{
  1301. hasStates = false;
  1302. }
  1303. }
  1304. private var _state:String;
  1305. /**
  1306. * The state at which to draw this object. This property is specific to Skinning.
  1307. **/
  1308. public function get state():String{
  1309. return _state;
  1310. }
  1311. public function set state(value:String):void{
  1312. _state = value;
  1313. }
  1314. private var _stateEvent:String;
  1315. /**
  1316. * The state event at which to draw this object. This property is specific to Skinning.
  1317. **/
  1318. public function get stateEvent():String{
  1319. return _stateEvent;
  1320. }
  1321. public function set stateEvent(value:String):void{
  1322. _stateEvent = value;
  1323. }
  1324. //END state related.
  1325. //Style related.
  1326. private var _styleName:Object;
  1327. /**
  1328. * The css style name associated with this Geometry. Not yet fully implemented as of Beta 3.
  1329. **/
  1330. public function get styleName():Object{
  1331. return _styleName;
  1332. }
  1333. public function set styleName(value:Object):void{
  1334. _styleName=value;
  1335. }
  1336. /**
  1337. * Called when the value of a style property is changed.
  1338. **/
  1339. public function styleChanged(styleProp:String):void{
  1340. //handle change
  1341. }
  1342. //END Style related.
  1343. //Filter / Display object related.
  1344. //Any setting of the below items indicate a requirement for a display
  1345. //object to be used at render time.
  1346. /**
  1347. * Returns true if this Geometry has filters.
  1348. **/
  1349. public var hasFilters:Boolean;
  1350. /**
  1351. * A collection of filters to apply to the geometry.
  1352. */
  1353. private var _filters:FilterCollection;
  1354. [Inspectable(category="General", arrayType="flash.filters.BitmapFilter")]
  1355. [ArrayElementType("flash.filters.BitmapFilter")]
  1356. /**
  1357. * An array of BitmapFilter objects applied to this Geometry.
  1358. **/
  1359. public function get filters():Array{
  1360. initFilterCollection();
  1361. return _filters.items;
  1362. }
  1363. public function set filters(value:Array):void {
  1364. initFilterCollection();
  1365. if(_filters.items != value){
  1366. var oldValue:Array=_filters.items;
  1367. _filters.items = value;
  1368. //call local helper to dispatch event
  1369. initChange("filters",oldValue,_filters.items,this);
  1370. }
  1371. if(value && value.length!=0){
  1372. hasFilters = true;
  1373. }
  1374. else{
  1375. hasFilters = false;
  1376. }
  1377. }
  1378. /**
  1379. * Initialize the filter collection by creating it and adding an event listener.
  1380. **/
  1381. private function initFilterCollection():void{
  1382. if(!_filters){
  1383. _filters = new FilterCollection();
  1384. //add the parent so it can be managed by the collection
  1385. _filters.parent = this;
  1386. //add a listener to the collection
  1387. if(enableEvents){
  1388. _filters.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler);
  1389. }
  1390. }
  1391. }
  1392. //End Filter related.
  1393. //Blend Mode related.
  1394. //private var _blendMode:String=undefined;
  1395. //[Inspectable(category="General", enumeration="normal,layer,multiply,screen,lighten,darken,difference,add,subtract,invert,alpha,erase,overlay,hardlight", defaultValue="normal")]
  1396. /**
  1397. * The blend mode which is used to render the geometry to the target.
  1398. */
  1399. /*public function get blendMode():String {
  1400. return _blendMode;
  1401. }
  1402. public function set blendMode(value:String):void {
  1403. if(_blendMode != value){
  1404. var oldValue:String=_blendMode;
  1405. _blendMode = value;
  1406. //call local helper to dispatch event
  1407. initChange("blendMode",oldValue,_blendMode,this);
  1408. }
  1409. }*/
  1410. //End Blend Mode related.
  1411. //Clipping related.
  1412. private var _clippingRectangle:Rectangle=null;
  1413. /**
  1414. * A clipping rectangle to use when rendering this geometry.
  1415. */
  1416. public function get clippingRectangle():Rectangle {
  1417. return _clippingRectangle;
  1418. }
  1419. public function set clippingRectangle(value:Rectangle):void {
  1420. if(_clippingRectangle != value){
  1421. var oldValue:Rectangle=_clippingRectangle;
  1422. _clippingRectangle = value;
  1423. //call local helper to dispatch event
  1424. initChange("clippingRectangle",oldValue,_clippingRectangle,this);
  1425. }
  1426. }
  1427. //Clipping related.
  1428. //Mask related.
  1429. private var _maskMode:String;
  1430. private var _maskSpace:String;
  1431. private var _mask:IGeometryComposition;
  1432. /**
  1433. * A separate geometry object to use as a mask when rendering this geometry.
  1434. */
  1435. public function get mask():IGeometryComposition {
  1436. return _mask;
  1437. }
  1438. public function set mask(value:IGeometryComposition):void {
  1439. if (_mask != value && value != this) {
  1440. if (_mask) Geometry(_mask).removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler);
  1441. var oldValue:IGeometryComposition=_mask;
  1442. _mask = value;
  1443. Geometry(_mask).addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, propertyChangeHandler);
  1444. //call local helper to dispatch event
  1445. initChange("mask", oldValue, _mask, this);
  1446. }
  1447. }
  1448. /**
  1449. * The mode used when this object is being masked by the geometry assigned to the mask property.
  1450. * The value can either be "clip" or "mask". Clip mode is shape based clipping, alpha mode is alpha based masking.
  1451. * "svgClip" is a mode that mimics svg's clip-path setting with a non-zero clip-rule and userSpaceOnUse clipping units
  1452. */
  1453. [Inspectable(category="General", enumeration="alpha,clip,svgClip")]
  1454. public function get maskMode():String {
  1455. return _maskMode?_maskMode:"clip";
  1456. }
  1457. public function set maskMode(value:String):void {
  1458. if (value == "alpha" || value=="clip" || value=="svgClip") {
  1459. //only fire propertyChange event if there is a mask assigned.
  1460. if (_mask) initChange("maskMode", maskMode, _maskMode = value, this);
  1461. else _maskMode = value
  1462. }
  1463. }
  1464. /**
  1465. * The coordinate space within which the referenced mask geometry is rendered before being applied as a mask (respecting maskMode)
  1466. * to this object.
  1467. */
  1468. [Inspectable(category="General", enumeration="local,global")]
  1469. public function get maskSpace():String {
  1470. return _maskSpace?_maskSpace:"local";
  1471. }
  1472. public function set maskSpace(value:String):void {
  1473. if (value == "local" || value=="global" ) {
  1474. //only fire propertyChange event if there is a mask assigned.
  1475. if (_mask) initChange("maskSpace", maskSpace, _maskSpace = value, this);
  1476. else _maskSpace = value
  1477. }
  1478. }
  1479. //End mask related.
  1480. //paint modifiers
  1481. private var _alpha:Number;
  1482. /**
  1483. * The alpha setting that applies to this object. Actual alpha used when rendering reflects this objects parent chain alpha settings. If this object descends from other
  1484. * geometries with alpha settings less than, the combined effect of the parent alphas is used in conjunction with the setting on this object.
  1485. */
  1486. public function get alpha():Number {
  1487. return isNaN(_alpha)?1:_alpha;
  1488. }
  1489. public function set alpha(value:Number):void {
  1490. if (value !=_alpha ) {
  1491. initChange("alpha", alpha, _alpha = value, this);
  1492. }
  1493. }
  1494. //end paint modifiers
  1495. }
  1496. }