You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by pi...@apache.org on 2019/09/10 04:49:59 UTC
[royale-asjs] 02/04: virtual layout in ADG. Should fix #468
This is an automated email from the ASF dual-hosted git repository.
piotrz pushed a commit to branch release/0.9.6
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
commit 070f3c48991a79cb0494548f05250b8b87849c9e
Author: Alex Harui <ah...@apache.org>
AuthorDate: Thu Sep 5 10:35:09 2019 -0700
virtual layout in ADG. Should fix #468
(cherry picked from commit 8ab1d813ee2f72bab957f9485e56ad89dcf6e1ab)
---
.../MXRoyale/src/main/resources/defaults.css | 9 +-
.../MXRoyale/src/main/royale/MXRoyaleClasses.as | 3 +
.../AdvancedDataGridListArea.as | 72 ++++
...actoryForICollectionViewAdvancedDataGridData.as | 106 ++++--
.../beads/layouts/AdvancedDataGridLayout.as | 145 ++++++++
.../AdvancedDataGridVirtualListVerticalLayout.as | 374 +++++++++++++++++++++
6 files changed, 683 insertions(+), 26 deletions(-)
diff --git a/frameworks/projects/MXRoyale/src/main/resources/defaults.css b/frameworks/projects/MXRoyale/src/main/resources/defaults.css
index f11aae0..b66359c 100644
--- a/frameworks/projects/MXRoyale/src/main/resources/defaults.css
+++ b/frameworks/projects/MXRoyale/src/main/resources/defaults.css
@@ -81,9 +81,12 @@ AdvancedDataGrid
IDataGridPresentationModel: ClassReference("org.apache.royale.html.beads.models.DataGridPresentationModel");
IBeadView: ClassReference("mx.controls.beads.AdvancedDataGridView");
IBeadModel: ClassReference("mx.controls.beads.models.DataGridICollectionViewModel");
- IBeadLayout: ClassReference("mx.controls.beads.layouts.DataGridLayout");
+ IBeadLayout: ClassReference("mx.controls.beads.layouts.AdvancedDataGridLayout");
IDataProviderNotifier: ClassReference("mx.controls.beads.DataProviderChangeNotifier");
columnClass: ClassReference("mx.controls.advancedDataGridClasses.AdvancedDataGridColumnList");
+ columnContainerClass: ClassReference("org.apache.royale.html.DataGridButtonBar");
+ columnLayoutClass: ClassReference("org.apache.royale.html.beads.layouts.ButtonBarLayout");
+ listAreaClass: ClassReference("mx.controls.advancedDataGridClasses.AdvancedDataGridListArea");
background-color: #FFFFFF;
border: 1px solid #222222;
@@ -94,9 +97,9 @@ AdvancedDataGrid
adg|AdvancedDataGridColumnList {
IBeadModel: ClassReference("mx.controls.beads.models.SingleSelectionICollectionViewModel");
IDataProviderItemRendererMapper: ClassReference("mx.controls.advancedDataGridClasses.DataItemRendererFactoryForICollectionViewAdvancedDataGridData");
- IBeadView: ClassReference("org.apache.royale.html.beads.ListView");
+ IBeadView: ClassReference("org.apache.royale.html.beads.VirtualListView");
IBeadController: ClassReference("mx.controls.advancedDataGridClasses.AdvancedDataGridSingleSelectionMouseController");
- IBeadLayout: ClassReference("org.apache.royale.html.beads.layouts.VerticalLayout");
+ IBeadLayout: ClassReference("mx.controls.beads.layouts.AdvancedDataGridVirtualListVerticalLayout");
IItemRendererClassFactory: ClassReference("org.apache.royale.core.ItemRendererClassFactory");
IItemRenderer: ClassReference("mx.controls.advancedDataGridClasses.AdvancedDataGridItemRenderer");
IViewport: ClassReference("org.apache.royale.html.supportClasses.Viewport");
diff --git a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
index 089aec6..9619309 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as
@@ -159,10 +159,13 @@ internal class MXRoyaleClasses
import mx.events.ProgressEvent; ProgressEvent;
import mx.controls.advancedDataGridClasses.MXAdvancedDataGridItemRenderer; MXAdvancedDataGridItemRenderer;
import mx.controls.advancedDataGridClasses.AdvancedDataGridColumnList; AdvancedDataGridColumnList;
+ import mx.controls.advancedDataGridClasses.AdvancedDataGridListArea; AdvancedDataGridListArea;
import mx.controls.advancedDataGridClasses.AdvancedDataGridSingleSelectionMouseController; AdvancedDataGridSingleSelectionMouseController;
import mx.controls.beads.AdvancedDataGridView; AdvancedDataGridView;
import mx.controls.beads.DataGridView; DataGridView;
+ import mx.controls.beads.layouts.AdvancedDataGridLayout; AdvancedDataGridLayout;
import mx.controls.beads.layouts.DataGridLayout; DataGridLayout;
+ import mx.controls.beads.layouts.AdvancedDataGridVirtualListVerticalLayout; AdvancedDataGridVirtualListVerticalLayout;
import mx.formatters.Formatter; Formatter;
import mx.formatters.IFormatter; IFormatter;
import mx.formatters.NumberBase; NumberBase;
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/advancedDataGridClasses/AdvancedDataGridListArea.as b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/advancedDataGridClasses/AdvancedDataGridListArea.as
new file mode 100644
index 0000000..4604f8d
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/advancedDataGridClasses/AdvancedDataGridListArea.as
@@ -0,0 +1,72 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.advancedDataGridClasses
+{
+
+/* import flash.display.DisplayObject;
+import flash.events.Event;
+ */
+import mx.controls.AdvancedDataGrid;
+
+COMPILE::JS
+{
+import org.apache.royale.core.WrappedHTMLElement;
+}
+import org.apache.royale.html.beads.DataGridListArea;
+
+
+/**
+ * The AdvancedDataGridColumnList class represnts a column in an AdvancedDataGrid control.
+ * There is one AdvancedDataGridColumnList per displayable column, even if a column
+ * is hidden or off-screen.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 9
+ * @playerversion AIR 1.1
+ * @productversion Royale 0.9.3
+ * @royalesuppresspublicvarwarning
+ */
+public class AdvancedDataGridListArea extends DataGridListArea
+{
+ public function AdvancedDataGridListArea()
+ {
+ super();
+ typeNames += " AdvancedDataGridListArea";
+
+ }
+
+ COMPILE::JS
+ override public function internalChildren():Array
+ {
+ var arr:Array = super.internalChildren();
+ // remove scrolling divs from the list
+ // in theory, the only thing that calls this
+ // is HorizontalLayout
+ var children:Array = [];
+ for each (var child:WrappedHTMLElement in children)
+ {
+ if (child.royale_wrapper)
+ children.push(child);
+ }
+ return children;
+ }
+}
+
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/advancedDataGridClasses/DataItemRendererFactoryForICollectionViewAdvancedDataGridData.as b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/advancedDataGridClasses/DataItemRendererFactoryForICollectionViewAdvancedDataGridData.as
index e749ac2..d56315a 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/advancedDataGridClasses/DataItemRendererFactoryForICollectionViewAdvancedDataGridData.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/advancedDataGridClasses/DataItemRendererFactoryForICollectionViewAdvancedDataGridData.as
@@ -20,6 +20,7 @@ package mx.controls.advancedDataGridClasses
{
import mx.collections.ICollectionView;
import mx.collections.IViewCursor;
+ import mx.collections.CursorBookmark;
import mx.controls.advancedDataGridClasses.AdvancedDataGridColumnList;
import mx.core.IUIComponent;
@@ -35,6 +36,7 @@ package mx.controls.advancedDataGridClasses
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;
@@ -45,7 +47,9 @@ package mx.controls.advancedDataGridClasses
import org.apache.royale.events.IEventDispatcher;
import org.apache.royale.events.ItemRendererEvent;
import org.apache.royale.html.List;
- import org.apache.royale.html.beads.DataItemRendererFactoryForCollectionView;
+ import org.apache.royale.html.beads.IListView;
+ import org.apache.royale.html.beads.VirtualDataItemRendererFactoryForArrayData;
+ import org.apache.royale.html.supportClasses.DataItemRenderer;
import org.apache.royale.html.supportClasses.TreeListData;
[Event(name="itemRendererCreated",type="org.apache.royale.events.ItemRendererEvent")]
@@ -62,7 +66,7 @@ package mx.controls.advancedDataGridClasses
* @playerversion AIR 2.6
* @productversion Royale 0.0
*/
- public class DataItemRendererFactoryForICollectionViewAdvancedDataGridData extends DataItemRendererFactoryForCollectionView
+ public class DataItemRendererFactoryForICollectionViewAdvancedDataGridData extends VirtualDataItemRendererFactoryForArrayData
{
/**
* Constructor.
@@ -109,30 +113,23 @@ package mx.controls.advancedDataGridClasses
if (!dp)
return;
- // listen for individual items being added in the future.
- var dped:IEventDispatcher = dp as IEventDispatcher;
- dped.addEventListener(CollectionEvent.ITEM_ADDED, itemAddedHandler);
- dped.addEventListener(CollectionEvent.ITEM_REMOVED, itemRemovedHandler);
- dped.addEventListener(CollectionEvent.ITEM_UPDATED, itemUpdatedHandler);
-
- dataGroup.removeAllItemRenderers();
+ cursor = dp.createCursor();
+ currentIndex = 0;
- var presentationModel:IListPresentationModel = _strand.getBeadByType(IListPresentationModel) as IListPresentationModel;
- labelField = dataProviderModel.labelField;
-
- var n:int = dp.length;
- var cursor:IViewCursor = dp.createCursor();
- for (var i:int = 0; i < n; i++)
- {
- var ir:ISelectableItemRenderer = itemRendererFactory.createItemRenderer(dataGroup) as ISelectableItemRenderer;
- var item:Object = cursor.current;
- cursor.moveNext();
- fillRenderer(i, item, ir, presentationModel);
- }
+ // listen for individual items being added in the future.
+ //var dped:IEventDispatcher = dp as IEventDispatcher;
+ //dped.addEventListener(CollectionEvent.ITEM_ADDED, itemAddedHandler);
+ //dped.addEventListener(CollectionEvent.ITEM_REMOVED, itemRemovedHandler);
+ //dped.addEventListener(CollectionEvent.ITEM_UPDATED, itemUpdatedHandler);
+ //dataGroup.removeAllItemRenderers();
+
IEventDispatcher(_strand).dispatchEvent(new Event("itemsCreated"));
+ IEventDispatcher(_strand).dispatchEvent(new Event("layoutNeeded"));
}
+ private var cursor:IViewCursor;
+ private var currentIndex:int;
/**
* Sets the itemRenderer's data with additional tree-related data.
@@ -142,7 +139,7 @@ package mx.controls.advancedDataGridClasses
* @playerversion AIR 2.6
* @productversion Royale 0.0
*/
- override protected function setData(ir:ISelectableItemRenderer, data:Object, index:int):void
+ protected function setData(ir:ISelectableItemRenderer, data:Object, index:int):void
{
if (!(_strand as AdvancedDataGridColumnList).adg) return;
@@ -162,7 +159,70 @@ package mx.controls.advancedDataGridClasses
if (firstColumn && (_strand as AdvancedDataGridColumnList).adg.groupLabelField)
ir.labelField = (_strand as AdvancedDataGridColumnList).adg.groupLabelField;
- super.setData(ir, data, index);
+ ir.data = data;
+ ir.index = index;
}
+
+ /**
+ * 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
+ */
+ override public function getItemRendererForIndex(index:int, elementIndex:int):ISelectableItemRenderer
+ {
+ var ir:ISelectableItemRenderer = rendererMap[index];
+ if (ir) return ir;
+
+ var dp:ICollectionView = dataProviderModel.dataProvider as ICollectionView;
+
+ 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.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 delta:int = index - currentIndex;
+ if (delta == -1)
+ {
+ cursor.movePrevious();
+ }
+ else if (delta == 1)
+ {
+ cursor.moveNext();
+ }
+ else if (delta != 0)
+ {
+ cursor.seek(CursorBookmark.CURRENT, delta);
+ }
+ currentIndex = index;
+
+ var item:Object = cursor.current;
+ setData(ir, item, index);
+
+ 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/beads/layouts/AdvancedDataGridLayout.as b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/beads/layouts/AdvancedDataGridLayout.as
new file mode 100644
index 0000000..37216e4
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/beads/layouts/AdvancedDataGridLayout.as
@@ -0,0 +1,145 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.beads.layouts
+{
+ import mx.controls.dataGridClasses.DataGridColumn;
+
+ import org.apache.royale.core.IBorderPaddingMarginValuesImpl;
+ import org.apache.royale.core.IDataGridModel;
+ import org.apache.royale.core.IDataProviderModel;
+ import org.apache.royale.core.IListPresentationModel;
+ import org.apache.royale.core.IStrand;
+ import org.apache.royale.core.IStrandWithPresentationModel;
+ import org.apache.royale.core.IUIBase;
+ import org.apache.royale.core.UIBase;
+ import org.apache.royale.core.ValuesManager;
+ import org.apache.royale.core.layout.EdgeData;
+ import org.apache.royale.events.Event;
+ import org.apache.royale.html.beads.IDataGridView;
+ import org.apache.royale.html.beads.models.ButtonBarModel;
+
+
+ /**
+ * The DataGridLayout class.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public class AdvancedDataGridLayout extends DataGridLayout
+ {
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public function AdvancedDataGridLayout()
+ {
+ }
+
+ protected function scrollHandler(e:Event):void
+ {
+ layout();
+ }
+
+ COMPILE::JS
+ protected var topSpacer:HTMLDivElement;
+
+ COMPILE::JS
+ protected var bottomSpacer:HTMLDivElement;
+
+ COMPILE::JS
+ private var listening:Boolean;
+
+ /**
+ * @copy org.apache.royale.core.IBeadLayout#layout
+ * @royaleignorecoercion org.apache.royale.core.IBorderPaddingMarginValuesImpl
+ * @royaleignorecoercion org.apache.royale.core.IDataGridModel
+ * @royaleignorecoercion org.apache.royale.core.IUIBase
+ * @royaleignorecoercion org.apache.royale.core.UIBase
+ * @royaleignorecoercion org.apache.royale.html.beads.IDataGridView
+ * @royaleignorecoercion org.apache.royale.html.beads.models.ButtonBarModel
+ * @royaleignorecoercion org.apache.royale.html.supportClasses.IDataGridColumn
+ */
+ override public function layout():Boolean
+ {
+ var presentationModel:IListPresentationModel = (uiHost as IStrandWithPresentationModel).presentationModel as IListPresentationModel;
+ var retval:Boolean = super.layout();
+ COMPILE::JS
+ {
+ if (!listening)
+ (uiHost.view as IDataGridView).listArea.element.addEventListener("scroll", scrollHandler);
+ listening = true;
+ }
+ if (!uiHost.isHeightSizedToContent())
+ {
+ var header:IUIBase = (uiHost.view as IDataGridView).header;
+ var bbmodel:ButtonBarModel = header.getBeadByType(ButtonBarModel) as ButtonBarModel;
+ // do the proportional sizing of columns
+ var borderMetrics:EdgeData = (ValuesManager.valuesImpl as IBorderPaddingMarginValuesImpl).getBorderMetrics(_strand as IUIBase);
+ var useWidth:Number = uiHost.width - (borderMetrics.left + borderMetrics.right);
+ var useHeight:Number = uiHost.height - (borderMetrics.top + borderMetrics.bottom);
+ var displayedColumns:Array = (uiHost.view as IDataGridView).columnLists;
+ var n:int = displayedColumns.length;
+ var listArea:IUIBase = (uiHost.view as IDataGridView).listArea;
+ COMPILE::JS
+ {
+ var topSpacerHeight:Number = Math.floor(listArea.element.scrollTop / presentationModel.rowHeight)
+ * presentationModel.rowHeight;
+ }
+ for (var i:int = 0; i < n; i++)
+ {
+ var columnList:UIBase = displayedColumns[i] as UIBase;
+ columnList.height = useHeight;
+ COMPILE::JS
+ {
+ columnList.element.style.position = "absolute";
+ columnList.element.style.top = (topSpacerHeight + 1).toString() + 'px';
+ columnList.dispatchEvent(new Event("layoutNeeded"));
+ }
+ }
+ var model:IDataGridModel = uiHost.model as IDataGridModel;
+ if (model.dataProvider && model.dataProvider.length)
+ {
+ var totalHeight:Number = model.dataProvider.length * presentationModel.rowHeight;
+ COMPILE::JS
+ {
+ if (!topSpacer)
+ {
+ topSpacer = document.createElement("div") as HTMLDivElement;
+ listArea.element.insertBefore(topSpacer, (listArea as UIBase).internalChildren()[0]);
+ }
+ topSpacer.style.height = topSpacerHeight.toString() + "px";
+ if (!bottomSpacer)
+ {
+ bottomSpacer = document.createElement("div") as HTMLDivElement;
+ listArea.element.appendChild(bottomSpacer);
+ }
+ bottomSpacer.style.height = (totalHeight - useHeight - topSpacerHeight).toString() + "px";
+ }
+ }
+ }
+ return retval;
+ }
+ }
+}
diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/beads/layouts/AdvancedDataGridVirtualListVerticalLayout.as b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/beads/layouts/AdvancedDataGridVirtualListVerticalLayout.as
new file mode 100644
index 0000000..33d72d6
--- /dev/null
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/beads/layouts/AdvancedDataGridVirtualListVerticalLayout.as
@@ -0,0 +1,374 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.beads.layouts
+{
+ import org.apache.royale.core.IBorderPaddingMarginValuesImpl;
+ import org.apache.royale.core.IDataProviderModel;
+ import org.apache.royale.core.IDataProviderVirtualItemRendererMapper;
+ import org.apache.royale.core.ILayoutView;
+ import org.apache.royale.core.IListPresentationModel;
+ 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.ValuesManager;
+ import org.apache.royale.core.layout.EdgeData;
+ import org.apache.royale.events.Event;
+ import org.apache.royale.html.beads.IDataGridView;
+ import org.apache.royale.html.beads.layouts.VirtualListVerticalLayout;
+ import org.apache.royale.html.beads.models.ButtonBarModel;
+ import org.apache.royale.html.beads.VirtualDataContainerView;
+
+
+ COMPILE::SWF {
+ import org.apache.royale.geom.Size;
+ }
+
+ /**
+ * The AdvancedDataGridVirtualListVerticalLayout class. It works a bit differently
+ * from other VirtualLayouts for JS because the div padding is applied to the container
+ * of these column lists. The lists don't scroll, they only update the renderers
+ * for the viewport.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public class AdvancedDataGridVirtualListVerticalLayout extends org.apache.royale.html.beads.layouts.VirtualListVerticalLayout
+ {
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public function AdvancedDataGridVirtualListVerticalLayout()
+ {
+ }
+
+ override public function set strand(value:IStrand):void
+ {
+ super.strand = value;
+ dataProviderModel.addEventListener("dataProviderChanged", dataProviderChangeHandler);
+ }
+
+ private function dataProviderChangeHandler(event:Event):void
+ {
+ var factory:IDataProviderVirtualItemRendererMapper = host.getBeadByType(IDataProviderVirtualItemRendererMapper) as IDataProviderVirtualItemRendererMapper;
+ while (visibleIndexes.length)
+ {
+ var index:int = visibleIndexes.pop();
+ factory.freeItemRendererForIndex(index);
+ }
+ }
+
+ 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 = getVerticalScrollPosition();
+ 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++)
+ {
+ if (i >= dp.length) continue; // no more renderers needed
+
+ 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 = getVerticalScrollPosition();
+ // correct overscroll on Safari?
+ var top:String = host.element.style.top;
+ var c:int = top.indexOf("px");
+ if (c > 0)
+ {
+ var topValue:Number = parseFloat(top.substring(0, c));
+ if (topValue < 0)
+ {
+ trace(host.element.style.top);
+ host.element.style.top = "1px";
+ }
+ }
+ // end correct overscroll on Safari
+ 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 (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++)
+ {
+ if (i >= dp.length) continue; // no more renderers needed
+
+ var ir:ISelectableItemRenderer;
+ if (i < firstIndex)
+ {
+ // the base class adds 1 because the div/scroll padding is in the
+ // same list/datagroup, but for ADG, the padding is outside of the lists
+ ir = factory.getItemRendererForIndex(i, i - startIndex);
+ ir.element.style.display = "block";
+ visibleIndexes.push(i);
+ }
+ else if (i > lastIndex)
+ {
+ ir = factory.getItemRendererForIndex(i, i - startIndex);
+ ir.element.style.display = "block";
+ visibleIndexes.push(i);
+ }
+ }
+ visibleIndexes = visibleIndexes.sort(numberSort);
+ inLayout = false;
+ return true;
+ }
+ }
+
+ /**
+ * @royaleignorecoercion HTMLDivElement
+ */
+ private function getVerticalScrollPosition():Number
+ {
+ COMPILE::SWF
+ {
+ return 0; // to do
+ }
+ COMPILE::JS
+ {
+ return Math.max((host.element.parentNode as HTMLDivElement).scrollTop, 0);
+ }
+ }
+
+ override protected function scrollHandler(e:Event):void
+ {
+ // don't scroll. The container of these column lists does the scrolling
+ }
+
+ }
+}