popup menu support

This commit is contained in:
Vadim Lopatin 2014-05-12 10:34:07 +04:00
parent 45cafad1cb
commit 0b35db01c7
6 changed files with 92 additions and 16 deletions

View File

@ -75,6 +75,14 @@ extern (C) int UIAppMain(string[] args) {
editItem.add(new Action(EditorActions.Undo, "Undo"d, "edit-undo", KeyCode.KEY_Z, KeyFlag.Control));
editItem.add(new Action(EditorActions.Redo, "Redo"d, "edit-redo", KeyCode.KEY_Y, KeyFlag.Control));
editItem.add(new Action(20, "Preferences..."d));
MenuItem editPopupItem = new MenuItem(null);
editPopupItem.add(new Action(EditorActions.Copy, "Copy"d, "edit-copy", KeyCode.KEY_C, KeyFlag.Control));
editPopupItem.add(new Action(EditorActions.Paste, "Paste"d, "edit-paste", KeyCode.KEY_V, KeyFlag.Control));
editPopupItem.add(new Action(EditorActions.Cut, "Cut"d, "edit-cut", KeyCode.KEY_X, KeyFlag.Control));
editPopupItem.add(new Action(EditorActions.Undo, "Undo"d, "edit-undo", KeyCode.KEY_Z, KeyFlag.Control));
editPopupItem.add(new Action(EditorActions.Redo, "Redo"d, "edit-redo", KeyCode.KEY_Y, KeyFlag.Control));
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));
@ -119,7 +127,7 @@ extern (C) int UIAppMain(string[] args) {
hlayout.addChild((new ImageWidget()).drawableId("btn_check").padding(Rect(5,5,5,5)).alignment(Align.Center));
hlayout.addChild((new TextWidget()).text("in horizontal layout"));
hlayout.addChild((new ImageWidget()).drawableId("exit").padding(Rect(5,5,5,5)).alignment(Align.Center));
hlayout.addChild((new EditLine("editline", "Some text to edit"d)).alignment(Align.Center).layoutWidth(FILL_PARENT));
hlayout.addChild((new EditLine("editline", "Some text to edit"d)).popupMenu(editPopupItem).alignment(Align.Center).layoutWidth(FILL_PARENT));
//hlayout.addChild((new Button()).text(">>")); //.textColor(0x40FF4000)
hlayout.backgroundColor = 0x8080C0;
layout.addChild(hlayout);
@ -278,6 +286,7 @@ extern (C) int UIAppMain(string[] args) {
EditLine editLine = new EditLine("editline1", "Single line editor sample text");
editors.addChild(createEditorSettingsControl(editLine));
editors.addChild(editLine);
editLine.popupMenu = editPopupItem;
// EditBox sample
editors.addChild(new TextWidget(null, "EditBox: Multiline editor"d));
@ -296,6 +305,7 @@ extern (C) int UIAppMain(string[] args) {
editBox.minFontSize(12).maxFontSize(75); // allow font zoom with Ctrl + MouseWheel
editors.addChild(createEditorSettingsControl(editBox));
editors.addChild(editBox);
editBox.popupMenu = editPopupItem;
editors.addChild(new TextWidget(null, "EditBox: additional view for the same content (split view testing)"d));
EditBox editBox2 = new EditBox("editbox2", ""d);

View File

@ -85,10 +85,12 @@ class Window {
protected PopupWidget[] _popups;
/// show new popup
PopupWidget showPopup(Widget content, Widget anchor = null, uint alignment = PopupAlign.Center) {
PopupWidget showPopup(Widget content, Widget anchor = null, uint alignment = PopupAlign.Center, int x = 0, int y = 0) {
PopupWidget res = new PopupWidget(content, this);
res.anchor.widget = anchor !is null ? anchor : _mainWidget;
res.anchor.alignment = alignment;
res.anchor.x = x;
res.anchor.y = y;
_popups ~= res;
if (_mainWidget !is null)
_mainWidget.requestLayout();

View File

@ -25,6 +25,8 @@ import dlangui.widgets.controls;
import dlangui.core.signals;
import dlangui.core.collections;
import dlangui.platforms.common.platform;
import dlangui.widgets.menu;
import dlangui.widgets.popup;
import std.algorithm;
@ -897,6 +899,36 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
]);
}
protected MenuItem _popupMenu;
@property MenuItem popupMenu() { return _popupMenu; }
@property EditWidgetBase popupMenu(MenuItem popupMenu) {
_popupMenu = popupMenu;
return this;
}
/// returns true if widget can show popup (e.g. by mouse right click at point x,y)
override bool canShowPopupMenu(int x, int y) {
if (_popupMenu is null)
return false;
if (_popupMenu.onBeforeOpeningSubmenu.assigned)
if (!_popupMenu.onBeforeOpeningSubmenu(_popupMenu))
return false;
return true;
}
/// shows popup at (x,y)
override void showPopupMenu(int x, int y) {
/// if preparation signal handler assigned, call it; don't show popup if false is returned from handler
if (_popupMenu.onBeforeOpeningSubmenu.assigned)
if (!_popupMenu.onBeforeOpeningSubmenu(_popupMenu))
return;
PopupMenu popupMenu = new PopupMenu(_popupMenu);
PopupWidget popup = window.showPopup(popupMenu, this, PopupAlign.Point | PopupAlign.Right, x, y);
popup.flags = PopupFlags.CloseOnClickOutside;
}
void onPopupMenuItem(MenuItem item) {
// TODO
}
/// when true, Tab / Shift+Tab presses are processed internally in widget (e.g. insert tab character) instead of focus change navigation.
@property bool wantTabs() {
return _wantTabs;
@ -1630,7 +1662,7 @@ class EditWidgetBase : WidgetGroup, EditableContentListener {
return handleAction(new Action(EditorActions.ScrollLineUp));
}
}
return false;
return super.onMouseEvent(event);
}

View File

@ -97,6 +97,12 @@ class MenuItem {
@property const(Action) action() const { return _action; }
/// sets item action
@property MenuItem action(Action a) { _action = a; return this; }
/// handle menu item click
Signal!(void, MenuItem) onMenuItem;
/// prepare for opening of submenu, return true if opening is allowed
Signal!(bool, MenuItem) onBeforeOpeningSubmenu;
this() {
_enabled = true;
}

View File

@ -32,10 +32,14 @@ enum PopupAlign : uint {
Below = 2,
/// place popup below anchor widget close to right bound (when no space enough, align near left bound)
Right = 4,
/// align to specified point
Point = 8,
}
struct PopupAnchor {
Widget widget;
int x;
int y;
uint alignment = PopupAlign.Center;
}
@ -105,17 +109,22 @@ class PopupWidget : LinearLayout {
Rect r;
Point anchorPt;
if (anchor.alignment & PopupAlign.Center) {
// center around center of anchor widget
r.left = anchorrc.middlex - w / 2;
r.top = anchorrc.middley - h / 2;
} else if (anchor.alignment & PopupAlign.Below) {
r.left = anchorrc.left;
r.top = anchorrc.bottom;
} else if (anchor.alignment & PopupAlign.Right) {
r.left = anchorrc.right;
r.top = anchorrc.top;
}
if (anchor.alignment & PopupAlign.Point) {
r.left = anchor.x;
r.top = anchor.y;
} else {
if (anchor.alignment & PopupAlign.Center) {
// center around center of anchor widget
r.left = anchorrc.middlex - w / 2;
r.top = anchorrc.middley - h / 2;
} else if (anchor.alignment & PopupAlign.Below) {
r.left = anchorrc.left;
r.top = anchorrc.bottom;
} else if (anchor.alignment & PopupAlign.Right) {
r.left = anchorrc.right;
r.top = anchorrc.top;
}
}
r.right = r.left + w;
r.bottom = r.top + h;
r.moveToFit(rc);

View File

@ -866,6 +866,12 @@ class Widget {
return true;
}
}
if (event.action == MouseAction.ButtonDown && event.button == MouseButton.Right) {
if (canShowPopupMenu(event.x, event.y)) {
showPopupMenu(event.x, event.y);
return true;
}
}
if (canFocus && event.action == MouseAction.ButtonDown && event.button == MouseButton.Left) {
setFocus();
return true;
@ -1034,6 +1040,17 @@ class Widget {
}
}
// ===========================================================
// popup menu support
/// returns true if widget can show popup menu (e.g. by mouse right click at point x,y)
bool canShowPopupMenu(int x, int y) {
return false;
}
/// shows popup menu at (x,y)
void showPopupMenu(int x, int y) {
// override to show popup
}
// ===========================================================
// Widget hierarhy methods