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 b98a1a5aad52cb7f087675f1d23fb14e937ccf30 Author: Alex Harui <[email protected]> AuthorDate: Tue May 12 00:40:19 2020 -0700 mx:Menu. Should fix #815 --- .../MXRoyale/src/main/resources/defaults.css | 19 +- .../src/main/resources/mx-royale-manifest.xml | 1 + .../MXRoyale/src/main/royale/MXRoyaleClasses.as | 1 + .../MXRoyale/src/main/royale/mx/controls/Menu.as | 485 +++++++++++++++++---- .../mx/controls/beads/models/CascadingMenuModel.as | 107 +++++ .../royale/mx/controls/listClasses/ListBase.as | 2 +- 6 files changed, 535 insertions(+), 80 deletions(-) diff --git a/frameworks/projects/MXRoyale/src/main/resources/defaults.css b/frameworks/projects/MXRoyale/src/main/resources/defaults.css index a188d11..dd0837c 100644 --- a/frameworks/projects/MXRoyale/src/main/resources/defaults.css +++ b/frameworks/projects/MXRoyale/src/main/resources/defaults.css @@ -356,11 +356,20 @@ menu|MenuBarItemRenderer { margin-right: 10px; cursor: pointer; } -/* + Menu { - IBeadModel: ClassReference("org.apache.royale.html.beads.models.CascadingMenuModel"); - IBeadController: ClassReference("org.apache.royale.html.beads.controllers.CascadingMenuSelectionMouseController"); - IItemRenderer: ClassReference("org.apache.royale.html.supportClasses.CascadingMenuItemRenderer"); + IMenu: ClassReference("org.apache.royale.html.CascadingMenu"); + IBeadModel: ClassReference("mx.controls.beads.models.CascadingMenuModel"); + IBeadController: ClassReference("mx.controls.beads.controllers.CascadingMenuSelectionMouseController"); + IItemRenderer: ClassReference("mx.controls.menuClasses.CascadingMenuItemRenderer"); + IBeadView: ClassReference("org.apache.royale.html.beads.ListView"); + IBeadLayout: ClassReference("org.apache.royale.html.beads.layouts.VerticalLayout"); + IDataProviderItemRendererMapper: ClassReference("mx.controls.listClasses.DataItemRendererFactoryForICollectionViewData"); + IItemRendererClassFactory: ClassReference("org.apache.royale.core.SelectableItemRendererClassFactory"); + IItemRendererInitializer: ClassReference("mx.controls.beads.ListItemRendererInitializer"); + ISelectableItemRenderer: ClassReference("org.apache.royale.html.beads.SolidBackgroundSelectableItemRendererBead"); + IListPresentationModel: ClassReference("org.apache.royale.html.beads.models.ListPresentationModel"); + position: absolute; background-color: white; border-width: 1px; @@ -368,7 +377,7 @@ Menu { border-color: #222222; box-shadow: 2px 2px 5px gray; } - +/* MenuItemRenderer { margin-top: 4px; margin-left: 2px; diff --git a/frameworks/projects/MXRoyale/src/main/resources/mx-royale-manifest.xml b/frameworks/projects/MXRoyale/src/main/resources/mx-royale-manifest.xml index 04b0943..45a65d6 100644 --- a/frameworks/projects/MXRoyale/src/main/resources/mx-royale-manifest.xml +++ b/frameworks/projects/MXRoyale/src/main/resources/mx-royale-manifest.xml @@ -118,6 +118,7 @@ <component id="Validator" class="mx.validators.Validator"/> <component id="DateFormatter" class="mx.formatters.DateFormatter"/> <component id="MenuBar" class="mx.controls.MenuBar"/> + <component id="Menu" class="mx.controls.Menu"/> <component id="Glow" class="mx.effects.Glow"/> <component id="StringValidator" class="mx.validators.StringValidator"/> <component id="RegExpValidator" class="mx.validators.RegExpValidator"/> diff --git a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as index d8d0c0a..b58e00b 100644 --- a/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as +++ b/frameworks/projects/MXRoyale/src/main/royale/MXRoyaleClasses.as @@ -266,6 +266,7 @@ internal class MXRoyaleClasses import mx.containers.beads.TabNavigatorView; TabNavigatorView; import mx.controls.TabBar; TabBar; import mx.controls.beads.models.ComboBoxModel; ComboBoxModel; + import mx.controls.beads.models.CascadingMenuModel; CascadingMenuModel; import mx.controls.beads.models.SingleSelectionICollectionViewModel; SingleSelectionICollectionViewModel; import mx.controls.beads.models.DataGridColumnICollectionViewModel; DataGridColumnICollectionViewModel; diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/Menu.as b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/Menu.as index 42f1cd2..b4d292b 100644 --- a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/Menu.as +++ b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/Menu.as @@ -21,8 +21,25 @@ package mx.controls { import org.apache.royale.events.Event; + import org.apache.royale.events.IEventDispatcher; import org.apache.royale.geom.Rectangle; import org.apache.royale.geom.Point; + import org.apache.royale.core.IListPresentationModel; + import org.apache.royale.core.ISelectionModel; + import org.apache.royale.core.ValuesManager; + import org.apache.royale.core.IFactory; + import org.apache.royale.core.IBead; + import org.apache.royale.core.IBeadLayout; + import org.apache.royale.core.ILayoutHost; + import org.apache.royale.core.IMenu; + import org.apache.royale.core.IUIBase; + import org.apache.royale.core.IDataProviderItemRendererMapper; + import org.apache.royale.core.IItemRendererClassFactory; + import org.apache.royale.core.IItemRendererProvider; + import org.apache.royale.html.beads.models.CascadingMenuModel; + import org.apache.royale.html.beads.models.MenuModel; + import org.apache.royale.utils.loadBeadFromValuesManager; + import mx.core.UIComponent; import mx.events.MouseEvent; @@ -571,7 +588,7 @@ package mx.controls * @playerversion AIR 1.1 * @productversion Flex 3 */ - public class Menu extends List implements IFocusManagerContainer + public class Menu extends UIComponent implements IFocusManagerContainer, IMenu { // include "../core/Version.as"; @@ -697,6 +714,7 @@ package mx.controls /*itemRenderer = new ClassFactory(MenuItemRenderer); setRowHeight(19); iconField = "icon";*/ + typeNames = "Menu"; visible = false; } @@ -906,13 +924,13 @@ package mx.controls * @see mx.controls.List * @see mx.controls.Tree */ - /*override public function set dataProvider(value:Object):void + public function set dataProvider(value:Object):void { // handle strings and xml if (typeof(value)=="string") value = new XML(value); - else if (value is XMLNode) - value = new XML(XMLNode(value).toString()); + //else if (value is XMLNode) + // value = new XML(XMLNode(value).toString()); else if (value is XMLList) value = new XMLListCollection(value as XMLList); @@ -948,29 +966,18 @@ package mx.controls _rootModel = new ArrayCollection(); } + (model as ISelectionModel).dataProvider = _rootModel; //flag for processing in commitProps dataProviderChanged = true; invalidateProperties(); - }*/ + } /** * @private */ - override public function get dataProvider():Object + public function get dataProvider():Object { - var model:* = super.dataProvider; - if (model == null) - { - if (_rootModel != null ) - { - return _rootModel; - } - } - else - { - return model; - } - return null; + return (model as ISelectionModel).dataProvider; } //-------------------------------------------------------------------------- @@ -1137,48 +1144,6 @@ package mx.controls itemRenderer = parentMenu.itemRenderer; } - // ------------------------------------------------------------------------- - // horizontalScrollPolicy - // ------------------------------------------------------------------------- - - [Inspectable(environment="none")] - - /** - * @private - */ - override public function get horizontalScrollPolicy():String - { - return ScrollPolicy.OFF; - } - - /** - * @private - */ - override public function set horizontalScrollPolicy(value:String):void - { - } - - // ------------------------------------------------------------------------- - // verticalScrollPolicy - // ------------------------------------------------------------------------- - - [Inspectable(environment="none")] - - /** - * @private - */ - override public function get verticalScrollPolicy():String - { - return ScrollPolicy.OFF; - } - - /** - * @private - */ - override public function set verticalScrollPolicy(value:String):void - { - } - //-------------------------------------------------------------------------- // // Overridden methods @@ -1252,7 +1217,7 @@ package mx.controls else { _listDataProvider = null; - super.dataProvider = null; + vider = null; } } @@ -1649,11 +1614,14 @@ package mx.controls * @playerversion AIR 1.1 * @productversion Flex 3 */ - public function show(xShow:Object = null, yShow:Object = null):void + public function show(parent:IUIBase, xShow:Number = 0, yShow:Number = 0):void { - /*//this could be an empty menu so we'll return if it is - if (collection && collection.length == 0) - return; + if (parent is UIComponent) + parentDisplayObject = (parent as UIComponent); + + //this could be an empty menu so we'll return if it is + //if (collection && collection.length == 0) + // return; // If parent is closed, then don't show this submenu if (parentMenu && !parentMenu.visible) @@ -1663,12 +1631,13 @@ package mx.controls if (visible) return; - if (parentDisplayObject && (!parent || !parent.contains(parentDisplayObject))) + if (parentDisplayObject && (!parent /* || !parent.contains(parentDisplayObject)*/)) { PopUpManager.addPopUp(this, parentDisplayObject, false); - addEventListener(MenuEvent.MENU_HIDE, menuHideHandler, false, EventPriority.DEFAULT_HANDLER); + //addEventListener(MenuEvent.MENU_HIDE, menuHideHandler, false, EventPriority.DEFAULT_HANDLER); + MenuModel.menuList.push(this); } - + /* // Fire an event var menuEvent:MenuEvent = new MenuEvent(MenuEvent.MENU_SHOW); menuEvent.menu = this; @@ -1680,12 +1649,13 @@ package mx.controls IActiveWindowManager(systemManager.getImplementation("mx.managers::IActiveWindowManager")); awm.activate(this); + */ // Position it - if (xShow !== null && !isNaN(Number(xShow))) + if (/*xShow !== null && */!isNaN(Number(xShow))) x = Number(xShow); - if (yShow !== null && !isNaN(Number(yShow))) + if (/*yShow !== null && */!isNaN(Number(yShow))) y = Number(yShow); - + /* // Adjust for menus that extend out of bounds var sm:ISystemManager = systemManager.topLevelSystemManager; var sbRoot:UIComponent = sm.getSandboxRoot(); @@ -1711,8 +1681,9 @@ package mx.controls // Make sure the Menu's width and height has been determined // before we try to set the size for its mask UIComponentGlobals.layoutManager.validateClient(this, true); + */ setActualSize(getExplicitOrMeasuredWidth(), getExplicitOrMeasuredHeight()); - + /* cacheAsBitmap = true; var duration:Number = getStyle("openDuration"); @@ -1720,9 +1691,10 @@ package mx.controls { scrollRect = new Rectangle(0, 0, unscaledWidth, 0); + */ // Make it visible visible = true; - + /* UIComponentGlobals.layoutManager.validateNow(); // Block all layout, responses from web service, and other background @@ -2638,6 +2610,371 @@ package mx.controls return arr; } + //-------------------------------------------------------------------------- + // + // Methods: Item fields + // + //-------------------------------------------------------------------------- + + /** + * Returns the string the renderer would display for the given data object + * based on the labelField and labelFunction properties. + * If the method cannot convert the parameter to a string, it returns a + * single space. + * + * @param data Object to be rendered. + * + * @return The string to be displayed based on the data. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function itemToLabel(data:Object):String + { + if (data == null) + return " "; + + /* + if (labelFunction != null) + return labelFunction(data); + */ + + if (data is XML) + { + try + { + if ((data as XML)[labelField].length() != 0) + data = (data as XML)[labelField]; + //by popular demand, this is a default XML labelField + //else if ([email protected]() != 0) + // data = data.@label; + } + catch(e:Error) + { + } + } + else if (data is Object) + { + try + { + if (data[labelField] != null) + data = data[labelField]; + } + catch(e:Error) + { + } + } + + if (data is String) + return String(data); + + try + { + return data.toString(); + } + catch(e:Error) + { + } + + return " "; + } + + /* + * IItemRendererProvider + */ + + private var _itemRenderer:IFactory; + + /** + * The class or factory used to display each item. + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.0 + */ + public function get itemRenderer():IFactory + { + return _itemRenderer; + } + public function set itemRenderer(value:IFactory):void + { + _itemRenderer = value; + } + + //---------------------------------- + // labelField + //---------------------------------- + + [Bindable("labelFieldChanged")] + [Inspectable(category="Data", defaultValue="label")] + + /** + * The name of the field in the data provider items to display as the label. + * By default the list looks for a property named <code>label</code> + * on each item and displays it. + * However, if the data objects do not contain a <code>label</code> + * property, you can set the <code>labelField</code> property to + * use a different property in the data object. An example would be + * "FullName" when viewing a set of people names fetched from a database. + * + * @default "label" + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + * @royaleignorecoercion org.apache.royale.core.ISelectionModel + */ + public function get labelField():String + { + return (model as ISelectionModel).labelField; + } + + /** + * @private + * @royaleignorecoercion org.apache.royale.core.ISelectionModel + */ + public function set labelField(value:String):void + { + (model as ISelectionModel).labelField = value; + } + + //---------------------------------- + // rowHeight + //---------------------------------- + + /** + * @private + * Storage for the rowHeight property. + */ + private var _rowHeight:Number; + + /** + * @private + */ + private var rowHeightChanged:Boolean = false; + + [Inspectable(category="General")] + + /** + * The height of the rows in pixels. + * Unless the <code>variableRowHeight</code> property is + * <code>true</code>, all rows are the same height. + * If not specified, the row height is based on + * the font size and other properties of the renderer. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function get rowHeight():Number + { + return _rowHeight; + } + + /** + * @private + * @royaleignorecoercion org.apache.royale.core.IListPresentationModel + */ + public function set rowHeight(value:Number):void + { + //explicitRowHeight = value; + + if (_rowHeight != value) + { + _rowHeight = value; + + (presentationModel as IListPresentationModel).rowHeight = value; + /* + invalidateSize(); + itemsSizeChanged = true; + invalidateDisplayList(); + + dispatchEvent(new Event("rowHeightChanged")); + */ + } + } + + /** + * @private + */ + private var _presentationModel:IListPresentationModel; + + /** + * The DataGrid's presentation model + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.9 + * @royaleignorecoercion org.apache.royale.core.IListPresentationModel + * @royaleignorecoercion org.apache.royale.core.IBead + */ + public function get presentationModel():IBead + { + if (_presentationModel == null) { + var bead:IBead = getBeadByType(IListPresentationModel); + if (bead) + _presentationModel = bead as IListPresentationModel; + else + { + var c:Class = ValuesManager.valuesImpl.getValue(this, "iListPresentationModel"); + if (c) { + _presentationModel = new c() as IListPresentationModel; + addBead(_presentationModel as IBead); + } + } + } + + return _presentationModel; + } + + override public function addedToParent():void + { + super.addedToParent(); + + // Load the layout bead if it hasn't already been loaded. + loadBeadFromValuesManager(IBeadLayout, "iBeadLayout", this); + + // Even though super.addedToParent dispatched "beadsAdded", DataContainer still needs its data mapper + // and item factory beads. These beads are added after super.addedToParent is called in case substitutions + // were made; these are just defaults extracted from CSS. + loadBeadFromValuesManager(IDataProviderItemRendererMapper, "iDataProviderItemRendererMapper", this); + loadBeadFromValuesManager(IItemRendererClassFactory, "iItemRendererClassFactory", this); + + dispatchEvent(new Event("initComplete")); + } + + /** + * Returns the ILayoutHost which is its view. From ILayoutParent. + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.8 + * @royaleignorecoercion org.apache.royale.core.ILayoutHost + */ + public function getLayoutHost():ILayoutHost + { + return view as ILayoutHost; + } + + //---------------------------------- + // selectedIndex + //---------------------------------- + + [Bindable("change")] + [Bindable("valueCommit")] + [Inspectable(category="General", defaultValue="-1")] + + /** + * The index in the data provider of the selected item. + * + * <p>The default value is -1 (no selected item).</p> + * + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + * @royaleignorecoercion org.apache.royale.core.ISelectionModel + */ + public function get selectedIndex():int + { + return (model as ISelectionModel).selectedIndex; + } + + /** + * @private + * @royaleignorecoercion org.apache.royale.core.ISelectionModel + */ + public function set selectedIndex(value:int):void + { + // if (!collection || collection.length == 0) + // { + (model as ISelectionModel).selectedIndex = value; + // bSelectionChanged = true; + // bSelectedIndexChanged = true; + // invalidateDisplayList(); + return; + // } + //commitSelectedIndex(value); + } + + //---------------------------------- + // selectedItem + //---------------------------------- + + [Bindable("change")] + [Bindable("valueCommit")] + + /** + * The selected item in the data provider. + * + * @langversion 3.0 + * @playerversion Flash 9 + * @playerversion AIR 1.1 + * @productversion Flex 3 + */ + public function get selectedItem():Object + { + return (model as ISelectionModel).selectedItem; + } + + /** + * @private + */ + public function set selectedItem(item:Object):void + { + (model as ISelectionModel).selectedItem = item; + } + + private var _parentMenuBar:IEventDispatcher; + + /** + * @private + * + * If this menu is used as part of a menu bar system, this property should reference + * that menu bar. If this property is set, the "change" event is dispatched against this + * object rather than the Menu itself. + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.9 + */ + public function get parentMenuBar():IEventDispatcher + { + return _parentMenuBar; + } + public function set parentMenuBar(value:IEventDispatcher):void + { + _parentMenuBar = value; + } + + /** + * The name of the field to use in the data that indicates a sub-menu. The + * default value is "menu". + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.9 + */ + public function get submenuField():String + { + return (model as CascadingMenuModel).submenuField; + } + + public function set submenuField(value:String):void + { + (model as CascadingMenuModel).submenuField = value; + } + } } diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/beads/models/CascadingMenuModel.as b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/beads/models/CascadingMenuModel.as new file mode 100644 index 0000000..2110d82 --- /dev/null +++ b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/beads/models/CascadingMenuModel.as @@ -0,0 +1,107 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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.models +{ + import org.apache.royale.core.IStrand; + import org.apache.royale.core.ICascadingMenuModel; + import org.apache.royale.events.Event; + + public class CascadingMenuModel extends SingleSelectionICollectionViewModel implements ICascadingMenuModel + { + public function CascadingMenuModel() + { + super(); + } + + private var _strand:IStrand; + override public function set strand(value:IStrand):void + { + _strand = value; + super.strand = value; + } + + private static var _menuList:Array = []; + + /** + * The array of active IMenu instances. This list is maintained so that any of the + * instances can close all of them. Imagine several cascading menus open the user + * selects one of the items. That menu uses this array to close itself and the others. + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.9 + */ + public static function get menuList():Array + { + return _menuList; + } + + /** + * Empties the menuList. + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.9 + */ + public static function clearMenuList():void + { + _menuList = []; + } + + /** + * Removes a specific menu from the menuList. + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.9 + */ + public static function removeMenu(menu:Object):void + { + for(var i:int=0; i < menuList.length; i++) { + if (menuList[i] == menu) { + menuList.splice(i,1); + break; + } + } + } + + private var _submenuField:String = "menu"; + + /** + * The field in the data object that identifies sub-menus. The default is "menu". + * + * @langversion 3.0 + * @playerversion Flash 10.2 + * @playerversion AIR 2.6 + * @productversion Royale 0.9 + */ + public function get submenuField():String + { + return _submenuField; + } + public function set submenuField(value:String):void + { + _submenuField = value; + dispatchEvent(new Event("submenuFieldChanged")); + } + } +} \ No newline at end of file diff --git a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/listClasses/ListBase.as b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/listClasses/ListBase.as index 12dd221..232b5b0 100644 --- a/frameworks/projects/MXRoyale/src/main/royale/mx/controls/listClasses/ListBase.as +++ b/frameworks/projects/MXRoyale/src/main/royale/mx/controls/listClasses/ListBase.as @@ -386,7 +386,7 @@ use namespace mx_internal; _labelFunction = value; } - //---------------------------------- + //---------------------------------- // selectedIndex //----------------------------------
