Merge pull request #559 from and3md/menu_and_popup_menu

Possibility to add popup menu to any widget, menu behavior fixes.
This commit is contained in:
Vadim Lopatin 2018-03-20 16:29:46 +03:00 committed by GitHub
commit 7be8c5ab04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 40 additions and 18 deletions

View File

@ -1505,8 +1505,11 @@ class Window : CustomEventTarget {
if (p is modal) if (p is modal)
break; break;
if (!insideOneOfPopups) { if (!insideOneOfPopups) {
if (p.onMouseEventOutside(event)) // stop loop when true is returned, but allow other main widget to handle event if (event.action == MouseAction.ButtonDown)
break; return true; // mouse button down should do nothing when click outside when popup visible
if (p.onMouseEventOutside(event)) {
return true; // mouse button up should do nothing when click outside when popup visible
}
} else { } else {
if (dispatchMouseEvent(p, event, cursorIsSet)) if (dispatchMouseEvent(p, event, cursorIsSet))
return true; return true;

View File

@ -256,7 +256,7 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler {
} }
/// override to handle main menu actions /// override to handle main menu actions
bool onMenuItemAction(const Action action) { override bool onMenuItemAction(const Action action) {
// default handling: dispatch action using window (first offered to focused control, then to main widget) // default handling: dispatch action using window (first offered to focused control, then to main widget)
return window.dispatchAction(action); return window.dispatchAction(action);
} }

View File

@ -849,13 +849,6 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction
acceleratorMap.add([ACTION_EDITOR_FIND_NEXT, ACTION_EDITOR_FIND_PREV]); acceleratorMap.add([ACTION_EDITOR_FIND_NEXT, ACTION_EDITOR_FIND_PREV]);
} }
protected MenuItem _popupMenu;
@property MenuItem popupMenu() { return _popupMenu; }
@property EditWidgetBase popupMenu(MenuItem popupMenu) {
_popupMenu = popupMenu;
return this;
}
/// ///
override bool onMenuItemAction(const Action action) { override bool onMenuItemAction(const Action action) {
return dispatchAction(action); return dispatchAction(action);

View File

@ -1005,7 +1005,7 @@ class GridWidgetBase : ScrollWidgetBase, GridModelAdapter, MenuItemActionHandler
} }
/// handle popup menu action /// handle popup menu action
protected bool onMenuItemAction(const Action action) { protected override bool onMenuItemAction(const Action action) {
if (menuItemAction.assigned) if (menuItemAction.assigned)
return menuItemAction(action); return menuItemAction(action);
return false; return false;

View File

@ -937,7 +937,7 @@ class MainMenu : MenuWidgetBase {
super(null, null, Orientation.Horizontal); super(null, null, Orientation.Horizontal);
id = "MAIN_MENU"; id = "MAIN_MENU";
styleId = STYLE_MAIN_MENU; styleId = STYLE_MAIN_MENU;
_clickOnButtonDown = true; _clickOnButtonDown = false;
selectOnHover = false; selectOnHover = false;
} }
@ -945,7 +945,7 @@ class MainMenu : MenuWidgetBase {
super(null, item, Orientation.Horizontal); super(null, item, Orientation.Horizontal);
id = "MAIN_MENU"; id = "MAIN_MENU";
styleId = STYLE_MAIN_MENU; styleId = STYLE_MAIN_MENU;
_clickOnButtonDown = true; _clickOnButtonDown = false;
selectOnHover = false; selectOnHover = false;
} }

View File

@ -174,10 +174,10 @@ class PopupWidget : LinearLayout {
if (visibility != Visibility.Visible) if (visibility != Visibility.Visible)
return false; return false;
if (_flags & PopupFlags.CloseOnClickOutside) { if (_flags & PopupFlags.CloseOnClickOutside) {
if (event.action == MouseAction.ButtonDown) { if (event.action == MouseAction.ButtonUp) {
// clicked outside - close popup // clicked outside - close popup
close(); close();
return false; return true;
} }
} }
if (_flags & PopupFlags.CloseOnMouseMoveOutside) { if (_flags & PopupFlags.CloseOnMouseMoveOutside) {

View File

@ -41,6 +41,7 @@ public {
import dlangui.core.i18n; import dlangui.core.i18n;
import dlangui.core.collections; import dlangui.core.collections;
import dlangui.widgets.styles; import dlangui.widgets.styles;
import dlangui.widgets.menu;
import dlangui.graphics.drawbuf; import dlangui.graphics.drawbuf;
import dlangui.graphics.resources; import dlangui.graphics.resources;
@ -153,7 +154,7 @@ enum CursorType {
* *
*/ */
@dmlwidget @dmlwidget
class Widget { class Widget : MenuItemActionHandler {
protected: protected:
/// widget id /// widget id
string _id; string _id;
@ -1506,13 +1507,38 @@ public:
// =========================================================== // ===========================================================
// popup menu support // popup menu support
override bool onMenuItemAction(const Action action) {
return dispatchAction(action);
}
protected MenuItem _popupMenu;
@property MenuItem popupMenu() { return _popupMenu; }
@property Widget popupMenu(MenuItem popupMenu) {
_popupMenu = popupMenu;
return this;
}
/// returns true if widget can show popup menu (e.g. by mouse right click at point x,y) /// returns true if widget can show popup menu (e.g. by mouse right click at point x,y)
bool canShowPopupMenu(int x, int y) { bool canShowPopupMenu(int x, int y) {
return false; if (_popupMenu is null)
return false;
if (_popupMenu.openingSubmenu.assigned)
if (!_popupMenu.openingSubmenu(_popupMenu))
return false;
return true;
} }
/// shows popup menu at (x,y) /// shows popup menu at (x,y)
void showPopupMenu(int x, int y) { void showPopupMenu(int x, int y) {
// override to show popup /// if preparation signal handler assigned, call it; don't show popup if false is returned from handler
if (_popupMenu.openingSubmenu.assigned)
if (!_popupMenu.openingSubmenu(_popupMenu))
return;
_popupMenu.updateActionState(this);
import dlangui.widgets.popup;
PopupMenu popupMenu = new PopupMenu(_popupMenu);
popupMenu.menuItemAction = this;
PopupWidget popup = window.showPopup(popupMenu, this, PopupAlign.Point | PopupAlign.Right, x, y);
popup.flags = PopupFlags.CloseOnClickOutside;
} }
/// override to change popup menu items state /// override to change popup menu items state
bool isActionEnabled(const Action action) { bool isActionEnabled(const Action action) {