refactoring

master
Eduardo Bart 13 years ago
parent 10ea2e5de1
commit 6a3ee47cc5

@ -34,6 +34,7 @@
// boost utilities // boost utilities
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/any.hpp>
// global constants // global constants
#include "const.h" #include "const.h"

@ -28,7 +28,7 @@ void LuaInterface::registerFunctions()
g_lua.bindClassMemberFunction<UIWidget>("setForegroundColor", &UIWidget::setForegroundColor); g_lua.bindClassMemberFunction<UIWidget>("setForegroundColor", &UIWidget::setForegroundColor);
g_lua.bindClassMemberFunction<UIWidget>("getOpacity", &UIWidget::getOpacity); g_lua.bindClassMemberFunction<UIWidget>("getOpacity", &UIWidget::getOpacity);
g_lua.bindClassMemberFunction<UIWidget>("setOpacity", &UIWidget::setOpacity); g_lua.bindClassMemberFunction<UIWidget>("setOpacity", &UIWidget::setOpacity);
g_lua.bindClassMemberFunction<UIWidget>("setStyle", &UIWidget::setStyle); g_lua.bindClassMemberFunction<UIWidget>("setStyle", &UIWidget::applyStyle);
g_lua.bindClassMemberFunction<UIWidget>("getMarginTop", &UIWidget::getMarginTop); g_lua.bindClassMemberFunction<UIWidget>("getMarginTop", &UIWidget::getMarginTop);
g_lua.bindClassMemberFunction<UIWidget>("setMarginTop", &UIWidget::setMarginTop); g_lua.bindClassMemberFunction<UIWidget>("setMarginTop", &UIWidget::setMarginTop);
g_lua.bindClassMemberFunction<UIWidget>("getMarginBottom", &UIWidget::getMarginBottom); g_lua.bindClassMemberFunction<UIWidget>("getMarginBottom", &UIWidget::getMarginBottom);

@ -374,9 +374,9 @@ bool UILineEdit::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
} else if(keyCode == KC_RETURN) { } else if(keyCode == KC_RETURN) {
if(m_onAction) if(m_onAction)
m_onAction(); m_onAction();
} else if(keyCode != 0) { } else if(keyChar != 0)
appendCharacter(keyChar); appendCharacter(keyChar);
} else else
return false; return false;
return true; return true;

@ -5,12 +5,12 @@ UIList::UIList()
} }
void UIList::onStyleApply(const OTMLNodePtr& styleNode) void UIList::render()
{ {
} }
void UIList::render() void UIList::onStyleApply(const OTMLNodePtr& styleNode)
{ {
} }

@ -1,23 +1,68 @@
#ifndef UILIST_H #ifndef UITEXTLIST_H
#define UILIST_H #define UITEXTLIST_H
#include "uiwidget.h" #include "uiwidget.h"
class UIListItem;
typedef std::shared_ptr<UIListItem> UIListItemPtr;
typedef std::list<UIListItemPtr> UIListItemList;
class UIListItem
{
public:
void setText(const std::string& text) { m_text = text; }
void setData(const boost::any& data) { m_data = data; }
boost::any getData() { return m_data; }
std::string getText() { return m_text; }
private:
std::string m_text;
boost::any m_data;
};
class UIList : public UIWidget class UIList : public UIWidget
{ {
public: public:
UIList(); UIList();
virtual void onStyleApply(const OTMLNodePtr& styleNode);
virtual void render(); virtual void render();
void insertItem(int row, const UIListItemPtr& item);
//void insertItems(int row, const UIListItemList& items);
int addItem(const UIListItemPtr& item);
//int addItems(const UIListItemList& items);
void removeItem(const UIListItemPtr& item);
void removeRow(int row);
UIListItemPtr takeRow(int row);
void setCurrentItem(const UIListItemPtr& item);
void setCurrentRow(int row);
UIListItemPtr getItem(int row);
UIListItemPtr getItemAt(const Point& point);
UIListItemList getItems();
int getItemRow(const UIListItemPtr& item);
int getItemsCount();
UIListItemPtr getCurrentItem();
int getCurrentRow();
protected: protected:
virtual void onStyleApply(const OTMLNodePtr& styleNode);
virtual bool onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers); virtual bool onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers);
virtual bool onMousePress(const Point& mousePos, UI::MouseButton button); virtual bool onMousePress(const Point& mousePos, UI::MouseButton button);
virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved); virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved);
private: // possible signals
std::list<std::string> m_items; //onItemActivated
//onItemChanged
//onCurrentItemChange
//onCurrenteRowChange
//onCurrentTextChange
//onItemClicked
std::list<UIListItem> m_items;
}; };
#endif #endif

@ -164,19 +164,13 @@ UIWidgetPtr UIManager::loadWidgetFromOTML(const OTMLNodePtr& widgetNode)
std::string widgetType = styleNode->valueAt("__widgetType"); std::string widgetType = styleNode->valueAt("__widgetType");
UIWidgetPtr widget; // call widget creation from lua
if(widgetType == "UIWidget") //g_lua.getGlobalField(widgetType, "create");
widget = UIWidgetPtr(new UIWidget); g_lua.getGlobal(widgetType);
else if(widgetType == "UILabel") g_lua.getField("create");
widget = UIWidgetPtr(new UILabel); g_lua.remove(-2);
else if(widgetType == "UIButton") g_lua.protectedCall(0, 1);
widget = UIWidgetPtr(new UIButton); UIWidgetPtr widget = g_lua.polymorphicPop<UIWidgetPtr>();
else if(widgetType == "UILineEdit")
widget = UIWidgetPtr(new UILineEdit);
else if(widgetType == "UIWindow")
widget = UIWidgetPtr(new UIWindow);
else
throw OTMLException(styleNode, "cannot determine widget type");
widget->onStyleApply(styleNode); widget->onStyleApply(styleNode);
widget->updateLayout(); widget->updateLayout();

@ -38,14 +38,16 @@ UIWidget::~UIWidget()
void UIWidget::destroy() void UIWidget::destroy()
{ {
//TODO: onDestroy event
// destroy only once // destroy only once
if(!m_destroyed) { if(!m_destroyed) {
// first release lua table, because it may contains references to children
releaseLuaFieldsTable(); releaseLuaFieldsTable();
// clear additional reference // clear additional child references
m_lockedWidgets.clear(); m_lockedChildren.clear();
m_focusedChild.reset(); m_focusedChild.reset();
m_anchors.clear();
m_anchoredWidgets.clear();
// destroy children // destroy children
while(m_children.size() > 0) { while(m_children.size() > 0) {
@ -57,11 +59,11 @@ void UIWidget::destroy()
if(UIWidgetPtr parent = getParent()) if(UIWidgetPtr parent = getParent())
parent->removeChild(asUIWidget()); parent->removeChild(asUIWidget());
// by now this widget is destroyed
m_destroyed = true;
// add destroy check event // add destroy check event
g_dispatcher.addEvent(std::bind(&UIWidget::destroyCheck, asUIWidget())); g_dispatcher.addEvent(std::bind(&UIWidget::destroyCheck, asUIWidget()));
m_destroyed = true;
m_enabled = false;
m_visible = false;
} else } else
logWarning("attempt to destroy widget '", m_id, "' again"); logWarning("attempt to destroy widget '", m_id, "' again");
} }
@ -79,121 +81,26 @@ void UIWidget::destroyCheck()
logWarning("destroyed widget with id '",m_id,"', but it still have ",realUseCount," references left"); logWarning("destroyed widget with id '",m_id,"', but it still have ",realUseCount," references left");
} }
void UIWidget::onStyleApply(const OTMLNodePtr& styleNode)
{
assert(!m_destroyed);
// load styles used by all widgets
for(const OTMLNodePtr& node : styleNode->children()) {
// id
if(node->tag() == "id") {
setId(node->value());
}
// image
else if(node->tag() == "image") {
setImage(Image::loadFromOTML(node));
}
else if(node->tag() == "border-image") {
setImage(BorderImage::loadFromOTML(node));
}
// font
else if(node->tag() == "font") {
setFont(g_fonts.getFont(node->value()));
}
// font color
else if(node->tag() == "color") {
setForegroundColor(node->value<Color>());
}
// color
else if(node->tag() == "background-color") {
setBackgroundColor(node->value<Color>());
}
// opacity
else if(node->tag() == "opacity") {
setOpacity(node->value<int>());
}
// size
else if(node->tag() == "size") {
resize(node->value<Size>());
}
else if(node->tag() == "width") {
setWidth(node->value<int>());
}
else if(node->tag() == "height") {
setHeight(node->value<int>());
}
// position
else if(node->tag() == "position") {
move(node->value<Point>());
}
else if(node->tag() == "x") {
setX(node->value<int>());
}
else if(node->tag() == "y") {
setY(node->value<int>());
}
// margins
else if(node->tag() == "margin.left") {
setMarginLeft(node->value<int>());
}
else if(node->tag() == "margin.right") {
setMarginRight(node->value<int>());
}
else if(node->tag() == "margin.top") {
setMarginTop(node->value<int>());
}
else if(node->tag() == "margin.bottom") {
setMarginBottom(node->value<int>());
}
// anchors
else if(boost::starts_with(node->tag(), "anchors.")) {
std::string what = node->tag().substr(8);
if(what == "fill") {
fill(node->value());
} else if(what == "centerIn") {
centerIn(node->value());
} else {
AnchorEdge myEdge = fw::translateAnchorEdge(what);
std::string anchorDescription = node->value();
std::vector<std::string> split;
boost::split(split, anchorDescription, boost::is_any_of(std::string(".")));
if(split.size() != 2)
throw OTMLException(node, "invalid anchor description");
std::string target = split[0];
AnchorEdge hookedEdge = fw::translateAnchorEdge(split[1]);
if(myEdge == AnchorNone)
throw OTMLException(node, "invalid anchor edge");
if(hookedEdge == AnchorNone)
throw OTMLException(node, "invalid anchor target edge");
addAnchor(myEdge, target, hookedEdge);
}
}
else if(node->tag() == "onLoad") {
g_lua.loadFunction(node->value<std::string>(), "@" + node->source() + "[" + node->tag() + "]");
luaSetField("onLoad");
}
}
}
void UIWidget::render() void UIWidget::render()
{ {
assert(!m_destroyed); assert(!m_destroyed);
// draw background image
g_graphics.bindColor(m_backgroundColor);
if(m_image) if(m_image)
m_image->draw(getRect()); m_image->draw(getRect());
// draw children
for(const UIWidgetPtr& child : m_children) { for(const UIWidgetPtr& child : m_children) {
if(child->isExplicitlyVisible()) { if(child->isExplicitlyVisible()) {
// store current graphics opacity
int oldOpacity = g_graphics.getOpacity(); int oldOpacity = g_graphics.getOpacity();
// decrease to self opacity
if(child->getOpacity() < oldOpacity) if(child->getOpacity() < oldOpacity)
g_graphics.setOpacity(child->getOpacity()); g_graphics.setOpacity(child->getOpacity());
g_graphics.bindColor(child->getBackgroundColor()); // bind child color
child->render(); child->render();
// debug draw box // debug draw box
@ -209,23 +116,27 @@ void UIWidget::setParent(const UIWidgetPtr& parent)
{ {
assert(!m_destroyed); assert(!m_destroyed);
UIWidgetPtr me = asUIWidget(); UIWidgetPtr self = asUIWidget();
// remove from old parent // remove from old parent
UIWidgetPtr oldParent = m_parent.lock(); UIWidgetPtr oldParent = m_parent.lock();
if(oldParent && oldParent->hasChild(me)) { if(oldParent && oldParent->hasChild(self))
oldParent->removeChild(me); oldParent->removeChild(self);
}
// reset parent
m_parent.reset(); m_parent.reset();
// set new parent
if(parent) { if(parent) {
m_parent = UIWidgetWeakPtr(parent); m_parent = UIWidgetWeakPtr(parent);
if(!parent->hasChild(me))
parent->addChild(me); // add to parent if needed
if(!parent->hasChild(self))
parent->addChild(self);
} }
} }
void UIWidget::setStyle(const std::string& styleName) void UIWidget::applyStyle(const std::string& styleName)
{ {
try { try {
OTMLNodePtr styleNode = g_ui.getStyle(styleName); OTMLNodePtr styleNode = g_ui.getStyle(styleName);
@ -271,6 +182,16 @@ bool UIWidget::isEnabled()
return false; return false;
} }
bool UIWidget::isVisible()
{
if(!m_visible)
return false;
else if(UIWidgetPtr parent = getParent())
return parent->isVisible();
else
return false;
}
bool UIWidget::hasFocus() bool UIWidget::hasFocus()
{ {
assert(!m_destroyed); assert(!m_destroyed);
@ -307,14 +228,9 @@ UIWidgetPtr UIWidget::getChildAfter(const UIWidgetPtr& relativeChild)
{ {
assert(!m_destroyed); assert(!m_destroyed);
for(auto it = m_children.begin(); it != m_children.end(); ++it) { auto it = std::find(m_children.begin(), m_children.end(), relativeChild);
const UIWidgetPtr& child = (*it); if(it != m_children.end() && ++it != m_children.end())
if(child == relativeChild) { return *it;
if(++it != m_children.end())
return (*it);
break;
}
}
return nullptr; return nullptr;
} }
@ -322,14 +238,9 @@ UIWidgetPtr UIWidget::getChildBefore(const UIWidgetPtr& relativeChild)
{ {
assert(!m_destroyed); assert(!m_destroyed);
for(auto it = m_children.rbegin(); it != m_children.rend(); ++it) { auto it = std::find(m_children.rbegin(), m_children.rend(), relativeChild);
const UIWidgetPtr& child = (*it); if(it != m_children.rend() && ++it != m_children.rend())
if(child == relativeChild) { return *it;
if(++it != m_children.rend())
return (*it);
break;
}
}
return nullptr; return nullptr;
} }
@ -406,7 +317,6 @@ UIWidgetPtr UIWidget::recursiveGetChildByPos(const Point& childPos)
return child; return child;
} }
} }
return nullptr; return nullptr;
} }
@ -419,35 +329,41 @@ UIWidgetPtr UIWidget::backwardsGetWidgetById(const std::string& id)
if(UIWidgetPtr parent = getParent()) if(UIWidgetPtr parent = getParent())
widget = parent->backwardsGetWidgetById(id); widget = parent->backwardsGetWidgetById(id);
} }
return widget; return widget;
} }
void UIWidget::focusChild(const UIWidgetPtr& focusedChild, UI::FocusReason reason) void UIWidget::focusChild(const UIWidgetPtr& child, UI::FocusReason reason)
{ {
assert(!m_destroyed); assert(!m_destroyed);
if(focusedChild != m_focusedChild) { if(!child)
return;
assert(hasChild(child));
if(child != m_focusedChild) {
UIWidgetPtr oldFocused = m_focusedChild; UIWidgetPtr oldFocused = m_focusedChild;
m_focusedChild = focusedChild; m_focusedChild = child;
if(oldFocused) if(oldFocused)
oldFocused->onFocusChange(false, reason); oldFocused->onFocusChange(false, reason);
if(focusedChild)
focusedChild->onFocusChange(focusedChild->hasFocus(), reason); if(child)
child->onFocusChange(child->hasFocus(), reason);
} }
} }
void UIWidget::addChild(const UIWidgetPtr& childToAdd) void UIWidget::addChild(const UIWidgetPtr& child)
{ {
assert(!m_destroyed); assert(!m_destroyed);
if(!childToAdd) if(!child)
return; return;
assert(!hasChild(childToAdd)); assert(!hasChild(child));
m_children.push_back(childToAdd);
childToAdd->setParent(asUIWidget()); m_children.push_back(child);
child->setParent(asUIWidget());
// recalculate anchors // recalculate anchors
getRootParent()->recalculateAnchoredWidgets(); getRootParent()->recalculateAnchoredWidgets();
@ -456,27 +372,29 @@ void UIWidget::addChild(const UIWidgetPtr& childToAdd)
updateChildrenLayout(); updateChildrenLayout();
// always focus new children // always focus new children
if(childToAdd->isFocusable() && childToAdd->isExplicitlyVisible() && childToAdd->isExplicitlyEnabled()) if(child->isFocusable() && child->isExplicitlyVisible() && child->isExplicitlyEnabled())
focusChild(childToAdd, UI::ActiveFocusReason); focusChild(child, UI::ActiveFocusReason);
} }
void UIWidget::insertChild(const UIWidgetPtr& childToInsert, int index) void UIWidget::insertChild(const UIWidgetPtr& child, int index)
{ {
assert(!m_destroyed); assert(!m_destroyed);
if(!childToInsert) // skip null children
if(!child)
return; return;
assert(!hasChild(childToInsert)); assert(!hasChild(child));
if(index < 0) if(index < 0)
index = m_children.size() + index -1; index = m_children.size() + index -1;
assert((uint)index <= m_children.size()); assert((uint)index <= m_children.size());
// retrieve child by index
auto it = m_children.begin() + index; auto it = m_children.begin() + index;
m_children.insert(it, childToInsert); m_children.insert(it, child);
childToInsert->setParent(asUIWidget()); child->setParent(asUIWidget());
// recalculate anchors // recalculate anchors
getRootParent()->recalculateAnchoredWidgets(); getRootParent()->recalculateAnchoredWidgets();
@ -485,28 +403,29 @@ void UIWidget::insertChild(const UIWidgetPtr& childToInsert, int index)
updateChildrenLayout(); updateChildrenLayout();
} }
void UIWidget::removeChild(const UIWidgetPtr& childToRemove) void UIWidget::removeChild(const UIWidgetPtr& child)
{ {
assert(!m_destroyed); assert(!m_destroyed);
if(!childToRemove) // skip null children
if(!child)
return; return;
// defocus if needed // defocus if needed
if(m_focusedChild == childToRemove) if(m_focusedChild == child)
focusChild(nullptr, UI::ActiveFocusReason); focusChild(nullptr, UI::ActiveFocusReason);
// try to unlock // unlock child if it was locked
unlockChild(childToRemove); unlockChild(child);
// remove from children list // remove from children list
auto it = std::find(m_children.begin(), m_children.end(), childToRemove); auto it = std::find(m_children.begin(), m_children.end(), child);
assert(it != m_children.end()); assert(it != m_children.end());
m_children.erase(it); m_children.erase(it);
// reset child parent // reset child parent
assert(childToRemove->getParent() == asUIWidget()); assert(child->getParent() == asUIWidget());
childToRemove->setParent(nullptr); child->setParent(nullptr);
// recalculate anchors // recalculate anchors
getRootParent()->recalculateAnchoredWidgets(); getRootParent()->recalculateAnchoredWidgets();
@ -521,73 +440,96 @@ void UIWidget::focusNextChild(UI::FocusReason reason)
UIWidgetPtr toFocus; UIWidgetPtr toFocus;
UIWidgetList rotatedChildren(m_children); UIWidgetList rotatedChildren(m_children);
auto focusedIt = std::find(rotatedChildren.begin(), rotatedChildren.end(), m_focusedChild);
if(focusedIt != rotatedChildren.end()) { if(m_focusedChild) {
std::rotate(rotatedChildren.begin(), focusedIt, rotatedChildren.end()); auto focusedIt = std::find(rotatedChildren.begin(), rotatedChildren.end(), m_focusedChild);
rotatedChildren.pop_front(); if(focusedIt != rotatedChildren.end()) {
for(const UIWidgetPtr& child : rotatedChildren) { std::rotate(rotatedChildren.begin(), focusedIt, rotatedChildren.end());
if(child->isFocusable()) { rotatedChildren.pop_front();
toFocus = child;
break;
}
} }
} else if(m_children.size() > 0) }
toFocus = m_children.back();
// finds next child to focus
for(const UIWidgetPtr& child : rotatedChildren) {
if(child->isFocusable()) {
toFocus = child;
break;
}
}
if(toFocus) if(toFocus)
focusChild(toFocus, reason); focusChild(toFocus, reason);
} }
void UIWidget::moveChildToTop(const UIWidgetPtr& childToMove) void UIWidget::moveChildToTop(const UIWidgetPtr& child)
{ {
assert(!m_destroyed); assert(!m_destroyed);
if(!child)
return;
// remove and push child again // remove and push child again
auto it = std::find(m_children.begin(), m_children.end(), childToMove); auto it = std::find(m_children.begin(), m_children.end(), child);
assert(it != m_children.end()); assert(it != m_children.end());
m_children.erase(it); m_children.erase(it);
m_children.push_back(childToMove); m_children.push_back(child);
} }
void UIWidget::lockChild(const UIWidgetPtr& childToLock) void UIWidget::lockChild(const UIWidgetPtr& child)
{ {
assert(hasChild(childToLock)); assert(!m_destroyed);
if(!child)
return;
// disable all other widgets assert(hasChild(child));
for(const UIWidgetPtr& widget : m_children) {
if(widget == childToLock) // disable all other children
widget->setEnabled(true); for(const UIWidgetPtr& otherChild : m_children) {
if(otherChild == child)
child->setEnabled(true);
else else
widget->setEnabled(false); otherChild->setEnabled(false);
} }
m_lockedWidgets.push_front(childToLock); m_lockedChildren.push_front(child);
// lock child focus // lock child focus
if(childToLock->isFocusable()) if(child->isFocusable())
focusChild(childToLock, UI::ActiveFocusReason); focusChild(child, UI::ActiveFocusReason);
} }
void UIWidget::unlockChild(const UIWidgetPtr& childToUnlock) void UIWidget::unlockChild(const UIWidgetPtr& child)
{ {
assert(hasChild(childToUnlock)); assert(!m_destroyed);
if(!child)
return;
assert(hasChild(child));
auto it = std::find(m_lockedWidgets.begin(), m_lockedWidgets.end(), childToUnlock); auto it = std::find(m_lockedChildren.begin(), m_lockedChildren.end(), child);
if(it != m_lockedWidgets.end()) if(it == m_lockedChildren.end())
m_lockedWidgets.erase(it); return;
UIWidgetPtr newLockedWidget; m_lockedChildren.erase(it);
if(m_lockedWidgets.size() > 0)
newLockedWidget = m_lockedWidgets.front();
for(const UIWidgetPtr& child : m_children) { // find new chick to lock
if(newLockedWidget) { UIWidgetPtr lockedChild;
if(child == newLockedWidget) if(m_lockedChildren.size() > 0)
child->setEnabled(true); lockedChild = m_lockedChildren.front();
for(const UIWidgetPtr& otherChild : m_children) {
// lock new child
if(lockedChild) {
if(otherChild == lockedChild)
lockedChild->setEnabled(true);
else else
child->setEnabled(false); otherChild->setEnabled(false);
} else }
child->setEnabled(true); // else unlock all
else
otherChild->setEnabled(true);
} }
} }
@ -814,6 +756,107 @@ void UIWidget::computeAnchoredWidgets()
child->computeAnchoredWidgets(); child->computeAnchoredWidgets();
} }
void UIWidget::onStyleApply(const OTMLNodePtr& styleNode)
{
assert(!m_destroyed);
// load styles used by all widgets
for(const OTMLNodePtr& node : styleNode->children()) {
// id
if(node->tag() == "id") {
setId(node->value());
}
// background image
else if(node->tag() == "image") {
setImage(Image::loadFromOTML(node));
}
else if(node->tag() == "border-image") {
setImage(BorderImage::loadFromOTML(node));
}
// font
else if(node->tag() == "font") {
setFont(g_fonts.getFont(node->value()));
}
// foreground color
else if(node->tag() == "color") {
setForegroundColor(node->value<Color>());
}
// background color
else if(node->tag() == "background-color") {
setBackgroundColor(node->value<Color>());
}
// opacity
else if(node->tag() == "opacity") {
setOpacity(node->value<int>());
}
// size
else if(node->tag() == "size") {
resize(node->value<Size>());
}
else if(node->tag() == "width") {
setWidth(node->value<int>());
}
else if(node->tag() == "height") {
setHeight(node->value<int>());
}
// absolute position
else if(node->tag() == "position") {
moveTo(node->value<Point>());
}
else if(node->tag() == "x") {
setX(node->value<int>());
}
else if(node->tag() == "y") {
setY(node->value<int>());
}
// margins
else if(node->tag() == "margin.left") {
setMarginLeft(node->value<int>());
}
else if(node->tag() == "margin.right") {
setMarginRight(node->value<int>());
}
else if(node->tag() == "margin.top") {
setMarginTop(node->value<int>());
}
else if(node->tag() == "margin.bottom") {
setMarginBottom(node->value<int>());
}
// anchors
else if(boost::starts_with(node->tag(), "anchors.")) {
std::string what = node->tag().substr(8);
if(what == "fill") {
fill(node->value());
} else if(what == "centerIn") {
centerIn(node->value());
} else {
AnchorEdge edge = fw::translateAnchorEdge(what);
std::string anchorDescription = node->value();
std::vector<std::string> split;
boost::split(split, anchorDescription, boost::is_any_of(std::string(".")));
if(split.size() != 2)
throw OTMLException(node, "invalid anchor description");
std::string hookedWidgetId = split[0];
AnchorEdge hookedEdge = fw::translateAnchorEdge(split[1]);
if(edge == AnchorNone)
throw OTMLException(node, "invalid anchor edge");
if(hookedEdge == AnchorNone)
throw OTMLException(node, "invalid anchor target edge");
addAnchor(edge, hookedWidgetId, hookedEdge);
}
}
else if(node->tag() == "onLoad") {
g_lua.loadFunction(node->value<std::string>(), "@" + node->source() + "[" + node->tag() + "]");
luaSetField("onLoad");
}
}
}
void UIWidget::onGeometryUpdate(const Rect& oldRect, const Rect& newRect) void UIWidget::onGeometryUpdate(const Rect& oldRect, const Rect& newRect)
{ {
@ -821,6 +864,7 @@ void UIWidget::onGeometryUpdate(const Rect& oldRect, const Rect& newRect)
void UIWidget::onFocusChange(bool focused, UI::FocusReason reason) void UIWidget::onFocusChange(bool focused, UI::FocusReason reason)
{ {
// when containers lose or get focus it's focused child do the same
if(m_focusedChild) if(m_focusedChild)
m_focusedChild->onFocusChange(focused, reason); m_focusedChild->onFocusChange(focused, reason);
} }
@ -837,6 +881,7 @@ bool UIWidget::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
// do a backup of children list, because it may change while looping it // do a backup of children list, because it may change while looping it
UIWidgetList children = m_children; UIWidgetList children = m_children;
for(const UIWidgetPtr& child : children) { for(const UIWidgetPtr& child : children) {
// events on hidden or disabled widgets are discarded
if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible()) if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible())
continue; continue;
@ -857,6 +902,7 @@ bool UIWidget::onKeyRelease(uchar keyCode, char keyChar, int keyboardModifiers)
// do a backup of children list, because it may change while looping it // do a backup of children list, because it may change while looping it
UIWidgetList children = m_children; UIWidgetList children = m_children;
for(const UIWidgetPtr& child : children) { for(const UIWidgetPtr& child : children) {
// events on hidden or disabled widgets are discarded
if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible()) if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible())
continue; continue;
@ -877,12 +923,13 @@ bool UIWidget::onMousePress(const Point& mousePos, UI::MouseButton button)
// do a backup of children list, because it may change while looping it // do a backup of children list, because it may change while looping it
UIWidgetList children = m_children; UIWidgetList children = m_children;
for(const UIWidgetPtr& child : children) { for(const UIWidgetPtr& child : children) {
// events on hidden or disabled widgets are discarded
if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible()) if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible())
continue; continue;
// mouse press events only go to children that contains the mouse position // mouse press events only go to children that contains the mouse position
if(child->getRect().contains(mousePos) && child == getChildByPos(mousePos)) { if(child->getRect().contains(mousePos) && child == getChildByPos(mousePos)) {
// focus it // when a focusable item is focused it must gain focus
if(child->isFocusable()) if(child->isFocusable())
focusChild(child, UI::MouseFocusReason); focusChild(child, UI::MouseFocusReason);
@ -901,6 +948,7 @@ bool UIWidget::onMouseRelease(const Point& mousePos, UI::MouseButton button)
// do a backup of children list, because it may change while looping it // do a backup of children list, because it may change while looping it
UIWidgetList children = m_children; UIWidgetList children = m_children;
for(const UIWidgetPtr& child : children) { for(const UIWidgetPtr& child : children) {
// events on hidden or disabled widgets are discarded
if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible()) if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible())
continue; continue;
@ -919,6 +967,7 @@ bool UIWidget::onMouseMove(const Point& mousePos, const Point& mouseMoved)
// do a backup of children list, because it may change while looping it // do a backup of children list, because it may change while looping it
UIWidgetList children = m_children; UIWidgetList children = m_children;
for(const UIWidgetPtr& child : children) { for(const UIWidgetPtr& child : children) {
// events on hidden or disabled widgets are discarded
if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible()) if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible())
continue; continue;
@ -948,6 +997,7 @@ bool UIWidget::onMouseWheel(const Point& mousePos, UI::MouseWheelDirection direc
// do a backup of children list, because it may change while looping it // do a backup of children list, because it may change while looping it
UIWidgetList children = m_children; UIWidgetList children = m_children;
for(const UIWidgetPtr& child : children) { for(const UIWidgetPtr& child : children) {
// events on hidden or disabled widgets are discarded
if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible()) if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible())
continue; continue;

@ -29,14 +29,14 @@ public:
void setHovered(bool hovered) { m_hovered = hovered; } void setHovered(bool hovered) { m_hovered = hovered; }
void setVisible(bool visible) { m_visible = visible; } void setVisible(bool visible) { m_visible = visible; }
void setParent(const UIWidgetPtr& parent); void setParent(const UIWidgetPtr& parent);
void setStyle(const std::string& styleName); void applyStyle(const std::string& styleName);
void setRect(const Rect& rect); void setRect(const Rect& rect);
void setX(int x) { move(Point(x, getY())); } void setX(int x) { moveTo(Point(x, getY())); }
void setY(int y) { move(Point(getX(), y)); } void setY(int y) { moveTo(Point(getX(), y)); }
void setWidth(int width) { resize(Size(width, getHeight())); } void setWidth(int width) { resize(Size(width, getHeight())); }
void setHeight(int height) { resize(Size(getWidth(), height)); } void setHeight(int height) { resize(Size(getWidth(), height)); }
void resize(const Size& size) { setRect(Rect(getPosition(), size)); } void resize(const Size& size) { setRect(Rect(getPosition(), size)); }
void move(const Point& pos) { setRect(Rect(pos, getSize())); } void moveTo(const Point& pos) { setRect(Rect(pos, getSize())); }
void setImage(const ImagePtr& image) { m_image = image; } void setImage(const ImagePtr& image) { m_image = image; }
virtual void setFont(const FontPtr& font) { m_font = font; } virtual void setFont(const FontPtr& font) { m_font = font; }
@ -54,6 +54,7 @@ public:
void enable() { setEnabled(true); } void enable() { setEnabled(true); }
bool isEnabled(); bool isEnabled();
bool isVisible();
bool isExplicitlyEnabled() const { return m_enabled; } bool isExplicitlyEnabled() const { return m_enabled; }
bool isExplicitlyVisible() const { return m_visible; } bool isExplicitlyVisible() const { return m_visible; }
bool isHovered() const { return m_hovered; } bool isHovered() const { return m_hovered; }
@ -96,14 +97,14 @@ public:
UIWidgetPtr recursiveGetChildByPos(const Point& childPos); UIWidgetPtr recursiveGetChildByPos(const Point& childPos);
UIWidgetPtr backwardsGetWidgetById(const std::string& id); UIWidgetPtr backwardsGetWidgetById(const std::string& id);
void addChild(const UIWidgetPtr& childToAdd); void addChild(const UIWidgetPtr& child);
void insertChild(const UIWidgetPtr& childToInsert, int index); void insertChild(const UIWidgetPtr& child, int index);
void removeChild(const UIWidgetPtr& childToRemove); void removeChild(const UIWidgetPtr& child);
void focusChild(const UIWidgetPtr& childToFocus, UI::FocusReason reason); void focusChild(const UIWidgetPtr& child, UI::FocusReason reason);
void focusNextChild(UI::FocusReason reason); void focusNextChild(UI::FocusReason reason);
void moveChildToTop(const UIWidgetPtr& childToMove); void moveChildToTop(const UIWidgetPtr& child);
void lockChild(const UIWidgetPtr& childToLock); void lockChild(const UIWidgetPtr& child);
void unlockChild(const UIWidgetPtr& childToUnlock); void unlockChild(const UIWidgetPtr& child);
void updateLayout(); void updateLayout();
void updateChildrenLayout(); void updateChildrenLayout();
@ -167,7 +168,7 @@ protected:
UIWeakWidgetList m_anchoredWidgets; UIWeakWidgetList m_anchoredWidgets;
UIWidgetWeakPtr m_parent; UIWidgetWeakPtr m_parent;
UIWidgetList m_children; UIWidgetList m_children;
UIWidgetList m_lockedWidgets; UIWidgetList m_lockedChildren;
UIWidgetPtr m_focusedChild; UIWidgetPtr m_focusedChild;
std::string m_id; std::string m_id;

@ -1,6 +1,7 @@
#include "uiwindow.h" #include "uiwindow.h"
#include <framework/graphics/borderimage.h> #include <framework/graphics/borderimage.h>
#include <framework/graphics/font.h> #include <framework/graphics/font.h>
#include <framework/graphics/graphics.h>
#include <framework/otml/otml.h> #include <framework/otml/otml.h>
UIWindow::UIWindow() UIWindow::UIWindow()
@ -45,6 +46,7 @@ void UIWindow::render()
headRect.setHeight(m_headHeight); headRect.setHeight(m_headHeight);
if(m_headImage && m_headHeight > 0) { if(m_headImage && m_headHeight > 0) {
g_graphics.bindColor(m_backgroundColor);
m_headImage->draw(headRect); m_headImage->draw(headRect);
// draw window head text // draw window head text
@ -118,7 +120,7 @@ bool UIWindow::onMouseRelease(const Point& mousePos, UI::MouseButton button)
bool UIWindow::onMouseMove(const Point& mousePos, const Point& mouseMoved) bool UIWindow::onMouseMove(const Point& mousePos, const Point& mouseMoved)
{ {
if(m_moving) { if(m_moving) {
move(mousePos - m_movingReference); moveTo(mousePos - m_movingReference);
return true; return true;
} }
return UIWidget::onMouseMove(mousePos, mouseMoved); return UIWidget::onMouseMove(mousePos, mouseMoved);

Loading…
Cancel
Save