Many UI improvements and minor fixes

This commit is contained in:
Eduardo Bart 2013-01-08 18:01:47 -02:00
parent a8d3bb97ea
commit 5344a179a4
16 changed files with 152 additions and 65 deletions

View File

@ -273,7 +273,8 @@ namespace Fw
LastState = 512, LastState = 512,
AlternateState = 1024, AlternateState = 1024,
DraggingState = 2048, DraggingState = 2048,
LastWidgetState = 4096 HiddenState = 4096,
LastWidgetState = 8192
}; };
enum DrawPane { enum DrawPane {

View File

@ -311,3 +311,9 @@ std::string ResourceManager::getBaseDir()
return buffer; return buffer;
} }
std::string ResourceManager::guessFileType(const std::string& filename, const std::string& type)
{
if(g_resources.fileExists(filename))
return filename;
return filename + "." + type;
}

View File

@ -70,6 +70,8 @@ public:
std::string getWorkDir() { return m_workDir; } std::string getWorkDir() { return m_workDir; }
std::deque<std::string> getSearchPaths() { return m_searchPaths; } std::deque<std::string> getSearchPaths() { return m_searchPaths; }
std::string guessFileType(const std::string& filename, const std::string& type);
private: private:
std::string m_workDir; std::string m_workDir;
std::string m_writeDir; std::string m_writeDir;

View File

@ -83,7 +83,7 @@ bool UIGridLayout::internalUpdate()
int numColumns = m_numColumns; int numColumns = m_numColumns;
if(m_flow && m_cellSize.width() > 0) { if(m_flow && m_cellSize.width() > 0) {
numColumns = clippingRect.width() / (m_cellSize.width() + m_cellSpacing); numColumns = (clippingRect.width() + m_cellSpacing) / (m_cellSize.width() + m_cellSpacing);
if(numColumns > 0) { if(numColumns > 0) {
m_numColumns = numColumns; m_numColumns = numColumns;
m_numLines = std::ceil(widgets.size() / (float)numColumns); m_numLines = std::ceil(widgets.size() / (float)numColumns);

View File

@ -46,6 +46,7 @@ public:
void setFlow(bool enable) { m_flow = enable; update(); } void setFlow(bool enable) { m_flow = enable; update(); }
Size getCellSize() { return m_cellSize; } Size getCellSize() { return m_cellSize; }
int getCellSpacing() { return m_cellSpacing; }
int getNumColumns() { return m_numColumns; } int getNumColumns() { return m_numColumns; }
int getNumLines() { return m_numLines; } int getNumLines() { return m_numLines; }

View File

@ -46,8 +46,8 @@ bool UIHorizontalLayout::internalUpdate()
std::reverse(widgets.begin(), widgets.end()); std::reverse(widgets.begin(), widgets.end());
bool changed = false; bool changed = false;
Rect clippingRect = parentWidget->getPaddingRect(); Rect paddingRect = parentWidget->getPaddingRect();
Point pos = (m_alignRight) ? clippingRect.topRight() : clippingRect.topLeft(); Point pos = (m_alignRight) ? paddingRect.topRight() : paddingRect.topLeft();
int preferredWidth = 0; int preferredWidth = 0;
int gap; int gap;
@ -62,13 +62,19 @@ bool UIHorizontalLayout::internalUpdate()
preferredWidth += gap; preferredWidth += gap;
if(widget->isFixedSize()) { if(widget->isFixedSize()) {
// center it if(widget->getTextAlign() & Fw::AlignTop) {
pos.y = clippingRect.top() + (clippingRect.height() - (widget->getMarginTop() + widget->getHeight() + widget->getMarginBottom()))/2; pos.y = paddingRect.top() + widget->getMarginTop();
pos.y = std::max(pos.y, parentWidget->getY()); } else if(widget->getTextAlign() & Fw::AlignBottom) {
pos.y = paddingRect.bottom() - widget->getHeight() - widget->getMarginBottom();
pos.y = std::max(pos.y, paddingRect.top());
} else { // center it
pos.y = paddingRect.top() + (paddingRect.height() - (widget->getMarginTop() + widget->getHeight() + widget->getMarginBottom()))/2;
pos.y = std::max(pos.y, paddingRect.top());
}
} else { } else {
// expand height // expand height
size.setHeight(clippingRect.height() - (widget->getMarginTop() + widget->getMarginBottom())); size.setHeight(paddingRect.height() - (widget->getMarginTop() + widget->getMarginBottom()));
pos.y = clippingRect.top() + (clippingRect.height() - size.height())/2; pos.y = paddingRect.top() + (paddingRect.height() - size.height())/2;
} }
if(widget->setRect(Rect(pos - parentWidget->getVirtualOffset(), size))) if(widget->setRect(Rect(pos - parentWidget->getVirtualOffset(), size)))

View File

@ -39,6 +39,7 @@ public:
protected: protected:
bool internalUpdate(); bool internalUpdate();
Fw::AlignmentFlag m_alignChidren;
stdext::boolean<false> m_alignRight; stdext::boolean<false> m_alignRight;
}; };

View File

@ -28,6 +28,7 @@
#include <framework/platform/platformwindow.h> #include <framework/platform/platformwindow.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
#include <framework/core/application.h> #include <framework/core/application.h>
#include <framework/core/resourcemanager.h>
UIManager g_ui; UIManager g_ui;
@ -149,7 +150,7 @@ void UIManager::inputEvent(const InputEvent& event)
break; break;
} }
case Fw::MouseWheelInputEvent: case Fw::MouseWheelInputEvent:
m_mouseReceiver->propagateOnMouseEvent(event.mousePos, widgetList); m_rootWidget->propagateOnMouseEvent(event.mousePos, widgetList);
for(const UIWidgetPtr& widget : widgetList) { for(const UIWidgetPtr& widget : widgetList) {
if(widget->onMouseWheel(event.mousePos, event.wheelDirection)) if(widget->onMouseWheel(event.mousePos, event.wheelDirection))
break; break;
@ -219,9 +220,12 @@ void UIManager::updateHoveredWidget(bool now)
return; return;
m_hoverUpdateScheduled = false; m_hoverUpdateScheduled = false;
UIWidgetPtr hoveredWidget = m_rootWidget->recursiveGetChildByPos(g_window.getMousePosition(), false); UIWidgetPtr hoveredWidget;
//if(!g_window.isMouseButtonPressed(Fw::MouseLeftButton) && !g_window.isMouseButtonPressed(Fw::MouseRightButton)) {
hoveredWidget = m_rootWidget->recursiveGetChildByPos(g_window.getMousePosition(), false);
if(hoveredWidget && !hoveredWidget->isEnabled()) if(hoveredWidget && !hoveredWidget->isEnabled())
hoveredWidget = nullptr; hoveredWidget = nullptr;
//}
if(hoveredWidget != m_hoveredWidget) { if(hoveredWidget != m_hoveredWidget) {
UIWidgetPtr oldHovered = m_hoveredWidget; UIWidgetPtr oldHovered = m_hoveredWidget;
@ -304,9 +308,11 @@ void UIManager::clearStyles()
m_styles.clear(); m_styles.clear();
} }
bool UIManager::importStyle(const std::string& file) bool UIManager::importStyle(std::string file)
{ {
try { try {
file = g_resources.guessFileType(file, "otui");
OTMLDocumentPtr doc = OTMLDocument::parse(file); OTMLDocumentPtr doc = OTMLDocument::parse(file);
for(const OTMLNodePtr& styleNode : doc->children()) for(const OTMLNodePtr& styleNode : doc->children())
@ -385,9 +391,11 @@ std::string UIManager::getStyleClass(const std::string& styleName)
return ""; return "";
} }
UIWidgetPtr UIManager::loadUI(const std::string& file, const UIWidgetPtr& parent) UIWidgetPtr UIManager::loadUI(std::string file, const UIWidgetPtr& parent)
{ {
try { try {
file = g_resources.guessFileType(file, "otui");
OTMLDocumentPtr doc = OTMLDocument::parse(file); OTMLDocumentPtr doc = OTMLDocument::parse(file);
UIWidgetPtr widget; UIWidgetPtr widget;
for(const OTMLNodePtr& node : doc->children()) { for(const OTMLNodePtr& node : doc->children()) {

View File

@ -44,12 +44,12 @@ public:
void updateHoveredWidget(bool now = false); void updateHoveredWidget(bool now = false);
void clearStyles(); void clearStyles();
bool importStyle(const std::string& file); bool importStyle(std::string file);
void importStyleFromOTML(const OTMLNodePtr& styleNode); void importStyleFromOTML(const OTMLNodePtr& styleNode);
OTMLNodePtr getStyle(const std::string& styleName); OTMLNodePtr getStyle(const std::string& styleName);
std::string getStyleClass(const std::string& styleName); std::string getStyleClass(const std::string& styleName);
UIWidgetPtr loadUI(const std::string& file, const UIWidgetPtr& parent); UIWidgetPtr loadUI(std::string file, const UIWidgetPtr& parent);
UIWidgetPtr displayUI(const std::string& file) { return loadUI(file, m_rootWidget); } UIWidgetPtr displayUI(const std::string& file) { return loadUI(file, m_rootWidget); }
UIWidgetPtr createWidget(const std::string& styleName, const UIWidgetPtr& parent); UIWidgetPtr createWidget(const std::string& styleName, const UIWidgetPtr& parent);
UIWidgetPtr createWidgetFromOTML(const OTMLNodePtr& widgetNode, const UIWidgetPtr& parent); UIWidgetPtr createWidgetFromOTML(const OTMLNodePtr& widgetNode, const UIWidgetPtr& parent);

View File

@ -96,6 +96,8 @@ Fw::WidgetState Fw::translateState(std::string state)
return Fw::AlternateState; return Fw::AlternateState;
else if(state == "dragging") else if(state == "dragging")
return Fw::DraggingState; return Fw::DraggingState;
else if(state == "hidden")
return Fw::HiddenState;
else else
return Fw::InvalidState; return Fw::InvalidState;
} }

View File

@ -47,8 +47,8 @@ bool UIVerticalLayout::internalUpdate()
if(m_alignBottom) if(m_alignBottom)
std::reverse(widgets.begin(), widgets.end()); std::reverse(widgets.begin(), widgets.end());
Rect clippingRect = parentWidget->getPaddingRect(); Rect paddingRect = parentWidget->getPaddingRect();
Point pos = (m_alignBottom) ? clippingRect.bottomLeft() : clippingRect.topLeft(); Point pos = (m_alignBottom) ? paddingRect .bottomLeft() : paddingRect.topLeft();
int preferredHeight = 0; int preferredHeight = 0;
int gap; int gap;
@ -64,12 +64,19 @@ bool UIVerticalLayout::internalUpdate()
if(widget->isFixedSize()) { if(widget->isFixedSize()) {
// center it // center it
pos.x = clippingRect.left() + (clippingRect.width() - (widget->getMarginLeft() + widget->getWidth() + widget->getMarginRight()))/2; if(widget->getTextAlign() & Fw::AlignLeft) {
pos.x = std::max(pos.x, parentWidget->getX()); pos.x = paddingRect.left() + widget->getMarginLeft();
} else if(widget->getTextAlign() & Fw::AlignLeft) {
pos.x = paddingRect.bottom() - widget->getHeight() - widget->getMarginBottom();
pos.x = std::max(pos.x, paddingRect.left());
} else {
pos.x = paddingRect.left() + (paddingRect.width() - (widget->getMarginLeft() + widget->getWidth() + widget->getMarginRight()))/2;
pos.x = std::max(pos.x, paddingRect.left());
}
} else { } else {
// expand width // expand width
size.setWidth(clippingRect.width() - (widget->getMarginLeft() + widget->getMarginRight())); size.setWidth(paddingRect.width() - (widget->getMarginLeft() + widget->getMarginRight()));
pos.x = clippingRect.left() + (clippingRect.width() - size.width())/2; pos.x = paddingRect.left() + (paddingRect.width() - size.width())/2;
} }
if(widget->setRect(Rect(pos - parentWidget->getVirtualOffset(), size))) if(widget->setRect(Rect(pos - parentWidget->getVirtualOffset(), size)))

View File

@ -124,17 +124,17 @@ void UIWidget::drawChildren(const Rect& visibleRect, Fw::DrawPane drawPane)
void UIWidget::addChild(const UIWidgetPtr& child) void UIWidget::addChild(const UIWidgetPtr& child)
{ {
if(!child) { if(!child) {
g_logger.warning("attempt to add a null child into a UIWidget"); g_logger.traceWarning("attempt to add a null child into a UIWidget");
return; return;
} }
if(child->isDestroyed()) { if(child->isDestroyed()) {
g_logger.warning("attemp to add a destroyed child into a UIWidget"); g_logger.traceWarning("attemp to add a destroyed child into a UIWidget");
return; return;
} }
if(hasChild(child)) { if(hasChild(child)) {
g_logger.warning("attempt to add a child again into a UIWidget"); g_logger.traceWarning("attempt to add a child again into a UIWidget");
return; return;
} }
@ -165,20 +165,20 @@ void UIWidget::addChild(const UIWidgetPtr& child)
void UIWidget::insertChild(int index, const UIWidgetPtr& child) void UIWidget::insertChild(int index, const UIWidgetPtr& child)
{ {
if(!child) { if(!child) {
g_logger.warning("attempt to insert a null child into a UIWidget"); g_logger.traceWarning("attempt to insert a null child into a UIWidget");
return; return;
} }
if(hasChild(child)) { if(hasChild(child)) {
g_logger.warning("attempt to insert a child again into a UIWidget"); g_logger.traceWarning("attempt to insert a child again into a UIWidget");
return; return;
} }
index = index <= 0 ? (m_children.size() + index) : index-1; index = index <= 0 ? (m_children.size() + index) : index-1;
if(!(index >= 0 && (uint)index <= m_children.size())) { if(!(index >= 0 && (uint)index <= m_children.size())) {
g_logger.traceError("attempt to insert a child in an invalid index"); //g_logger.traceWarning("attempt to insert a child UIWidget into an invalid index, using nearest index...");
return; index = std::min(std::max(index, 0), (int)m_children.size());
} }
// retrieve child by index // retrieve child by index
@ -232,7 +232,7 @@ void UIWidget::removeChild(UIWidgetPtr child)
g_ui.onWidgetDisappear(child); g_ui.onWidgetDisappear(child);
} else } else
g_logger.error("attempt to remove an unknown child from a UIWidget"); g_logger.traceError("attempt to remove an unknown child from a UIWidget");
} }
@ -376,7 +376,7 @@ void UIWidget::moveChildToIndex(const UIWidgetPtr& child, int index)
return; return;
if((uint)index - 1 > m_children.size()) { if((uint)index - 1 > m_children.size()) {
g_logger.error(stdext::format("moving %s to index %d on %s", child->getId(), index, m_id)); g_logger.traceError(stdext::format("moving %s to index %d on %s", child->getId(), index, m_id));
return; return;
} }
@ -472,7 +472,11 @@ void UIWidget::unlockChild(const UIWidgetPtr& child)
void UIWidget::mergeStyle(const OTMLNodePtr& styleNode) void UIWidget::mergeStyle(const OTMLNodePtr& styleNode)
{ {
applyStyle(styleNode); applyStyle(styleNode);
std::string name = m_style->tag();
std::string source = m_style->source();
m_style->merge(styleNode); m_style->merge(styleNode);
m_style->setTag(name);
m_style->setSource(source);
updateStyle(); updateStyle();
} }
@ -491,7 +495,7 @@ void UIWidget::applyStyle(const OTMLNodePtr& styleNode)
if(node->tag()[0] == '!') { if(node->tag()[0] == '!') {
std::string tag = node->tag().substr(1); std::string tag = node->tag().substr(1);
std::string code = stdext::format("tostring(%s)", node->value().c_str()); std::string code = stdext::format("tostring(%s)", node->value().c_str());
std::string origin = "@" + node->source() + "[" + node->tag() + "]"; std::string origin = "@" + node->source() + ": [" + node->tag() + "]";
g_lua.evaluateExpression(code, origin); g_lua.evaluateExpression(code, origin);
std::string value = g_lua.popString(); std::string value = g_lua.popString();
@ -510,7 +514,7 @@ void UIWidget::applyStyle(const OTMLNodePtr& styleNode)
} }
m_firstOnStyle = false; m_firstOnStyle = false;
} catch(stdext::exception& e) { } catch(stdext::exception& e) {
g_logger.error(stdext::format("failed to apply style to widget '%s': %s", m_id, e.what())); g_logger.traceError(stdext::format("failed to apply style to widget '%s': %s", m_id, e.what()));
} }
m_loadingStyle = false; m_loadingStyle = false;
} }
@ -523,7 +527,7 @@ void UIWidget::addAnchor(Fw::AnchorEdge anchoredEdge, const std::string& hookedW
if(UIAnchorLayoutPtr anchorLayout = getAnchoredLayout()) if(UIAnchorLayoutPtr anchorLayout = getAnchoredLayout())
anchorLayout->addAnchor(static_self_cast<UIWidget>(), anchoredEdge, hookedWidgetId, hookedEdge); anchorLayout->addAnchor(static_self_cast<UIWidget>(), anchoredEdge, hookedWidgetId, hookedEdge);
else else
g_logger.error(stdext::format("cannot add anchors to widget '%s': the parent doesn't use anchors layout", m_id)); g_logger.traceError(stdext::format("cannot add anchors to widget '%s': the parent doesn't use anchors layout", m_id));
} }
void UIWidget::removeAnchor(Fw::AnchorEdge anchoredEdge) void UIWidget::removeAnchor(Fw::AnchorEdge anchoredEdge)
@ -540,7 +544,7 @@ void UIWidget::centerIn(const std::string& hookedWidgetId)
anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorHorizontalCenter, hookedWidgetId, Fw::AnchorHorizontalCenter); anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorHorizontalCenter, hookedWidgetId, Fw::AnchorHorizontalCenter);
anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorVerticalCenter, hookedWidgetId, Fw::AnchorVerticalCenter); anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorVerticalCenter, hookedWidgetId, Fw::AnchorVerticalCenter);
} else } else
g_logger.error(stdext::format("cannot add anchors to widget '%s': the parent doesn't use anchors layout", m_id)); g_logger.traceError(stdext::format("cannot add anchors to widget '%s': the parent doesn't use anchors layout", m_id));
} }
void UIWidget::fill(const std::string& hookedWidgetId) void UIWidget::fill(const std::string& hookedWidgetId)
@ -554,7 +558,7 @@ void UIWidget::fill(const std::string& hookedWidgetId)
anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorTop, hookedWidgetId, Fw::AnchorTop); anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorTop, hookedWidgetId, Fw::AnchorTop);
anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorBottom, hookedWidgetId, Fw::AnchorBottom); anchorLayout->addAnchor(static_self_cast<UIWidget>(), Fw::AnchorBottom, hookedWidgetId, Fw::AnchorBottom);
} else } else
g_logger.error(stdext::format("cannot add anchors to widget '%s': the parent doesn't use anchors layout", m_id)); g_logger.traceError(stdext::format("cannot add anchors to widget '%s': the parent doesn't use anchors layout", m_id));
} }
void UIWidget::breakAnchors() void UIWidget::breakAnchors()
@ -751,6 +755,7 @@ void UIWidget::destroyChildren()
child->destroy(); child->destroy();
} }
if(layout)
layout->enableUpdates(); layout->enableUpdates();
} }
@ -790,6 +795,9 @@ void UIWidget::setParent(const UIWidgetPtr& parent)
void UIWidget::setLayout(const UILayoutPtr& layout) void UIWidget::setLayout(const UILayoutPtr& layout)
{ {
if(!layout)
stdext::throw_exception("attempt to set a nil layout to a widget");
if(m_layout) if(m_layout)
m_layout->disableUpdates(); m_layout->disableUpdates();
@ -893,14 +901,13 @@ void UIWidget::setVisible(bool visible)
updateParentLayout(); updateParentLayout();
updateState(Fw::ActiveState); updateState(Fw::ActiveState);
updateState(Fw::HiddenState);
// visibility can change the current hovered widget // visibility can change the current hovered widget
if(visible) if(visible)
g_ui.onWidgetAppear(static_self_cast<UIWidget>()); g_ui.onWidgetAppear(static_self_cast<UIWidget>());
else else
g_ui.onWidgetDisappear(static_self_cast<UIWidget>()); g_ui.onWidgetDisappear(static_self_cast<UIWidget>());
callLuaField("onVisibilityChange", visible);
} }
} }
@ -956,16 +963,6 @@ void UIWidget::setVirtualOffset(const Point& offset)
m_layout->update(); m_layout->update();
} }
bool UIWidget::isVisible()
{
if(!m_visible)
return false;
else if(UIWidgetPtr parent = getParent())
return parent->isVisible();
else
return static_self_cast<UIWidget>() == g_ui.getRootWidget();
}
bool UIWidget::isAnchored() bool UIWidget::isAnchored()
{ {
if(UIWidgetPtr parent = getParent()) if(UIWidgetPtr parent = getParent())
@ -1289,6 +1286,19 @@ void UIWidget::updateState(Fw::WidgetState state)
newStatus = (getParent() && (getParent()->getChildIndex(static_self_cast<UIWidget>()) % 2) == 1); newStatus = (getParent() && (getParent()->getChildIndex(static_self_cast<UIWidget>()) % 2) == 1);
break; break;
} }
case Fw::HiddenState: {
bool visible = true;
UIWidgetPtr widget = static_self_cast<UIWidget>();
do {
if(!widget->isExplicitlyVisible()) {
visible = false;
break;
}
} while((widget = widget->getParent()));
newStatus = !visible;
updateChildren = newStatus != oldStatus;
break;
}
default: default:
return; return;
} }
@ -1304,6 +1314,8 @@ void UIWidget::updateState(Fw::WidgetState state)
// disabled widgets cannot have hover state // disabled widgets cannot have hover state
if(state == Fw::DisabledState && !newStatus && isHovered()) { if(state == Fw::DisabledState && !newStatus && isHovered()) {
g_ui.updateHoveredWidget(); g_ui.updateHoveredWidget();
} else if(state == Fw::HiddenState) {
onVisibilityChange(!newStatus);
} }
} }
} }
@ -1414,7 +1426,7 @@ void UIWidget::onGeometryChange(const Rect& oldRect, const Rect& newRect)
// move children that is outside the parent rect to inside again // move children that is outside the parent rect to inside again
for(const UIWidgetPtr& child : m_children) { for(const UIWidgetPtr& child : m_children) {
if(!child->isAnchored()) if(!child->isAnchored() && child->isVisible())
child->bindRectToParent(); child->bindRectToParent();
} }
@ -1443,6 +1455,13 @@ void UIWidget::onHoverChange(bool hovered)
callLuaField("onHoverChange", hovered); callLuaField("onHoverChange", hovered);
} }
void UIWidget::onVisibilityChange(bool visible)
{
if(!isAnchored())
bindRectToParent();
callLuaField("onVisibilityChange", visible);
}
bool UIWidget::onDragEnter(const Point& mousePos) bool UIWidget::onDragEnter(const Point& mousePos)
{ {
return callLuaField<bool>("onDragEnter", mousePos); return callLuaField<bool>("onDragEnter", mousePos);

View File

@ -132,7 +132,6 @@ public:
void setAutoRepeatDelay(int delay) { m_autoRepeatDelay = delay; } void setAutoRepeatDelay(int delay) { m_autoRepeatDelay = delay; }
void setVirtualOffset(const Point& offset); void setVirtualOffset(const Point& offset);
bool isVisible();
bool isAnchored(); bool isAnchored();
bool isChildLocked(const UIWidgetPtr& child); bool isChildLocked(const UIWidgetPtr& child);
bool hasChild(const UIWidgetPtr& child); bool hasChild(const UIWidgetPtr& child);
@ -185,6 +184,7 @@ protected:
virtual void onFocusChange(bool focused, Fw::FocusReason reason); virtual void onFocusChange(bool focused, Fw::FocusReason reason);
virtual void onChildFocusChange(const UIWidgetPtr& focusedChild, const UIWidgetPtr& unfocusedChild, Fw::FocusReason reason); virtual void onChildFocusChange(const UIWidgetPtr& focusedChild, const UIWidgetPtr& unfocusedChild, Fw::FocusReason reason);
virtual void onHoverChange(bool hovered); virtual void onHoverChange(bool hovered);
virtual void onVisibilityChange(bool visible);
virtual bool onDragEnter(const Point& mousePos); virtual bool onDragEnter(const Point& mousePos);
virtual bool onDragLeave(UIWidgetPtr droppedWidget, const Point& mousePos); virtual bool onDragLeave(UIWidgetPtr droppedWidget, const Point& mousePos);
virtual bool onDragMove(const Point& mousePos, const Point& mouseMoved); virtual bool onDragMove(const Point& mousePos, const Point& mouseMoved);
@ -232,7 +232,8 @@ public:
bool isChecked() { return hasState(Fw::CheckedState); } bool isChecked() { return hasState(Fw::CheckedState); }
bool isOn() { return hasState(Fw::OnState); } bool isOn() { return hasState(Fw::OnState); }
bool isDragging() { return hasState(Fw::DraggingState); } bool isDragging() { return hasState(Fw::DraggingState); }
bool isHidden() { return !isVisible(); } bool isVisible() { return !hasState(Fw::HiddenState); }
bool isHidden() { return hasState(Fw::HiddenState); }
bool isExplicitlyEnabled() { return m_enabled; } bool isExplicitlyEnabled() { return m_enabled; }
bool isExplicitlyVisible() { return m_visible; } bool isExplicitlyVisible() { return m_visible; }
bool isFocusable() { return m_focusable; } bool isFocusable() { return m_focusable; }
@ -280,6 +281,7 @@ protected:
Color m_iconColor; Color m_iconColor;
Rect m_iconRect; Rect m_iconRect;
Rect m_iconClipRect; Rect m_iconClipRect;
Fw::AlignmentFlag m_iconAlign;
EdgeGroup<Color> m_borderColor; EdgeGroup<Color> m_borderColor;
EdgeGroup<int> m_borderWidth; EdgeGroup<int> m_borderWidth;
EdgeGroup<int> m_margin; EdgeGroup<int> m_margin;
@ -306,14 +308,15 @@ public:
void setBackgroundRect(const Rect& rect) { m_backgroundRect = rect; } void setBackgroundRect(const Rect& rect) { m_backgroundRect = rect; }
void setIcon(const std::string& iconFile); void setIcon(const std::string& iconFile);
void setIconColor(const Color& color) { m_iconColor = color; } void setIconColor(const Color& color) { m_iconColor = color; }
void setIconOffsetX(int x) { m_iconRect.setX(x); } void setIconOffsetX(int x) { m_iconOffset.x = x; }
void setIconOffsetY(int y) { m_iconRect.setX(y); } void setIconOffsetY(int y) { m_iconOffset.y = y; }
void setIconOffset(const Point& pos) { m_iconRect.move(pos); } void setIconOffset(const Point& pos) { m_iconOffset = pos; }
void setIconWidth(int width) { m_iconRect.setWidth(width); } void setIconWidth(int width) { m_iconRect.setWidth(width); }
void setIconHeight(int height) { m_iconRect.setHeight(height); } void setIconHeight(int height) { m_iconRect.setHeight(height); }
void setIconSize(const Size& size) { m_iconRect.resize(size); } void setIconSize(const Size& size) { m_iconRect.resize(size); }
void setIconRect(const Rect& rect) { m_iconRect = rect; } void setIconRect(const Rect& rect) { m_iconRect = rect; }
void setIconClip(const Rect& rect) { m_iconClipRect = rect; } void setIconClip(const Rect& rect) { m_iconClipRect = rect; }
void setIconAlign(Fw::AlignmentFlag align) { m_iconAlign = align; }
void setBorderWidth(int width) { m_borderWidth.set(width); updateLayout(); } void setBorderWidth(int width) { m_borderWidth.set(width); updateLayout(); }
void setBorderWidthTop(int width) { m_borderWidth.top = width; } void setBorderWidthTop(int width) { m_borderWidth.top = width; }
void setBorderWidthRight(int width) { m_borderWidth.right = width; } void setBorderWidthRight(int width) { m_borderWidth.right = width; }
@ -404,6 +407,7 @@ protected:
Rect m_imageClipRect; Rect m_imageClipRect;
Rect m_imageRect; Rect m_imageRect;
Color m_imageColor; Color m_imageColor;
Point m_iconOffset;
stdext::boolean<false> m_imageFixedRatio; stdext::boolean<false> m_imageFixedRatio;
stdext::boolean<false> m_imageRepeated; stdext::boolean<false> m_imageRepeated;
stdext::boolean<false> m_imageSmooth; stdext::boolean<false> m_imageSmooth;

View File

@ -38,6 +38,7 @@ void UIWidget::initBaseStyle()
m_iconColor = Color::white; m_iconColor = Color::white;
m_color = Color::white; m_color = Color::white;
m_opacity = 1.0f; m_opacity = 1.0f;
m_iconAlign = Fw::AlignNone;
// generate an unique id, this is need because anchored layouts find widgets by id // generate an unique id, this is need because anchored layouts find widgets by id
static unsigned long id = 1; static unsigned long id = 1;
@ -102,6 +103,8 @@ void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode)
setIconRect(node->value<Rect>()); setIconRect(node->value<Rect>());
else if(node->tag() == "icon-clip") else if(node->tag() == "icon-clip")
setIconClip(node->value<Rect>()); setIconClip(node->value<Rect>());
else if(node->tag() == "icon-align")
setIconAlign(Fw::translateAlignment(node->value()));
else if(node->tag() == "opacity") else if(node->tag() == "opacity")
setOpacity(node->value<float>()); setOpacity(node->value<float>());
else if(node->tag() == "enabled") else if(node->tag() == "enabled")
@ -110,7 +113,7 @@ void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode)
setVisible(node->value<bool>()); setVisible(node->value<bool>());
else if(node->tag() == "checked") else if(node->tag() == "checked")
setChecked(node->value<bool>()); setChecked(node->value<bool>());
else if(node->tag() == "dragable") else if(node->tag() == "draggable")
setDraggable(node->value<bool>()); setDraggable(node->value<bool>());
else if(node->tag() == "on") else if(node->tag() == "on")
setOn(node->value<bool>()); setOn(node->value<bool>());
@ -306,14 +309,14 @@ void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode)
// load once // load once
if(m_firstOnStyle) { if(m_firstOnStyle) {
std::string funcName = node->tag().substr(1); std::string funcName = node->tag().substr(1);
std::string funcOrigin = "@" + node->source() + "[" + node->tag() + "]"; std::string funcOrigin = "@" + node->source() + ": [" + node->tag() + "]";
g_lua.loadFunction(node->value(), funcOrigin); g_lua.loadFunction(node->value(), funcOrigin);
luaSetField(funcName); luaSetField(funcName);
} }
// lua fields value // lua fields value
} else if(stdext::starts_with(node->tag(), "&")) { } else if(stdext::starts_with(node->tag(), "&")) {
std::string fieldName = node->tag().substr(1); std::string fieldName = node->tag().substr(1);
std::string fieldOrigin = "@" + node->source() + "[" + node->tag() + "]"; std::string fieldOrigin = "@" + node->source() + ": [" + node->tag() + "]";
g_lua.evaluateExpression(node->value(), fieldOrigin); g_lua.evaluateExpression(node->value(), fieldOrigin);
luaSetField(fieldName); luaSetField(fieldName);
@ -375,7 +378,12 @@ void UIWidget::drawIcon(const Rect& screenCoords)
drawRect.resize(m_iconRect.size()); drawRect.resize(m_iconRect.size());
} else { } else {
drawRect.resize(m_iconClipRect.size()); drawRect.resize(m_iconClipRect.size());
if(m_iconAlign == Fw::AlignNone)
drawRect.moveCenter(screenCoords.center()); drawRect.moveCenter(screenCoords.center());
else
drawRect.alignIn(screenCoords, m_iconAlign);
drawRect.translate(m_iconOffset);
} }
g_painter->setColor(m_iconColor); g_painter->setColor(m_iconColor);
g_painter->drawTexturedRect(drawRect, m_icon, m_iconClipRect); g_painter->drawTexturedRect(drawRect, m_icon, m_iconClipRect);
@ -385,6 +393,6 @@ void UIWidget::drawIcon(const Rect& screenCoords)
void UIWidget::setIcon(const std::string& iconFile) void UIWidget::setIcon(const std::string& iconFile)
{ {
m_icon = g_textures.getTexture(iconFile); m_icon = g_textures.getTexture(iconFile);
if(!m_iconClipRect.isValid()) if(m_icon && !m_iconClipRect.isValid())
m_iconClipRect = Rect(0, 0, m_icon->getSize()); m_iconClipRect = Rect(0, 0, m_icon->getSize());
} }

View File

@ -44,7 +44,7 @@ void UIWidget::updateText()
// update rect size // update rect size
if(!m_rect.isValid() || m_textAutoResize) { if(!m_rect.isValid() || m_textAutoResize) {
Size textBoxSize = getTextSize(); Size textBoxSize = getTextSize();
textBoxSize += Size(m_padding.left + m_padding.right, m_padding.top + m_padding.bottom); textBoxSize += Size(m_padding.left + m_padding.right, m_padding.top + m_padding.bottom) + m_textOffset.toSize();
Size size = getSize(); Size size = getSize();
if(size.width() <= 0 || (m_textAutoResize && !m_textWrap)) if(size.width() <= 0 || (m_textAutoResize && !m_textWrap))
size.setWidth(textBoxSize.width()); size.setWidth(textBoxSize.width());
@ -82,12 +82,13 @@ void UIWidget::drawText(const Rect& screenCoords)
return; return;
if(screenCoords != m_textCachedScreenCoords || m_textMustRecache) { if(screenCoords != m_textCachedScreenCoords || m_textMustRecache) {
Rect coords = Rect(screenCoords.topLeft() + m_textOffset, screenCoords.bottomRight());
m_textMustRecache = false; m_textMustRecache = false;
m_textCachedScreenCoords = screenCoords; m_textCachedScreenCoords = coords;
m_textCoordsBuffer.clear(); m_textCoordsBuffer.clear();
m_font->calculateDrawTextCoords(m_textCoordsBuffer, m_drawText, screenCoords.translated(m_textOffset), m_textAlign); m_font->calculateDrawTextCoords(m_textCoordsBuffer, m_drawText, coords, m_textAlign);
} }
g_painter->setColor(m_color); g_painter->setColor(m_color);

View File

@ -284,6 +284,27 @@ public:
moveTop(r.top()); moveTop(r.top());
} }
void alignIn(const TRect<T> &r, Fw::AlignmentFlag align) {
if(align == Fw::AlignTopLeft)
moveTopLeft(r.topLeft());
else if(align == Fw::AlignTopRight)
moveTopRight(r.topRight());
else if(align == Fw::AlignTopCenter)
moveTopCenter(r.topCenter());
else if(align == Fw::AlignBottomLeft)
moveBottomLeft(r.bottomLeft());
else if(align == Fw::AlignBottomRight)
moveBottomRight(r.bottomRight());
else if(align == Fw::AlignBottomCenter)
moveBottomCenter(r.bottomCenter());
else if(align == Fw::AlignLeftCenter)
moveCenterLeft(r.centerLeft());
else if(align == Fw::AlignCenter)
moveCenter(r.center());
else if(align == Fw::AlignRightCenter)
moveCenterRight(r.centerRight());
}
TRect<T>& operator=(const TRect<T>& other) { x1 = other.x1; y1 = other.y1; x2 = other.x2; y2 = other.y2; return *this; } TRect<T>& operator=(const TRect<T>& other) { x1 = other.x1; y1 = other.y1; x2 = other.x2; y2 = other.y2; return *this; }
bool operator==(const TRect<T>& other) const { return (x1 == other.x1 && y1 == other.y1 && x2 == other.x2 && y2 == other.y2); } bool operator==(const TRect<T>& other) const { return (x1 == other.x1 && y1 == other.y1 && x2 == other.x2 && y2 == other.y2); }
bool operator!=(const TRect<T>& other) const { return (x1 != other.x1 || y1 != other.y1 || x2 != other.x2 || y2 != other.y2); } bool operator!=(const TRect<T>& other) const { return (x1 != other.x1 || y1 != other.y1 || x2 != other.x2 || y2 != other.y2); }