rework ui layouts, now it is more flexible and modular

This commit is contained in:
Eduardo Bart 2011-05-09 17:38:01 -03:00
parent 6d871b305f
commit 51fe97644d
29 changed files with 441 additions and 398 deletions

View File

@ -90,7 +90,7 @@ SET(SOURCES
src/framework/graphics/textarea.cpp src/framework/graphics/textarea.cpp
# framework ui # framework ui
src/framework/ui/uilayout.cpp src/framework/ui/uianchorlayout.cpp
src/framework/ui/uielement.cpp src/framework/ui/uielement.cpp
src/framework/ui/uielementskin.cpp src/framework/ui/uielementskin.cpp
src/framework/ui/uibuttonskin.cpp src/framework/ui/uibuttonskin.cpp

View File

@ -4,8 +4,7 @@ function onEnterMenuState()
end end
function onLeaveMenuState() function onLeaveMenuState()
mainMenu:destroy()
mainMenu = nil
end end
function onApplicationClose() function onApplicationClose()

View File

@ -34,7 +34,6 @@ panels:
# the default panel is empty # the default panel is empty
roundedGridPanel: roundedGridPanel:
default size: [117, 171]
bordered image: bordered image:
left border: [0,214,5,32] left border: [0,214,5,32]
right border: [6,214,5,32] right border: [6,214,5,32]

View File

@ -39,6 +39,7 @@ void Engine::init()
// initialize stuff // initialize stuff
g_graphics.init(); g_graphics.init();
g_fonts.init("tibia-12px-rounded"); g_fonts.init("tibia-12px-rounded");
g_lua.init();
} }
void Engine::terminate() void Engine::terminate()
@ -46,6 +47,14 @@ void Engine::terminate()
// terminate stuff // terminate stuff
g_fonts.terminate(); g_fonts.terminate();
g_graphics.terminate(); g_graphics.terminate();
// destroy root ui
UIContainer::getRoot()->destroy();
g_lua.terminate();
// poll remaning events
g_engine.poll();
} }
void Engine::poll() void Engine::poll()
@ -116,14 +125,6 @@ void Engine::run()
m_stopping = false; m_stopping = false;
m_running = false; m_running = false;
g_lua.collectGarbage();
// destroy root ui
rootContainer->destroy();
// poll remaning events
g_engine.poll();
} }
void Engine::stop() void Engine::stop()

View File

@ -41,11 +41,8 @@ void registerLuaFunctions()
g_lua.registerMemberFunction("load", &lua_UI_load); g_lua.registerMemberFunction("load", &lua_UI_load);
g_lua.registerMemberFunction("getRootContainer", &lua_UI_getRootContainer); g_lua.registerMemberFunction("getRootContainer", &lua_UI_getRootContainer);
// UILayout
g_lua.registerClass("UILayout");
// UIElement // UIElement
g_lua.registerClass("UIElement", "UILayout"); g_lua.registerClass("UIElement");
g_lua.registerMemberField("id", &lua_UIElement_getId, &lua_UIElement_setId); g_lua.registerMemberField("id", &lua_UIElement_getId, &lua_UIElement_setId);
g_lua.registerMemberField("enabled", &lua_UIElement_isEnabled, &lua_UIElement_setEnabled); g_lua.registerMemberField("enabled", &lua_UIElement_isEnabled, &lua_UIElement_setEnabled);
g_lua.registerMemberField("visible", &lua_UIElement_isVisible, &lua_UIElement_setVisible); g_lua.registerMemberField("visible", &lua_UIElement_isVisible, &lua_UIElement_setVisible);
@ -224,7 +221,7 @@ int lua_UIElement_setLocked()
int lua_UIElement_destroy() int lua_UIElement_destroy()
{ {
if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance())) if(UIElementPtr element = boost::dynamic_pointer_cast<UIElement>(g_lua.popClassInstance()))
element->destroy(); element->destroyLater();
g_dispatcher.addTask(boost::bind(&LuaScript::collectGarbage, &g_lua)); g_dispatcher.addTask(boost::bind(&LuaScript::collectGarbage, &g_lua));
return 1; return 1;
} }

View File

@ -30,7 +30,7 @@
LuaScript g_lua; LuaScript g_lua;
LuaScript::LuaScript() void LuaScript::init()
{ {
L = luaL_newstate(); L = luaL_newstate();
if(!L) if(!L)
@ -45,9 +45,11 @@ LuaScript::LuaScript()
registerLuaFunctions(); registerLuaFunctions();
} }
LuaScript::~LuaScript() void LuaScript::terminate()
{ {
collectGarbage();
lua_close(L); lua_close(L);
L = NULL;
} }
void LuaScript::loadAllModules() void LuaScript::loadAllModules()

View File

@ -36,8 +36,10 @@ struct lua_State;
class LuaScript class LuaScript
{ {
public: public:
LuaScript(); LuaScript() : L(NULL) { }
virtual ~LuaScript();
void init();
void terminate();
void loadAllModules(); void loadAllModules();
bool loadFile(const std::string& fileName); bool loadFile(const std::string& fileName);

View File

@ -0,0 +1,162 @@
/* 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.
*/
#include <prerequisites.h>
#include <ui/uianchorlayout.h>
UIElementPtr Anchor::getAnchorLineElement() const
{
if(!m_anchoredElement.expired())
return m_anchoredElement.lock()->backwardsGetElementById(m_anchorLine.getElementId());
return UIElementPtr();
}
int Anchor::getAnchorLinePoint() const
{
UIElementPtr anchorLineElement = getAnchorLineElement();
if(anchorLineElement) {
switch(m_anchorLine.getEdge()) {
case UI::AnchorLeft:
return anchorLineElement->getRect().left();
case UI::AnchorRight:
return anchorLineElement->getRect().right();
case UI::AnchorTop:
return anchorLineElement->getRect().top();
case UI::AnchorBottom:
return anchorLineElement->getRect().bottom();
case UI::AnchorHorizontalCenter:
return anchorLineElement->getRect().horizontalCenter();
case UI::AnchorVerticalCenter:
return anchorLineElement->getRect().verticalCenter();
default:
break;
}
}
return -9999;
}
bool UIAnchorLayout::addAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const AnchorLine& anchorLine)
{
Anchor anchor(anchoredElement, anchoredEdge, anchorLine);
UIElementPtr anchorLineElement = anchor.getAnchorLineElement();
// we can never anchor with itself
if(anchoredElement == anchorLineElement) {
logError("ERROR: anchoring with itself is not possible");
return false;
}
// TODO: check if itself is already anchored on the anchor element
// setup the anchor
m_anchors.push_back(anchor);
// recalculate anchored element layout
recalculateElementLayout(anchoredElement);
return true;
}
void UIAnchorLayout::recalculateElementLayout(const UIElementPtr& element)
{
Rect rect = element->getRect();
bool verticalMoved = false;
bool horizontalMoved = false;
foreach(const Anchor& anchor, m_anchors) {
if(anchor.getAnchoredElement() == element && anchor.getAnchorLineElement()) {
int point = anchor.getAnchorLinePoint();
switch(anchor.getAnchoredEdge()) {
case UI::AnchorHorizontalCenter:
rect.moveHorizontalCenter(point + element->getMarginLeft() - element->getMarginRight());
horizontalMoved = true;
break;
case UI::AnchorLeft:
if(!horizontalMoved) {
rect.moveLeft(point + element->getMarginLeft());
horizontalMoved = true;
} else
rect.setLeft(point + element->getMarginLeft());
break;
case UI::AnchorRight:
if(!horizontalMoved) {
rect.moveRight(point - element->getMarginRight());
horizontalMoved = true;
} else
rect.setRight(point - element->getMarginRight());
break;
case UI::AnchorVerticalCenter:
rect.moveVerticalCenter(point + element->getMarginTop() - element->getMarginBottom());
verticalMoved = true;
break;
case UI::AnchorTop:
if(!verticalMoved) {
rect.moveTop(point + element->getMarginTop());
verticalMoved = true;
} else
rect.setTop(point + element->getMarginTop());
break;
case UI::AnchorBottom:
if(!verticalMoved) {
rect.moveBottom(point - element->getMarginBottom());
verticalMoved = true;
} else
rect.setBottom(point - element->getMarginBottom());
break;
default:
break;
}
}
}
if(rect != element->getRect())
element->setRect(rect);
}
void UIAnchorLayout::recalculateChildrenLayout(const UIElementPtr& parent)
{
foreach(const Anchor& anchor, m_anchors) {
if(anchor.getAnchorLineElement() == parent) {
UIElementPtr child = anchor.getAnchoredElement();
if(child)
recalculateElementLayout(child);
}
}
}
UI::AnchorPoint UIAnchorLayout::parseAnchorPoint(const std::string& anchorPointStr)
{
if(anchorPointStr == "left")
return UI::AnchorLeft;
else if(anchorPointStr == "right")
return UI::AnchorRight;
else if(anchorPointStr == "top")
return UI::AnchorTop;
else if(anchorPointStr == "bottom")
return UI::AnchorBottom;
else if(anchorPointStr == "horizontalCenter")
return UI::AnchorHorizontalCenter;
else if(anchorPointStr == "verticalCenter")
return UI::AnchorVerticalCenter;
return UI::AnchorNone;
}

View File

@ -0,0 +1,77 @@
/* 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 UIANCHORLAYOUT_H
#define UIANCHORLAYOUT_H
#include <prerequisites.h>
#include <ui/uiconstants.h>
#include <ui/uilayout.h>
#include <ui/uielement.h>
class AnchorLine
{
public:
AnchorLine(const std::string& elementId, UI::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; }
const std::string& getElementId() const { return m_elementId; }
private:
std::string m_elementId;
UI::AnchorPoint m_edge;
};
class Anchor
{
public:
Anchor(const UIElementPtr& anchoredElement, UI::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; }
int getAnchorLinePoint() const;
private:
UIElementWeakPtr m_anchoredElement;
UI::AnchorPoint m_anchoredEdge;
AnchorLine m_anchorLine;
};
class UIAnchorLayout : public UILayout
{
public:
bool addAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const AnchorLine& anchorLine);
void recalculateElementLayout(const UIElementPtr& element);
void recalculateChildrenLayout(const UIElementPtr& parent);
static UI::AnchorPoint parseAnchorPoint(const std::string& anchorPointStr);
private:
std::vector<Anchor> m_anchors;
};
typedef boost::shared_ptr<UIAnchorLayout> UIAnchorLayoutPtr;
#endif // UIANCHORLAYOUT_H

View File

@ -29,9 +29,9 @@
void UIButton::onInputEvent(const InputEvent& event) void UIButton::onInputEvent(const InputEvent& event)
{ {
if(event.type == EV_MOUSE_LDOWN && getRect().contains(event.mousePos)) { if(event.type == EV_MOUSE_LDOWN && getRect().contains(event.mousePos)) {
m_state = UI::ButtonDown; m_state = ButtonDown;
} else if(event.type == EV_MOUSE_LUP && m_state == UI::ButtonDown) { } else if(event.type == EV_MOUSE_LUP && m_state == ButtonDown) {
m_state = UI::ButtonUp; m_state = ButtonUp;
if(getRect().contains(event.mousePos)) { if(getRect().contains(event.mousePos)) {
g_dispatcher.addTask(boost::bind(&Scriptable::callLuaTableField, shared_from_this(), "onClick")); g_dispatcher.addTask(boost::bind(&Scriptable::callLuaTableField, shared_from_this(), "onClick"));
} }

View File

@ -35,22 +35,29 @@ typedef boost::shared_ptr<UIButton> UIButtonPtr;
class UIButton : public UIElement class UIButton : public UIElement
{ {
public: public:
enum ButtonState
{
ButtonUp,
ButtonDown,
ButtonMouseOver
};
UIButton() : UIButton() :
UIElement(UI::Button), UIElement(UI::Button),
m_state(UI::ButtonUp) { } m_state(ButtonUp) { }
void onInputEvent(const InputEvent& event); void onInputEvent(const InputEvent& event);
void setText(const std::string& text) { m_text = text; } void setText(const std::string& text) { m_text = text; }
std::string getText() const { return m_text; } std::string getText() const { return m_text; }
UI::EButtonState getState() { return m_state; } ButtonState getState() { return m_state; }
virtual const char *getScriptableName() const { return "UIButton"; } virtual const char *getScriptableName() const { return "UIButton"; }
private: private:
std::string m_text; std::string m_text;
UI::EButtonState m_state; ButtonState m_state;
}; };
#endif // UIBUTTON_H #endif // UIBUTTON_H

View File

@ -50,10 +50,10 @@ void UIButtonSkin::draw(UIElement *element)
Rect textRect = button->getRect(); Rect textRect = button->getRect();
if(button->getState() == UI::ButtonDown && m_buttonDownImage) { if(button->getState() == UIButton::ButtonDown && m_buttonDownImage) {
m_buttonDownImage->draw(element->getRect()); m_buttonDownImage->draw(element->getRect());
textRect.translate(m_buttonDownTranslate); textRect.translate(m_buttonDownTranslate);
} else if(button->getState() == UI::ButtonMouseOver && m_buttonHoverImage) { } else if(button->getState() == UIButton::ButtonMouseOver && m_buttonHoverImage) {
m_buttonHoverImage->draw(element->getRect()); m_buttonHoverImage->draw(element->getRect());
} else { } else {
UIElementSkin::draw(element); UIElementSkin::draw(element);

View File

@ -25,7 +25,7 @@
#include <prerequisites.h> #include <prerequisites.h>
#include <ui/uicheckbox.h> #include <ui/uicheckbox.h>
UICheckBox::UICheckBox(UI::EElementType type): UIElement(type) UICheckBox::UICheckBox(UI::ElementType type): UIElement(type)
{ {
} }

View File

@ -31,7 +31,7 @@
class UICheckBox : public UIElement class UICheckBox : public UIElement
{ {
public: public:
UICheckBox(UI::EElementType type = UI::Element); UICheckBox(UI::ElementType type = UI::Element);
virtual const char *getScriptableName() const { return "UICheckBox"; } virtual const char *getScriptableName() const { return "UICheckBox"; }
}; };

View File

@ -26,33 +26,7 @@
#define UICONSTANTS_H #define UICONSTANTS_H
namespace UI { namespace UI {
enum EButtonState enum ElementType {
{
ButtonUp,
ButtonDown,
ButtonMouseOver
};
enum EButtonEvent
{
ButtonPressUp,
ButtonPressDown,
ButtonEnterMouseOver,
ButtonLeaveMouseOver
};
enum EMessageBoxFlags
{
MessageBoxOk = 1 << 0,
MessageBoxCancel = 1 << 1,
MessageBoxYes = 1 << 2,
MessageBoxNo = 1 << 3,
MessageBoxOkCancel = MessageBoxOk | MessageBoxCancel,
MessageBoxYesNo = MessageBoxYes | MessageBoxNo
};
enum EElementType
{
Element = 0, Element = 0,
Container, Container,
Panel, Panel,
@ -63,6 +37,16 @@ namespace UI {
CheckBox, CheckBox,
LineDecoration LineDecoration
}; };
enum AnchorPoint {
AnchorLeft = 0,
AnchorHorizontalCenter,
AnchorRight,
AnchorTop,
AnchorVerticalCenter,
AnchorBottom,
AnchorNone
};
} }
#endif // UICONSTANTS_H #endif // UICONSTANTS_H

View File

@ -25,9 +25,10 @@
#include <prerequisites.h> #include <prerequisites.h>
#include <core/resources.h> #include <core/resources.h>
#include <ui/uicontainer.h> #include <ui/uicontainer.h>
#include <ui/uianchorlayout.h>
#include <core/dispatcher.h> #include <core/dispatcher.h>
void UIContainer::internalOnDestroy() void UIContainer::destroy()
{ {
//logTraceDebug(getId()); //logTraceDebug(getId());
@ -37,11 +38,11 @@ void UIContainer::internalOnDestroy()
// destroy children // destroy children
while(m_children.size() > 0) { while(m_children.size() > 0) {
UIElementPtr element = m_children.back(); //hold reference UIElementPtr element = m_children.front(); //hold reference
element->internalOnDestroy(); element->destroy();
} }
UIElement::internalOnDestroy(); UIElement::destroy();
} }
UIContainerPtr& UIContainer::getRoot() UIContainerPtr& UIContainer::getRoot()
@ -50,6 +51,7 @@ UIContainerPtr& UIContainer::getRoot()
if(!rootContainer) { if(!rootContainer) {
rootContainer = UIContainerPtr(new UIContainer); rootContainer = UIContainerPtr(new UIContainer);
rootContainer->setId("root"); rootContainer->setId("root");
rootContainer->setLayout(UILayoutPtr(new UIAnchorLayout));
} }
return rootContainer; return rootContainer;
} }
@ -87,9 +89,15 @@ bool UIContainer::hasChild(const UIElementPtr& child)
UIElementPtr UIContainer::getChildById(const std::string& id) UIElementPtr UIContainer::getChildById(const std::string& id)
{ {
if(getId() == id) if(getId() == id || id == "self")
return asUIElement(); return asUIElement();
if(id == "parent")
return getParent();
if(id == "root")
return getRoot();
foreach(const UIElementPtr& child, m_children) { foreach(const UIElementPtr& child, m_children) {
if(child->getId() == id) if(child->getId() == id)
return child; return child;
@ -111,9 +119,15 @@ UIElementPtr UIContainer::getChildByPos(const Point& pos)
UIElementPtr UIContainer::recursiveGetChildById(const std::string& id) UIElementPtr UIContainer::recursiveGetChildById(const std::string& id)
{ {
if(getId() == id) if(getId() == id || id == "self")
return asUIElement(); return asUIElement();
if(id == "parent")
return getParent();
if(id == "root")
return getRoot();
foreach(const UIElementPtr& element, m_children) { foreach(const UIElementPtr& element, m_children) {
if(element->getId() == id) if(element->getId() == id)
return element; return element;

View File

@ -31,10 +31,11 @@
class UIContainer : public UIElement class UIContainer : public UIElement
{ {
public: public:
UIContainer(UI::EElementType type = UI::Container) : UIContainer(UI::ElementType type = UI::Container) :
UIElement(type) { } UIElement(type) { }
virtual ~UIContainer() { } virtual ~UIContainer() { }
virtual void destroy();
virtual void onLoad(); virtual void onLoad();
virtual void render(); virtual void render();
virtual void onInputEvent(const InputEvent& event); virtual void onInputEvent(const InputEvent& event);
@ -70,7 +71,7 @@ public:
/// Get focused element /// Get focused element
UIElementPtr getFocusedElement() const { return m_focusedElement; } UIElementPtr getFocusedElement() const { return m_focusedElement; }
virtual UI::EElementType getElementType() const { return UI::Container; } virtual UI::ElementType getElementType() const { return UI::Container; }
UIContainerPtr asUIContainer() { return boost::static_pointer_cast<UIContainer>(shared_from_this()); } UIContainerPtr asUIContainer() { return boost::static_pointer_cast<UIContainer>(shared_from_this()); }
virtual const char *getScriptableName() const { return "UIContainer"; } virtual const char *getScriptableName() const { return "UIContainer"; }
@ -78,9 +79,6 @@ public:
/// Get root container (the container that contains everything) /// Get root container (the container that contains everything)
static UIContainerPtr& getRoot(); static UIContainerPtr& getRoot();
protected:
virtual void internalOnDestroy();
private: private:
std::list<UIElementPtr> m_children; std::list<UIElementPtr> m_children;
std::list<UIElementPtr> m_lockedElements; std::list<UIElementPtr> m_lockedElements;

View File

@ -30,11 +30,15 @@
#include <ui/uielementskin.h> #include <ui/uielementskin.h>
#include <ui/uicontainer.h> #include <ui/uicontainer.h>
UIElement::UIElement(UI::EElementType type) : UIElement::UIElement(UI::ElementType type) :
UILayout(), Scriptable(),
m_type(type), m_type(type),
m_visible(true), m_visible(true),
m_enabled(true) m_enabled(true),
m_marginLeft(0),
m_marginRight(0),
m_marginTop(0),
m_marginBottom(0)
{ {
} }
@ -44,13 +48,13 @@ UIElement::~UIElement()
//logTraceDebug(getId()); //logTraceDebug(getId());
} }
void UIElement::destroy() void UIElement::destroyLater()
{ {
//logTraceDebug(getId()); //logTraceDebug(getId());
g_dispatcher.addTask(boost::bind(&UIElement::internalOnDestroy, asUIElement())); g_dispatcher.addTask(boost::bind(&UIElement::destroy, asUIElement()));
} }
void UIElement::internalOnDestroy() void UIElement::destroy()
{ {
//logTraceDebug(getId()); //logTraceDebug(getId());
@ -58,17 +62,16 @@ void UIElement::internalOnDestroy()
callLuaTableField("onDestroy"); callLuaTableField("onDestroy");
// remove from parent // remove from parent
if(getParent()) { if(getParent())
getParent()->removeChild(me); getParent()->removeChild(me);
}
// free script stuff // free script stuff
releaseLuaTableRef(); releaseLuaTableRef();
g_dispatcher.addTask(boost::bind(&UIElement::internalDestroyCheck, asUIElement())); g_dispatcher.addTask(boost::bind(&UIElement::destroyCheck, me));
} }
void UIElement::internalDestroyCheck() void UIElement::destroyCheck()
{ {
//logTraceDebug(getId()); //logTraceDebug(getId());
@ -79,6 +82,29 @@ void UIElement::internalDestroyCheck()
} }
} }
void UIElement::setSize(const Size& size)
{
Rect rect = getRect();
if(rect.isValid())
rect.setSize(size);
else
rect = Rect(0, 0, size);
setRect(rect);
getLayout()->recalculateElementLayout(asUIElement());
}
void UIElement::setRect(const Rect& rect)
{
if(rect != m_rect) {
m_rect = rect;
// rect updated, recalculate children layout
getLayout()->recalculateChildrenLayout(asUIElement());
onRectUpdate();
}
}
void UIElement::setSkin(const UIElementSkinPtr& skin) void UIElement::setSkin(const UIElementSkinPtr& skin)
{ {
m_skin = skin; m_skin = skin;
@ -100,11 +126,16 @@ void UIElement::render()
UIElementPtr UIElement::backwardsGetElementById(const std::string& id) UIElementPtr UIElement::backwardsGetElementById(const std::string& id)
{ {
if(getId() == id) if(getId() == id || id == "self")
return asUIElement(); return asUIElement();
UIElementPtr element; if(id == "parent")
return getParent();
if(id == "root")
return UIContainer::getRoot();
UIElementPtr element;
if(asUIContainer()) { if(asUIContainer()) {
element = asUIContainer()->recursiveGetChildById(id); element = asUIContainer()->recursiveGetChildById(id);
if(element) if(element)
@ -169,3 +200,12 @@ void UIElement::setFocused(bool focused)
} }
} }
} }
UILayoutPtr UIElement::getLayout() const
{
if(m_layout)
return m_layout;
else if(getParent())
return getParent()->getLayout();
return UILayoutPtr();
}

View File

@ -27,9 +27,10 @@
#include <prerequisites.h> #include <prerequisites.h>
#include <core/input.h> #include <core/input.h>
#include <script/scriptable.h>
#include <ui/uiconstants.h> #include <ui/uiconstants.h>
#include <ui/uilayout.h>
#include <ui/uielementskin.h> #include <ui/uielementskin.h>
#include <ui/uilayout.h>
class UIElementSkin; class UIElementSkin;
@ -41,18 +42,15 @@ class UIElement;
typedef boost::shared_ptr<UIElement> UIElementPtr; typedef boost::shared_ptr<UIElement> UIElementPtr;
typedef boost::weak_ptr<UIElement> UIElementWeakPtr; typedef boost::weak_ptr<UIElement> UIElementWeakPtr;
typedef boost::function<void(UIElementPtr)> UIElementCallback; class UIElement : public Scriptable
class UIElement : public UILayout
{ {
public: public:
UIElement(UI::EElementType type = UI::Element); UIElement(UI::ElementType type = UI::Element);
virtual ~UIElement(); virtual ~UIElement();
/// Destroy this element by removing it from its parent void destroyLater();
void destroy(); virtual void destroy();
virtual void internalOnDestroy(); virtual void destroyCheck();
virtual void internalDestroyCheck();
/// Draw element /// Draw element
virtual void render(); virtual void render();
@ -61,11 +59,15 @@ public:
virtual void onLoad(); virtual void onLoad();
virtual void onInputEvent(const InputEvent& event) { } virtual void onInputEvent(const InputEvent& event) { }
virtual void onFocusChange() { } virtual void onFocusChange() { }
virtual void onRectUpdate() { }
UIElementPtr backwardsGetElementById(const std::string& id); UIElementPtr backwardsGetElementById(const std::string& id);
void moveTo(Point pos); void moveTo(Point pos);
void setLayout(const UILayoutPtr& layout) { m_layout = layout; }
UILayoutPtr getLayout() const;
void setSkin(const UIElementSkinPtr& skin); void setSkin(const UIElementSkinPtr& skin);
UIElementSkinPtr getSkin() const { return m_skin; } UIElementSkinPtr getSkin() const { return m_skin; }
@ -85,19 +87,48 @@ public:
bool isVisible() const { return m_visible; } bool isVisible() const { return m_visible; }
virtual bool isFocusable() const { return false; } virtual bool isFocusable() const { return false; }
UI::EElementType getElementType() const { return m_type; } UI::ElementType getElementType() const { return m_type; }
UIElementPtr asUIElement() { return boost::static_pointer_cast<UIElement>(shared_from_this()); } UIElementPtr asUIElement() { return boost::static_pointer_cast<UIElement>(shared_from_this()); }
virtual UIContainerPtr asUIContainer() { return UIContainerPtr(); } virtual UIContainerPtr asUIContainer() { return UIContainerPtr(); }
virtual const char *getScriptableName() const { return "UIElement"; } virtual const char *getScriptableName() const { return "UIElement"; }
void setSize(const Size& size);
Size getSize() { return m_rect.size(); }
/// Set the layout rect, always absolute position
void setRect(const Rect& rect);
/// Get layout size, it always return the absolute position
Rect getRect() const { return m_rect; }
// margins
void setMargin(int top, int left, int bottom, int right) { m_marginLeft = left; m_marginRight = right; m_marginTop = top; m_marginBottom = bottom; getLayout()->recalculateElementLayout(asUIElement()); }
void setMargin(int horizontal, int vertical) { m_marginLeft = m_marginRight = horizontal; m_marginTop = m_marginBottom = vertical; getLayout()->recalculateElementLayout(asUIElement()); }
void setMargin(int margin) { m_marginLeft = m_marginRight = m_marginTop = m_marginBottom = margin; getLayout()->recalculateElementLayout(asUIElement()); }
void setMarginLeft(int margin) { m_marginLeft = margin; getLayout()->recalculateElementLayout(asUIElement()); }
void setMarginRight(int margin) { m_marginRight = margin; getLayout()->recalculateElementLayout(asUIElement()); }
void setMarginTop(int margin) { m_marginTop = margin; getLayout()->recalculateElementLayout(asUIElement()); }
void setMarginBottom(int margin) { m_marginBottom = margin; getLayout()->recalculateElementLayout(asUIElement()); }
int getMarginLeft() const { return m_marginLeft; }
int getMarginRight() const { return m_marginRight; }
int getMarginTop() const { return m_marginTop; }
int getMarginBottom() const { return m_marginBottom; }
private: private:
UI::EElementType m_type; UI::ElementType m_type;
UIContainerWeakPtr m_parent; UIContainerWeakPtr m_parent;
UIElementSkinPtr m_skin; UIElementSkinPtr m_skin;
UILayoutPtr m_layout;
std::string m_id; std::string m_id;
bool m_visible; bool m_visible;
bool m_enabled; bool m_enabled;
Rect m_rect;
int m_marginLeft;
int m_marginRight;
int m_marginTop;
int m_marginBottom;
}; };
#endif // UIELEMENT_H #endif // UIELEMENT_H

View File

@ -34,7 +34,7 @@ class UIElement;
class UIElementSkin class UIElementSkin
{ {
public: public:
UIElementSkin(const std::string& name, UI::EElementType elementType) : UIElementSkin(const std::string& name, UI::ElementType elementType) :
m_name(name), m_name(name),
m_elementType(elementType) { } m_elementType(elementType) { }
UIElementSkin() : m_elementType(UI::Element) { } UIElementSkin() : m_elementType(UI::Element) { }
@ -49,7 +49,7 @@ public:
const std::string& getName() const { return m_name; } const std::string& getName() const { return m_name; }
const Size& getDefaultSize() const { return m_defaultSize; } const Size& getDefaultSize() const { return m_defaultSize; }
UI::EElementType getElementType() const { return m_elementType; } UI::ElementType getElementType() const { return m_elementType; }
ImagePtr getDefaultImage() const { return m_defaultImage; } ImagePtr getDefaultImage() const { return m_defaultImage; }
protected: protected:
@ -57,7 +57,7 @@ protected:
private: private:
std::string m_name; std::string m_name;
UI::EElementType m_elementType; UI::ElementType m_elementType;
Size m_defaultSize; Size m_defaultSize;
ImagePtr m_defaultImage; ImagePtr m_defaultImage;
}; };

View File

@ -1,160 +0,0 @@
/* 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.
*/
#include <prerequisites.h>
#include <ui/uielement.h>
#include <ui/uilayout.h>
int AnchorLine::getPos() const
{
UILayoutPtr element = m_relativeElement.lock();
if(element) {
switch(m_anchorType) {
case ANCHOR_LEFT:
return element->getRect().left();
case ANCHOR_RIGHT:
return element->getRect().right();
case ANCHOR_TOP:
return element->getRect().top();
case ANCHOR_BOTTOM:
return element->getRect().bottom();
case ANCHOR_HORIZONTAL_CENTER:
return element->getRect().horizontalCenter();
case ANCHOR_VERTICAL_CENTER:
return element->getRect().verticalCenter();
default:
return 0;
}
}
logError("ERROR: anchor line of an element has expired, your UI is missconfigured");
return 0;
}
void UILayout::setSize(const Size& size)
{
if(m_rect.isValid())
m_rect.setSize(size);
else
m_rect = Rect(0, 0, size);
// rect updated, recalculate itself and anchored elements positions
recalculateLayout();
}
void UILayout::setRect(const Rect& rect)
{
m_rect = rect;
// rect updated, recalculate itself and anchored elements positions
recalculateAnchoredLayout();
}
bool UILayout::addAnchor(EAnchorType type, const AnchorLine& anchorLine)
{
// we can never anchor with itself
if(anchorLine.getRelativeElement() == asUILayout()) {
logError("ERROR: anchoring with itself is not possible");
return false;
}
// check if this layout is already anchored with the relative element
// this only happens in missconfigurations
for(auto it = m_anchoredElements.begin(); it != m_anchoredElements.end(); ++it) {
if((*it).lock() == anchorLine.getRelativeElement()) {
logError("ERROR: anchoring elements with each other is not possible");
return false;
}
}
// setup the anchor
m_anchors[type] = anchorLine;
anchorLine.getRelativeElement()->addAnchoredElement(asUILayout());
// recalculate itself and anchored elements
recalculateLayout();
return true;
}
void UILayout::addAnchoredElement(UILayoutPtr anchoredElement)
{
// check if is already anchored
bool found = false;
for(auto it = m_anchoredElements.begin(); it != m_anchoredElements.end(); ++it) {
if((*it).lock() == anchoredElement) {
found = true;
break;
}
}
// if not, anchor it
if(!found)
m_anchoredElements.push_back(anchoredElement);
}
void UILayout::recalculateLayout()
{
// recalculate horizontal position
if(m_anchors[ANCHOR_HORIZONTAL_CENTER].isValid()) {
m_rect.moveHorizontalCenter(m_anchors[ANCHOR_HORIZONTAL_CENTER].getPos() + m_marginLeft - m_marginRight);
} else {
if(m_anchors[ANCHOR_LEFT].isValid() && m_anchors[ANCHOR_RIGHT].isValid()) {
m_rect.setLeft(m_anchors[ANCHOR_LEFT].getPos() + m_marginLeft);
m_rect.setRight(m_anchors[ANCHOR_RIGHT].getPos() - m_marginRight);
} else if(m_anchors[ANCHOR_LEFT].isValid()) {
m_rect.moveLeft(m_anchors[ANCHOR_LEFT].getPos() + m_marginLeft);
} else if(m_anchors[ANCHOR_RIGHT].isValid()) {
m_rect.moveRight(m_anchors[ANCHOR_RIGHT].getPos() - m_marginRight);
}
}
// recalculate vertical position
if(m_anchors[ANCHOR_VERTICAL_CENTER].isValid()) {
m_rect.moveVerticalCenter(m_anchors[ANCHOR_VERTICAL_CENTER].getPos() + m_marginTop - m_marginBottom);
} else {
if(m_anchors[ANCHOR_TOP].isValid() && m_anchors[ANCHOR_BOTTOM].isValid()) {
m_rect.setTop(m_anchors[ANCHOR_TOP].getPos() + m_marginTop);
m_rect.setBottom(m_anchors[ANCHOR_BOTTOM].getPos() - m_marginBottom);
} else if(m_anchors[ANCHOR_TOP].isValid()) {
m_rect.moveTop(m_anchors[ANCHOR_TOP].getPos() + m_marginTop);
} else if(m_anchors[ANCHOR_BOTTOM].isValid()) {
m_rect.moveBottom(m_anchors[ANCHOR_BOTTOM].getPos() - m_marginBottom);
}
}
recalculateAnchoredLayout();
// fire layout update event
onLayoutRectChange(m_rect);
}
void UILayout::recalculateAnchoredLayout()
{
// recalculate anchored elements positions
for(auto it = m_anchoredElements.begin(); it != m_anchoredElements.end(); ++it) {
UILayoutPtr element = (*it).lock();
if(element)
element->recalculateLayout();
}
}

View File

@ -26,109 +26,20 @@
#define UILAYOUT_H #define UILAYOUT_H
#include <prerequisites.h> #include <prerequisites.h>
#include <ui/uiconstants.h>
#include <script/scriptable.h>
enum EAnchorType { class UIElement;
ANCHOR_LEFT = 0, typedef boost::shared_ptr<UIElement> UIElementPtr;
ANCHOR_RIGHT,
ANCHOR_TOP,
ANCHOR_BOTTOM,
ANCHOR_HORIZONTAL_CENTER,
ANCHOR_VERTICAL_CENTER,
ANCHOR_NONE
};
class UILayout; class UILayout;
typedef boost::shared_ptr<UILayout> UILayoutPtr; typedef boost::shared_ptr<UILayout> UILayoutPtr;
typedef boost::weak_ptr<UILayout> UILayoutWeakPtr;
class AnchorLine class UILayout : public boost::enable_shared_from_this<UILayout>
{ {
public: public:
AnchorLine() : m_anchorType(ANCHOR_NONE) { } UILayout() { }
AnchorLine(const AnchorLine& other) :
m_relativeElement(other.m_relativeElement), m_anchorType(other.m_anchorType) { }
AnchorLine(UILayoutPtr relativeElement, EAnchorType anchorType) :
m_relativeElement(relativeElement), m_anchorType(anchorType) { }
bool isValid() const { return (m_anchorType != ANCHOR_NONE && !m_relativeElement.expired()); }
/// Get the position relative to this anchor line virtual void recalculateElementLayout(const UIElementPtr& element) = 0;
int getPos() const; virtual void recalculateChildrenLayout(const UIElementPtr& parent) = 0;
EAnchorType getAnchorType() const { return m_anchorType; }
UILayoutPtr getRelativeElement() const { return m_relativeElement.lock(); }
private:
UILayoutWeakPtr m_relativeElement;
EAnchorType m_anchorType;
};
class UILayout : public Scriptable
{
public:
UILayout() : Scriptable(),
m_marginLeft(0),
m_marginRight(0),
m_marginTop(0),
m_marginBottom(0) { }
virtual ~UILayout() { }
void setSize(const Size& size);
Size getSize() { return m_rect.size(); }
/// Set the layout rect, always absolute position
void setRect(const Rect& rect);
/// Get layout size, it always return the absolute position
Rect getRect() const { return m_rect; }
// anchors add methods
bool addAnchor(EAnchorType type, const AnchorLine& anchorLine);
void anchorLeft(const AnchorLine& anchorLine) { addAnchor(ANCHOR_LEFT, anchorLine); }
void anchorRight(const AnchorLine& anchorLine) { addAnchor(ANCHOR_RIGHT, anchorLine); }
void anchorTop(const AnchorLine& anchorLine) { addAnchor(ANCHOR_TOP, anchorLine); }
void anchorBottom(const AnchorLine& anchorLine) { addAnchor(ANCHOR_BOTTOM, anchorLine); }
void anchorHorizontalCenter(const AnchorLine& anchorLine) { addAnchor(ANCHOR_HORIZONTAL_CENTER, anchorLine); }
void anchorVerticalCenter(const AnchorLine& anchorLine) { addAnchor(ANCHOR_VERTICAL_CENTER, anchorLine); }
// anchor lines
AnchorLine left() { return AnchorLine(asUILayout(), ANCHOR_LEFT); }
AnchorLine right() { return AnchorLine(asUILayout(), ANCHOR_RIGHT); }
AnchorLine top() { return AnchorLine(asUILayout(), ANCHOR_TOP); }
AnchorLine bottom() { return AnchorLine(asUILayout(), ANCHOR_BOTTOM); }
AnchorLine horizontalCenter() { return AnchorLine(asUILayout(), ANCHOR_HORIZONTAL_CENTER); }
AnchorLine verticalCenter() { return AnchorLine(asUILayout(), ANCHOR_VERTICAL_CENTER); }
// margins
void setMargin(int top, int left, int bottom, int right) { m_marginLeft = left; m_marginRight = right; m_marginTop = top; m_marginBottom = bottom; recalculateLayout(); }
void setMargin(int horizontal, int vertical) { m_marginLeft = m_marginRight = horizontal; m_marginTop = m_marginBottom = vertical; recalculateLayout(); }
void setMargin(int margin) { m_marginLeft = m_marginRight = m_marginTop = m_marginBottom = margin; recalculateLayout(); }
void setMarginLeft(int margin) { m_marginLeft = margin; recalculateLayout(); }
void setMarginRight(int margin) { m_marginRight = margin; recalculateLayout(); }
void setMarginTop(int margin) { m_marginTop = margin; recalculateLayout(); }
void setMarginBottom(int margin) { m_marginBottom = margin; recalculateLayout(); }
UILayoutPtr asUILayout() { return boost::static_pointer_cast<UILayout>(shared_from_this()); }
virtual const char *getScriptableName() const { return "UILayout"; }
protected:
virtual void onLayoutRectChange(const Rect& newRect) { }
private:
/// Recalculate itself and anchored elements positions
void recalculateLayout();
/// Recalculate anchored elements positions
void recalculateAnchoredLayout();
void addAnchoredElement(UILayoutPtr anchoredElement);
AnchorLine m_anchors[6];
Rect m_rect;
int m_marginLeft;
int m_marginRight;
int m_marginTop;
int m_marginBottom;
std::list<UILayoutWeakPtr> m_anchoredElements;
}; };
#endif // UILAYOUT_H #endif // UILAYOUT_H

View File

@ -28,6 +28,7 @@
#include <ui/uiloader.h> #include <ui/uiloader.h>
#include <script/luascript.h> #include <script/luascript.h>
#include <script/luafunctions.h> #include <script/luafunctions.h>
#include "uianchorlayout.h"
UIElementPtr UILoader::createElementFromId(const std::string& id) UIElementPtr UILoader::createElementFromId(const std::string& id)
{ {
@ -206,22 +207,22 @@ void UILoader::loadElement(const UIElementPtr& element, const YAML::Node& node)
} }
if(node.FindValue("anchors.left")) if(node.FindValue("anchors.left"))
loadElementAnchor(element, ANCHOR_LEFT, node["anchors.left"]); loadElementAnchor(element, UI::AnchorLeft, node["anchors.left"]);
if(node.FindValue("anchors.right")) if(node.FindValue("anchors.right"))
loadElementAnchor(element, ANCHOR_RIGHT, node["anchors.right"]); loadElementAnchor(element, UI::AnchorRight, node["anchors.right"]);
if(node.FindValue("anchors.top")) if(node.FindValue("anchors.top"))
loadElementAnchor(element, ANCHOR_TOP, node["anchors.top"]); loadElementAnchor(element, UI::AnchorTop, node["anchors.top"]);
if(node.FindValue("anchors.bottom")) if(node.FindValue("anchors.bottom"))
loadElementAnchor(element, ANCHOR_BOTTOM, node["anchors.bottom"]); loadElementAnchor(element, UI::AnchorBottom, node["anchors.bottom"]);
if(node.FindValue("anchors.horizontalCenter")) if(node.FindValue("anchors.horizontalCenter"))
loadElementAnchor(element, ANCHOR_HORIZONTAL_CENTER, node["anchors.horizontalCenter"]); loadElementAnchor(element, UI::AnchorHorizontalCenter, node["anchors.horizontalCenter"]);
if(node.FindValue("anchors.verticalCenter")) if(node.FindValue("anchors.verticalCenter"))
loadElementAnchor(element, ANCHOR_VERTICAL_CENTER, node["anchors.verticalCenter"]); loadElementAnchor(element, UI::AnchorVerticalCenter, node["anchors.verticalCenter"]);
// load events // load events
if(node.FindValue("onLoad")) { if(node.FindValue("onLoad")) {
@ -261,8 +262,14 @@ void UILoader::loadElement(const UIElementPtr& element, const YAML::Node& node)
} }
} }
void UILoader::loadElementAnchor(const UIElementPtr& element, EAnchorType type, const YAML::Node& node) void UILoader::loadElementAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const YAML::Node& node)
{ {
UIAnchorLayoutPtr layout = boost::dynamic_pointer_cast<UIAnchorLayout>(anchoredElement->getLayout());
if(!layout) {
logError(YAML::Exception(node.GetMark(), "could not add anchor, because this element does not participate of an anchor layout").what());
return;
}
std::string anchorDescription; std::string anchorDescription;
node >> anchorDescription; node >> anchorDescription;
@ -273,44 +280,16 @@ void UILoader::loadElementAnchor(const UIElementPtr& element, EAnchorType type,
return; return;
} }
std::string relativeElementId = split[0]; std::string anchorLineElementId = split[0];
std::string relativeAnchorTypeId = split[1]; UI::AnchorPoint anchorLineEdge = UIAnchorLayout::parseAnchorPoint(split[1]);
EAnchorType relativeAnchorType;
if(relativeAnchorTypeId == "left") if(anchorLineEdge == UI::AnchorNone) {
relativeAnchorType = ANCHOR_LEFT;
else if(relativeAnchorTypeId == "right")
relativeAnchorType = ANCHOR_RIGHT;
else if(relativeAnchorTypeId == "top")
relativeAnchorType = ANCHOR_TOP;
else if(relativeAnchorTypeId == "bottom")
relativeAnchorType = ANCHOR_BOTTOM;
else if(relativeAnchorTypeId == "horizontalCenter")
relativeAnchorType = ANCHOR_HORIZONTAL_CENTER;
else if(relativeAnchorTypeId == "verticalCenter")
relativeAnchorType = ANCHOR_VERTICAL_CENTER;
else {
logError(YAML::Exception(node.GetMark(), "invalid anchor type").what()); logError(YAML::Exception(node.GetMark(), "invalid anchor type").what());
return; return;
} }
UILayoutPtr relativeElement; if(!layout->addAnchor(anchoredElement, anchoredEdge, AnchorLine(anchorLineElementId, anchorLineEdge)))
if(relativeElementId == "parent" && element->getParent()) {
relativeElement = element->getParent()->asUILayout();
} else if(relativeElementId == "root") {
relativeElement = UIContainer::getRoot();
} else {
UIElementPtr tmp = element->backwardsGetElementById(relativeElementId);
if(tmp)
relativeElement = tmp->asUILayout();
}
if(relativeElement) {
if(!element->addAnchor(type, AnchorLine(relativeElement, relativeAnchorType)))
logError(YAML::Exception(node.GetMark(), "anchoring failed").what()); logError(YAML::Exception(node.GetMark(), "anchoring failed").what());
} else {
logError(YAML::Exception(node.GetMark(), "anchoring failed, does the relative element really exists?").what());
}
} }
void UILoader::loadButton(const UIButtonPtr& button, const YAML::Node& node) void UILoader::loadButton(const UIButtonPtr& button, const YAML::Node& node)

View File

@ -50,7 +50,7 @@ private:
static void loadElement(const UIElementPtr& element, const YAML::Node& node); static void loadElement(const UIElementPtr& element, const YAML::Node& node);
/// Load anchor from a YAML node /// Load anchor from a YAML node
static void loadElementAnchor(const UIElementPtr& element, EAnchorType type, const YAML::Node& node); static void loadElementAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const YAML::Node& node);
// specific elements loading // specific elements loading
static void loadButton(const UIButtonPtr& button, const YAML::Node& node); static void loadButton(const UIButtonPtr& button, const YAML::Node& node);

View File

@ -136,7 +136,7 @@ void UISkins::terminate()
} }
UIElementSkinPtr UISkins::getElementSkin(UI::EElementType elementType, const std::string& name) UIElementSkinPtr UISkins::getElementSkin(UI::ElementType elementType, const std::string& name)
{ {
for(auto it = m_elementSkins.begin(); it != m_elementSkins.end(); ++it) { for(auto it = m_elementSkins.begin(); it != m_elementSkins.end(); ++it) {
const UIElementSkinPtr& skin = (*it); const UIElementSkinPtr& skin = (*it);

View File

@ -37,7 +37,7 @@ public:
void load(const std::string& skinsFile); void load(const std::string& skinsFile);
void terminate(); void terminate();
UIElementSkinPtr getElementSkin(UI::EElementType elementType, const std::string& name = "default"); UIElementSkinPtr getElementSkin(UI::ElementType elementType, const std::string& name = "default");
TexturePtr getDefaultTexture() { return m_defaultTexture; } TexturePtr getDefaultTexture() { return m_defaultTexture; }
private: private:

View File

@ -60,10 +60,10 @@ void UITextEdit::onInputEvent(const InputEvent& event)
} }
} }
void UITextEdit::onLayoutRectChange(const Rect& rect) void UITextEdit::onRectUpdate()
{ {
UITextEditSkin *skin = static_cast<UITextEditSkin*>(getSkin().get()); UITextEditSkin *skin = static_cast<UITextEditSkin*>(getSkin().get());
Rect textRect = rect; Rect textRect = getRect();
int margin = skin->getTextMargin(); int margin = skin->getTextMargin();
textRect.setLeft(textRect.left()+margin); textRect.setLeft(textRect.left()+margin);
textRect.setRight(textRect.right()-margin); textRect.setRight(textRect.right()-margin);

View File

@ -37,7 +37,7 @@ public:
UITextEdit(); UITextEdit();
void onInputEvent(const InputEvent& event); void onInputEvent(const InputEvent& event);
void onLayoutRectChange(const Rect& rect); void onRectUpdate();
void onFocusChange(); void onFocusChange();
void setText(const std::string& text); void setText(const std::string& text);

View File

@ -38,7 +38,7 @@ template <class T>
class TSize class TSize
{ {
public: public:
inline TSize() : wd(0), ht(0) {}; inline TSize() : wd(-1), ht(-1) {};
inline TSize(T width, T height) : wd(width), ht(height) { }; inline TSize(T width, T height) : wd(width), ht(height) { };
inline TSize(const TSize<T>& other) : wd(other.wd), ht(other.ht) { }; inline TSize(const TSize<T>& other) : wd(other.wd), ht(other.ht) { };