////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package spark.components.supportClasses
{

import flash.display.DisplayObject;
import flash.events.Event;
import flash.geom.Point;
import flash.utils.*;

import mx.core.FlexVersion;
import mx.core.IFactory;
import mx.core.ILayoutElement;
import mx.core.IVisualElement;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.events.PropertyChangeEvent;

import spark.events.SkinPartEvent;
import spark.utils.FTETextUtil;

use namespace mx_internal;

//--------------------------------------
//  Styles
//--------------------------------------

/**
 *  @copy spark.components.supportClasses.GroupBase#style:chromeColor
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="chromeColor", type="uint", format="Color", inherit="yes", theme="spark, mobile")]

/**
 *  Name of the skin class to use for this component when a validation error occurs. 
 *  
 *  @default spark.skins.spark.ErrorSkin
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="errorSkin", type="Class")]

/**
 *  Name of the skin class to use for this component. The skin must be a class 
 *  that extends UIComponent. 
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="skinClass", type="Class")]

//--------------------------------------
//  Excluded APIs
//--------------------------------------

[Exclude(name="themeColor", kind="style")]
[Exclude(name="addChild", kind="method")]
[Exclude(name="addChildAt", kind="method")]
[Exclude(name="removeChild", kind="method")]
[Exclude(name="removeChildAt", kind="method")]
[Exclude(name="setChildIndex", kind="method")]
[Exclude(name="swapChildren", kind="method")]
[Exclude(name="swapChildrenAt", kind="method")]
[Exclude(name="numChildren", kind="property")]
[Exclude(name="getChildAt", kind="method")]
[Exclude(name="getChildIndex", kind="method")]

//--------------------------------------
//  Other metadata
//--------------------------------------

[ResourceBundle("components")]

/**
 *  The SkinnableComponent class defines the base class for skinnable components. 
 *  The skins used by a SkinnableComponent class are typically child classes of 
 *  the Skin class.
 *
 *  <p>Associate a skin class with a component class by setting the <code>skinClass</code> style property of the 
 *  component class. You can set the <code>skinClass</code> property in CSS, as the following example shows:</p>
 *
 *  <pre>MyComponent
 *  {
 *    skinClass: ClassReference("my.skins.MyComponentSkin")
 *  }</pre>
 *
 *  <p>The following example sets the <code>skinClass</code> property in MXML:</p>
 *
 *  <pre>
 *  &lt;MyComponent skinClass="my.skins.MyComponentSkin"/&gt;</pre>
 *
 *
 *  @see spark.components.supportClasses.Skin
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
public class SkinnableComponent extends UIComponent
{
    include "../../core/Version.as";

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Constructor.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function SkinnableComponent()
    {
        // Initially state is dirty
        skinStateIsDirty = true;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------
    
    private var _skinDestructionPolicy:String = "never";
    private var skinDestructionPolicyChanged:Boolean = false;
    
    /**
     *  @private
     * 
     *  If set to "auto", then the component will call detachSkin when it has been
     *  removed from the Stage. If it is then added back to the Stage, the component
     *  will call attachSkin. Set this to "auto" if you want to reduce the memory 
     *  usage of this component while it is not attached to the Stage. 
     * 
     *  Possible values are "auto" and "never".    
     * 
     *  @default "never"
     */ 
    mx_internal function get skinDestructionPolicy():String
    {
        return _skinDestructionPolicy;
    }
    
    mx_internal function set skinDestructionPolicy(value:String):void
    {
        if (value == _skinDestructionPolicy)
            return;
     
        _skinDestructionPolicy = value;
        
        skinDestructionPolicyChanged = true;
        invalidateProperties();
    }
    
    /**
     * @private 
     * 
     * Contains a flat list of all the skin parts. This includes
     * inherited skin parts. It is best to use a for...in to loop
     * through the skin parts. The property name will be the name of the 
     * skin part and it's value will be a boolean specifying if it is required
     * or not.
	 * 
	 * The actual return value of this method will be generated by the
	 * compiler and may not be null.
	 * 
     */
    protected function get skinParts():Object
    {
        return null;
    }
    
    //----------------------------------
    //  skin
    //----------------------------------
    
    /**
     * @private 
     * Storage for skin instance
     */ 
    private var _skin:UIComponent;
    
    [Bindable("skinChanged")]
    
    /**
     *  The instance of the skin class for this component instance. 
     *  This is a read-only property that gets set automomatically when Flex 
     *  calls the <code>attachSkin()</code> method.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get skin():UIComponent
    {
        return _skin;
    }
    
    /**
     *  @private
     *  Setter for the skin instance.  This is so the bindable event
     *  is dispatched
     */ 
    private function setSkin(value:UIComponent):void
    {
        if (value === _skin)
           return;
        
        _skin = value;
        dispatchEvent(new Event("skinChanged"));
    }

    //----------------------------------
    //  suggestedFocusSkinExclusions
    //----------------------------------
    
    /**
     *  Lists the skin parts that are
     *  excluded from bitmaps captured and used to
     *  show focus. This list is only used if
     *  the skin's <code>focusSkinExclusions</code> property is <code>null</code>.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get suggestedFocusSkinExclusions():Array
    {
        return null;
    }
    

    //--------------------------------------------------------------------------
    //
    //  Overridden properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  baselinePosition
    //----------------------------------

    /**
     *  @inheritDoc
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    override public function get baselinePosition():Number
    {
        if (!validateBaselinePosition())
            return NaN;

        // Unless the height is very small, the baselinePosition
        // of a generic UIComponent is calculated as if there was
        // a UITextField using the component's styles
        // whose top coincides with the component's top.
        // If the height is small, the baselinePosition is calculated
        // as if there were text within whose ascent the component
        // is vertically centered.
        // At the crossover height, these two calculations
        // produce the same result.

        return FTETextUtil.calculateFontBaseline(this, height, moduleFactory);
    }

    //----------------------------------
    //  currentCSSState
    //----------------------------------

    /**
     *  The state to be used when matching CSS pseudo-selectors. This override
     *  returns the current skin state instead of the component state.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 2.5
     *  @productversion Flex 4.5
     */ 
    override protected function get currentCSSState():String
    {
        return getCurrentSkinState();
    }

    //----------------------------------
    //  enabled
    //----------------------------------

    [Inspectable(category="General", enumeration="true,false", defaultValue="true")]

    /**
     *  @private
     */
    override public function set enabled(value:Boolean):void
    {
        super.enabled = value;
        invalidateSkinState();

        // If enabled, reset the mouseChildren, mouseEnabled to the previously
        // set explicit value, otherwise disable mouse interaction.
        super.mouseChildren = value ? _explicitMouseChildren : false;
        super.mouseEnabled  = value ? _explicitMouseEnabled  : false; 
    }

    //----------------------------------
    //  errorString
    //----------------------------------

    /**
     *  @private
     */
    private var errorObj:DisplayObject;
    private var errorStringChanged:Boolean;
    
    /**
     *  @private
     */
    override public function set errorString(value:String):void
    {
        super.errorString = value;
        
        errorStringChanged = true;
        invalidateProperties();
    }
    
    //----------------------------------
    //  mouseEnabled
    //----------------------------------

    private var _explicitMouseEnabled:Boolean = true;

    /**
     *  @private
     */
    override public function set mouseEnabled(value:Boolean):void
    {
        if (enabled)
            super.mouseEnabled = value;
        _explicitMouseEnabled = value;
    }
    
    //----------------------------------
    //  mouseChildren
    //----------------------------------

    private var _explicitMouseChildren:Boolean = true;

    /**
     *  @private
     */
    override public function set mouseChildren(value:Boolean):void
    {
        if (enabled)
            super.mouseChildren = value;
        _explicitMouseChildren = value;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private 
     */
    override public function matchesCSSState(cssState:String):Boolean
    {
        return getCurrentSkinState() == cssState || currentState == cssState;
    }

    /**
     *  @private
     */
    override protected function createChildren():void
    {
        super.createChildren();
        
        if (moduleFactory)
            validateSkinChange();
    }
    
    /**
     *  @private
     */
    private function validateSkinChange():void
    {
        // If our new skin Class happens to match our existing skin Class there is no
        // reason to fully unload then reload our skin.  
        var skipReload:Boolean = false;
        
        if (_skin)
        {
            var factory:Object = getStyle("skinFactory");
            var newSkinClass:Class;
            
            // if it's a factory, only reload the skin if the skinFactory
            // style has been explicitly changed.  right now this style is only 
            // used by design view, and this is the contract we have with them.
            if (factory)
                skipReload = !skinFactoryStyleChanged;
            else
            {
                newSkinClass = getStyle("skinClass");
                
                skipReload = newSkinClass && 
                    getQualifiedClassName(newSkinClass) == getQualifiedClassName(_skin);
            }
            
            skinFactoryStyleChanged = false;
        }
        
        if (!skipReload)
        {
            if (skin)
            {
                detachSkin();                
                // If there is an error skin remove it since it has to go on top of the new skin.
                removeErrorSkin();
            }
            attachSkin();            
            updateErrorSkin();
        }
    }
    
    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();

        if (skinChanged)
        {
            skinChanged = false;
            validateSkinChange();
        }

        if (skinStateIsDirty)
        {
            // This component must first be updated to the pending state as the
            // skin inherits styles from this component.
            var pendingState:String = getCurrentSkinState();
            stateChanged(skin.currentState, pendingState, false);
            skin.currentState = pendingState;
            skinStateIsDirty = false;
        }
        
        if (errorStringChanged)
        {
            updateErrorSkin();
            errorStringChanged = false;
        }
        
        if (skinDestructionPolicyChanged)
        {
            if (skinDestructionPolicy == "auto")
            {
                addEventListener(Event.ADDED_TO_STAGE, adddedToStageHandler);
                addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
            }
            else
            {
                removeEventListener(Event.ADDED_TO_STAGE, adddedToStageHandler);
                removeEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
            }
            
            skinDestructionPolicyChanged = false;
        }
    }

    /**
     *  @private
     */
    override protected function measure():void
    {
        if (skin)
        {
            if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_5)
            {
                measuredWidth = skin.getExplicitOrMeasuredWidth();
                measuredHeight = skin.getExplicitOrMeasuredHeight();

                measuredMinWidth = isNaN( skin.explicitWidth ) ? skin.minWidth : skin.explicitWidth;
                measuredMinHeight = isNaN( skin.explicitHeight ) ? skin.minHeight : skin.explicitHeight;
            }
            else
            {
                measuredWidth = skin.getExplicitOrMeasuredWidth(); 
                measuredHeight = skin.getExplicitOrMeasuredHeight();

                measuredMinWidth = skin.minWidth;
                measuredMinHeight = skin.minHeight;
            }
        }
    }
    
    /**
     *  @private
     */
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {
        if (skin)
            skin.setActualSize(unscaledWidth, unscaledHeight);
     }

    /**
     *  @private
     */
    override public function styleChanged(styleProp:String):void
    {
        var allStyles:Boolean = styleProp == null || styleProp == "styleName";
        
        if (allStyles || styleProp == "skinClass" || styleProp == "skinFactory")
        {
            skinChanged = true;
            invalidateProperties();
            
            if (styleProp == "skinFactory")
                skinFactoryStyleChanged = true;
        }
        
        super.styleChanged(styleProp);
    }
    
    /**
     *  @private
     */
    mx_internal var focusObj:DisplayObject;
    mx_internal var drawFocusAnyway:Boolean;
    
    /**
     *  @private
     */
    override public function drawFocus(isFocused:Boolean):void
    {
        if (isFocused && focusManager)
        {
            // For some composite components, the focused object may not
            // be "this". If so, we don't want to draw the focus.
            if (!drawFocusAnyway && focusManager.getFocus() != this)
                return;
                
            if (!focusObj)
            {
                var focusSkinClass:Class = getStyle("focusSkin");
                
                if (focusSkinClass)
                    focusObj = new focusSkinClass();
                
                if (focusObj)
                    super.addChildAt(focusObj, 0);
            }
            if (focusObj && "target" in focusObj)
                focusObj["target"] = this;
        }
        else
        {
            if (focusObj)
                super.removeChild(focusObj);
            focusObj = null;
        }
    }
    
    //--------------------------------------------------------------------------
    //
    // Skin states support
    //
    //--------------------------------------------------------------------------

    /**
     *  Returns the name of the state to be applied to the skin. For example, a
     *  Button component could return the String "up", "down", "over", or "disabled" 
     *  to specify the state.
     * 
     *  <p>A subclass of SkinnableComponent must override this method to return a value.</p>
     * 
     *  @return A string specifying the name of the state to apply to the skin.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function getCurrentSkinState():String 
    {
        return null; 
    }
    
    /**
     *  Marks the component so that the new state of the skin is set
     *  during a later screen update.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function invalidateSkinState():void
    {
        if (skinStateIsDirty)
            return; // State is already invalidated

        skinStateIsDirty = true;
        invalidateProperties();
    }

    //--------------------------------------------------------------------------
    //
    //  Methods - Skin/Behavior lifecycle
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Create the skin for the component. 
     *  You do not call this method directly. 
     *  Flex calls it automatically when it calls <code>createChildren()</code> or  
     *  the <code>UIComponent.commitProperties()</code> method.
     *  Typically, a subclass of SkinnableComponent does not override this method.
     * 
     *  <p>This method instantiates the skin for the component, 
     *  adds the skin as a child of the component, and 
     *  resolves all part associations for the skin</p>
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function attachSkin():void
    {
        // Factory
        var skinClassFactory:IFactory = getStyle("skinFactory") as IFactory;        
        
        if (skinClassFactory)
            setSkin( skinClassFactory.newInstance() as UIComponent );
        
        // Class
        if (!skin)
        {
            var skinClass:Class = getStyle("skinClass") as Class;
            
            if (skinClass)
                setSkin( new skinClass() );
        }
        
        if (skin)
        {
            skin.owner = this;
            
            // As a convenience if someone has declared hostComponent
            // we assign a reference to ourselves.  If the hostComponent
            // property exists as a direct result of utilizing [HostComponent]
            // metadata it will be strongly typed. We need to do more work
            // here and only assign if the type exactly matches our component
            // type.
            if ("hostComponent" in skin)
            {
                try 
                {
                    Object(skin).hostComponent = this;
                }
                catch (err:Error) {}
            }
            
            // the skin's styles should be the same as the components
            skin.styleName = this;
             
            // Note: The Spark PanelAccImpl adds a child Sprite at index 0.
            // The skin should be in front of that.
            super.addChild(skin);
            
            skin.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, skin_propertyChangeHandler);
        }
        else
        {
            throw(new Error(resourceManager.getString("components", "skinNotFound", [this])));
        }
        
        findSkinParts();
        
        invalidateSkinState();
    }
    
    /**
     *  Find the skin parts in the skin class and assign them to the properties of the component.
     *  You do not call this method directly. 
     *  Flex calls it automatically when it calls the <code>attachSkin()</code> method.
     *  Typically, a subclass of SkinnableComponent does not override this method.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function findSkinParts():void
    {
        if (skinParts)
        {
            for (var id:String in skinParts)
            {
                if (skinParts[id] == true)
                {
                    if (!(id in skin))
                        throw(new Error(resourceManager.getString("components", "requiredSkinPartNotFound", [id])));
                }
                
                if (id in skin)
                {
                    this[id] = skin[id];
                    
                    // If the assigned part has already been instantiated, call partAdded() here,
                    // but only for static parts.
                    if (this[id] != null && !(this[id] is IFactory))
                        partAdded(id, this[id]);
                }
            }
        }
    }
    
    /**
     *  Clear out references to skin parts. 
     *  You do not call this method directly. 
     *  Flex calls it automatically when it calls the <code>detachSkin()</code> method.
     *
     *  <p>Typically, subclasses of SkinnableComponent do not override this method.</p>
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function clearSkinParts():void
    {
        if (skinParts)
        {
            for (var id:String in skinParts)
            {
                if (this[id] != null)
                {
                    if (!(this[id] is IFactory))
                    {
                        partRemoved(id, this[id]);
                    }
                    else
                    {
                        var len:int = numDynamicParts(id);
                        for (var j:int = len - 1; j >= 0; j--)
                            removeDynamicPartInstance(id, getDynamicPartAt(id, j));
                    }
                }
              
                this[id] = null;
            }
        }
    }
    
    /**
     *  Destroys and removes the skin for this component. 
     *  You do not call this method directly. 
     *  Flex calls it automatically when a skin is changed at runtime.
     *
     *  This method removes the skin and clears all part associations.
     *
     *  <p>Typically, subclasses of SkinnableComponent do not override this method.</p>
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function detachSkin():void
    {       
        skin.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, skin_propertyChangeHandler);
        
        skin.styleName = null;
        clearSkinParts();
        super.removeChild(skin);
        setSkin(null);
    }
    
    /**
     *  @private
     *  Method to draw or remove the error skin. The error skin is added as a sibling of the skin. 
     */
    mx_internal function updateErrorSkin():void
    {
        if (errorString != null && errorString != "" && getStyle("showErrorSkin"))
        {
            if (!errorObj)
            {
                var errorObjClass:Class = getStyle("errorSkin");
                
                if (errorObjClass)
                    errorObj = new errorObjClass();
                
                if (errorObj)
                {
                    if ("target" in errorObj)
                        errorObj["target"] = this;
                    super.addChild(errorObj);
                }
            }
        }
        else
        {
            removeErrorSkin();
        }
    }
    
    private function removeErrorSkin():void
    {
        if (errorObj)
        {
            super.removeChild(errorObj);
            errorObj = null;
        }

    }

    //--------------------------------------------------------------------------
    //
    //  Methods - Parts
    //
    //--------------------------------------------------------------------------
    
    /**
     *  Called when a skin part is added. 
     *  You do not call this method directly. 
     *  For static parts, Flex calls it automatically when it calls the <code>attachSkin()</code> method. 
     *  For dynamic parts, Flex calls it automatically when it calls 
     *  the <code>createDynamicPartInstance()</code> method. 
     *
     *  <p>Override this function to attach behavior to the part. 
     *  If you want to override behavior on a skin part that is inherited from a base class, 
     *  do not call the <code>super.partAdded()</code> method. 
     *  Otherwise, you should always call the <code>super.partAdded()</code> method.</p>
     *
     *  @param partname The name of the part.
     *
     *  @param instance The instance of the part.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function partAdded(partName:String, instance:Object):void
    {
        // Dispatch a partAdded event.
        // This event is an internal implementation detail subject to change.
        // The accessibility implementation classes listen for this to know
        // when to add their event listeners to skin parts being added.
        var event:SkinPartEvent = new SkinPartEvent(SkinPartEvent.PART_ADDED);
        event.partName = partName;
        event.instance = instance;
        dispatchEvent(event);
    }

    /**
     *  Called when an instance of a skin part is being removed. 
     *  You do not call this method directly. 
     *  For static parts, Flex calls it automatically when it calls the <code>detachSkin()</code> method. 
     *  For dynamic parts, Flex calls it automatically when it calls 
     *  the <code>removeDynamicPartInstance()</code> method. 
     *
     *  <p>Override this function to remove behavior from the part.</p>
     *
     *  @param partname The name of the part.
     *
     *  @param instance The instance of the part.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function partRemoved(partName:String, instance:Object):void
    {       
        // Dispatch a partRemoved event.
        // This event is an internal implementation detail subject to change.
        // The accessibility implementation classes listen for this to know
        // when to remove their event listeners from skin parts being removed
        var event:SkinPartEvent = new SkinPartEvent(SkinPartEvent.PART_REMOVED);
        event.partName = partName;
        event.instance = instance;
        dispatchEvent(event);
    }
    
    //--------------------------------------------------------------------------
    //
    //  Methods - Dynamic Parts
    //
    //--------------------------------------------------------------------------
    
    // Private cache of instantiated dynamic parts. This is accessed through
    // the numDynamicParts() and getDynamicPartAt() methods.
    private var dynamicPartsCache:Object;
    
    /**
     *  Create an instance of a dynamic skin part. 
     *  Dynamic skin parts should always be instantiated by this method, 
     *  rather than directly by calling the <code>newInstance()</code> method on the factory.
     *  This method creates the part, but does not add it to the display list.
     *  The component must call the <code>Group.addElement()</code> method, or the appropriate 
     *  method to add the skin part to the display list. 
     *
     *  @param partName The name of the part.
     *
     *  @return The instance of the part, or null if it cannot create the part.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function createDynamicPartInstance(partName:String):Object
    {
        var factory:IFactory = this[partName];
        
        if (factory)
        {
            var instance:* = factory.newInstance();
            
            // Add to the dynamic parts cache
            if (!dynamicPartsCache)
                dynamicPartsCache = {};
                
            if (!dynamicPartsCache[partName])
                dynamicPartsCache[partName] = [];
            
            dynamicPartsCache[partName].push(instance);
            
            // Send notification
            partAdded(partName, instance);
            
            return instance;
        }
        
        return null;
    }
    
    /**
     *  Remove an instance of a dynamic part. 
     *  You must call this method  before a dynamic part is deleted.
     *  This method does not remove the part from the display list.
     *
     *  @param partname The name of the part.
     *
     *  @param instance The instance of the part.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function removeDynamicPartInstance(partName:String, instance:Object):void
    {
        // Send notification
        partRemoved(partName, instance);
        
        // Remove from the dynamic parts cache
        var cache:Array = dynamicPartsCache[partName] as Array;
        cache.splice(cache.indexOf(instance), 1);
    }

    /**
     *  Returns the number of instances of a dynamic part.
     *
     *  @param partName The name of the dynamic part.
     *
     *  @return The number of instances of the dynamic part.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function numDynamicParts(partName:String):int
    {
        if (dynamicPartsCache && dynamicPartsCache[partName])
            return dynamicPartsCache[partName].length;
        
        return 0;
    }
    
    /**
     *  Returns a specific instance of a dynamic part.
     *
     *  @param partName The name of the dynamic part.
     *
     *  @param index The index of the dynamic part.
     *
     *  @return The instance of the part, or null if it the part does not exist.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    protected function getDynamicPartAt(partName:String, index:int):Object
    {
        if (dynamicPartsCache && dynamicPartsCache[partName])
            return dynamicPartsCache[partName][index];
        
        return null;
    }

    //---------------------------------
    //  Utility methods for subclasses
    //---------------------------------

    /**
     * @private
     * 
     * Utility method to calculate a skin part's position relative to our component.
     *
     * @param part The skin part instance to obtain coordinates of.
     *
     * @return The component relative position of the part.
     */ 
    protected function getSkinPartPosition(part:IVisualElement):Point
    {
        return (!part || !part.parent) ? new Point(0, 0) :
            globalToLocal(part.parent.localToGlobal(new Point((part as ILayoutElement).getLayoutBoundsX(), (part as ILayoutElement).getLayoutBoundsY())));
    }
    
    /**
     * @private
     * 
     * Utility method to calculate a skin part's baseline position relative to 
     * the component.
     *
     * @param part The skin part instance to obtain baseline of.
     *
     * @return The baseline position of the part.
     */ 
    protected function getBaselinePositionForPart(part:IVisualElement):Number
    {
        if (!part || !validateBaselinePosition())
            return super.baselinePosition;

        return getSkinPartPosition(part).y + part.baselinePosition;
    }

    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------
    
    /**
     * @private
     * Called when a slot on the skin has been assigned a value. Deferred parts
     * may be instantiated long after the skin has been created.
     */
    private function skin_propertyChangeHandler(event:PropertyChangeEvent):void
    {
        if (skinParts)
        {
            var skinPartID:String = event.property as String;
            if (skinParts[skinPartID] != null)
            {
                if (event.newValue == null)
                {
                    if (!(this[skinPartID] is IFactory))
                        partRemoved(skinPartID, this[skinPartID]);
                    this[skinPartID] = event.newValue;
                }
                else
                {
                    this[skinPartID] = event.newValue;                
                    if (!(this[skinPartID] is IFactory))
                        partAdded(skinPartID, this[skinPartID]);
                }
            }
        }
    }
    
    /**
     *  @private
     */
    private function adddedToStageHandler(event:Event):void
    {
        if (skin == null)
        {
            attachSkin();
        }
    }
    
    /**
     *  @private
     */
    private function removedFromStageHandler(event:Event):void
    {
        detachSkin();
    }
    
    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    override public function addChild(child:DisplayObject):DisplayObject
    {
        throw(new Error(resourceManager.getString("components", "addChildError")));
    }
    
    /**
     *  @private
     */
    override public function addChildAt(child:DisplayObject, index:int):DisplayObject
    {
        throw(new Error(resourceManager.getString("components", "addChildAtError")));
    }
    
    /**
     *  @private
     */
    override public function removeChild(child:DisplayObject):DisplayObject
    {
        throw(new Error(resourceManager.getString("components", "removeChildError")));
    }
    
    /**
     *  @private
     */
    override public function removeChildAt(index:int):DisplayObject
    {
        throw(new Error(resourceManager.getString("components", "removeChildAtError")));
    }
    
    /**
     *  @private
     */
    override public function setChildIndex(child:DisplayObject, index:int):void
    {
        throw(new Error(resourceManager.getString("components", "setChildIndexError")));
    }
    
    /**
     *  @private
     */
    override public function swapChildren(child1:DisplayObject, child2:DisplayObject):void
    {
        throw(new Error(resourceManager.getString("components", "swapChildrenError")));
    }
    
    /**
     *  @private
     */
    override public function swapChildrenAt(index1:int, index2:int):void
    {
        throw(new Error(resourceManager.getString("components", "swapChildrenAtError")));
    }
    
    //--------------------------------------------------------------------------
    //
    //  Private variables
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     *  True if the skin has changed and hasn't gone through validation yet.
     */
    private var skinChanged:Boolean = false;
    
    /**
     *  @private
     *  True if the skinFactory style has explicitly changed or not.  We use 
     *  this to determine whether we need to actually create a new skin or 
     *  not in validateSkinChange().
     */
    private var skinFactoryStyleChanged:Boolean = false;
    
        
    /**
     *  @private
     *  Whether the skin state is invalid or not.
     */
    private var skinStateIsDirty:Boolean = false;
}

}
