From 64c9e4f1d5b5acd78ec1b2a3b95f348e3c7e097d Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Sun, 5 Feb 2012 23:44:47 -0200 Subject: [PATCH] add modulemanager module --- TODO | 3 +- modules/addon_terminal/commands.lua | 17 ++- modules/client/client.otmod | 1 + .../client_modulemanager/modulemanager.lua | 118 ++++++++++++++++++ .../client_modulemanager/modulemanager.otmod | 11 ++ .../client_modulemanager/modulemanager.otui | 117 +++++++++++++++++ .../client_modulemanager/modulemanager.png | Bin 0 -> 952 bytes modules/client_topmenu/topmenu.otui | 2 +- modules/core_styles/styles/buttons.otui | 2 +- modules/core_styles/styles/checkboxes.otui | 4 +- modules/core_styles/styles/comboboxes.otui | 4 +- modules/core_styles/styles/labels.otui | 2 +- modules/core_styles/styles/popupmenus.otui | 4 +- modules/game_miniwindow/miniwindow.otmod | 2 +- src/framework/application.cpp | 2 - src/framework/const.h | 2 +- src/framework/core/declarations.h | 1 + src/framework/core/module.cpp | 61 ++++----- src/framework/core/module.h | 8 +- src/framework/core/modulemanager.cpp | 18 ++- src/framework/core/modulemanager.h | 1 + src/framework/luafunctions.cpp | 27 ++++ src/framework/ui/uilineedit.cpp | 4 +- src/framework/ui/uiwidget.cpp | 25 +++- src/framework/ui/uiwidget.h | 3 + 25 files changed, 379 insertions(+), 60 deletions(-) create mode 100644 modules/client_modulemanager/modulemanager.lua create mode 100644 modules/client_modulemanager/modulemanager.otmod create mode 100644 modules/client_modulemanager/modulemanager.otui create mode 100644 modules/client_modulemanager/modulemanager.png diff --git a/TODO b/TODO index 543597e1..fe93f026 100644 --- a/TODO +++ b/TODO @@ -75,6 +75,8 @@ game/graphics window with options do lua game event calls from Game instead from GameProtocol auto walk +minimap window + login queue questlog edit texts @@ -82,4 +84,3 @@ trade window shop window battle window hotkeys window -minimap window diff --git a/modules/addon_terminal/commands.lua b/modules/addon_terminal/commands.lua index 3d588dc0..b08f80e2 100644 --- a/modules/addon_terminal/commands.lua +++ b/modules/addon_terminal/commands.lua @@ -1,6 +1,17 @@ -function dumpWidgets() - for i=1,rootWidget:getChildCount() do - print(rootWidget:getChildByIndex(i):getId()) +function dumpWidgets(widget, level) + widget = widget or rootWidget + level = level or 0 + for i=1,widget:getChildCount() do + local child = widget:getChildByIndex(i) + if child:isVisible() then + local name = child:getId() + if name:match('widget%d+') == nil then + print(string.rep(' ', level) .. name) + end + if child:getId() ~= 'terminalBuffer' then + dumpWidgets(child, level+1) + end + end end end diff --git a/modules/client/client.otmod b/modules/client/client.otmod index fa8555bb..84f89a58 100644 --- a/modules/client/client.otmod +++ b/modules/client/client.otmod @@ -12,6 +12,7 @@ Module - client_about - client_options - client_entergame + - client_modulemanager - game onLoad: | diff --git a/modules/client_modulemanager/modulemanager.lua b/modules/client_modulemanager/modulemanager.lua new file mode 100644 index 00000000..c1cf41da --- /dev/null +++ b/modules/client_modulemanager/modulemanager.lua @@ -0,0 +1,118 @@ +ModuleManager = {} + +local moduleManagerWindow +local moduleManagerButton +local moduleList + +function ModuleManager.init() + moduleManagerWindow = displayUI('modulemanager.otui') + moduleManagerWindow:hide() + moduleList = moduleManagerWindow:getChildById('moduleList') + connect(moduleList, { onChildFocusChange = function(self, focusedChild) + if focusedChild == nil then return end + ModuleManager.updateModuleInfo(focusedChild:getText()) + end }) + + moduleManagerButton = TopMenu.addButton('moduleManagerButton', 'Module manager', 'modulemanager.png', ModuleManager.toggle) + + addEvent(ModuleManager.listModules) +end + +function ModuleManager.terminate() + moduleManagerWindow:destroy() + moduleManagerWindow = nil + moduleManagerButton:destroy() + moduleManagerButton = nil + moduleList = nil +end + +function ModuleManager.hide() + moduleManagerWindow:hide() +end + +function ModuleManager.show() + moduleManagerWindow:show() + moduleManagerWindow:focus() + moduleManagerWindow:raise() + +end + +function ModuleManager.toggle() + if moduleManagerWindow:isVisible() then + ModuleManager.hide() + else + ModuleManager.show() + end +end + +function ModuleManager.refreshModules() + g_modules.discoverModules() + ModuleManager.listModules() +end + +function ModuleManager.listModules() + moduleList:destroyChildren() + + local modules = g_modules.getModules() + for i,module in ipairs(modules) do + local label = createWidget('ModuleListLabel', moduleList) + label:setText(module:getName()) + end + + moduleList:focusChild(moduleList:getFirstChild(), ActiveFocusReason) +end + +function ModuleManager.updateModuleInfo(moduleName) + local name = '' + local description = '' + local autoLoad = '' + local author = '' + local website = '' + local version = '' + local canLoad = false + local canUnload = false + + local module = g_modules.getModule(moduleName) + if module then + name = module:getName() + description = module:getDescription() + author = module:getAuthor() + website = module:getWebsite() + version = module:getVersion() + canUnload = module:isLoaded() + canLoad = not canUnload + end + + moduleManagerWindow:recursiveGetChildById('moduleName'):setText(name) + moduleManagerWindow:recursiveGetChildById('moduleDescription'):setText(description) + moduleManagerWindow:recursiveGetChildById('moduleDescription'):wrapText() + moduleManagerWindow:recursiveGetChildById('moduleAuthor'):setText(author) + moduleManagerWindow:recursiveGetChildById('moduleWebsite'):setText(website) + moduleManagerWindow:recursiveGetChildById('moduleVersion'):setText(version) + + moduleManagerWindow:recursiveGetChildById('moduleLoadButton'):setEnabled(canLoad) + moduleManagerWindow:recursiveGetChildById('moduleUnloadButton'):setEnabled(canUnload) +end + +function ModuleManager.loadCurrentModule() + local focusedChild = moduleList:getFocusedChild() + if focusedChild then + local module = g_modules.getModule(focusedChild:getText()) + if module then + module:load() + ModuleManager.updateModuleInfo(module:getName()) + end + end +end + +function ModuleManager.unloadCurrentModule() + local focusedChild = moduleList:getFocusedChild() + if focusedChild then + local module = g_modules.getModule(focusedChild:getText()) + if module then + module:unload() + ModuleManager.updateModuleInfo(module:getName()) + end + end +end + diff --git a/modules/client_modulemanager/modulemanager.otmod b/modules/client_modulemanager/modulemanager.otmod new file mode 100644 index 00000000..589a99c2 --- /dev/null +++ b/modules/client_modulemanager/modulemanager.otmod @@ -0,0 +1,11 @@ +Module + name: client_modulemanager + description: Manage other modules + author: OTClient team + website: https://github.com/edubart/otclient + onLoad: | + require 'modulemanager' + ModuleManager.init() + + onUnload: | + ModuleManager.terminate() diff --git a/modules/client_modulemanager/modulemanager.otui b/modules/client_modulemanager/modulemanager.otui new file mode 100644 index 00000000..a41cba75 --- /dev/null +++ b/modules/client_modulemanager/modulemanager.otui @@ -0,0 +1,117 @@ +ModuleListLabel < Label + font: verdana-11px-monochrome + background-color: alpha + text-offset: 2 0 + focusable: true + + $focus: + background-color: #ffffff22 + color: #ffffff + +ModuleInfoLabel < Label + $!first: + margin-top: 5 + margin-bottom: 2 + +ModuleValueLabel < UILabel + font: verdana-11px-antialised + color: #aaaaaa + text-offset: 3 0 + image-source: /core_styles/images/panel_flat.png + image-border: 1 + +MainWindow + id: moduleManagerWindow + size: 450 450 + text: Module Manager + + @onEscape: ModuleManager.hide() + + TextList + id: moduleList + anchors.top: parent.top + anchors.left: parent.left + anchors.bottom: parent.bottom + width: 180 + padding: 1 + focusable: false + margin-bottom: 30 + + Button + anchors.top: moduleList.bottom + anchors.horizontalCenter: moduleList.horizontalCenter + margin-top: 8 + text: Refresh + @onClick: ModuleManager.refreshModules() + + Panel + id: moduleInfo + anchors.left: moduleList.right + anchors.top: parent.top + anchors.right: parent.right + margin: 0 5 5 15 + layout: + type: verticalBox + fit-children: true + + ModuleInfoLabel + text: Module name + ModuleValueLabel + id: moduleName + + ModuleInfoLabel + text: Description + ModuleValueLabel + id: moduleDescription + height: 100 + + ModuleInfoLabel + text: Loaded + ModuleValueLabel + id: moduleLoaded + + //ModuleInfoLabel + // text: Autoload + //ModuleValueLabel + // id: moduleAutoload + + //ModuleInfoLabel + // text: Autoload antecedence + //ModuleValueLabel + // id: moduleLoadAntecedence + // text: 1000 + + ModuleInfoLabel + text: Author + ModuleValueLabel + id: moduleAuthor + + ModuleInfoLabel + text: Website + ModuleValueLabel + id: moduleWebsite + + ModuleInfoLabel + text: Version + ModuleValueLabel + id: moduleVersion + + Button + id: moduleLoadButton + anchors.top: moduleInfo.bottom + anchors.left: moduleInfo.left + margin-top: 8 + text: Load + enabled: false + @onClick: ModuleManager.loadCurrentModule() + + Button + id: moduleUnloadButton + anchors.top: moduleInfo.bottom + anchors.right: moduleInfo.right + margin-left: 10 + margin-top: 8 + text: Unload + enabled: false + @onClick: ModuleManager.unloadCurrentModule() + diff --git a/modules/client_modulemanager/modulemanager.png b/modules/client_modulemanager/modulemanager.png new file mode 100644 index 0000000000000000000000000000000000000000..8089991d85842c4285ec7b491f19fdf54f2566cd GIT binary patch literal 952 zcmV;p14sOcP)WdKcSAT=OUWpE%eFfcbDGBY|bIXW>oAS*C2FfhB!{15;D00(qQO+^RS z2?Z4#1$EKfJpcdz32;bRa{vGf5&!@T5&_cPe*6Fc00d`2O+f$vv5yPEnNtOw$O!8T9KAg?V_nt$BdddnVHPIcmKZYH)GX+m-l%0y?f93&N<(G z0C-3k4Fa?RKh;qUAe*BL( zb#(WqGMaro3FZdN#oi4YC$VkEM-X}t*Uulv(!zaY^(rPeP9y2bqc|~zN0l0u7FY1( zY3g;UG-ss|`Rx}Nj9_lh0lYP}9p%w+L{bR04p;vbarq|B zoV%;Fcg}qB*~KD|vJ1l5&o@B(8ips{!g_Kebq}QSkOd$HirV?i!Z#89 zGCTo?PF{e`7U69kzFkFdycU)b^*hK?25Q3u5+Ve67g&Ky4Ppxv8bIJH`xh!V!GQtJ zR6+JJgph2`qSb8kTIec`LBV$kkUuPu`n9RR8Axz*^hITWBV}eKoqJ;N*CJ5Gg%ivIF zU=5Pf@#Ya%U`r5Pe2fAiIHp*UZ z%Oba|0dlo2hW9}+P>2_E2-~eJ1mVy5fTxXkxKT^L(=zG%>Fdjs2X%;n6(!@WI)DzbgUDE!uzONBa%adhzmCJa%w$oOHT_W0=ipF +class ModuleManager; class Module; class Event; class ScheduledEvent; diff --git a/src/framework/core/module.cpp b/src/framework/core/module.cpp index 7af5fc9a..c1fad18a 100644 --- a/src/framework/core/module.cpp +++ b/src/framework/core/module.cpp @@ -31,36 +31,6 @@ Module::Module(const std::string& name) m_name = name; } -void Module::discover(const OTMLNodePtr& moduleNode) -{ - const static std::string none = "none"; - m_description = moduleNode->valueAt("description", none); - m_author = moduleNode->valueAt("author", none); - m_website = moduleNode->valueAt("website", none); - m_version = moduleNode->valueAt("version", none); - m_autoLoad = moduleNode->valueAt("autoLoad", false); - m_autoLoadAntecedence = moduleNode->valueAt("autoLoadAntecedence", 100); - - if(OTMLNodePtr node = moduleNode->get("dependencies")) { - for(const OTMLNodePtr& tmp : node->children()) - m_dependencies.push_back(tmp->value()); - } - - // set onLoad callback - if(OTMLNodePtr node = moduleNode->get("onLoad")) { - g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]"); - g_lua.useValue(); - m_loadCallback = g_lua.polymorphicPop(); - } - - // set onUnload callback - if(OTMLNodePtr node = moduleNode->get("onUnload")) { - g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]"); - g_lua.useValue(); - m_unloadCallback = g_lua.polymorphicPop(); - } -} - bool Module::load() { if(m_loaded) @@ -95,3 +65,34 @@ void Module::unload() m_loaded = false; } } + +void Module::discover(const OTMLNodePtr& moduleNode) +{ + const static std::string none = "none"; + m_description = moduleNode->valueAt("description", none); + m_author = moduleNode->valueAt("author", none); + m_website = moduleNode->valueAt("website", none); + m_version = moduleNode->valueAt("version", none); + m_autoLoad = moduleNode->valueAt("autoLoad", false); + m_autoLoadAntecedence = moduleNode->valueAt("autoLoadAntecedence", 100); + + if(OTMLNodePtr node = moduleNode->get("dependencies")) { + for(const OTMLNodePtr& tmp : node->children()) + m_dependencies.push_back(tmp->value()); + } + + // set onLoad callback + if(OTMLNodePtr node = moduleNode->get("onLoad")) { + g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]"); + g_lua.useValue(); + m_loadCallback = g_lua.polymorphicPop(); + } + + // set onUnload callback + if(OTMLNodePtr node = moduleNode->get("onUnload")) { + g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]"); + g_lua.useValue(); + m_unloadCallback = g_lua.polymorphicPop(); + } +} + diff --git a/src/framework/core/module.h b/src/framework/core/module.h index ee43ff1f..8b64373c 100644 --- a/src/framework/core/module.h +++ b/src/framework/core/module.h @@ -26,12 +26,12 @@ #include "declarations.h" #include +#include -class Module +class Module : public LuaObject { public: Module(const std::string& name); - void discover(const OTMLNodePtr& moduleNode); bool load(); void unload(); @@ -46,6 +46,10 @@ public: bool isAutoLoad() { return m_autoLoad; } int getAutoLoadAntecedence() { return m_autoLoadAntecedence; } +protected: + void discover(const OTMLNodePtr& moduleNode); + friend class ModuleManager; + private: Boolean m_loaded; Boolean m_autoLoad; diff --git a/src/framework/core/modulemanager.cpp b/src/framework/core/modulemanager.cpp index 6af78872..699436af 100644 --- a/src/framework/core/modulemanager.cpp +++ b/src/framework/core/modulemanager.cpp @@ -30,6 +30,9 @@ ModuleManager g_modules; void ModuleManager::discoverModules() { + // remove modules that are not loaded + m_autoLoadModules.clear(); + auto moduleDirs = g_resources.listDirectoryFiles("/"); for(const std::string& moduleDir : moduleDirs) { auto moduleFiles = g_resources.listDirectoryFiles("/" + moduleDir); @@ -85,12 +88,19 @@ ModulePtr ModuleManager::discoverModule(const std::string& moduleFile) OTMLNodePtr moduleNode = doc->at("Module"); std::string name = moduleNode->valueAt("name"); - if(getModule(name)) - Fw::throwException("module '", name, "' already exists, cannot have duplicate module names"); + //if(getModule(name)) + // Fw::throwException("module '", name, "' already exists, cannot have duplicate module names"); - module = ModulePtr(new Module(name)); + bool push = false; + module = getModule(name); + if(!module) { + module = ModulePtr(new Module(name)); + push = true; + } module->discover(moduleNode); - m_modules.push_back(module); + + if(push) + m_modules.push_back(module); } catch(Exception& e) { logError("Unable to discover module from file '", moduleFile, "': ", e.what()); } diff --git a/src/framework/core/modulemanager.h b/src/framework/core/modulemanager.h index 2419b511..c75499df 100644 --- a/src/framework/core/modulemanager.h +++ b/src/framework/core/modulemanager.h @@ -36,6 +36,7 @@ public: void unloadModules(); ModulePtr getModule(const std::string& moduleName); + std::vector getModules() { return m_modules; } private: std::vector m_modules; diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index 1963b72e..539a6d82 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include void Application::registerLuaFunctions() { @@ -83,6 +85,7 @@ void Application::registerLuaFunctions() g_lua.bindClassMemberFunction("ungrabKeyboard", &UIWidget::ungrabKeyboard); g_lua.bindClassMemberFunction("bindRectToParent", &UIWidget::bindRectToParent); g_lua.bindClassMemberFunction("destroy", &UIWidget::destroy); + g_lua.bindClassMemberFunction("destroyChildren", &UIWidget::destroyChildren); g_lua.bindClassMemberFunction("setId", &UIWidget::setId); g_lua.bindClassMemberFunction("setParent", &UIWidget::setParent); g_lua.bindClassMemberFunction("setLayout", &UIWidget::setLayout); @@ -361,6 +364,19 @@ void Application::registerLuaFunctions() // Protocol g_lua.registerClass(); + // Module + g_lua.registerClass(); + g_lua.bindClassMemberFunction("load", &Module::load); + g_lua.bindClassMemberFunction("unload", &Module::unload); + g_lua.bindClassMemberFunction("isLoaded", &Module::isLoaded); + g_lua.bindClassMemberFunction("getDescription", &Module::getDescription); + g_lua.bindClassMemberFunction("getName", &Module::getName); + g_lua.bindClassMemberFunction("getAuthor", &Module::getAuthor); + g_lua.bindClassMemberFunction("getWebsite", &Module::getWebsite); + g_lua.bindClassMemberFunction("getVersion", &Module::getVersion); + g_lua.bindClassMemberFunction("isAutoLoad", &Module::isAutoLoad); + g_lua.bindClassMemberFunction("getAutoLoadAntecedence", &Module::getAutoLoadAntecedence); + // network manipulation via lua is disabled for a while /* // OutputMessage @@ -451,6 +467,17 @@ void Application::registerLuaFunctions() g_lua.bindClassStaticFunction("g_ui", "setDebugBoxesDrawing", std::bind(&UIManager::setDebugBoxesDrawing, &g_ui, _1)); g_lua.bindClassStaticFunction("g_ui", "isDrawingDebugBoxes", std::bind(&UIManager::setDebugBoxesDrawing, &g_ui, _1)); + // ModuleManager + g_lua.registerStaticClass("g_modules"); + g_lua.bindClassStaticFunction("g_modules", "discoverModulesPath", std::bind(&ModuleManager::discoverModulesPath, &g_modules)); + g_lua.bindClassStaticFunction("g_modules", "discoverModules", std::bind(&ModuleManager::discoverModules, &g_modules)); + g_lua.bindClassStaticFunction("g_modules", "autoLoadModules", std::bind(&ModuleManager::autoLoadModules, &g_modules, _1)); + g_lua.bindClassStaticFunction("g_modules", "discoverModule", std::bind(&ModuleManager::discoverModule, &g_modules, _1)); + g_lua.bindClassStaticFunction("g_modules", "ensureModuleLoaded", std::bind(&ModuleManager::ensureModuleLoaded, &g_modules, _1)); + g_lua.bindClassStaticFunction("g_modules", "unloadModules", std::bind(&ModuleManager::unloadModules, &g_modules)); + g_lua.bindClassStaticFunction("g_modules", "getModule", std::bind(&ModuleManager::getModule, &g_modules, _1)); + g_lua.bindClassStaticFunction("g_modules", "getModules", std::bind(&ModuleManager::getModules, &g_modules)); + // FontManager g_lua.registerStaticClass("g_fonts"); g_lua.bindClassStaticFunction("g_fonts", "importFont", std::bind(&FontManager::importFont, &g_fonts, _1)); diff --git a/src/framework/ui/uilineedit.cpp b/src/framework/ui/uilineedit.cpp index 1825505e..8ec38388 100644 --- a/src/framework/ui/uilineedit.cpp +++ b/src/framework/ui/uilineedit.cpp @@ -421,7 +421,7 @@ void UILineEdit::onGeometryChange(const Rect& oldRect, const Rect& newRect) void UILineEdit::onFocusChange(bool focused, Fw::FocusReason reason) { if(focused && !m_alwaysActive) { - if(reason == Fw::TabFocusReason) + if(reason == Fw::KeyboardFocusReason) setCursorPos(m_text.length()); else blinkCursor(); @@ -452,7 +452,7 @@ bool UILineEdit::onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilt else if(keyCode == Fw::KeyTab) { if(!m_alwaysActive) { if(UIWidgetPtr parent = getParent()) - parent->focusNextChild(Fw::TabFocusReason); + parent->focusNextChild(Fw::KeyboardFocusReason); } } else return false; diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index 15a455e9..4f660c77 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -219,6 +219,8 @@ void UIWidget::focusChild(const UIWidgetPtr& child, Fw::FocusReason reason) oldFocused->updateState(Fw::FocusState); oldFocused->updateState(Fw::ActiveState); } + + onChildFocusChange(child, oldFocused, reason); } void UIWidget::focusNextChild(Fw::FocusReason reason) @@ -485,7 +487,6 @@ void UIWidget::lower() void UIWidget::raise() { - focus(); UIWidgetPtr parent = getParent(); if(parent) parent->raiseChild(asUIWidget()); @@ -546,9 +547,7 @@ void UIWidget::destroy() parent->removeChild(asUIWidget()); } - // destroy children - while(!m_children.empty()) - getFirstChild()->destroy(); + destroyChildren(); callLuaField("onDestroy"); @@ -568,6 +567,12 @@ void UIWidget::destroy() m_destroyed = true; } +void UIWidget::destroyChildren() +{ + while(!m_children.empty()) + getFirstChild()->destroy(); +} + void UIWidget::setId(const std::string& id) { m_id = id; @@ -1108,6 +1113,11 @@ void UIWidget::onFocusChange(bool focused, Fw::FocusReason reason) callLuaField("onFocusChange", focused, reason); } +void UIWidget::onChildFocusChange(const UIWidgetPtr& focusedChild, const UIWidgetPtr& unfocusedChild, Fw::FocusReason reason) +{ + callLuaField("onChildFocusChange", focusedChild, unfocusedChild, reason); +} + void UIWidget::onHoverChange(bool hovered) { callLuaField("onHoverChange", hovered); @@ -1168,7 +1178,7 @@ bool UIWidget::onMousePress(const Point& mousePos, Fw::MouseButton button) bool UIWidget::onMouseRelease(const Point& mousePos, Fw::MouseButton button) { if(isPressed() && getRect().contains(mousePos)) - callLuaField("onClick"); + onClick(mousePos); UIWidgetPtr draggedWidget = g_ui.getDraggingWidget(); if(draggedWidget && button == Fw::MouseLeftButton && (containsPoint(mousePos) || asUIWidget() == g_ui.getRootWidget())) { @@ -1196,6 +1206,11 @@ bool UIWidget::onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direc return callLuaField("onMouseWheel", mousePos, direction); } +bool UIWidget::onClick(const Point& mousePos) +{ + return callLuaField("onClick", mousePos); +} + bool UIWidget::onDoubleClick(const Point& mousePos) { return callLuaField("onDoubleClick", mousePos); diff --git a/src/framework/ui/uiwidget.h b/src/framework/ui/uiwidget.h index 25c5875f..da127349 100644 --- a/src/framework/ui/uiwidget.h +++ b/src/framework/ui/uiwidget.h @@ -105,6 +105,7 @@ public: void ungrabKeyboard(); void bindRectToParent(); void destroy(); + void destroyChildren(); void setId(const std::string& id); void setParent(const UIWidgetPtr& parent); @@ -169,6 +170,7 @@ protected: virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode); virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect); virtual void onFocusChange(bool focused, Fw::FocusReason reason); + virtual void onChildFocusChange(const UIWidgetPtr& focusedChild, const UIWidgetPtr& unfocusedChild, Fw::FocusReason reason); virtual void onHoverChange(bool hovered); virtual void onDragEnter(const Point& mousePos); virtual void onDragLeave(UIWidgetPtr droppedWidget, const Point& mousePos); @@ -181,6 +183,7 @@ protected: virtual bool onMouseRelease(const Point& mousePos, Fw::MouseButton button); virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved); virtual bool onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direction); + virtual bool onClick(const Point& mousePos); virtual bool onDoubleClick(const Point& mousePos); bool propagateOnKeyText(const std::string& keyText);