menu refactoring

This commit is contained in:
Vadim Lopatin 2014-04-14 21:53:53 +04:00
parent d9df28a02c
commit a8ddcd9c4f
5 changed files with 69 additions and 93 deletions

View File

@ -54,10 +54,19 @@ extern (C) int UIAppMain(string[] args) {
fileItem.add(new Action(10, "Open..."d)); fileItem.add(new Action(10, "Open..."d));
fileItem.add(new Action(11, "Save..."d)); fileItem.add(new Action(11, "Save..."d));
fileItem.add(new Action(12, "Exit"d)); fileItem.add(new Action(12, "Exit"d));
MenuItem editItem = new MenuItem(new Action(2, "Edit"d));
editItem.add(new Action(20, "Copy"d));
editItem.add(new Action(21, "Paste"d));
editItem.add(new Action(22, "Cut"d));
MenuItem windowItem = new MenuItem(new Action(3, "Window"d));
windowItem.add(new Action(30, "Preferences"d));
MenuItem helpItem = new MenuItem(new Action(4, "Help"d));
helpItem.add(new Action(40, "View Help"d));
helpItem.add(new Action(41, "About"d));
mainMenuItems.add(fileItem); mainMenuItems.add(fileItem);
mainMenuItems.add(new Action(2, "Edit"d)); mainMenuItems.add(editItem);
mainMenuItems.add(new Action(3, "Window"d)); mainMenuItems.add(windowItem);
mainMenuItems.add(new Action(4, "Help"d)); mainMenuItems.add(helpItem);
MainMenu mainMenu = new MainMenu(mainMenuItems); MainMenu mainMenu = new MainMenu(mainMenuItems);
contentLayout.addChild(mainMenu); contentLayout.addChild(mainMenu);

View File

@ -418,6 +418,7 @@ class Win32Window : Window {
/// request window redraw /// request window redraw
override void invalidate() { override void invalidate() {
InvalidateRect(_hwnd, null, FALSE); InvalidateRect(_hwnd, null, FALSE);
UpdateWindow(_hwnd);
} }
/// after drawing, call to schedule redraw if animation is active /// after drawing, call to schedule redraw if animation is active

View File

@ -80,6 +80,13 @@ class ListWidget : WidgetGroup, OnScrollHandler {
/// item with Selected state, -1 if no such item /// item with Selected state, -1 if no such item
protected int _selectedItemIndex; protected int _selectedItemIndex;
/// when true, mouse hover selects underlying item
protected bool _selectOnHover;
/// when true, mouse hover selects underlying item
@property bool selectOnHover() { return _selectOnHover; }
/// when true, mouse hover selects underlying item
@property ListWidget selectOnHover(bool select) { _selectOnHover = select; return this; }
/// returns rectangle for item (not scrolled, first item starts at 0,0) /// returns rectangle for item (not scrolled, first item starts at 0,0)
Rect itemRectNoScroll(int index) { Rect itemRectNoScroll(int index) {
Rect res; Rect res;
@ -173,6 +180,10 @@ class ListWidget : WidgetGroup, OnScrollHandler {
} }
} }
/// override to handle change of selection
protected void selectionChanged(int index, int previouslySelectedItem = -1, MouseEvent event = null) {
}
protected void selectItem(int index) { protected void selectItem(int index) {
if (_selectedItemIndex == index) if (_selectedItemIndex == index)
return; return;
@ -475,9 +486,13 @@ class ListWidget : WidgetGroup, OnScrollHandler {
itemrc.top += rc.top - scrollOffset.y; itemrc.top += rc.top - scrollOffset.y;
itemrc.bottom += rc.top - scrollOffset.y; itemrc.bottom += rc.top - scrollOffset.y;
if (itemrc.isPointInside(Point(event.x, event.y))) { if (itemrc.isPointInside(Point(event.x, event.y))) {
if (event.flags & (MouseFlag.LButton || MouseFlag.RButton)) { if ((event.flags & (MouseFlag.LButton || MouseFlag.RButton)) || _selectOnHover) {
if (_selectedItemIndex == i)
return true;
int prevSelection = _selectedItemIndex;
selectItem(i); selectItem(i);
setHoverItem(-1); setHoverItem(-1);
selectionChanged(_selectedItemIndex, prevSelection, event);
} else } else
setHoverItem(i); setHoverItem(i);
} }

View File

@ -77,117 +77,64 @@ class MenuItemWidget : HorizontalLayout {
addChild(_label); addChild(_label);
trackHover = true; trackHover = true;
} }
/// 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, ")");
// support onClick
if (_handler !is null) {
if (event.action == MouseAction.ButtonDown && event.button == MouseButton.Left) {
setState(State.Selected);
_handler.onItemMouseDown(this, event);
return true;
}
if (event.action == MouseAction.ButtonUp && event.button == MouseButton.Left) {
resetState(State.Selected);
_handler.onItemMouseDown(this, event);
return true;
}
/*
if (event.action == MouseAction.ButtonUp && event.button == MouseButton.Left) {
resetState(State.Pressed);
_onClickListener(this);
return true;
}
if (event.action == MouseAction.FocusOut || event.action == MouseAction.Cancel) {
resetState(State.Pressed);
resetState(State.Hovered);
return true;
}
if (event.action == MouseAction.FocusIn) {
setState(State.Pressed);
return true;
}
*/
}
return super.onMouseEvent(event);
}
} }
class MainMenu : HorizontalLayout, MenuItemWidgetHandler { class MenuWidgetBase : ListWidget {
protected MenuItem _item; protected MenuItem _item;
protected PopupMenu _openedMenu;
protected PopupWidget _openedPopup; protected PopupWidget _openedPopup;
protected MenuItemWidget _openedMenu;
this(MenuItem item, Orientation orientation) {
override protected bool onItemMouseDown(MenuItemWidget itemWidget, MouseEvent ev) {
PopupMenu popupMenu = new PopupMenu(itemWidget.item);
PopupWidget popup = window.showPopup(popupMenu, itemWidget, PopupAlign.Below);
ev.track(popupMenu);
return true;
}
override protected bool onItemMouseUp(MenuItemWidget itemWidget, MouseEvent ev) {
return true;
}
/*
protected bool onItemClick(Widget w) {
MenuItemWidget itemWidget = cast(MenuItemWidget)w;
Log.d("onItemClick ", w.id);
window.showPopup(new PopupMenu(itemWidget.item), itemWidget, PopupAlign.Below);
return true;
}
*/
this(MenuItem item) {
id = "MAIN_MENU";
styleId = "MAIN_MENU";
_item = item; _item = item;
for (int i = 0; i < item.subitemCount; i++) { this.orientation = orientation;
MenuItemWidget subitem = new MenuItemWidget(item.subitem(i));
//subitem.onClickListener = &onItemClick;
subitem.handler = this;
addChild(subitem);
}
addChild((new Widget()).layoutWidth(FILL_PARENT));
}
}
class PopupMenu : ListWidget, MenuItemWidgetHandler {
protected MenuItem _item;
this(MenuItem item) {
id = "popup_menu"; id = "popup_menu";
styleId = "POPUP_MENU"; styleId = "POPUP_MENU";
_item = item;
WidgetListAdapter adapter = new WidgetListAdapter(); WidgetListAdapter adapter = new WidgetListAdapter();
for (int i=0; i < _item.subitemCount; i++) { for (int i=0; i < _item.subitemCount; i++) {
MenuItem subitem = _item.subitem(i); MenuItem subitem = _item.subitem(i);
MenuItemWidget widget = new MenuItemWidget(subitem); MenuItemWidget widget = new MenuItemWidget(subitem);
widget.handler = this; //widget.handler = this;
adapter.widgets.add(widget); adapter.widgets.add(widget);
} }
ownAdapter = adapter; ownAdapter = adapter;
} }
override protected bool onItemMouseDown(MenuItemWidget itemWidget, MouseEvent ev) { /// 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 (itemWidget.item.isSubmenu()) {
if (_openedPopup !is null)
_openedPopup.close();
PopupMenu popupMenu = new PopupMenu(itemWidget.item); PopupMenu popupMenu = new PopupMenu(itemWidget.item);
PopupWidget popup = window.showPopup(popupMenu, itemWidget, PopupAlign.Below); PopupWidget popup = window.showPopup(popupMenu, itemWidget, PopupAlign.Below);
ev.track(popupMenu); if (event !is null && (event.flags & (MouseFlag.LButton || MouseFlag.RButton)))
event.track(popupMenu);
_openedPopup = popup;
_openedMenu = popupMenu;
selectOnHover = true;
} else { } else {
// normal item // normal item
} }
return true;
}
override protected bool onItemMouseUp(MenuItemWidget itemWidget, MouseEvent ev) {
if (itemWidget.item.isSubmenu()) {
} else {
// normal item
// TODO: action
}
return true;
} }
} }
class MainMenu : MenuWidgetBase {
this(MenuItem item) {
super(item, Orientation.Horizontal);
id = "MAIN_MENU";
styleId = "MAIN_MENU";
}
}
class PopupMenu : MenuWidgetBase {
this(MenuItem item) {
super(item, Orientation.Vertical);
id = "POPUP_MENU";
styleId = "POPUP_MENU";
selectOnHover = true;
}
}

View File

@ -32,6 +32,10 @@ class PopupWidget : LinearLayout {
override void measure(int parentWidth, int parentHeight) { override void measure(int parentWidth, int parentHeight) {
super.measure(parentWidth, parentHeight); super.measure(parentWidth, parentHeight);
} }
/// close and destroy popup
void close() {
window.removePopup(this);
}
/// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout). /// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout).
override void layout(Rect rc) { override void layout(Rect rc) {