You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by ah...@apache.org on 2018/12/03 07:19:18 UTC
[royale-asjs] 06/08: virtual item renderers for MXRoyale
This is an automated email from the ASF dual-hosted git repository.
aharui pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
commit 27ac6d36901ab6686f88df13376b3e6be5882926
Author: Alex Harui <ah...@apache.org>
AuthorDate: Sun Dec 2 22:25:39 2018 -0800
virtual item renderers for MXRoyale
---
.../MXRoyale/src/main/royale/MXRoyaleClasses.as | 1 +
...ataItemRendererFactoryForICollectionViewData.as | 190 ++++++++++
.../listClasses/VirtualListVerticalLayout.as | 416 +++++++++++++++++++++
3 files changed, 607 insertions(+)
diff --git a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
index f6796d2..db25050 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
@@ -71,6 +71,7 @@ internal class MXRoyaleClasses
import mx.controls.treeClasses.ITreeDataDescriptor; ITreeDataDescriptor;
import mx.controls.treeClasses.TreeListData; TreeListData;
import mx.controls.listClasses.DataItemRendererFactoryForICollectionViewData; DataItemRendererFactoryForICollectionViewData;
+ import mx.controls.listClasses.VirtualDataItemRendererFactoryForICollectionViewData; VirtualDataItemRendererFactoryForICollectionViewData;
import mx.controls.treeClasses.DataItemRendererFactoryForICollectionViewHierarchicalData; DataItemRendererFactoryForICollectionViewHierarchicalData;
import mx.charts.chartClasses.RenderData; RenderData;
import mx.effects.EffectInstance; EffectInstance;
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/listClasses/VirtualDataItemRendererFactoryForICollectionViewData.as b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/listClasses/VirtualDataItemRendererFactoryForICollectionViewData.as
new file mode 100644
index 0000000..20a5a5f
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/listClasses/VirtualDataItemRendererFactoryForICollectionViewData.as
@@ -0,0 +1,190 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.controls.listClasses
+{
+ import mx.collections.CursorBookmark;
+ import mx.collections.ICollectionView;
+ import mx.collections.IViewCursor;
+
+ import org.apache.royale.core.IBead;
+ import org.apache.royale.core.IBeadModel;
+ import org.apache.royale.core.IDataProviderItemRendererMapper;
+ import org.apache.royale.core.IDataProviderVirtualItemRendererMapper;
+ import org.apache.royale.core.IDataProviderModel;
+ import org.apache.royale.core.IItemRendererClassFactory;
+ import org.apache.royale.core.IItemRendererParent;
+ import org.apache.royale.core.IListPresentationModel;
+ import org.apache.royale.core.ISelectableItemRenderer;
+ import org.apache.royale.core.IStrand;
+ import org.apache.royale.core.IStrandWithModelView;
+ import org.apache.royale.core.IUIBase;
+ import org.apache.royale.core.SimpleCSSStyles;
+ import org.apache.royale.core.UIBase;
+ import org.apache.royale.core.ValuesManager;
+ import org.apache.royale.events.CollectionEvent;
+ import org.apache.royale.events.Event;
+ import org.apache.royale.events.EventDispatcher;
+ import org.apache.royale.events.IEventDispatcher;
+ import org.apache.royale.events.ItemRendererEvent;
+ import org.apache.royale.html.List;
+ import org.apache.royale.html.beads.IListView;
+ import org.apache.royale.html.beads.DataItemRendererFactoryForCollectionView;
+ import org.apache.royale.html.supportClasses.DataItemRenderer;
+
+ [Event(name="itemRendererCreated",type="org.apache.royale.events.ItemRendererEvent")]
+
+ /**
+ * The DataItemRendererFactoryForHierarchicalData class reads a
+ * HierarchicalData object and creates an item renderer for every
+ * item in the array. Other implementations of
+ * IDataProviderItemRendererMapper map different data
+ * structures or manage a virtual set of renderers.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public class VirtualDataItemRendererFactoryForICollectionViewData extends DataItemRendererFactoryForICollectionViewData
+ implements IDataProviderVirtualItemRendererMapper
+ {
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public function VirtualDataItemRendererFactoryForICollectionViewData()
+ {
+ super();
+ }
+
+ protected var dataProviderModel:IDataProviderModel;
+
+ protected var dataField:String;
+
+ /**
+ * Free an item renderer for a given index.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.0
+ * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
+ * @royaleignorecoercion org.apache.royale.html.beads.IListView
+ */
+ public function freeItemRendererForIndex(index:int):void
+ {
+ var ir:ISelectableItemRenderer = rendererMap[index];
+ var view:IListView = (_strand as IStrandWithModelView).view as IListView;
+ var dataGroup:IItemRendererParent = view.dataGroup;
+ dataGroup.removeItemRenderer(ir);
+ delete rendererMap[index];
+ }
+
+ private var rendererMap:Object = {};
+
+ private var currentIndex:int = 0;
+
+ private var cursor:IViewCursor;
+
+ /**
+ * The org.apache.royale.core.IItemRendererParent that will
+ * parent the item renderers.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
+ * @royaleignorecoercion org.apache.royale.html.beads.IListView
+ */
+ override protected function dataProviderChangeHandler(event:Event):void
+ {
+ // do not call super as it will be non-virtual and renderer every item in the dp
+
+ var dp:Array = dataProviderModel.dataProvider as Array;
+ if (!dp)
+ return;
+
+ var view:IListView = (_strand as IStrandWithModelView).view as IListView;
+ var dataGroup:IItemRendererParent = view.dataGroup;
+
+ dataGroup.removeAllItemRenderers();
+ }
+
+
+ /**
+ * Get an item renderer for a given index.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.9.0
+ * @royaleignorecoercion org.apache.royale.core.IStrandWithModelView
+ * @royaleignorecoercion org.apache.royale.html.beads.IListView
+ */
+ public function getItemRendererForIndex(index:int, elementIndex:int):ISelectableItemRenderer
+ {
+ var ir:ISelectableItemRenderer = rendererMap[index];
+ if (ir) return ir;
+
+ if (!cursor)
+ {
+ var dp:ICollectionView = dataProviderModel.dataProvider as ICollectionView;
+ cursor = dp.createCursor();
+ }
+
+ ir = itemRendererFactory.createItemRenderer(dataGroup) as ISelectableItemRenderer;
+ var dataItemRenderer:DataItemRenderer = ir as DataItemRenderer;
+
+ var view:IListView = (_strand as IStrandWithModelView).view as IListView;
+ var dataGroup:IItemRendererParent = view.dataGroup;
+ dataGroup.addItemRendererAt(ir, elementIndex);
+ ir.index = index;
+ ir.labelField = labelField;
+ if (dataItemRenderer)
+ {
+ dataItemRenderer.dataField = dataField;
+ }
+ rendererMap[index] = ir;
+
+ var presentationModel:IListPresentationModel = _strand.getBeadByType(IListPresentationModel) as IListPresentationModel;
+ if (presentationModel) {
+ var style:SimpleCSSStyles = new SimpleCSSStyles();
+ style.marginBottom = presentationModel.separatorThickness;
+ UIBase(ir).style = style;
+ UIBase(ir).height = presentationModel.rowHeight;
+ UIBase(ir).percentWidth = 100;
+ }
+ var distance:int = index - currentIndex;
+ cursor.seek(CursorBookmark.CURRENT, distance);
+ currentIndex = index;
+ ir.data = cursor.current;
+
+ var newEvent:ItemRendererEvent = new ItemRendererEvent(ItemRendererEvent.CREATED);
+ newEvent.itemRenderer = ir;
+ dispatchEvent(newEvent);
+ return ir;
+ }
+
+ }
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/listClasses/VirtualListVerticalLayout.as b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/listClasses/VirtualListVerticalLayout.as
new file mode 100644
index 0000000..923b8b9
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/listClasses/VirtualListVerticalLayout.as
@@ -0,0 +1,416 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.royale.html.beads.layouts
+{
+ import org.apache.royale.core.IBeadLayout;
+ import org.apache.royale.core.IBeadModel;
+ import org.apache.royale.core.IBorderPaddingMarginValuesImpl;
+ import org.apache.royale.core.IDataProviderModel;
+ import org.apache.royale.core.IDataProviderVirtualItemRendererMapper;
+ import org.apache.royale.core.ILayoutChild;
+ import org.apache.royale.core.ILayoutHost;
+ import org.apache.royale.core.ILayoutParent;
+ import org.apache.royale.core.ILayoutView;
+ import org.apache.royale.core.IListPresentationModel;
+ import org.apache.royale.core.IParentIUIBase;
+ import org.apache.royale.core.IScrollingViewport;
+ import org.apache.royale.core.ISelectableItemRenderer;
+ import org.apache.royale.core.IStrand;
+ import org.apache.royale.core.IStrandWithPresentationModel;
+ import org.apache.royale.core.IUIBase;
+ import org.apache.royale.core.LayoutBase;
+ import org.apache.royale.core.ValuesManager;
+ import org.apache.royale.core.layout.EdgeData;
+ COMPILE::JS
+ {
+ import org.apache.royale.core.WrappedHTMLElement;
+ }
+ import org.apache.royale.events.Event;
+ import org.apache.royale.events.IEventDispatcher;
+ import org.apache.royale.geom.Rectangle;
+ import org.apache.royale.html.beads.VirtualDataContainerView;
+ import org.apache.royale.utils.CSSUtils;
+
+ COMPILE::SWF {
+ import org.apache.royale.geom.Size;
+ }
+
+ /**
+ * The VerticalLayout class is a simple layout
+ * bead. It takes the set of children and lays them out
+ * vertically in one column, separating them according to
+ * CSS layout rules for margin and horizontal-align styles.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public class VirtualListVerticalLayout extends LayoutBase implements IBeadLayout
+ {
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ * @royaleignorecoercion HTMLDivElement
+ */
+ public function VirtualListVerticalLayout()
+ {
+ super();
+ }
+
+ protected var dataProviderModel:IDataProviderModel;
+
+ override public function set strand(value:IStrand):void
+ {
+ super.strand = value;
+ dataProviderModel = host.getBeadByType(IDataProviderModel) as IDataProviderModel;
+ COMPILE::JS
+ {
+ host.element.addEventListener("scroll", scrollHandler);
+ }
+ }
+
+ COMPILE::JS
+ private var topSpacer:HTMLDivElement;
+
+ COMPILE::JS
+ private var bottomSpacer:HTMLDivElement;
+
+ private var visibleIndexes:Array = [];
+
+ private function scrollHandler(e:Event):void
+ {
+ layout();
+ }
+
+ private var inLayout:Boolean;
+
+ /**
+ * Layout children vertically
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ * @royaleignorecoercion Array
+ * @royaleignorecoercion org.apache.royale.core.ILayoutHost
+ * @royaleignorecoercion org.apache.royale.core.WrappedHTMLElement
+ * @royaleignorecoercion org.apache.royale.core.IListPresentationModel
+ * @royaleignorecoercion org.apache.royale.core.IStrandWithPresentationModel
+ */
+ override public function layout():Boolean
+ {
+ if (inLayout) return true;
+ inLayout = true;
+
+ COMPILE::SWF
+ {
+ // the strategy for virtualization in SWF is based on the
+ // fact that we can completely control the scrolling metrics
+ // instead of trying to rely on the browsers built-in scrolling.
+ // This code puts enough renderers on the screen and then dictates
+ // the scrolling metrics.
+ var contentView:ILayoutView = layoutView;
+
+ var maxWidth:Number = 0;
+ var maxHeight:Number = 0;
+ var dp:Array = dataProviderModel.dataProvider as Array;
+ if (!dp)
+ {
+ inLayout = false;
+ return true;
+ }
+ var presentationModel:IListPresentationModel = (host as IStrandWithPresentationModel).presentationModel as IListPresentationModel;
+ var hostWidthSizedToContent:Boolean = host.isWidthSizedToContent();
+ var hostHeightSizedToContent:Boolean = host.isHeightSizedToContent();
+ var hostWidth:Number = host.width;
+ var hostHeight:Number = host.height;
+
+ var data:Object;
+ var canAdjust:Boolean = false;
+
+ var paddingMetrics:EdgeData = (ValuesManager.valuesImpl as IBorderPaddingMarginValuesImpl).getPaddingMetrics(host);
+ var borderMetrics:EdgeData = (ValuesManager.valuesImpl as IBorderPaddingMarginValuesImpl).getBorderMetrics(host);
+
+ // adjust the host's usable size by the metrics. If hostSizedToContent, then the
+ // resulting adjusted value may be less than zero.
+ hostWidth -= paddingMetrics.left + paddingMetrics.right + borderMetrics.left + borderMetrics.right;
+ hostHeight -= paddingMetrics.top + paddingMetrics.bottom + borderMetrics.top + borderMetrics.bottom;
+
+ var xpos:Number = borderMetrics.left + paddingMetrics.left;
+ var ypos:Number = borderMetrics.top + paddingMetrics.top;
+
+ var viewport:IScrollingViewport = host.getBeadByType(IScrollingViewport) as IScrollingViewport;
+ viewport.addEventListener("verticalScrollPositionChanged", scrollHandler);
+ var viewportTop:Number = viewport.verticalScrollPosition;
+ var viewportHeight:Number = hostHeight;
+ var startIndex:int = Math.floor(viewportTop / presentationModel.rowHeight);
+ var factory:IDataProviderVirtualItemRendererMapper = host.getBeadByType(IDataProviderVirtualItemRendererMapper) as IDataProviderVirtualItemRendererMapper;
+ var endIndex:int = Math.ceil((viewportTop + viewportHeight) / presentationModel.rowHeight);
+ var freeIndex:int;
+ var firstIndex:int;
+ var lastIndex:int;
+
+ if (visibleIndexes.length)
+ {
+ if (startIndex < visibleIndexes[0])
+ {
+ // see if we can re-use any renderers
+ freeIndex = visibleIndexes.pop();
+ while (freeIndex >= endIndex)
+ {
+ factory.freeItemRendererForIndex(freeIndex);
+ if (visibleIndexes.length == 0)
+ break;
+ freeIndex = visibleIndexes.pop();
+ }
+ if (visibleIndexes.length)
+ endIndex = visibleIndexes[visibleIndexes.length - 1];
+ }
+ else if (startIndex > visibleIndexes[0])
+ {
+ // see if we can re-use any renderers
+ freeIndex = visibleIndexes.shift();
+ while (freeIndex < startIndex)
+ {
+ factory.freeItemRendererForIndex(freeIndex);
+ if (visibleIndexes.length == 0)
+ break;
+ freeIndex = visibleIndexes.shift();
+ }
+ }
+ else
+ {
+ // see if rows got added or removed because height changed
+ lastIndex = visibleIndexes[visibleIndexes.length - 1];
+ if (lastIndex > endIndex)
+ {
+ // see if we can re-use any renderers
+ freeIndex = visibleIndexes.pop();
+ while (freeIndex > endIndex)
+ {
+ factory.freeItemRendererForIndex(freeIndex);
+ if (visibleIndexes.length == 0)
+ break;
+ freeIndex = visibleIndexes.pop();
+ }
+ inLayout = false;
+ return true; // we should be all done if we shrunk
+ }
+ }
+ firstIndex = visibleIndexes[0];
+ lastIndex = visibleIndexes[visibleIndexes.length - 1];
+ }
+ else
+ {
+ firstIndex = dp.length;
+ lastIndex = 0;
+ }
+ for (var i:int = startIndex; i < endIndex; i++)
+ {
+ var ir:ISelectableItemRenderer;
+ if (i < firstIndex)
+ {
+ ir = factory.getItemRendererForIndex(i, i - startIndex);
+ sizeAndPositionRenderer(ir, xpos, ypos + (presentationModel.rowHeight * i), hostWidth, hostHeight);
+ visibleIndexes.push(i);
+ }
+ else if (i > lastIndex)
+ {
+ ir = factory.getItemRendererForIndex(i, i - startIndex);
+ sizeAndPositionRenderer(ir, xpos, ypos + (presentationModel.rowHeight * i), hostWidth, hostHeight);
+ visibleIndexes.push(i);
+ }
+ }
+ visibleIndexes = visibleIndexes.sort(numberSort);
+
+ var view:VirtualDataContainerView = host.getBeadByType(VirtualDataContainerView) as VirtualDataContainerView;
+ view.lastContentSize = new Size(hostWidth, dp.length * presentationModel.rowHeight);
+
+ inLayout = false;
+ return true;
+ }
+ COMPILE::JS
+ {
+ // the strategy for virtualization in JS is to leverage the built-in scrollbars
+ // by creating a topSpacer and bottomSpacer that take up the area that is offscreen
+ // so the scrollbars have the right metrics, then create enough renderers to
+ // show in the visible area. This code does not recycle renderers, but the
+ // factory can. This code does try to keep renderers on the DOM that aren't
+ // going off-screen
+ var contentView:ILayoutView = layoutView;
+ var dp:Array = dataProviderModel.dataProvider as Array;
+ if (!dp)
+ {
+ inLayout = false;
+ return true;
+ }
+ var presentationModel:IListPresentationModel = (host as IStrandWithPresentationModel).presentationModel as IListPresentationModel;
+ var totalHeight:Number = presentationModel.rowHeight * dp.length;
+ var viewportTop:Number = Math.max(contentView.element.scrollTop, 0);
+ var viewportHeight:Number = contentView.element.clientHeight;
+ var startIndex:int = Math.floor(viewportTop / presentationModel.rowHeight);
+ var factory:IDataProviderVirtualItemRendererMapper = host.getBeadByType(IDataProviderVirtualItemRendererMapper) as IDataProviderVirtualItemRendererMapper;
+ var endIndex:int = Math.ceil((viewportTop + viewportHeight) / presentationModel.rowHeight);
+ var freeIndex:int;
+ var firstIndex:int;
+ var lastIndex:int;
+ if (!topSpacer)
+ {
+ topSpacer = document.createElement("div") as HTMLDivElement;
+ contentView.element.appendChild(topSpacer);
+ }
+ topSpacer.style.height = (startIndex * presentationModel.rowHeight).toString() + "px";
+ if (visibleIndexes.length)
+ {
+ if (startIndex < visibleIndexes[0])
+ {
+ // see if we can re-use any renderers
+ freeIndex = visibleIndexes.pop();
+ while (freeIndex >= endIndex)
+ {
+ factory.freeItemRendererForIndex(freeIndex);
+ if (visibleIndexes.length == 0)
+ break;
+ freeIndex = visibleIndexes.pop();
+ }
+ if (visibleIndexes.length)
+ endIndex = visibleIndexes[visibleIndexes.length - 1];
+ }
+ else if (startIndex > visibleIndexes[0])
+ {
+ // see if we can re-use any renderers
+ freeIndex = visibleIndexes.shift();
+ while (freeIndex < startIndex)
+ {
+ factory.freeItemRendererForIndex(freeIndex);
+ if (visibleIndexes.length == 0)
+ break;
+ freeIndex = visibleIndexes.shift();
+ }
+ }
+ else
+ {
+ // see if rows got added or removed because height changed
+ lastIndex = visibleIndexes[visibleIndexes.length - 1];
+ if (lastIndex > endIndex)
+ {
+ // see if we can re-use any renderers
+ freeIndex = visibleIndexes.pop();
+ while (freeIndex > endIndex)
+ {
+ factory.freeItemRendererForIndex(freeIndex);
+ if (visibleIndexes.length == 0)
+ break;
+ freeIndex = visibleIndexes.pop();
+ }
+ inLayout = false;
+ return true; // we should be all done if we shrunk
+ }
+ }
+ firstIndex = visibleIndexes[0];
+ lastIndex = visibleIndexes[visibleIndexes.length - 1];
+ }
+ else
+ {
+ firstIndex = dp.length;
+ lastIndex = 0;
+ }
+ for (var i:int = startIndex; i < endIndex; i++)
+ {
+ var ir:ISelectableItemRenderer;
+ if (i < firstIndex)
+ {
+ ir = factory.getItemRendererForIndex(i, i - startIndex + 1);
+ ir.element.style.display = "block";
+ visibleIndexes.push(i);
+ }
+ else if (i > lastIndex)
+ {
+ ir = factory.getItemRendererForIndex(i, i - startIndex + 1);
+ ir.element.style.display = "block";
+ visibleIndexes.push(i);
+ }
+ }
+ visibleIndexes = visibleIndexes.sort(numberSort);
+ if (!bottomSpacer)
+ {
+ bottomSpacer = document.createElement("div") as HTMLDivElement;
+ contentView.element.appendChild(bottomSpacer);
+ }
+ bottomSpacer.style.height = ((dp.length - endIndex) * presentationModel.rowHeight).toString() + "px";
+ inLayout = false;
+ return true;
+ }
+ }
+
+ public function numberSort(a:int, b:int):int
+ {
+ return a - b;
+ }
+
+ COMPILE::SWF
+ private function sizeAndPositionRenderer(ir:ISelectableItemRenderer, xpos:Number, ypos:Number, hostWidth:Number, hostHeight:Number):void
+ {
+ var ilc:ILayoutChild;
+ var positions:Object = childPositions(ir);
+ var margins:Object = childMargins(ir, hostWidth, hostHeight);
+
+ ilc = ir as ILayoutChild;
+ var child:IUIBase = ir as IUIBase;
+
+ ypos += margins.top;
+
+ var childXpos:Number = xpos + margins.left; // default x position
+
+ var childWidth:Number = child.width;
+ if (ilc != null && !isNaN(ilc.percentWidth)) {
+ childWidth = hostWidth * ilc.percentWidth/100.0;
+ ilc.setWidth(childWidth);
+ }
+ else if (ilc.isWidthSizedToContent() && !margins.auto)
+ {
+ childWidth = hostWidth;
+ ilc.setWidth(childWidth);
+ }
+ if (margins.auto)
+ childXpos = (hostWidth - childWidth) / 2;
+
+ if (ilc) {
+ ilc.setX(childXpos);
+ ilc.setY(ypos);
+
+ if (!isNaN(ilc.percentHeight)) {
+ var newHeight:Number = hostHeight * ilc.percentHeight / 100;
+ ilc.setHeight(newHeight);
+ }
+
+ } else {
+ child.x = childXpos;
+ child.y = ypos;
+ }
+
+ ypos += child.height + margins.bottom;
+ }
+ }
+}