Many UI improvements and minor fixes
This commit is contained in:
parent
a8d3bb97ea
commit
5344a179a4
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
|
|
@ -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); }
|
||||||
|
|
Loading…
Reference in New Issue