menu is working

This commit is contained in:
Vadim Lopatin 2014-04-14 23:25:24 +04:00
parent a8ddcd9c4f
commit fb0e1b6c6b
4 changed files with 104 additions and 24 deletions

View File

@ -134,6 +134,7 @@ class MouseEvent {
protected ButtonDetails _lbutton;
protected ButtonDetails _mbutton;
protected ButtonDetails _rbutton;
protected bool _doNotTrackButtonDown;
@property ref ButtonDetails lbutton() { return _lbutton; }
@property ref ButtonDetails rbutton() { return _rbutton; }
@property ref ButtonDetails mbutton() { return _mbutton; }
@ -146,6 +147,8 @@ class MouseEvent {
@property short y() { return _y; }
/// get event tracking widget to override
@property Widget trackingWidget() { return _trackingWidget; }
@property bool doNotTrackButtonDown() { return _doNotTrackButtonDown; }
@property void doNotTrackButtonDown(bool flg) { _doNotTrackButtonDown = flg; }
/// override mouse tracking widget
void track(Widget w) {
_trackingWidget = w;

View File

@ -191,7 +191,7 @@ class Window {
// if not processed by children, offer event to root
if (sendAndCheckOverride(root, event)) {
Log.d("MouseEvent is processed");
if (event.action == MouseAction.ButtonDown && _mouseCaptureWidget is null) {
if (event.action == MouseAction.ButtonDown && _mouseCaptureWidget is null && !event.doNotTrackButtonDown) {
Log.d("Setting active widget");
setCaptureWidget(root, event);
} else if (event.action == MouseAction.Move) {
@ -263,6 +263,8 @@ class Window {
}
protected bool sendAndCheckOverride(Widget widget, MouseEvent event) {
if (!isChild(widget))
return false;
bool res = widget.onMouseEvent(event);
if (event.trackingWidget !is null && _mouseCaptureWidget !is event.trackingWidget) {
setCaptureWidget(event.trackingWidget, event);

View File

@ -87,6 +87,9 @@ class ListWidget : WidgetGroup, OnScrollHandler {
/// when true, mouse hover selects underlying item
@property ListWidget selectOnHover(bool select) { _selectOnHover = select; return this; }
/// if true, generate itemClicked on mouse down instead mouse up event
protected bool _clickOnButtonDown;
/// returns rectangle for item (not scrolled, first item starts at 0,0)
Rect itemRectNoScroll(int index) {
Rect res;
@ -183,6 +186,9 @@ class ListWidget : WidgetGroup, OnScrollHandler {
/// override to handle change of selection
protected void selectionChanged(int index, int previouslySelectedItem = -1, MouseEvent event = null) {
}
/// override to handle mouse up on item
protected void itemClicked(int index) {
}
protected void selectItem(int index) {
if (_selectedItemIndex == index)
@ -487,14 +493,22 @@ class ListWidget : WidgetGroup, OnScrollHandler {
itemrc.bottom += rc.top - scrollOffset.y;
if (itemrc.isPointInside(Point(event.x, event.y))) {
if ((event.flags & (MouseFlag.LButton || MouseFlag.RButton)) || _selectOnHover) {
if (_selectedItemIndex == i)
return true;
int prevSelection = _selectedItemIndex;
selectItem(i);
setHoverItem(-1);
selectionChanged(_selectedItemIndex, prevSelection, event);
if (_selectedItemIndex != i) {
int prevSelection = _selectedItemIndex;
selectItem(i);
setHoverItem(-1);
selectionChanged(_selectedItemIndex, prevSelection, event);
}
} else
setHoverItem(i);
if ((event.button == MouseFlag.LButton || event.button == MouseFlag.RButton)) {
if ((_clickOnButtonDown && event.action == MouseAction.ButtonDown) || (!_clickOnButtonDown && event.action == MouseAction.ButtonUp)) {
itemClicked(i);
if (_clickOnButtonDown)
event.doNotTrackButtonDown = true;
}
}
return true;
}
}
return true;

View File

@ -80,11 +80,13 @@ class MenuItemWidget : HorizontalLayout {
}
class MenuWidgetBase : ListWidget {
protected MenuWidgetBase _parentMenu;
protected MenuItem _item;
protected PopupMenu _openedMenu;
protected PopupWidget _openedPopup;
this(MenuItem item, Orientation orientation) {
this(MenuWidgetBase parentMenu, MenuItem item, Orientation orientation) {
_parentMenu = parentMenu;
_item = item;
this.orientation = orientation;
id = "popup_menu";
@ -99,39 +101,98 @@ class MenuWidgetBase : ListWidget {
ownAdapter = adapter;
}
protected void openSubmenu(MenuItemWidget itemWidget) {
if (_openedPopup !is null)
_openedPopup.close();
PopupMenu popupMenu = new PopupMenu(itemWidget.item, this);
PopupWidget popup = window.showPopup(popupMenu, itemWidget, PopupAlign.Below);
//if (event !is null && (event.flags & (MouseFlag.LButton || MouseFlag.RButton)))
// event.track(popupMenu);
_openedPopup = popup;
_openedMenu = popupMenu;
}
/// override to handle change of selection
override protected void selectionChanged(int index, int previouslySelectedItem = -1, MouseEvent event = null) {
MenuItemWidget itemWidget = index >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(index) : null;
if (itemWidget.item.isSubmenu()) {
if (_openedPopup !is null)
_openedPopup.close();
PopupMenu popupMenu = new PopupMenu(itemWidget.item);
PopupWidget popup = window.showPopup(popupMenu, itemWidget, PopupAlign.Below);
if (event !is null && (event.flags & (MouseFlag.LButton || MouseFlag.RButton)))
event.track(popupMenu);
_openedPopup = popup;
_openedMenu = popupMenu;
selectOnHover = true;
} else {
// normal item
}
if (itemWidget !is null) {
if (itemWidget.item.isSubmenu()) {
if (_selectOnHover) {
openSubmenu(itemWidget);
}
} else {
// normal item
}
}
}
protected bool delegate(MenuItem item) _onMenuItemClickListener;
@property bool delegate(MenuItem item) onMenuItemListener() { return _onMenuItemClickListener; }
@property MenuWidgetBase onMenuItemListener(bool delegate(MenuItem item) listener) { _onMenuItemClickListener = listener; return this; }
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);
}
}
}
}
class MainMenu : MenuWidgetBase {
this(MenuItem item) {
super(item, Orientation.Horizontal);
super(null, item, Orientation.Horizontal);
id = "MAIN_MENU";
styleId = "MAIN_MENU";
_clickOnButtonDown = true;
}
}
class PopupMenu : MenuWidgetBase {
this(MenuItem item) {
super(item, Orientation.Vertical);
this(MenuItem item, MenuWidgetBase parentMenu = null) {
super(parentMenu, item, Orientation.Vertical);
id = "POPUP_MENU";
styleId = "POPUP_MENU";
selectOnHover = true;