rework ui layouts, now it is more flexible and modular
This commit is contained in:
parent
6d871b305f
commit
51fe97644d
|
@ -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
|
||||||
|
|
|
@ -4,8 +4,7 @@ function onEnterMenuState()
|
||||||
end
|
end
|
||||||
|
|
||||||
function onLeaveMenuState()
|
function onLeaveMenuState()
|
||||||
mainMenu:destroy()
|
|
||||||
mainMenu = nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function onApplicationClose()
|
function onApplicationClose()
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
#endif // UILAYOUT_H
|
||||||
{
|
|
||||||
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
|
|
|
@ -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()) {
|
logError(YAML::Exception(node.GetMark(), "anchoring failed").what());
|
||||||
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());
|
|
||||||
} 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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) { };
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue