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 afe6a2af57a76985033d893c9ceaf89a545e2f5a Author: Alex Harui <[email protected]> AuthorDate: Tue Feb 13 17:09:19 2018 -0800 JS fixed row height virtual lists --- .../Basic/src/main/resources/basic-manifest.xml | 2 + .../royale/core/IListWithPresentationModel.as | 46 +++ .../royale/org/apache/royale/html/DataContainer.as | 3 +- .../royale/html/beads/VirtualDataContainerView.as | 223 +++++++++++++++ .../VirtualDataItemRendererFactoryForArrayData.as | 215 ++++++++++++++ .../apache/royale/html/beads/VirtualListView.as | 185 ++++++++++++ .../beads/layouts/VirtualListVerticalLayout.as | 309 +++++++++++++++++++++ .../projects/Core/src/main/royale/CoreClasses.as | 1 + .../core/IDataProviderVirtualItemRendererMapper.as | 43 +++ 9 files changed, 1026 insertions(+), 1 deletion(-) diff --git a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml index 0ba6ba8..19d525e 100644 --- a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml +++ b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml @@ -70,6 +70,7 @@ <component id="BasicLayout" class="org.apache.royale.html.beads.layouts.BasicLayout"/> <component id="RemovableBasicLayout" class="org.apache.royale.html.beads.layouts.RemovableBasicLayout"/> <component id="VerticalLayout" class="org.apache.royale.html.beads.layouts.VerticalLayout"/> + <component id="VirtualListVerticalLayout" class="org.apache.royale.html.beads.layouts.VirtualListVerticalLayout"/> <component id="VerticalLayoutWithPaddingAndGap" class="org.apache.royale.html.beads.layouts.VerticalLayoutWithPaddingAndGap"/> <component id="VerticalFlexLayout" class="org.apache.royale.html.beads.layouts.VerticalFlexLayout"/> <component id="VerticalSliderLayout" class="org.apache.royale.html.beads.layouts.VerticalSliderLayout" /> @@ -166,6 +167,7 @@ <component id="DynamicRemoveAllByNullItemRendererForArrayListData" class="org.apache.royale.html.beads.DynamicRemoveAllByNullItemRendererForArrayListData" /> <component id="TextItemRendererFactoryForArrayData" class="org.apache.royale.html.beads.TextItemRendererFactoryForArrayData" /> <component id="TextItemRendererFactoryForStringVectorData" class="org.apache.royale.html.beads.TextItemRendererFactoryForStringVectorData" /> + <component id="VirtualDataItemRendererFactoryForArrayData" class="org.apache.royale.html.beads.VirtualDataItemRendererFactoryForArrayData" /> <component id="DateChooser" class="org.apache.royale.html.DateChooser"/> <component id="DateChooserList" class="org.apache.royale.html.supportClasses.DateChooserList" /> diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/IListWithPresentationModel.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/IListWithPresentationModel.as new file mode 100644 index 0000000..3e24bfc --- /dev/null +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/core/IListWithPresentationModel.as @@ -0,0 +1,46 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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.core +{ + import org.apache.royale.core.IListPresentationModel; + + /** + * The IListWithPresentationModel interface is implemented by any IList + * that supports a separate IListPresentationModel + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.0 + */ + public interface IListWithPresentationModel extends IList + { + /** + * Returns the component within the list (maybe even the list shell itself) + * which will be the parent of each itemRenderer. + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.0 + */ + function get presentationModel():IListPresentationModel; + + } +} diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/DataContainer.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/DataContainer.as index 47d54b8..bb5707e 100644 --- a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/DataContainer.as +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/DataContainer.as @@ -30,6 +30,7 @@ package org.apache.royale.html import org.apache.royale.core.IItemRendererParent; import org.apache.royale.core.ILayoutView; import org.apache.royale.core.IList; + import org.apache.royale.core.IListWithPresentationModel; import org.apache.royale.core.IListPresentationModel; import org.apache.royale.core.IRollOverModel; import org.apache.royale.core.IDataProviderModel; @@ -73,7 +74,7 @@ package org.apache.royale.html * @playerversion AIR 2.6 * @productversion Royale 0.0 */ - public class DataContainer extends DataContainerBase + public class DataContainer extends DataContainerBase implements IListWithPresentationModel { /** * constructor. diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/VirtualDataContainerView.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/VirtualDataContainerView.as new file mode 100644 index 0000000..dc38e6f --- /dev/null +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/VirtualDataContainerView.as @@ -0,0 +1,223 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +{ + import org.apache.royale.core.BeadViewBase; + import org.apache.royale.core.ContainerBase; + import org.apache.royale.core.IBead; + import org.apache.royale.core.IBeadLayout; + import org.apache.royale.core.IBeadModel; + import org.apache.royale.core.IBeadView; + import org.apache.royale.core.IDataProviderModel; + import org.apache.royale.core.IItemRenderer; + import org.apache.royale.core.IItemRendererParent; + import org.apache.royale.core.IList; + import org.apache.royale.core.IParent; + import org.apache.royale.core.IParentIUIBase; + import org.apache.royale.core.ISelectableItemRenderer; + import org.apache.royale.core.ISelectionModel; + import org.apache.royale.core.IStrand; + import org.apache.royale.core.IUIBase; + import org.apache.royale.core.LayoutBase; + import org.apache.royale.core.Strand; + import org.apache.royale.core.UIBase; + import org.apache.royale.core.ValuesManager; + import org.apache.royale.events.Event; + import org.apache.royale.events.IEventDispatcher; + import org.apache.royale.html.supportClasses.Border; + import org.apache.royale.html.supportClasses.DataGroup; + + /** + * The DataContainerView provides the visual elements for the DataContainer. + * + * @viewbead + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.8 + */ + COMPILE::JS + public class VirtualDataContainerView extends ContainerView implements IListView + { + public function VirtualDataContainerView() + { + super(); + } + + /** + * @copy org.apache.royale.core.IBead#strand + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.8 + */ + override public function set strand(value:IStrand):void + { + _strand = value; + super.strand = value; + + host.addEventListener("beadsAdded", beadsAddedHandler); + } + + protected var dataModel:IDataProviderModel; + + /** + * @royaleignorecoercion org.apache.royale.core.IItemRendererParent + */ + public function get dataGroup():IItemRendererParent + { + return super.contentView as IItemRendererParent; + } + + protected function beadsAddedHandler(event:Event):void + { + dataModel = _strand.getBeadByType(IDataProviderModel) as IDataProviderModel; + host.addEventListener("itemsCreated", itemsCreatedHandler); + dataModel.addEventListener("dataProviderChanged", dataProviderChangeHandler); + } + + /** + * @private + */ + override protected function handleInitComplete(event:Event):void + { + super.handleInitComplete(event); + } + + /** + * @private + */ + protected function itemsCreatedHandler(event:Event):void + { + // trace("DataContainerView: itemsCreatedHandler"); + host.dispatchEvent(new Event("layoutNeeded")); + } + + /** + * @private + */ + protected function dataProviderChangeHandler(event:Event):void + { + // trace("DataContainerView: dataProviderChangeHandler"); + adjustView(); + performLayout(event); + } + + } + + COMPILE::SWF + public class VirtualDataContainerView extends ContainerView implements IListView + { + public function VirtualDataContainerView() + { + super(); + } + + protected var dataModel:IDataProviderModel; + + /** + * @private + */ + override public function get host():IUIBase + { + return _strand as IUIBase; + } + + /** + * @copy org.apache.royale.core.IBead#strand + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.8 + */ + override public function set strand(value:IStrand):void + { + _strand = value; + super.strand = value; + + host.addEventListener("beadsAdded", beadsAddedHandler); + } + + override protected function completeSetup():void + { + super.completeSetup(); + + // list is not interested in UI children, it wants to know when new items + // have been added or the dataProvider has changed. +// host.removeEventListener("childrenAdded", childrenChangedHandler); +// host.removeEventListener("childrenAdded", performLayout); + } + + protected function beadsAddedHandler(event:Event):void + { + dataModel = _strand.getBeadByType(IDataProviderModel) as IDataProviderModel; + dataModel.addEventListener("dataProviderChanged", dataProviderChangeHandler); + } + + override protected function handleInitComplete(event:Event):void + { + super.handleInitComplete(event); + } + + /** + * The area holding the itemRenderers. + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.8 + */ + public function get dataGroup():IItemRendererParent + { + return super.contentView as IItemRendererParent; + } + + /** + * @private + */ + override public function get resizableView():IUIBase + { + return _strand as IUIBase; + } + + /** + * @private + */ + protected function dataProviderChangeHandler(event:Event):void + { + host.dispatchEvent(new Event("layoutNeeded")); + } + + /** + * respond to a change in size or request to re-layout everything + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.0 + */ + override protected function resizeHandler(event:Event):void + { + // might need to do something here, not sure yet. + super.resizeHandler(event); + } + } +} diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/VirtualDataItemRendererFactoryForArrayData.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/VirtualDataItemRendererFactoryForArrayData.as new file mode 100644 index 0000000..e78e67f --- /dev/null +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/VirtualDataItemRendererFactoryForArrayData.as @@ -0,0 +1,215 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +{ + import org.apache.royale.core.IBead; + import org.apache.royale.core.IChild; + import org.apache.royale.core.IDataProviderModel; + import org.apache.royale.core.IDataProviderVirtualItemRendererMapper; + import org.apache.royale.core.IItemRendererClassFactory; + import org.apache.royale.core.IItemRendererParent; + import org.apache.royale.core.ILayoutHost; + import org.apache.royale.core.IList; + import org.apache.royale.core.IListPresentationModel; + import org.apache.royale.core.IParentIUIBase; + import org.apache.royale.core.ISelectableItemRenderer; + import org.apache.royale.core.IStrand; + 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.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.supportClasses.DataItemRenderer; + import org.apache.royale.utils.loadBeadFromValuesManager; + + [Event(name="itemRendererCreated",type="org.apache.royale.events.ItemRendererEvent")] + + /** + * The DataItemRendererFactoryForArrayData class reads an + * array of data 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 VirtualDataItemRendererFactoryForArrayData extends EventDispatcher implements IBead, IDataProviderVirtualItemRendererMapper + { + /** + * Constructor. + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.0 + */ + public function VirtualDataItemRendererFactoryForArrayData(target:Object=null) + { + super(target); + } + + protected var dataProviderModel:IDataProviderModel; + protected var dataFieldProvider:DataFieldProviderBead; + + protected var labelField:String; + protected var dataField:String; + + private var _strand:IStrand; + + /** + * @copy org.apache.royale.core.IBead#strand + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.0 + */ + public function set strand(value:IStrand):void + { + _strand = value; + IEventDispatcher(value).addEventListener("initComplete",finishSetup); + } + + /** + * @private + */ + private function finishSetup(event:Event):void + { + dataProviderModel = _strand.getBeadByType(IDataProviderModel) as IDataProviderModel; + dataProviderModel.addEventListener("dataProviderChanged", dataProviderChangeHandler); + labelField = dataProviderModel.labelField; + + dataFieldProvider = _strand.getBeadByType(DataFieldProviderBead) as DataFieldProviderBead; + if (dataFieldProvider) + { + dataField = dataFieldProvider.dataField; + } + + // if the host component inherits from DataContainerBase, the itemRendererClassFactory will + // already have been loaded by DataContainerBase.addedToParent function. + if(!_itemRendererFactory) + _itemRendererFactory = loadBeadFromValuesManager(IItemRendererClassFactory, "iItemRendererClassFactory", _strand) as IItemRendererClassFactory; + + dataProviderChangeHandler(null); + } + + private var _itemRendererFactory:IItemRendererClassFactory; + + /** + * The org.apache.royale.core.IItemRendererClassFactory used + * to generate instances of item renderers. + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.0 + */ + public function get itemRendererFactory():IItemRendererClassFactory + { + if(!_itemRendererFactory) + _itemRendererFactory = loadBeadFromValuesManager(IItemRendererClassFactory, "iItemRendererClassFactory", _strand) as IItemRendererClassFactory; + + return _itemRendererFactory; + } + + /** + * @private + */ + public function set itemRendererFactory(value:IItemRendererClassFactory):void + { + _itemRendererFactory = value; + } + + /** + * 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 + */ + protected function dataProviderChangeHandler(event:Event):void + { + var dp:Array = dataProviderModel.dataProvider as Array; + if (!dp) + return; + + var list:IList = _strand as IList; + var dataGroup:IItemRendererParent = list.dataGroup; + + dataGroup.removeAllItemRenderers(); + } + + public function freeItemRendererForIndex(index:int):void + { + var ir:ISelectableItemRenderer = rendererMap[index]; + var list:IList = _strand as IList; + var dataGroup:IItemRendererParent = list.dataGroup; + dataGroup.removeItemRenderer(ir); + delete rendererMap[index]; + } + + private var rendererMap:Object = {}; + + public function getItemRendererForIndex(index:int, elementIndex:int):ISelectableItemRenderer + { + var ir:ISelectableItemRenderer = rendererMap[index]; + if (ir) return ir; + + var dp:Array = dataProviderModel.dataProvider as Array; + + ir = itemRendererFactory.createItemRenderer(dataGroup) as ISelectableItemRenderer; + var dataItemRenderer:DataItemRenderer = ir as DataItemRenderer; + + var list:IList = _strand as IList; + var dataGroup:IItemRendererParent = list.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; + } + ir.data = dp[index]; + + var newEvent:ItemRendererEvent = new ItemRendererEvent(ItemRendererEvent.CREATED); + newEvent.itemRenderer = ir; + dispatchEvent(newEvent); + return ir; + } + } +} diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/VirtualListView.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/VirtualListView.as new file mode 100644 index 0000000..f125deb --- /dev/null +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/VirtualListView.as @@ -0,0 +1,185 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 +{ + import org.apache.royale.core.BeadViewBase; + import org.apache.royale.core.ContainerBase; + import org.apache.royale.core.IBead; + import org.apache.royale.core.IBeadLayout; + import org.apache.royale.core.IBeadModel; + import org.apache.royale.core.IBeadView; + import org.apache.royale.core.IList; + import org.apache.royale.core.ISelectableItemRenderer; + import org.apache.royale.core.IItemRenderer; + import org.apache.royale.core.IItemRendererParent; + import org.apache.royale.core.IParent; + import org.apache.royale.core.IParentIUIBase; + import org.apache.royale.core.IRollOverModel; + import org.apache.royale.core.ISelectionModel; + import org.apache.royale.core.IStrand; + import org.apache.royale.core.IUIBase; + import org.apache.royale.core.Strand; + import org.apache.royale.core.UIBase; + import org.apache.royale.core.ValuesManager; + import org.apache.royale.events.Event; + import org.apache.royale.events.IEventDispatcher; + import org.apache.royale.html.beads.models.ArraySelectionModel; + import org.apache.royale.html.supportClasses.Border; + import org.apache.royale.html.supportClasses.DataGroup; + + /** + * The List class creates the visual elements of the org.apache.royale.html.List + * component. A List consists of the area to display the data (in the dataGroup), any + * scrollbars, and so forth. + * + * @viewbead + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.0 + */ + COMPILE::JS + public class VirtualListView extends VirtualDataContainerView + { + public function VirtualListView() + { + super(); + } + + protected var listModel:ISelectionModel; + + protected var lastSelectedIndex:int = -1; + + /** + * @private + */ + override protected function handleInitComplete(event:Event):void + { + listModel = _strand.getBeadByType(ISelectionModel) as ISelectionModel; + listModel.addEventListener("selectedIndexChanged", selectionChangeHandler); + listModel.addEventListener("rollOverIndexChanged", rollOverIndexChangeHandler); + + super.handleInitComplete(event); + } + + /** + * @private + * @royaleignorecoercion org.apache.royale.core.ISelectableItemRenderer + */ + protected function selectionChangeHandler(event:Event):void + { + var ir:ISelectableItemRenderer = dataGroup.getItemRendererForIndex(lastSelectedIndex) as ISelectableItemRenderer; + if(ir) + ir.selected = false; + ir = dataGroup.getItemRendererForIndex(listModel.selectedIndex) as ISelectableItemRenderer; + if(ir) + ir.selected = true; + + lastSelectedIndex = listModel.selectedIndex; + } + + protected var lastRollOverIndex:int = -1; + + /** + * @private + * @royaleignorecoercion org.apache.royale.core.ISelectableItemRenderer + * * @royaleignorecoercion org.apache.royale.core.IRollOverModel + */ + protected function rollOverIndexChangeHandler(event:Event):void + { + var ir:ISelectableItemRenderer = dataGroup.getItemRendererForIndex(lastRollOverIndex) as ISelectableItemRenderer; + if(ir) + ir.hovered = false; + ir = dataGroup.getItemRendererForIndex((listModel as IRollOverModel).rollOverIndex) as ISelectableItemRenderer; + if(ir) + ir.hovered = true; + lastRollOverIndex = (listModel as IRollOverModel).rollOverIndex; + } + } + + COMPILE::SWF + public class VirtualListView extends VirtualDataContainerView + { + public function VirtualListView() + { + super(); + } + + protected var listModel:ISelectionModel; + + /** + * @copy org.apache.royale.core.IBead#strand + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.0 + */ + override public function set strand(value:IStrand):void + { + _strand = value; + super.strand = value; + } + + /** + * @private + */ + override protected function handleInitComplete(event:Event):void + { + super.handleInitComplete(event); + + listModel = _strand.getBeadByType(ISelectionModel) as ISelectionModel; + listModel.addEventListener("selectedIndexChanged", selectionChangeHandler); + listModel.addEventListener("rollOverIndexChanged", rollOverIndexChangeHandler); + } + + protected var lastSelectedIndex:int = -1; + + /** + * @private + */ + protected function selectionChangeHandler(event:Event):void + { + var ir:ISelectableItemRenderer = dataGroup.getItemRendererForIndex(lastSelectedIndex) as ISelectableItemRenderer; + if (ir) + ir.selected = false; + ir = dataGroup.getItemRendererForIndex(listModel.selectedIndex) as ISelectableItemRenderer; + if (ir) + ir.selected = true; + lastSelectedIndex = listModel.selectedIndex; + } + + protected var lastRollOverIndex:int = -1; + + /** + * @private + */ + protected function rollOverIndexChangeHandler(event:Event):void + { + var ir:ISelectableItemRenderer = dataGroup.getItemRendererForIndex(lastRollOverIndex) as ISelectableItemRenderer; + if(ir) + ir.hovered = false; + ir = dataGroup.getItemRendererForIndex(IRollOverModel(listModel).rollOverIndex) as ISelectableItemRenderer; + if(ir) + ir.hovered = true; + + lastRollOverIndex = IRollOverModel(listModel).rollOverIndex; + } + } +} diff --git a/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/layouts/VirtualListVerticalLayout.as b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/layouts/VirtualListVerticalLayout.as new file mode 100644 index 0000000..703c024 --- /dev/null +++ b/frameworks/projects/Basic/src/main/royale/org/apache/royale/html/beads/layouts/VirtualListVerticalLayout.as @@ -0,0 +1,309 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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.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.IListWithPresentationModel; + import org.apache.royale.core.IParentIUIBase; + import org.apache.royale.core.ISelectableItemRenderer; + import org.apache.royale.core.IStrand; + import org.apache.royale.core.IUIBase; + import org.apache.royale.core.LayoutBase; + import org.apache.royale.core.ValuesManager; + 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.utils.CSSContainerUtils; + import org.apache.royale.utils.CSSUtils; + + /** + * 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; + + COMPILE::JS + private var visibleIndexes:Array = []; + + COMPILE::JS + 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 org.apache.royale.core.ILayoutHost + * @royaleignorecoercion org.apache.royale.core.WrappedHTMLElement + */ + override public function layout():Boolean + { + if (inLayout) return true; + inLayout = true; + + COMPILE::SWF + { + var contentView:ILayoutView = layoutView; + + var n:Number = contentView.numElements; + if (n == 0) return false; + + var maxWidth:Number = 0; + var maxHeight:Number = 0; + var hostWidthSizedToContent:Boolean = host.isWidthSizedToContent(); + var hostHeightSizedToContent:Boolean = host.isHeightSizedToContent(); + var hostWidth:Number = host.width; + var hostHeight:Number = host.height; + + var ilc:ILayoutChild; + var data:Object; + var canAdjust:Boolean = false; + + var paddingMetrics:Rectangle = CSSContainerUtils.getPaddingMetrics(host); + var borderMetrics:Rectangle = CSSContainerUtils.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; + + // First pass determines the data about the child. + for(var i:int=0; i < n; i++) + { + var child:IUIBase = contentView.getElementAt(i) as IUIBase; + if (child == null || !child.visible) continue; + var positions:Object = childPositions(child); + var margins:Object = childMargins(child, hostWidth, hostHeight); + + ilc = child as ILayoutChild; + + 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; + } + + 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; + var presentationModel:IListPresentationModel = (host as IListWithPresentationModel).presentationModel; + 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; + } + + } +} diff --git a/frameworks/projects/Core/src/main/royale/CoreClasses.as b/frameworks/projects/Core/src/main/royale/CoreClasses.as index edd9b69..5102ba3 100644 --- a/frameworks/projects/Core/src/main/royale/CoreClasses.as +++ b/frameworks/projects/Core/src/main/royale/CoreClasses.as @@ -70,6 +70,7 @@ internal class CoreClasses import org.apache.royale.core.IContentView; IContentView; import org.apache.royale.core.IContentViewHost; IContentViewHost; import org.apache.royale.core.IDataProviderItemRendererMapper; IDataProviderItemRendererMapper; + import org.apache.royale.core.IDataProviderVirtualItemRendererMapper; IDataProviderVirtualItemRendererMapper; import org.apache.royale.core.IDataProviderNotifier; IDataProviderNotifier; import org.apache.royale.core.IBinaryImageModel; IBinaryImageModel; import org.apache.royale.core.IDocument; IDocument; diff --git a/frameworks/projects/Core/src/main/royale/org/apache/royale/core/IDataProviderVirtualItemRendererMapper.as b/frameworks/projects/Core/src/main/royale/org/apache/royale/core/IDataProviderVirtualItemRendererMapper.as new file mode 100644 index 0000000..d31aa60 --- /dev/null +++ b/frameworks/projects/Core/src/main/royale/org/apache/royale/core/IDataProviderVirtualItemRendererMapper.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 org.apache.royale.core +{ + import org.apache.royale.core.IBead; + import org.apache.royale.core.IItemRendererClassFactory; + + /** + * The IDataProviderItemRendererMapper interface is the interface for beads + * that know how to iterate through a dataProvider, generate item renderers, + * and assign items from the dataProvider to those item renderers. In Royale, + * a wide range of data providers are allowed, from simple Arrays and Vectors + * on up to sophisticated data structures that dispatch change events. + * Different IDataProviderItemRendererMapper implements are often required to + * iterate through those different data structures. + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.0 + */ + public interface IDataProviderVirtualItemRendererMapper extends IDataProviderItemRendererMapper + { + function freeItemRendererForIndex(index:int):void; + function getItemRendererForIndex(index:int, elementIndex:int):ISelectableItemRenderer; + } +} -- To stop receiving notification emails like this one, please contact [email protected].
