diff --git a/haxe/ui/containers/menus/Menu.hx b/haxe/ui/containers/menus/Menu.hx index dc9cf84ad..dd1bb16a7 100644 --- a/haxe/ui/containers/menus/Menu.hx +++ b/haxe/ui/containers/menus/Menu.hx @@ -1,5 +1,8 @@ package haxe.ui.containers.menus; +import haxe.ui.util.Timer; +import haxe.ui.util.Variant; +import haxe.ui.behaviours.DataBehaviour; import haxe.ui.behaviours.DefaultBehaviour; import haxe.ui.components.Button; import haxe.ui.components.Label; @@ -21,7 +24,9 @@ import Std.is as isOfType; @:composite(MenuEvents, Builder, Layout) class Menu extends Box { - @:behaviour(DefaultBehaviour) public var menuStyleNames:String; + @:behaviour(DefaultBehaviour) public var menuStyleNames:String; + @:behaviour(CurrentIndexBehaviour, 0) public var currentIndex:Int; + @:behaviour(CurrentItemBehaviour) public var currentItem:MenuItem; /** Utility property to add a single `MenuEvent.MENU_SELECTED` event @@ -39,6 +44,48 @@ class Menu extends Box { // Behaviours //*********************************************************************************************************** +@:dox(hide) @:noCompletion +@:access(haxe.ui.core.Component) +private class CurrentIndexBehaviour extends DataBehaviour { + + public override function set(value:Variant) { + var _menu:Menu = cast _component; + var itemsNbr = _menu.findComponents(MenuItem, 1).length; + if (value >= itemsNbr) { + value = 0; + } + super.set(value); + } + + private override function validateData() { + var _menu:Menu = cast _component; + var items = _menu.findComponents(MenuItem, 1); + var itemNbr:Int = _value; + _menu.currentItem = items[itemNbr]; + } +} + +@:dox(hide) @:noCompletion +@:access(haxe.ui.core.Component) +private class CurrentItemBehaviour extends DataBehaviour { + + private override function validateData() { + var _menu:Menu = cast _component; + var menuItemC:Component = _value; + var menuItem:MenuItem = cast menuItemC; + var index = _menu.findComponents(MenuItem, 1).indexOf(menuItem); + _menu.currentIndex = index; + + for (child in _menu.childComponents) { + child.removeClass(":hover", true, true); + } + + var item:Component = _value; + if (item != null) item.addClass(":hover", true, true); + } +} + + //*********************************************************************************************************** // Events //*********************************************************************************************************** @@ -47,10 +94,12 @@ class Menu extends Box { @:access(haxe.ui.containers.menus.Builder) class MenuEvents extends haxe.ui.events.Events { private var _menu:Menu; - private var _currentItem:MenuItem = null; public var currentSubMenu:Menu = null; public var parentMenu:Menu = null; + private static inline var TIME_MOUSE_OPENS_MS:Int =400; + private var _timer:Timer = null; + public var button:Button = null; public function new(menu:Menu) { @@ -142,15 +191,39 @@ class MenuEvents extends haxe.ui.events.Events { } } + if (parentMenu != null) { + // so that's is always the parent menu that is visually selected + // even if you have previously hovered over parent's siblings. + var menuItem:MenuItem = null; + for (mi => menu in cast(parentMenu._compositeBuilder, Builder)._subMenus) { + if (_menu == menu) menuItem = mi; + } + parentMenu.currentItem = menuItem; + } + + if (_timer != null) { + _timer.stop(); + _timer = null; + } if (subMenus.get(item) != null) { - _currentItem = item; - showSubMenu(cast(subMenus.get(item), Menu), item); + _menu.currentItem = item; lastEventSubMenu = event; + _timer = new Timer(TIME_MOUSE_OPENS_MS, function f() { + showSubMenu(cast(subMenus.get(item), Menu), item); + _timer.stop(); + _timer = null; + }); } else { if (currentSubMenu != null) { if (!isMouseAimingForSubMenu(event)) { hideCurrentSubMenu(); lastEventSubMenu = null; + } else { + _timer = new Timer(TIME_MOUSE_OPENS_MS, function f() { + hideCurrentSubMenu(); + _timer.stop(); + _timer = null; + }); } lastEventSubMenu = event; } @@ -185,11 +258,15 @@ class MenuEvents extends haxe.ui.events.Events { } private function onItemMouseOut(event:MouseEvent) { + if (_timer != null) { + _timer.stop(); + _timer = null; + } if (currentSubMenu != null) { - _currentItem.addClass(":hover", true, true); + _menu.currentItem.addClass(":hover", true, true); return; } else { - _currentItem = null; + _menu.currentItem = null; } }