1////////////////////////////////////////////////////////////////////////////////
2//
3//  ADOBE SYSTEMS INCORPORATED
4//  Copyright 2008 Adobe Systems Incorporated
5//  All Rights Reserved.
6//
7//  NOTICE: Adobe permits you to use, modify, and distribute this file
8//  in accordance with the terms of the license agreement accompanying it.
9//
10////////////////////////////////////////////////////////////////////////////////
11
12package spark.primitives.supportClasses
13{
14
15import flash.display.BitmapData;
16import flash.display.BlendMode;
17import flash.display.DisplayObject;
18import flash.display.DisplayObjectContainer;
19import flash.display.Shape;
20import flash.display.Sprite;
21import flash.events.Event;
22import flash.events.EventDispatcher;
23import flash.events.IEventDispatcher;
24import flash.geom.ColorTransform;
25import flash.geom.Matrix;
26import flash.geom.Matrix3D;
27import flash.geom.Point;
28import flash.geom.Rectangle;
29import flash.geom.Transform;
30import flash.geom.Vector3D;
31
32import mx.core.AdvancedLayoutFeatures;
33import mx.core.DesignLayer;
34import mx.core.IInvalidating;
35import mx.core.ILayoutDirectionElement;
36import mx.core.ILayoutElement;
37import mx.core.IMXMLObject;
38import mx.core.IUIComponent;
39import mx.core.IVisualElement;
40import mx.core.LayoutDirection;
41import mx.core.UIComponent;
42import mx.core.UIComponentGlobals;
43import mx.core.mx_internal;
44import mx.events.FlexEvent;
45import mx.events.PropertyChangeEvent;
46import mx.filters.BaseFilter;
47import mx.filters.IBitmapFilter;
48import mx.geom.Transform;
49import mx.geom.TransformOffsets;
50import mx.graphics.shaderClasses.ColorBurnShader;
51import mx.graphics.shaderClasses.ColorDodgeShader;
52import mx.graphics.shaderClasses.ColorShader;
53import mx.graphics.shaderClasses.ExclusionShader;
54import mx.graphics.shaderClasses.HueShader;
55import mx.graphics.shaderClasses.LuminosityShader;
56import mx.graphics.shaderClasses.SaturationShader;
57import mx.graphics.shaderClasses.SoftLightShader;
58import mx.managers.ILayoutManagerClient;
59import mx.utils.MatrixUtil;
60
61import spark.components.supportClasses.InvalidatingSprite;
62import spark.core.DisplayObjectSharingMode;
63import spark.core.IGraphicElement;
64import spark.core.IGraphicElementContainer;
65import spark.core.MaskType;
66import spark.utils.FTETextUtil;
67import spark.utils.MaskUtil;
68
69use namespace mx_internal;
70
71/**
72 *  A base class for defining individual graphic elements. Types of graphic elements include:
73 *  <ul>
74 *   <li>Shapes</li>
75 *   <li>Text</li>
76 *   <li>Raster images</li>
77 *  </ul>
78 *
79 *  <p>When defining a graphic element, you specify an explicit size for the element;
80 *  that is, you cannot use percentage sizing as you can when specifying the size of a control.</p>
81 *
82 *  <p>The TBounds are the boundaries of an
83 *  object in the object's parent coordinate space. The UBounds are the boundaries
84 *  of an object in its own coordinate space.</p>
85 *
86 *  <p>If you set the transform.matrix declaratively in MXML, then it will override
87 *  the values of any transform properties (rotation, scaleX, scaleY, x, and y).
88 *  If you set the transform.matrix or the transform properties in ActionScript, then
89 *  the last value set will be used.</p>
90 *
91 *  @langversion 3.0
92 *  @playerversion Flash 10
93 *  @playerversion AIR 1.5
94 *  @productversion Flex 4
95 */
96public class GraphicElement extends EventDispatcher
97    implements IGraphicElement, IInvalidating, ILayoutElement, IVisualElement, IMXMLObject
98{
99    include "../../core/Version.as";
100
101    //--------------------------------------------------------------------------
102    //
103    //  Class constants
104    //
105    //--------------------------------------------------------------------------
106
107    /**
108     *  @private
109     *  The default value for the <code>maxWidth</code> property.
110     */
111    private static const DEFAULT_MAX_WIDTH:Number = 10000;
112
113    /**
114     *  @private
115     *  The default value for the <code>maxHeight</code> property.
116     */
117    private static const DEFAULT_MAX_HEIGHT:Number = 10000;
118
119     /**
120     *  @private
121     *  The default value for the <code>minWidth</code> property.
122     */
123    private static const DEFAULT_MIN_WIDTH:Number = 0;
124
125    /**
126     *  @private
127     *  The default value for the <code>minHeight</code> property.
128     */
129    private static const DEFAULT_MIN_HEIGHT:Number = 0;
130
131    //--------------------------------------------------------------------------
132    //
133    //  Constructor
134    //
135    //--------------------------------------------------------------------------
136
137    /**
138     *  @private
139     */
140    public function GraphicElement()
141    {
142        super();
143    }
144
145    //--------------------------------------------------------------------------
146    //
147    //  Variables
148    //
149    //--------------------------------------------------------------------------
150
151    /**
152     *  @private
153     */
154    private var displayObjectChanged:Boolean;
155
156    /**
157     *  @private
158     */
159    private var _colorTransform:ColorTransform;
160
161    private var colorTransformChanged:Boolean;
162
163    /**
164     *  @private The Sprite to draw into.
165     *  If null, then we just use displayObject or sharedDisplayObject
166     */
167    private var _drawnDisplayObject:InvalidatingSprite;
168
169    /**
170     *  @private
171     *  Whether this element needs to have its
172     *  commitProperties() method called.
173     */
174    mx_internal var invalidatePropertiesFlag:Boolean = false;
175
176    /**
177     *  @private
178     *  Whether this element needs to have its
179     *  measure() method called.
180     */
181    mx_internal var invalidateSizeFlag:Boolean = false;
182
183    /**
184     *  @private
185     *  Whether this element needs to be have its
186     *  updateDisplayList() method called.
187     */
188    mx_internal var invalidateDisplayListFlag:Boolean = false;
189
190
191    /**
192     *  Contain all of the implementation details of how the GraphicElement implements
193     *  transform and layering support. In most cases, you should not have to modify this
194     *  property.
195     *
196     *  @langversion 3.0
197     *  @playerversion Flash 10
198     *  @playerversion AIR 1.5
199     *  @productversion Flex 4
200     */
201    protected var layoutFeatures:AdvancedLayoutFeatures;
202
203
204    /**
205     *  @private
206     *  storage for the x property. This property is used when a GraphicElement has a simple transform.
207     */
208    private var _x:Number = 0;
209
210    /**
211     *  @private
212     *  storage for the y property. This property is used when a GraphicElement has a simple transform.
213     */
214    private var _y:Number = 0;
215
216    //--------------------------------------------------------------------------
217    //
218    //  Properties
219    //
220    //--------------------------------------------------------------------------
221
222    /**
223     *  @copy mx.core.IVisualElement#postLayoutTransformOffsets
224     *
225     *  @langversion 3.0
226     *  @playerversion Flash 10
227     *  @playerversion AIR 1.5
228     *  @productversion Flex 4
229     */
230    public function get postLayoutTransformOffsets():TransformOffsets
231    {
232        return (layoutFeatures == null)? null:layoutFeatures.postLayoutTransformOffsets;
233    }
234
235    /**
236     * @private
237     */
238    public function set postLayoutTransformOffsets(value:TransformOffsets):void
239    {
240        if (value != null)
241            allocateLayoutFeatures();
242
243        if (layoutFeatures.postLayoutTransformOffsets != null)
244            layoutFeatures.postLayoutTransformOffsets.removeEventListener(Event.CHANGE,transformOffsetsChangedHandler);
245        layoutFeatures.postLayoutTransformOffsets = value;
246        if (layoutFeatures.postLayoutTransformOffsets != null)
247            layoutFeatures.postLayoutTransformOffsets.addEventListener(Event.CHANGE,transformOffsetsChangedHandler);
248    }
249
250    /**
251     *  @private
252     */
253    mx_internal function allocateLayoutFeatures():void
254    {
255        if (layoutFeatures != null)
256            return;
257        layoutFeatures = new AdvancedLayoutFeatures();
258        layoutFeatures.layoutX = _x;
259        layoutFeatures.layoutY = _y;
260        layoutFeatures.layoutWidth = _width;  // for the mirror transform
261    }
262
263    /**
264     *  @private
265     */
266    private function invalidateTransform(changeInvalidatesLayering:Boolean = true,
267                                           invalidateLayout:Boolean = true):void
268    {
269        if (changeInvalidatesLayering)
270            invalidateDisplayObjectSharing();
271
272        // Make sure we apply the transform
273        if (layoutFeatures != null)
274            layoutFeatures.updatePending = true;
275
276        // If we are sharing a display object we need to redraw
277        if (displayObjectSharingMode != DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT)
278            invalidateDisplayList();
279        else
280            invalidateProperties(); // We apply the transform in commitProperties
281
282        // Trigger a layout pass
283        if (invalidateLayout)
284            invalidateParentSizeAndDisplayList();
285        }
286
287    /**
288     * @private
289     */
290    private function transformOffsetsChangedHandler(e:Event):void
291    {
292        invalidateTransform();
293    }
294
295    //----------------------------------
296    //  alpha
297    //----------------------------------
298
299    /**
300     *  @private
301     *  Storage for the alpha property.
302     */
303    private var _alpha:Number = 1.0;
304    private var _effectiveAlpha:Number = 1.0;
305
306    /**
307     *  @private
308     */
309    private var alphaChanged:Boolean = false;
310
311    [Inspectable(category="General", minValue="0.0", maxValue="1.0")]
312
313    /**
314     *  The level of transparency of the graphic element. Valid values are decimal values between
315     *  0 (fully transparent) and 1 (fully opaque). For example, a value of .25 means that the
316     *  element has 25% opacity.
317     *
318     *  @langversion 3.0
319     *  @playerversion Flash 10
320     *  @playerversion AIR 1.5
321     *  @productversion Flex 4
322     */
323    public function get alpha():Number
324    {
325        return _alpha;
326    }
327
328    /**
329     *  @private
330     */
331    public function set alpha(value:Number):void
332    {
333        if (_alpha == value)
334            return;
335
336        var previous:Boolean = needsDisplayObject;
337        _alpha = value;
338
339    // The product of _alpha and the designLayer's
340    // alpha is the effectiveAlpha which is
341    // committed in commitProperties()
342        if (designLayer)
343            value = value * designLayer.effectiveAlpha;
344
345        if (_blendMode == "auto")
346        {
347            // If alpha changes from an opaque/transparent (1/0) and translucent
348            // (0 < value < 1), then trigger a blendMode change
349            if ((value > 0 && value < 1 && (_effectiveAlpha == 0 || _effectiveAlpha == 1)) ||
350                ((value == 0 || value == 1) && (_effectiveAlpha > 0 && _effectiveAlpha < 1)))
351            {
352                blendModeChanged = true;
353            }
354        }
355
356        _effectiveAlpha = value;
357
358        // Clear the colorTransform flag since alpha was explicitly set
359        var mxTransform:mx.geom.Transform = _transform as mx.geom.Transform;
360        if (mxTransform)
361            mxTransform.applyColorTransformAlpha = false;
362
363        if (previous != needsDisplayObject)
364            invalidateDisplayObjectSharing();
365
366        alphaChanged = true;
367        invalidateProperties();
368    }
369
370    //----------------------------------
371    //  alwaysCreateDisplayObject
372    //----------------------------------
373
374    private var _alwaysCreateDisplayObject:Boolean;
375
376    /**
377     *  Specifies that this GraphicElement is to be associated with and be rendered
378     *  to its own DisplayObject.
379     *
380     *  @default false
381     *
382     *  @langversion 3.0
383     *  @playerversion Flash 10
384     *  @playerversion AIR 1.5
385     *  @productversion Flex 4.5
386     */
387    public function get alwaysCreateDisplayObject():Boolean
388    {
389        return _alwaysCreateDisplayObject;
390    }
391
392    /**
393     *  @private
394     */
395    public function set alwaysCreateDisplayObject(value:Boolean):void
396    {
397        if (value != _alwaysCreateDisplayObject)
398        {
399            var previous:Boolean = needsDisplayObject;
400            _alwaysCreateDisplayObject = value;
401            if (previous != needsDisplayObject)
402                invalidateDisplayObjectSharing();
403        }
404    }
405
406    //----------------------------------
407    //  baseline
408    //----------------------------------
409
410    /**
411     *  @private
412     *  Storage for the baseline property.
413     */
414    private var _baseline:Object;
415
416    [Inspectable(category="General")]
417
418    /**
419     *  @inheritDoc
420     *
421     *  @langversion 3.0
422     *  @playerversion Flash 10
423     *  @playerversion AIR 1.5
424     *  @productversion Flex 4
425     */
426    public function get baseline():Object
427    {
428        return _baseline;
429    }
430
431    /**
432     *  @private
433     */
434    public function set baseline(value:Object):void
435    {
436        if (_baseline == value)
437            return;
438
439        _baseline = value;
440        invalidateParentSizeAndDisplayList();
441    }
442
443    //----------------------------------
444    //  baselinePosition
445    //----------------------------------
446
447    [Inspectable(category="General")]
448
449    /**
450     *  The y-coordinate of the baseline
451     *  of the first line of text of the component.
452     *
453     *  @langversion 3.0
454     *  @playerversion Flash 10
455     *  @playerversion AIR 1.5
456     *  @productversion Flex 4
457     */
458    public function get baselinePosition():Number
459    {
460        // Subclasses of GraphicElement should return something
461        // here as appropriate (e.g. text centric GraphicElements).
462        var parentUIC:UIComponent = parent as UIComponent;
463
464        if (parentUIC)
465        {
466            if (!parentUIC.validateBaselinePosition())
467                return NaN;
468
469            return FTETextUtil.calculateFontBaseline(parentUIC, height, parentUIC.moduleFactory);
470        }
471
472        return 0;
473    }
474
475    //----------------------------------
476    //  blendMode
477    //----------------------------------
478
479    /**
480     *  @private
481     *  Storage for the blendMode property.
482     */
483    private var _blendMode:String = "auto";
484
485    /**
486     *  @private
487     */
488    private var blendModeChanged:Boolean;
489    private var blendShaderChanged:Boolean;
490    private var blendModeExplicitlySet:Boolean = false;
491
492    [Inspectable(category="General", enumeration="auto,add,alpha,darken,difference,erase,hardlight,invert,layer,lighten,multiply,normal,subtract,screen,overlay,colordodge,colorburn,exclusion,softlight,hue,saturation,color,luminosity", defaultValue="auto")]
493
494    /**
495     *  A value from the BlendMode class that specifies which blend mode to use.
496     *
497     *  @default auto
498     *
499     *  @see flash.display.DisplayObject#blendMode
500     *  @see flash.display.BlendMode
501     *
502     *  @langversion 3.0
503     *  @playerversion Flash 10
504     *  @playerversion AIR 1.5
505     *  @productversion Flex 4
506     */
507    public function get blendMode():String
508    {
509        return _blendMode;
510    }
511
512    /**
513     *  @private
514     */
515    public function set blendMode(value:String):void
516    {
517        if (value == _blendMode)
518            return;
519
520        var oldValue:String = _blendMode;
521
522        _blendMode = value;
523        blendModeChanged = true;
524
525        // If one of the non-native Flash blendModes is set,
526        // record the new value and set the appropriate
527        // blendShader on the display object.
528        if (isAIMBlendMode(value))
529        {
530            blendShaderChanged = true;
531        }
532
533        // Only need to re-do display object assignment if blendmode was normal
534        // and is changing to something else, or the blend mode was something else
535        // and is going back to normal.  This is because display object sharing
536        // only happens when blendMode is normal.
537        if ((oldValue == BlendMode.NORMAL || value == BlendMode.NORMAL) &&
538            !(oldValue == BlendMode.NORMAL && value == BlendMode.NORMAL))
539        {
540            invalidateDisplayObjectSharing();
541        }
542
543        invalidateProperties();
544    }
545
546    //----------------------------------
547    //  bottom
548    //----------------------------------
549
550    /**
551     *  @private
552     *  Storage for the bottom property.
553     */
554    private var _bottom:Object;
555
556    [Inspectable(category="General")]
557
558    /**
559     *  @inheritDoc
560     *
561     *  @langversion 3.0
562     *  @playerversion Flash 10
563     *  @playerversion AIR 1.5
564     *  @productversion Flex 4
565     */
566    public function get bottom():Object
567    {
568        return _bottom;
569    }
570
571    /**
572     *  @private
573     */
574    public function set bottom(value:Object):void
575    {
576        if (_bottom == value)
577            return;
578
579        _bottom = value;
580        invalidateParentSizeAndDisplayList();
581    }
582
583    //----------------------------------
584    //  owner
585    //----------------------------------
586
587    /**
588     *  @private
589     */
590    private var _owner:DisplayObjectContainer;
591
592    /**
593     *  @inheritDoc
594     *
595     *  @langversion 3.0
596     *  @playerversion Flash 10
597     *  @playerversion AIR 1.5
598     *  @productversion Flex 4
599     */
600    public function get owner():DisplayObjectContainer
601    {
602        return _owner ? _owner : parent;
603    }
604
605    public function set owner(value:DisplayObjectContainer):void
606    {
607        _owner = value;
608    }
609
610    //----------------------------------
611    //  layer
612    //----------------------------------
613
614    /**
615     *  @private
616     *  Storage for the layer property.
617     */
618    private var _designLayer:DesignLayer;
619
620    [Inspectable (environment='none')]
621
622    /**
623     *  @copy mx.core.IVisualElement#designLayer
624     *
625     *  @langversion 3.0
626     *  @playerversion Flash 10
627     *  @playerversion AIR 1.5
628     *  @productversion Flex 4
629     */
630    public function get designLayer():DesignLayer
631    {
632        return _designLayer;
633    }
634
635    /**
636     *  @private
637     */
638    public function set designLayer(value:DesignLayer):void
639    {
640        if (_designLayer)
641            _designLayer.removeEventListener("layerPropertyChange", layer_PropertyChange, false);
642
643        _designLayer = value;
644
645        if (_designLayer)
646            _designLayer.addEventListener("layerPropertyChange", layer_PropertyChange, false, 0, true);
647
648        _effectiveAlpha = _designLayer ? _alpha * _designLayer.effectiveAlpha : _alpha;
649        _effectiveVisibility = _designLayer ? _visible && _designLayer.effectiveVisibility : _visible;
650        alphaChanged = true;
651        visibleChanged = true;
652        invalidateProperties();
653    }
654
655    //----------------------------------
656    //  parent
657    //----------------------------------
658
659    /**
660     *  @private
661     *  Storage for the parent property.
662     */
663    private var _parent:IGraphicElementContainer;
664
665    /**
666     *  @inheritDoc
667     *
668     *  @langversion 3.0
669     *  @playerversion Flash 10
670     *  @playerversion AIR 1.5
671     *  @productversion Flex 4
672     */
673    public function get parent():DisplayObjectContainer
674    {
675        return _parent as DisplayObjectContainer;
676    }
677
678    /**
679     *  @inheritDoc
680     *
681     *  @langversion 3.0
682     *  @playerversion Flash 10
683     *  @playerversion AIR 1.5
684     *  @productversion Flex 4
685     */
686    public function parentChanged(value:IGraphicElementContainer):void
687    {
688        _parent = value;
689        invalidateLayoutDirection();
690
691        // if we now have a parent and we need to do some invalidation, let our parent know
692        if (parent)
693        {
694            if (invalidatePropertiesFlag)
695                IGraphicElementContainer(parent).invalidateGraphicElementProperties(this);
696            if (invalidateSizeFlag)
697                IGraphicElementContainer(parent).invalidateGraphicElementSize(this);
698            if (invalidateDisplayListFlag)
699                IGraphicElementContainer(parent).invalidateGraphicElementDisplayList(this);
700        }
701    }
702
703    //----------------------------------
704    //  explicitHeight
705    //----------------------------------
706
707    /**
708     *  @private
709     *  Storage for the explicitHeight property.
710     */
711    private var _explicitHeight:Number;
712
713    [Inspectable(category="General")]
714
715    /**
716     *  Number that specifies the explicit height of the component,
717     *  in pixels, in the component's coordinates.
718     *
719     *  @see mx.core.UIComponent#explicitHeight
720     *
721     *  @langversion 3.0
722     *  @playerversion Flash 10
723     *  @playerversion AIR 1.5
724     *  @productversion Flex 4
725     */
726    public function get explicitHeight():Number
727    {
728        return _explicitHeight;
729    }
730
731    /**
732     *  @private
733     */
734    public function set explicitHeight(value:Number):void
735    {
736        if (_explicitHeight == value)
737            return;
738
739        // height can be pixel or percent, not both
740        if (!isNaN(value))
741            percentHeight = NaN;
742
743        _explicitHeight = value;
744
745        invalidateSize();
746        invalidateParentSizeAndDisplayList();
747    }
748
749    //----------------------------------
750    //  explicitMaxHeight
751    //----------------------------------
752
753    /**
754     *  The maximum recommended height of the component to be considered
755     *  by the parent during layout. This value is in the
756     *  component's coordinates, in pixels.
757     *
758     *  @see mx.core.UIComponent#explicitMaxHeight
759     *
760     *  @langversion 3.0
761     *  @playerversion Flash 10
762     *  @playerversion AIR 1.5
763     *  @productversion Flex 4
764     */
765    public function get explicitMaxHeight():Number { return maxHeight; }
766    public function set explicitMaxHeight(value:Number):void { maxHeight = value; }
767
768    //----------------------------------
769    //  explicitMaxWidth
770    //----------------------------------
771
772    /**
773     *  The maximum recommended width of the component to be considered
774     *  by the parent during layout. This value is in the
775     *  component's coordinates, in pixels.
776     *
777     *  @see mx.core.UIComponent#explicitMaxWidth
778     *
779     *  @langversion 3.0
780     *  @playerversion Flash 10
781     *  @playerversion AIR 1.5
782     *  @productversion Flex 4
783     */
784    public function get explicitMaxWidth():Number { return maxWidth; }
785    public function set explicitMaxWidth(value:Number):void { maxWidth = value; }
786
787    //----------------------------------
788    //  explicitMinHeight
789    //----------------------------------
790
791    /**
792     *  The minimum recommended height of the component to be considered
793     *  by the parent during layout. This value is in the
794     *  component's coordinates, in pixels.
795     *
796     *  @see mx.core.UIComponent#explicitMinHeight
797     *
798     *  @langversion 3.0
799     *  @playerversion Flash 10
800     *  @playerversion AIR 1.5
801     *  @productversion Flex 4
802     */
803    public function get explicitMinHeight():Number { return minHeight; }
804    public function set explicitMinHeight(value:Number):void { minHeight = value; }
805
806    //----------------------------------
807    //  explicitMinWidth
808    //----------------------------------
809
810    /**
811     *  The minimum recommended width of the component to be considered
812     *  by the parent during layout. This value is in the
813     *  component's coordinates, in pixels.
814     *
815     *  @see mx.core.UIComponent#explicitMinWidth
816     *
817     *  @langversion 3.0
818     *  @playerversion Flash 10
819     *  @playerversion AIR 1.5
820     *  @productversion Flex 4
821     */
822    public function get explicitMinWidth():Number { return minWidth; }
823    public function set explicitMinWidth(value:Number):void { minWidth = value; }
824
825    //----------------------------------
826    //  explicitWidth
827    //----------------------------------
828
829    /**
830     *  @private
831     *  Storage for the explicitHeight property.
832     */
833    private var _explicitWidth:Number;
834
835    [Inspectable(category="General")]
836
837    /**
838     *  Number that specifies the explicit width of the component,
839     *  in pixels, in the component's coordinates.
840     *
841     *  @see mx.core.UIComponent#explicitWidth
842     *
843     *  @langversion 3.0
844     *  @playerversion Flash 10
845     *  @playerversion AIR 1.5
846     *  @productversion Flex 4
847     */
848    public function get explicitWidth():Number
849    {
850        return _explicitWidth;
851    }
852
853    /**
854     *  @private
855     */
856    public function set explicitWidth(value:Number):void
857    {
858        if (_explicitWidth == value)
859            return;
860
861        // height can be pixel or percent, not both
862        if (!isNaN(value))
863            percentWidth = NaN;
864
865        _explicitWidth = value;
866
867        invalidateSize();
868        invalidateParentSizeAndDisplayList();
869    }
870
871    //----------------------------------
872    //  filters
873    //----------------------------------
874
875    /**
876     *  @private
877     *  Storage for the filters property.
878     */
879    private var _filters:Array = [];
880
881    /**
882     *  @private
883     */
884    private var filtersChanged:Boolean;
885
886    /**
887     *  @private
888     */
889    private var _clonedFilters:Array;
890
891    [Inspectable(category="General")]
892
893    /**
894     *  An indexed array that contains each filter object currently associated with the graphic element.
895     *  The mx.filters package contains classes that define specific filters you can use.
896     *
897     *  <p>The getter returns a copy of the filters array. The filters property value can only be changed
898     *  via the setter.</p>
899     *
900     *  @see spark.filters.BevelFilter
901     *  @see spark.filters.BlurFilter
902     *  @see spark.filters.ColorMatrixFilter
903     *  @see spark.filters.ConvolutionFilter
904     *  @see spark.filters.DisplacementMapFilter
905     *  @see spark.filters.DropShadowFilter
906     *  @see spark.filters.GlowFilter
907     *  @see spark.filters.GradientBevelFilter
908     *  @see spark.filters.GradientFilter
909     *  @see spark.filters.GradientGlowFilter
910     *  @see spark.filters.ShaderFilter
911     *
912     *  @langversion 3.0
913     *  @playerversion Flash 10
914     *  @playerversion AIR 1.5
915     *  @productversion Flex 4
916     */
917    public function get filters():Array
918    {
919        // Return a copy of the filters to prevent it from being mutated.
920        // The only way to change the filters is through the setter.
921        return _filters.slice();
922    }
923
924    /**
925     *  @private
926     */
927    public function set filters(value:Array):void
928    {
929        var i:int = 0;
930        var len:int = _filters ? _filters.length : 0;
931        var newLen:int = value ? value.length : 0;
932        var edFilter:IEventDispatcher;
933
934        if (len == 0 && newLen == 0)
935            return;
936
937        // Remove the event listeners on the previous filters
938        for (i = 0; i < len; i++)
939        {
940            edFilter = _filters[i] as IEventDispatcher;
941            if (edFilter)
942                edFilter.removeEventListener(BaseFilter.CHANGE, filterChangedHandler);
943        }
944
945        var previous:Boolean = needsDisplayObject;
946        _filters = value;
947        if (previous != needsDisplayObject)
948            invalidateDisplayObjectSharing();
949
950        _clonedFilters = [];
951
952        for (i = 0; i < newLen; i++)
953        {
954            if (value[i] is IBitmapFilter)
955            {
956                edFilter = value[i] as IEventDispatcher;
957                if (edFilter)
958                    edFilter.addEventListener(BaseFilter.CHANGE, filterChangedHandler);
959                _clonedFilters.push(IBitmapFilter(value[i]).clone());
960            }
961            else
962            {
963                _clonedFilters.push(value[i]);
964            }
965        }
966
967        filtersChanged = true;
968        invalidateProperties();
969    }
970
971    //----------------------------------
972    //  height
973    //----------------------------------
974
975    /**
976     *  @private
977     *  Storage for the height property.
978     */
979    mx_internal var _height:Number = 0;
980
981    [Bindable("propertyChange")]
982    [Inspectable(category="General")]
983    [PercentProxy("percentHeight")]
984
985    /**
986     *  The height of the graphic element.
987     *
988     *  @default 0
989     *
990     *  @langversion 3.0
991     *  @playerversion Flash 10
992     *  @playerversion AIR 1.5
993     *  @productversion Flex 4
994     */
995    public function get height():Number
996    {
997        return _height;
998    }
999
1000    /**
1001     *  @private
1002     */
1003
1004    public function set height(value:Number):void
1005    {
1006        explicitHeight = value;
1007
1008        if (_height == value)
1009            return;
1010
1011        var oldValue:Number = _height;
1012        _height = value;
1013        dispatchPropertyChangeEvent("height", oldValue, value);
1014
1015        // Invalidate the display list, since we're changing the actual height
1016        // and we're not going to correctly detect whether the layout sets
1017        // new actual height different from our previous value.
1018        invalidateDisplayList();
1019    }
1020
1021    //----------------------------------
1022    //  horizontalCenter
1023    //----------------------------------
1024
1025    /**
1026     *  @private
1027     *  Storage for the horizontalCenter property.
1028     */
1029    private var _horizontalCenter:Object;
1030
1031    [Inspectable(category="General")]
1032
1033    /**
1034     *  @inheritDoc
1035     *
1036     *  @langversion 3.0
1037     *  @playerversion Flash 10
1038     *  @playerversion AIR 1.5
1039     *  @productversion Flex 4
1040     */
1041    public function get horizontalCenter():Object
1042    {
1043        return _horizontalCenter;
1044    }
1045
1046    /**
1047     *  @private
1048     */
1049    public function set horizontalCenter(value:Object):void
1050    {
1051        if (_horizontalCenter == value)
1052            return;
1053
1054        _horizontalCenter = value;
1055        invalidateParentSizeAndDisplayList();
1056    }
1057
1058    //----------------------------------
1059    //  id
1060    //----------------------------------
1061
1062    /**
1063     *  @private
1064     *  Storage for the id property.
1065     */
1066    private var _id:String;
1067
1068    /**
1069     *  The identity of the component.
1070     *
1071     *  @langversion 3.0
1072     *  @playerversion Flash 10
1073     *  @playerversion AIR 1.5
1074     *  @productversion Flex 4
1075     */
1076    public function get id():String
1077    {
1078        return _id;
1079    }
1080
1081    /**
1082     *  @private
1083     */
1084    public function set id(value:String):void
1085    {
1086        _id = value;
1087    }
1088
1089    //----------------------------------
1090    //  left
1091    //----------------------------------
1092
1093    /**
1094     *  @private
1095     *  Storage for the left property.
1096     */
1097    private var _left:Object;
1098
1099    [Inspectable(category="General")]
1100
1101    /**
1102     *  @inheritDoc
1103     *
1104     *  @langversion 3.0
1105     *  @playerversion Flash 10
1106     *  @playerversion AIR 1.5
1107     *  @productversion Flex 4
1108     */
1109    public function get left():Object
1110    {
1111        return _left;
1112    }
1113
1114    /**
1115     *  @private
1116     */
1117    public function set left(value:Object):void
1118    {
1119        if (_left == value)
1120            return;
1121
1122        _left = value;
1123        invalidateParentSizeAndDisplayList();
1124    }
1125
1126    //----------------------------------
1127    //  mask
1128    //----------------------------------
1129
1130    /**
1131     *  @private
1132     *  Storage for the mask property.
1133     */
1134    private var _mask:DisplayObject;
1135
1136    /**
1137     *  @private
1138     */
1139    private var maskChanged:Boolean;
1140
1141    [Inspectable(category="General")]
1142
1143    /**
1144     *  The calling display object is masked by the specified mask object.
1145     *  If, the mask display object is not on the display list, it will be added to the display list
1146     *  as a child of the displayObject. The mask object itself is not drawn.
1147     *  Set mask to null to remove the mask.
1148     *
1149     *  To use another GraphicElement as a mask, wrap the GraphicElement in a Group or other container.
1150     *
1151     *  @see flash.display.DisplayObject#mask
1152     *
1153     *  @langversion 3.0
1154     *  @playerversion Flash 10
1155     *  @playerversion AIR 1.5
1156     *  @productversion Flex 4
1157     */
1158    public function get mask():DisplayObject
1159    {
1160        return _mask;
1161    }
1162
1163    /**
1164     *  @private
1165     */
1166    public function set mask(value:DisplayObject):void
1167    {
1168        if (_mask == value)
1169            return;
1170
1171        var oldMask:UIComponent = _mask as UIComponent;
1172
1173        var previous:Boolean = needsDisplayObject;
1174        _mask = value;
1175
1176        // If the old mask was attached by us, then we need to
1177        // undo the attachment logic
1178        if (oldMask && oldMask.$parent === displayObject)
1179        {
1180            if (oldMask.parent is UIComponent)
1181                UIComponent(oldMask.parent).childRemoved(oldMask);
1182            oldMask.$parent.removeChild(oldMask);
1183        }
1184
1185        // Cleanup the drawnDisplayObject mask and _drawnDisplayObject here
1186        // because displayObject (the parent of _drawnDisplayObject)
1187        // might be null in commitProperties
1188        if (!_mask || _mask.parent)
1189        {
1190            if (drawnDisplayObject)
1191                drawnDisplayObject.mask = null;
1192
1193            if (_drawnDisplayObject)
1194            {
1195                if (_drawnDisplayObject.parent)
1196                    _drawnDisplayObject.parent.removeChild(_drawnDisplayObject);
1197                _drawnDisplayObject = null;
1198            }
1199        }
1200
1201        maskChanged = true;
1202        maskTypeChanged = true;
1203        if (previous != needsDisplayObject)
1204            invalidateDisplayObjectSharing();
1205
1206        invalidateProperties();
1207        invalidateDisplayList();
1208    }
1209
1210    //----------------------------------
1211    //  maskType
1212    //----------------------------------
1213
1214    /**
1215     *  @private
1216     *  Storage for the maskType property.
1217     */
1218    private var _maskType:String = MaskType.CLIP;
1219
1220    /**
1221     *  @private
1222     */
1223    private var maskTypeChanged:Boolean;
1224
1225    [Inspectable(category="General", enumeration="clip,alpha,luminosity", defaultValue="clip")]
1226
1227    /**
1228     *  <p>Defines how the mask is applied to the GraphicElement.</p>
1229     *
1230     *  <p>The possible values are <code>MaskType.CLIP</code>, <code>MaskType.ALPHA</code>, and
1231     *  <code>MaskType.LUMINOSITY</code>.</p>
1232     *
1233     *  <p><strong>Clip Masking</strong></p>
1234     *
1235     *  <p>When masking in clip mode, a clipping masks is reduced to 1-bit.  This means that a mask will
1236     *  not affect the opacity of a pixel in the source content; it either leaves the value unmodified,
1237     *  if the corresponding pixel in the mask is has a non-zero alpha value, or makes it fully
1238     *  transparent, if the mask pixel value has an alpha value of zero.</p>
1239     *
1240     *  <p>When clip masking is used, only the actual path and shape vectors and fills defined by the
1241     *  mask are used to determine the effect on the source content.  strokes and bitmap filters
1242     *  defined on the mask are ignored.  Any filled region in the mask is considered filled, and renders
1243     *  the source content.  The type and parameters of the fill is irrelevant;  a solid color fill,
1244     *  gradient fill, or bitmap fill in a mask will all render the underlying source content, regardless
1245     *  of the alpha values of the mask fill.</p>
1246     *
1247     *  <p>BitmapGraphics are treated as bitmap filled rectangles when used in a clipping mask.  As a
1248     *  result, the alpha channel of the source bitmap is irrelevant when part of a mask -- the bitmap
1249     *  affects the mask in the same manner as solid filled rectangle of equivalent dimensions.</p>
1250     *
1251     *  <p><strong>Alpha Masking</strong></p>
1252     *
1253     *  <p>In alpha mode, the opacity of each pixel in the source content is multiplied by the opacity
1254     *  of the corresponding region of the mask.  i.e., a pixel in the source content with an opacity of
1255     *  1 that is masked by a region of opacity of .5 will have a resulting opacity of .5.  A source pixel
1256     *  with an opacity of .8 masked by a region with opacity of .5 will have a resulting opacity of .4.</p>
1257     *
1258     *  <p>Conceptually, alpha masking is equivalent to rendering the transformed mask and source content
1259     *  into separate RGBA surfaces, and multiplying the alpha channel of the mask content into the alpha
1260     *  channel of the source content.  All of the mask content is rendered into its surface before
1261     *  compositing into the source content's surface. As a result, all FXG features, such as strokes,
1262     *  bitmap filters, and fill opacity will affect the final composited content.</p>
1263     *
1264     *  <p>When in alpha mode, the alpha channel of any bitmap data is composited normally into the mask
1265     *  alpha channel, and will affect the final rendered content. This holds true for both BitmapGraphics
1266     *  and bitmap filled shapes and paths.</p>
1267     *
1268     *  <p><strong>Luminosity Masking</strong></p>
1269     *
1270     *  <p>A luminosity mask, sometimes called a 'soft mask', works very similarly to an alpha mask
1271     *  except that both the opacity and RGB color value of a pixel in the source content is multiplied
1272     *  by the opacity and RGB color value of the corresponding region in the mask.</p>
1273     *
1274     *  <p>Conceptually, luminosity masking is equivalent to rendering the transformed mask and source content
1275     *  into separate RGBA surfaces, and multiplying the alpha channel and the RGB color value of the mask
1276     *  content into the alpha channel and RGB color value of the source content.  All of the mask content is
1277     *  rendered into its surface before compositing into the source content's surface. As a result, all FXG
1278     *  features, such as strokes, bitmap filters, and fill opacity will affect the final composited
1279     *  content.</p>
1280     *
1281     *  <p>Luminosity masking is not native to Flash but is common in Adobe Creative Suite tools like Adobe
1282     *  Illustrator and Adobe Photoshop. In order to accomplish the visual effect of a luminosity mask in
1283     *  Flash-rendered content, a graphic element specifying a luminosity mask actually instantiates a shader
1284     *  filter that mimics the visual look of a luminosity mask as rendered in Adobe Creative Suite tools.</p>
1285     *
1286     *  <p>Objects being masked by luminosity masks can set properties to control the RGB color value and
1287     *  clipping of the mask. See the luminosityInvert and luminosityClip attributes.</p>
1288     *
1289     *  @default MaskType.CLIP
1290     *
1291     *  @see spark.core.MarkType
1292     *
1293     *  @langversion 3.0
1294     *  @playerversion Flash 10
1295     *  @playerversion AIR 1.5
1296     *  @productversion Flex 4
1297     */
1298    public function get maskType():String
1299    {
1300        return _maskType;
1301    }
1302
1303    /**
1304     *  @private
1305     */
1306    public function set maskType(value:String):void
1307    {
1308        if (_maskType == value)
1309            return;
1310
1311        _maskType = value;
1312        maskTypeChanged = true;
1313        invalidateProperties();
1314    }
1315
1316    //----------------------------------
1317    //  luminosityInvert
1318    //----------------------------------
1319
1320    /**
1321     *  @private
1322     *  Storage for the luminosityInvert property.
1323     */
1324    private var _luminosityInvert:Boolean = false;
1325
1326    /**
1327     *  @private
1328     */
1329    private var luminositySettingsChanged:Boolean;
1330
1331    [Inspectable(category="General", enumeration="true,false", defaultValue="false")]
1332
1333    /**
1334     *  A property that controls the calculation of the RGB
1335     *  color value of a graphic element being masked by
1336     *  a luminosity mask. If true, the RGB color value of a
1337     *  pixel in the source content is inverted and multipled
1338     *  by the corresponding region in the mask. If false,
1339     *  the source content's pixel's RGB color value is used
1340     *  directly.
1341     *
1342     *  @default false
1343     *  @see #maskType
1344     *
1345     *  @langversion 3.0
1346     *  @playerversion Flash 10
1347     *  @playerversion AIR 1.5
1348     *  @productversion Flex 4
1349     */
1350    public function get luminosityInvert():Boolean
1351    {
1352        return _luminosityInvert;
1353    }
1354
1355    /**
1356     *  @private
1357     */
1358    public function set luminosityInvert(value:Boolean):void
1359    {
1360        if (_luminosityInvert == value)
1361            return;
1362
1363        _luminosityInvert = value;
1364        luminositySettingsChanged = true;
1365    }
1366
1367    //----------------------------------
1368    //  luminosityClip
1369    //----------------------------------
1370
1371    /**
1372     *  @private
1373     *  Storage for the luminosityClip property.
1374     */
1375    private var _luminosityClip:Boolean = false;
1376
1377    [Inspectable(category="General", enumeration="true,false", defaultValue="false")]
1378
1379    /**
1380     *  A property that controls whether the luminosity
1381     *  mask clips the masked content. This property can
1382     *  only have an effect if the graphic element has a
1383     *  mask applied to it that is of type
1384     *  MaskType.LUMINOSITY.
1385     *
1386     *  @default false
1387     *  @see #maskType
1388     *
1389     *  @langversion 3.0
1390     *  @playerversion Flash 10
1391     *  @playerversion AIR 1.5
1392     *  @productversion Flex 4
1393     */
1394    public function get luminosityClip():Boolean
1395    {
1396        return _luminosityClip;
1397    }
1398
1399    /**
1400     *  @private
1401     */
1402    public function set luminosityClip(value:Boolean):void
1403    {
1404        if (_luminosityClip == value)
1405            return;
1406
1407        _luminosityClip = value;
1408        luminositySettingsChanged = true;
1409    }
1410
1411    //----------------------------------
1412    //  maxHeight
1413    //----------------------------------
1414
1415    /**
1416     *  @private
1417     *  Storage for the maxHeight property.
1418     */
1419    private var _maxHeight:Number;
1420
1421    [Inspectable(category="General")]
1422
1423    /**
1424     *  @copy mx.core.UIComponent#maxHeight
1425     *
1426     *  @langversion 3.0
1427     *  @playerversion Flash 10
1428     *  @playerversion AIR 1.5
1429     *  @productversion Flex 4
1430     */
1431    public function get maxHeight():Number
1432    {
1433        return !isNaN(_maxHeight) ? _maxHeight : DEFAULT_MAX_HEIGHT;
1434    }
1435
1436    /**
1437     *  @private
1438     */
1439    public function set maxHeight(value:Number):void
1440    {
1441        if (_maxHeight == value)
1442            return;
1443
1444        _maxHeight = value;
1445
1446        invalidateSize();
1447        invalidateParentSizeAndDisplayList();
1448    }
1449
1450    //----------------------------------
1451    //  maxWidth
1452    //----------------------------------
1453
1454    /**
1455     *  @private
1456     *  Storage for the maxHeight property.
1457     */
1458    mx_internal var _maxWidth:Number;
1459
1460    [Inspectable(category="General")]
1461
1462    /**
1463     *  @copy mx.core.UIComponent#maxWidth
1464     *
1465     *  @langversion 3.0
1466     *  @playerversion Flash 10
1467     *  @playerversion AIR 1.5
1468     *  @productversion Flex 4
1469     */
1470    public function get maxWidth():Number
1471    {
1472        return !isNaN(_maxWidth) ? _maxWidth : DEFAULT_MAX_WIDTH;
1473    }
1474
1475    /**
1476     *  @private
1477     */
1478    public function set maxWidth(value:Number):void
1479    {
1480        if (_maxWidth == value)
1481            return;
1482
1483        _maxWidth = value;
1484
1485        invalidateSize();
1486        invalidateParentSizeAndDisplayList();
1487    }
1488
1489    //----------------------------------
1490    //  measuredHeight
1491    //----------------------------------
1492
1493    /**
1494     *  @private
1495     *  Storage for the measuredHeight property.
1496     */
1497    private var _measuredHeight:Number = 0;
1498
1499    /**
1500     *  @copy mx.core.UIComponent#measuredHeight
1501     *
1502     *  @langversion 3.0
1503     *  @playerversion Flash 10
1504     *  @playerversion AIR 1.5
1505     *  @productversion Flex 4
1506     */
1507    public function get measuredHeight():Number
1508    {
1509        return _measuredHeight;
1510    }
1511
1512    /**
1513     *  @private
1514     */
1515    public function set measuredHeight(value:Number):void
1516    {
1517        _measuredHeight = value;
1518    }
1519
1520    //----------------------------------
1521    //  measuredWidth
1522    //----------------------------------
1523
1524    /**
1525     *  @private
1526     *  Storage for the measuredWidth property.
1527     */
1528    private var _measuredWidth:Number = 0;
1529
1530    /**
1531     *  @copy mx.core.UIComponent#measuredWidth
1532     *
1533     *  @langversion 3.0
1534     *  @playerversion Flash 10
1535     *  @playerversion AIR 1.5
1536     *  @productversion Flex 4
1537     */
1538    public function get measuredWidth():Number
1539    {
1540        return _measuredWidth;
1541    }
1542
1543    /**
1544     *  @private
1545     */
1546    public function set measuredWidth(value:Number):void
1547    {
1548        _measuredWidth = value;
1549    }
1550
1551    //----------------------------------
1552    //  measuredX
1553    //----------------------------------
1554
1555    /**
1556     *  @private
1557     *  Storage for the measuredX property.
1558     */
1559    private var _measuredX:Number = 0;
1560
1561    /**
1562     *  The default measured bounds top-left corner relative to the origin of the element.
1563     *
1564     *  @langversion 3.0
1565     *  @playerversion Flash 10
1566     *  @playerversion AIR 1.5
1567     *  @productversion Flex 4
1568     */
1569    public function get measuredX():Number
1570    {
1571        return _measuredX;
1572    }
1573
1574    /**
1575     *  @private
1576     */
1577    public function set measuredX(value:Number):void
1578    {
1579        _measuredX = value;
1580    }
1581
1582    //----------------------------------
1583    //  measuredY
1584    //----------------------------------
1585
1586    /**
1587     *  @private
1588     *  Storage for the measuredY property.
1589     */
1590    private var _measuredY:Number = 0;
1591
1592    /**
1593     *  The default measured bounds top-left corner relative to the origin of the element.
1594     *
1595     *  @langversion 3.0
1596     *  @playerversion Flash 10
1597     *  @playerversion AIR 1.5
1598     *  @productversion Flex 4
1599     */
1600    public function get measuredY():Number
1601    {
1602        return _measuredY;
1603    }
1604
1605    /**
1606     *  @private
1607     */
1608    public function set measuredY(value:Number):void
1609    {
1610        _measuredY = value;
1611    }
1612
1613    //----------------------------------
1614    //  minHeight
1615    //----------------------------------
1616
1617    /**
1618     *  @private
1619     *  Storage for the minHeight property.
1620     */
1621    private var _minHeight:Number;
1622
1623    [Inspectable(category="General")]
1624
1625    /**
1626     *  @copy mx.core.UIComponent#minHeight
1627     *
1628     *  @langversion 3.0
1629     *  @playerversion Flash 10
1630     *  @playerversion AIR 1.5
1631     *  @productversion Flex 4
1632     */
1633    public function get minHeight():Number
1634    {
1635        return !isNaN(_minHeight) ? _minHeight : DEFAULT_MIN_HEIGHT;
1636    }
1637
1638    /**
1639     *  @private
1640     */
1641    public function set minHeight(value:Number):void
1642    {
1643        if (_minHeight == value)
1644            return;
1645
1646        _minHeight = value;
1647
1648        invalidateSize();
1649        invalidateParentSizeAndDisplayList();
1650    }
1651
1652    //----------------------------------
1653    //  minWidth
1654    //----------------------------------
1655
1656    /**
1657     *  @private
1658     *  Storage for the minWidth property.
1659     */
1660    private var _minWidth:Number;
1661
1662    [Inspectable(category="General")]
1663
1664    /**
1665     *  @copy mx.core.UIComponent#minWidth
1666     *
1667     *  @langversion 3.0
1668     *  @playerversion Flash 10
1669     *  @playerversion AIR 1.5
1670     *  @productversion Flex 4
1671     */
1672    public function get minWidth():Number
1673    {
1674        return !isNaN(_minWidth) ? _minWidth : DEFAULT_MIN_WIDTH;
1675    }
1676
1677    /**
1678     *  @private
1679     */
1680    public function set minWidth(value:Number):void
1681    {
1682        if (_minWidth == value)
1683            return;
1684
1685        _minWidth = value;
1686
1687        invalidateSize();
1688        invalidateParentSizeAndDisplayList();
1689    }
1690
1691    //----------------------------------
1692    //  percentHeight
1693    //----------------------------------
1694
1695    /**
1696     *  @private
1697     *  Storage for the percentHeight property.
1698     */
1699    private var _percentHeight:Number;
1700
1701    [Inspectable(category="General")]
1702
1703    /**
1704     *  @inheritDoc
1705     *
1706     *  @langversion 3.0
1707     *  @playerversion Flash 10
1708     *  @playerversion AIR 1.5
1709     *  @productversion Flex 4
1710     */
1711    public function get percentHeight():Number
1712    {
1713        return _percentHeight;
1714    }
1715
1716    /**
1717     *  @private
1718     */
1719    public function set percentHeight(value:Number):void
1720    {
1721        if (_percentHeight == value)
1722            return;
1723
1724        if (!isNaN(value))
1725            explicitHeight = NaN;
1726
1727        _percentHeight = value;
1728
1729        invalidateParentSizeAndDisplayList();
1730    }
1731
1732    //----------------------------------
1733    //  percentWidth
1734    //----------------------------------
1735
1736    /**
1737     *  @private
1738     *  Storage for the percentWidth property.
1739     */
1740    private var _percentWidth:Number;
1741
1742    [Inspectable(category="General")]
1743
1744    /**
1745     *  @copy mx.core.UIComponent#percentWidth
1746     *
1747     *  @langversion 3.0
1748     *  @playerversion Flash 10
1749     *  @playerversion AIR 1.5
1750     *  @productversion Flex 4
1751     */
1752    public function get percentWidth():Number
1753    {
1754        return _percentWidth;
1755    }
1756
1757    /**
1758     *  @private
1759     */
1760    public function set percentWidth(value:Number):void
1761    {
1762        if (_percentWidth == value)
1763            return;
1764
1765        if (!isNaN(value))
1766            explicitWidth = NaN;
1767
1768        _percentWidth = value;
1769
1770        invalidateParentSizeAndDisplayList();
1771    }
1772
1773    //----------------------------------
1774    //  right
1775    //----------------------------------
1776
1777    /**
1778     *  @private
1779     *  Storage for the right property.
1780     */
1781    private var _right:Object;
1782
1783    [Inspectable(category="General")]
1784
1785    /**
1786     *  @inheritDoc
1787     *
1788     *  @langversion 3.0
1789     *  @playerversion Flash 10
1790     *  @playerversion AIR 1.5
1791     *  @productversion Flex 4
1792     */
1793    public function get right():Object
1794    {
1795        return _right;
1796    }
1797
1798    /**
1799     *  @private
1800     */
1801    public function set right(value:Object):void
1802    {
1803        if (_right == value)
1804            return;
1805
1806        _right = value;
1807        invalidateParentSizeAndDisplayList();
1808    }
1809
1810    //----------------------------------
1811    //  rotation
1812    //----------------------------------
1813
1814    [Inspectable(category="General")]
1815
1816    /**
1817     * Indicates the x-axis rotation of the element instance, in degrees, from its original orientation
1818     * relative to the 3D parent container. Values from 0 to 180 represent clockwise rotation; values
1819     * from 0 to -180 represent counterclockwise rotation. Values outside this range are added to or subtracted from
1820     * 360 to obtain a value within the range.
1821     *
1822     * This property is ignored during calculation by any of Flex's 2D layouts.
1823     *
1824     *  @langversion 3.0
1825     *  @playerversion Flash 10
1826     *  @playerversion AIR 1.5
1827     *  @productversion Flex 4
1828     */
1829    public function get rotationX():Number
1830    {
1831        return (layoutFeatures == null)? 0:layoutFeatures.layoutRotationX;
1832    }
1833
1834    /**
1835     *  @private
1836     */
1837    public function set rotationX(value:Number):void
1838    {
1839        if (rotationX == value)
1840            return;
1841
1842        allocateLayoutFeatures();
1843        var previous:Boolean = needsDisplayObject;
1844        layoutFeatures.layoutRotationX = value;
1845        invalidateTransform(previous != needsDisplayObject);
1846    }
1847
1848    [Inspectable(category="General")]
1849
1850    /**
1851     * Indicates the y-axis rotation of the DisplayObject instance, in degrees, from its original orientation
1852     * relative to the 3D parent container. Values from 0 to 180 represent clockwise rotation; values
1853     * from 0 to -180 represent counterclockwise rotation. Values outside this range are added to or subtracted from
1854     * 360 to obtain a value within the range.
1855     *
1856     * This property is ignored during calculation by any of Flex's 2D layouts.
1857     *
1858     *  @langversion 3.0
1859     *  @playerversion Flash 10
1860     *  @playerversion AIR 1.5
1861     *  @productversion Flex 4
1862     */
1863    public function get rotationY():Number
1864    {
1865        return (layoutFeatures == null)? 0:layoutFeatures.layoutRotationY;
1866    }
1867    /**
1868     *  @private
1869     */
1870    public function set rotationY(value:Number):void
1871    {
1872        if (rotationY == value)
1873            return;
1874
1875        allocateLayoutFeatures();
1876        var previous:Boolean = needsDisplayObject;
1877        layoutFeatures.layoutRotationY = value;
1878        invalidateTransform(previous != needsDisplayObject);
1879    }
1880
1881    [Inspectable(category="General")]
1882
1883    /**
1884     *  Indicates the rotation of the element, in degrees,
1885     *  from the transform point.
1886     *
1887     *  @langversion 3.0
1888     *  @playerversion Flash 10
1889     *  @playerversion AIR 1.5
1890     *  @productversion Flex 4
1891     */
1892    public function get rotationZ():Number
1893    {
1894        return (layoutFeatures == null)? 0:layoutFeatures.layoutRotationZ;
1895    }
1896
1897    /**
1898     *  @private
1899     */
1900    public function set rotationZ(value:Number):void
1901    {
1902        if (rotationZ == value)
1903            return;
1904
1905        allocateLayoutFeatures();
1906        var previous:Boolean = needsDisplayObject;
1907        layoutFeatures.layoutRotationZ = value;
1908        invalidateTransform(previous != needsDisplayObject);
1909    }
1910
1911    [Inspectable(category="General")]
1912
1913    /**
1914     *  Indicates the rotation of the element, in degrees,
1915     *  from the transform point.
1916     *
1917     *  @langversion 3.0
1918     *  @playerversion Flash 10
1919     *  @playerversion AIR 1.5
1920     *  @productversion Flex 4
1921     */
1922    public function get rotation():Number
1923    {
1924        return (layoutFeatures == null)? 0:layoutFeatures.layoutRotationZ;
1925    }
1926
1927    /**
1928     *  @private
1929     */
1930    public function set rotation(value:Number):void
1931    {
1932        rotationZ = value;
1933    }
1934
1935    //----------------------------------
1936    //  scaleX
1937    //----------------------------------
1938
1939    [Inspectable(category="General")]
1940
1941    /**
1942     *  The horizontal scale (percentage) of the element
1943     *  as applied from the transform point.
1944     *
1945     *  @langversion 3.0
1946     *  @playerversion Flash 10
1947     *  @playerversion AIR 1.5
1948     *  @productversion Flex 4
1949     */
1950    public function get scaleX():Number
1951    {
1952        return (layoutFeatures == null)? 1:layoutFeatures.layoutScaleX;
1953    }
1954
1955    /**
1956     *  @private
1957     */
1958    public function set scaleX(value:Number):void
1959    {
1960        if (scaleX == value)
1961            return;
1962
1963        allocateLayoutFeatures();
1964        var previous:Boolean = needsDisplayObject;
1965        layoutFeatures.layoutScaleX = value;
1966        invalidateTransform(previous != needsDisplayObject);
1967    }
1968
1969    //----------------------------------
1970    //  scaleY
1971    //----------------------------------
1972
1973    [Inspectable(category="General")]
1974
1975    /**
1976     *  The vertical scale (percentage) of the element
1977     *  as applied from the transform point.
1978     *
1979     *  @langversion 3.0
1980     *  @playerversion Flash 10
1981     *  @playerversion AIR 1.5
1982     *  @productversion Flex 4
1983     */
1984    public function get scaleY():Number
1985    {
1986        return (layoutFeatures == null)? 1:layoutFeatures.layoutScaleY;
1987    }
1988
1989    /**
1990     *  @private
1991     */
1992    public function set scaleY(value:Number):void
1993    {
1994        if (scaleY == value)
1995            return;
1996
1997        allocateLayoutFeatures();
1998        var previous:Boolean = needsDisplayObject;
1999        layoutFeatures.layoutScaleY = value;
2000        invalidateTransform(previous != needsDisplayObject);
2001    }
2002
2003    //----------------------------------
2004    //  scaleZ
2005    //----------------------------------
2006
2007    [Inspectable(category="General")]
2008
2009    /**
2010     *  The z scale (percentage) of the element
2011     *  as applied from the transform point.
2012     *
2013     *  @langversion 3.0
2014     *  @playerversion Flash 10
2015     *  @playerversion AIR 1.5
2016     *  @productversion Flex 4
2017     */
2018    public function get scaleZ():Number
2019    {
2020        return (layoutFeatures == null)? 1:layoutFeatures.layoutScaleZ;
2021    }
2022
2023    /**
2024     *  @private
2025     */
2026    public function set scaleZ(value:Number):void
2027    {
2028        if (scaleZ == value)
2029            return;
2030
2031        allocateLayoutFeatures();
2032        var previous:Boolean = needsDisplayObject;
2033        layoutFeatures.layoutScaleZ = value;
2034        invalidateTransform(previous != needsDisplayObject);
2035    }
2036
2037    //----------------------------------
2038    //  top
2039    //----------------------------------
2040
2041    /**
2042     *  @private
2043     *  Storage for the top property.
2044     */
2045    private var _top:Object;
2046
2047    [Inspectable(category="General")]
2048
2049    /**
2050     *  @inheritDoc
2051     *
2052     *  @langversion 3.0
2053     *  @playerversion Flash 10
2054     *  @playerversion AIR 1.5
2055     *  @productversion Flex 4
2056     */
2057    public function get top():Object
2058    {
2059        return _top;
2060    }
2061
2062    /**
2063     *  @private
2064     */
2065    public function set top(value:Object):void
2066    {
2067        if (_top == value)
2068            return;
2069
2070        _top = value;
2071        invalidateParentSizeAndDisplayList();
2072    }
2073
2074    //----------------------------------
2075    //  transform
2076    //----------------------------------
2077
2078    /**
2079     *  @private
2080     *  Storage for the transform property.
2081     */
2082    private var _transform:flash.geom.Transform;
2083
2084    /**
2085     *  @copy mx.core.IFlexDisplayObject#transform
2086     *
2087     *  @langversion 3.0
2088     *  @playerversion Flash 10
2089     *  @playerversion AIR 1.5
2090     *  @productversion Flex 4
2091     */
2092    public function get transform():flash.geom.Transform
2093    {
2094        if (!_transform)
2095            setTransform(new mx.geom.Transform());
2096
2097        return _transform;
2098    }
2099
2100    /**
2101     *  @private
2102     */
2103    public function set transform(value:flash.geom.Transform):void
2104    {
2105        // TODO (jszeto): Add perspectiveProjection support
2106        var matrix:Matrix = value && value.matrix ? value.matrix.clone() : null;
2107        var matrix3D:Matrix3D = value && value.matrix3D ? value.matrix3D.clone() : null;
2108        var colorTransform:ColorTransform = value ? value.colorTransform : null;
2109
2110        var mxTransform:mx.geom.Transform = value as mx.geom.Transform;
2111        if (mxTransform)
2112        {
2113            if (!mxTransform.applyMatrix)
2114                matrix = null;
2115
2116            if (!mxTransform.applyMatrix3D)
2117                matrix3D = null;
2118        }
2119
2120        setTransform(value);
2121
2122        var previous:Boolean = needsDisplayObject;
2123
2124        if (_transform)
2125        {
2126            allocateLayoutFeatures();
2127
2128            if (matrix != null)
2129            {
2130                layoutFeatures.layoutMatrix = matrix;
2131            }
2132            else if (matrix3D != null)
2133            {
2134                layoutFeatures.layoutMatrix3D = matrix3D;
2135            }
2136        }
2137
2138
2139        applyColorTransform(colorTransform, mxTransform && mxTransform.applyColorTransformAlpha);
2140
2141        invalidateTransform(previous != needsDisplayObject);
2142    }
2143
2144    /**
2145     * @private
2146     */
2147    private function setTransform(value:flash.geom.Transform):void
2148    {
2149        // Clean up the old transform
2150        var oldTransform:mx.geom.Transform = _transform as mx.geom.Transform;
2151        if (oldTransform)
2152            oldTransform.target = null;
2153
2154        var newTransform:mx.geom.Transform = value as mx.geom.Transform;
2155
2156        if (newTransform)
2157            newTransform.target = this;
2158
2159        _transform = value;
2160    }
2161
2162    /**
2163     * @private
2164     *
2165     * Sets the colorTransform property of the transform. Called by mx.geom.Transform
2166     * when its colorTransform property has been changed.
2167     */
2168    public function setColorTransform(value:ColorTransform):void
2169    {
2170        applyColorTransform(value, true);
2171    }
2172
2173    /**
2174     * @private
2175     */
2176    private function applyColorTransform(value:ColorTransform, updateAlpha:Boolean):void
2177    {
2178        if (_colorTransform != value)
2179        {
2180            var previous:Boolean = needsDisplayObject;
2181            // Make a copy of the colorTransform
2182            _colorTransform = new ColorTransform(value.redMultiplier, value.greenMultiplier, value.blueMultiplier, value.alphaMultiplier,
2183                value.redOffset, value.greenOffset, value.blueOffset, value.alphaOffset);
2184
2185            if (updateAlpha)
2186            {
2187                _alpha = value.alphaMultiplier;
2188                _effectiveAlpha = _alpha;
2189            }
2190
2191            if (displayObject && displayObjectSharingMode == DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT)
2192            {
2193                displayObject.transform.colorTransform = _colorTransform;
2194            }
2195            else
2196            {
2197                colorTransformChanged = true;
2198                invalidateProperties();
2199                if (previous != needsDisplayObject)
2200                    invalidateDisplayObjectSharing();
2201            }
2202        }
2203    }
2204
2205    /**
2206     * @private
2207     */
2208    private function isAIMBlendMode(value:String):Boolean
2209    {
2210        if (value == "colordodge" ||
2211            value =="colorburn" || value =="exclusion" ||
2212            value =="softlight" || value =="hue" ||
2213            value =="saturation" || value =="color" ||
2214            value =="luminosity")
2215            return true;
2216        else return false;
2217    }
2218
2219    /**
2220     *  @copy mx.core.ILayoutElement#transformAround()
2221     *
2222     *  @langversion 3.0
2223     *  @playerversion Flash 10
2224     *  @playerversion AIR 1.5
2225     *  @productversion Flex 4
2226     */
2227    public function transformAround(transformCenter:Vector3D,
2228                                    scale:Vector3D = null,
2229                                    rotation:Vector3D = null,
2230                                    translation:Vector3D = null,
2231                                    postLayoutScale:Vector3D = null,
2232                                    postLayoutRotation:Vector3D = null,
2233                                    postLayoutTranslation:Vector3D = null,
2234                                    invalidateLayout:Boolean = true):void
2235    {
2236        // TODO (egreenfi): optimize for simple translations
2237        allocateLayoutFeatures();
2238        var previous:Boolean = needsDisplayObject;
2239        var prevX:Number = layoutFeatures.layoutX;
2240        var prevY:Number = layoutFeatures.layoutY;
2241        var prevZ:Number = layoutFeatures.layoutZ;
2242        layoutFeatures.transformAround(transformCenter,scale,rotation,translation,postLayoutScale,postLayoutRotation,postLayoutTranslation);
2243        invalidateTransform(previous != needsDisplayObject, invalidateLayout);
2244        if (prevX != layoutFeatures.layoutX)
2245            dispatchPropertyChangeEvent("x", prevX, layoutFeatures.layoutX);
2246        if (prevY != layoutFeatures.layoutY)
2247            dispatchPropertyChangeEvent("y", prevY, layoutFeatures.layoutY);
2248        if (prevZ != layoutFeatures.layoutZ)
2249            dispatchPropertyChangeEvent("z", prevZ, layoutFeatures.layoutZ);
2250    }
2251
2252    /**
2253     * A utility method to transform a point specified in the local
2254     * coordinates of this object to its location in the object's parent's
2255     * coordinates. The pre-layout and post-layout result will be set on
2256     * the <code>position</code> and <code>postLayoutPosition</code>
2257     * parameters, if they are non-null.
2258     *
2259     * @param localPosition The point to be transformed, specified in the
2260     * local coordinates of the object.
2261     * @param position A Vector3D point that will hold the pre-layout
2262     * result. If null, the parameter is ignored.
2263     * @param postLayoutPosition A Vector3D point that will hold the post-layout
2264     * result. If null, the parameter is ignored.
2265     *
2266     *  @langversion 3.0
2267     *  @playerversion Flash 10
2268     *  @playerversion AIR 1.5
2269     *  @productversion Flex 4
2270     */
2271    public function transformPointToParent(localPosition:Vector3D,
2272                                           position:Vector3D,
2273                                           postLayoutPosition:Vector3D):void
2274    {
2275        if (layoutFeatures != null)
2276        {
2277            layoutFeatures.transformPointToParent(true, localPosition, position,
2278                postLayoutPosition);
2279        }
2280        else
2281        {
2282            var xformPt:Point = new Point();
2283            if (localPosition)
2284            {
2285                xformPt.x = localPosition.x;
2286                xformPt.y = localPosition.y;
2287            }
2288            if (position != null)
2289            {
2290                position.x = xformPt.x + _x;
2291                position.y = xformPt.y + _y;
2292                position.z = 0;
2293            }
2294            if (postLayoutPosition != null)
2295            {
2296                postLayoutPosition.x = xformPt.x + _x;
2297                postLayoutPosition.y = xformPt.y + _y;
2298                postLayoutPosition.z = 0;
2299            }
2300        }
2301    }
2302
2303    //----------------------------------
2304    //  transformX
2305    //----------------------------------
2306
2307    [Inspectable(category="General")]
2308
2309    /**
2310     *  The x position transform point of the element.
2311     *
2312     *  @langversion 3.0
2313     *  @playerversion Flash 10
2314     *  @playerversion AIR 1.5
2315     *  @productversion Flex 4
2316     */
2317    public function get transformX():Number
2318    {
2319        return (layoutFeatures == null)? 0:layoutFeatures.transformX;
2320    }
2321
2322    /**
2323     *  @private
2324     */
2325    public function set transformX(value:Number):void
2326    {
2327        if (transformX  == value)
2328            return;
2329
2330        allocateLayoutFeatures();
2331        layoutFeatures.transformX = value;
2332        invalidateTransform(false);
2333    }
2334
2335    //----------------------------------
2336    //  transformY
2337    //----------------------------------
2338
2339    [Inspectable(category="General")]
2340
2341    /**
2342     *  The y position transform point of the element.
2343     *
2344     *  @langversion 3.0
2345     *  @playerversion Flash 10
2346     *  @playerversion AIR 1.5
2347     *  @productversion Flex 4
2348     */
2349    public function get transformY():Number
2350    {
2351        return (layoutFeatures == null)? 0:layoutFeatures.transformY;
2352    }
2353
2354    /**
2355     *  @private
2356     */
2357    public function set transformY(value:Number):void
2358    {
2359        if (transformY == value)
2360            return;
2361
2362        allocateLayoutFeatures();
2363        layoutFeatures.transformY = value;
2364        invalidateTransform(false);
2365    }
2366
2367    //----------------------------------
2368    //  transformZ
2369    //----------------------------------
2370
2371    [Inspectable(category="General")]
2372
2373    /**
2374     *  The z position transform point of the element.
2375     *
2376     *  @langversion 3.0
2377     *  @playerversion Flash 10
2378     *  @playerversion AIR 1.5
2379     *  @productversion Flex 4
2380     */
2381    public function get transformZ():Number
2382    {
2383        return (layoutFeatures == null)? 0:layoutFeatures.transformZ;
2384    }
2385
2386    /**
2387     *  @private
2388     */
2389    public function set transformZ(value:Number):void
2390    {
2391        if (transformZ == value)
2392            return;
2393
2394        allocateLayoutFeatures();
2395        var previous:Boolean = needsDisplayObject;
2396        layoutFeatures.transformZ = value;
2397        invalidateTransform(previous != needsDisplayObject);
2398    }
2399
2400    //----------------------------------
2401    //  verticalCenter
2402    //----------------------------------
2403
2404    /**
2405     *  @private
2406     *  Storage for the verticalCenter property.
2407     */
2408    private var _verticalCenter:Object;
2409
2410    [Inspectable(category="General")]
2411
2412    /**
2413     *  @inheritDoc
2414     *
2415     *  @langversion 3.0
2416     *  @playerversion Flash 10
2417     *  @playerversion AIR 1.5
2418     *  @productversion Flex 4
2419     */
2420    public function get verticalCenter():Object
2421    {
2422        return _verticalCenter;
2423    }
2424
2425    /**
2426     *  @private
2427     */
2428    public function set verticalCenter(value:Object):void
2429    {
2430        if (_verticalCenter == value)
2431            return;
2432
2433        _verticalCenter = value;
2434        invalidateParentSizeAndDisplayList();
2435    }
2436
2437    //----------------------------------
2438    //  width
2439    //----------------------------------
2440
2441    /**
2442     *  @private
2443     *  Storage for the width property.
2444     */
2445    mx_internal var _width:Number = 0;
2446
2447    [Bindable("propertyChange")]
2448    [Inspectable(category="General")]
2449    [PercentProxy("percentWidth")]
2450
2451    /**
2452     *  The width of the graphic element.
2453     *
2454     *  @default 0
2455     *
2456     *  @langversion 3.0
2457     *  @playerversion Flash 10
2458     *  @playerversion AIR 1.5
2459     *  @productversion Flex 4
2460     */
2461    public function get width():Number
2462    {
2463        return _width;
2464    }
2465
2466    /**
2467     *  @private
2468     */
2469    public function set width(value:Number):void
2470    {
2471        explicitWidth = value;
2472
2473        if (_width == value)
2474            return;
2475
2476        var oldValue:Number = _width;
2477        _width = value;
2478
2479        // The width is needed for the mirroring transform.
2480        if (layoutFeatures)
2481        {
2482            layoutFeatures.layoutWidth = value;
2483            invalidateTransform();
2484        }
2485
2486        dispatchPropertyChangeEvent("width", oldValue, value);
2487
2488        // Invalidate the display list, since we're changing the actual width
2489        // and we're not going to correctly detect whether the layout sets
2490        // new actual width different from our previous value.
2491        invalidateDisplayList();
2492    }
2493
2494    //----------------------------------
2495    //  depth
2496    //----------------------------------
2497
2498    /**
2499     *  @inheritDoc
2500     *
2501     *  @langversion 3.0
2502     *  @playerversion Flash 10
2503     *  @playerversion AIR 1.5
2504     *  @productversion Flex 4
2505     */
2506    public function get depth():Number
2507    {
2508        return (layoutFeatures == null) ? 0 : layoutFeatures.depth;
2509    }
2510
2511    /**
2512     *  @private
2513     */
2514    public function set depth(value:Number):void
2515    {
2516        if (value == depth)
2517            return;
2518
2519        allocateLayoutFeatures();
2520        layoutFeatures.depth = value;
2521        if (_parent is UIComponent)
2522            UIComponent(_parent).invalidateLayering();
2523        invalidateProperties();
2524    }
2525
2526    //----------------------------------
2527    //  x
2528    //----------------------------------
2529
2530    [Bindable("propertyChange")]
2531    [Inspectable(category="General")]
2532
2533    /**
2534     *  The x position of the graphic element.
2535     *
2536     *  @langversion 3.0
2537     *  @playerversion Flash 10
2538     *  @playerversion AIR 1.5
2539     *  @productversion Flex 4
2540     */
2541    public function get x():Number
2542    {
2543        return (layoutFeatures == null)? _x:layoutFeatures.layoutX;
2544    }
2545
2546    /**
2547     *  @private
2548     */
2549    public function set x(value:Number):void
2550    {
2551        var oldValue:Number = x;
2552        if (oldValue == value)
2553            return;
2554
2555        if (layoutFeatures != null)
2556            layoutFeatures.layoutX = value;
2557        else
2558            _x = value;
2559
2560        dispatchPropertyChangeEvent("x", oldValue, value);
2561        invalidateTransform(false);
2562    }
2563
2564    //----------------------------------
2565    //  y
2566    //----------------------------------
2567
2568    [Bindable("propertyChange")]
2569    [Inspectable(category="General")]
2570
2571    /**
2572     *  The y position of the graphic element.
2573     *
2574     *  @langversion 3.0
2575     *  @playerversion Flash 10
2576     *  @playerversion AIR 1.5
2577     *  @productversion Flex 4
2578     */
2579    public function get y():Number
2580    {
2581        return (layoutFeatures == null)? _y:layoutFeatures.layoutY;
2582    }
2583
2584    /**
2585     *  @private
2586     */
2587    public function set y(value:Number):void
2588    {
2589        var oldValue:Number = y;
2590        if (oldValue == value)
2591            return;
2592
2593        if (layoutFeatures != null)
2594            layoutFeatures.layoutY = value;
2595        else
2596            _y = value;
2597        dispatchPropertyChangeEvent("y", oldValue, value);
2598        invalidateTransform(false);
2599    }
2600
2601    //----------------------------------
2602    //  z
2603    //----------------------------------
2604
2605    [Bindable("propertyChange")]
2606    [Inspectable(category="General")]
2607
2608    /**
2609     *  The z position of the graphic element.
2610     *
2611     *  @langversion 3.0
2612     *  @playerversion Flash 10
2613     *  @playerversion AIR 1.5
2614     *  @productversion Flex 4
2615     */
2616    public function get z():Number
2617    {
2618        return (layoutFeatures == null)? 0:layoutFeatures.layoutZ;
2619    }
2620
2621    /**
2622     *  @private
2623     */
2624    public function set z(value:Number):void
2625    {
2626        if (z == value)
2627            return;
2628        var oldValue:Number = z;
2629
2630        allocateLayoutFeatures();
2631        var previous:Boolean = needsDisplayObject;
2632        layoutFeatures.layoutZ = value;
2633        invalidateTransform(previous != needsDisplayObject);
2634        dispatchPropertyChangeEvent("z", oldValue, value);
2635    }
2636
2637    //----------------------------------
2638    //  visible
2639    //----------------------------------
2640
2641    /**
2642     *  @private
2643     *  Storage for the visible property.
2644     */
2645    private var _visible:Boolean = true;
2646
2647
2648    /**
2649     *  @private
2650     *  The actual 'effective' visibility of this
2651     *  element, one that considers the visibility of
2652     *  the owning design layer parent (if any).
2653     */
2654    protected var _effectiveVisibility:Boolean = true;
2655
2656    /**
2657     *  @private
2658     */
2659    private var visibleChanged:Boolean;
2660
2661    [Inspectable(category="General")]
2662
2663    /**
2664     *  @inheritDoc
2665     *
2666     *  @langversion 3.0
2667     *  @playerversion Flash 10
2668     *  @playerversion AIR 1.5
2669     *  @productversion Flex 4
2670     */
2671    public function get visible():Boolean
2672    {
2673        return _visible;
2674    }
2675
2676    /**
2677     *  @private
2678     */
2679    public function set visible(value:Boolean):void
2680    {
2681        _visible = value;
2682
2683        if (designLayer && !designLayer.effectiveVisibility)
2684            value = false;
2685
2686        if (_effectiveVisibility == value)
2687            return;
2688
2689        _effectiveVisibility = value;
2690        visibleChanged = true;
2691        invalidateProperties();
2692    }
2693
2694    //--------------------------------------------------------------------------
2695    //
2696    //  Properties: IDisplayObjectElement
2697    //
2698    //--------------------------------------------------------------------------
2699
2700    //----------------------------------
2701    //  displayObject
2702    //----------------------------------
2703
2704    /**
2705     *  @private
2706     *  Storage for the displayObject property.
2707     */
2708    private var _displayObject:DisplayObject;
2709
2710    [Bindable("propertyChange")]
2711    [Inspectable(category="General")]
2712
2713    /**
2714     *  @inheritDoc
2715     *
2716     *  @langversion 3.0
2717     *  @playerversion Flash 10
2718     *  @playerversion AIR 1.5
2719     *  @productversion Flex 4
2720     */
2721    public function get displayObject():DisplayObject
2722    {
2723        return _displayObject;
2724    }
2725
2726    /**
2727     *  @private
2728     */
2729    protected function setDisplayObject(value:DisplayObject):void
2730    {
2731        if (_displayObject == value)
2732            return;
2733
2734        var oldValue:DisplayObject = _displayObject;
2735
2736        // If we owned the old display object and we have assigned a 3D matrix,
2737        // clear it from the display object so that we can set it in the new
2738        // display object. A Matrix3D object can't be used simultaneously with
2739        // more than one display object.
2740        if (oldValue && displayObjectSharingMode == DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT)
2741            oldValue.transform.matrix3D = null;
2742
2743        _displayObject = value;
2744        dispatchPropertyChangeEvent("displayObject", oldValue, value);
2745
2746        // We need to apply the display object related properties.
2747        displayObjectChanged = true;
2748        invalidateProperties();
2749    }
2750
2751    //--------------------------------------------------------------------------
2752    //
2753    //  Properties
2754    //
2755    //--------------------------------------------------------------------------
2756
2757    //----------------------------------
2758    //  drawX
2759    //----------------------------------
2760
2761    /**
2762     *  The x position where the element should be drawn.
2763     *
2764     *  @langversion 3.0
2765     *  @playerversion Flash 10
2766     *  @playerversion AIR 1.5
2767     *  @productversion Flex 4
2768     */
2769    protected function get drawX():Number
2770    {
2771        // If we don't share the display object, we will draw at 0,0
2772        // since the display object will be positioned at x,y
2773        if (displayObjectSharingMode == DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT)
2774            return 0;
2775
2776        // Otherwise we draw at x,y since the display object will be
2777        // positioned at 0,0
2778        if (layoutFeatures != null && layoutFeatures.postLayoutTransformOffsets != null)
2779            return x + layoutFeatures.postLayoutTransformOffsets.x;
2780
2781        return x;
2782    }
2783
2784    //----------------------------------
2785    //  drawY
2786    //----------------------------------
2787
2788    /**
2789     *  The y position where the element should be drawn.
2790     *
2791     *  @langversion 3.0
2792     *  @playerversion Flash 10
2793     *  @playerversion AIR 1.5
2794     *  @productversion Flex 4
2795     */
2796    protected function get drawY():Number
2797    {
2798        // If we don't share the display object, we will draw at 0,0
2799        // since the display object will be positioned at x,y
2800        if (displayObjectSharingMode == DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT)
2801            return 0;
2802
2803        // Otherwise we draw at x,y since the display object will be
2804        // positioned at 0,0
2805        if (layoutFeatures != null && layoutFeatures.postLayoutTransformOffsets != null)
2806            return y + layoutFeatures.postLayoutTransformOffsets.y;
2807
2808        return y;
2809    }
2810
2811    //----------------------------------
2812    //  hasComplexLayoutMatrix
2813    //----------------------------------
2814
2815    /**
2816     *  Returns true if the GraphicElement has any non-translation (x,y) transform properties
2817     *
2818     *  @langversion 3.0
2819     *  @playerversion Flash 10
2820     *  @playerversion AIR 1.5
2821     *  @productversion Flex 4
2822     */
2823    protected function get hasComplexLayoutMatrix():Boolean
2824    {
2825        return (layoutFeatures == null ? false : !MatrixUtil.isDeltaIdentity(layoutFeatures.layoutMatrix));
2826    }
2827
2828    //----------------------------------
2829    //  includeInLayout
2830    //----------------------------------
2831
2832    /**
2833     *  @private
2834     *  Storage for the includeInLayout property.
2835     */
2836    private var _includeInLayout:Boolean = true;
2837
2838    [Inspectable(category="General", defaultValue="true")]
2839
2840    /**
2841     *  Specifies whether this element is included in the layout of the parent.
2842     *
2843     *  @default true
2844     *
2845     *  @langversion 3.0
2846     *  @playerversion Flash 10
2847     *  @playerversion AIR 1.5
2848     *  @productversion Flex 4
2849     */
2850    public function get includeInLayout():Boolean
2851    {
2852        return _includeInLayout;
2853    }
2854
2855    /**
2856     *  @private
2857     */
2858    public function set includeInLayout(value:Boolean):void
2859    {
2860        if (_includeInLayout == value)
2861            return;
2862
2863        // Temporarily set includeInLayout to true so that
2864        // invalidating the parent doesn't return early.
2865        _includeInLayout = true;
2866        invalidateParentSizeAndDisplayList();
2867
2868        _includeInLayout = value;
2869    }
2870
2871    //----------------------------------
2872    //  displayObjectSharingMode
2873    //----------------------------------
2874
2875    private var _displayObjectSharingMode:String;
2876
2877    [Inspectable(category="General", enumeration="ownsUnsharedObject,ownsSharedObject,usesSharedObject")]
2878
2879    /**
2880     *  @private
2881     */
2882    public function set displayObjectSharingMode(value:String):void
2883    {
2884        if (value == _displayObjectSharingMode)
2885            return;
2886
2887        if (value != DisplayObjectSharingMode.USES_SHARED_OBJECT ||
2888            _displayObjectSharingMode != DisplayObjectSharingMode.USES_SHARED_OBJECT)
2889        {
2890            // If the element was previously at the head of the shared sequence or
2891            // it is assigned to be at the head, make sure to reapply the
2892            // displayObject specific properties.
2893            displayObjectChanged = true;
2894            invalidateProperties();
2895        }
2896        _displayObjectSharingMode = value;
2897    }
2898
2899    /**
2900     *  @inheritDoc
2901     *
2902     *  @langversion 3.0
2903     *  @playerversion Flash 10
2904     *  @playerversion AIR 1.5
2905     *  @productversion Flex 4
2906     */
2907    public function get displayObjectSharingMode():String
2908    {
2909        return _displayObjectSharingMode;
2910    }
2911
2912    //----------------------------------
2913    //  layoutDirection
2914    //----------------------------------
2915
2916    private var _layoutDirection:String = null;
2917
2918    [Inspectable(category="General", enumeration="ltr,rtl")]
2919
2920    /**
2921     *  @inheritDoc
2922     *
2923     *  @langversion 3.0
2924     *  @playerversion Flash 10
2925     *  @playerversion AIR 1.5
2926     *  @productversion Flex 4
2927     */
2928    public function get layoutDirection():String
2929    {
2930        if (_layoutDirection != null)
2931            return _layoutDirection;
2932
2933        const parentElt:ILayoutDirectionElement = parent as ILayoutDirectionElement;
2934        return (parentElt) ? parentElt.layoutDirection : LayoutDirection.LTR;
2935    }
2936
2937    /**
2938     *  @private
2939     */
2940    public function set layoutDirection(value:String):void
2941    {
2942        if (_layoutDirection == value)
2943            return;
2944
2945        _layoutDirection = value;
2946        invalidateLayoutDirection();
2947    }
2948
2949    /**
2950     * @inheritDoc
2951     *
2952     *  @langversion 3.0
2953     *  @playerversion Flash 10
2954     *  @playerversion AIR 1.5
2955     *  @productversion Flex 4
2956     */
2957    public function invalidateLayoutDirection():void
2958    {
2959        const parentElt:ILayoutDirectionElement = parent as ILayoutDirectionElement;
2960        if (!parentElt)
2961            return;
2962
2963        // If this element's layoutDirection doesn't match its parent's, then
2964        // set the layoutFeatures.mirror flag.  Similarly, if mirroring isn't
2965        // required, then clear the layoutFeatures.mirror flag.
2966
2967        const mirror:Boolean = (parentElt.layoutDirection != null && _layoutDirection != null)
2968            && (_layoutDirection != parentElt.layoutDirection);
2969
2970        if ((layoutFeatures) ? (mirror != layoutFeatures.mirror) : mirror)
2971        {
2972            if (layoutFeatures == null)
2973                allocateLayoutFeatures();
2974            var previous:Boolean = needsDisplayObject;
2975            layoutFeatures.mirror = mirror;
2976            invalidateTransform(previous != needsDisplayObject);
2977        }
2978    }
2979
2980    //--------------------------------------------------------------------------
2981    //
2982    //  Methods
2983    //
2984    //--------------------------------------------------------------------------
2985
2986    /**
2987     *  Called automatically by the MXML compiler when the GraphicElement
2988     *  is created using an MXML tag.
2989     *  If you create the GraphicElement through ActionScript you must set the
2990     * <code>id</code> property manually.
2991     *
2992     *  @param document The MXML document containing this GraphicElement (not used).
2993     *  @param id The MXML id for this GraphicElement.
2994     *
2995     *  @langversion 3.0
2996     *  @playerversion Flash 10
2997     *  @playerversion AIR 1.5
2998     *  @productversion Flex 4
2999     */
3000    public function initialized(document:Object, id:String):void
3001    {
3002        this.id = id;
3003    }
3004
3005    /**
3006     * Converts the point object from the object's (local) coordinates
3007     * to the Stage (global) coordinates.
3008     *
3009     * <p>This method allows you to convert any given x and y coordinates from
3010     * values that are relative to the origin (0,0) of a specific object
3011     * (local coordinates) to values that are relative to the origin
3012     * of the Stage (global coordinates).</p>
3013     *
3014     * <p>To use this method, first create an instance of the Point class.
3015     * The x and y values that you assign represent local coordinates
3016     * because they relate to the origin of the object.</p>
3017     *
3018     * <p>You then pass the Point instance that you created as the parameter
3019     * to the localToGlobal() method. The method returns a new Point object
3020     * with x and y values that relate to the origin of the Stage instead of
3021     * the origin of the object.</p>
3022     *
3023     * @param point The name or identifier of a point created with the Point
3024     * class, specifying the x and y coordinates as properties.
3025     *
3026     * @return A Point object with coordinates relative to the Stage.
3027     *
3028     * @see flash.display.DisplayObject#localToGlobal
3029     *
3030     *  @langversion 3.0
3031     *  @playerversion Flash 10
3032     *  @playerversion AIR 1.5
3033     *  @productversion Flex 4
3034     */
3035    public function localToGlobal(point:Point):Point
3036    {
3037        // If there is not yet a displayObject or it's not parented, just
3038        // return its local position
3039        if (!displayObject || !displayObject.parent)
3040            return new Point(x, y);
3041
3042        var returnVal:Point = displayObject.localToGlobal(point);
3043
3044        if (!needsDisplayObject)
3045        {
3046            // If we're sharing the displayObject, add in our offset
3047            returnVal.x += drawX;
3048            returnVal.y += drawY;
3049        }
3050
3051        return returnVal;
3052    }
3053
3054    /**
3055     *  @inheritDoc
3056     *
3057     *  @langversion 3.0
3058     *  @playerversion Flash 10
3059     *  @playerversion AIR 1.5
3060     *  @productversion Flex 4
3061     */
3062    public function createDisplayObject():DisplayObject
3063    {
3064        setDisplayObject(new InvalidatingSprite());
3065        return displayObject;
3066    }
3067
3068    /**
3069     *  True if the element requires an exclusive DisplayObject.
3070     *
3071     *  Developers don't usually call this method directly, but override it in
3072     *  their subclasses to indicate that an exclusive DisplayObject is needed.
3073     *
3074     *  Usually a subclass needs a DisplayObject when it has to set its properties.
3075     *
3076     *  Some examples of such DisplayObject properties are <code>filters</code>,
3077     *  <code>blendMode</code>, <code>mask</code>,
3078     *  <code>rotation</code>, <code>alpha</code>.
3079     *
3080     *  @return Returns true when the element requires an exclusive DisplayObject.
3081     *
3082     *  @langversion 3.0
3083     *  @playerversion Flash 10
3084     *  @playerversion AIR 1.5
3085     *  @productversion Flex 4
3086     */
3087    protected function get needsDisplayObject():Boolean
3088    {
3089        var result:Boolean = (alwaysCreateDisplayObject ||
3090        (_filters && _filters.length > 0) ||
3091            (_blendMode != BlendMode.NORMAL && _blendMode != "auto") || _mask ||
3092            (layoutFeatures != null && (layoutFeatures.layoutScaleX != 1 || layoutFeatures.layoutScaleY != 1 || layoutFeatures.layoutScaleZ != 1 ||
3093            layoutFeatures.layoutRotationX != 0 || layoutFeatures.layoutRotationY != 0 || layoutFeatures.layoutRotationZ != 0 ||
3094            layoutFeatures.layoutZ  != 0 || layoutFeatures.mirror)) ||
3095            _colorTransform != null ||
3096            _effectiveAlpha != 1);
3097
3098        if (layoutFeatures != null && layoutFeatures.postLayoutTransformOffsets != null)
3099        {
3100            var o:TransformOffsets = layoutFeatures.postLayoutTransformOffsets;
3101            result = result || (o.scaleX != 1 || o.scaleY != 1 || o.scaleZ != 1 ||
3102            o.rotationX != 0 || o.rotationY != 0 || o.rotationZ != 0 || o.z  != 0);
3103        }
3104
3105        return result;
3106    }
3107
3108    /**
3109     *  @inheritDoc
3110     *
3111     *  @langversion 3.0
3112     *  @playerversion Flash 10
3113     *  @playerversion AIR 1.5
3114     *  @productversion Flex 4
3115     */
3116    public function setSharedDisplayObject(sharedDisplayObject:DisplayObject):Boolean
3117    {
3118        if (!(sharedDisplayObject is Sprite) || _alwaysCreateDisplayObject || needsDisplayObject)
3119            return false;
3120        setDisplayObject(sharedDisplayObject);
3121        return true;
3122    }
3123
3124    /**
3125     *  @inheritDoc
3126     *
3127     *  @langversion 3.0
3128     *  @playerversion Flash 10
3129     *  @playerversion AIR 1.5
3130     *  @productversion Flex 4
3131     */
3132    public function canShareWithPrevious(element:IGraphicElement):Boolean
3133    {
3134        // No need to check _alwaysCreateDisplayObject or needsDisplayObject,
3135        // as those will be checked in setSharedDisplayObject
3136        return element is GraphicElement;
3137    }
3138
3139    /**
3140     *  @inheritDoc
3141     *
3142     *  @langversion 3.0
3143     *  @playerversion Flash 10
3144     *  @playerversion AIR 1.5
3145     *  @productversion Flex 4
3146     */
3147    public function canShareWithNext(element:IGraphicElement):Boolean
3148    {
3149        return element is GraphicElement && !_alwaysCreateDisplayObject && !needsDisplayObject;
3150    }
3151
3152    /**
3153     *  The actual DisplayObject that is drawn into by the GraphicElement. Typically this is
3154     *  equivalent to the <code>displayObject</code> property. Subclasses should perform drawing commands on
3155     *  this property instead of on <code>displayObject</code>.
3156     *
3157     *  @langversion 3.0
3158     *  @playerversion Flash 10
3159     *  @playerversion AIR 1.5
3160     *  @productversion Flex 4
3161     */
3162    protected function get drawnDisplayObject():DisplayObject
3163    {
3164        // _drawnDisplayObject is non-null if we needed to create a mask
3165        return _drawnDisplayObject ? _drawnDisplayObject : displayObject;
3166    }
3167
3168    /**
3169     *  Returns a bitmap snapshot of the GraphicElement.
3170     *  The bitmap contains all transformations and is reduced
3171     *  to fit the visual bounds of the object.
3172     *
3173     *  @param transparent Whether or not the bitmap image supports per-pixel transparency.
3174     *  The default value is true (transparent). To create a fully transparent bitmap, set the value of the
3175     *  transparent parameter to true and the value of the fillColor parameter to 0x00000000 (or to 0).
3176     *  Setting the transparent property to false can result in minor improvements in rendering performance.
3177     *
3178     *  @param fillColor A 32-bit ARGB color value that you use to fill the bitmap image area.
3179     *  The default value is 0xFFFFFFFF (solid white).
3180     *
3181     *  @param useLocalSpace Whether or not the bitmap shows the GraphicElement in the local or global
3182     *  coordinate space. If true, then the snapshot is in the local space. The default value is true.
3183     *
3184     *  @param clipRect A Rectangle object that defines the area of the source object to draw.
3185     *  If you do not supply this value, no clipping occurs and the entire source object is drawn.
3186     *  The clipRect should be defined in the coordinate space specified by useLocalSpace
3187     *
3188     *  @return A bitmap snapshot of the GraphicElement or null if the input element has no visible bounds.
3189     *
3190     *
3191     *  @langversion 3.0
3192     *  @playerversion Flash 10
3193     *  @playerversion AIR 1.5
3194     *  @productversion Flex 4
3195     */
3196    mx_internal function captureBitmapData(transparent:Boolean = true, fillColor:uint = 0xFFFFFFFF, useLocalSpace:Boolean = true, clipRect:Rectangle = null):BitmapData
3197    {
3198        if (!layoutFeatures || !layoutFeatures.is3D)
3199        {
3200            var restoreDisplayObject:Boolean = false;
3201            var oldDisplayObject:DisplayObject;
3202
3203            if (!displayObject || displayObjectSharingMode != DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT)
3204            {
3205                restoreDisplayObject = true;
3206                oldDisplayObject = displayObject;
3207                setDisplayObject(new InvalidatingSprite());
3208                if (parent is UIComponent)
3209                    UIComponent(parent).$addChild(displayObject);
3210                else
3211                    parent.addChild(displayObject);
3212                invalidateDisplayList();
3213                validateDisplayList();
3214            }
3215
3216            var topLevel:Sprite = Sprite(IUIComponent(parent).systemManager.getSandboxRoot());
3217            var rectBounds:Rectangle = useLocalSpace ?
3218                        new Rectangle(getLayoutBoundsX(), getLayoutBoundsY(), getLayoutBoundsWidth(), getLayoutBoundsHeight()) :
3219                        displayObject.getBounds(topLevel);
3220
3221            if (rectBounds.width == 0 || rectBounds.height == 0)
3222                return null;
3223
3224            var bitmapData:BitmapData = new BitmapData(Math.ceil(rectBounds.width), Math.ceil(rectBounds.height), transparent, fillColor);
3225
3226            // Can't use target's concatenatedMatrix, as it is sometimes wrong
3227            var m:Matrix = useLocalSpace ?
3228                displayObject.transform.matrix :
3229                MatrixUtil.getConcatenatedMatrix(displayObject, null);
3230
3231            if (m)
3232                m.translate(-rectBounds.x, -rectBounds.y);
3233
3234            bitmapData.draw(displayObject, m, null, null, clipRect);
3235
3236            if (restoreDisplayObject)
3237            {
3238                if (parent is UIComponent)
3239                    UIComponent(parent).$removeChild(displayObject);
3240                else
3241                    parent.removeChild(displayObject);
3242                setDisplayObject(oldDisplayObject);
3243            }
3244            return bitmapData;
3245
3246        }
3247        else
3248        {
3249            return get3DSnapshot(transparent, fillColor, useLocalSpace);
3250        }
3251    }
3252
3253   /**
3254     *  @private
3255     *  Returns a bitmap snapshot of a 3D transformed displayObject. Since BitmapData.draw ignores
3256     *  the transform matrix of its target when it draws, we need to parent the target in a temporary
3257     *  sprite and call BitmapData.draw on that temp sprite. We can't take a bitmap snapshot of the
3258     *  real parent because it might have other children.
3259     */
3260    private function get3DSnapshot(transparent:Boolean = true, fillColor:uint = 0xFFFFFFFF, useLocalSpace:Boolean = true):BitmapData
3261    {
3262        var topLevel:Sprite = Sprite(IUIComponent(parent).systemManager);
3263        var dispObjParent:DisplayObjectContainer = displayObject.parent;
3264        var drawSprite:Sprite = new Sprite();
3265
3266        // Get the visual bounds of the target in both local and global coordinates
3267        var topLevelRect:Rectangle = displayObject.getBounds(topLevel);
3268        var displayObjectRect:Rectangle = displayObject.getBounds(dispObjParent);
3269
3270        // Keep a reference to the original 3D matrix. We will restore this later.
3271        var oldMat3D:Matrix3D = displayObject.transform.matrix3D.clone();
3272
3273        // Get the concatenated 3D matrix which we will use to position the target when we reparent it
3274        var globalMat3D:Matrix3D = displayObject.transform.getRelativeMatrix3D(topLevel);
3275        var newMat3D:Matrix3D = oldMat3D.clone();
3276
3277
3278        // Remove the target from its current parent, making sure to store the child index
3279        var displayObjectIndex:int = parent.getChildIndex(displayObject);
3280        if (parent is UIComponent)
3281            UIComponent(parent).$removeChild(displayObject);
3282        else
3283            parent.removeChild(displayObject);
3284
3285        // Parent the target to the drawSprite and then attach the drawSprite to the stage
3286        topLevel.addChild(drawSprite);
3287        drawSprite.addChild(displayObject);
3288
3289        // Assign the globally translated matrix to the target
3290        if (useLocalSpace)
3291        {
3292            newMat3D.position = globalMat3D.position;
3293            displayObject.transform.matrix3D = newMat3D;
3294        }
3295        else
3296        {
3297            displayObject.transform.matrix3D = globalMat3D;
3298        }
3299        // Translate the bitmap so that the left-top bounds ends up at (0,0)
3300        var m:Matrix = new Matrix();
3301        m.translate(-topLevelRect.left, - topLevelRect.top);
3302
3303        // Draw to the bitmapData
3304        var snapshot:BitmapData = new BitmapData( topLevelRect.width, topLevelRect.height, transparent, fillColor);
3305        snapshot.draw(drawSprite, m, null, null, null, true);
3306
3307        // Remove target from temporary sprite and remove temp sprite from stage
3308        drawSprite.removeChild(displayObject);
3309        topLevel.removeChild(drawSprite);
3310
3311        // Reattach the target to its original parent at its original child position
3312        if (parent is UIComponent)
3313            UIComponent(parent).$addChildAt(displayObject, displayObjectIndex);
3314        else
3315            parent.addChildAt(displayObject, displayObjectIndex);
3316
3317        // Restore the original 3D matrix
3318        displayObject.transform.matrix3D = oldMat3D;
3319
3320        return snapshot;
3321    }
3322
3323    /**
3324     *  @private
3325     */
3326    protected function layer_PropertyChange(event:PropertyChangeEvent):void
3327    {
3328        switch (event.property)
3329        {
3330            case "effectiveVisibility":
3331            {
3332                var newValue:Boolean = (event.newValue && _visible);
3333
3334                if (newValue != _effectiveVisibility)
3335                {
3336                    _effectiveVisibility = newValue;
3337                    visibleChanged = true;
3338                    invalidateProperties();
3339                }
3340                break;
3341            }
3342            case "effectiveAlpha":
3343            {
3344                var newAlpha:Number = Number(event.newValue) * _alpha;
3345                if (newAlpha != _effectiveAlpha)
3346                {
3347                    _effectiveAlpha = newAlpha;
3348                    alphaChanged = true;
3349
3350                    var mxTransform:mx.geom.Transform = _transform as mx.geom.Transform;
3351                    if (mxTransform)
3352                        mxTransform.applyColorTransformAlpha = false;
3353
3354                    invalidateDisplayObjectSharing();
3355                    invalidateProperties();
3356                }
3357                break;
3358            }
3359        }
3360    }
3361
3362    /**
3363     *  Dispatches a propertyChange event.
3364     *
3365     *  @param prop The property that changed.
3366     *
3367     *  @param oldValue The previous value of the property.
3368     *
3369     *  @param value The new value of the property.
3370     *
3371     *  @langversion 3.0
3372     *  @playerversion Flash 10
3373     *  @playerversion AIR 1.5
3374     *  @productversion Flex 4
3375     */
3376    mx_internal function dispatchPropertyChangeEvent(prop:String, oldValue:*,
3377                                                   value:*):void
3378    {
3379        if (hasEventListener("propertyChange"))
3380            dispatchEvent(PropertyChangeEvent.createUpdateEvent(
3381                this, prop, oldValue, value));
3382
3383    }
3384
3385    /**
3386     *  Utility method that notifies the host that this element has changed and needs
3387     *  its layer to be updated.
3388     *
3389     *  @langversion 3.0
3390     *  @playerversion Flash 10
3391     *  @playerversion AIR 1.5
3392     *  @productversion Flex 4
3393     */
3394    protected function invalidateDisplayObjectSharing():void
3395    {
3396        if (parent)
3397            IGraphicElementContainer(parent).invalidateGraphicElementSharing(this);
3398    }
3399
3400    /**
3401     *  Calling this method results in a call to the elements's
3402     *  <code>validateProperties()</code> method
3403     *  before the display list is rendered.
3404     *
3405     *  <p>Subclasses should do their work in
3406     *  <code>commitProperties()</code>.</p>
3407     *
3408     *  @langversion 3.0
3409     *  @playerversion Flash 10
3410     *  @playerversion AIR 1.5
3411     *  @productversion Flex 4
3412     */
3413    public function invalidateProperties():void
3414    {
3415        if (invalidatePropertiesFlag)
3416            return;
3417        invalidatePropertiesFlag = true;
3418
3419        if (parent)
3420            IGraphicElementContainer(parent).invalidateGraphicElementProperties(this);
3421    }
3422
3423    /**
3424     *  Calling this method results in a call to the elements's
3425     *  <code>validateSize()</code> method
3426     *  before the display list is rendered.
3427     *
3428     *  <p>Subclasses should override and do their measurement in
3429     *  <code>measure()</code>.
3430     *  By default when <code>explicitWidth</code> and <code>explicitHeight</code>
3431     *  are set, <code>measure()</code> will not be called. To override this
3432     *  default behavior subclasses should override <code>skipMeasure()</code>.</p>
3433     *
3434     *  @langversion 3.0
3435     *  @playerversion Flash 10
3436     *  @playerversion AIR 1.5
3437     *  @productversion Flex 4
3438     */
3439    public function invalidateSize():void
3440    {
3441        if (invalidateSizeFlag)
3442            return;
3443        invalidateSizeFlag = true;
3444
3445        if (parent)
3446            IGraphicElementContainer(parent).invalidateGraphicElementSize(this);
3447    }
3448
3449    /**
3450     *  Helper method to invalidate parent size and display list if
3451     *  this object affects its layout (includeInLayout is true).
3452     *
3453     *  @langversion 3.0
3454     *  @playerversion Flash 10
3455     *  @playerversion AIR 1.5
3456     *  @productversion Flex 4
3457     */
3458    protected function invalidateParentSizeAndDisplayList():void
3459    {
3460        if (!includeInLayout)
3461            return;
3462
3463        // We want to invalidate both the parent size and parent display list.
3464        if (parent && parent is IInvalidating)
3465        {
3466            IInvalidating(parent).invalidateSize();
3467            IInvalidating(parent).invalidateDisplayList();
3468        }
3469    }
3470
3471    /**
3472     *  Calling this method results in a call to the elements's
3473     *  <code>validateDisplayList()</code> method
3474     *  before the display list is rendered.
3475     *
3476     *  <p>Subclasses should override and do their work in
3477     *  <code>updateDisplayList()</code>.</p>
3478     *
3479     *  @langversion 3.0
3480     *  @playerversion Flash 10
3481     *  @playerversion AIR 1.5
3482     *  @productversion Flex 4
3483     */
3484    public function invalidateDisplayList():void
3485    {
3486        if (invalidateDisplayListFlag)
3487            return;
3488        invalidateDisplayListFlag = true;
3489
3490        // The IGraphicElementContainer will take care of redrawing all graphic elements that
3491        // share the display object with this element.
3492        if (parent)
3493            IGraphicElementContainer(parent).invalidateGraphicElementDisplayList(this);
3494    }
3495
3496    /**
3497     *  Validates and updates the properties and layout of this object
3498     *  by immediately calling <code>validateProperties()</code>,
3499     *  <code>validateSize()</code>, and <code>validateDisplayList()</code>,
3500     *  if necessary.
3501     *
3502     *  @langversion 3.0
3503     *  @playerversion Flash 10
3504     *  @playerversion AIR 1.5
3505     *  @productversion Flex 4
3506     */
3507    public function validateNow():void
3508    {
3509        if (parent)
3510        {
3511            UIComponentGlobals.layoutManager.validateClient(
3512                ILayoutManagerClient(parent));
3513        }
3514    }
3515
3516    /**
3517     *  Used by layout logic to validate the properties of a component
3518     *  by calling the <code>commitProperties()</code> method.
3519     *  In general, subclasses should
3520     *  override the <code>commitProperties()</code> method and not this method.
3521     *
3522     *  @langversion 3.0
3523     *  @playerversion Flash 10
3524     *  @playerversion AIR 1.5
3525     *  @productversion Flex 4
3526     */
3527    public function validateProperties():void
3528    {
3529        if (!invalidatePropertiesFlag)
3530            return;
3531        commitProperties();
3532        invalidatePropertiesFlag = false;
3533
3534        // If we aren't doing any more invalidation, send out an UpdateComplete event
3535        if (!invalidatePropertiesFlag && !invalidateSizeFlag && !invalidateDisplayListFlag)
3536            dispatchUpdateComplete();
3537    }
3538
3539    /**
3540     *  Processes the properties set on the element.
3541     *  This is an advanced method that you might override
3542     *  when creating a subclass.
3543     *
3544     *  <p>You do not call this method directly.
3545     *  Flex calls the <code>commitProperties()</code> method when you
3546     *  use the <code>addElement()</code> method to add an element to an
3547     *  <code>IGraphicElementContainer</code> container such as Group,
3548     *  or when you call the <code>invalidateProperties()</code> method of the element.
3549     *  Calls to the <code>commitProperties()</code> method occur before calls to the
3550     *  <code>measure()</code> method. This lets you set property values that might
3551     *  be used by the <code>measure()</code> method.</p>
3552     *
3553     *  <p>Some elements have properties that
3554     *  interact with each other.
3555     *  It is often best at startup time to process all of these
3556     *  properties at one time to avoid duplicating work.</p>
3557     *
3558     *  @langversion 3.0
3559     *  @playerversion Flash 10
3560     *  @playerversion AIR 1.5
3561     *  @productversion Flex 4
3562     */
3563    protected function commitProperties():void
3564    {
3565        //trace("GraphicElement.commitProperties displayObject",displayObject,"this",this);
3566        var updateTransform:Boolean = false;
3567        var mxTransform:mx.geom.Transform;
3568
3569        // If we are the first in the sequence, setup the displayObject properties
3570        if (displayObjectSharingMode != DisplayObjectSharingMode.USES_SHARED_OBJECT && displayObject)
3571        {
3572            if (colorTransformChanged || displayObjectChanged)
3573            {
3574                colorTransformChanged = false;
3575                if (_colorTransform)
3576                    displayObject.transform.colorTransform = _colorTransform;
3577            }
3578
3579            if (alphaChanged || displayObjectChanged)
3580            {
3581                alphaChanged = false;
3582
3583                mxTransform = _transform as mx.geom.Transform;
3584                if (!mxTransform || !mxTransform.applyColorTransformAlpha)
3585                    displayObject.alpha = _effectiveAlpha;
3586            }
3587
3588            if (blendModeChanged || displayObjectChanged)
3589            {
3590                blendModeChanged = false;
3591
3592                // Figure out the correct value to push down
3593                // to the displayObject's blendMode
3594                if (_blendMode == "auto")
3595                {
3596                    if (alpha == 0 || alpha == 1)
3597                        displayObject.blendMode = BlendMode.NORMAL;
3598                    else
3599                        displayObject.blendMode = BlendMode.LAYER;
3600                }
3601
3602                else if (!isAIMBlendMode(_blendMode))
3603                {
3604                    displayObject.blendMode = _blendMode;
3605                }
3606
3607                // The blendMode is neither a native value,
3608                // or the 'auto' value so lets set blendMode
3609                // to normal.
3610                else
3611                {
3612                    displayObject.blendMode = "normal";
3613                }
3614
3615                if (blendShaderChanged)
3616                {
3617                    // The graphic element's blendMode was set to a non-Flash
3618                    // blendMode. We mimic the look by instantiating the
3619                    // appropriate shader class and setting the blendShader
3620                    // property on the displayObject.
3621                    blendShaderChanged = false;
3622
3623                    switch(_blendMode)
3624                    {
3625                        case "color":
3626                        {
3627                            displayObject.blendShader = new ColorShader();
3628                            break;
3629                        }
3630                        case "colordodge":
3631                        {
3632                            displayObject.blendShader = new ColorDodgeShader();
3633                            break;
3634                        }
3635                        case "colorburn":
3636                        {
3637                            displayObject.blendShader = new ColorBurnShader();
3638                            break;
3639                        }
3640                        case "exclusion":
3641                        {
3642                            displayObject.blendShader = new ExclusionShader();
3643                            break;
3644                        }
3645                        case "hue":
3646                        {
3647                            displayObject.blendShader = new HueShader();
3648                            break;
3649                        }
3650                        case "luminosity":
3651                        {
3652                            displayObject.blendShader = new LuminosityShader();
3653                            break;
3654                        }
3655                        case "saturation":
3656                        {
3657                            displayObject.blendShader = new SaturationShader();
3658                            break;
3659                        }
3660                        case "softlight":
3661                        {
3662                            displayObject.blendShader = new SoftLightShader();
3663                            break;
3664                        }
3665                    }
3666                }
3667            }
3668
3669            if (filtersChanged || displayObjectChanged)
3670            {
3671                filtersChanged = false;
3672
3673                // there's a flash player bug...even setting filters to null here
3674                // causes memory to skyrocket
3675                if (filtersChanged || _clonedFilters)
3676                    displayObject.filters = _clonedFilters;
3677            }
3678
3679            if (maskChanged || displayObjectChanged)
3680            {
3681                maskChanged = false;
3682
3683                if (_mask)
3684                {
3685                    // If the mask is not parented, then we need to parent it.
3686                    // Since a mask can not be a child of the maskee,
3687                    // we make the mask and maskee siblings. We create a new maskee
3688                    // called _drawnDisplayObject. Then we attach both the mask
3689                    // and maskee to displayObject.
3690                    if (!_mask.parent)
3691                    {
3692                        Sprite(displayObject).addChild(_mask);
3693
3694                        MaskUtil.applyMask(_mask, parent);
3695
3696                        if (!_drawnDisplayObject)
3697                        {
3698                            // Clear the original displayObject because it might have previously
3699                            // drawn the shape.
3700                            if (displayObject is Sprite)
3701                                Sprite(displayObject).graphics.clear();
3702                            else if (displayObject is Shape)
3703                                Shape(displayObject).graphics.clear();
3704
3705                            // Create a new target for the drawing commands
3706                            _drawnDisplayObject = new InvalidatingSprite();
3707                            Sprite(displayObject).addChild(_drawnDisplayObject);
3708                        }
3709                    }
3710
3711                    drawnDisplayObject.mask = _mask;
3712                }
3713            }
3714
3715            if (luminositySettingsChanged)
3716            {
3717                luminositySettingsChanged = false;
3718
3719                MaskUtil.applyLuminositySettings(
3720                    _mask, _maskType, _luminosityInvert, _luminosityClip);
3721            }
3722
3723            if (maskTypeChanged || displayObjectChanged)
3724            {
3725                maskTypeChanged = false;
3726                MaskUtil.applyMaskType(
3727                    _mask, _maskType, _luminosityInvert, _luminosityClip,
3728                    drawnDisplayObject);
3729            }
3730
3731            // If we don't share the DisplayObject, set the property directly.
3732            // If displayObject has changed and we're sharing, then ensure
3733            // the visible property is set to true.
3734            if (displayObjectChanged)
3735                displayObject.visible = (displayObjectSharingMode == DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT) ? _effectiveVisibility : true;
3736
3737            updateTransform = true;
3738            displayObjectChanged = false;
3739        }
3740
3741        if (visibleChanged)
3742        {
3743            visibleChanged = false;
3744
3745            // If we don't share the DisplayObject, set the property directly,
3746            // otherwise redraw.
3747            if (displayObjectSharingMode == DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT)
3748            {
3749                displayObject.visible = _effectiveVisibility;
3750            }
3751            else
3752                invalidateDisplayList();
3753        }
3754
3755        if ((layoutFeatures == null || layoutFeatures.updatePending) ||
3756            updateTransform)
3757        {
3758            applyComputedTransform();
3759        }
3760    }
3761
3762    /**
3763     *  @inheritDoc
3764     *
3765     *  @langversion 3.0
3766     *  @playerversion Flash 10
3767     *  @playerversion AIR 1.5
3768     *  @productversion Flex 4
3769     */
3770    public function validateSize():void
3771    {
3772        if (!invalidateSizeFlag)
3773            return;
3774        invalidateSizeFlag = false;
3775
3776        var sizeChanging:Boolean = measureSizes();
3777
3778        if (!sizeChanging || !includeInLayout)
3779        {
3780            // If we aren't doing any more invalidation, send out an UpdateComplete event
3781            if (!invalidatePropertiesFlag && !invalidateSizeFlag && !invalidateDisplayListFlag)
3782                dispatchUpdateComplete();
3783            return;
3784        }
3785
3786        // Our size has changed, parent has to resize and run layout code
3787        invalidateParentSizeAndDisplayList();
3788    }
3789
3790    /**
3791     *  Determines if the call to the <code>measure()</code> method can be skipped.
3792     *
3793     *  @return Returns <code>true</code> when the <code>measureSizes()</code> method can skip the call to
3794     *  the <code>measure()</code> method. For example this is usually <code>true</code> when both the <code>explicitWidth</code> and
3795     *  <code>explicitHeight</code> properties are set. For paths, this is <code>true</code> when the bounds of the path
3796     *  have not changed.
3797     *
3798     *  @langversion 3.0
3799     *  @playerversion Flash 10
3800     *  @playerversion AIR 1.5
3801     *  @productversion Flex 4
3802     */
3803    protected function canSkipMeasurement():Boolean
3804    {
3805        return !isNaN(explicitWidth) && !isNaN(explicitHeight);
3806    }
3807
3808    /**
3809     *  @private
3810     */
3811    private function measureSizes():Boolean
3812    {
3813        var oldWidth:Number = preferredWidthPreTransform();
3814        var oldHeight:Number = preferredHeightPreTransform();
3815        var oldX:Number = measuredX;
3816        var oldY:Number = measuredY;
3817
3818        if (!canSkipMeasurement())
3819            measure();
3820
3821        if (!isNaN(explicitMinWidth) && measuredWidth < explicitMinWidth)
3822            measuredWidth = explicitMinWidth;
3823
3824        if (!isNaN(explicitMaxWidth) && measuredWidth > explicitMaxWidth)
3825            measuredWidth = explicitMaxWidth;
3826
3827        if (!isNaN(explicitMinHeight) && measuredHeight < explicitMinHeight)
3828            measuredHeight = explicitMinHeight;
3829
3830        if (!isNaN(explicitMaxHeight) && measuredHeight > explicitMaxHeight)
3831            measuredHeight = explicitMaxHeight;
3832
3833        // Did measure() have effect on preferred size?
3834        if (oldWidth != preferredWidthPreTransform() ||
3835            oldHeight != preferredHeightPreTransform() ||
3836            oldX != measuredX ||
3837            oldY != measuredY)
3838        {
3839            // Preferred size has changed, layout will be affected.
3840            return true;
3841        }
3842
3843        return false;
3844    }
3845
3846    /**
3847     *  Calculates the default size of the element. This is an advanced
3848     *  method that you might override when creating a subclass of GraphicElement.
3849     *
3850     *  <p>You do not call this method directly. Flex calls the
3851     *  <code>measure()</code> method when the element is added to an
3852     *  <code>IGraphicElementContainer</code> container such as Group
3853     *  using the <code>addElement()</code> method, and when the element's
3854     *  <code>invalidateSize()</code> method is called. </p>
3855     *
3856     *  <p>By default you set both explicit height and explicit width of an element,
3857     *  Flex does not call the <code>measure()</code> method,
3858     *  even if you explicitly call the <code>invalidateSize()</code> method.
3859     *  To override this behavior, override <code>skipMeasure()</code> method.</p>
3860     *
3861     *  <p>In your override of this method, you must set the
3862     *  <code>measuredWidth</code> and <code>measuredHeight</code> properties
3863     *  to define the default size.
3864     *  You can optionally set the <code>measuredX</code> and
3865     *  <code>measuredY</code> properties to define the default measured bounds
3866     *  top-left corner relative to the origin of the element.</p>
3867     *
3868     *  <p>The conceptual point of <code>measure()</code> is for the element to
3869     *  provide its own natural or intrinsic bounds as a default. Therefore, the
3870     *  <code>measuredWidth</code> and <code>measuredHeight</code> properties
3871     *  should be determined by factors such as:</p>
3872     *  <ul>
3873     *     <li>The amount of text the component needs to display.</li>
3874     *     <li>The size of a JPEG image that the component displays.</li>
3875     *  </ul>
3876     *
3877     *  <p>In some cases, there is no intrinsic way to determine default values.
3878     *  For example, a simple GreenCircle element might simply set
3879     *  measuredWidth = 100 and measuredHeight = 100 in its <code>measure()</code> method to
3880     *  provide a reasonable default size. In other cases, such as a TextArea,
3881     *  an appropriate computation (such as finding the right width and height
3882     *  that would just display all the text and have the aspect ratio of a Golden Rectangle)
3883     *  might be too time-consuming to be worthwhile.</p>
3884     *
3885     *  <p>The default implementation of <code>measure()</code>
3886     *  sets the values of the <code>measuredWidth</code>, <code>measuredHeight</code>,
3887     *  <code>measuredX</code>, and <code>measuredY</code> properties
3888     *  to <code>0</code>.</p>
3889     *
3890     *  @langversion 3.0
3891     *  @playerversion Flash 10
3892     *  @playerversion AIR 1.5
3893     *  @productversion Flex 4
3894     */
3895    protected function measure():void
3896    {
3897        measuredWidth = 0;
3898        measuredHeight = 0;
3899        measuredX = 0;
3900        measuredY = 0;
3901    }
3902
3903    /**
3904     *  @inheritDoc
3905     *
3906     *  @langversion 3.0
3907     *  @playerversion Flash 10
3908     *  @playerversion AIR 1.5
3909     *  @productversion Flex 4
3910     */
3911    public function validateDisplayList():void
3912    {
3913        // Don't check the invalidateDisplayListFlag for early return, the IGraphicElementContainer takes care to
3914        // call validateDisplayList() only for elements that need to redraw.
3915        // Note that even when invalidateDisplayListFlag is false for a particular element,
3916        // the IGraphicElementContainer may still call it to redraw if it shares a display object with another
3917        // element that is redrawing.
3918        // if (!invalidateDisplayListFlag)
3919        //    return;
3920
3921        var wasInvalid:Boolean = invalidateDisplayListFlag;
3922        invalidateDisplayListFlag = false;
3923
3924        // we commit our transform in two places. First, during commit properties, because our size depends on it,
3925        // and our parent will most likely take it into account during layout. Secondly, here, because our parent will likely
3926        // change our xform as a result of layout, and we need to commit it before we end up on screen.
3927        if (layoutFeatures == null || layoutFeatures.updatePending)
3928        {
3929            applyComputedTransform();
3930        }
3931
3932        // If we are the first in the sequence, clear the graphics:
3933        if (displayObjectSharingMode != DisplayObjectSharingMode.USES_SHARED_OBJECT)
3934        {
3935            if (drawnDisplayObject is Sprite)
3936                Sprite(drawnDisplayObject).graphics.clear();
3937            // TODO (rfrishbe): We don't really support shapes, but we should
3938            //else if (drawnDisplayObject is Shape)
3939                //Shape(drawnDisplayObject).graphics.clear();
3940        }
3941
3942        doUpdateDisplayList();
3943
3944        // If we aren't doing any more invalidation, send out an UpdateComplete event
3945        if (!invalidatePropertiesFlag && !invalidateSizeFlag && !invalidateDisplayListFlag && wasInvalid)
3946            dispatchUpdateComplete();
3947
3948        // LAYOUT_DEBUG
3949        //LayoutManager.debugHelper.addElement(ILayoutElement(this));
3950    }
3951
3952    /**
3953     *  @private
3954     */
3955    mx_internal function doUpdateDisplayList():void
3956    {
3957        if (_effectiveVisibility || displayObjectSharingMode == DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT)
3958            updateDisplayList(_width, _height);
3959    }
3960
3961    /**
3962     *  Draws the element and/or sizes and positions its content.
3963     *  This is an advanced method that you might override
3964     *  when creating a subclass of GraphicElement.
3965     *
3966     *  <p>You do not call this method directly. Flex calls the
3967     *  <code>updateDisplayList()</code> method when the component is added
3968     *  to an <code>IGraphicElementContainer</code> container such as Group
3969     *  using the <code>addElement()</code> method, and when the element's
3970     *  <code>invalidateDisplayList()</code> method is called. </p>
3971     *
3972     *  <p>This method is where you would do programmatic drawing
3973     *  using methods on the elements's displayObject
3974     *  such as <code>graphics.drawRect()</code>.</p>
3975     *
3976     *  @param unscaledWidth Specifies the width of the component, in pixels,
3977     *  in the component's coordinates, regardless of the value of the
3978     *  <code>scaleX</code> property of the component.
3979
3980     *  @param unscaledHeight Specifies the height of the component, in pixels,
3981     *  in the component's coordinates, regardless of the value of the
3982     *  <code>scaleY</code> property of the component.
3983     *
3984     *  @langversion 3.0
3985     *  @playerversion Flash 10
3986     *  @playerversion AIR 1.5
3987     *  @productversion Flex 4
3988     */
3989    protected function updateDisplayList(unscaledWidth:Number,
3990                                         unscaledHeight:Number):void
3991    {
3992    }
3993
3994    /**
3995     *  @private
3996     *  Helper function to dispatch the UpdateComplete event
3997     */
3998    private function dispatchUpdateComplete():void
3999    {
4000        if (hasEventListener(FlexEvent.UPDATE_COMPLETE))
4001            dispatchEvent(new FlexEvent(FlexEvent.UPDATE_COMPLETE));
4002    }
4003
4004    //--------------------------------------------------------------------------
4005    //
4006    //  Methods: ILayoutElement
4007    //
4008    //--------------------------------------------------------------------------
4009
4010    /**
4011     *  @inheritDoc
4012     *
4013     *  @langversion 3.0
4014     *  @playerversion Flash 10
4015     *  @playerversion AIR 1.5
4016     *  @productversion Flex 4
4017     */
4018    public function getMaxBoundsWidth(postLayoutTransform:Boolean = true):Number
4019    {
4020        return transformWidthForLayout(maxWidth, maxHeight, postLayoutTransform);
4021    }
4022
4023    /**
4024     *  @inheritDoc
4025     *
4026     *  @langversion 3.0
4027     *  @playerversion Flash 10
4028     *  @playerversion AIR 1.5
4029     *  @productversion Flex 4
4030     */
4031    public function getMaxBoundsHeight(postLayoutTransform:Boolean = true):Number
4032    {
4033        return transformHeightForLayout(maxWidth, maxHeight, postLayoutTransform);
4034    }
4035
4036    /**
4037     *  @inheritDoc
4038     *
4039     *  @langversion 3.0
4040     *  @playerversion Flash 10
4041     *  @playerversion AIR 1.5
4042     *  @productversion Flex 4
4043     */
4044    public function getMinBoundsWidth(postLayoutTransform:Boolean = true):Number
4045    {
4046        return transformWidthForLayout(minWidth, minHeight, postLayoutTransform);
4047    }
4048
4049    /**
4050     *  @inheritDoc
4051     *
4052     *  @langversion 3.0
4053     *  @playerversion Flash 10
4054     *  @playerversion AIR 1.5
4055     *  @productversion Flex 4
4056     */
4057    public function getMinBoundsHeight(postLayoutTransform:Boolean = true):Number
4058    {
4059        return transformHeightForLayout(minWidth, minHeight, postLayoutTransform);
4060    }
4061
4062    /**
4063     *  @inheritDoc
4064     *
4065     *  @langversion 3.0
4066     *  @playerversion Flash 10
4067     *  @playerversion AIR 1.5
4068     *  @productversion Flex 4
4069     */
4070    public function getPreferredBoundsWidth(postLayoutTransform:Boolean = true):Number
4071    {
4072        return transformWidthForLayout(preferredWidthPreTransform(),
4073                                       preferredHeightPreTransform(),
4074                                       postLayoutTransform);
4075    }
4076
4077    /**
4078     *  @inheritDoc
4079     *
4080     *  @langversion 3.0
4081     *  @playerversion Flash 10
4082     *  @playerversion AIR 1.5
4083     *  @productversion Flex 4
4084     */
4085    public function getPreferredBoundsHeight(postLayoutTransform:Boolean = true):Number
4086    {
4087        return transformHeightForLayout(preferredWidthPreTransform(),
4088                                       preferredHeightPreTransform(),
4089                                       postLayoutTransform);
4090    }
4091
4092    /**
4093     *  @inheritDoc
4094     *
4095     *  @langversion 3.0
4096     *  @playerversion Flash 10
4097     *  @playerversion AIR 1.5
4098     *  @productversion Flex 4
4099     */
4100    public function getBoundsXAtSize(width:Number, height:Number, postLayoutTransform:Boolean = true):Number
4101    {
4102        var strokeExtents:Rectangle = getStrokeExtents(postLayoutTransform);
4103        var m:Matrix = getComplexMatrix(postLayoutTransform);
4104        if (!m)
4105            return strokeExtents.left + this.measuredX + this.x;
4106
4107        if (!isNaN(width))
4108            width -= strokeExtents.width;
4109
4110        if (!isNaN(height))
4111            height -= strokeExtents.height;
4112
4113        // Calculate the width and height pre-transform:
4114        var newSize:Point = MatrixUtil.fitBounds(width, height, m,
4115                                                 explicitWidth, explicitHeight,
4116                                                 preferredWidthPreTransform(),
4117                                                 preferredHeightPreTransform(),
4118                                                 minWidth, minHeight,
4119                                                 maxWidth, maxHeight);
4120        if (!newSize)
4121            newSize = new Point(minWidth, minHeight);
4122
4123        var topLeft:Point = new Point(measuredX, measuredY);
4124        MatrixUtil.transformBounds(newSize.x, newSize.y, m, topLeft);
4125        return strokeExtents.left + topLeft.x;
4126    }
4127
4128    /**
4129     *  @inheritDoc
4130     *
4131     *  @langversion 3.0
4132     *  @playerversion Flash 10
4133     *  @playerversion AIR 1.5
4134     *  @productversion Flex 4
4135     */
4136    public function getBoundsYAtSize(width:Number, height:Number, postLayoutTransform:Boolean = true):Number
4137    {
4138        var strokeExtents:Rectangle = getStrokeExtents(postLayoutTransform);
4139        var m:Matrix = getComplexMatrix(postLayoutTransform);
4140        if (!m)
4141            return strokeExtents.top + this.measuredY + this.y;
4142
4143        if (!isNaN(width))
4144            width -= strokeExtents.width;
4145
4146        if (!isNaN(height))
4147            height -= strokeExtents.height;
4148
4149        // Calculate the width and height pre-transform:
4150        var newSize:Point = MatrixUtil.fitBounds(width, height, m,
4151                                                 explicitWidth, explicitHeight,
4152                                                 preferredWidthPreTransform(),
4153                                                 preferredHeightPreTransform(),
4154                                                 minWidth, minHeight,
4155                                                 maxWidth, maxHeight);
4156        if (!newSize)
4157            newSize = new Point(minWidth, minHeight);
4158
4159        var topLeft:Point = new Point(measuredX, measuredY);
4160        MatrixUtil.transformBounds(newSize.x, newSize.y, m, topLeft);
4161        return strokeExtents.top + topLeft.y;
4162    }
4163
4164    /**
4165     *  @inheritDoc
4166     *
4167     *  @langversion 3.0
4168     *  @playerversion Flash 10
4169     *  @playerversion AIR 1.5
4170     *  @productversion Flex 4
4171     */
4172    public function getLayoutBoundsX(postLayoutTransform:Boolean = true):Number
4173    {
4174        // Take stroke into account:
4175        var stroke:Number = getStrokeExtents(postLayoutTransform).left;
4176
4177        var m:Matrix = getComplexMatrix(postLayoutTransform);
4178        if (!m)
4179            return stroke + this.measuredX + this.x;
4180
4181        var topLeft:Point = new Point(measuredX, measuredY);
4182        MatrixUtil.transformBounds(_width, _height, m, topLeft);
4183        return stroke + topLeft.x;
4184    }
4185
4186    /**
4187     *  @inheritDoc
4188     *
4189     *  @langversion 3.0
4190     *  @playerversion Flash 10
4191     *  @playerversion AIR 1.5
4192     *  @productversion Flex 4
4193     */
4194    public function getLayoutBoundsY(postLayoutTransform:Boolean = true):Number
4195    {
4196        // Take stroke into account:
4197        var stroke:Number = getStrokeExtents(postLayoutTransform).top;
4198
4199        var m:Matrix = getComplexMatrix(postLayoutTransform);
4200        if (!m)
4201            return stroke + this.measuredY + this.y;
4202
4203        var topLeft:Point = new Point(measuredX, measuredY);
4204        MatrixUtil.transformBounds(_width, _height, m, topLeft);
4205        return stroke + topLeft.y;
4206    }
4207
4208    /**
4209     *  @inheritDoc
4210     *
4211     *  @langversion 3.0
4212     *  @playerversion Flash 10
4213     *  @playerversion AIR 1.5
4214     *  @productversion Flex 4
4215     */
4216    public function getLayoutBoundsWidth(postLayoutTransform:Boolean = true):Number
4217    {
4218        return transformWidthForLayout(_width, _height, postLayoutTransform);
4219    }
4220
4221    /**
4222     *  @inheritDoc
4223     *
4224     *  @langversion 3.0
4225     *  @playerversion Flash 10
4226     *  @playerversion AIR 1.5
4227     *  @productversion Flex 4
4228     */
4229    public function getLayoutBoundsHeight(postLayoutTransform:Boolean = true):Number
4230    {
4231        return transformHeightForLayout(_width, _height, postLayoutTransform);
4232    }
4233
4234    /**
4235     *  Transform the element's size.
4236     *
4237     *  <p>This method calculates the bounding box of the graphic element as if the element’s width/height properties were set to the passed in values.
4238     *  The method returns the width of the bounding box.</p>
4239     *
4240     *  <p>In general, this method is not for use by developers. Instead, you should implement or override the methods defined by the ILayoutElement interface.</p>
4241     *
4242     *  @param width The target pre-transform width.
4243     *
4244     *  @param height The target pre-transform height.
4245     *
4246     *  @param postLayoutTransform When <code>true</code>, the returned bounding box is around the transformed element in its parent space (the element's transform is applied first).
4247     *
4248     *  @return Returns the transformed width. Transformation is this element's
4249     *  layout transformation matrix.
4250     *
4251     *  @langversion 3.0
4252     *  @playerversion Flash 10
4253     *  @playerversion AIR 1.5
4254     *  @productversion Flex 4
4255     */
4256    protected function transformWidthForLayout(width:Number,
4257                                               height:Number,
4258                                               postLayoutTransform:Boolean = true):Number
4259    {
4260        if (postLayoutTransform && hasComplexLayoutMatrix)
4261            width = MatrixUtil.transformSize(width, height,
4262                                             layoutFeatures.layoutMatrix).x;
4263
4264        // Take stroke into account
4265        width += getStrokeExtents(postLayoutTransform).width;
4266        return width;
4267    }
4268
4269    /**
4270     *  Transform the element's size.
4271     *
4272     *  <p>This method calculates the bounding box of the graphic element as if the element’s width/height properties were set to the passed in values.
4273     *  The method returns the height of the bounding box.</p>
4274     *
4275     *  <p>In general, this method is not for use by developers. Instead, you should implement or override the methods defined by the ILayoutElement interface.</p>
4276     *
4277     *  @param width The target pre-transform width.
4278     *
4279     *  @param height The target pre-transform height.
4280     *
4281     *  @param postLayoutTransform When <code>true</code>, the returned bounding box is around the transformed element in its parent space (the element's transform is applied first).
4282     *
4283     *  @return Returns the transformed height. Transformation is this element's
4284     *  layout transformation matrix.
4285     *
4286     *  @langversion 3.0
4287     *  @playerversion Flash 10
4288     *  @playerversion AIR 1.5
4289     *  @productversion Flex 4
4290     */
4291    protected function transformHeightForLayout(width:Number,
4292                                                height:Number,
4293                                                postLayoutTransform:Boolean = true):Number
4294    {
4295        if (postLayoutTransform && hasComplexLayoutMatrix)
4296            height = MatrixUtil.transformSize(width, height,
4297                                              layoutFeatures.layoutMatrix).y;
4298
4299        // Take stroke into account
4300        height += getStrokeExtents(postLayoutTransform).height;
4301        return height;
4302    }
4303
4304    /**
4305     *  Used for the implementation of the ILayoutElement interface,
4306     *  returns the explicit of measured width pre-transform.
4307     *
4308     * @return The explicit measured height, pre-transform.
4309     *
4310     *  @langversion 3.0
4311     *  @playerversion Flash 10
4312     *  @playerversion AIR 1.5
4313     *  @productversion Flex 4
4314     */
4315    protected function preferredWidthPreTransform():Number
4316    {
4317        return isNaN(explicitWidth) ? measuredWidth : explicitWidth;
4318    }
4319
4320    /**
4321     *  Used for the implementation of the ILayoutElement interface,
4322     *  returns the explicit measured height pre-transform.
4323     *
4324     * @return The explicit measured height, pre-transform.
4325     *
4326     *  @langversion 3.0
4327     *  @playerversion Flash 10
4328     *  @playerversion AIR 1.5
4329     *  @productversion Flex 4
4330     */
4331    protected function preferredHeightPreTransform():Number
4332    {
4333        return isNaN(explicitHeight) ? measuredHeight: explicitHeight;
4334    }
4335
4336    /**
4337     *  @inheritDoc
4338     *
4339     *  @langversion 3.0
4340     *  @playerversion Flash 10
4341     *  @playerversion AIR 1.5
4342     *  @productversion Flex 4
4343     */
4344    public function setLayoutBoundsPosition(newBoundsX:Number, newBoundsY:Number, postLayoutTransform:Boolean = true):void
4345    {
4346        var currentBoundsX:Number = getLayoutBoundsX(postLayoutTransform);
4347        var currentBoundsY:Number = getLayoutBoundsY(postLayoutTransform);
4348
4349        var currentX:Number = this.x;
4350        var currentY:Number = this.y;
4351
4352        var newX:Number = currentX + newBoundsX - currentBoundsX;
4353        var newY:Number = currentY + newBoundsY - currentBoundsY;
4354
4355        if (newX != currentX || newY != currentY)
4356        {
4357            if (layoutFeatures != null)
4358            {
4359                layoutFeatures.layoutX = newX;
4360                layoutFeatures.layoutY = newY;
4361
4362                // note that we don't want to call invalidateTransform, because
4363                // this is in the middle of an update pass. Instead, we just note that the
4364                // transform has an update pending, so we can apply it later.
4365                layoutFeatures.updatePending = true;
4366            }
4367            else
4368            {
4369                _x = newX;
4370                _y = newY;
4371            }
4372            if (newX != currentX)
4373                dispatchPropertyChangeEvent("x", currentX, newX);
4374            if (newY != currentY)
4375                dispatchPropertyChangeEvent("y", currentY, newY);
4376
4377            invalidateDisplayList();
4378        }
4379    }
4380
4381    /**
4382     *  @inheritDoc
4383     *
4384     *  @langversion 3.0
4385     *  @playerversion Flash 10
4386     *  @playerversion AIR 1.5
4387     *  @productversion Flex 4
4388     */
4389    public function setLayoutBoundsSize(width:Number,
4390                                        height:Number,
4391                                        postLayoutTransform:Boolean = true):void
4392    {
4393        if (!isNaN(width) || !isNaN(height))
4394        {
4395            var strokeExtents:Rectangle = getStrokeExtents(postLayoutTransform);
4396
4397            if (!isNaN(width))
4398               width -= strokeExtents.width;
4399            if (!isNaN(height))
4400               height -= strokeExtents.height;
4401        }
4402
4403        // Calculate the width and height pre-transform:
4404        var m:Matrix;
4405        if (postLayoutTransform && hasComplexLayoutMatrix)
4406            m = layoutFeatures.layoutMatrix;
4407        if (!m)
4408        {
4409            if (isNaN(width))
4410                width = preferredWidthPreTransform();
4411            if (isNaN(height))
4412                height = preferredHeightPreTransform();
4413        }
4414        else
4415        {
4416            var newSize:Point = MatrixUtil.fitBounds(width, height, m,
4417                                                     explicitWidth, explicitHeight,
4418                                                     preferredWidthPreTransform(),
4419                                                     preferredHeightPreTransform(),
4420                                                     minWidth, minHeight,
4421                                                     maxWidth, maxHeight);
4422
4423            if (newSize)
4424            {
4425                width = newSize.x;
4426                height = newSize.y;
4427            }
4428            else
4429            {
4430                width = minWidth;
4431                height = minHeight;
4432            }
4433        }
4434
4435        setActualSize(width, height);
4436    }
4437
4438    /**
4439     *  @private
4440     */
4441    mx_internal function setActualSize(width:Number, height:Number):void
4442    {
4443        if (_width != width || _height != height)
4444        {
4445            var oldWidth:Number = _width;
4446            var oldHeight:Number = _height;
4447
4448            _width = width;
4449            _height = height;
4450
4451            if (layoutFeatures)  // mirroring transform depends on width
4452            {
4453                layoutFeatures.layoutWidth = width;
4454                invalidateTransform(false /*changeInvalidatesLayering*/, false /*invalidateLayout*/);
4455            }
4456
4457            if (width != oldWidth)
4458                dispatchPropertyChangeEvent("width", oldWidth, width);
4459            if (height != oldHeight)
4460                dispatchPropertyChangeEvent("height", oldHeight, height);
4461
4462            invalidateDisplayList();
4463        }
4464    }
4465
4466    /**
4467     *  @inheritDoc
4468     *
4469     *  @langversion 3.0
4470     *  @playerversion Flash 10
4471     *  @playerversion AIR 1.5
4472     *  @productversion Flex 4
4473     */
4474    public function getLayoutMatrix():Matrix
4475    {
4476        // esg: _layoutFeatures keeps a single internal copy of the layoutMatrix.
4477        // since this is an internal class, we don't need to worry about developers
4478        // accidentally messing with this matrix, _unless_ we hand it out. Instead,
4479        // we hand out a clone.
4480        if (layoutFeatures != null)
4481            return layoutFeatures.layoutMatrix.clone();
4482        var m:Matrix = new Matrix();
4483        m.translate(_x,_y);
4484        return m;
4485    }
4486
4487    /**
4488     *  @inheritDoc
4489     *
4490     *  @langversion 3.0
4491     *  @playerversion Flash 10
4492     *  @playerversion AIR 1.5
4493     *  @productversion Flex 4
4494     */
4495    public function setLayoutMatrix(value:Matrix, invalidateLayout:Boolean):void
4496    {
4497        allocateLayoutFeatures();
4498        var previous:Boolean = needsDisplayObject;
4499
4500        // Early exit if possible. We don't want to invalidate unnecessarily.
4501        if (MatrixUtil.isEqual(layoutFeatures.layoutMatrix, value))
4502            return;
4503
4504        layoutFeatures.layoutMatrix = value;
4505        invalidateTransform(previous != needsDisplayObject, invalidateLayout);
4506    }
4507
4508    /**
4509     *  @inheritDoc
4510     *
4511     *  @langversion 3.0
4512     *  @playerversion Flash 10
4513     *  @playerversion AIR 1.5
4514     *  @productversion Flex 4
4515     */
4516    public function get hasLayoutMatrix3D():Boolean
4517    {
4518        return layoutFeatures ? layoutFeatures.layoutIs3D : false;
4519    }
4520
4521    /**
4522     *  @inheritDoc
4523     *
4524     *  @langversion 3.0
4525     *  @playerversion Flash 10
4526     *  @playerversion AIR 1.5
4527     *  @productversion Flex 4
4528     */
4529    public function get is3D():Boolean
4530    {
4531        return layoutFeatures ? layoutFeatures.is3D: false;
4532    }
4533
4534    /**
4535     *  @inheritDoc
4536     *
4537     *  @langversion 3.0
4538     *  @playerversion Flash 10
4539     *  @playerversion AIR 1.5
4540     *  @productversion Flex 4
4541     */
4542    public function getLayoutMatrix3D():Matrix3D
4543    {
4544        // esg: _layoutFeatures keeps a single internal copy of the layoutMatrix.
4545        // since this is an internal class, we don't need to worry about developers
4546        // accidentally messing with this matrix, _unless_ we hand it out. Instead,
4547        // we hand out a clone.
4548        if (layoutFeatures != null)
4549            return layoutFeatures.layoutMatrix3D.clone();
4550        var m:Matrix3D = new Matrix3D();
4551        m.appendTranslation(_x,_y,0);
4552        return m;
4553    }
4554
4555    /**
4556     *  @inheritDoc
4557     *
4558     *  @langversion 3.0
4559     *  @playerversion Flash 10
4560     *  @playerversion AIR 1.5
4561     *  @productversion Flex 4
4562     */
4563    public function setLayoutMatrix3D(value:Matrix3D, invalidateLayout:Boolean):void
4564    {
4565        allocateLayoutFeatures();
4566        var previous:Boolean = needsDisplayObject;
4567
4568        // Early exit if possible. We don't want to invalidate unnecessarily.
4569        if (MatrixUtil.isEqual3D(layoutFeatures.layoutMatrix3D, value))
4570            return;
4571
4572        layoutFeatures.layoutMatrix3D = value;
4573        invalidateTransform(previous != needsDisplayObject, invalidateLayout);
4574    }
4575
4576    /**
4577     *  @private
4578     *  Applies the transform to the DisplayObject.
4579     */
4580    mx_internal function applyComputedTransform():void
4581    {
4582        if (layoutFeatures != null)
4583            layoutFeatures.updatePending = false;
4584
4585        // Only the first elment in the sequence updates the transform
4586        if (displayObjectSharingMode == DisplayObjectSharingMode.USES_SHARED_OBJECT || !displayObject)
4587            return;
4588
4589        if (layoutFeatures != null)
4590        {
4591            if (layoutFeatures.is3D)
4592            {
4593                displayObject.transform.matrix3D = layoutFeatures.computedMatrix3D;
4594            }
4595            else
4596            {
4597                var m:Matrix = layoutFeatures.computedMatrix.clone();
4598                // If the displayObject is shared, then put it at 0,0
4599                if (displayObjectSharingMode == DisplayObjectSharingMode.OWNS_SHARED_OBJECT)
4600                {
4601                    m.tx = 0;
4602                    m.ty = 0;
4603                }
4604                displayObject.transform.matrix = m;
4605            }
4606        }
4607        else
4608        {
4609            // If the displayObject is shared, then put it at 0,0
4610            if (displayObjectSharingMode == DisplayObjectSharingMode.OWNS_SHARED_OBJECT)
4611            {
4612                displayObject.x = 0;
4613                displayObject.y = 0;
4614            }
4615            else
4616            {
4617                displayObject.x = _x;
4618                displayObject.y = _y;
4619            }
4620        }
4621    }
4622
4623    mx_internal function getComplexMatrix(performCheck:Boolean):Matrix
4624    {
4625        return performCheck && hasComplexLayoutMatrix ? layoutFeatures.layoutMatrix : null;
4626    }
4627
4628    static mx_internal var _strokeExtents:Rectangle = new Rectangle();
4629
4630    /**
4631     *  Returns the amount of pixels occupied by the stroke on each side
4632     *  of the element's bounds.
4633     *
4634     *  @param postLayoutTransform If <code>true</code>, the stroke extents are calculated
4635     *  in parent coordinate space (after applying the element's transformations).
4636     *
4637     *  @return Rectangle of the stroke extents. The rectangle's <code>left</code>,
4638     *  <code>right</code>, <code>top</code> and <code>bottom</code> properties
4639     *  represent the stroke extent for the respective side of the element's
4640     *  bounding box.
4641     *
4642     *  @langversion 3.0
4643     *  @playerversion Flash 10
4644     *  @playerversion AIR 1.5
4645     *  @productversion Flex 4
4646     */
4647    protected function getStrokeExtents(postLayoutTransform:Boolean = true):Rectangle
4648    {
4649        _strokeExtents.x = 0;
4650        _strokeExtents.y = 0;
4651        _strokeExtents.width = 0;
4652        _strokeExtents.height = 0;
4653        return _strokeExtents;
4654    }
4655
4656    //--------------------------------------------------------------------------
4657    //
4658    //  Event handlers
4659    //
4660    //--------------------------------------------------------------------------
4661
4662    /**
4663     *  @private
4664     *  Called when a bitmap filter associated with the element is modified.
4665     */
4666    private function filterChangedHandler(event:Event):void
4667    {
4668        filters = _filters;
4669    }
4670
4671}
4672
4673}
4674