From 532d7f239f6189b12a1a96eb2604a06e98f0fd98 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Tue, 15 Nov 2011 21:47:32 -0200 Subject: [PATCH] new widget, UICheckBox --- CMakeLists.txt | 8 +- README.rdoc | 20 ++--- TODO | 4 +- modules/about/about.otui | 4 +- modules/core_styles/core_styles.otmod | 1 + modules/core_styles/styles/buttons.otui | 14 +-- modules/core_styles/styles/windows.otui | 2 +- modules/entergame/characterlist.otui | 6 +- modules/entergame/entergame.otui | 27 +++++- modules/inventory/inventory.lua | 5 +- modules/inventory/itempopupmenu.otui | 2 +- modules/options/options.otui | 12 +-- modules/outfit/outfit.otui | 8 +- modules/topmenu/topmenu.otui | 8 +- src/framework/const.h | 6 +- src/framework/core/resourcemanager.cpp | 1 - src/framework/global.h | 1 - src/framework/luascript/luafunctions.cpp | 4 + src/framework/ui/declarations.h | 9 +- src/framework/ui/ui.h | 1 + src/framework/ui/uibutton.cpp | 6 +- src/framework/ui/uibutton.h | 2 +- src/framework/ui/uicheckbox.cpp | 66 +++++++++++++++ src/framework/ui/uicheckbox.h | 50 +++++++++++ src/framework/ui/uiframecounter.cpp | 1 + src/framework/ui/uilabel.cpp | 1 + src/framework/ui/uitranslator.cpp | 90 ++++++++++++++++++++ src/framework/ui/uitranslator.h | 37 ++++++++ src/framework/ui/uiwidget.cpp | 103 +++++++++++++++-------- src/framework/ui/uiwidget.h | 90 ++++++++++---------- src/framework/ui/uiwindow.cpp | 1 + 31 files changed, 453 insertions(+), 137 deletions(-) create mode 100644 src/framework/ui/uicheckbox.cpp create mode 100644 src/framework/ui/uicheckbox.h create mode 100644 src/framework/ui/uitranslator.cpp create mode 100644 src/framework/ui/uitranslator.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 294890df..75d11486 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ IF(CMAKE_BUILD_TYPE STREQUAL "Debug") ADD_DEFINITIONS(-D_DEBUG) ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug") -SET(SOURCES src/framework/ui/uiframecounter.cpp +SET(SOURCES # main src/main.cpp @@ -94,9 +94,6 @@ SET(SOURCES src/framework/ui/uiframecounter.cpp src/framework/net/rsa.cpp src/framework/net/server.cpp - # framework util - src/framework/util/translator.cpp - # framework core src/framework/core/logger.cpp src/framework/core/configs.cpp @@ -142,6 +139,9 @@ SET(SOURCES src/framework/ui/uiframecounter.cpp src/framework/ui/uiverticallayout.cpp src/framework/ui/uilayout.cpp src/framework/ui/uiprogressbar.cpp + src/framework/ui/uicheckbox.cpp + src/framework/ui/uiframecounter.cpp + src/framework/ui/uitranslator.cpp ) IF(HANDLE_EXCEPTIONS) diff --git a/README.rdoc b/README.rdoc index 71517137..784288c7 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,17 +1,12 @@ == What is OTClient? OTClient is an alternative Tibia client for usage with otserv. It aims to be complete and flexible, -for that it uses LUA scripting for all game interface functionality and configuration files created with -a syntax similar to CSS for its interface design. OTClient works with a modular system, this means +for that it uses LUA scripting for all game interface functionality and OTML files that has a syntax +similar to CSS for the client interface design. OTClient works with a modular system, this means that each functionality is a separated module, giving the possibility to users modify and customize anything easily. Users can also create new mods and extend game interface for their own purposes. OTClient is written in C++2011, the upcoming C++ standard. -== Need help? - -If you have any questions or are looking for more information, please feel free to ask on our official -forum at http://otclient.info/ - == Getting Started In short, if you need to compile OTClient, follow these tutorials: @@ -19,9 +14,14 @@ In short, if you need to compile OTClient, follow these tutorials: * {Compiling on Ubuntu}[http://otclient.info/page/articles.html/_/general/compiling-on-ubuntu-r12] Checkout our website at {http://otclient.info}[http://otclient.info/] for tutorials and more information +== Need help? + +If you have any questions or are looking for more information, please feel free to ask on our official +forum at http://otclient.info/ + == Bugs -Have found a bug? Please create an issue in our bug tracker! +Have found a bug? Please create an issue in our bug tracker http://otclient.info/tracker == Contributing @@ -31,8 +31,8 @@ We encourage you to contribute to OTClient! Please check out == Authors -* edubart (project creator and leader developer) -* baxnie (official developer) +* edubart (project creator and leader developer) +* baxnie (official developer) == License diff --git a/TODO b/TODO index 0de6d376..4adafe45 100644 --- a/TODO +++ b/TODO @@ -11,4 +11,6 @@ padding remember password/account scrollbar make otui syntax more like css -a real working border and background property in otui \ No newline at end of file +a real working border and background property in otui +setIcon() for buttons +load state styles in order \ No newline at end of file diff --git a/modules/about/about.otui b/modules/about/about.otui index a92e93bc..4466dff9 100644 --- a/modules/about/about.otui +++ b/modules/about/about.otui @@ -41,7 +41,7 @@ MainWindow anchors.bottom: parent.bottom margin.bottom: 9 margin.right: 9 - onClick: About.openWebpage() + @onClick: About.openWebpage() HorizontalSeparator anchors.left: parent.left @@ -58,4 +58,4 @@ MainWindow anchors.top: parent.top margin.top: 191 margin.left: 188 - onClick: About.destroy() + @onClick: About.destroy() diff --git a/modules/core_styles/core_styles.otmod b/modules/core_styles/core_styles.otmod index 38823be7..93ce19d8 100644 --- a/modules/core_styles/core_styles.otmod +++ b/modules/core_styles/core_styles.otmod @@ -11,6 +11,7 @@ Module importStyles 'styles/panels.otui' importStyles 'styles/separators.otui' importStyles 'styles/lineedits.otui' + importStyles 'styles/checkboxes.otui' importStyles 'styles/windows.otui' importStyles 'styles/listboxes.otui' importStyles 'styles/items.otui' diff --git a/modules/core_styles/styles/buttons.otui b/modules/core_styles/styles/buttons.otui index 6d4eaa9c..59ba2375 100644 --- a/modules/core_styles/styles/buttons.otui +++ b/modules/core_styles/styles/buttons.otui @@ -8,18 +8,18 @@ Button < UIButton source: /core_styles/images/button.png border: 5 - state.hover: + $hover: border-image: source: /core_styles/images/button_hover.png border: 5 - state.pressed: + $pressed: text-translate: 1 1 border-image: source: /core_styles/images/button_down.png border: 5 - state.disabled: + $disabled: color: #999999 background-color: #ffffff88 @@ -32,14 +32,14 @@ TopButton < UIButton size: 26 25 border: 3 - state.hover: + $hover: border-image: source: /core_styles/images/top_button.png size: 26 25 offset: 26 0 border: 3 - state.pressed: + $pressed: text-translate: 1 1 border-image: source: /core_styles/images/top_button.png @@ -47,7 +47,7 @@ TopButton < UIButton offset: 52 0 border: 3 - state.disabled: + $disabled: background-color: #ffffff66 MenuButton < UIButton @@ -58,7 +58,7 @@ MenuButton < UIButton source: /core_styles/images/menu.png size: 64 24 - state.hover: + $hover: border-image: source: /core_styles/images/menu.png offset: 0 24 diff --git a/modules/core_styles/styles/windows.otui b/modules/core_styles/styles/windows.otui index 43d6e350..704f135d 100644 --- a/modules/core_styles/styles/windows.otui +++ b/modules/core_styles/styles/windows.otui @@ -12,7 +12,7 @@ Window < UIWindow border: 4 border.top: 20 - state.pressed: + $pressed: opacity: 192 MiniWindow < UIWindow diff --git a/modules/entergame/characterlist.otui b/modules/entergame/characterlist.otui index b0cec258..f92438a5 100644 --- a/modules/entergame/characterlist.otui +++ b/modules/entergame/characterlist.otui @@ -8,7 +8,7 @@ CharacterListLabel < Label margin.right: 1 margin.top: 1 - state.focus: + $focus: background-color: #ffffff22 color: #ffffff @@ -55,7 +55,7 @@ MainWindow anchors.bottom: parent.bottom margin.bottom: 16 margin.right: 16 - onClick: CharacterList.doLogin() + @onClick: CharacterList.doLogin() Button id: buttonCancel @@ -65,4 +65,4 @@ MainWindow anchors.bottom: parent.bottom margin.bottom: 16 margin.right: 16 - onClick: CharacterList.destroy() \ No newline at end of file + @onClick: CharacterList.destroy() \ No newline at end of file diff --git a/modules/entergame/entergame.otui b/modules/entergame/entergame.otui index c76487fc..ffc3a1ee 100644 --- a/modules/entergame/entergame.otui +++ b/modules/entergame/entergame.otui @@ -1,7 +1,7 @@ MainWindow id: enterGame title: Enter Game - size: 236 160 + size: 236 200 onEnter: EnterGame.doLogin() onEscape: EnterGame.hide() @@ -38,6 +38,27 @@ MainWindow margin.left: 18 margin.right: 18 + CheckBox + id: rememberPasswordBox + text: Remember password + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin.top: 10 + margin.left: 18 + margin.right: 18 + + CheckBox + id: autoLoginBox + text: Auto login + checked: true + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin.top: 8 + margin.left: 18 + margin.right: 18 + Button text: Ok width: 64 @@ -45,7 +66,7 @@ MainWindow anchors.bottom: parent.bottom margin.bottom: 16 margin.right: 16 - onClick: EnterGame.doLogin() + @onClick: EnterGame.doLogin() Button text: Cancel @@ -54,4 +75,4 @@ MainWindow anchors.bottom: parent.bottom margin.bottom: 16 margin.right: 16 - onClick: EnterGame.hide() + @onClick: EnterGame.hide() diff --git a/modules/inventory/inventory.lua b/modules/inventory/inventory.lua index b9a551cf..5420a50b 100644 --- a/modules/inventory/inventory.lua +++ b/modules/inventory/inventory.lua @@ -17,10 +17,9 @@ local InventorySlotAmmo = 10 -- public functions function Inventory.create() window = loadUI("/inventory/inventory.otui", Game.gameRightPanel) - + local itemWidget = window:getChildById('feet') window:setHeight(itemWidget:getPosition().y + itemWidget:getHeight() - window:getPosition().y) - end function Inventory.destroy() @@ -52,7 +51,7 @@ function Inventory.onInventoryChange(slot, item) elseif slot == InventorySlotAmmo then slotId = 'ammo' end - + local itemWidget = window:getChildById(slotId) itemWidget:setItem(item) end diff --git a/modules/inventory/itempopupmenu.otui b/modules/inventory/itempopupmenu.otui index c6c0e869..3240b322 100644 --- a/modules/inventory/itempopupmenu.otui +++ b/modules/inventory/itempopupmenu.otui @@ -7,4 +7,4 @@ Panel MenuButton text: Quit - onClick: exit() \ No newline at end of file + @onClick: exit() \ No newline at end of file diff --git a/modules/options/options.otui b/modules/options/options.otui index d074a9e5..90cf0187 100644 --- a/modules/options/options.otui +++ b/modules/options/options.otui @@ -10,7 +10,7 @@ MainWindow anchors.top: parent.top margin.left: 18 margin.top: 32 - onClick: displayErrorBox("Error", "Not implemented yet") + @onClick: displayErrorBox("Error", "Not implemented yet") Label text: |- @@ -28,7 +28,7 @@ MainWindow anchors.top: parent.top margin.left: 18 margin.top: 65 - onClick: displayErrorBox("Error", "Not implemented yet") + @onClick: displayErrorBox("Error", "Not implemented yet") Label text: |- @@ -46,7 +46,7 @@ MainWindow anchors.top: parent.top margin.left: 18 margin.top: 98 - onClick: displayErrorBox("Error", "Not implemented yet") + @onClick: displayErrorBox("Error", "Not implemented yet") Label text: Customise the console @@ -62,7 +62,7 @@ MainWindow anchors.top: parent.top margin.left: 18 margin.top: 131 - onClick: displayErrorBox("Error", "Not implemented yet") + @onClick: displayErrorBox("Error", "Not implemented yet") Label text: Edit your hotkey texts @@ -86,7 +86,7 @@ MainWindow anchors.bottom: parent.bottom margin.left: 18 margin.bottom: 60 - onClick: displayErrorBox("Error", "Not implemented yet") + @onClick: displayErrorBox("Error", "Not implemented yet") Label text: |- @@ -113,4 +113,4 @@ MainWindow anchors.bottom: parent.bottom margin.right: 10 margin.bottom: 10 - onClick: Options.destroy() \ No newline at end of file + @onClick: Options.destroy() \ No newline at end of file diff --git a/modules/outfit/outfit.otui b/modules/outfit/outfit.otui index 67a6b772..427e2515 100644 --- a/modules/outfit/outfit.otui +++ b/modules/outfit/outfit.otui @@ -12,7 +12,7 @@ Window margin.left: 20 Button - onClick: Outfit.previousType() + @onClick: Outfit.previousType() text: << width: 32 margin.top: 3 @@ -20,7 +20,7 @@ Window anchors.left: creature.left Button - onClick: Outfit.nextType() + @onClick: Outfit.nextType() text: >> width: 32 margin.top: 3 @@ -43,7 +43,7 @@ Window anchors.bottom: parent.bottom margin.bottom: 16 margin.right: 16 - onClick: Outfit.accept() + @onClick: Outfit.accept() Button id: buttonCancel @@ -53,4 +53,4 @@ Window anchors.bottom: parent.bottom margin.bottom: 16 margin.right: 16 - onClick: Outfit.destroy() + @onClick: Outfit.destroy() diff --git a/modules/topmenu/topmenu.otui b/modules/topmenu/topmenu.otui index 9e8206c2..b410b575 100644 --- a/modules/topmenu/topmenu.otui +++ b/modules/topmenu/topmenu.otui @@ -12,7 +12,7 @@ TopPanel margin.top: 4 margin.left: 6 tooltip: Options - onClick: Options.create() + @onClick: Options.create() UIWidget size: 16 16 @@ -25,7 +25,7 @@ TopPanel anchors.left: prev.right margin.left: 6 tooltip: Enter game with a character - onClick: | + @onClick: | if Game.isOnline() then CharacterList.show() else @@ -44,7 +44,7 @@ TopPanel margin.top: 4 margin.right: 6 tooltip: Logout - onClick: | + @onClick: | if Game.isOnline() then Game.logout(false) else @@ -63,7 +63,7 @@ TopPanel margin.top: 4 margin.right: 6 tooltip: About OTClient - onClick: About.create() + @onClick: About.create() UIWidget size: 16 16 diff --git a/src/framework/const.h b/src/framework/const.h index e8337610..d8df86ba 100644 --- a/src/framework/const.h +++ b/src/framework/const.h @@ -246,12 +246,16 @@ namespace Fw }; enum WidgetState { + InvalidState = -1, DefaultState = 0, ActiveState = 1, FocusState = 2, HoverState = 4, PressedState = 8, - DisabledState = 16 + DisabledState = 16, + CheckedState = 32, + OnState = 64, + LastState = 128 //FirstState, //MiddleState, //LastState, diff --git a/src/framework/core/resourcemanager.cpp b/src/framework/core/resourcemanager.cpp index 3544dbe2..ecf5e12e 100644 --- a/src/framework/core/resourcemanager.cpp +++ b/src/framework/core/resourcemanager.cpp @@ -44,7 +44,6 @@ void ResourceManager::init(const char* argv0, const char *appName) bool found = false; for(const std::string& dir : possibleDirs) { - dump << dir; if(g_resources.addToSearchPath(dir)) { logInfo("Using modules directory '", dir.c_str(), "'"); found = true; diff --git a/src/framework/global.h b/src/framework/global.h index 167c093f..2d8e874a 100644 --- a/src/framework/global.h +++ b/src/framework/global.h @@ -64,7 +64,6 @@ // additional utilities #include "util/types.h" #include "util/tools.h" -#include "util/translator.h" #include "util/point.h" #include "util/color.h" #include "util/rect.h" diff --git a/src/framework/luascript/luafunctions.cpp b/src/framework/luascript/luafunctions.cpp index 3c686ea6..8620f963 100644 --- a/src/framework/luascript/luafunctions.cpp +++ b/src/framework/luascript/luafunctions.cpp @@ -129,6 +129,10 @@ void LuaInterface::registerFunctions() g_lua.bindClassMemberFunction("clearText", &UILineEdit::clearText); g_lua.bindClassMemberFunction("getCursorPos", &UILineEdit::getCursorPos); + // UICheckBox + g_lua.registerClass(); + g_lua.bindClassStaticFunction("create", &UIWidget::create); + // UIWindow g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &UIWidget::create); diff --git a/src/framework/ui/declarations.h b/src/framework/ui/declarations.h index 3c68ab28..d8597876 100644 --- a/src/framework/ui/declarations.h +++ b/src/framework/ui/declarations.h @@ -24,15 +24,16 @@ #define FRAMEWORK_UI_DECLARATIONS_H #include -#include class UIManager; class UIWidget; class UILabel; class UIButton; class UILineEdit; -class UIWindow; +class UICheckBox; +class UIProgressBar; class UIFrameCounter; +class UIWindow; class UILayout; class UIVerticalLayout; class UIAnchorLayout; @@ -43,8 +44,10 @@ typedef std::weak_ptr UIWidgetWeakPtr; typedef std::shared_ptr UILabelPtr; typedef std::shared_ptr UIButtonPtr; typedef std::shared_ptr UILineEditPtr; +typedef std::shared_ptr UICheckBoxPtr; +typedef std::shared_ptr UIProgressBarPtr; +typedef std::shared_ptr UIFrameCounterPtr; typedef std::shared_ptr UIWindowPtr; -typedef std::shared_ptr UIFrameCounterPtr; typedef std::shared_ptr UILayoutPtr; typedef std::shared_ptr UIVerticalLayoutPtr; typedef std::shared_ptr UIAnchorLayoutPtr; diff --git a/src/framework/ui/ui.h b/src/framework/ui/ui.h index f78df8bf..3f409fee 100644 --- a/src/framework/ui/ui.h +++ b/src/framework/ui/ui.h @@ -31,5 +31,6 @@ #include "uiwindow.h" #include "uiframecounter.h" #include "uiprogressbar.h" +#include "uicheckbox.h" #endif diff --git a/src/framework/ui/uibutton.cpp b/src/framework/ui/uibutton.cpp index d7ae7c0b..f8ffe945 100644 --- a/src/framework/ui/uibutton.cpp +++ b/src/framework/ui/uibutton.cpp @@ -40,7 +40,7 @@ void UIButton::render() { UIWidget::render(); Rect textRect = m_rect; - textRect.translate(m_textTranslate); + textRect.translate(m_textOffset); m_font->renderText(m_text, textRect, Fw::AlignCenter, m_foregroundColor); } @@ -49,8 +49,8 @@ void UIButton::onStyleApply(const OTMLNodePtr& styleNode) UIWidget::onStyleApply(styleNode); for(OTMLNodePtr node : styleNode->children()) { - if(node->tag() == "text-translate") { - m_textTranslate = node->value(); + if(node->tag() == "text-offset") { + m_textOffset = node->value(); } else if(node->tag() == "text") { m_text = node->value(); } diff --git a/src/framework/ui/uibutton.h b/src/framework/ui/uibutton.h index 3095c20d..e7a6d743 100644 --- a/src/framework/ui/uibutton.h +++ b/src/framework/ui/uibutton.h @@ -44,7 +44,7 @@ protected: virtual void onMouseRelease(const Point& mousePos, Fw::MouseButton button); SimpleCallback m_onClick; - Point m_textTranslate; + Point m_textOffset; std::string m_text; }; diff --git a/src/framework/ui/uicheckbox.cpp b/src/framework/ui/uicheckbox.cpp new file mode 100644 index 00000000..d3d6c5c8 --- /dev/null +++ b/src/framework/ui/uicheckbox.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2010-2011 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. + */ + +#include "uicheckbox.h" +#include +#include +#include +#include +#include + +void UICheckBox::render() +{ + Rect boxRect; + boxRect.setSize(m_boxSize); + boxRect.moveLeft(m_rect.left()); + boxRect.moveVerticalCenter(m_rect.verticalCenter()); + g_graphics.bindColor(m_backgroundColor); + m_image->draw(boxRect); + + Rect textRect(m_rect); + textRect.setTopLeft(textRect.topLeft() + m_textOffset); + m_font->renderText(m_text, textRect, Fw::AlignLeft, m_foregroundColor); +} + +void UICheckBox::onMouseRelease(const Point& mousePos, Fw::MouseButton button) +{ + if(isPressed() && getRect().contains(mousePos)) + setState(Fw::CheckedState, !isChecked()); +} + +void UICheckBox::onStyleApply(const OTMLNodePtr& styleNode) +{ + UIWidget::onStyleApply(styleNode); + + for(OTMLNodePtr node : styleNode->children()) { + if(node->tag() == "text-offset") + m_textOffset = node->value(); + else if(node->tag() == "text") + m_text = node->value(); + else if(node->tag() == "box-size") + m_boxSize = node->value(); + else if(node->tag() == "checked") { + // must be scheduled because setChecked can change the style again + g_dispatcher.addEvent(std::bind(&UICheckBox::setChecked, asUICheckBox(), node->value())); + } + } +} diff --git a/src/framework/ui/uicheckbox.h b/src/framework/ui/uicheckbox.h new file mode 100644 index 00000000..6f072f34 --- /dev/null +++ b/src/framework/ui/uicheckbox.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010-2011 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 UICHECKBOX_H +#define UICHECKBOX_H + +#include "uiwidget.h" + +class UICheckBox : public UIWidget +{ +public: + void render(); + + bool isChecked() { return hasState(Fw::CheckedState); } + void setChecked(bool checked) { setState(Fw::CheckedState, checked); } + + void setText(const std::string& text) { m_text = text; } + std::string getText() { return m_text; } + + UICheckBoxPtr asUICheckBox() { return std::static_pointer_cast(shared_from_this()); } + +protected: + virtual void onStyleApply(const OTMLNodePtr& styleNode); + virtual void onMouseRelease(const Point& mousePos, Fw::MouseButton button); + + std::string m_text; + Size m_boxSize; + Point m_textOffset; +}; + +#endif diff --git a/src/framework/ui/uiframecounter.cpp b/src/framework/ui/uiframecounter.cpp index def2cb50..3f95f094 100644 --- a/src/framework/ui/uiframecounter.cpp +++ b/src/framework/ui/uiframecounter.cpp @@ -21,6 +21,7 @@ */ #include "uiframecounter.h" +#include "uitranslator.h" #include #include #include diff --git a/src/framework/ui/uilabel.cpp b/src/framework/ui/uilabel.cpp index 74af3f8f..51d3cf42 100644 --- a/src/framework/ui/uilabel.cpp +++ b/src/framework/ui/uilabel.cpp @@ -21,6 +21,7 @@ */ #include "uilabel.h" +#include "uitranslator.h" #include #include diff --git a/src/framework/ui/uitranslator.cpp b/src/framework/ui/uitranslator.cpp new file mode 100644 index 00000000..03b2a985 --- /dev/null +++ b/src/framework/ui/uitranslator.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2010-2011 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. + */ + +#include "uitranslator.h" +#include + +Fw::AlignmentFlag Fw::translateAlignment(std::string aligment) +{ + boost::to_lower(aligment); + boost::erase_all(aligment, " "); + if(aligment == "topleft") + return Fw::AlignTopLeft; + else if(aligment == "topright") + return Fw::AlignTopRight; + else if(aligment == "bottomleft") + return Fw::AlignBottomLeft; + else if(aligment == "bottomright") + return Fw::AlignBottomRight; + else if(aligment == "left") + return Fw::AlignLeftCenter; + else if(aligment == "right") + return Fw::AlignRightCenter; + else if(aligment == "top") + return Fw::AlignTopCenter; + else if(aligment == "bottom") + return Fw::AlignBottomCenter; + else if(aligment == "center") + return Fw::AlignCenter; + return Fw::AlignNone; +} + +Fw::AnchorEdge Fw::translateAnchorEdge(std::string anchorEdge) +{ + boost::to_lower(anchorEdge); + boost::erase_all(anchorEdge, " "); + if(anchorEdge == "left") + return Fw::AnchorLeft; + else if(anchorEdge == "right") + return Fw::AnchorRight; + else if(anchorEdge == "top") + return Fw::AnchorTop; + else if(anchorEdge == "bottom") + return Fw::AnchorBottom; + else if(anchorEdge == "horizontalcenter") + return Fw::AnchorHorizontalCenter; + else if(anchorEdge == "verticalcenter") + return Fw::AnchorVerticalCenter; + return Fw::AnchorNone; +} + +Fw::WidgetState Fw::translateState(std::string state) +{ + boost::to_lower(state); + boost::erase_all(state, " "); + if(state == "active") + return Fw::ActiveState; + else if(state == "focus") + return Fw::FocusState; + else if(state == "hover") + return Fw::HoverState; + else if(state == "pressed") + return Fw::PressedState; + else if(state == "checked") + return Fw::CheckedState; + else if(state == "disabled") + return Fw::DisabledState; + else if(state == "on") + return Fw::OnState; + else + return Fw::InvalidState; +} diff --git a/src/framework/ui/uitranslator.h b/src/framework/ui/uitranslator.h new file mode 100644 index 00000000..76660573 --- /dev/null +++ b/src/framework/ui/uitranslator.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010-2011 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 TRANSLATOR_H +#define TRANSLATOR_H + +#include "../const.h" +#include + +namespace Fw { + +AlignmentFlag translateAlignment(std::string aligment); +AnchorEdge translateAnchorEdge(std::string anchorEdge); +WidgetState translateState(std::string state); + +}; + +#endif diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index 787d4ac4..dc71b50e 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -24,6 +24,7 @@ #include "uimanager.h" #include "uianchorlayout.h" #include "uiverticallayout.h" +#include "uitranslator.h" #include #include @@ -36,6 +37,7 @@ UIWidget::UIWidget() { m_updateEventScheduled = false; + m_firstOnStyle = true; m_states = Fw::DefaultState; // generate an unique id, this is need because anchored layouts find widgets by id @@ -611,6 +613,28 @@ void UIWidget::updateLayout() m_layout->update(); } +void UIWidget::setState(Fw::WidgetState state, bool on) +{ + if(state == Fw::InvalidState) + return; + + int oldStates = m_states; + if(on) + m_states |= state; + else + m_states &= ~state; + + if(oldStates != m_states) + updateStyle(); +} + +bool UIWidget::hasState(Fw::WidgetState state) +{ + if(state == Fw::InvalidState) + return false; + return (m_states & state); +} + void UIWidget::updateState(Fw::WidgetState state) { bool newStatus = true; @@ -675,12 +699,7 @@ void UIWidget::updateState(Fw::WidgetState state) } if(newStatus != oldStatus) { - if(newStatus) - m_states |= state; - else - m_states &= ~state; - - updateStyle(); + setState(state, newStatus); if(state == Fw::FocusState) { g_dispatcher.addEvent(std::bind(&UIWidget::onFocusChange, asUIWidget(), newStatus, m_lastFocusReason)); @@ -691,10 +710,8 @@ void UIWidget::updateState(Fw::WidgetState state) void UIWidget::updateStates() { - updateState(Fw::ActiveState); - updateState(Fw::FocusState); - updateState(Fw::DisabledState); - updateState(Fw::HoverState); + for(int state = 1; state != Fw::LastState; state <<= 1) + updateState((Fw::WidgetState)state); } void UIWidget::updateStyle() @@ -712,26 +729,32 @@ void UIWidget::updateStyle() } } - // merge states styles, NOTE: order does matter - OTMLNodePtr style = m_style->get("state.active"); - if(style && hasState(Fw::ActiveState)) - newStateStyle->merge(style); - - style = m_style->get("state.focus"); - if(style && hasState(Fw::FocusState)) - newStateStyle->merge(style); - - style = m_style->get("state.hover"); - if(style && hasState(Fw::HoverState)) - newStateStyle->merge(style); - - style = m_style->get("state.pressed"); - if(style && hasState(Fw::PressedState)) - newStateStyle->merge(style); + // checks for states combination + for(const OTMLNodePtr& style : m_style->children()) { + if(boost::starts_with(style->tag(), "$")) { + std::string statesStr = style->tag().substr(1); + std::vector statesSplit; + boost::split(statesSplit, statesStr, boost::is_any_of(std::string(" "))); + + bool match = true; + for(std::string stateStr : statesSplit) { + if(stateStr.length() == 0) + continue; + + bool notstate = (stateStr[0] == '!'); + if(notstate) + stateStr = stateStr.substr(1); + + bool stateOn = hasState(Fw::translateState(stateStr)); + if((!notstate && !stateOn) || (notstate && stateOn)) + match = false; + } - style = m_style->get("state.disabled"); - if(style && hasState(Fw::DisabledState)) - newStateStyle->merge(style); + // merge states styles + if(match) + newStateStyle->merge(style); + } + } applyStyle(newStateStyle); m_stateStyle = newStateStyle; @@ -886,13 +909,25 @@ void UIWidget::onStyleApply(const OTMLNodePtr& styleNode) anchorLayout->addAnchor(asUIWidget(), anchoredEdge, hookedWidgetId, hookedEdge); } - } else if(node->tag() == "onClick" || - node->tag() == "onMousePress" || - node->tag() == "onHoverChange") { - g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]"); - luaSetField(node->tag()); + // lua functions + } else if(boost::starts_with(node->tag(), "@")) { + // on load once + if(m_firstOnStyle) { + std::string funcName = node->tag().substr(1); + std::string funcOrigin = "@" + node->source() + "[" + node->tag() + "]"; + g_lua.loadFunction(node->value(), funcOrigin); + luaSetField(funcName); + } + // lua fields value + } else if(boost::starts_with(node->tag(), "&")) { + std::string fieldName = node->tag().substr(1); + std::string fieldOrigin = "@" + node->source() + "[" + node->tag() + "]"; + g_lua.evaluateExpression(node->value(), fieldOrigin); + luaSetField(fieldName); } } + + m_firstOnStyle = false; } void UIWidget::onGeometryUpdate(const Rect& oldRect, const Rect& newRect) diff --git a/src/framework/ui/uiwidget.h b/src/framework/ui/uiwidget.h index 05f60b17..c1308956 100644 --- a/src/framework/ui/uiwidget.h +++ b/src/framework/ui/uiwidget.h @@ -80,49 +80,48 @@ public: void unlock(); void focus(); - bool isActive() const { return hasState(Fw::ActiveState); } - bool isEnabled() const { return !hasState(Fw::DisabledState); } - bool isDisabled() const { return hasState(Fw::DisabledState); } - bool isFocused() const { return hasState(Fw::FocusState); } - bool isHovered() const { return hasState(Fw::HoverState); } - bool isPressed() const { return hasState(Fw::PressedState); } + bool isActive() { return hasState(Fw::ActiveState); } + bool isEnabled() { return !hasState(Fw::DisabledState); } + bool isDisabled() { return hasState(Fw::DisabledState); } + bool isFocused() { return hasState(Fw::FocusState); } + bool isHovered() { return hasState(Fw::HoverState); } + bool isPressed() { return hasState(Fw::PressedState); } bool isVisible(); bool isHidden() { return !isVisible(); } - bool isExplicitlyEnabled() const { return m_enabled; } - bool isExplicitlyVisible() const { return m_visible; } - bool isFocusable() const { return m_focusable; } - bool isPhantom() const { return m_phantom; } - bool isSizeFixed() const { return m_fixedSize; } - bool hasChildren() const { return m_children.size() > 0; } + bool isExplicitlyEnabled() { return m_enabled; } + bool isExplicitlyVisible() { return m_visible; } + bool isFocusable() { return m_focusable; } + bool isPhantom() { return m_phantom; } + bool isSizeFixed() { return m_fixedSize; } + bool hasChildren() { return m_children.size() > 0; } bool hasChild(const UIWidgetPtr& child); - bool hasState(Fw::WidgetState state) const { return m_states & state; } - std::string getId() const { return m_id; } - int getChildCount() const { return m_children.size(); } - UILayoutPtr getLayout() const { return m_layout; } - UIWidgetPtr getParent() const { return m_parent.lock(); } + std::string getId() { return m_id; } + int getChildCount() { return m_children.size(); } + UILayoutPtr getLayout() { return m_layout; } + UIWidgetPtr getParent() { return m_parent.lock(); } UIWidgetPtr getRootParent(); - Point getPosition() const { return m_rect.topLeft(); } - Size getSize() const { return m_rect.size(); } - Rect getRect() const { return m_rect; } - int getX() const { return m_rect.x(); } - int getY() const { return m_rect.y(); } - int getWidth() const { return m_rect.width(); } - int getHeight() const { return m_rect.height(); } - ImagePtr getImage() const { return m_image; } - FontPtr getFont() const { return m_font; } - Color getForegroundColor() const { return m_foregroundColor; } - Color getBackgroundColor() const { return m_backgroundColor; } - int getOpacity() const { return m_opacity; } - int getMarginLeft() const { return m_marginLeft; } - int getMarginRight() const { return m_marginRight; } - int getMarginTop() const { return m_marginTop; } - int getMarginBottom() const { return m_marginBottom; } - Fw::FocusReason getLastFocusReason() const { return m_lastFocusReason; } - OTMLNodePtr getStyle() const { return m_style; } - - UIWidgetList getChildren() const { return m_children; } - UIWidgetPtr getFocusedChild() const { return m_focusedChild; } + Point getPosition() { return m_rect.topLeft(); } + Size getSize() { return m_rect.size(); } + Rect getRect() { return m_rect; } + int getX() { return m_rect.x(); } + int getY() { return m_rect.y(); } + int getWidth() { return m_rect.width(); } + int getHeight() { return m_rect.height(); } + ImagePtr getImage() { return m_image; } + FontPtr getFont() { return m_font; } + Color getForegroundColor() { return m_foregroundColor; } + Color getBackgroundColor() { return m_backgroundColor; } + int getOpacity() { return m_opacity; } + int getMarginLeft() { return m_marginLeft; } + int getMarginRight() { return m_marginRight; } + int getMarginTop() { return m_marginTop; } + int getMarginBottom() { return m_marginBottom; } + Fw::FocusReason getLastFocusReason() { return m_lastFocusReason; } + OTMLNodePtr getStyle() { return m_style; } + + UIWidgetList getChildren() { return m_children; } + UIWidgetPtr getFocusedChild() { return m_focusedChild; } UIWidgetPtr getChildAfter(const UIWidgetPtr& relativeChild); UIWidgetPtr getChildBefore(const UIWidgetPtr& relativeChild); UIWidgetPtr getChildById(const std::string& childId); @@ -147,16 +146,17 @@ public: void updateParentLayout(); void updateLayout(); - virtual void updateState(Fw::WidgetState state); + void updateStates(); - virtual void updateStyle(); + virtual void updateState(Fw::WidgetState state); + void setState(Fw::WidgetState state, bool on); + bool hasState(Fw::WidgetState state); + + void updateStyle(); void applyStyle(const OTMLNodePtr& styleNode); UIWidgetPtr asUIWidget() { return std::static_pointer_cast(shared_from_this()); } -private: - bool m_updateEventScheduled; - protected: /// Triggered when widget style is changed virtual void onStyleApply(const OTMLNodePtr& styleNode); @@ -190,6 +190,8 @@ protected: bool m_fixedSize; bool m_pressed; bool m_phantom; + bool m_updateEventScheduled; + bool m_firstOnStyle; Rect m_rect; UILayoutPtr m_layout; UIWidgetWeakPtr m_parent; @@ -198,7 +200,7 @@ protected: UIWidgetPtr m_focusedChild; OTMLNodePtr m_style; OTMLNodePtr m_stateStyle; - uint m_states; + int m_states; // basic style components used by all widgets ImagePtr m_image; diff --git a/src/framework/ui/uiwindow.cpp b/src/framework/ui/uiwindow.cpp index 39bdb7a9..16f36839 100644 --- a/src/framework/ui/uiwindow.cpp +++ b/src/framework/ui/uiwindow.cpp @@ -21,6 +21,7 @@ */ #include "uiwindow.h" +#include "uitranslator.h" #include #include #include