////////////////////////////////////////////////////////////////////////////////
//
//  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
{

import mx.collections.IList;
import mx.core.IDataRenderer;
import mx.core.IFactory;
import mx.core.IUIComponent;
import mx.core.IVisualElement;
import mx.core.mx_internal;
import mx.events.PropertyChangeEvent;
import mx.utils.BitFlagUtil;

import spark.components.supportClasses.SkinnableContainerBase;
import spark.components.supportClasses.GroupBase;
import spark.components.beads.SkinnableDataContainerView;
import spark.components.beads.SparkDataContainerView;
import spark.core.IViewport;
//import spark.events.RendererExistenceEvent;
import spark.layouts.supportClasses.LayoutBase;

use namespace mx_internal;

import org.apache.royale.core.IBead;
import org.apache.royale.core.IItemRendererProvider;
import org.apache.royale.core.IStrandWithPresentationModel;
import org.apache.royale.core.IListPresentationModel;
import org.apache.royale.html.beads.models.ListPresentationModel;

import org.apache.royale.binding.ContainerDataBinding;
import org.apache.royale.binding.DataBindingBase;
import org.apache.royale.core.IBeadLayout;
import org.apache.royale.core.IBeadView;
import org.apache.royale.core.IChild;
import org.apache.royale.core.ILayoutHost;
import org.apache.royale.core.ILayoutParent;
import org.apache.royale.core.IParent;
import org.apache.royale.core.ItemRendererClassFactory;
import org.apache.royale.core.ValuesManager;
import org.apache.royale.events.Event;
import org.apache.royale.events.IEventDispatcher;
import org.apache.royale.events.ValueEvent;
import org.apache.royale.utils.loadBeadFromValuesManager;


/**
 *  Dispatched when a renderer is added to the container.
 *  The <code>event.renderer</code> property contains 
 *  the renderer that was added.
 *
 *  @eventType spark.events.RendererExistenceEvent.RENDERER_ADD
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
//[Event(name="rendererAdd", type="spark.events.RendererExistenceEvent")]

/**
 *  Dispatched when a renderer is removed from the container.
 *  The <code>event.renderer</code> property contains 
 *  the renderer that was removed.
 *
 *  @eventType spark.events.RendererExistenceEvent.RENDERER_REMOVE
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
//[Event(name="rendererRemove", type="spark.events.RendererExistenceEvent")]

//include "../styles/metadata/BasicInheritingTextStyles.as"

/**
 *  The alpha of the focus ring for this component.
 *
 *  @default 0.55
 * 
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="focusAlpha", type="Number", inherit="no", theme="spark, mobile", minValue="0.0", maxValue="1.0")]

/**
 *  Color of focus ring when the component is in focus.
 *
 *  @default 0x70B2EE
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */ 
[Style(name="focusColor", type="uint", format="Color", inherit="yes", theme="spark, mobile")]

/**
 *  Thickness, in pixels, of the focus rectangle outline.
 *
 *  @default 2
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
[Style(name="focusThickness", type="Number", format="Length", inherit="no", minValue="0.0")]

[DefaultProperty("dataProvider")]

//[IconFile("SkinnableDataContainer.png")]

/**
 *  The SkinnableDataContainer class is the base container class for
 *  data items.  The SkinnableDataContainer class converts data 
 *  items to visual elements for display.
 *  While this container can hold visual elements, it is often used only 
 *  to hold data items as children.
 *
 *  <p>The SkinnableDataContainer class takes as children data items 
 *  or visual elements that implement the IVisualElement interface
 *  and are Display Objects.
 *  Data items can be simple data items such String and Number objects, 
 *  and more complicated data items such as Object and XMLNode objects. 
 *  While these containers can hold visual elements, 
 *  they are often used only to hold data items as children.</p>
 *
 *  <p>An item renderer defines the visual representation of the 
 *  data item in the container. 
 *  The item renderer converts the data item into a format that can 
 *  be displayed by the container. 
 *  You must pass an item renderer to a SkinnableDataContainer to 
 *  render data items appropriately.</p>
 *
 *  <p>If you want a container of data items and don't need a skin, then 
 *  it is recommended to use a DataGroup (which cannot be skinned) to 
 *  improve performance and application size.</p>
 *
 *  <p>The SkinnableDataContainer container has the following default characteristics:</p>
 *  <table class="innertable">
 *     <tr><th>Characteristic</th><th>Description</th></tr>
 *     <tr><td>Default size</td><td>Large enough to display its children</td></tr>
 *     <tr><td>Minimum size</td><td>0 pixels</td></tr>
 *     <tr><td>Maximum size</td><td>10000 pixels wide and 10000 pixels high</td></tr>
 *  </table>
 * 
 *  @mxml
 *
 *  <p>The <code>&lt;s:SkinnableDataContainer&gt;</code> tag inherits all of the tag 
 *  attributes of its superclass and adds the following tag attributes:</p>
 *
 *  <pre>
 *  &lt;s:SkinnableDataContainer
 *    <strong>Properties</strong>
 *    autoLayout="true"
 *    dataProvider="null"
 *    itemRenderer="null"
 *    itemRendererFunction="null"
 *    layout="VerticalLayout"
 *    typicalItem="null"
 *  
 *    <strong>Styles</strong>
 *    alignmentBaseline="useDominantBaseline"
 *    baselineShift="0.0"
 *    cffHinting="horizontal_stem"
 *    color="0"
 *    digitCase="default"
 *    digitWidth="default"
 *    direction="LTR"
 *    dominantBaseline="auto"
 *    focusAlpha="0.55"
 *    focusColor=""
 *    focusThickness="2"
 *    fontFamily="Arial"
 *    fontLookup="device"
 *    fontSize="12"
 *    fontStyle="normal"
 *    fontWeight="normal"
 *    justificationRule="auto"
 *    justificationStyle="auto"
 *    kerning="auto"
 *    ligatureLevel="common"
 *    lineHeight="120%"
 *    lineThrough="false"
 *    locale="en"
 *    renderingMode="CFF"
 *    textAlign="start"
 *    textAlignLast="start"
 *    textAlpha="1"
 *    textJustify="inter_word"
 *    trackingLeft="0"
 *    trackingRight="0"
 *    typographicCase="default"
 *  
 *    <strong>Events</strong>
 *    rendererAdd="<i>No default</i>"
 *    rendererRemove="<i>No default</i>"
 *  /&gt;
 *  </pre>
 *
 *  @see SkinnableContainer
 *  @see DataGroup
 *  @see spark.skins.spark.SkinnableDataContainerSkin
 *
 *  @includeExample examples/SkinnableDataContainerExample.mxml
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Royale 0.9.8
 */
public class SkinnableDataContainer extends SkinnableContainerBase implements IItemRendererProvider, IStrandWithPresentationModel, ILayoutParent
{ //implements IItemRendererOwner
    //include "../core/Version.as";
    
    //--------------------------------------------------------------------------
    //
    //  Class constants
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private static const AUTO_LAYOUT_PROPERTY_FLAG:uint = 1 << 0;
    
    /**
     *  @private
     */
    private static const DATA_PROVIDER_PROPERTY_FLAG:uint = 1 << 1;
    
    /**
     *  @private
     */
    private static const ITEM_RENDERER_PROPERTY_FLAG:uint = 1 << 2;
    
    /**
     *  @private
     */
    private static const ITEM_RENDERER_FUNCTION_PROPERTY_FLAG:uint = 1 << 3;
    
    /**
     *  @private
     */
    private static const LAYOUT_PROPERTY_FLAG:uint = 1 << 4;
    
    /**
     *  @private
     */
    private static const TYPICAL_ITEM_PROPERTY_FLAG:uint = 1 << 5;
    
    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructor. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Royale 0.9.8
     */
    public function SkinnableDataContainer()
    {
        super();
        typeNames = "SkinnableDataContainer";
    }


    /**
     * Returns the ILayoutHost which is its view. From ILayoutParent.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion Royale 0.8
     */
    public function getLayoutHost():ILayoutHost
    {
        return view as ILayoutHost;
    }

    
    /**
     *  The presentation model for the list.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion Royale 0.9
     *  @royaleignorecoercion org.apache.royale.core.IListPresentationModel
     */
    public function get presentationModel():IBead
    {
        var presModel:IListPresentationModel = getBeadByType(IListPresentationModel) as IListPresentationModel;
        if (presModel == null) {
            presModel = new ListPresentationModel();
            presModel.rowHeight = 18;
            addBead(presModel);
        }
        return presModel;
    }

    
    //--------------------------------------------------------------------------
    //
    //  Skin Parts
    //
    //--------------------------------------------------------------------------
    
    [Bindable]
    [SkinPart(required="false")]
    
    /**
     *  An optional skin part that defines the DataGroup in the skin class 
     *  where data items get pushed into, rendered, and laid out.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    //public var dataGroup:DataGroup;
    
    /**
     *  @private
     *  Several properties are proxied to dataGroup.  However, when dataGroup
     *  is not around, we need to store values set on SkinnableDataContainer.  This object 
     *  stores those values.  If dataGroup is around, the values are stored 
     *  on the dataGroup directly.  However, we need to know what values 
     *  have been set by the developer on the SkinnableDataContainer (versus set on 
     *  the dataGroup or defaults of the dataGroup) as those are values 
     *  we want to carry around if the dataGroup changes (via a new skin). 
     *  In order to store this info effeciently, dataGroupProperties becomes 
     *  a uint to store a series of BitFlags.  These bits represent whether a 
     *  property has been explicitly set on this SkinnableDataContainer.  When the 
     *  dataGroup is not around, dataGroupProperties is a typeless 
     *  object to store these proxied properties.  When dataGroup is around,
     *  dataGroupProperties stores booleans as to whether these properties 
     *  have been explicitly set or not.
     */
    //private var dataGroupProperties:Object = {};
    
    //--------------------------------------------------------------------------
    //
    //  Properties 
    //
    //--------------------------------------------------------------------------
    
    //--------------------------------------------------------------------------
    //
    //  Properties proxied to dataGroup
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  autoLayout
    //----------------------------------

    //[Inspectable(defaultValue="true")]

    /**
     *  @copy spark.components.supportClasses.GroupBase#autoLayout
     *
     *  @default true
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    /* public function get autoLayout():Boolean
    {
        if (dataGroup)
            return dataGroup.autoLayout;
        else
        {
            // want the default to be true
            var v:* = dataGroupProperties.autoLayout;
            return (v === undefined) ? true : v;
        }
    } */

    /**
     *  @private
     */
    /* public function set autoLayout(value:Boolean):void
    {
        if (dataGroup)
        {
            dataGroup.autoLayout = value;
            dataGroupProperties = BitFlagUtil.update(dataGroupProperties as uint, 
                                                     AUTO_LAYOUT_PROPERTY_FLAG, true);
        }
        else
            dataGroupProperties.autoLayout = value;
    }
     */
    //----------------------------------
    //  dataProvider
    //----------------------------------    
    
    /**
     *  @copy spark.components.DataGroup#dataProvider
     *
     *  @see #itemRenderer
     *  @see #itemRendererFunction
     *  @see mx.collections.IList
     *  @see mx.collections.ArrayCollection
     *  @see mx.collections.ArrayList
     *  @see mx.collections.XMLListCollection
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Royale 0.9.8
     * 
     *  @royaleignorecoercion spark.components.DataGroup
     *  @royaleignorecoercion spark.components.beads.SparkDataContainerView
     */
    [Bindable("dataProviderChanged")]
    [Inspectable(category="Data")]
    
    public function get dataProvider():IList
    {       
        /* return (dataGroup) 
            ? dataGroup.dataProvider 
            : dataGroupProperties.dataProvider; */

        return ((view as SparkDataContainerView).contentView as DataGroup).dataProvider;
    }
    
    /**
     *  @private
     *  @royaleignorecoercion spark.components.DataGroup
     *  @royaleignorecoercion spark.components.beads.SparkDataContainerView
     */
    public function set dataProvider(value:IList):void
    {
        /* if (dataGroup)
        {
            dataGroup.dataProvider = value;
            dataGroupProperties = BitFlagUtil.update(dataGroupProperties as uint, 
                                                     DATA_PROVIDER_PROPERTY_FLAG, true);
        }
        else
            dataGroupProperties.dataProvider = value;
        dispatchEvent(new Event("dataProviderChanged")); */

        if (isWidthSizedToContent() || isHeightSizedToContent())
            ((view as SparkDataContainerView).contentView as DataGroup).addEventListener("itemsCreated", itemsCreatedHandler);
        ((view as SparkDataContainerView).contentView as DataGroup).dataProvider = value;
    }

    private function itemsCreatedHandler(event:Event):void
    {
        if (parent)
        {
            COMPILE::JS
            {
                // clear last width/height so elements size to content
                element.style.width = "";
                element.style.height = "";
                ((view as SparkDataContainerView).contentView as DataGroup).element.style.width = "";
                ((view as SparkDataContainerView).contentView as DataGroup).element.style.height = "";
            }
            (parent as IEventDispatcher).dispatchEvent(new Event("layoutNeeded"));
        }
    }
    
    //----------------------------------
    //  itemRenderer
    //----------------------------------
    
    [Inspectable(category="Data")]
    
    /**
     *  @copy spark.components.DataGroup#itemRenderer
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Royale 0.9.8
     */
    [SWFOverride(returns="org.apache.royale.core.IFactory")]
    public function get itemRenderer():IFactory
    {
        /* return (dataGroup) 
            ? dataGroup.itemRenderer 
            : dataGroupProperties.itemRenderer; */

        return ((view as SparkDataContainerView).contentView as DataGroup).itemRenderer;
    }
    
    /**
     *  @private
     */
    [SWFOverride(params="org.apache.royale.core.IFactory", altparams="mx.core.IFactory")]
    public function set itemRenderer(value:IFactory):void
    {
        /* if (dataGroup)
        {
            dataGroup.itemRenderer = value;
            dataGroupProperties = BitFlagUtil.update(dataGroupProperties as uint, 
                                                     ITEM_RENDERER_PROPERTY_FLAG, true);
        }
        else
            dataGroupProperties.itemRenderer = value; */

        ((view as SparkDataContainerView).contentView as DataGroup).itemRenderer = value;
        // the ItemRendererFactory was already put on the DataGroup's strand and
        // determined which factory to use so we have to set it up later here.
        var factory:ItemRendererClassFactory = ((view as SparkDataContainerView).contentView as DataGroup).getBeadByType(ItemRendererClassFactory) as ItemRendererClassFactory;
        factory.createFunction = factory.createFromClass;
        factory.itemRendererFactory = value;
    }
    
    //----------------------------------
    //  itemRendererFunction
    //----------------------------------
    
    [Inspectable(category="Data")]
    
    /**
     *  @copy spark.components.DataGroup#itemRendererFunction
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Royale 0.9.8
     */
    public function get itemRendererFunction():Function
    {
        /* return (dataGroup) 
            ? dataGroup.itemRendererFunction 
            : dataGroupProperties.itemRendererFunction; */

        return null;
    }
    
    /**
     *  @private
     */
    public function set itemRendererFunction(value:Function):void
    {
        /* if (dataGroup)
        {
            dataGroup.itemRendererFunction = value;
            dataGroupProperties = BitFlagUtil.update(dataGroupProperties as uint, 
                                                     ITEM_RENDERER_FUNCTION_PROPERTY_FLAG, true);
        }
        else
            dataGroupProperties.itemRendererFunction = value; */
    }
    
    //----------------------------------
    //  layout
    //----------------------------------

    private var _layout:LayoutBase;
    
    [Inspectable(category="General")]
    
    /**
     *  @copy spark.components.supportClasses.GroupBase#layout
     *
     *  @default VerticalLayout
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Royale 0.9.8
     */     
    public function get layout():LayoutBase
    {
        /* return (dataGroup) 
            ? dataGroup.layout 
            : dataGroupProperties.layout;
         */
        //if (!_layout)
        //    _layout = new BasicLayout();
        return _layout;
    }

    /**
     *  @private
     *  @royaleignorecoercion spark.components.GroupBase
     *  @royaleignorecoercion spark.components.beads.SparkDataContainerView
     */
    public function set layout(value:LayoutBase):void
    {
        /*
        if (dataGroup)
        {
            dataGroup.layout = value;
            dataGroupProperties = BitFlagUtil.update(dataGroupProperties as uint, 
                                                     LAYOUT_PROPERTY_FLAG, true);
        }
        else
            dataGroupProperties.layout = value;
         */
        _layout = value;
        if (getBeadByType(IBeadView))
        {
            ((view as SkinnableDataContainerView).contentView as GroupBase).layout = value;
            if (parent)
                ((view as SkinnableDataContainerView).contentView as GroupBase).dispatchEvent(new Event("layoutNeeded"));       
        }
    }
    
    //----------------------------------
    //  typicalItem
    //----------------------------------

    //[Inspectable(category="Data")]
    
    /**
     *  @copy spark.components.DataGroup#typicalItem
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
     public function get typicalItem():Object
    {
        trace("SkinnableDataContainer::typicalItem is not implemented");
        return null;
        /*return (dataGroup) 
            ? dataGroup.typicalItem 
            : dataGroupProperties.typicalItem;*/
    } 

    /**
     *  @private
     */
     public function set typicalItem(value:Object):void
    {
        trace("SkinnableDataContainer::typicalItem is not implemented");
        /*if (dataGroup)
        {
            dataGroup.typicalItem = value;
            dataGroupProperties = BitFlagUtil.update(dataGroupProperties as uint, 
                                                     TYPICAL_ITEM_PROPERTY_FLAG, true);
        }
        else
            dataGroupProperties.typicalItem = value;*/
    } 
    
    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  From the specified data item, return the String representation 
     *  of the data item for an item renderer to display.
     *  This method uses the <code>toString()</code> method of 
     *  the data item to convert it to a String representation.
     *  A Null data item returns an empty string.
     *
     *  @param item The data item.
     *
     *  @return The String representation of the data item.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Royale 0.9.8
     */
    public function itemToLabel(item:Object):String
    {
        if (item !== null)
            return item.toString();
        else return " ";
    }

    /**
     *  Updates an item renderer for use or reuse. 
     *  When an item renderer is first created,
     *  or when it is recycled because of virtualization, this 
     *  SkinnableDataContainer instance can set the 
     *  item renderer's <code>label</code> property and 
     *  <code>owner</code> property. 
     *  
     *  @param renderer The renderer being updated. 
     *  
     *  @param itemIndex The index of the data item in the data provider. 
     *  
     *  @param data The data object this item renderer is representing. 
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     * 
     */
    /* public function updateRenderer(renderer:IVisualElement, itemIndex:int, data:Object):void
    {
        // set the owner
        renderer.owner = this;
        
        // Set the index
        if (renderer is IItemRenderer)
            IItemRenderer(renderer).itemIndex = itemIndex;

        // set the label to the toString() of the data 
        if (renderer is IItemRenderer)
            IItemRenderer(renderer).label = itemToLabel(data);
        
        // always set the data last
        if ((renderer is IDataRenderer) && (renderer !== data))
            IDataRenderer(renderer).data = data;
    }
     */
    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------
    
    /**
     *  @private
     */
    override protected function partAdded(partName:String, instance:Object):void
    {
        super.partAdded(partName, instance);

        /* if (instance == dataGroup)
        {
            // copy proxied values from dataGroupProperties (if set) to dataGroup
            
            var newDataGroupProperties:uint = 0;
            
            if (dataGroupProperties.layout !== undefined)
            {
                dataGroup.layout = dataGroupProperties.layout;
                newDataGroupProperties = BitFlagUtil.update(newDataGroupProperties as uint, 
                                                            LAYOUT_PROPERTY_FLAG, true);;
            }
            
            if (dataGroupProperties.autoLayout !== undefined)
            {
                dataGroup.autoLayout = dataGroupProperties.autoLayout;
                newDataGroupProperties = BitFlagUtil.update(newDataGroupProperties as uint, 
                                                            AUTO_LAYOUT_PROPERTY_FLAG, true);
            }
            
            if (dataGroupProperties.dataProvider !== undefined)
            {
                dataGroup.dataProvider = dataGroupProperties.dataProvider;
                newDataGroupProperties = BitFlagUtil.update(newDataGroupProperties as uint, 
                                                            DATA_PROVIDER_PROPERTY_FLAG, true);
            }
            
            if (dataGroupProperties.itemRenderer !== undefined)
            {
                dataGroup.itemRenderer = dataGroupProperties.itemRenderer;
                newDataGroupProperties = BitFlagUtil.update(newDataGroupProperties as uint, 
                                                            ITEM_RENDERER_PROPERTY_FLAG, true);
            }
            
            if (dataGroupProperties.itemRendererFunction !== undefined)
            {
                dataGroup.itemRendererFunction = dataGroupProperties.itemRendererFunction;
                newDataGroupProperties = BitFlagUtil.update(newDataGroupProperties as uint, 
                                                            ITEM_RENDERER_FUNCTION_PROPERTY_FLAG, true);
            }
                       
            if (dataGroupProperties.typicalItem !== undefined)
            {
                dataGroup.typicalItem = dataGroupProperties.typicalItem;
                newDataGroupProperties = BitFlagUtil.update(newDataGroupProperties as uint, 
                                                            TYPICAL_ITEM_PROPERTY_FLAG, true);
            }
            
            dataGroupProperties = newDataGroupProperties;
            
            // Register our instance as the dataGroup's item renderer update delegate.
            dataGroup.rendererUpdateDelegate = this;
            
            // The only reason we have these listeners is to re-dispatch events.  
            // We only add as necessary.
            
            if (hasEventListener(RendererExistenceEvent.RENDERER_ADD))
            {
                dataGroup.addEventListener(
                    RendererExistenceEvent.RENDERER_ADD, dispatchEvent);
            }
            
            if (hasEventListener(RendererExistenceEvent.RENDERER_REMOVE))
            {
                dataGroup.addEventListener(
                    RendererExistenceEvent.RENDERER_REMOVE, dispatchEvent);
            }
        } */
    }
    
    /**
     * @private
     */
    override protected function partRemoved(partName:String, instance:Object):void
    {
        /* super.partRemoved(partName, instance);

        if (instance == dataGroup)
        {
            dataGroup.removeEventListener(
                RendererExistenceEvent.RENDERER_ADD, dispatchEvent);
            dataGroup.removeEventListener(
                RendererExistenceEvent.RENDERER_REMOVE, dispatchEvent);
            
            // copy proxied values from dataGroup (if explicitly set) to dataGroupProperties
            
            var newDataGroupProperties:Object = {};
            
            if (BitFlagUtil.isSet(dataGroupProperties as uint, LAYOUT_PROPERTY_FLAG))
                newDataGroupProperties.layout = dataGroup.layout;
            
            if (BitFlagUtil.isSet(dataGroupProperties as uint, AUTO_LAYOUT_PROPERTY_FLAG))
                newDataGroupProperties.autoLayout = dataGroup.autoLayout;
            
            if (BitFlagUtil.isSet(dataGroupProperties as uint, DATA_PROVIDER_PROPERTY_FLAG))
                newDataGroupProperties.dataProvider = dataGroup.dataProvider;
            
            if (BitFlagUtil.isSet(dataGroupProperties as uint, ITEM_RENDERER_PROPERTY_FLAG))
                newDataGroupProperties.itemRenderer = dataGroup.itemRenderer;
            
            if (BitFlagUtil.isSet(dataGroupProperties as uint, ITEM_RENDERER_FUNCTION_PROPERTY_FLAG))
                newDataGroupProperties.itemRendererFunction = dataGroup.itemRendererFunction;
            
            if (BitFlagUtil.isSet(dataGroupProperties as uint, TYPICAL_ITEM_PROPERTY_FLAG))
                newDataGroupProperties.typicalItem = dataGroup.typicalItem;
            
            dataGroupProperties = newDataGroupProperties;
            
            dataGroup.dataProvider = null;
            dataGroup.layout = null;
            dataGroup.rendererUpdateDelegate = null;
        } */
    }
    
    /**
     *  @private
     * 
     *  This method is overridden so we can figure out when someone starts listening
     *  for property change events.  If no one's listening for them, then we don't 
     *  listen for them on our dataGroup.
     */
    /* override public function addEventListener(
        type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false) : void
    {
        super.addEventListener(type, listener, useCapture, priority, useWeakReference);
        
        // TODO (rfrishbe): this isn't ideal as we should deal with the useCapture, 
        // priority, and useWeakReference parameters.
        
        // if it's a different type of event or the dataGroup doesn't
        // exist, don't worry about it.  When the dataGroup, 
        // gets created up, we'll check to see whether we need to add this 
        // event listener to the dataGroup.
        
        if (type == RendererExistenceEvent.RENDERER_ADD && dataGroup)
        {
            dataGroup.addEventListener(
                RendererExistenceEvent.RENDERER_ADD, dispatchEvent);
        }
        
        if (type == RendererExistenceEvent.RENDERER_REMOVE && dataGroup)
        {
            dataGroup.addEventListener(
                RendererExistenceEvent.RENDERER_REMOVE, dispatchEvent);
        }
    } */
    
    /**
     *  @private
     * 
     *  This method is overridden so we can figure out when someone stops listening
     *  for property change events.  If no one's listening for them, then we don't 
     *  listen for them on our dataGroup.
     */
    /* override public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false) : void
    {
        super.removeEventListener(type, listener, useCapture);
        
        // if no one's listening to us for this event any more, let's 
        // remove our underlying event listener from the dataGroup.
        if (type == RendererExistenceEvent.RENDERER_ADD && dataGroup)
        {
            if (!hasEventListener(RendererExistenceEvent.RENDERER_ADD))
            {
                dataGroup.removeEventListener(
                    RendererExistenceEvent.RENDERER_ADD, dispatchEvent);
            }
        }
        
        if (type == RendererExistenceEvent.RENDERER_REMOVE && dataGroup)
        {
            if (!hasEventListener(RendererExistenceEvent.RENDERER_REMOVE))
            {
                dataGroup.removeEventListener(
                    RendererExistenceEvent.RENDERER_REMOVE, dispatchEvent);
            }
        }
    } */

    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------

    //--------------------------------------------------------------------------
    //
    //  IMXMLDocument et al
    //
    //--------------------------------------------------------------------------
    
    private var _mxmlDescriptor:Array;
    private var _mxmlDocument:Object = this;

    /**
     *  @private
     *  @royaleignorecoercion spark.components.DataGroup
     *  @royaleignorecoercion spark.components.beads.SparkDataContainerView
     */
    override public function addedToParent():void
    {
//        if (!getBeadByType(IBeadLayout))
//            addBead(new VerticalLayout());

        if (!initialized) {
            // each MXML file can also have styles in fx:Style block
            ValuesManager.valuesImpl.init(this);
        }

        super.addedToParent();

        // Load the layout bead if it hasn't already been loaded.
        loadBeadFromValuesManager(IBeadLayout, "iBeadLayout", this);

        dispatchEvent(new Event("beadsAdded"));
        dispatchEvent(new Event("initComplete"));
        if ((isHeightSizedToContent() || !isNaN(explicitHeight)) &&
            (isWidthSizedToContent() || !isNaN(explicitWidth)))
            dispatchEvent(new Event("layoutNeeded"));

//		((view as SparkDataContainerView).contentView as DataGroup).addEventListener("change", redispatcher);
		((view as SparkDataContainerView).contentView as DataGroup).addEventListener("itemClick", redispatcher);
		((view as SparkDataContainerView).contentView as DataGroup).addEventListener("doubleClick", redispatcher);
		
        setActualSize(getExplicitOrMeasuredWidth(), getExplicitOrMeasuredHeight());
    }

    override protected function createChildren():void
    {
        super.createChildren();
        
        if (getBeadByType(DataBindingBase) == null)
            addBead(new ContainerDataBinding());
        
        dispatchEvent(new Event("initBindings"));
    }
    
    override public function setActualSize(w:Number, h:Number):void
    {
        super.setActualSize(w, h);
        ((view as SparkDataContainerView).contentView as DataGroup).setActualSize(w, h);
    }

	private function redispatcher(event:Event):void
	{
		dispatchEvent(new Event(event.type));
	}
}

}
