new widget, UICheckBox

This commit is contained in:
Eduardo Bart 2011-11-15 21:47:32 -02:00
parent 9c986c4c5c
commit 532d7f239f
31 changed files with 449 additions and 133 deletions

View File

@ -50,7 +50,7 @@ IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
ADD_DEFINITIONS(-D_DEBUG) ADD_DEFINITIONS(-D_DEBUG)
ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug") ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug")
SET(SOURCES src/framework/ui/uiframecounter.cpp SET(SOURCES
# main # main
src/main.cpp src/main.cpp
@ -94,9 +94,6 @@ SET(SOURCES src/framework/ui/uiframecounter.cpp
src/framework/net/rsa.cpp src/framework/net/rsa.cpp
src/framework/net/server.cpp src/framework/net/server.cpp
# framework util
src/framework/util/translator.cpp
# framework core # framework core
src/framework/core/logger.cpp src/framework/core/logger.cpp
src/framework/core/configs.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/uiverticallayout.cpp
src/framework/ui/uilayout.cpp src/framework/ui/uilayout.cpp
src/framework/ui/uiprogressbar.cpp src/framework/ui/uiprogressbar.cpp
src/framework/ui/uicheckbox.cpp
src/framework/ui/uiframecounter.cpp
src/framework/ui/uitranslator.cpp
) )
IF(HANDLE_EXCEPTIONS) IF(HANDLE_EXCEPTIONS)

View File

@ -1,17 +1,12 @@
== What is OTClient? == What is OTClient?
OTClient is an alternative Tibia client for usage with otserv. It aims to be complete and flexible, 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 for that it uses LUA scripting for all game interface functionality and OTML files that has a syntax
a syntax similar to CSS for its interface design. OTClient works with a modular system, this means 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 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. 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. 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 == Getting Started
In short, if you need to compile OTClient, follow these tutorials: 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] * {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 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 == 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 http://otclient.info/tracker
== Contributing == Contributing
@ -31,8 +31,8 @@ We encourage you to contribute to OTClient! Please check out
== Authors == Authors
* edubart <edub4rt@gmail.com> (project creator and leader developer) * edubart (project creator and leader developer) <edub4rt@gmail.com>
* baxnie <henrique_santiago93@hotmail.com> (official developer) * baxnie (official developer) <henrique_santiago93@hotmail.com>
== License == License

4
TODO
View File

@ -11,4 +11,6 @@ padding
remember password/account remember password/account
scrollbar scrollbar
make otui syntax more like css make otui syntax more like css
a real working border and background property in otui a real working border and background property in otui
setIcon() for buttons
load state styles in order

View File

@ -41,7 +41,7 @@ MainWindow
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin.bottom: 9 margin.bottom: 9
margin.right: 9 margin.right: 9
onClick: About.openWebpage() @onClick: About.openWebpage()
HorizontalSeparator HorizontalSeparator
anchors.left: parent.left anchors.left: parent.left
@ -58,4 +58,4 @@ MainWindow
anchors.top: parent.top anchors.top: parent.top
margin.top: 191 margin.top: 191
margin.left: 188 margin.left: 188
onClick: About.destroy() @onClick: About.destroy()

View File

@ -11,6 +11,7 @@ Module
importStyles 'styles/panels.otui' importStyles 'styles/panels.otui'
importStyles 'styles/separators.otui' importStyles 'styles/separators.otui'
importStyles 'styles/lineedits.otui' importStyles 'styles/lineedits.otui'
importStyles 'styles/checkboxes.otui'
importStyles 'styles/windows.otui' importStyles 'styles/windows.otui'
importStyles 'styles/listboxes.otui' importStyles 'styles/listboxes.otui'
importStyles 'styles/items.otui' importStyles 'styles/items.otui'

View File

@ -8,18 +8,18 @@ Button < UIButton
source: /core_styles/images/button.png source: /core_styles/images/button.png
border: 5 border: 5
state.hover: $hover:
border-image: border-image:
source: /core_styles/images/button_hover.png source: /core_styles/images/button_hover.png
border: 5 border: 5
state.pressed: $pressed:
text-translate: 1 1 text-translate: 1 1
border-image: border-image:
source: /core_styles/images/button_down.png source: /core_styles/images/button_down.png
border: 5 border: 5
state.disabled: $disabled:
color: #999999 color: #999999
background-color: #ffffff88 background-color: #ffffff88
@ -32,14 +32,14 @@ TopButton < UIButton
size: 26 25 size: 26 25
border: 3 border: 3
state.hover: $hover:
border-image: border-image:
source: /core_styles/images/top_button.png source: /core_styles/images/top_button.png
size: 26 25 size: 26 25
offset: 26 0 offset: 26 0
border: 3 border: 3
state.pressed: $pressed:
text-translate: 1 1 text-translate: 1 1
border-image: border-image:
source: /core_styles/images/top_button.png source: /core_styles/images/top_button.png
@ -47,7 +47,7 @@ TopButton < UIButton
offset: 52 0 offset: 52 0
border: 3 border: 3
state.disabled: $disabled:
background-color: #ffffff66 background-color: #ffffff66
MenuButton < UIButton MenuButton < UIButton
@ -58,7 +58,7 @@ MenuButton < UIButton
source: /core_styles/images/menu.png source: /core_styles/images/menu.png
size: 64 24 size: 64 24
state.hover: $hover:
border-image: border-image:
source: /core_styles/images/menu.png source: /core_styles/images/menu.png
offset: 0 24 offset: 0 24

View File

@ -12,7 +12,7 @@ Window < UIWindow
border: 4 border: 4
border.top: 20 border.top: 20
state.pressed: $pressed:
opacity: 192 opacity: 192
MiniWindow < UIWindow MiniWindow < UIWindow

View File

@ -8,7 +8,7 @@ CharacterListLabel < Label
margin.right: 1 margin.right: 1
margin.top: 1 margin.top: 1
state.focus: $focus:
background-color: #ffffff22 background-color: #ffffff22
color: #ffffff color: #ffffff
@ -55,7 +55,7 @@ MainWindow
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin.bottom: 16 margin.bottom: 16
margin.right: 16 margin.right: 16
onClick: CharacterList.doLogin() @onClick: CharacterList.doLogin()
Button Button
id: buttonCancel id: buttonCancel
@ -65,4 +65,4 @@ MainWindow
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin.bottom: 16 margin.bottom: 16
margin.right: 16 margin.right: 16
onClick: CharacterList.destroy() @onClick: CharacterList.destroy()

View File

@ -1,7 +1,7 @@
MainWindow MainWindow
id: enterGame id: enterGame
title: Enter Game title: Enter Game
size: 236 160 size: 236 200
onEnter: EnterGame.doLogin() onEnter: EnterGame.doLogin()
onEscape: EnterGame.hide() onEscape: EnterGame.hide()
@ -38,6 +38,27 @@ MainWindow
margin.left: 18 margin.left: 18
margin.right: 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 Button
text: Ok text: Ok
width: 64 width: 64
@ -45,7 +66,7 @@ MainWindow
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin.bottom: 16 margin.bottom: 16
margin.right: 16 margin.right: 16
onClick: EnterGame.doLogin() @onClick: EnterGame.doLogin()
Button Button
text: Cancel text: Cancel
@ -54,4 +75,4 @@ MainWindow
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin.bottom: 16 margin.bottom: 16
margin.right: 16 margin.right: 16
onClick: EnterGame.hide() @onClick: EnterGame.hide()

View File

@ -17,10 +17,9 @@ local InventorySlotAmmo = 10
-- public functions -- public functions
function Inventory.create() function Inventory.create()
window = loadUI("/inventory/inventory.otui", Game.gameRightPanel) window = loadUI("/inventory/inventory.otui", Game.gameRightPanel)
local itemWidget = window:getChildById('feet') local itemWidget = window:getChildById('feet')
window:setHeight(itemWidget:getPosition().y + itemWidget:getHeight() - window:getPosition().y) window:setHeight(itemWidget:getPosition().y + itemWidget:getHeight() - window:getPosition().y)
end end
function Inventory.destroy() function Inventory.destroy()
@ -52,7 +51,7 @@ function Inventory.onInventoryChange(slot, item)
elseif slot == InventorySlotAmmo then elseif slot == InventorySlotAmmo then
slotId = 'ammo' slotId = 'ammo'
end end
local itemWidget = window:getChildById(slotId) local itemWidget = window:getChildById(slotId)
itemWidget:setItem(item) itemWidget:setItem(item)
end end

View File

@ -7,4 +7,4 @@ Panel
MenuButton MenuButton
text: Quit text: Quit
onClick: exit() @onClick: exit()

View File

@ -10,7 +10,7 @@ MainWindow
anchors.top: parent.top anchors.top: parent.top
margin.left: 18 margin.left: 18
margin.top: 32 margin.top: 32
onClick: displayErrorBox("Error", "Not implemented yet") @onClick: displayErrorBox("Error", "Not implemented yet")
Label Label
text: |- text: |-
@ -28,7 +28,7 @@ MainWindow
anchors.top: parent.top anchors.top: parent.top
margin.left: 18 margin.left: 18
margin.top: 65 margin.top: 65
onClick: displayErrorBox("Error", "Not implemented yet") @onClick: displayErrorBox("Error", "Not implemented yet")
Label Label
text: |- text: |-
@ -46,7 +46,7 @@ MainWindow
anchors.top: parent.top anchors.top: parent.top
margin.left: 18 margin.left: 18
margin.top: 98 margin.top: 98
onClick: displayErrorBox("Error", "Not implemented yet") @onClick: displayErrorBox("Error", "Not implemented yet")
Label Label
text: Customise the console text: Customise the console
@ -62,7 +62,7 @@ MainWindow
anchors.top: parent.top anchors.top: parent.top
margin.left: 18 margin.left: 18
margin.top: 131 margin.top: 131
onClick: displayErrorBox("Error", "Not implemented yet") @onClick: displayErrorBox("Error", "Not implemented yet")
Label Label
text: Edit your hotkey texts text: Edit your hotkey texts
@ -86,7 +86,7 @@ MainWindow
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin.left: 18 margin.left: 18
margin.bottom: 60 margin.bottom: 60
onClick: displayErrorBox("Error", "Not implemented yet") @onClick: displayErrorBox("Error", "Not implemented yet")
Label Label
text: |- text: |-
@ -113,4 +113,4 @@ MainWindow
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin.right: 10 margin.right: 10
margin.bottom: 10 margin.bottom: 10
onClick: Options.destroy() @onClick: Options.destroy()

View File

@ -12,7 +12,7 @@ Window
margin.left: 20 margin.left: 20
Button Button
onClick: Outfit.previousType() @onClick: Outfit.previousType()
text: << text: <<
width: 32 width: 32
margin.top: 3 margin.top: 3
@ -20,7 +20,7 @@ Window
anchors.left: creature.left anchors.left: creature.left
Button Button
onClick: Outfit.nextType() @onClick: Outfit.nextType()
text: >> text: >>
width: 32 width: 32
margin.top: 3 margin.top: 3
@ -43,7 +43,7 @@ Window
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin.bottom: 16 margin.bottom: 16
margin.right: 16 margin.right: 16
onClick: Outfit.accept() @onClick: Outfit.accept()
Button Button
id: buttonCancel id: buttonCancel
@ -53,4 +53,4 @@ Window
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin.bottom: 16 margin.bottom: 16
margin.right: 16 margin.right: 16
onClick: Outfit.destroy() @onClick: Outfit.destroy()

View File

@ -12,7 +12,7 @@ TopPanel
margin.top: 4 margin.top: 4
margin.left: 6 margin.left: 6
tooltip: Options tooltip: Options
onClick: Options.create() @onClick: Options.create()
UIWidget UIWidget
size: 16 16 size: 16 16
@ -25,7 +25,7 @@ TopPanel
anchors.left: prev.right anchors.left: prev.right
margin.left: 6 margin.left: 6
tooltip: Enter game with a character tooltip: Enter game with a character
onClick: | @onClick: |
if Game.isOnline() then if Game.isOnline() then
CharacterList.show() CharacterList.show()
else else
@ -44,7 +44,7 @@ TopPanel
margin.top: 4 margin.top: 4
margin.right: 6 margin.right: 6
tooltip: Logout tooltip: Logout
onClick: | @onClick: |
if Game.isOnline() then if Game.isOnline() then
Game.logout(false) Game.logout(false)
else else
@ -63,7 +63,7 @@ TopPanel
margin.top: 4 margin.top: 4
margin.right: 6 margin.right: 6
tooltip: About OTClient tooltip: About OTClient
onClick: About.create() @onClick: About.create()
UIWidget UIWidget
size: 16 16 size: 16 16

View File

@ -246,12 +246,16 @@ namespace Fw
}; };
enum WidgetState { enum WidgetState {
InvalidState = -1,
DefaultState = 0, DefaultState = 0,
ActiveState = 1, ActiveState = 1,
FocusState = 2, FocusState = 2,
HoverState = 4, HoverState = 4,
PressedState = 8, PressedState = 8,
DisabledState = 16 DisabledState = 16,
CheckedState = 32,
OnState = 64,
LastState = 128
//FirstState, //FirstState,
//MiddleState, //MiddleState,
//LastState, //LastState,

View File

@ -44,7 +44,6 @@ void ResourceManager::init(const char* argv0, const char *appName)
bool found = false; bool found = false;
for(const std::string& dir : possibleDirs) { for(const std::string& dir : possibleDirs) {
dump << dir;
if(g_resources.addToSearchPath(dir)) { if(g_resources.addToSearchPath(dir)) {
logInfo("Using modules directory '", dir.c_str(), "'"); logInfo("Using modules directory '", dir.c_str(), "'");
found = true; found = true;

View File

@ -64,7 +64,6 @@
// additional utilities // additional utilities
#include "util/types.h" #include "util/types.h"
#include "util/tools.h" #include "util/tools.h"
#include "util/translator.h"
#include "util/point.h" #include "util/point.h"
#include "util/color.h" #include "util/color.h"
#include "util/rect.h" #include "util/rect.h"

View File

@ -129,6 +129,10 @@ void LuaInterface::registerFunctions()
g_lua.bindClassMemberFunction<UILineEdit>("clearText", &UILineEdit::clearText); g_lua.bindClassMemberFunction<UILineEdit>("clearText", &UILineEdit::clearText);
g_lua.bindClassMemberFunction<UILineEdit>("getCursorPos", &UILineEdit::getCursorPos); g_lua.bindClassMemberFunction<UILineEdit>("getCursorPos", &UILineEdit::getCursorPos);
// UICheckBox
g_lua.registerClass<UICheckBox, UIWidget>();
g_lua.bindClassStaticFunction<UICheckBox>("create", &UIWidget::create<UICheckBox>);
// UIWindow // UIWindow
g_lua.registerClass<UIWindow, UIWidget>(); g_lua.registerClass<UIWindow, UIWidget>();
g_lua.bindClassStaticFunction<UIWindow>("create", &UIWidget::create<UIWindow>); g_lua.bindClassStaticFunction<UIWindow>("create", &UIWidget::create<UIWindow>);

View File

@ -24,15 +24,16 @@
#define FRAMEWORK_UI_DECLARATIONS_H #define FRAMEWORK_UI_DECLARATIONS_H
#include <framework/global.h> #include <framework/global.h>
#include <framework/platform/platformevent.h>
class UIManager; class UIManager;
class UIWidget; class UIWidget;
class UILabel; class UILabel;
class UIButton; class UIButton;
class UILineEdit; class UILineEdit;
class UIWindow; class UICheckBox;
class UIProgressBar;
class UIFrameCounter; class UIFrameCounter;
class UIWindow;
class UILayout; class UILayout;
class UIVerticalLayout; class UIVerticalLayout;
class UIAnchorLayout; class UIAnchorLayout;
@ -43,8 +44,10 @@ typedef std::weak_ptr<UIWidget> UIWidgetWeakPtr;
typedef std::shared_ptr<UILabel> UILabelPtr; typedef std::shared_ptr<UILabel> UILabelPtr;
typedef std::shared_ptr<UIButton> UIButtonPtr; typedef std::shared_ptr<UIButton> UIButtonPtr;
typedef std::shared_ptr<UILineEdit> UILineEditPtr; typedef std::shared_ptr<UILineEdit> UILineEditPtr;
typedef std::shared_ptr<UICheckBox> UICheckBoxPtr;
typedef std::shared_ptr<UIProgressBar> UIProgressBarPtr;
typedef std::shared_ptr<UIFrameCounter> UIFrameCounterPtr;
typedef std::shared_ptr<UIWindow> UIWindowPtr; typedef std::shared_ptr<UIWindow> UIWindowPtr;
typedef std::shared_ptr<UIWindow> UIFrameCounterPtr;
typedef std::shared_ptr<UILayout> UILayoutPtr; typedef std::shared_ptr<UILayout> UILayoutPtr;
typedef std::shared_ptr<UIVerticalLayout> UIVerticalLayoutPtr; typedef std::shared_ptr<UIVerticalLayout> UIVerticalLayoutPtr;
typedef std::shared_ptr<UIAnchorLayout> UIAnchorLayoutPtr; typedef std::shared_ptr<UIAnchorLayout> UIAnchorLayoutPtr;

View File

@ -31,5 +31,6 @@
#include "uiwindow.h" #include "uiwindow.h"
#include "uiframecounter.h" #include "uiframecounter.h"
#include "uiprogressbar.h" #include "uiprogressbar.h"
#include "uicheckbox.h"
#endif #endif

View File

@ -40,7 +40,7 @@ void UIButton::render()
{ {
UIWidget::render(); UIWidget::render();
Rect textRect = m_rect; Rect textRect = m_rect;
textRect.translate(m_textTranslate); textRect.translate(m_textOffset);
m_font->renderText(m_text, textRect, Fw::AlignCenter, m_foregroundColor); m_font->renderText(m_text, textRect, Fw::AlignCenter, m_foregroundColor);
} }
@ -49,8 +49,8 @@ void UIButton::onStyleApply(const OTMLNodePtr& styleNode)
UIWidget::onStyleApply(styleNode); UIWidget::onStyleApply(styleNode);
for(OTMLNodePtr node : styleNode->children()) { for(OTMLNodePtr node : styleNode->children()) {
if(node->tag() == "text-translate") { if(node->tag() == "text-offset") {
m_textTranslate = node->value<Point>(); m_textOffset = node->value<Point>();
} else if(node->tag() == "text") { } else if(node->tag() == "text") {
m_text = node->value(); m_text = node->value();
} }

View File

@ -44,7 +44,7 @@ protected:
virtual void onMouseRelease(const Point& mousePos, Fw::MouseButton button); virtual void onMouseRelease(const Point& mousePos, Fw::MouseButton button);
SimpleCallback m_onClick; SimpleCallback m_onClick;
Point m_textTranslate; Point m_textOffset;
std::string m_text; std::string m_text;
}; };

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2010-2011 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.
*/
#include "uicheckbox.h"
#include <framework/otml/otmlnode.h>
#include <framework/graphics/image.h>
#include <framework/graphics/font.h>
#include <framework/graphics/graphics.h>
#include <framework/core/eventdispatcher.h>
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<Point>();
else if(node->tag() == "text")
m_text = node->value();
else if(node->tag() == "box-size")
m_boxSize = node->value<Size>();
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<bool>()));
}
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2010-2011 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 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<UICheckBox>(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

View File

@ -21,6 +21,7 @@
*/ */
#include "uiframecounter.h" #include "uiframecounter.h"
#include "uitranslator.h"
#include <framework/graphics/font.h> #include <framework/graphics/font.h>
#include <framework/otml/otmlnode.h> #include <framework/otml/otmlnode.h>
#include <framework/platform/platform.h> #include <framework/platform/platform.h>

View File

@ -21,6 +21,7 @@
*/ */
#include "uilabel.h" #include "uilabel.h"
#include "uitranslator.h"
#include <framework/graphics/font.h> #include <framework/graphics/font.h>
#include <framework/otml/otmlnode.h> #include <framework/otml/otmlnode.h>

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2010-2011 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.
*/
#include "uitranslator.h"
#include <boost/algorithm/string.hpp>
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;
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2010-2011 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 TRANSLATOR_H
#define TRANSLATOR_H
#include "../const.h"
#include <string>
namespace Fw {
AlignmentFlag translateAlignment(std::string aligment);
AnchorEdge translateAnchorEdge(std::string anchorEdge);
WidgetState translateState(std::string state);
};
#endif

View File

@ -24,6 +24,7 @@
#include "uimanager.h" #include "uimanager.h"
#include "uianchorlayout.h" #include "uianchorlayout.h"
#include "uiverticallayout.h" #include "uiverticallayout.h"
#include "uitranslator.h"
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
#include <framework/graphics/image.h> #include <framework/graphics/image.h>
@ -36,6 +37,7 @@
UIWidget::UIWidget() UIWidget::UIWidget()
{ {
m_updateEventScheduled = false; m_updateEventScheduled = false;
m_firstOnStyle = true;
m_states = Fw::DefaultState; m_states = Fw::DefaultState;
// generate an unique id, this is need because anchored layouts find widgets by id // generate an unique id, this is need because anchored layouts find widgets by id
@ -611,6 +613,28 @@ void UIWidget::updateLayout()
m_layout->update(); 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) void UIWidget::updateState(Fw::WidgetState state)
{ {
bool newStatus = true; bool newStatus = true;
@ -675,12 +699,7 @@ void UIWidget::updateState(Fw::WidgetState state)
} }
if(newStatus != oldStatus) { if(newStatus != oldStatus) {
if(newStatus) setState(state, newStatus);
m_states |= state;
else
m_states &= ~state;
updateStyle();
if(state == Fw::FocusState) { if(state == Fw::FocusState) {
g_dispatcher.addEvent(std::bind(&UIWidget::onFocusChange, asUIWidget(), newStatus, m_lastFocusReason)); g_dispatcher.addEvent(std::bind(&UIWidget::onFocusChange, asUIWidget(), newStatus, m_lastFocusReason));
@ -691,10 +710,8 @@ void UIWidget::updateState(Fw::WidgetState state)
void UIWidget::updateStates() void UIWidget::updateStates()
{ {
updateState(Fw::ActiveState); for(int state = 1; state != Fw::LastState; state <<= 1)
updateState(Fw::FocusState); updateState((Fw::WidgetState)state);
updateState(Fw::DisabledState);
updateState(Fw::HoverState);
} }
void UIWidget::updateStyle() void UIWidget::updateStyle()
@ -712,26 +729,32 @@ void UIWidget::updateStyle()
} }
} }
// merge states styles, NOTE: order does matter // checks for states combination
OTMLNodePtr style = m_style->get("state.active"); for(const OTMLNodePtr& style : m_style->children()) {
if(style && hasState(Fw::ActiveState)) if(boost::starts_with(style->tag(), "$")) {
newStateStyle->merge(style); std::string statesStr = style->tag().substr(1);
std::vector<std::string> statesSplit;
boost::split(statesSplit, statesStr, boost::is_any_of(std::string(" ")));
style = m_style->get("state.focus"); bool match = true;
if(style && hasState(Fw::FocusState)) for(std::string stateStr : statesSplit) {
newStateStyle->merge(style); if(stateStr.length() == 0)
continue;
style = m_style->get("state.hover"); bool notstate = (stateStr[0] == '!');
if(style && hasState(Fw::HoverState)) if(notstate)
newStateStyle->merge(style); stateStr = stateStr.substr(1);
style = m_style->get("state.pressed"); bool stateOn = hasState(Fw::translateState(stateStr));
if(style && hasState(Fw::PressedState)) if((!notstate && !stateOn) || (notstate && stateOn))
newStateStyle->merge(style); match = false;
}
style = m_style->get("state.disabled"); // merge states styles
if(style && hasState(Fw::DisabledState)) if(match)
newStateStyle->merge(style); newStateStyle->merge(style);
}
}
applyStyle(newStateStyle); applyStyle(newStateStyle);
m_stateStyle = newStateStyle; m_stateStyle = newStateStyle;
@ -886,13 +909,25 @@ void UIWidget::onStyleApply(const OTMLNodePtr& styleNode)
anchorLayout->addAnchor(asUIWidget(), anchoredEdge, hookedWidgetId, hookedEdge); anchorLayout->addAnchor(asUIWidget(), anchoredEdge, hookedWidgetId, hookedEdge);
} }
} else if(node->tag() == "onClick" || // lua functions
node->tag() == "onMousePress" || } else if(boost::starts_with(node->tag(), "@")) {
node->tag() == "onHoverChange") { // on load once
g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]"); if(m_firstOnStyle) {
luaSetField(node->tag()); 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) void UIWidget::onGeometryUpdate(const Rect& oldRect, const Rect& newRect)

View File

@ -80,49 +80,48 @@ public:
void unlock(); void unlock();
void focus(); void focus();
bool isActive() const { return hasState(Fw::ActiveState); } bool isActive() { return hasState(Fw::ActiveState); }
bool isEnabled() const { return !hasState(Fw::DisabledState); } bool isEnabled() { return !hasState(Fw::DisabledState); }
bool isDisabled() const { return hasState(Fw::DisabledState); } bool isDisabled() { return hasState(Fw::DisabledState); }
bool isFocused() const { return hasState(Fw::FocusState); } bool isFocused() { return hasState(Fw::FocusState); }
bool isHovered() const { return hasState(Fw::HoverState); } bool isHovered() { return hasState(Fw::HoverState); }
bool isPressed() const { return hasState(Fw::PressedState); } bool isPressed() { return hasState(Fw::PressedState); }
bool isVisible(); bool isVisible();
bool isHidden() { return !isVisible(); } bool isHidden() { return !isVisible(); }
bool isExplicitlyEnabled() const { return m_enabled; } bool isExplicitlyEnabled() { return m_enabled; }
bool isExplicitlyVisible() const { return m_visible; } bool isExplicitlyVisible() { return m_visible; }
bool isFocusable() const { return m_focusable; } bool isFocusable() { return m_focusable; }
bool isPhantom() const { return m_phantom; } bool isPhantom() { return m_phantom; }
bool isSizeFixed() const { return m_fixedSize; } bool isSizeFixed() { return m_fixedSize; }
bool hasChildren() const { return m_children.size() > 0; } bool hasChildren() { return m_children.size() > 0; }
bool hasChild(const UIWidgetPtr& child); bool hasChild(const UIWidgetPtr& child);
bool hasState(Fw::WidgetState state) const { return m_states & state; }
std::string getId() const { return m_id; } std::string getId() { return m_id; }
int getChildCount() const { return m_children.size(); } int getChildCount() { return m_children.size(); }
UILayoutPtr getLayout() const { return m_layout; } UILayoutPtr getLayout() { return m_layout; }
UIWidgetPtr getParent() const { return m_parent.lock(); } UIWidgetPtr getParent() { return m_parent.lock(); }
UIWidgetPtr getRootParent(); UIWidgetPtr getRootParent();
Point getPosition() const { return m_rect.topLeft(); } Point getPosition() { return m_rect.topLeft(); }
Size getSize() const { return m_rect.size(); } Size getSize() { return m_rect.size(); }
Rect getRect() const { return m_rect; } Rect getRect() { return m_rect; }
int getX() const { return m_rect.x(); } int getX() { return m_rect.x(); }
int getY() const { return m_rect.y(); } int getY() { return m_rect.y(); }
int getWidth() const { return m_rect.width(); } int getWidth() { return m_rect.width(); }
int getHeight() const { return m_rect.height(); } int getHeight() { return m_rect.height(); }
ImagePtr getImage() const { return m_image; } ImagePtr getImage() { return m_image; }
FontPtr getFont() const { return m_font; } FontPtr getFont() { return m_font; }
Color getForegroundColor() const { return m_foregroundColor; } Color getForegroundColor() { return m_foregroundColor; }
Color getBackgroundColor() const { return m_backgroundColor; } Color getBackgroundColor() { return m_backgroundColor; }
int getOpacity() const { return m_opacity; } int getOpacity() { return m_opacity; }
int getMarginLeft() const { return m_marginLeft; } int getMarginLeft() { return m_marginLeft; }
int getMarginRight() const { return m_marginRight; } int getMarginRight() { return m_marginRight; }
int getMarginTop() const { return m_marginTop; } int getMarginTop() { return m_marginTop; }
int getMarginBottom() const { return m_marginBottom; } int getMarginBottom() { return m_marginBottom; }
Fw::FocusReason getLastFocusReason() const { return m_lastFocusReason; } Fw::FocusReason getLastFocusReason() { return m_lastFocusReason; }
OTMLNodePtr getStyle() const { return m_style; } OTMLNodePtr getStyle() { return m_style; }
UIWidgetList getChildren() const { return m_children; } UIWidgetList getChildren() { return m_children; }
UIWidgetPtr getFocusedChild() const { return m_focusedChild; } UIWidgetPtr getFocusedChild() { return m_focusedChild; }
UIWidgetPtr getChildAfter(const UIWidgetPtr& relativeChild); UIWidgetPtr getChildAfter(const UIWidgetPtr& relativeChild);
UIWidgetPtr getChildBefore(const UIWidgetPtr& relativeChild); UIWidgetPtr getChildBefore(const UIWidgetPtr& relativeChild);
UIWidgetPtr getChildById(const std::string& childId); UIWidgetPtr getChildById(const std::string& childId);
@ -147,16 +146,17 @@ public:
void updateParentLayout(); void updateParentLayout();
void updateLayout(); void updateLayout();
virtual void updateState(Fw::WidgetState state);
void updateStates(); 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); void applyStyle(const OTMLNodePtr& styleNode);
UIWidgetPtr asUIWidget() { return std::static_pointer_cast<UIWidget>(shared_from_this()); } UIWidgetPtr asUIWidget() { return std::static_pointer_cast<UIWidget>(shared_from_this()); }
private:
bool m_updateEventScheduled;
protected: protected:
/// Triggered when widget style is changed /// Triggered when widget style is changed
virtual void onStyleApply(const OTMLNodePtr& styleNode); virtual void onStyleApply(const OTMLNodePtr& styleNode);
@ -190,6 +190,8 @@ protected:
bool m_fixedSize; bool m_fixedSize;
bool m_pressed; bool m_pressed;
bool m_phantom; bool m_phantom;
bool m_updateEventScheduled;
bool m_firstOnStyle;
Rect m_rect; Rect m_rect;
UILayoutPtr m_layout; UILayoutPtr m_layout;
UIWidgetWeakPtr m_parent; UIWidgetWeakPtr m_parent;
@ -198,7 +200,7 @@ protected:
UIWidgetPtr m_focusedChild; UIWidgetPtr m_focusedChild;
OTMLNodePtr m_style; OTMLNodePtr m_style;
OTMLNodePtr m_stateStyle; OTMLNodePtr m_stateStyle;
uint m_states; int m_states;
// basic style components used by all widgets // basic style components used by all widgets
ImagePtr m_image; ImagePtr m_image;

View File

@ -21,6 +21,7 @@
*/ */
#include "uiwindow.h" #include "uiwindow.h"
#include "uitranslator.h"
#include <framework/graphics/borderimage.h> #include <framework/graphics/borderimage.h>
#include <framework/graphics/font.h> #include <framework/graphics/font.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>