mirror of https://github.com/buggins/dlangui.git
205 lines
6.1 KiB
D
205 lines
6.1 KiB
D
module dlangui.widgets.menu;
|
|
|
|
import dlangui.core.events;
|
|
import dlangui.widgets.controls;
|
|
import dlangui.widgets.layouts;
|
|
import dlangui.widgets.lists;
|
|
import dlangui.widgets.popup;
|
|
|
|
/// menu item properties
|
|
class MenuItem {
|
|
protected bool _checkable;
|
|
protected bool _checked;
|
|
protected bool _enabled;
|
|
protected Action _action;
|
|
protected MenuItem[] _subitems;
|
|
/// item action id, 0 if no action
|
|
@property int id() { return _action is null ? 0 : _action.id; }
|
|
/// returns count of submenu items
|
|
@property int subitemCount() {
|
|
return cast(int)_subitems.length;
|
|
}
|
|
/// returns submenu item by index
|
|
MenuItem subitem(int index) {
|
|
return _subitems[index];
|
|
}
|
|
/// adds submenu item
|
|
MenuItem add(MenuItem subitem) {
|
|
_subitems ~= subitem;
|
|
return this;
|
|
}
|
|
/// adds submenu item from action
|
|
MenuItem add(Action subitemAction) {
|
|
_subitems ~= new MenuItem(subitemAction);
|
|
return this;
|
|
}
|
|
/// returns true if item is submenu (contains subitems)
|
|
@property bool isSubmenu() {
|
|
return _subitems.length > 0;
|
|
}
|
|
/// returns item label
|
|
@property UIString label() {
|
|
return _action.labelValue;
|
|
}
|
|
/// returns item action
|
|
@property const(Action) action() const { return _action; }
|
|
/// sets item action
|
|
@property MenuItem action(Action a) { _action = a; return this; }
|
|
this() {
|
|
_enabled = true;
|
|
}
|
|
this(Action action) {
|
|
_action = action;
|
|
_enabled = true;
|
|
}
|
|
~this() {
|
|
// TODO
|
|
}
|
|
}
|
|
|
|
/// widget to draw menu item
|
|
class MenuItemWidget : HorizontalLayout {
|
|
protected MenuItem _item;
|
|
protected TextWidget _label;
|
|
@property MenuItem item() { return _item; }
|
|
this(MenuItem item) {
|
|
id="menuitem";
|
|
_item = item;
|
|
styleId = "MENU_ITEM";
|
|
_label = new TextWidget("MENU_LABEL");
|
|
_label.text = _item.label;
|
|
addChild(_label);
|
|
trackHover = true;
|
|
}
|
|
}
|
|
|
|
/// base class for menus
|
|
class MenuWidgetBase : ListWidget {
|
|
protected MenuWidgetBase _parentMenu;
|
|
protected MenuItem _item;
|
|
protected PopupMenu _openedMenu;
|
|
protected PopupWidget _openedPopup;
|
|
protected bool delegate(MenuItem item) _onMenuItemClickListener;
|
|
/// menu item click listener
|
|
@property bool delegate(MenuItem item) onMenuItemListener() { return _onMenuItemClickListener; }
|
|
/// menu item click listener
|
|
@property MenuWidgetBase onMenuItemListener(bool delegate(MenuItem item) listener) { _onMenuItemClickListener = listener; return this; }
|
|
|
|
this(MenuWidgetBase parentMenu, MenuItem item, Orientation orientation) {
|
|
_parentMenu = parentMenu;
|
|
_item = item;
|
|
this.orientation = orientation;
|
|
id = "popup_menu";
|
|
styleId = "POPUP_MENU";
|
|
WidgetListAdapter adapter = new WidgetListAdapter();
|
|
for (int i=0; i < _item.subitemCount; i++) {
|
|
MenuItem subitem = _item.subitem(i);
|
|
MenuItemWidget widget = new MenuItemWidget(subitem);
|
|
if (orientation == Orientation.Horizontal)
|
|
widget.styleId = "MAIN_MENU_ITEM";
|
|
adapter.widgets.add(widget);
|
|
}
|
|
ownAdapter = adapter;
|
|
}
|
|
|
|
protected void onPopupClosed(PopupWidget p) {
|
|
_openedPopup = null;
|
|
_openedMenu = null;
|
|
selectItem(-1);
|
|
}
|
|
|
|
protected void openSubmenu(MenuItemWidget itemWidget) {
|
|
if (_openedPopup !is null) {
|
|
_openedPopup.close();
|
|
}
|
|
PopupMenu popupMenu = new PopupMenu(itemWidget.item, this);
|
|
PopupWidget popup = window.showPopup(popupMenu, itemWidget, orientation == Orientation.Horizontal ? PopupAlign.Below : PopupAlign.Right);
|
|
popup.onPopupCloseListener = &onPopupClosed;
|
|
popup.flags = PopupFlags.CloseOnClickOutside;
|
|
_openedPopup = popup;
|
|
_openedMenu = popupMenu;
|
|
}
|
|
|
|
/// override to handle change of selection
|
|
override protected void selectionChanged(int index, int previouslySelectedItem = -1) {
|
|
MenuItemWidget itemWidget = index >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(index) : null;
|
|
if (itemWidget !is null) {
|
|
if (itemWidget.item.isSubmenu()) {
|
|
if (_selectOnHover) {
|
|
openSubmenu(itemWidget);
|
|
}
|
|
} else {
|
|
// normal item
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void onMenuItem(MenuItem item) {
|
|
if (_openedPopup !is null) {
|
|
_openedPopup.close();
|
|
_openedPopup = null;
|
|
}
|
|
if (_parentMenu !is null)
|
|
_parentMenu.onMenuItem(item);
|
|
else {
|
|
// top level handling
|
|
Log.d("onMenuItem ", item.id);
|
|
selectItem(-1);
|
|
selectOnHover = false;
|
|
bool delegate(MenuItem item) listener = _onMenuItemClickListener;
|
|
PopupWidget popup = cast(PopupWidget)parent;
|
|
if (popup)
|
|
popup.close();
|
|
// this pointer now can be invalid - if popup removed
|
|
if (listener !is null)
|
|
listener(item);
|
|
}
|
|
}
|
|
|
|
/// override to handle mouse up on item
|
|
override protected void itemClicked(int index) {
|
|
MenuItemWidget itemWidget = index >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(index) : null;
|
|
if (itemWidget !is null) {
|
|
Log.d("Menu Item clicked ", itemWidget.item.action.id);
|
|
if (itemWidget.item.isSubmenu()) {
|
|
// submenu clicked
|
|
if (_clickOnButtonDown && _openedPopup !is null && _openedMenu._item is itemWidget.item) {
|
|
// second click on main menu opened item
|
|
_openedPopup.close();
|
|
_openedPopup = null;
|
|
selectItem(-1);
|
|
selectOnHover = false;
|
|
} else {
|
|
openSubmenu(itemWidget);
|
|
selectOnHover = true;
|
|
}
|
|
} else {
|
|
// normal item
|
|
onMenuItem(itemWidget.item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// main menu (horizontal)
|
|
class MainMenu : MenuWidgetBase {
|
|
|
|
this(MenuItem item) {
|
|
super(null, item, Orientation.Horizontal);
|
|
id = "MAIN_MENU";
|
|
styleId = "MAIN_MENU";
|
|
_clickOnButtonDown = true;
|
|
}
|
|
}
|
|
|
|
/// popup menu widget (vertical layout of items)
|
|
class PopupMenu : MenuWidgetBase {
|
|
|
|
this(MenuItem item, MenuWidgetBase parentMenu = null) {
|
|
super(parentMenu, item, Orientation.Vertical);
|
|
id = "POPUP_MENU";
|
|
styleId = "POPUP_MENU";
|
|
selectOnHover = true;
|
|
}
|
|
}
|