From bddcfb08fdb89a91455754385d70d17c7f8cd19b Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Sun, 17 Jul 2011 03:56:57 -0300 Subject: [PATCH] rework ui related scripting stuff --- ...sans-11px-bold.yml => sans-11px-bold.otml} | 0 ...sans-12px-bold.yml => sans-12px-bold.otml} | 0 ...ialised.yml => tibia-10px-antialised.otml} | 0 ...ochrome.yml => tibia-10px-monochrome.otml} | 0 ...px-rounded.yml => tibia-12px-rounded.otml} | 0 ...tialised.yml => tibia-8px-antialised.otml} | 0 data/modules/core/aliases.lua | 4 + data/modules/core/core.lua | 4 + data/modules/core/enums.lua | 8 + data/modules/core/module.otml | 8 + data/modules/core/util.lua | 5 + data/modules/mainmenu/entergame.lua | 57 ++ data/modules/mainmenu/init.lua | 16 + data/modules/mainmenu/menustate.lua | 63 --- .../mainmenu/{module.yml => module.otml} | 0 .../entergamewindow.otml} | 6 +- .../{infowindow.yml => ui/infowindow.otml} | 0 .../{mainmenu.yml => ui/mainmenu.otml} | 26 +- .../optionswindow.otml} | 0 data/modules/messagebox/messagebox.lua | 102 +++- data/modules/messagebox/messagebox.yml | 18 - data/modules/messagebox/module.otml | 8 + data/skins/{lightness.yml => lightness.otml} | 0 data/skins/{tibiaskin.yml => tibiaskin.otml} | 0 src/framework/otml/otmlparser.cpp | 8 +- src/framework/otml/otmlparser.h | 9 +- src/framework/script/scriptcontext.cpp | 2 +- src/framework/script/scriptfunctions.cpp | 499 +++++++++++++----- src/framework/script/scriptfunctions.h | 42 -- src/framework/ui/ui.h | 27 - src/framework/ui/uianchorlayout.cpp | 43 +- src/framework/ui/uianchorlayout.h | 32 +- src/framework/ui/uibuttonskin.h | 1 - src/framework/ui/uiconstants.h | 28 - src/framework/ui/uicontainer.h | 2 +- src/framework/ui/uielement.cpp | 39 +- src/framework/ui/uielement.h | 37 +- src/framework/ui/uielementskin.h | 4 +- src/framework/ui/uilabel.cpp | 4 +- src/framework/ui/uilabel.h | 2 +- src/framework/ui/uiloader.cpp | 33 +- src/framework/ui/uiloader.h | 4 +- src/framework/util/rect.h | 51 +- src/main.cpp | 2 +- src/protocollogin.cpp | 14 +- src/protocollogin.h | 25 +- 46 files changed, 733 insertions(+), 500 deletions(-) rename data/fonts/{sans-11px-bold.yml => sans-11px-bold.otml} (100%) rename data/fonts/{sans-12px-bold.yml => sans-12px-bold.otml} (100%) rename data/fonts/{tibia-10px-antialised.yml => tibia-10px-antialised.otml} (100%) rename data/fonts/{tibia-10px-monochrome.yml => tibia-10px-monochrome.otml} (100%) rename data/fonts/{tibia-12px-rounded.yml => tibia-12px-rounded.otml} (100%) rename data/fonts/{tibia-8px-antialised.yml => tibia-8px-antialised.otml} (100%) create mode 100644 data/modules/core/aliases.lua create mode 100644 data/modules/core/core.lua create mode 100644 data/modules/core/enums.lua create mode 100644 data/modules/core/module.otml create mode 100644 data/modules/core/util.lua create mode 100644 data/modules/mainmenu/entergame.lua create mode 100644 data/modules/mainmenu/init.lua delete mode 100644 data/modules/mainmenu/menustate.lua rename data/modules/mainmenu/{module.yml => module.otml} (100%) rename data/modules/mainmenu/{entergamewindow.yml => ui/entergamewindow.otml} (91%) rename data/modules/mainmenu/{infowindow.yml => ui/infowindow.otml} (100%) rename data/modules/mainmenu/{mainmenu.yml => ui/mainmenu.otml} (66%) rename data/modules/mainmenu/{optionswindow.yml => ui/optionswindow.otml} (100%) delete mode 100644 data/modules/messagebox/messagebox.yml create mode 100644 data/modules/messagebox/module.otml rename data/skins/{lightness.yml => lightness.otml} (100%) rename data/skins/{tibiaskin.yml => tibiaskin.otml} (100%) delete mode 100644 src/framework/ui/uiconstants.h diff --git a/data/fonts/sans-11px-bold.yml b/data/fonts/sans-11px-bold.otml similarity index 100% rename from data/fonts/sans-11px-bold.yml rename to data/fonts/sans-11px-bold.otml diff --git a/data/fonts/sans-12px-bold.yml b/data/fonts/sans-12px-bold.otml similarity index 100% rename from data/fonts/sans-12px-bold.yml rename to data/fonts/sans-12px-bold.otml diff --git a/data/fonts/tibia-10px-antialised.yml b/data/fonts/tibia-10px-antialised.otml similarity index 100% rename from data/fonts/tibia-10px-antialised.yml rename to data/fonts/tibia-10px-antialised.otml diff --git a/data/fonts/tibia-10px-monochrome.yml b/data/fonts/tibia-10px-monochrome.otml similarity index 100% rename from data/fonts/tibia-10px-monochrome.yml rename to data/fonts/tibia-10px-monochrome.otml diff --git a/data/fonts/tibia-12px-rounded.yml b/data/fonts/tibia-12px-rounded.otml similarity index 100% rename from data/fonts/tibia-12px-rounded.yml rename to data/fonts/tibia-12px-rounded.otml diff --git a/data/fonts/tibia-8px-antialised.yml b/data/fonts/tibia-8px-antialised.otml similarity index 100% rename from data/fonts/tibia-8px-antialised.yml rename to data/fonts/tibia-8px-antialised.otml diff --git a/data/modules/core/aliases.lua b/data/modules/core/aliases.lua new file mode 100644 index 00000000..e89d69bc --- /dev/null +++ b/data/modules/core/aliases.lua @@ -0,0 +1,4 @@ +-- some aliases +loadUI = UI.load +rootUI = UI.getRootContainer() + diff --git a/data/modules/core/core.lua b/data/modules/core/core.lua new file mode 100644 index 00000000..604b5cad --- /dev/null +++ b/data/modules/core/core.lua @@ -0,0 +1,4 @@ +require 'aliases' +require 'enums' +require 'util' + diff --git a/data/modules/core/enums.lua b/data/modules/core/enums.lua new file mode 100644 index 00000000..0692d973 --- /dev/null +++ b/data/modules/core/enums.lua @@ -0,0 +1,8 @@ +-- AnchorPoint +AnchorNone = 0 +AnchorTop = 1 +AnchorBottom = 2 +AnchorLeft = 3 +AnchorRight = 4 +AnchorVerticalCenter = 5 +AnchorHorizontalCenter = 6 diff --git a/data/modules/core/module.otml b/data/modules/core/module.otml new file mode 100644 index 00000000..5fa85e5e --- /dev/null +++ b/data/modules/core/module.otml @@ -0,0 +1,8 @@ +title: Core +notes: Core utilities used by other modules +author: edubart +version: 1 +website: https://github.com/edubart/otclient +enabled: true +script: core.lua + diff --git a/data/modules/core/util.lua b/data/modules/core/util.lua new file mode 100644 index 00000000..7e9c6c4f --- /dev/null +++ b/data/modules/core/util.lua @@ -0,0 +1,5 @@ +function createEmptyFunction() + local emptyFunction = function() end + return emptyFunction +end + diff --git a/data/modules/mainmenu/entergame.lua b/data/modules/mainmenu/entergame.lua new file mode 100644 index 00000000..2648c56a --- /dev/null +++ b/data/modules/mainmenu/entergame.lua @@ -0,0 +1,57 @@ +function EnterGame_connectToLoginServer() + -- create login protocol + local protocolLogin = ProtocolLogin.new() + + -- used to recreate enter game window + local recreateEnterGame = function() + loadUI("ui/entergamewindow") + end + + -- display loading message box + local loadBox = displayCancelBox("Please wait", "Connecting..") + + -- cancel loading callback + loadBox.onCancel = function() + -- cancel protocol and reacreate enter game window + protocolLogin:cancel() + recreateEnterGame() + end + + -- error callback + protocolLogin.onError = function(error) + -- destroy loading message box + loadBox:destroy() + + -- display error message + local errorBox = displayErrorBox("Login Error", error) + + -- cancel protocol and reacreate enter game window + self.cancel() + errorBox.onOk = recreateEnterGame + end + + -- motd callback + protocolLogin.onMotd = function(motd) + -- destroy loading message box + loadBox:destroy() + + -- display motd + local motdNumber = string.sub(motd, 0, string.find(motd, "\n")) + local motdText = string.sub(motd, string.find(motd, "\n") + 1, string.len(motd)) + local motdBox = displayInfoBox("Message of the day", motdText) + + -- cancel protocol and reacreate enter game window + self.cancel() + motdBox.onOk = recreateEnterGame + end + + -- get account and password and login + local enterGameWindow = rootUI:child("enterGameWindow") + local account = enterGameWindow:child("accountNameTextEdit").text + local password = enterGameWindow:child("passwordTextEdit").text + protocolLogin:login(account, password) + + -- destroy enter game window + enterGameWindow:destroy() +end + diff --git a/data/modules/mainmenu/init.lua b/data/modules/mainmenu/init.lua new file mode 100644 index 00000000..bce7aeb4 --- /dev/null +++ b/data/modules/mainmenu/init.lua @@ -0,0 +1,16 @@ +require 'entergame' + +function initializeApplication() + mainMenu = loadUI("ui/mainmenu") +end + +function terminateApplication() + App.exit() +end + +-- here is where everything starts +if not initialized then + initializeApplication() + App.onClose = terminateApplication + initialized = true +end diff --git a/data/modules/mainmenu/menustate.lua b/data/modules/mainmenu/menustate.lua deleted file mode 100644 index 82bca65b..00000000 --- a/data/modules/mainmenu/menustate.lua +++ /dev/null @@ -1,63 +0,0 @@ --- menu state -function onEnterMenuState() - mainMenu = UI.load("mainmenu.yml") -end - -function onLeaveMenuState() - -end - -function onApplicationClose() - onLeaveMenuState() - App.exit() -end - -function enterGame_onOkClicked() - local enterGameWindow = UI.getRootContainer():child("enterGameWindow") - enterGameWindow.visible = false - - local loadMessageBox = messageBox("Please wait", "Connecting..") - loadMessageBox.onDestroy = function() - --TODO: cancel protocol - enterGameWindow.visible = true - protocolLogin = nil - end - - protocolLogin = ProtocolLogin.new() - protocolLogin.onError = function(error) - loadMessageBox.onDestroy = nil - loadMessageBox:destroy() - local msgBox = messageBox("Login Error", error) - msgBox.onDestroy = function() - enterGameWindow.visible = true - end - protocolLogin = nil - end - protocolLogin.onMotd = function(motd) - loadMessageBox.onDestroy = nil - loadMessageBox:destroy() - - local motdNumber = string.sub(motd, 0, string.find(motd, "\n")) - local motdText = string.sub(motd, string.find(motd, "\n") + 1, string.len(motd)) - - local msgBox = messageBox("Message of the day", motdText) - msgBox.onDestroy = function() - enterGameWindow.visible = true - end - protocolLogin = nil - end - - local account = enterGameWindow:child("accountNameTextEdit").text - local password = enterGameWindow:child("passwordTextEdit").text - account = "tibialua0" - password = "lua123456" - - protocolLogin:login(account, password) -end - --- here is where everything starts -if not initialStateLoaded then - onEnterMenuState() - App.onClose = onApplicationClose - initialStateLoaded = true -end diff --git a/data/modules/mainmenu/module.yml b/data/modules/mainmenu/module.otml similarity index 100% rename from data/modules/mainmenu/module.yml rename to data/modules/mainmenu/module.otml diff --git a/data/modules/mainmenu/entergamewindow.yml b/data/modules/mainmenu/ui/entergamewindow.otml similarity index 91% rename from data/modules/mainmenu/entergamewindow.yml rename to data/modules/mainmenu/ui/entergamewindow.otml index 857275a4..524920c5 100644 --- a/data/modules/mainmenu/entergamewindow.yml +++ b/data/modules/mainmenu/ui/entergamewindow.otml @@ -3,7 +3,7 @@ size: [236, 178] anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter - onLoad: self.locked = true + onLoad: self:setLocked() %label#accountNameLabel text: Account name @@ -34,7 +34,7 @@ anchors.top: parent.top margin.top: 94 margin.left: 132 - onClick: messageBox("Error", "Not implemented yet") + onClick: displayErrorBox("Error", "Not implemented yet") %button#okButton text: Ok @@ -43,7 +43,7 @@ anchors.bottom: parent.bottom margin.bottom: 10 margin.right: 66 - onClick: enterGame_onOkClicked() + onClick: EnterGame_connectToLoginServer() %button#cancelButton text: Cancel diff --git a/data/modules/mainmenu/infowindow.yml b/data/modules/mainmenu/ui/infowindow.otml similarity index 100% rename from data/modules/mainmenu/infowindow.yml rename to data/modules/mainmenu/ui/infowindow.otml diff --git a/data/modules/mainmenu/mainmenu.yml b/data/modules/mainmenu/ui/mainmenu.otml similarity index 66% rename from data/modules/mainmenu/mainmenu.yml rename to data/modules/mainmenu/ui/mainmenu.otml index e5dc3f6a..68f830ae 100644 --- a/data/modules/mainmenu/mainmenu.yml +++ b/data/modules/mainmenu/ui/mainmenu.otml @@ -5,22 +5,6 @@ anchors.top: parent.top anchors.bottom: parent.bottom - %panel#icos4d - skin: - image: /skins/lightness/mouse.png - anchors.left: parent.left - anchors.top: parent.top - margin.left: -2 - margin.top: 70 - - %panel#mouse - skin: - image: /skins/lightness/icos4d.png - anchors.right: parent.right - anchors.bottom: parent.bottom - margin.left: 60 - margin.top: 70 - %panel#mainMenu skin: roundedGridPanel size: [117, 171] @@ -34,32 +18,32 @@ anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter margin.top: 16 - onClick: UI.load("entergamewindow.yml") + onClick: UI.load("entergamewindow") %button#accessAccountButton text: Access Account anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter margin.top: 46 - onClick: messageBox("Error", "Not implemented yet") + onClick: displayErrorBox("Error", "Not implemented yet") %button#optionsButton text: Options anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter margin.top: 76 - onClick: UI.load("optionswindow.yml") + onClick: UI.load("optionswindow") %button#infoButton text: Info anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter margin.top: 106 - onClick: UI.load("infowindow.yml") + onClick: UI.load("infowindow") %button#exitGameButton text: Exit anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter margin.top: 136 - onClick: onApplicationClose() + onClick: terminateApplication() diff --git a/data/modules/mainmenu/optionswindow.yml b/data/modules/mainmenu/ui/optionswindow.otml similarity index 100% rename from data/modules/mainmenu/optionswindow.yml rename to data/modules/mainmenu/ui/optionswindow.otml diff --git a/data/modules/messagebox/messagebox.lua b/data/modules/messagebox/messagebox.lua index 01386656..b4369a06 100644 --- a/data/modules/messagebox/messagebox.lua +++ b/data/modules/messagebox/messagebox.lua @@ -1,34 +1,86 @@ MessageBox = {} MessageBox.__index = MessageBox -function MessageBox.create(title, text) - local msgBox = {} - setmetatable(msgBox, MessageBox) - - local window = UI.load("messagebox.yml") - window.locked = true - window.title = title - window:child("textLabel").text = text - window:child("okButton").onClick = function() - self.parent:destroy() - end - window.onDestroy = function() - if msgBox.onDestroy then - msgBox.onDestroy() - end - end - - msgBox.window = window - return msgBox +-- messagebox flags +MessageBoxOk = 1 +MessageBoxCancel = 2 + +function MessageBox.create(title, text, flags) + local box = {} + setmetatable(box, MessageBox) + + -- create messagebox window + local window = UIWindow.new("messageBoxWindow", rootUI) + window.title = title + window:centerIn(rootUI) + window:setLocked() + + -- create messagebox label + local label = UILabel.new("messageBoxLabel", window) + label.text = text + label:addAnchor(AnchorHorizontalCenter, window, AnchorHorizontalCenter) + label:addAnchor(AnchorTop, window, AnchorTop) + label:setMargin(27, 0) + + -- set window size based on label size + window.width = label.width + 40 + window.height = label.height + 64 + + -- setup messagebox first button + local buttonText + local button1 = UIButton.new("messageBoxButton1", window) + button1:addAnchor(AnchorBottom, window, AnchorBottom) + button1:addAnchor(AnchorRight, window, AnchorRight) + button1:setMargin(10) + + if flags == MessageBoxOk then + buttonText = "Ok" + box.onOk = createEmptyFunction() + button1.onClick = function() + box.onOk() + box:destroy() + end + elseif flags == MessageBoxCancel then + buttonText = "Cancel" + box.onCancel = createEmptyFunction() + button1.onClick = function() + box.onCancel() + box:destroy() + end + end + button1.text = buttonText + + box.window = window + return box end function MessageBox:destroy() - if self.window then - self.window:destroy() - self.window = nil - end + if self.onDestroy then + self.onDestroy() + self.onDestroy = nil + end + if self.window then + self.window:destroy() + self.window = nil + end + self.onOk = nil + self.onCancel = nil +end + +-- shortcuts for creating message boxes +function displayMessageBox(title, text, flags) + return MessageBox.create(title, text, flags) +end + +function displayErrorBox(title, text) + return MessageBox.create(title, text, MessageBoxOk) +end + +function displayInfoBox(title, text) + return MessageBox.create(title, text, MessageBoxOk) end -function messageBox(title, text) - return MessageBox.create(title, text) +function displayCancelBox(title, text) + return MessageBox.create(title, text, MessageBoxCancel) end + diff --git a/data/modules/messagebox/messagebox.yml b/data/modules/messagebox/messagebox.yml deleted file mode 100644 index 778f04d5..00000000 --- a/data/modules/messagebox/messagebox.yml +++ /dev/null @@ -1,18 +0,0 @@ -%window#messageBoxWindow - size: [192, 78] - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - - - %label#textLabel - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - margin.top: 27 - - %button#okButton - text: Ok - size: [43, 20] - anchors.right: parent.right - anchors.bottom: parent.bottom - margin.bottom: 10 - margin.right: 10 diff --git a/data/modules/messagebox/module.otml b/data/modules/messagebox/module.otml new file mode 100644 index 00000000..9e132246 --- /dev/null +++ b/data/modules/messagebox/module.otml @@ -0,0 +1,8 @@ +title: Message box +notes: Functions for creating message boxes +author: edubart +version: 1 +website: https://github.com/edubart/otclient +enabled: true +script: messagebox.lua + diff --git a/data/skins/lightness.yml b/data/skins/lightness.otml similarity index 100% rename from data/skins/lightness.yml rename to data/skins/lightness.otml diff --git a/data/skins/tibiaskin.yml b/data/skins/tibiaskin.otml similarity index 100% rename from data/skins/tibiaskin.yml rename to data/skins/tibiaskin.otml diff --git a/src/framework/otml/otmlparser.cpp b/src/framework/otml/otmlparser.cpp index 9dcf9641..e4ec96a4 100644 --- a/src/framework/otml/otmlparser.cpp +++ b/src/framework/otml/otmlparser.cpp @@ -5,8 +5,8 @@ OTMLParser::OTMLParser(std::istream& in, std::string what) : m_currentDepth(0), m_currentLine(0), - m_rootNode(new OTMLNode), m_currentParent(m_rootNode), m_previousNode(0), - m_what(what), m_in(in) + m_rootNode(new OTMLNode(what)), m_currentParent(m_rootNode), m_previousNode(0), + m_in(in) { parse(); } @@ -20,8 +20,8 @@ void OTMLParser::throwError(const std::string& message, int line) { std::stringstream ss; ss << "OTML syntax error"; - if(!m_what.empty()) - ss << " in '" << m_what << "'"; + if(!what().empty()) + ss << " in '" << what() << "'"; if(line > 0) ss << " at line " << line; ss << ": " << message; diff --git a/src/framework/otml/otmlparser.h b/src/framework/otml/otmlparser.h index c23ee42c..4038488e 100644 --- a/src/framework/otml/otmlparser.h +++ b/src/framework/otml/otmlparser.h @@ -1,11 +1,9 @@ #ifndef OTMLPARSER_H #define OTMLPARSER_H -#include -#include -#include +#include -class OTMLNode; +#include class OTMLParser { @@ -14,7 +12,7 @@ public: ~OTMLParser(); OTMLNode* getDocument() const { return m_rootNode; } - std::string what() { return m_what; } + std::string what() { return m_rootNode->what(); } void throwError(const std::string& message, int line); @@ -33,7 +31,6 @@ private: OTMLNode* m_rootNode; OTMLNode* m_currentParent; OTMLNode* m_previousNode; - std::string m_what; std::istream& m_in; }; diff --git a/src/framework/script/scriptcontext.cpp b/src/framework/script/scriptcontext.cpp index a9347cda..b356d075 100644 --- a/src/framework/script/scriptcontext.cpp +++ b/src/framework/script/scriptcontext.cpp @@ -593,7 +593,7 @@ int ScriptContext::luaPackageLoader(lua_State* L) if(g_resources.fileExists(fileName)) { std::stringstream fin; if(g_resources.loadFile(fileName, fin)) - luaL_loadbuffer(L, fin.str().c_str(), fin.str().length(), fileName.c_str()); + luaL_loadbuffer(L, fin.str().c_str(), fin.str().length(), ("@" + g_resources.resolvePath(fileName)).c_str()); } else { lua_pushfstring(L, "\n\tcould not load lua script " LUA_QS, fileName.c_str()); } diff --git a/src/framework/script/scriptfunctions.cpp b/src/framework/script/scriptfunctions.cpp index 023622b6..2a150385 100644 --- a/src/framework/script/scriptfunctions.cpp +++ b/src/framework/script/scriptfunctions.cpp @@ -7,112 +7,116 @@ #include #include "../../protocollogin.h" -void registerScriptFunctions() -{ - // App - g_lua.registerModule("App"); - g_lua.registerMemberFunction("exit", &lua_App_exit); - - // UI - g_lua.registerClass("UI"); - g_lua.registerMemberFunction("load", &lua_UI_load); - g_lua.registerMemberFunction("getRootContainer", &lua_UI_getRootContainer); - - // UIElement - g_lua.registerClass("UIElement"); - g_lua.registerMemberField("id", &lua_UIElement_getId, &lua_UIElement_setId); - g_lua.registerMemberField("enabled", &lua_UIElement_isEnabled, &lua_UIElement_setEnabled); - g_lua.registerMemberField("visible", &lua_UIElement_isVisible, &lua_UIElement_setVisible); - g_lua.registerMemberField("focused", &lua_UIElement_isFocused, &lua_UIElement_setFocused); - g_lua.registerMemberField("parent", &lua_UIElement_getParent, &lua_UIElement_setParent); - g_lua.registerMemberField("locked", NULL, &lua_UIElement_setLocked); - g_lua.registerMemberFunction("destroy", &lua_UIElement_destroy); - - // UIContainer - g_lua.registerClass("UIContainer", "UIElement"); - g_lua.registerMemberFunction("child", &lua_UIContainer_getChild); - g_lua.registerMemberFunction("children", &lua_UIContainer_getChildren); - - // UILabel - g_lua.registerClass("UILabel", "UIElement"); - g_lua.registerMemberField("text", &lua_UILabel_getText, &lua_UILabel_setText); - - // UIButton - g_lua.registerClass("UIButton", "UIElement"); - - // UITextEdit - g_lua.registerClass("UITextEdit", "UIElement"); - g_lua.registerMemberField("text", &lua_UITextEdit_getText, &lua_UITextEdit_setText); - - // UIWindow - g_lua.registerClass("UIWindow", "UIContainer"); - g_lua.registerMemberField("title", &lua_UIWindow_getTitle, &lua_UIWindow_setTitle); - - // Protocol - g_lua.registerClass("ProtocolLogin"); - g_lua.registerMemberFunction("new", []{ - ProtocolLoginPtr protocolLogin(new ProtocolLogin); - g_lua.pushClassInstance(protocolLogin); - return 1; - }); - g_lua.registerMemberFunction("login", []{ - std::string accountPassword = g_lua.popString(); - std::string accountName = g_lua.popString(); - if(ProtocolLoginPtr protocolLogin = boost::dynamic_pointer_cast(g_lua.popClassInstance())) - protocolLogin->login(accountName, accountPassword); - return 0; - }); - -} +#include //////////////////////////////////////////////////////////////////////////////// -// App module +// App -int lua_App_exit() -{ +int lua_App_exit() { g_engine.stop(); - return 1; + return 0; } + //////////////////////////////////////////////////////////////////////////////// -// UI module +// UI -int lua_UI_load() -{ +int lua_UI_load() { UIContainerPtr parent; - if(g_lua.getStackSize() > 1) { + if(g_lua.getStackSize() > 1) parent = boost::dynamic_pointer_cast(g_lua.popClassInstance()); - } else { + else parent = UIContainer::getRoot(); - } std::string uiFile = g_lua.popString(); + if(!boost::ends_with(uiFile, ".otml")) + uiFile.append(".otml"); + UIElementPtr element; - if(parent) + if(parent) { element = g_uiLoader.loadFromFile(uiFile.c_str(), parent); - else - g_lua.reportErrorWithTraceback("invalid parent container"); + if(!element) { + g_lua.reportFuncErrorWithTraceback("failed to load UI"); + } + } else + g_lua.reportFuncErrorWithTraceback("invalid parent container"); g_lua.pushClassInstance(element); return 1; } -int lua_UI_getRootContainer() -{ +int lua_UI_getRootContainer() { UIContainerPtr rootContainer = UIContainer::getRoot(); g_lua.pushClassInstance(rootContainer); return 1; } + //////////////////////////////////////////////////////////////////////////////// // UIElement -int lua_UIElement_getId() +UIElementPtr lua_createUIElement(UI::ElementType elementType) { + std::string id; + UIContainerPtr parent; + + if(g_lua.getStackSize() > 1) + parent = boost::dynamic_pointer_cast(g_lua.popClassInstance()); + + if(g_lua.getStackSize() > 0) { + if(g_lua.isString()) + id = g_lua.popString(); + else + parent = boost::dynamic_pointer_cast(g_lua.popClassInstance()); + } + + UIElementPtr element; + switch(elementType) { + case UI::Element: + element = UIElementPtr(new UIElement); + break; + case UI::Container: + element = UIElementPtr(new UIContainer); + break; + case UI::Label: + element = UIElementPtr(new UILabel); + break; + case UI::Button: + element = UIElementPtr(new UIButton); + break; + case UI::TextEdit: + element = UIElementPtr(new UITextEdit); + break; + case UI::Window: + element = UIElementPtr(new UIWindow); + break; + default: + break; + } + + if(element) { + if(!id.empty()) + element->setId(id); + + if(parent) + parent->addChild(element); + + element->applyDefaultSkin(); + } + + return element; +} + +int lua_UIElement_new() { + g_lua.pushClassInstance(lua_createUIElement(UI::Element)); + return 1; +} + +int lua_UIElement_getId() { if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) g_lua.pushString(element->getId()); else @@ -120,16 +124,14 @@ int lua_UIElement_getId() return 1; } -int lua_UIElement_setId() -{ +int lua_UIElement_setId() { std::string id = g_lua.popString(); if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) element->setId(id); - return 1; + return 0; } -int lua_UIElement_isEnabled() -{ +int lua_UIElement_isEnabled() { if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) g_lua.pushBoolean(element->isEnabled()); else @@ -137,16 +139,14 @@ int lua_UIElement_isEnabled() return 1; } -int lua_UIElement_setEnabled() -{ +int lua_UIElement_setEnabled() { bool enabled = g_lua.popBoolean(); if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) element->setEnabled(enabled); - return 1; + return 0; } -int lua_UIElement_isVisible() -{ +int lua_UIElement_isVisible() { if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) g_lua.pushBoolean(element->isVisible()); else @@ -154,16 +154,14 @@ int lua_UIElement_isVisible() return 1; } -int lua_UIElement_setVisible() -{ +int lua_UIElement_setVisible() { bool visible = g_lua.popBoolean(); if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) element->setVisible(visible); - return 1; + return 0; } -int lua_UIElement_isFocused() -{ +int lua_UIElement_isFocused() { if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) g_lua.pushBoolean(element->isFocused()); else @@ -171,16 +169,44 @@ int lua_UIElement_isFocused() return 1; } -int lua_UIElement_setFocused() -{ +int lua_UIElement_setFocused() { bool focused = g_lua.popBoolean(); if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) element->setFocused(focused); + return 0; +} + +int lua_UIElement_getWidth() { + if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) + g_lua.pushInteger(element->getWidth()); + else + g_lua.pushInteger(0); return 1; } -int lua_UIElement_getParent() -{ +int lua_UIElement_setWidth() { + int width = g_lua.popInteger(); + if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) + element->setWidth(width); + return 0; +} + +int lua_UIElement_getHeight() { + if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) + g_lua.pushInteger(element->getHeight()); + else + g_lua.pushInteger(0); + return 1; +} + +int lua_UIElement_setHeight() { + int height = g_lua.popInteger(); + if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) + element->setHeight(height); + return 0; +} + +int lua_UIElement_getParent() { if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) g_lua.pushClassInstance(element->getParent()); else @@ -188,44 +214,98 @@ int lua_UIElement_getParent() return 1; } -int lua_UIElement_setParent() -{ +int lua_UIElement_setParent() { UIContainerPtr parent = boost::dynamic_pointer_cast(g_lua.popClassInstance()); if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) element->setParent(parent); - return 1; + return 0; } -int lua_UIElement_setLocked() -{ - bool locked = g_lua.popBoolean(); +int lua_UIElement_setLocked() { + bool locked = true; + if(g_lua.getStackSize() > 1) + locked = g_lua.popBoolean(); + if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) { if(UIContainerPtr container = element->getParent()) { if(locked) container->lockElement(element); else container->unlockElement(element); - } + } else + g_lua.reportFuncErrorWithTraceback("locking failed, element has no parent"); + } + + return 0; +} + +int lua_UIElement_setMargin() { + int top = 0, right = 0, bottom = 0, left = 0; + if(g_lua.getStackSize() == 5) { + left = g_lua.popInteger(); + bottom = g_lua.popInteger(); + right = g_lua.popInteger(); + top = g_lua.popInteger(); + } else if(g_lua.getStackSize() == 3) { + left = right = g_lua.popInteger(); + top = bottom = g_lua.popInteger(); + } else if(g_lua.getStackSize() == 2) { + top = right = bottom = left = g_lua.popInteger(); } else { - g_lua.reportFuncErrorWithTraceback("invalid element"); + g_lua.reportFuncErrorWithTraceback("invalid number of arguments"); } - return 1; + + if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) + element->setMargin(top, right, bottom, left); + return 0; } -int lua_UIElement_destroy() -{ +int lua_UIElement_destroy() { if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) element->destroyLater(); g_dispatcher.addTask(boost::bind(&ScriptContext::collectGarbage, &g_lua)); - return 1; + return 0; } +int lua_UIElement_centerIn() { + std::string targetId; + if(g_lua.isString()) + targetId = g_lua.popString(); + else if(UIElementPtr target = boost::dynamic_pointer_cast(g_lua.popClassInstance())) + targetId = target->getId(); + + if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) + element->centerIn(targetId); + return 0; +} + +int lua_UIElement_addAnchor() { + AnchorPoint targetEdge = (AnchorPoint)g_lua.popInteger(); + + std::string targetId; + if(g_lua.isString()) + targetId = g_lua.popString(); + else if(UIElementPtr target = boost::dynamic_pointer_cast(g_lua.popClassInstance())) + targetId = target->getId(); + + AnchorPoint anchoredEdge = (AnchorPoint)g_lua.popInteger(); + + if(UIElementPtr element = boost::dynamic_pointer_cast(g_lua.popClassInstance())) + element->addAnchor(anchoredEdge, AnchorLine(targetId, targetEdge)); + return 0; +} + + //////////////////////////////////////////////////////////////////////////////// // UIContainer -int lua_UIContainer_getChild() -{ +int lua_UIContainer_new() { + g_lua.pushClassInstance(lua_createUIElement(UI::Container)); + return 1; +} + +int lua_UIContainer_child() { std::string id = g_lua.popString(); if(UIContainerPtr container = boost::dynamic_pointer_cast(g_lua.popClassInstance())) g_lua.pushClassInstance(container->getChildById(id)); @@ -234,8 +314,7 @@ int lua_UIContainer_getChild() return 1; } -int lua_UIContainer_getChildren() -{ +int lua_UIContainer_getChildren() { if(UIContainerPtr container = boost::dynamic_pointer_cast(g_lua.popClassInstance())) { g_lua.newTable(); foreach(const UIElementPtr& child, container->getChildren()) { @@ -248,19 +327,32 @@ int lua_UIContainer_getChildren() return 1; } +int lua_UIContainer_addChild() { + UIElementPtr child = boost::dynamic_pointer_cast(g_lua.popClassInstance()); + UIContainerPtr container = boost::dynamic_pointer_cast(g_lua.popClassInstance()); + if(container && child) + container->addChild(child); + return 0; +} + + + //////////////////////////////////////////////////////////////////////////////// // UILabel -int lua_UILabel_setText() -{ +int lua_UILabel_new() { + g_lua.pushClassInstance(lua_createUIElement(UI::Label)); + return 1; +} + +int lua_UILabel_setText() { std::string text = g_lua.popString(); if(UILabelPtr label = boost::dynamic_pointer_cast(g_lua.popClassInstance())) label->setText(text); - return 1; + return 0; } -int lua_UILabel_getText() -{ +int lua_UILabel_getText() { if(UILabelPtr label = boost::dynamic_pointer_cast(g_lua.popClassInstance())) g_lua.pushString(label->getText()); else @@ -269,19 +361,48 @@ int lua_UILabel_getText() } + //////////////////////////////////////////////////////////////////////////////// -// UILabel +// UIButton -int lua_UITextEdit_setText() -{ +int lua_UIButton_new() { + g_lua.pushClassInstance(lua_createUIElement(UI::Button)); + return 1; +} + +int lua_UIButton_setText() { + std::string text = g_lua.popString(); + if(UIButtonPtr button = boost::dynamic_pointer_cast(g_lua.popClassInstance())) + button->setText(text); + return 0; +} + +int lua_UIButton_getText() { + if(UIButtonPtr button = boost::dynamic_pointer_cast(g_lua.popClassInstance())) + g_lua.pushString(button->getText()); + else + g_lua.pushNil(); + return 1; +} + + + +//////////////////////////////////////////////////////////////////////////////// +// UITextEdit + +int lua_UITextEdit_new() { + g_lua.pushClassInstance(lua_createUIElement(UI::TextEdit)); + return 1; +} + +int lua_UITextEdit_setText() { std::string text = g_lua.popString(); if(UITextEditPtr textEdit = boost::dynamic_pointer_cast(g_lua.popClassInstance())) textEdit->setText(text); - return 1; + return 0; } -int lua_UITextEdit_getText() -{ +int lua_UITextEdit_getText() { if(UITextEditPtr textEdit = boost::dynamic_pointer_cast(g_lua.popClassInstance())) g_lua.pushString(textEdit->getText()); else @@ -289,22 +410,152 @@ int lua_UITextEdit_getText() return 1; } + + //////////////////////////////////////////////////////////////////////////////// // UIWindow -int lua_UIWindow_setTitle() -{ +int lua_UIWindow_new() { + g_lua.pushClassInstance(lua_createUIElement(UI::Window)); + return 1; +} + +int lua_UIWindow_setTitle() { std::string title = g_lua.popString(); if(UIWindowPtr window = boost::dynamic_pointer_cast(g_lua.popClassInstance())) window->setTitle(title); - return 1; + return 0; } -int lua_UIWindow_getTitle() -{ +int lua_UIWindow_getTitle() { if(UIWindowPtr window = boost::dynamic_pointer_cast(g_lua.popClassInstance())) g_lua.pushString(window->getTitle()); else g_lua.pushNil(); return 1; } + + + +void registerScriptFunctions() +{ + //////////////////////////////////////////////////////////////////////////////// + // App + g_lua.registerModule("App"); + // App.exit() + g_lua.registerMemberFunction("exit", &lua_App_exit); + + + //////////////////////////////////////////////////////////////////////////////// + // UI + g_lua.registerClass("UI"); + // UI.load(file, [parent]) + g_lua.registerMemberFunction("load", &lua_UI_load); + // UI.getRootContainer() + g_lua.registerMemberFunction("getRootContainer", &lua_UI_getRootContainer); + + + //////////////////////////////////////////////////////////////////////////////// + // UIElement + g_lua.registerClass("UIElement"); + // (UIElement) UIElement.new([UIContainer parent], [string id]) + g_lua.registerMemberFunction("new", &lua_UIElement_new); + // (string) UIElement.id + g_lua.registerMemberField("id", &lua_UIElement_getId, &lua_UIElement_setId); + // (boolean) UIElement.enabled + g_lua.registerMemberField("enabled", &lua_UIElement_isEnabled, &lua_UIElement_setEnabled); + // (boolean UIElement.visible + g_lua.registerMemberField("visible", &lua_UIElement_isVisible, &lua_UIElement_setVisible); + // (boolean UIElement.focused + g_lua.registerMemberField("focused", &lua_UIElement_isFocused, &lua_UIElement_setFocused); + // (integer) UIElement.width + g_lua.registerMemberField("width", &lua_UIElement_getWidth, &lua_UIElement_setWidth); + // (integer) UIElement.height + g_lua.registerMemberField("height", &lua_UIElement_getHeight, &lua_UIElement_setHeight); + // (UIContainer UIElement.parent + g_lua.registerMemberField("parent", &lua_UIElement_getParent, &lua_UIElement_setParent); + // element:setLocked(boolean locked) + g_lua.registerMemberFunction("setLocked", &lua_UIElement_setLocked); + // element:setMargin(int all) + // element:setMargin(int vertical, int horizontal) + // element:setMargin(int top, right, bottom, left) + g_lua.registerMemberFunction("setMargin", &lua_UIElement_setMargin); + // element:destroy() + g_lua.registerMemberFunction("destroy", &lua_UIElement_destroy); + // element:centerIn(UIContainer target) + g_lua.registerMemberFunction("centerIn", &lua_UIElement_centerIn); + // element:addAnchor(AnchorPoint anchoredEdge, UIElement target, AnchorPoint targetEdge) + // element:addAnchor(AnchorPoint anchoredEdge, string targetId, AnchorPoint targetEdge) + g_lua.registerMemberFunction("addAnchor", &lua_UIElement_addAnchor); + + + //////////////////////////////////////////////////////////////////////////////// + // UIContainer + g_lua.registerClass("UIContainer", "UIElement"); + // UIContainer.new([UIContainer parent], [string id]) + g_lua.registerMemberFunction("new", &lua_UIContainer_new); + // container:child(string id) + g_lua.registerMemberFunction("child", &lua_UIContainer_child); + // (table) container:children() + g_lua.registerMemberFunction("children", &lua_UIContainer_getChildren); + // container:addChild(UIElement child) + g_lua.registerMemberFunction("addChild", &lua_UIContainer_addChild); + + + //////////////////////////////////////////////////////////////////////////////// + // UILabel + g_lua.registerClass("UILabel", "UIElement"); + // UILabel.new([UIContainer parent], [string id]) + g_lua.registerMemberFunction("new", &lua_UILabel_new); + // label.text + g_lua.registerMemberField("text", &lua_UILabel_getText, &lua_UILabel_setText); + + + //////////////////////////////////////////////////////////////////////////////// + // UIButton + g_lua.registerClass("UIButton", "UIElement"); + // UIButton.new([UIContainer parent], [string id]) + g_lua.registerMemberFunction("new", &lua_UIButton_new); + // button.text + g_lua.registerMemberField("text", &lua_UIButton_getText, &lua_UIButton_setText); + + + //////////////////////////////////////////////////////////////////////////////// + // UITextEdit + g_lua.registerClass("UITextEdit", "UIElement"); + // UITextEdit.new([UIContainer parent], [string id]) + g_lua.registerMemberFunction("new", &lua_UITextEdit_new); + // textEdit.text + g_lua.registerMemberField("text", &lua_UITextEdit_getText, &lua_UITextEdit_setText); + + + //////////////////////////////////////////////////////////////////////////////// + // UIWindow + g_lua.registerClass("UIWindow", "UIContainer"); + // UIWindow.new([UIContainer parent], [string id]) + g_lua.registerMemberFunction("new", &lua_UIWindow_new); + // window.title + g_lua.registerMemberField("title", &lua_UIWindow_getTitle, &lua_UIWindow_setTitle); + + + //////////////////////////////////////////////////////////////////////////////// + // Protocol + g_lua.registerClass("ProtocolLogin"); + g_lua.registerMemberFunction("new", []{ + g_lua.pushClassInstance(ScriptObjectPtr(new ProtocolLogin)); + return 1; + }); + g_lua.registerMemberFunction("login", []{ + std::string accountPassword = g_lua.popString(); + std::string accountName = g_lua.popString(); + if(ProtocolLoginPtr protocolLogin = boost::dynamic_pointer_cast(g_lua.popClassInstance())) + protocolLogin->login(accountName, accountPassword); + return 0; + }); + g_lua.registerMemberFunction("cancel", []{ + //TODO: this func + return 0; + }); +} + + diff --git a/src/framework/script/scriptfunctions.h b/src/framework/script/scriptfunctions.h index d5767885..f7269566 100644 --- a/src/framework/script/scriptfunctions.h +++ b/src/framework/script/scriptfunctions.h @@ -7,46 +7,4 @@ void registerScriptFunctions(); -// App -int lua_App_exit(); - -// UI -int lua_UI_load(); -int lua_UI_getRootContainer(); - -// UIElement -int lua_UIElement_getId(); -int lua_UIElement_setId(); -int lua_UIElement_isEnabled(); -int lua_UIElement_setEnabled(); -int lua_UIElement_isVisible(); -int lua_UIElement_setVisible(); -int lua_UIElement_isFocused(); -int lua_UIElement_setFocused(); -int lua_UIElement_getParent(); -int lua_UIElement_setParent(); -int lua_UIElement_setLocked(); -int lua_UIElement_destroy(); -void lua_UIElement_onLoad(); -void lua_UIElement_onDestroy(); - -// UIContainer -int lua_UIContainer_getChild(); -int lua_UIContainer_getChildren(); - -// UILabel -int lua_UILabel_setText(); -int lua_UILabel_getText(); - -// UITextEdit -int lua_UITextEdit_setText(); -int lua_UITextEdit_getText(); - -// UIButton -void lua_UIButton_onClick(); - -// UIWindow -int lua_UIWindow_setTitle(); -int lua_UIWindow_getTitle(); - #endif // SCRIPTFUNCTIONS_H diff --git a/src/framework/ui/ui.h b/src/framework/ui/ui.h index ab83f86a..c726608a 100644 --- a/src/framework/ui/ui.h +++ b/src/framework/ui/ui.h @@ -1,39 +1,12 @@ -/* The MIT License - * - * Copyright (c) 2010 OTClient, https://github.com/edubart/otclient - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - #ifndef UI_H #define UI_H #include -#include #include #include - #include #include - #include #include #include diff --git a/src/framework/ui/uianchorlayout.cpp b/src/framework/ui/uianchorlayout.cpp index 85ac07c2..3427733b 100644 --- a/src/framework/ui/uianchorlayout.cpp +++ b/src/framework/ui/uianchorlayout.cpp @@ -1,5 +1,6 @@ #include #include +#include UIElementPtr Anchor::getAnchorLineElement() const { @@ -13,17 +14,17 @@ int Anchor::getAnchorLinePoint() const UIElementPtr anchorLineElement = getAnchorLineElement(); if(anchorLineElement) { switch(m_anchorLine.getEdge()) { - case UI::AnchorLeft: + case AnchorLeft: return anchorLineElement->getRect().left(); - case UI::AnchorRight: + case AnchorRight: return anchorLineElement->getRect().right(); - case UI::AnchorTop: + case AnchorTop: return anchorLineElement->getRect().top(); - case UI::AnchorBottom: + case AnchorBottom: return anchorLineElement->getRect().bottom(); - case UI::AnchorHorizontalCenter: + case AnchorHorizontalCenter: return anchorLineElement->getRect().horizontalCenter(); - case UI::AnchorVerticalCenter: + case AnchorVerticalCenter: return anchorLineElement->getRect().verticalCenter(); default: break; @@ -31,7 +32,7 @@ int Anchor::getAnchorLinePoint() const } return -9999; } -bool UIAnchorLayout::addAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const AnchorLine& anchorLine) +bool UIAnchorLayout::addAnchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, const AnchorLine& anchorLine) { Anchor anchor(anchoredElement, anchoredEdge, anchorLine); UIElementPtr anchorLineElement = anchor.getAnchorLineElement(); @@ -71,36 +72,36 @@ void UIAnchorLayout::recalculateElementLayout(const UIElementPtr& element) if(anchor.getAnchoredElement() == element && anchor.getAnchorLineElement()) { int point = anchor.getAnchorLinePoint(); switch(anchor.getAnchoredEdge()) { - case UI::AnchorHorizontalCenter: + case AnchorHorizontalCenter: rect.moveHorizontalCenter(point + element->getMarginLeft() - element->getMarginRight()); horizontalMoved = true; break; - case UI::AnchorLeft: + case AnchorLeft: if(!horizontalMoved) { rect.moveLeft(point + element->getMarginLeft()); horizontalMoved = true; } else rect.setLeft(point + element->getMarginLeft()); break; - case UI::AnchorRight: + case AnchorRight: if(!horizontalMoved) { rect.moveRight(point - element->getMarginRight()); horizontalMoved = true; } else rect.setRight(point - element->getMarginRight()); break; - case UI::AnchorVerticalCenter: + case AnchorVerticalCenter: rect.moveVerticalCenter(point + element->getMarginTop() - element->getMarginBottom()); verticalMoved = true; break; - case UI::AnchorTop: + case AnchorTop: if(!verticalMoved) { rect.moveTop(point + element->getMarginTop()); verticalMoved = true; } else rect.setTop(point + element->getMarginTop()); break; - case UI::AnchorBottom: + case AnchorBottom: if(!verticalMoved) { rect.moveBottom(point - element->getMarginBottom()); verticalMoved = true; @@ -139,19 +140,19 @@ bool UIAnchorLayout::hasElementInAnchorTree(const UIElementPtr& element, const U return false; } -UI::AnchorPoint UIAnchorLayout::parseAnchorPoint(const std::string& anchorPointStr) +AnchorPoint UIAnchorLayout::parseAnchorPoint(const std::string& anchorPointStr) { if(anchorPointStr == "left") - return UI::AnchorLeft; + return AnchorLeft; else if(anchorPointStr == "right") - return UI::AnchorRight; + return AnchorRight; else if(anchorPointStr == "top") - return UI::AnchorTop; + return AnchorTop; else if(anchorPointStr == "bottom") - return UI::AnchorBottom; + return AnchorBottom; else if(anchorPointStr == "horizontalCenter") - return UI::AnchorHorizontalCenter; + return AnchorHorizontalCenter; else if(anchorPointStr == "verticalCenter") - return UI::AnchorVerticalCenter; - return UI::AnchorNone; + return AnchorVerticalCenter; + return AnchorNone; } diff --git a/src/framework/ui/uianchorlayout.h b/src/framework/ui/uianchorlayout.h index f72dc489..6de1f399 100644 --- a/src/framework/ui/uianchorlayout.h +++ b/src/framework/ui/uianchorlayout.h @@ -2,48 +2,60 @@ #define UIANCHORLAYOUT_H #include -#include #include -#include + +class UIElement; +typedef boost::shared_ptr UIElementPtr; +typedef boost::weak_ptr UIElementWeakPtr; + +enum AnchorPoint { + AnchorNone = 0, + AnchorTop, + AnchorBottom, + AnchorLeft, + AnchorRight, + AnchorVerticalCenter, + AnchorHorizontalCenter, +}; class AnchorLine { public: - AnchorLine(const std::string& elementId, UI::AnchorPoint edge) : m_elementId(elementId), m_edge(edge) { } + AnchorLine(const std::string& elementId, AnchorPoint edge) : m_elementId(elementId), m_edge(edge) { } AnchorLine(const AnchorLine& other) : m_elementId(other.m_elementId), m_edge(other.m_edge) { } - UI::AnchorPoint getEdge() const { return m_edge; } + AnchorPoint getEdge() const { return m_edge; } const std::string& getElementId() const { return m_elementId; } private: std::string m_elementId; - UI::AnchorPoint m_edge; + AnchorPoint m_edge; }; class Anchor { public: - Anchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const AnchorLine& anchorLine) + Anchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, const AnchorLine& anchorLine) : m_anchoredElement(anchoredElement), m_anchoredEdge(anchoredEdge), m_anchorLine(anchorLine) { } UIElementPtr getAnchorLineElement() const ; UIElementPtr getAnchoredElement() const { return m_anchoredElement.lock(); } - UI::AnchorPoint getAnchoredEdge() const { return m_anchoredEdge; } + AnchorPoint getAnchoredEdge() const { return m_anchoredEdge; } int getAnchorLinePoint() const; private: UIElementWeakPtr m_anchoredElement; - UI::AnchorPoint m_anchoredEdge; + AnchorPoint m_anchoredEdge; AnchorLine m_anchorLine; }; class UIAnchorLayout : public UILayout { public: - bool addAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const AnchorLine& anchorLine); + bool addAnchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, const AnchorLine& anchorLine); void recalculateElementLayout(const UIElementPtr& element); void recalculateChildrenLayout(const UIElementPtr& parent); bool hasElementInAnchorTree(const UIElementPtr& element, const UIElementPtr& treeAnchor); - static UI::AnchorPoint parseAnchorPoint(const std::string& anchorPointStr); + static AnchorPoint parseAnchorPoint(const std::string& anchorPointStr); private: std::vector m_anchors; diff --git a/src/framework/ui/uibuttonskin.h b/src/framework/ui/uibuttonskin.h index b7cf5f78..26a35490 100644 --- a/src/framework/ui/uibuttonskin.h +++ b/src/framework/ui/uibuttonskin.h @@ -2,7 +2,6 @@ #define UIBUTTONSKIN_H #include -#include #include class Font; diff --git a/src/framework/ui/uiconstants.h b/src/framework/ui/uiconstants.h deleted file mode 100644 index b0968fc2..00000000 --- a/src/framework/ui/uiconstants.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef UICONSTANTS_H -#define UICONSTANTS_H - -namespace UI { - enum ElementType { - Element = 0, - Container, - Panel, - Window, - Label, - TextEdit, - Button, - CheckBox, - LineDecoration - }; - - enum AnchorPoint { - AnchorNone = 0, - AnchorTop, - AnchorBottom, - AnchorLeft, - AnchorRight, - AnchorVerticalCenter, - AnchorHorizontalCenter, - }; -} - -#endif // UICONSTANTS_H diff --git a/src/framework/ui/uicontainer.h b/src/framework/ui/uicontainer.h index 57086b2a..619c852e 100644 --- a/src/framework/ui/uicontainer.h +++ b/src/framework/ui/uicontainer.h @@ -34,7 +34,7 @@ public: const std::list& getChildren() const { return m_children; } /// Pushs a child to the top void pushChildToTop(const UIElementPtr& child); - + /// Return number of children int getChildCount() const { return m_children.size(); } /// Disable all children except the specified element diff --git a/src/framework/ui/uielement.cpp b/src/framework/ui/uielement.cpp index 478ceb60..314421c8 100644 --- a/src/framework/ui/uielement.cpp +++ b/src/framework/ui/uielement.cpp @@ -5,6 +5,7 @@ #include #include #include +#include UIElement::UIElement(UI::ElementType type) : ScriptObject(), @@ -17,7 +18,9 @@ UIElement::UIElement(UI::ElementType type) : m_marginTop(0), m_marginBottom(0) { - + // generate an unique id, this is need because anchoed layouts find elements by id + static unsigned long id = 1; + m_id = make_string("element", id++); } UIElement::~UIElement() @@ -62,12 +65,11 @@ void UIElement::destroyCheck() void UIElement::setSize(const Size& size) { Rect rect = getRect(); - if(rect.isValid()) - rect.setSize(size); - else - rect = Rect(0, 0, size); + rect.setSize(size); setRect(rect); - getLayout()->recalculateElementLayout(asUIElement()); + + if(UILayoutPtr layout = getLayout()) + layout->recalculateElementLayout(asUIElement()); } void UIElement::setRect(const Rect& rect) @@ -76,12 +78,18 @@ void UIElement::setRect(const Rect& rect) m_rect = rect; // rect updated, recalculate children layout - getLayout()->recalculateChildrenLayout(asUIElement()); + if(UILayoutPtr layout = getLayout()) + layout->recalculateChildrenLayout(asUIElement()); onRectUpdate(); } } +void UIElement::applyDefaultSkin() +{ + setSkin(g_uiSkins.getElementSkin(getElementType(), "default")); +} + void UIElement::setSkin(const UIElementSkinPtr& skin) { m_skin = skin; @@ -186,3 +194,20 @@ UILayoutPtr UIElement::getLayout() const return getParent()->getLayout(); return UILayoutPtr(); } + +void UIElement::centerIn(const std::string& targetId) +{ + addAnchor(AnchorHorizontalCenter, AnchorLine(targetId, AnchorHorizontalCenter)); + addAnchor(AnchorVerticalCenter, AnchorLine(targetId, AnchorVerticalCenter)); +} + +void UIElement::addAnchor(AnchorPoint anchoredEdge, AnchorLine anchorEdge) +{ + UIElementPtr target = backwardsGetElementById(anchorEdge.getElementId()); + if(!target) + warning("warning: element id '", anchorEdge.getElementId(), "' doesn't exist while anchoring element '", getId(), "'"); + + UIAnchorLayoutPtr layout = boost::dynamic_pointer_cast(getLayout()); + if(layout) + layout->addAnchor(asUIElement(), anchoredEdge, anchorEdge); +} diff --git a/src/framework/ui/uielement.h b/src/framework/ui/uielement.h index 9c2f2392..ad378945 100644 --- a/src/framework/ui/uielement.h +++ b/src/framework/ui/uielement.h @@ -4,11 +4,24 @@ #include #include #include