rework ui related scripting stuff

This commit is contained in:
Eduardo Bart
2011-07-17 03:56:57 -03:00
parent 571801ae39
commit bddcfb08fd
46 changed files with 740 additions and 507 deletions

View File

@@ -1,39 +1,12 @@
/* The MIT License
*
* Copyright (c) 2010 OTClient, https://github.com/edubart/otclient
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef UI_H
#define UI_H
#include <global.h>
#include <ui/uiconstants.h>
#include <ui/uiskins.h>
#include <ui/uiloader.h>
#include <ui/uielement.h>
#include <ui/uielementskin.h>
#include <ui/uicontainer.h>
#include <ui/uibutton.h>
#include <ui/uilabel.h>

View File

@@ -1,5 +1,6 @@
#include <global.h>
#include <ui/uianchorlayout.h>
#include <ui/uielement.h>
UIElementPtr Anchor::getAnchorLineElement() const
{
@@ -13,17 +14,17 @@ int Anchor::getAnchorLinePoint() const
UIElementPtr anchorLineElement = getAnchorLineElement();
if(anchorLineElement) {
switch(m_anchorLine.getEdge()) {
case UI::AnchorLeft:
case AnchorLeft:
return anchorLineElement->getRect().left();
case UI::AnchorRight:
case AnchorRight:
return anchorLineElement->getRect().right();
case UI::AnchorTop:
case AnchorTop:
return anchorLineElement->getRect().top();
case UI::AnchorBottom:
case AnchorBottom:
return anchorLineElement->getRect().bottom();
case UI::AnchorHorizontalCenter:
case AnchorHorizontalCenter:
return anchorLineElement->getRect().horizontalCenter();
case UI::AnchorVerticalCenter:
case AnchorVerticalCenter:
return anchorLineElement->getRect().verticalCenter();
default:
break;
@@ -31,7 +32,7 @@ int Anchor::getAnchorLinePoint() const
}
return -9999;
}
bool UIAnchorLayout::addAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const AnchorLine& anchorLine)
bool UIAnchorLayout::addAnchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, const AnchorLine& anchorLine)
{
Anchor anchor(anchoredElement, anchoredEdge, anchorLine);
UIElementPtr anchorLineElement = anchor.getAnchorLineElement();
@@ -71,36 +72,36 @@ void UIAnchorLayout::recalculateElementLayout(const UIElementPtr& element)
if(anchor.getAnchoredElement() == element && anchor.getAnchorLineElement()) {
int point = anchor.getAnchorLinePoint();
switch(anchor.getAnchoredEdge()) {
case UI::AnchorHorizontalCenter:
case AnchorHorizontalCenter:
rect.moveHorizontalCenter(point + element->getMarginLeft() - element->getMarginRight());
horizontalMoved = true;
break;
case UI::AnchorLeft:
case AnchorLeft:
if(!horizontalMoved) {
rect.moveLeft(point + element->getMarginLeft());
horizontalMoved = true;
} else
rect.setLeft(point + element->getMarginLeft());
break;
case UI::AnchorRight:
case AnchorRight:
if(!horizontalMoved) {
rect.moveRight(point - element->getMarginRight());
horizontalMoved = true;
} else
rect.setRight(point - element->getMarginRight());
break;
case UI::AnchorVerticalCenter:
case AnchorVerticalCenter:
rect.moveVerticalCenter(point + element->getMarginTop() - element->getMarginBottom());
verticalMoved = true;
break;
case UI::AnchorTop:
case AnchorTop:
if(!verticalMoved) {
rect.moveTop(point + element->getMarginTop());
verticalMoved = true;
} else
rect.setTop(point + element->getMarginTop());
break;
case UI::AnchorBottom:
case AnchorBottom:
if(!verticalMoved) {
rect.moveBottom(point - element->getMarginBottom());
verticalMoved = true;
@@ -139,19 +140,19 @@ bool UIAnchorLayout::hasElementInAnchorTree(const UIElementPtr& element, const U
return false;
}
UI::AnchorPoint UIAnchorLayout::parseAnchorPoint(const std::string& anchorPointStr)
AnchorPoint UIAnchorLayout::parseAnchorPoint(const std::string& anchorPointStr)
{
if(anchorPointStr == "left")
return UI::AnchorLeft;
return AnchorLeft;
else if(anchorPointStr == "right")
return UI::AnchorRight;
return AnchorRight;
else if(anchorPointStr == "top")
return UI::AnchorTop;
return AnchorTop;
else if(anchorPointStr == "bottom")
return UI::AnchorBottom;
return AnchorBottom;
else if(anchorPointStr == "horizontalCenter")
return UI::AnchorHorizontalCenter;
return AnchorHorizontalCenter;
else if(anchorPointStr == "verticalCenter")
return UI::AnchorVerticalCenter;
return UI::AnchorNone;
return AnchorVerticalCenter;
return AnchorNone;
}

View File

@@ -2,48 +2,60 @@
#define UIANCHORLAYOUT_H
#include <global.h>
#include <ui/uiconstants.h>
#include <ui/uilayout.h>
#include <ui/uielement.h>
class UIElement;
typedef boost::shared_ptr<UIElement> UIElementPtr;
typedef boost::weak_ptr<UIElement> UIElementWeakPtr;
enum AnchorPoint {
AnchorNone = 0,
AnchorTop,
AnchorBottom,
AnchorLeft,
AnchorRight,
AnchorVerticalCenter,
AnchorHorizontalCenter,
};
class AnchorLine
{
public:
AnchorLine(const std::string& elementId, UI::AnchorPoint edge) : m_elementId(elementId), m_edge(edge) { }
AnchorLine(const std::string& elementId, AnchorPoint edge) : m_elementId(elementId), m_edge(edge) { }
AnchorLine(const AnchorLine& other) : m_elementId(other.m_elementId), m_edge(other.m_edge) { }
UI::AnchorPoint getEdge() const { return m_edge; }
AnchorPoint getEdge() const { return m_edge; }
const std::string& getElementId() const { return m_elementId; }
private:
std::string m_elementId;
UI::AnchorPoint m_edge;
AnchorPoint m_edge;
};
class Anchor
{
public:
Anchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const AnchorLine& anchorLine)
Anchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, const AnchorLine& anchorLine)
: m_anchoredElement(anchoredElement), m_anchoredEdge(anchoredEdge), m_anchorLine(anchorLine) { }
UIElementPtr getAnchorLineElement() const ;
UIElementPtr getAnchoredElement() const { return m_anchoredElement.lock(); }
UI::AnchorPoint getAnchoredEdge() const { return m_anchoredEdge; }
AnchorPoint getAnchoredEdge() const { return m_anchoredEdge; }
int getAnchorLinePoint() const;
private:
UIElementWeakPtr m_anchoredElement;
UI::AnchorPoint m_anchoredEdge;
AnchorPoint m_anchoredEdge;
AnchorLine m_anchorLine;
};
class UIAnchorLayout : public UILayout
{
public:
bool addAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, const AnchorLine& anchorLine);
bool addAnchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, const AnchorLine& anchorLine);
void recalculateElementLayout(const UIElementPtr& element);
void recalculateChildrenLayout(const UIElementPtr& parent);
bool hasElementInAnchorTree(const UIElementPtr& element, const UIElementPtr& treeAnchor);
static UI::AnchorPoint parseAnchorPoint(const std::string& anchorPointStr);
static AnchorPoint parseAnchorPoint(const std::string& anchorPointStr);
private:
std::vector<Anchor> m_anchors;

View File

@@ -2,7 +2,6 @@
#define UIBUTTONSKIN_H
#include <global.h>
#include <ui/uiconstants.h>
#include <ui/uielementskin.h>
class Font;

View File

@@ -1,28 +0,0 @@
#ifndef UICONSTANTS_H
#define UICONSTANTS_H
namespace UI {
enum ElementType {
Element = 0,
Container,
Panel,
Window,
Label,
TextEdit,
Button,
CheckBox,
LineDecoration
};
enum AnchorPoint {
AnchorNone = 0,
AnchorTop,
AnchorBottom,
AnchorLeft,
AnchorRight,
AnchorVerticalCenter,
AnchorHorizontalCenter,
};
}
#endif // UICONSTANTS_H

View File

@@ -34,7 +34,7 @@ public:
const std::list<UIElementPtr>& getChildren() const { return m_children; }
/// Pushs a child to the top
void pushChildToTop(const UIElementPtr& child);
/// Return number of children
int getChildCount() const { return m_children.size(); }
/// Disable all children except the specified element

View File

@@ -5,6 +5,7 @@
#include <ui/uiskins.h>
#include <ui/uielementskin.h>
#include <ui/uicontainer.h>
#include <ui/uianchorlayout.h>
UIElement::UIElement(UI::ElementType type) :
ScriptObject(),
@@ -17,7 +18,9 @@ UIElement::UIElement(UI::ElementType type) :
m_marginTop(0),
m_marginBottom(0)
{
// generate an unique id, this is need because anchoed layouts find elements by id
static unsigned long id = 1;
m_id = make_string("element", id++);
}
UIElement::~UIElement()
@@ -62,12 +65,11 @@ void UIElement::destroyCheck()
void UIElement::setSize(const Size& size)
{
Rect rect = getRect();
if(rect.isValid())
rect.setSize(size);
else
rect = Rect(0, 0, size);
rect.setSize(size);
setRect(rect);
getLayout()->recalculateElementLayout(asUIElement());
if(UILayoutPtr layout = getLayout())
layout->recalculateElementLayout(asUIElement());
}
void UIElement::setRect(const Rect& rect)
@@ -76,12 +78,18 @@ void UIElement::setRect(const Rect& rect)
m_rect = rect;
// rect updated, recalculate children layout
getLayout()->recalculateChildrenLayout(asUIElement());
if(UILayoutPtr layout = getLayout())
layout->recalculateChildrenLayout(asUIElement());
onRectUpdate();
}
}
void UIElement::applyDefaultSkin()
{
setSkin(g_uiSkins.getElementSkin(getElementType(), "default"));
}
void UIElement::setSkin(const UIElementSkinPtr& skin)
{
m_skin = skin;
@@ -186,3 +194,20 @@ UILayoutPtr UIElement::getLayout() const
return getParent()->getLayout();
return UILayoutPtr();
}
void UIElement::centerIn(const std::string& targetId)
{
addAnchor(AnchorHorizontalCenter, AnchorLine(targetId, AnchorHorizontalCenter));
addAnchor(AnchorVerticalCenter, AnchorLine(targetId, AnchorVerticalCenter));
}
void UIElement::addAnchor(AnchorPoint anchoredEdge, AnchorLine anchorEdge)
{
UIElementPtr target = backwardsGetElementById(anchorEdge.getElementId());
if(!target)
warning("warning: element id '", anchorEdge.getElementId(), "' doesn't exist while anchoring element '", getId(), "'");
UIAnchorLayoutPtr layout = boost::dynamic_pointer_cast<UIAnchorLayout>(getLayout());
if(layout)
layout->addAnchor(asUIElement(), anchoredEdge, anchorEdge);
}

View File

@@ -4,11 +4,24 @@
#include <global.h>
#include <core/input.h>
#include <script/scriptobject.h>
#include <ui/uiconstants.h>
#include <ui/uielementskin.h>
#include <ui/uilayout.h>
#include <ui/uianchorlayout.h>
namespace UI {
enum ElementType {
Element = 0,
Container,
Panel,
Window,
Label,
TextEdit,
Button,
CheckBox,
LineDecoration
};
}
class UIElementSkin;
typedef boost::shared_ptr<UIElementSkin> UIElementSkinPtr;
class UIContainer;
typedef boost::shared_ptr<UIContainer> UIContainerPtr;
@@ -44,6 +57,7 @@ public:
void setLayout(const UILayoutPtr& layout) { m_layout = layout; }
UILayoutPtr getLayout() const;
void applyDefaultSkin();
void setSkin(const UIElementSkinPtr& skin);
UIElementSkinPtr getSkin() const { return m_skin; }
@@ -73,7 +87,14 @@ public:
virtual const char *getScriptObjectType() const { return "UIElement"; }
void setSize(const Size& size);
Size getSize() { return m_rect.size(); }
void setSize(int width, int height) { setSize(Size(width, height)); }
Size getSize() const { return m_rect.size(); }
void setWidth(int width) { setSize(width, getSize().height()); }
int getWidth() const { return getSize().width(); }
void setHeight(int height) { setSize(getSize().width(), height); }
int getHeight() const { return getSize().height(); }
/// Set the layout rect, always absolute position
void setRect(const Rect& rect);
@@ -81,8 +102,8 @@ public:
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 top, int right, int bottom, int left) { m_marginLeft = left; m_marginRight = right; m_marginTop = top; m_marginBottom = bottom; getLayout()->recalculateElementLayout(asUIElement()); }
void setMargin(int vertical, int horizontal) { 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()); }
@@ -94,6 +115,10 @@ public:
int getMarginTop() const { return m_marginTop; }
int getMarginBottom() const { return m_marginBottom; }
// layout related
void centerIn(const std::string& targetId);
void addAnchor(AnchorPoint anchoredEdge, AnchorLine anchorEdge);
private:
UI::ElementType m_type;
UIContainerWeakPtr m_parent;

View File

@@ -3,12 +3,10 @@
#include <global.h>
#include <graphics/image.h>
#include <ui/uiconstants.h>
#include <ui/uielement.h>
#include <graphics/font.h>
#include <otml/otmlnode.h>
class UIElement;
class UIElementSkin
{
public:

View File

@@ -1,9 +1,11 @@
#include <global.h>
#include <ui/uilabel.h>
#include <ui/uielementskin.h>
void UILabel::setText(const std::string& text)
{
m_text = text;
// text size changed, reaplly skin
getSkin()->apply(this);
if(getSkin())
getSkin()->apply(this);
}

View File

@@ -13,7 +13,7 @@ public:
m_align(AlignLeftCenter) { }
void setText(const std::string& text);
std::string getText() const { return m_text; }
std::string getText() const { return m_text; }
void setAlign(AlignmentFlag align) { m_align = align; }
AlignmentFlag getAlign() const { return m_align; }

View File

@@ -48,11 +48,11 @@ UIElementPtr UILoader::createElementFromId(const std::string& id)
UIElementPtr UILoader::loadFromFile(std::string filePath, const UIContainerPtr& parent)
{
UIElementPtr element;
std::stringstream fin;
if(!g_resources.loadFile(filePath, fin)) {
error("ERROR: Could not load ui ", filePath);
return UIElementPtr();
}
if(!g_resources.loadFile(filePath, fin))
return element;
try {
OTMLParser parser(fin, filePath);
@@ -65,7 +65,7 @@ UIElementPtr UILoader::loadFromFile(std::string filePath, const UIContainerPtr&
// only after that we can load anchors
// create element interpreting it's id
UIElementPtr element = createElementFromId(elementId);
element = createElementFromId(elementId);
if(!element) {
error(doc->front()->generateErrorMessage("invalid root element type"));
return element;
@@ -81,12 +81,11 @@ UIElementPtr UILoader::loadFromFile(std::string filePath, const UIContainerPtr&
// report onLoad events
element->onLoad();
return element;
} catch(OTMLException e) {
error("ERROR: Failed to load ui ",filePath,": ", e.what());
}
return UIElementPtr();
return element;
}
void UILoader::populateContainer(const UIContainerPtr& parent, OTMLNode* node)
@@ -138,7 +137,7 @@ void UILoader::loadElement(const UIElementPtr& element, OTMLNode* node)
element->setSkin(skin);
}
} else // apply default skin
element->setSkin(g_uiSkins.getElementSkin(element->getElementType(), "default"));
element->applyDefaultSkin();
// load elements common proprieties
if(node->hasChild("size"))
@@ -151,12 +150,12 @@ void UILoader::loadElement(const UIElementPtr& element, OTMLNode* node)
element->setMarginBottom(node->readAtPath("margin/bottom", 0));
// load anchors
loadElementAnchor(element, UI::AnchorLeft, node->atPath("anchors/left"));
loadElementAnchor(element, UI::AnchorRight, node->atPath("anchors/right"));
loadElementAnchor(element, UI::AnchorTop, node->atPath("anchors/top"));
loadElementAnchor(element, UI::AnchorBottom, node->atPath("anchors/bottom"));
loadElementAnchor(element, UI::AnchorHorizontalCenter, node->atPath("anchors/horizontalCenter"));
loadElementAnchor(element, UI::AnchorVerticalCenter, node->atPath("anchors/verticalCenter"));
loadElementAnchor(element, AnchorLeft, node->atPath("anchors/left"));
loadElementAnchor(element, AnchorRight, node->atPath("anchors/right"));
loadElementAnchor(element, AnchorTop, node->atPath("anchors/top"));
loadElementAnchor(element, AnchorBottom, node->atPath("anchors/bottom"));
loadElementAnchor(element, AnchorHorizontalCenter, node->atPath("anchors/horizontalCenter"));
loadElementAnchor(element, AnchorVerticalCenter, node->atPath("anchors/verticalCenter"));
// load basic element events
loadElementScriptFunction(element, node->at("onLoad"));
@@ -178,7 +177,7 @@ void UILoader::loadElement(const UIElementPtr& element, OTMLNode* node)
}
}
void UILoader::loadElementAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, OTMLNode* node)
void UILoader::loadElementAnchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, OTMLNode* node)
{
if(!node)
return;
@@ -203,9 +202,9 @@ void UILoader::loadElementAnchor(const UIElementPtr& anchoredElement, UI::Anchor
}
std::string anchorLineElementId = split[0];
UI::AnchorPoint anchorLineEdge = UIAnchorLayout::parseAnchorPoint(split[1]);
AnchorPoint anchorLineEdge = UIAnchorLayout::parseAnchorPoint(split[1]);
if(anchorLineEdge == UI::AnchorNone) {
if(anchorLineEdge == AnchorNone) {
error(node->generateErrorMessage("invalid anchor type"));
return;
}

View File

@@ -26,11 +26,11 @@
#define UILOADER_H
#include <global.h>
#include <ui/uiconstants.h>
#include <ui/uicontainer.h>
#include <ui/uibutton.h>
#include <ui/uiwindow.h>
#include <ui/uilabel.h>
#include <ui/uianchorlayout.h>
class UILoader
{
@@ -52,7 +52,7 @@ private:
void loadElement(const UIElementPtr& element, OTMLNode* node);
/// Load anchor from a OTML node
void loadElementAnchor(const UIElementPtr& anchoredElement, UI::AnchorPoint anchoredEdge, OTMLNode* node);
void loadElementAnchor(const UIElementPtr& anchoredElement, AnchorPoint anchoredEdge, OTMLNode* node);
/// Load element lua function
void loadElementScriptFunction(const UIElementPtr& element, OTMLNode* node);