You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ma...@apache.org on 2013/10/05 01:03:10 UTC

[04/15] https://issues.apache.org/jira/browse/FLEX-33777 Dagrid for mobile - formatted sources code - added ASDOC (almost all) - bug: Bitmap renderer does not support MultiDPI when appDPI is set

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/MobileGridColumn.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/MobileGridColumn.as b/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/MobileGridColumn.as
new file mode 100644
index 0000000..a404bb2
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/MobileGridColumn.as
@@ -0,0 +1,148 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.events.IEventDispatcher;
+
+import mx.utils.ObjectUtil;
+
+import spark.collections.SortField;
+
+/**
+ *  The MobileGridColumn class defines  a column to display in a MobileGrid control.
+ * <p> The MobileGridColumn class specifies the characteristics of the column to display,
+ * such as the field of the data provider item whose value is to be displayed in the column.
+ * MobileGridColumn takes most of its properties  from its parent class and adds the following Grid-specific options:</p>
+ * <ul>
+ *     <li>headerText and headerStyleName: optional label and style to display in the header for this column </li>
+ *     <li>sortable, sortDescending and sortField: sorting options for this column </li>
+ *  </ul>
+ *
+ *  @see spark.components.MobileGrid
+ *  @see spark.components.supportClasses.PartRendererDescriptorBase
+ *
+ *  @langversion 3.0
+ *  @playerversion AIR 3.8
+ *  @productversion Flex 4.11
+ */
+public class MobileGridColumn extends PartRendererDescriptorBase
+{
+
+    private var _headerText:String = null;
+    private var _headerStyleName:String;
+    private var _sortDescending:Boolean;
+    private var _sortable: Boolean = true;
+
+    public function MobileGridColumn(target:IEventDispatcher = null)
+    {
+        super(target);
+        labelFunction = null;
+        width = 100; // default width;
+        itemRenderer = null; // will set default ;
+    }
+
+    /** Defines the text to be displayed in the column's header.
+     * <p>If this property is not set, the header label will use the value  of dataField property instead.</p>
+     * @see #dataField
+     */
+    public function get headerText():String
+    {
+        return _headerText != null ? _headerText : dataField ;
+    }
+
+    public function set headerText(value:String):void
+    {
+        _headerText = value;
+    }
+
+    /** Defines the css style name to be used for displaying this column's header label.
+     * <p>Use this property to display the header in a different color or font, or with a different text alignment.</p>
+     */
+    public function get headerStyleName():String
+    {
+        return _headerStyleName;
+    }
+
+    public function set headerStyleName(value:String):void
+    {
+        _headerStyleName = value;
+    }
+
+    /** Flag indicating whether a column can be sorted by clicking on its header.
+     *  <p>This flag is effective only if the MobileGrid </p>
+     */
+    public function get sortable():Boolean
+    {
+        return _sortable;
+    }
+
+    public function set sortable(value:Boolean):void
+    {
+        _sortable = value;
+    }
+
+    public function get sortDescending():Boolean
+    {
+        return _sortDescending;
+    }
+
+    public function set sortDescending(value:Boolean):void
+    {
+        _sortDescending = value;
+    }
+
+    //----------------------------------
+    //  sortField
+    //----------------------------------
+
+    /**
+     *  Returns a SortField that can be used to sort a collection by this
+     *  column's <code>dataField</code>.
+     *
+     *
+     *  <p>If the <code>dataField</code> properties are not defined, but the
+     *  <code>labelFunction</code> property is defined, then it assigns the
+     *  <code>compareFunction</code> to a closure that does a basic string compare
+     *  on the <code>labelFunction</code> applied to the data objects.</p>
+
+     */
+    public function get sortField():SortField
+    {
+        const column:MobileGridColumn = this;
+
+        var sortField:SortField = new SortField(dataField);
+
+        var cF:Function = null;
+        if (dataField == null && labelFunction != null)
+        {
+            // use basic string compare on the labelFunction results
+            cF = function (a:Object, b:Object):int
+            {
+                return ObjectUtil.stringCompare(labelFunction(a), labelFunction(b));
+            };
+            sortField.compareFunction = cF;
+        }
+        sortField.descending = column.sortDescending;
+        return sortField;
+    }
+
+
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/MobileGridHeader.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/MobileGridHeader.as b/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/MobileGridHeader.as
new file mode 100644
index 0000000..1cdfbf6
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/MobileGridHeader.as
@@ -0,0 +1,151 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 mx.collections.ArrayList;
+import mx.core.UIComponent;
+import mx.core.mx_internal;
+
+import spark.components.ButtonBar;
+import spark.components.MobileGrid;
+import spark.events.IndexChangeEvent;
+import spark.events.MobileGridHeaderEvent;
+import spark.events.RendererExistenceEvent;
+import spark.utils.MultiDPIBitmapSource;
+
+use namespace  mx_internal;
+
+[Event(name="sortChange", type="spark.events.MobileGridHeaderEvent")]
+
+/**  @private
+ *    internal class used by MobileGrid to manage and display  the grid's column headers.
+ *    It inherits from ButtonBar so that headers can display text and be clicked and forwards header clicks to the MobileGrid for managing sorting.
+ *    the default skin for this class is : spark.skins.MobileGridHeaderButtonBarSkin
+ *
+ *    @see spark.skins.MobileGridHeaderButtonBarSkin
+ */
+public class MobileGridHeader extends ButtonBar
+{
+
+    [Embed(source="../../../../assets/images/mobile320/dg_header_asc.png")]
+    private const ascIcon320Cls:Class;
+
+    [Embed(source="../../../../assets/images/mobile320/dg_header_desc.png")]
+    private const descIcon320Cls:Class;
+
+    [Embed(source="../../../../assets/images/mobile160/dg_header_asc.png")]
+    private const ascIcon160Cls:Class;
+
+    [Embed(source="../../../../assets/images/mobile160/dg_header_desc.png")]
+    private const descIcon160Cls:Class;
+
+    protected var descIconCls:MultiDPIBitmapSource;
+    protected var ascIconCls:MultiDPIBitmapSource;
+
+    private var _dataGrid:MobileGrid;
+    private var _columns: Array;
+    private var _sortIndex:int = -1;
+
+      public function MobileGridHeader()
+    {
+        this.labelField = "headerText";
+        this.iconFunction = getIconForButton;
+        this.setStyle("iconPlacement", "right");
+        this.buttonMode = false;
+        this.requireSelection = false;
+        addEventListener(IndexChangeEvent.CHANGING, changingHandler);
+        addEventListener(RendererExistenceEvent.RENDERER_ADD, rendererAddHandler);
+
+        descIconCls = new MultiDPIBitmapSource();
+        descIconCls.source160dpi = descIcon160Cls;
+        descIconCls.source320dpi = descIcon320Cls;
+        ascIconCls = new MultiDPIBitmapSource();
+        ascIconCls.source160dpi = ascIcon160Cls;
+        ascIconCls.source320dpi = ascIcon320Cls;
+    }
+
+    public function set columns(value:Array):void
+    {
+        _columns = value;
+        if (_columns)
+        {
+            dataProvider = new ArrayList(_columns);
+        }
+        else
+        {
+            dataProvider = null;
+        }
+    }
+
+    public function set dataGrid(value:MobileGrid):void
+    {
+        _dataGrid = value;
+    }
+
+    private function changingHandler(event:IndexChangeEvent):void
+    {
+        event.preventDefault();      // to clear selection
+        var i:int = event.newIndex;
+        var c: MobileGridColumn = _columns[i];
+        if (_dataGrid.sortableColumns && c.sortable)   {
+            var headerEvent:MobileGridHeaderEvent = new MobileGridHeaderEvent(MobileGridHeaderEvent.SORT_CHANGE, c.colNum, false, true);
+            // HEADER_RELEASE event is cancelable
+            dispatchEvent(headerEvent);
+        }
+    }
+
+    /* will be sent back by MobileGrid when sort is confirmed */
+    mx_internal function setSort(newSortIndex:int, desc:Boolean):void
+    {
+        var prevSortIndex:int = _sortIndex;
+        _sortIndex = newSortIndex;
+
+        // update old and new
+        if (prevSortIndex != -1)
+            dataProvider.itemUpdated(_columns[prevSortIndex]);
+        if (_sortIndex != -1)
+            dataProvider.itemUpdated(_columns[_sortIndex]);
+    }
+
+    private function rendererAddHandler(event:RendererExistenceEvent):void
+    {
+        var button:UIComponent = UIComponent(event.renderer);
+        var index:int = event.index;
+        var col:MobileGridColumn = MobileGridColumn(_columns[index]);
+        // don't size the last button
+        if (index != dataProvider.length - 1)
+            button.explicitWidth = col.scaledWidth;
+        else
+            button.percentWidth = 100;
+    }
+
+    private function getIconForButton(col:MobileGridColumn):Object
+    {
+        if (col.colNum === _sortIndex)
+        {
+            return  col.sortDescending ? descIconCls : ascIconCls;
+        }
+        else
+        {
+            return null;
+        }
+    }
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/MobileGridRowRenderer.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/MobileGridRowRenderer.as b/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/MobileGridRowRenderer.as
new file mode 100644
index 0000000..0461d22
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/MobileGridRowRenderer.as
@@ -0,0 +1,34 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+{
+
+/**  @private
+ *    This is the internal list itemRenderer used for rendering grid cells in a single row of a MobileGrid.
+ *    It inherits all its behavior for its parent class and only sets the part renderers layout.
+ */
+public class MobileGridRowRenderer extends ListMultiPartItemRendererBase
+{
+    public function MobileGridRowRenderer()
+    {
+        partRenderersLayout = new ListMultiPartTabbedLayout(this);
+    }
+
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/PartRendererDescriptorBase.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/PartRendererDescriptorBase.as b/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/PartRendererDescriptorBase.as
new file mode 100644
index 0000000..57a3cbb
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/components/supportClasses/PartRendererDescriptorBase.as
@@ -0,0 +1,184 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.events.EventDispatcher;
+import flash.events.IEventDispatcher;
+
+import mx.core.ClassFactory;
+import mx.core.DPIClassification;
+import mx.core.IFactory;
+import mx.core.mx_internal;
+
+import spark.components.itemRenderers.IItemPartRendererBase;
+import spark.components.itemRenderers.IItemTextPartRenderer;
+import spark.components.itemRenderers.ItemTextPartRenderer;
+import spark.utils.DensityUtil2;
+
+/**  This is the base class for GridColumn
+ *
+ */
+public class PartRendererDescriptorBase extends EventDispatcher implements IPartRendererDescriptor
+{
+
+    private var _colNum:int;
+    private var _dataField:String;
+    private var _width:Number;
+    private var _scaledWidth:Number;
+    private var _itemRenderer:IFactory;
+    private var _labelFunction:Function;
+    private var _styleName:String;
+    private var _textAlign:String;
+
+    public function PartRendererDescriptorBase(target:IEventDispatcher = null)
+    {
+        super(target);
+        _labelFunction = null;
+        width = 100; // default width;
+        itemRenderer = null; // will set default ;
+    }
+
+    /* IDataGridColumn impl*/
+
+    public function set dataField(value:String):void
+    {
+        _dataField = value;
+    }
+
+    public function get dataField():String
+    {
+        return _dataField;
+    }
+
+    public function get labelFunction():Function
+    {
+        return _labelFunction;
+    }
+
+    /**
+     *  An idempotent function that converts a data provider item into a column-specific string
+     *  that's used to initialize the item renderer's <code>label</code> property.
+     *
+     *  <p>You can use a label function to combine the values of several data provider items
+     *  into a single string.
+     *  If specified, this property is used by the
+     *  <code>itemToLabel()</code> method, which computes the value of each item
+     *  renderer's <code>label</code> property in this column.</p>
+     *
+     *  <p>The function specified to the <code>labelFunction</code> property
+     *  must have the following signature:</p>
+     *
+     *  <pre>labelFunction(item:Object):String</pre>
+     *
+     *  <p>The <code>item</code> parameter is the data provider item for an entire row.
+     *  The second parameter is this column object.</p>
+     *
+     *  <p>A typical label function could concatenate the firstName and
+     *  lastName properties of the data provider item ,
+     *  or do some custom formatting on a Date value property.</p>
+     */
+    public function set labelFunction(value:Function):void
+    {
+        _labelFunction = value;
+    }
+
+    public function set styleName(value:String):void
+    {
+        _styleName = value;
+    }
+
+    /** set the desired width of the column at the application's current DPI (or 160 if none)
+     * default value is 100
+     * the actual pixel width maybe higher if the runtimeDPI or application DPI  are different than 160
+     *
+     * @param value = desired width of the column at 160 DPI
+     */
+    public function set width(value:Number):void
+    {
+        _width = value;
+        _scaledWidth = DensityUtil2.dpiScale(value, DPIClassification.DPI_160);
+    }
+
+    /** set the desired width of the column at the application's current DPI (or 160 if none)
+     * default value is 100
+     * the actual pixel width maybe higher if the runtimeDPI or application DPI  are different than 160
+     *
+     * @param value = desired width of the column at 160 DPI
+     */
+    public function set widthAt160DPI(value:Number):void
+    {
+        _width = value;
+        _scaledWidth = DensityUtil2.dpiScale(value, DPIClassification.DPI_160);
+    }
+
+    public function get scaledWidth():Number
+    {
+        return  _scaledWidth;
+    }
+
+    mx_internal function get colNum():int
+    {
+        return _colNum;
+    }
+
+    mx_internal function set colNum(value:int):void
+    {
+        _colNum = value;
+    }
+
+    public function get itemRenderer():IFactory
+    {
+        return _itemRenderer;
+    }
+
+    public function set itemRenderer(value:IFactory):void
+    {
+        _itemRenderer = value ? value : new ClassFactory(ItemTextPartRenderer);
+    }
+
+    public function get styleName():String
+    {
+        return _styleName;
+    }
+
+    [Inspectable(enumeration="left,right,center,justify")]
+    public function set textAlign(value:String):void
+    {
+        _textAlign = value;
+    }
+
+    public function createPartRenderer():IItemPartRendererBase
+    {
+        var pr:IItemPartRendererBase = _itemRenderer.newInstance() as IItemPartRendererBase;
+        if (pr)
+        {
+            pr.cssStyleName = _styleName;
+            if (pr is IItemTextPartRenderer)  {
+                with( IItemTextPartRenderer(pr)){
+                    labelField = _dataField;
+                    labelFunction = _labelFunction;
+                    textAlign = _textAlign;
+                }
+            }
+        }
+        return pr;
+    }
+
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/events/MobileGridHeaderEvent.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/events/MobileGridHeaderEvent.as b/frameworks/projects/experimental_mobile/src/spark/events/MobileGridHeaderEvent.as
new file mode 100644
index 0000000..06558b7
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/events/MobileGridHeaderEvent.as
@@ -0,0 +1,58 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.events
+{
+import flash.events.Event;
+
+/**
+ *  The MobileGridHeaderEvent class represents events that are dispatched when
+    the user clicks  on the header of a column in the DataGrid to sort it.
+ *
+ *  @see spark.components.MobileGrid
+ *
+ *  @langversion 3.0
+ *  @playerversion AIR 3.8
+ *  @productversion Flex 4.11
+ */
+
+//   Note: we didn't use neither mx:DataGridEven because it's in not available for mobile not GridSortEvent because it handles multiple sorting
+public class MobileGridHeaderEvent extends Event
+{
+
+    public static const SORT_CHANGE:String = "sortChange";
+
+    private var _columnIndex:int;
+
+    public function MobileGridHeaderEvent(type:String, pindex:int, bubbles:Boolean = false, cancelable:Boolean = false)
+    {
+        super(type, bubbles, cancelable);
+        this._columnIndex = pindex;
+    }
+
+    public function get columnIndex():int
+    {
+        return _columnIndex;
+    }
+
+    override public function clone():Event
+    {
+        return new MobileGridHeaderEvent(type, columnIndex, bubbles, cancelable);
+    }
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridHeaderButtonBarSkin.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridHeaderButtonBarSkin.as b/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridHeaderButtonBarSkin.as
new file mode 100644
index 0000000..5c21a0f
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridHeaderButtonBarSkin.as
@@ -0,0 +1,89 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins
+{
+import spark.components.ButtonBarButton;
+import spark.components.DataGroup;
+import spark.layouts.HorizontalLayout;
+import spark.layouts.VerticalAlign;
+import spark.skins.mobile.ButtonBarSkin;
+import spark.skins.mobile.supportClasses.ButtonBarButtonClassFactory;
+
+public class MobileGridHeaderButtonBarSkin extends ButtonBarSkin
+{
+
+    public function MobileGridHeaderButtonBarSkin()
+    {
+        super();
+    }
+
+    override protected function createChildren():void
+    {
+        if (!firstButton)
+        {
+            firstButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+            ButtonBarButtonClassFactory(firstButton).skinClass = MobileGridHeaderFirstButtonSkin;
+        }
+
+        if (!lastButton)
+        {
+            lastButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+            ButtonBarButtonClassFactory(lastButton).skinClass = MobileGridHeaderButtonSkin;
+        }
+
+        if (!middleButton)
+        {
+            middleButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+            ButtonBarButtonClassFactory(middleButton).skinClass = MobileGridHeaderButtonSkin;
+        }
+
+        // create the data group to house the buttons
+        if (!dataGroup)
+        {
+            dataGroup = new DataGroup();
+            var hLayout:HorizontalLayout = new HorizontalLayout();
+            hLayout.gap = 0;
+            hLayout.verticalAlign = VerticalAlign.CONTENT_JUSTIFY;
+            hLayout.useVirtualLayout = false;
+
+            dataGroup.layout = hLayout;
+            addChild(dataGroup);
+        }
+    }
+
+    /**
+     *  @private
+     */
+    override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+    {
+        super.drawBackground(unscaledWidth, unscaledHeight);
+
+        // backgroundAlpha style is not supported by ButtonBar
+        // TabbedViewNavigatorSkin sets a hard-coded value to support
+        // overlayControls
+        var backgroundAlphaValue:* = getStyle("backgroundAlpha");
+        var backgroundAlpha:Number = (backgroundAlphaValue === undefined)
+                ? 1 : getStyle("backgroundAlpha");
+
+        graphics.beginFill(getStyle("chromeColor"), backgroundAlpha);
+        graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
+        graphics.endFill();
+    }
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridHeaderButtonSkin.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridHeaderButtonSkin.as b/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridHeaderButtonSkin.as
new file mode 100644
index 0000000..425847f
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridHeaderButtonSkin.as
@@ -0,0 +1,43 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins
+{
+
+import spark.skins.mobile.ButtonBarMiddleButtonSkin;
+import spark.skins.mobile.assets.MobileGridHeaderButton_down;
+import spark.skins.mobile.assets.MobileGridHeaderButton_up;
+
+public class MobileGridHeaderButtonSkin extends ButtonBarMiddleButtonSkin
+{
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+    public function MobileGridHeaderButtonSkin()
+    {
+        super();
+
+        upBorderSkin = MobileGridHeaderButton_up;
+        downBorderSkin = MobileGridHeaderButton_down;
+    }
+
+
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridHeaderFirstButtonSkin.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridHeaderFirstButtonSkin.as b/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridHeaderFirstButtonSkin.as
new file mode 100644
index 0000000..d3240c2
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridHeaderFirstButtonSkin.as
@@ -0,0 +1,35 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins
+{
+import spark.skins.mobile.assets.MobileGridHeaderFirstButton_down;
+import spark.skins.mobile.assets.MobileGridHeaderFirstButton_up;
+
+public class MobileGridHeaderFirstButtonSkin extends MobileGridHeaderButtonSkin
+{
+
+    public function MobileGridHeaderFirstButtonSkin()
+    {
+        super();
+        upBorderSkin = MobileGridHeaderFirstButton_up;
+        downBorderSkin = MobileGridHeaderFirstButton_down;
+    }
+
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridSkin.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridSkin.as b/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridSkin.as
new file mode 100644
index 0000000..20c46a0
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/skins/MobileGridSkin.as
@@ -0,0 +1,178 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins
+{
+import flash.display.BlendMode;
+
+import mx.core.BitmapAsset;
+import mx.core.ClassFactory;
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.components.DataGroup;
+import spark.components.LabelItemRenderer;
+import spark.components.MobileGrid;
+import spark.components.Scroller;
+import spark.components.supportClasses.MobileGridHeader;
+import spark.layouts.HorizontalAlign;
+import spark.layouts.VerticalLayout;
+import spark.skins.mobile.supportClasses.MobileSkin;
+import spark.utils.MultiDPIBitmapSource;
+import spark.utils.MultiDPIBitmapSourceExt;
+
+use namespace mx_internal;
+
+public class MobileGridSkin extends MobileSkin
+{
+
+    [Embed(source="../../../assets/images/mobile320/dg_header_shadow.png")]
+    private const headerShadowCls320:Class;
+
+    [Embed(source="../../../assets/images/mobile160/dg_header_shadow.png")]
+    private const headerShadowCls160:Class;
+
+    public var hostComponent:MobileGrid;
+    // skin parts
+    public var headerGroup:MobileGridHeader;
+    public var scroller:Scroller;
+    public var dataGroup:DataGroup;
+    private var headerShadowCls:Class;
+    private var headerShadow:BitmapAsset;
+
+
+    public function MobileGridSkin()
+    {
+        super();
+        minWidth = 112;
+        blendMode = BlendMode.NORMAL;
+        switch (applicationDPI)
+        {
+            case DPIClassification.DPI_320:
+            case DPIClassification.DPI_480:
+                minWidth = 200;
+                break;
+            case DPIClassification.DPI_160:
+            case DPIClassification.DPI_240:
+            default:
+                minWidth = 100;
+                break;
+        }
+        var headerShadowSrc:MultiDPIBitmapSource = new MultiDPIBitmapSourceExt();
+        headerShadowSrc.source320dpi = headerShadowCls320;
+        headerShadowSrc.source160dpi = headerShadowCls160;
+        headerShadowCls = Class(headerShadowSrc.getSource(NaN));
+    }
+
+    override protected function commitCurrentState():void
+    {
+        super.commitCurrentState();
+        alpha = currentState.indexOf("disabled") == -1 ? 1 : 0.5;
+    }
+
+
+    /**
+     *  @private
+     */
+    override protected function createChildren():void
+    {
+
+        if (!dataGroup)
+        {
+            // Create data group layout
+            var layout:VerticalLayout = new VerticalLayout();
+            layout.requestedMinRowCount = 5;
+            layout.horizontalAlign = HorizontalAlign.JUSTIFY;
+            layout.gap = 0;
+
+            // Create data group
+            dataGroup = new DataGroup();
+            dataGroup.layout = layout;
+            dataGroup.itemRenderer = new ClassFactory(LabelItemRenderer);
+        }
+        if (!scroller)
+        {
+            // Create scroller
+            scroller = new Scroller();
+            scroller.minViewportInset = 1;
+            scroller.hasFocusableChildren = false;
+            scroller.ensureElementIsVisibleForSoftKeyboard = false;
+            addChild(scroller);
+        }
+
+        // Associate scroller with data group
+        if (!scroller.viewport)
+        {
+            scroller.viewport = dataGroup;
+        }
+
+        headerShadow = new headerShadowCls();
+        addChild(headerShadow);
+
+        /* add after, for the drop shadow*/
+
+        headerGroup = new MobileGridHeader();
+        headerGroup.id = "hg";
+        addChild(headerGroup);
+    }
+
+    /**
+     *  @private
+     */
+    override protected function measure():void
+    {
+        measuredWidth = scroller.getPreferredBoundsWidth();
+        measuredHeight = scroller.getPreferredBoundsHeight() + headerGroup.getPreferredBoundsHeight();
+    }
+
+    /**
+     *  @private
+     */
+    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+    {
+        super.updateDisplayList(unscaledWidth, unscaledHeight);
+
+        var borderWidth:int = getStyle("borderVisible") ? 1 : 0;
+        var headerHeight:Number = headerGroup.getPreferredBoundsHeight();
+
+        // Background
+        graphics.beginFill(getStyle("contentBackgroundColor"), getStyle("contentBackgroundAlpha"));
+        graphics.drawRect(borderWidth, borderWidth, unscaledWidth - 2 * borderWidth, unscaledHeight - 2 * borderWidth);
+        graphics.endFill();
+
+        // Border
+        if (getStyle("borderVisible"))
+        {
+            graphics.lineStyle(1, getStyle("borderColor"), getStyle("borderAlpha"), true);
+            graphics.drawRect(0, 0, unscaledWidth - 1, unscaledHeight - 1);
+        }
+
+        // Header
+        setElementSize(headerGroup, unscaledWidth, headerHeight);
+        setElementPosition(headerGroup, 0, 0);
+
+        //Shadow
+        setElementSize(headerShadow, unscaledWidth, headerShadow.height);
+        setElementPosition(headerShadow, 0, headerHeight);
+        // Scroller
+        scroller.minViewportInset = borderWidth;
+        setElementSize(scroller, unscaledWidth, unscaledHeight);
+        setElementPosition(scroller, 0, headerHeight);
+    }
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderButton_down.fxg
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderButton_down.fxg b/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderButton_down.fxg
new file mode 100644
index 0000000..37be5cc
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderButton_down.fxg
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+-->
+<Graphic version="2.0" xmlns="http://ns.adobe.com/fxg/2008"
+         scaleGridLeft="5" scaleGridRight="49" scaleGridTop="10" scaleGridBottom="54">
+
+    <Rect width="50" height="64">
+        <fill>
+            <LinearGradient x="0" y="0" scaleX="64" rotation="90">
+                <GradientEntry color="#B0B0B0" ratio="0"/>
+                <GradientEntry color="#5b5b5b" ratio="0.05"/>
+                <GradientEntry color="#505050" ratio="0.75"/>
+                <GradientEntry color="#404040" ratio="1"/>
+            </LinearGradient>
+        </fill>
+    </Rect>
+    <Rect width="1" height="40" x="0" y="12">
+        <fill>
+            <SolidColor color="#666666" alpha="0.5"/>
+        </fill>
+    </Rect>
+    <Rect width="1" height="40" x="1" y="12">
+        <fill>
+            <SolidColor color="#cccccc" alpha="0.5"/>
+        </fill>
+    </Rect>
+
+</Graphic>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderButton_up.fxg
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderButton_up.fxg b/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderButton_up.fxg
new file mode 100644
index 0000000..6130486
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderButton_up.fxg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+-->
+<Graphic version="2.0" xmlns="http://ns.adobe.com/fxg/2008"
+         scaleGridLeft="5" scaleGridRight="49" scaleGridTop="10" scaleGridBottom="54">
+    <Rect width="50" height="64">
+        <fill>
+            <LinearGradient x="0" y="0" scaleX="64" rotation="90">
+                <GradientEntry color="#999999" ratio="0"/>
+                <GradientEntry color="#404040" ratio="0.05"/>
+                <GradientEntry color="#303030" ratio="0.75"/>
+                <GradientEntry color="#202020" ratio="1"/>
+            </LinearGradient>
+        </fill>
+    </Rect>
+    <Rect width="1" height="40" x="0" y="12">
+        <fill>
+            <SolidColor color="#666666" alpha="0.5"/>
+        </fill>
+    </Rect>
+    <Rect width="1" height="40" x="1" y="12">
+        <fill>
+            <SolidColor color="#cccccc" alpha="0.5"/>
+        </fill>
+    </Rect>
+</Graphic>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderFirstButton_down.fxg
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderFirstButton_down.fxg b/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderFirstButton_down.fxg
new file mode 100644
index 0000000..1540367
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderFirstButton_down.fxg
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+-->
+<Graphic version="2.0" xmlns="http://ns.adobe.com/fxg/2008">
+    <Rect width="160" height="64">
+        <fill>
+            <LinearGradient x="0" y="0" scaleX="64" rotation="90">
+                <GradientEntry color="#B0B0B0" ratio="0"/>
+                <GradientEntry color="#5b5b5b" ratio="0.05"/>
+                <GradientEntry color="#505050" ratio="0.75"/>
+                <GradientEntry color="#404040" ratio="1"/>
+            </LinearGradient>
+        </fill>
+    </Rect>
+
+</Graphic>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderFirstButton_up.fxg
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderFirstButton_up.fxg b/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderFirstButton_up.fxg
new file mode 100644
index 0000000..d898d78
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/skins/mobile/assets/MobileGridHeaderFirstButton_up.fxg
@@ -0,0 +1,32 @@
+<Graphic version="2.0" xmlns="http://ns.adobe.com/fxg/2008">
+    <!--
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+-->
+    <Rect width="100" height="64">
+        <fill>
+            <LinearGradient x="0" y="0" scaleX="64" rotation="90">
+                <GradientEntry color="#999999" ratio="0"/>
+                <GradientEntry color="#404040" ratio="0.05"/>
+                <GradientEntry color="#303030" ratio="0.75"/>
+                <GradientEntry color="#202020" ratio="1"/>
+            </LinearGradient>
+        </fill>
+    </Rect>
+</Graphic>

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/utils/DensityUtil2.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/utils/DensityUtil2.as b/frameworks/projects/experimental_mobile/src/spark/utils/DensityUtil2.as
new file mode 100644
index 0000000..8c76e73
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/utils/DensityUtil2.as
@@ -0,0 +1,88 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+
+import mx.core.FlexGlobals;
+import mx.core.mx_internal;
+import mx.managers.SystemManager;
+
+import spark.components.Application;
+
+public class DensityUtil2
+{
+
+    use namespace mx_internal;
+
+    private static var _setApplicationDPI:Number = 0;
+
+    /**  Calculates a scale factor to be used when element authored for  <code>sourceDPI</code>
+     *   two algorithms: <br/>
+     *   Application.applicationDPI has been set, which means scaling factor  occurs already, so additional scaling is required, return 1
+     *  Application.applicationDPI has not been set, then return runTimeDPI / sourceDPI
+     *  examples:
+     *  runtimeDPI = 320 and sourceDPI = 160 and  applicationDPI not set  (ie=320) => 2
+     *  runtimeDPI = 160 and sourceDPI = 160 and applicationDPI not set (ie=160)  => 1
+     *  runtimeDPI = 160 and sourceDPI = 160 and applicationDPI = 160 => 1
+     *  runtimeDPI = 320 and sourceDPI = 160 and applicationDPI = 160 => 1 (scaling occurs)
+     * @param sourceDPI
+     * @return  scale factor
+     */
+
+    public static function getPostDPIScale(sourceDPI:Number):Number
+    {
+
+        var appDPI:Number = getSetApplicationDPI();
+        if (isNaN(appDPI))
+        {
+            // was not set,
+            var runDPI:Number = FlexGlobals.topLevelApplication.runtimeDPI;
+            return runDPI / sourceDPI;
+        }
+        else
+            return 1.0; //  already scaled
+    }
+
+
+    public static function dpiScale(value:Number, sourceDPI:Number):Number
+    {
+        var appDPI:Number = getSetApplicationDPI();
+        if (isNaN(appDPI))
+        {
+            var runDPI:Number = FlexGlobals.topLevelApplication.runtimeDPI;
+            return value * runDPI / sourceDPI;
+        }
+        else
+            return value; //  already scaled
+
+    }
+
+    private static function getSetApplicationDPI():Number
+    {
+        if (_setApplicationDPI == 0)
+        {
+            var application:Application = FlexGlobals.topLevelApplication as Application;
+            var sm:SystemManager = application ? application.systemManager as SystemManager : null;
+            _setApplicationDPI = sm ? sm.info()["applicationDPI"] : NaN;
+        }
+        return _setApplicationDPI;
+    }
+
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/utils/MultiDPIBitmapSourceExt.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/utils/MultiDPIBitmapSourceExt.as b/frameworks/projects/experimental_mobile/src/spark/utils/MultiDPIBitmapSourceExt.as
new file mode 100644
index 0000000..eb3ac03
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/utils/MultiDPIBitmapSourceExt.as
@@ -0,0 +1,44 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+import mx.core.FlexGlobals;
+import mx.utils.DensityUtil;
+
+public class MultiDPIBitmapSourceExt extends MultiDPIBitmapSource
+{
+
+
+    override public function getSource(desiredDPI:Number):Object
+    {
+        if (isNaN(desiredDPI))
+        {
+            var app:Object = FlexGlobals.topLevelApplication;
+            var dpi:Number;
+            if ("runtimeDPI" in app)
+                dpi = app["runtimeDPI"];
+            else
+                dpi = DensityUtil.getRuntimeDPI();
+            return getSource(dpi);
+        }
+        else
+            return super.getSource(desiredDPI);
+    }
+}
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b78de5c0/frameworks/projects/experimental_mobile/src/spark/utils/UIComponentUtils.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/experimental_mobile/src/spark/utils/UIComponentUtils.as b/frameworks/projects/experimental_mobile/src/spark/utils/UIComponentUtils.as
new file mode 100644
index 0000000..0ecf82c
--- /dev/null
+++ b/frameworks/projects/experimental_mobile/src/spark/utils/UIComponentUtils.as
@@ -0,0 +1,163 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+import mx.collections.IList;
+import mx.core.IFlexDisplayObject;
+import mx.core.ILayoutElement;
+import mx.core.UIComponent;
+
+import spark.components.IItemRendererOwner;
+
+public class UIComponentUtils
+{
+
+    /* fast function based on char length and not on pixel length*/
+    public static function computeLongestItem(listComponent:IItemRendererOwner, dataProvider:IList, max:int = 10):Object
+    {
+        if (!dataProvider)
+        {
+            return null;
+        }
+        max = Math.min(max, dataProvider.length);
+        var maxLength:int = 0;
+        var longestItem:Object;
+        var item:Object;
+        var itemStringLength:int;
+        for (var i:int = 0; i < max; i++)
+        {
+            item = dataProvider.getItemAt(i);
+            itemStringLength = listComponent.itemToLabel(item).length;
+            if (itemStringLength >= maxLength)
+            {
+                maxLength = itemStringLength;
+                longestItem = item;
+            }
+        }
+        return longestItem;
+    }
+
+    public static function itemToLabel(item:Object, labelField:String, labelFunction:Function, nullLabel:String = '-'):String
+    {
+        if (labelFunction != null)
+        {
+            return labelFunction(item);
+        }
+        else if (item == null)
+        {
+            return nullLabel;
+        }
+        else
+        {
+            return   item[labelField];
+        }
+    }
+
+    public static function clearBoundsSize(comp:UIComponent):void
+    {
+        comp.explicitWidth = NaN; // was set before
+        comp.explicitHeight = NaN;
+        comp.setLayoutBoundsSize(NaN, NaN);
+    }
+
+    public static function setElementSize(element:Object, width:Number, height:Number):void
+    {
+        if (element is ILayoutElement)
+        {
+            ILayoutElement(element).setLayoutBoundsSize(width, height, false);
+        }
+        else if (element is IFlexDisplayObject)
+        {
+            IFlexDisplayObject(element).setActualSize(width, height);
+        }
+        else
+        {
+            element.width = width;
+            element.height = height;
+        }
+    }
+
+    public static function setElementPosition(element:Object, x:Number, y:Number):void
+    {
+        if (element is ILayoutElement)
+        {
+            ILayoutElement(element).setLayoutBoundsPosition(x, y, false);
+        }
+        else if (element is IFlexDisplayObject)
+        {
+            IFlexDisplayObject(element).move(x, y);
+        }
+        else
+        {
+            element.x = x;
+            element.y = y;
+        }
+    }
+
+    public static function getElementPreferredWidth(element:Object):Number
+    {
+        var result:Number;
+
+        if (element is ILayoutElement)
+        {
+            result = ILayoutElement(element).getPreferredBoundsWidth();
+        }
+        else if (element is IFlexDisplayObject)
+        {
+            result = IFlexDisplayObject(element).measuredWidth;
+        }
+        else
+        {
+            result = element.width;
+        }
+        return Math.round(result);
+    }
+
+    public static function getElementPreferredHeight(element:Object):Number
+    {
+        var result:Number;
+
+        if (element is ILayoutElement)
+        {
+            result = ILayoutElement(element).getPreferredBoundsHeight();
+        }
+        else if (element is IFlexDisplayObject)
+        {
+            result = IFlexDisplayObject(element).measuredHeight;
+        }
+        else
+        {
+            result = element.height;
+        }
+        return Math.ceil(result);
+    }
+
+    public static function offsetForCenter(inLength:Number, outLength:Number):Number
+    {
+        return ( outLength - inLength) / 2;
+    }
+
+    public static function setElementPositionTopRight(component:Object, container:Object, paddingTop:Number = 0, paddingRight:Number = 0):void
+    {
+        var right:Number = getElementPreferredWidth(container) - getElementPreferredWidth(component) - paddingRight;
+        setElementPosition(component, paddingTop, right);
+    }
+
+}
+}