From d9df28a02c7e95906d460f26204d8379a35c959c Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Mon, 14 Apr 2014 20:51:48 +0400 Subject: [PATCH] menus --- src/dlangui/platforms/common/platform.d | 3 +- src/dlangui/widgets/lists.d | 67 +++++++++++++++++++++++-- src/dlangui/widgets/menu.d | 8 ++- src/dlangui/widgets/styles.d | 3 +- 4 files changed, 72 insertions(+), 9 deletions(-) diff --git a/src/dlangui/platforms/common/platform.d b/src/dlangui/platforms/common/platform.d index 55bfc758..9390401d 100644 --- a/src/dlangui/platforms/common/platform.d +++ b/src/dlangui/platforms/common/platform.d @@ -338,7 +338,8 @@ class Window { processed = checkRemoveTracking(event); } if (!res) { - foreach(p; _popups) { + for (int i = cast(int)_popups.length - 1; i >= 0; i--) { + auto p = _popups[i]; if (dispatchMouseEvent(p, event)) return true; } diff --git a/src/dlangui/widgets/lists.d b/src/dlangui/widgets/lists.d index 63128c17..16edece2 100644 --- a/src/dlangui/widgets/lists.d +++ b/src/dlangui/widgets/lists.d @@ -9,6 +9,12 @@ interface ListAdapter { @property int itemCount(); /// return list item widget by item index Widget itemWidget(int index); + /// return list item's state flags + uint itemState(int index); + /// set one or more list item's state flags, returns updated state + uint setItemState(int index, uint flags); + /// reset one or more list item's state flags, returns updated state + uint resetItemState(int index, uint flags); } /// List adapter for simple list of widget instances @@ -24,6 +30,18 @@ class WidgetListAdapter : ListAdapter { override Widget itemWidget(int index) { return _widgets.get(index); } + /// return list item's state flags + override uint itemState(int index) { + return _widgets.get(index).state; + } + /// set one or more list item's state flags, returns updated state + override uint setItemState(int index, uint flags) { + return _widgets.get(index).setState(flags).state; + } + /// reset one or more list item's state flags, returns updated state + override uint resetItemState(int index, uint flags) { + return _widgets.get(index).resetState(flags).state; + } } /// List @@ -57,6 +75,10 @@ class ListWidget : WidgetGroup, OnScrollHandler { protected Rect _clientRc; /// total height of all items for Vertical orientation, or width for Horizontal protected int _totalSize; + /// item with Hover state, -1 if no such item + protected int _hoverItemIndex; + /// item with Selected state, -1 if no such item + protected int _selectedItemIndex; /// returns rectangle for item (not scrolled, first item starts at 0,0) Rect itemRectNoScroll(int index) { @@ -129,12 +151,42 @@ class ListWidget : WidgetGroup, OnScrollHandler { this(string ID = null, Orientation orientation = Orientation.Vertical) { super(ID); _orientation = orientation; + _hoverItemIndex = -1; + _selectedItemIndex = -1; _scrollbar = new ScrollBar("listscroll", orientation); _scrollbar.visibility = Visibility.Gone; _scrollbar.onScrollEventListener = &onScrollEvent; addChild(_scrollbar); } + protected void setHoverItem(int index) { + if (_hoverItemIndex == index) + return; + if (_hoverItemIndex != -1) { + _adapter.resetItemState(_hoverItemIndex, State.Hovered); + invalidate(); + } + _hoverItemIndex = index; + if (_hoverItemIndex != -1) { + _adapter.setItemState(_hoverItemIndex, State.Hovered); + invalidate(); + } + } + + protected void selectItem(int index) { + if (_selectedItemIndex == index) + return; + if (_selectedItemIndex != -1) { + _adapter.resetItemState(_selectedItemIndex, State.Selected); + invalidate(); + } + _selectedItemIndex = index; + if (_selectedItemIndex != -1) { + _adapter.setItemState(_selectedItemIndex, State.Selected); + invalidate(); + } + } + ~this() { if (_adapter !is null && _ownAdapter) destroy(_adapter); @@ -402,6 +454,10 @@ class ListWidget : WidgetGroup, OnScrollHandler { /// process mouse event; return true if event is processed by widget. override bool onMouseEvent(MouseEvent event) { Log.d("onMouseEvent ", id, " ", event.action, " (", event.x, ",", event.y, ")"); + if (event.action == MouseAction.Leave || event.action == MouseAction.Cancel) { + setHoverItem(-1); + return true; + } // support onClick Rect rc = _pos; applyMargins(rc); @@ -419,13 +475,14 @@ class ListWidget : WidgetGroup, OnScrollHandler { itemrc.top += rc.top - scrollOffset.y; itemrc.bottom += rc.top - scrollOffset.y; if (itemrc.isPointInside(Point(event.x, event.y))) { - Widget w = itemWidget(i); - if (w.onMouseEvent(event)) { - return true; - } + if (event.flags & (MouseFlag.LButton || MouseFlag.RButton)) { + selectItem(i); + setHoverItem(-1); + } else + setHoverItem(i); } } - return super.onMouseEvent(event); + return true; } } diff --git a/src/dlangui/widgets/menu.d b/src/dlangui/widgets/menu.d index 0b48391c..ee2e2d56 100644 --- a/src/dlangui/widgets/menu.d +++ b/src/dlangui/widgets/menu.d @@ -84,12 +84,12 @@ class MenuItemWidget : HorizontalLayout { // support onClick if (_handler !is null) { if (event.action == MouseAction.ButtonDown && event.button == MouseButton.Left) { - setState(State.Pressed); + setState(State.Selected); _handler.onItemMouseDown(this, event); return true; } if (event.action == MouseAction.ButtonUp && event.button == MouseButton.Left) { - resetState(State.Pressed); + resetState(State.Selected); _handler.onItemMouseDown(this, event); return true; } @@ -117,6 +117,10 @@ class MenuItemWidget : HorizontalLayout { class MainMenu : HorizontalLayout, MenuItemWidgetHandler { protected MenuItem _item; + protected PopupWidget _openedPopup; + protected MenuItemWidget _openedMenu; + + override protected bool onItemMouseDown(MenuItemWidget itemWidget, MouseEvent ev) { PopupMenu popupMenu = new PopupMenu(itemWidget.item); diff --git a/src/dlangui/widgets/styles.d b/src/dlangui/widgets/styles.d index 173f1046..12136301 100644 --- a/src/dlangui/widgets/styles.d +++ b/src/dlangui/widgets/styles.d @@ -668,7 +668,8 @@ Theme createDefaultTheme() { Style menuItem = res.createSubstyle("MENU_ITEM").padding(Rect(4,2,4,2)); //.backgroundColor(0xE0E080) ; menuItem.createState(State.Focused, State.Focused).backgroundColor(0x40C0C000); menuItem.createState(State.Pressed, State.Pressed).backgroundColor(0x4080C000); - menuItem.createState(State.Hovered, State.Hovered).backgroundColor(0x80FFFF00); + menuItem.createState(State.Selected, State.Selected).backgroundColor(0x40FFFF00); + menuItem.createState(State.Hovered, State.Hovered).backgroundColor(0xC0FFFF00); Style poopupMenu = res.createSubstyle("POPUP_MENU").backgroundImageId("btn_default_small");