diff --git a/examples/example1/src/example1.d b/examples/example1/src/example1.d index 28a46091..d6a414b2 100644 --- a/examples/example1/src/example1.d +++ b/examples/example1/src/example1.d @@ -341,31 +341,33 @@ extern (C) int UIAppMain(string[] args) { mainMenuItems.add(windowItem); mainMenuItems.add(helpItem); MainMenu mainMenu = new MainMenu(mainMenuItems); - mainMenu.menuItemClick = delegate(MenuItem item) { - Log.d("mainMenu.onMenuItemListener", item.label); - const Action a = item.action; - if (a) { - if (a.id == ACTION_FILE_EXIT) { - window.close(); - return true; - } else if (a.id == 41) { - window.showMessageBox(UIString("About"d), UIString("DLangUI demo app\n(C) Vadim Lopatin, 2014\nhttp://github.com/buggins/dlangui"d)); - return true; - } else if (a.id == ACTION_FILE_OPEN) { - UIString caption; - caption = "Open Text File"d; - FileDialog dlg = new FileDialog(caption, window, null); - dlg.addFilter(FileFilterEntry(UIString("FILTER_ALL_FILES", "All files (*)"d), "*")); - dlg.addFilter(FileFilterEntry(UIString("FILTER_TEXT_FILES", "Text files (*.txt)"d), "*.txt")); - dlg.addFilter(FileFilterEntry(UIString("FILTER_SOURCE_FILES", "Source files"d), "*.d;*.dd;*.c;*.cc;*.cpp;*.h;*.hpp")); - dlg.addFilter(FileFilterEntry(UIString("FILTER_EXECUTABLE_FILES", "Executable files"d), "*", true)); - //dlg.filterIndex = 2; - dlg.dialogResult = delegate(Dialog dlg, const Action result) { - if (result.id == ACTION_OPEN.id) { - string filename = result.stringParam; - if (filename.endsWith(".d") || filename.endsWith(".txt") || filename.endsWith(".cpp") || filename.endsWith(".h") || filename.endsWith(".c") - || filename.endsWith(".json") || filename.endsWith(".dd") || filename.endsWith(".ddoc") || filename.endsWith(".xml") || filename.endsWith(".html") - || filename.endsWith(".html") || filename.endsWith(".css") || filename.endsWith(".log") || filename.endsWith(".hpp")) { + contentLayout.addChild(mainMenu); + // to let main menu handle keyboard shortcuts + contentLayout.keyToAction = delegate(Widget source, uint keyCode, uint flags) { + return mainMenu.findKeyAction(keyCode, flags); + }; + contentLayout.onAction = delegate(Widget source, const Action a) { + if (a.id == ACTION_FILE_EXIT) { + window.close(); + return true; + } else if (a.id == 41) { + window.showMessageBox(UIString("About"d), UIString("DLangUI demo app\n(C) Vadim Lopatin, 2014\nhttp://github.com/buggins/dlangui"d)); + return true; + } else if (a.id == ACTION_FILE_OPEN) { + UIString caption; + caption = "Open Text File"d; + FileDialog dlg = new FileDialog(caption, window, null); + dlg.addFilter(FileFilterEntry(UIString("FILTER_ALL_FILES", "All files (*)"d), "*")); + dlg.addFilter(FileFilterEntry(UIString("FILTER_TEXT_FILES", "Text files (*.txt)"d), "*.txt")); + dlg.addFilter(FileFilterEntry(UIString("FILTER_SOURCE_FILES", "Source files"d), "*.d;*.dd;*.c;*.cc;*.cpp;*.h;*.hpp")); + dlg.addFilter(FileFilterEntry(UIString("FILTER_EXECUTABLE_FILES", "Executable files"d), "*", true)); + //dlg.filterIndex = 2; + dlg.dialogResult = delegate(Dialog dlg, const Action result) { + if (result.id == ACTION_OPEN.id) { + string filename = result.stringParam; + if (filename.endsWith(".d") || filename.endsWith(".txt") || filename.endsWith(".cpp") || filename.endsWith(".h") || filename.endsWith(".c") + || filename.endsWith(".json") || filename.endsWith(".dd") || filename.endsWith(".ddoc") || filename.endsWith(".xml") || filename.endsWith(".html") + || filename.endsWith(".html") || filename.endsWith(".css") || filename.endsWith(".log") || filename.endsWith(".hpp")) { // open source file in tab int index = tabs.tabIndex(filename); if (index >= 0) { @@ -385,17 +387,22 @@ extern (C) int UIAppMain(string[] args) { Log.d("FileDialog.onDialogResult: ", result, " param=", result.stringParam); window.showMessageBox(UIString("FileOpen result"d), UIString("Filename: "d ~ toUTF32(filename))); } - } + } - }; - dlg.show(); - return true; - } else - return contentLayout.dispatchAction(a); + }; + dlg.show(); + return true; + } else + return contentLayout.dispatchAction(a); + }; + mainMenu.menuItemClick = delegate(MenuItem item) { + Log.d("mainMenu.onMenuItemListener", item.label); + const Action a = item.action; + if (a) { + return contentLayout.dispatchAction(a); } return false; }; - contentLayout.addChild(mainMenu); // ========= create tabs =================== diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index 3021c6e6..fc7973e8 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -96,6 +96,16 @@ interface OnKeyHandler { bool onKey(Widget source, KeyEvent event); } +/// interface - slot for keyToAction +interface OnKeyActionHandler { + Action findKeyAction(Widget source, uint keyCode, uint keyFlags); +} + +/// interface - slot for onAction +interface OnActionHandler { + bool onAction(Widget source, const Action action); +} + /// interface - slot for onMouse interface OnMouseHandler { bool onMouse(Widget source, MouseEvent event); @@ -1093,6 +1103,9 @@ public: /// override to handle specific actions bool handleAction(const Action a) { + if (onAction.assigned) + if (onAction(this, a)) + return true; return false; } /// override to handle specific actions state (e.g. change enabled state for supported actions) @@ -1144,6 +1157,10 @@ public: /// map key to action Action findKeyAction(uint keyCode, uint flags) { Action action = _acceleratorMap.findByKey(keyCode, flags); + if (action) + return action; + if (keyToAction.assigned) + action = keyToAction(this, keyCode, flags); return action; } @@ -1282,6 +1299,12 @@ public: /// key event listener (bool delegate(Widget, KeyEvent)) - return true if event is processed by handler Signal!OnKeyHandler keyEvent; + /// action by key lookup handler + Listener!OnKeyActionHandler keyToAction; + + /// action handlers + Signal!OnActionHandler onAction; + /// mouse event listener (bool delegate(Widget, MouseEvent)) - return true if event is processed by handler Signal!OnMouseHandler mouseEvent;