diff --git a/src/framework/const.h b/src/framework/const.h index fc14c88b..a6c20f80 100644 --- a/src/framework/const.h +++ b/src/framework/const.h @@ -266,11 +266,10 @@ namespace Fw DisabledState = 16, CheckedState = 32, OnState = 64, - LastState = 128 - //FirstState, - //MiddleState, - //LastState, - //AlternateState + FirstState = 128, + MiddleState = 256, + AlternateState = 512, + LastState = 1024, }; enum AppicationFlags { diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index d7f0ae90..3a8a5f37 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -83,6 +83,10 @@ void Application::registerLuaFunctions() g_lua.bindClassMemberFunction("isFocused", &UIWidget::isFocused); g_lua.bindClassMemberFunction("isHovered", &UIWidget::isHovered); g_lua.bindClassMemberFunction("isPressed", &UIWidget::isPressed); + g_lua.bindClassMemberFunction("isFirst", &UIWidget::isFirst); + g_lua.bindClassMemberFunction("isMiddle", &UIWidget::isMiddle); + g_lua.bindClassMemberFunction("isLast", &UIWidget::isLast); + g_lua.bindClassMemberFunction("isAlternate", &UIWidget::isAlternate); g_lua.bindClassMemberFunction("isVisible", &UIWidget::isVisible); g_lua.bindClassMemberFunction("isHidden", &UIWidget::isHidden); g_lua.bindClassMemberFunction("isExplicitlyEnabled", &UIWidget::isExplicitlyEnabled); @@ -142,11 +146,6 @@ void Application::registerLuaFunctions() g_lua.bindClassMemberFunction("getChildIndex", &UIWidget::getChildIndex); g_lua.bindClassMemberFunction("updateParentLayout", &UIWidget::updateParentLayout); g_lua.bindClassMemberFunction("updateLayout", &UIWidget::updateLayout); - g_lua.bindClassMemberFunction("updateStates", &UIWidget::updateStates); - g_lua.bindClassMemberFunction("updateState", &UIWidget::updateState); - g_lua.bindClassMemberFunction("setState", &UIWidget::setState); - g_lua.bindClassMemberFunction("hasState", &UIWidget::hasState); - g_lua.bindClassMemberFunction("updateStyle", &UIWidget::updateStyle); g_lua.bindClassMemberFunction("applyStyle", &UIWidget::applyStyle); // UILayout diff --git a/src/framework/ui/uitranslator.cpp b/src/framework/ui/uitranslator.cpp index 3d825812..024ae5cd 100644 --- a/src/framework/ui/uitranslator.cpp +++ b/src/framework/ui/uitranslator.cpp @@ -70,7 +70,7 @@ Fw::AnchorEdge Fw::translateAnchorEdge(std::string anchorEdge) Fw::WidgetState Fw::translateState(std::string state) { boost::to_lower(state); - boost::erase_all(state, " "); + boost::trim(state); if(state == "active") return Fw::ActiveState; else if(state == "focus") @@ -85,6 +85,14 @@ Fw::WidgetState Fw::translateState(std::string state) return Fw::DisabledState; else if(state == "on") return Fw::OnState; + else if(state == "first") + return Fw::FirstState; + else if(state == "middle") + return Fw::MiddleState; + else if(state == "last") + return Fw::LastState; + else if(state == "alternate") + return Fw::AlternateState; else return Fw::InvalidState; } diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index e5ff3190..f14397dd 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -422,6 +422,7 @@ void UIWidget::addChild(const UIWidgetPtr& child) // update new child states child->updateStates(); + updateChildrenIndexStates(); } void UIWidget::insertChild(int index, const UIWidgetPtr& child) @@ -454,6 +455,7 @@ void UIWidget::insertChild(int index, const UIWidgetPtr& child) // update new child states child->updateStates(); + updateChildrenIndexStates(); } void UIWidget::removeChild(const UIWidgetPtr& child) @@ -481,6 +483,7 @@ void UIWidget::removeChild(const UIWidgetPtr& child) // update child states child->updateStates(); + updateChildrenIndexStates(); if(focusAnother && !m_focusedChild) focusPreviousChild(Fw::ActiveFocusReason); @@ -549,6 +552,7 @@ void UIWidget::moveChildToTop(const UIWidgetPtr& child) assert(it != m_children.end()); m_children.erase(it); m_children.push_back(child); + updateChildrenIndexStates(); } void UIWidget::moveChildToIndex(const UIWidgetPtr& child, int index) @@ -561,6 +565,7 @@ void UIWidget::moveChildToIndex(const UIWidgetPtr& child, int index) assert(it != m_children.end()); m_children.erase(it); m_children.insert(m_children.begin() + index - 1, child); + updateChildrenIndexStates(); } void UIWidget::lockChild(const UIWidgetPtr& child) @@ -663,6 +668,16 @@ void UIWidget::updateLayout() m_layout->update(); } +void UIWidget::applyStyle(const OTMLNodePtr& styleNode) +{ + try { + onStyleApply(styleNode); + callLuaField("onStyleApply", styleNode); + } catch(Exception& e) { + logError("Failed to apply style to widget '", m_id, "' style: ", e.what()); + } +} + bool UIWidget::setState(Fw::WidgetState state, bool on) { if(state == Fw::InvalidState) @@ -694,54 +709,76 @@ void UIWidget::updateState(Fw::WidgetState state) bool oldStatus = hasState(state); bool updateChildren = false; - if(state == Fw::ActiveState) { - UIWidgetPtr widget = asUIWidget(); - UIWidgetPtr parent; - do { - parent = widget->getParent(); - if(!widget->isExplicitlyEnabled() || - ((parent && parent->getFocusedChild() != widget))) { - newStatus = false; - break; - } - } while(widget = parent); - - updateChildren = true; - } - else if(state == Fw::FocusState) { - newStatus = (getParent() && getParent()->getFocusedChild() == asUIWidget()); - } - else if(state == Fw::HoverState) { - updateChildren = true; - Point mousePos = g_window.getMousePos(); - UIWidgetPtr widget = asUIWidget(); - UIWidgetPtr parent; - do { - parent = widget->getParent(); - if(!widget->isExplicitlyEnabled() || !widget->isExplicitlyVisible() || !widget->containsPoint(mousePos) || - (parent && widget != parent->getChildByPos(mousePos))) { - newStatus = false; - break; - } - } while(widget = parent); - } - else if(state == Fw::PressedState) { - newStatus = m_pressed; - } - else if(state == Fw::DisabledState) { - bool enabled = true; - updateChildren = true; - UIWidgetPtr widget = asUIWidget(); - do { - if(!widget->isExplicitlyEnabled()) { - enabled = false; - break; - } - } while(widget = widget->getParent()); - newStatus = !enabled; - } - else { - return; + switch(state) { + case Fw::ActiveState: { + UIWidgetPtr widget = asUIWidget(); + UIWidgetPtr parent; + do { + parent = widget->getParent(); + if(!widget->isExplicitlyEnabled() || + ((parent && parent->getFocusedChild() != widget))) { + newStatus = false; + break; + } + } while(widget = parent); + + updateChildren = true; + break; + } + case Fw::FocusState: { + newStatus = (getParent() && getParent()->getFocusedChild() == asUIWidget()); + break; + } + case Fw::HoverState: { + updateChildren = true; + Point mousePos = g_window.getMousePos(); + UIWidgetPtr widget = asUIWidget(); + UIWidgetPtr parent; + do { + parent = widget->getParent(); + if(!widget->isExplicitlyEnabled() || !widget->isExplicitlyVisible() || !widget->containsPoint(mousePos) || + (parent && widget != parent->getChildByPos(mousePos))) { + newStatus = false; + break; + } + } while(widget = parent); + break; + } + case Fw::PressedState: { + newStatus = m_pressed; + break; + } + case Fw::DisabledState: { + bool enabled = true; + updateChildren = true; + UIWidgetPtr widget = asUIWidget(); + do { + if(!widget->isExplicitlyEnabled()) { + enabled = false; + break; + } + } while(widget = widget->getParent()); + newStatus = !enabled; + break; + } + case Fw::FirstState: { + newStatus = (getParent() && getParent()->getFirstChild() == asUIWidget()); + break; + } + case Fw::MiddleState: { + newStatus = (getParent() && getParent()->getFirstChild() != asUIWidget() && getParent()->getLastChild() != asUIWidget()); + break; + } + case Fw::LastState: { + newStatus = (getParent() && getParent()->getLastChild() == asUIWidget()); + break; + } + case Fw::AlternateState: { + newStatus = (getParent() && (getParent()->getChildIndex(asUIWidget()) % 2) == 1); + break; + } + default: + return; } if(updateChildren) { @@ -765,6 +802,16 @@ void UIWidget::updateStates() updateState((Fw::WidgetState)state); } +void UIWidget::updateChildrenIndexStates() +{ + for(const UIWidgetPtr& child : m_children) { + child->updateState(Fw::FirstState); + child->updateState(Fw::MiddleState); + child->updateState(Fw::LastState); + child->updateState(Fw::AlternateState); + } +} + void UIWidget::updateStyle() { if(!m_style) @@ -814,16 +861,6 @@ void UIWidget::updateStyle() m_stateStyle = newStateStyle; } -void UIWidget::applyStyle(const OTMLNodePtr& styleNode) -{ - try { - onStyleApply(styleNode); - callLuaField("onStyleApply", styleNode); - } catch(Exception& e) { - logError("Failed to apply style to widget '", m_id, "' style: ", e.what()); - } -} - void UIWidget::onStyleApply(const OTMLNodePtr& styleNode) { // first set id diff --git a/src/framework/ui/uiwidget.h b/src/framework/ui/uiwidget.h index d4cc395d..8e1b1df0 100644 --- a/src/framework/ui/uiwidget.h +++ b/src/framework/ui/uiwidget.h @@ -84,49 +84,53 @@ public: void grabKeyboard(); void ungrabKeyboard(); - bool isActive() { return hasState(Fw::ActiveState); } - bool isEnabled() { return !hasState(Fw::DisabledState); } - bool isDisabled() { return hasState(Fw::DisabledState); } - bool isFocused() { return hasState(Fw::FocusState); } - bool isHovered() { return hasState(Fw::HoverState); } - bool isPressed() { return hasState(Fw::PressedState); } + bool isActive() { return hasState(Fw::ActiveState); } + bool isEnabled() { return !hasState(Fw::DisabledState); } + bool isDisabled() { return hasState(Fw::DisabledState); } + bool isFocused() { return hasState(Fw::FocusState); } + bool isHovered() { return hasState(Fw::HoverState); } + bool isPressed() { return hasState(Fw::PressedState); } + bool isFirst() { return hasState(Fw::FirstState); } + bool isMiddle() { return hasState(Fw::MiddleState); } + bool isLast() { return hasState(Fw::LastState); } + bool isAlternate() { return hasState(Fw::AlternateState); } bool isVisible(); bool isHidden() { return !isVisible(); } - bool isExplicitlyEnabled() { return m_enabled; } - bool isExplicitlyVisible() { return m_visible; } - bool isFocusable() { return m_focusable; } - bool isPhantom() { return m_phantom; } - bool isSizeFixed() { return m_fixedSize; } + bool isExplicitlyEnabled() { return m_enabled; } + bool isExplicitlyVisible() { return m_visible; } + bool isFocusable() { return m_focusable; } + bool isPhantom() { return m_phantom; } + bool isSizeFixed() { return m_fixedSize; } bool containsPoint(const Point& point) { return m_rect.contains(point); } - bool hasChildren() { return m_children.size() > 0; } + bool hasChildren() { return m_children.size() > 0; } bool hasChild(const UIWidgetPtr& child); - std::string getId() { return m_id; } - int getChildCount() { return m_children.size(); } - UILayoutPtr getLayout() { return m_layout; } - UIWidgetPtr getParent() { return m_parent.lock(); } + std::string getId() { return m_id; } + int getChildCount() { return m_children.size(); } + UILayoutPtr getLayout() { return m_layout; } + UIWidgetPtr getParent() { return m_parent.lock(); } UIWidgetPtr getRootParent(); - Point getPosition() { return m_rect.topLeft(); } - Size getSize() { return m_rect.size(); } - Rect getRect() { return m_rect; } - int getX() { return m_rect.x(); } - int getY() { return m_rect.y(); } - int getWidth() { return m_rect.width(); } - int getHeight() { return m_rect.height(); } - ImagePtr getImage() { return m_image; } - FontPtr getFont() { return m_font; } - Color getForegroundColor() { return m_foregroundColor; } - Color getBackgroundColor() { return m_backgroundColor; } - int getOpacity() { return m_opacity; } - int getMarginTop() { return m_marginTop; } - int getMarginRight() { return m_marginRight; } - int getMarginBottom() { return m_marginBottom; } - int getMarginLeft() { return m_marginLeft; } - Fw::FocusReason getLastFocusReason() { return m_lastFocusReason; } - OTMLNodePtr getStyle() { return m_style; } - - UIWidgetList getChildren() { return m_children; } - UIWidgetPtr getFocusedChild() { return m_focusedChild; } + Point getPosition() { return m_rect.topLeft(); } + Size getSize() { return m_rect.size(); } + Rect getRect() { return m_rect; } + int getX() { return m_rect.x(); } + int getY() { return m_rect.y(); } + int getWidth() { return m_rect.width(); } + int getHeight() { return m_rect.height(); } + ImagePtr getImage() { return m_image; } + FontPtr getFont() { return m_font; } + Color getForegroundColor() { return m_foregroundColor; } + Color getBackgroundColor() { return m_backgroundColor; } + int getOpacity() { return m_opacity; } + int getMarginTop() { return m_marginTop; } + int getMarginRight() { return m_marginRight; } + int getMarginBottom() { return m_marginBottom; } + int getMarginLeft() { return m_marginLeft; } + Fw::FocusReason getLastFocusReason() { return m_lastFocusReason; } + OTMLNodePtr getStyle() { return m_style; } + + UIWidgetList getChildren() { return m_children; } + UIWidgetPtr getFocusedChild() { return m_focusedChild; } UIWidgetPtr getChildAfter(const UIWidgetPtr& relativeChild); UIWidgetPtr getChildBefore(const UIWidgetPtr& relativeChild); UIWidgetPtr getChildById(const std::string& childId); @@ -153,16 +157,20 @@ public: void updateParentLayout(); void updateLayout(); + void applyStyle(const OTMLNodePtr& styleNode); - void updateStates(); - virtual void updateState(Fw::WidgetState state); + UIWidgetPtr asUIWidget() { return std::static_pointer_cast(shared_from_this()); } + +protected: bool setState(Fw::WidgetState state, bool on); bool hasState(Fw::WidgetState state); - void updateStyle(); - void applyStyle(const OTMLNodePtr& styleNode); +private: + void updateState(Fw::WidgetState state); + void updateStates(); + void updateChildrenIndexStates(); - UIWidgetPtr asUIWidget() { return std::static_pointer_cast(shared_from_this()); } + void updateStyle(); protected: /// Triggered when widget style is changed