void UIWidget::destroy() { if(m_destroyed) logWarning("attempt to destroy widget '", m_id, "' two times"); setVisible(false); setEnabled(false); // release input grabs if(g_ui.getKeyboardReceiver() == asUIWidget()) g_ui.resetKeyboardReceiver(); if(g_ui.getMouseReceiver() == asUIWidget()) g_ui.resetMouseReceiver(); // remove itself from parent if(UIWidgetPtr parent = getParent()) { if(parent->hasChild(asUIWidget())) parent->removeChild(asUIWidget()); } callLuaField("onDestroy"); m_destroyed = true; }
void UIWidget::insertChild(int index, const UIWidgetPtr& child) { if(!child) { logWarning("attempt to insert a null child into a UIWidget"); return; } if(hasChild(child)) { logWarning("attempt to insert a child again into a UIWidget"); return; } index = index <= 0 ? (m_children.size() + index) : index-1; assert(index >= 0 && (uint)index <= m_children.size()); // retrieve child by index auto it = m_children.begin() + index; m_children.insert(it, child); child->setParent(asUIWidget()); // create default layout if needed if(!m_layout) m_layout = UIAnchorLayoutPtr(new UIAnchorLayout(asUIWidget())); // add to layout and updates it m_layout->addWidget(child); // update new child states child->updateStates(); updateChildrenIndexStates(); }
void UIWidget::addChild(const UIWidgetPtr& child) { if(!child) { logWarning("attempt to add a null child into a UIWidget"); return; } if(hasChild(child)) { logWarning("attempt to add a child again into a UIWidget"); return; } m_children.push_back(child); child->setParent(asUIWidget()); // create default layout if(!m_layout) m_layout = UIAnchorLayoutPtr(new UIAnchorLayout(asUIWidget())); // add to layout and updates it m_layout->addWidget(child); // update new child states child->updateStates(); updateChildrenIndexStates(); }
void UIWidget::centerIn(const std::string& hookedWidgetId) { if(UIAnchorLayoutPtr anchorLayout = getAnchoredLayout()) { anchorLayout->addAnchor(asUIWidget(), Fw::AnchorHorizontalCenter, hookedWidgetId, Fw::AnchorHorizontalCenter); anchorLayout->addAnchor(asUIWidget(), Fw::AnchorVerticalCenter, hookedWidgetId, Fw::AnchorVerticalCenter); } else logError("cannot add anchors to widget ", m_id, ": the parent doesn't use anchors layout"); }
void UIWidget::setDragging(bool dragging) { if(dragging) { g_ui.setDraggingWidget(asUIWidget()); } else { if(g_ui.getDraggingWidget() == asUIWidget()) g_ui.setDraggingWidget(nullptr); } m_dragging = dragging; }
void UIWidget::fill(const std::string& hookedWidgetId) { if(UIAnchorLayoutPtr anchorLayout = getAnchoredLayout()) { anchorLayout->addAnchor(asUIWidget(), Fw::AnchorLeft, hookedWidgetId, Fw::AnchorLeft); anchorLayout->addAnchor(asUIWidget(), Fw::AnchorRight, hookedWidgetId, Fw::AnchorRight); anchorLayout->addAnchor(asUIWidget(), Fw::AnchorTop, hookedWidgetId, Fw::AnchorTop); anchorLayout->addAnchor(asUIWidget(), Fw::AnchorBottom, hookedWidgetId, Fw::AnchorBottom); } else logError("cannot add anchors to widget ", m_id, ": the parent doesn't use anchors layout"); }
bool UIWidget::onMouseRelease(const Point& mousePos, Fw::MouseButton button) { if(isPressed() && getRect().contains(mousePos)) callLuaField("onClick"); UIWidgetPtr draggedWidget = g_ui.getDraggingWidget(); if(draggedWidget && button == Fw::MouseLeftButton && (containsPoint(mousePos) || asUIWidget() == g_ui.getRootWidget())) { onDrop(draggedWidget, mousePos); draggedWidget->onDragLeave(asUIWidget(), mousePos); draggedWidget->setDragging(false); } return callLuaField<bool>("onMouseRelease", mousePos, button); }
void UIWidget::focus() { if(!m_focusable) return; if(UIWidgetPtr parent = getParent()) parent->focusChild(asUIWidget(), Fw::ActiveFocusReason); }
void UIWidget::addAnchor(Fw::AnchorEdge anchoredEdge, const std::string& hookedWidgetId, Fw::AnchorEdge hookedEdge) { if(UIAnchorLayoutPtr anchorLayout = getAnchoredLayout()) anchorLayout->addAnchor(asUIWidget(), anchoredEdge, hookedWidgetId, hookedEdge); else logError("cannot add anchors to widget ", m_id, ": the parent doesn't use anchors layout"); }
bool UIWidget::isAnchored() { if(UIWidgetPtr parent = getParent()) if(UIAnchorLayoutPtr anchorLayout = parent->getAnchoredLayout()) return anchorLayout->hasAnchors(asUIWidget()); return false; }
void UIWidget::grabMouse() { if(m_destroyed) return; g_ui.setMouseReceiver(asUIWidget()); }
void UIWidget::grabKeyboard() { if(m_destroyed) return; g_ui.setKeyboardReceiver(asUIWidget()); }
void UIWidget::setParent(const UIWidgetPtr& parent) { // remove from old parent UIWidgetPtr oldParent = getParent(); // the parent is already the same if(oldParent == parent) return; UIWidgetPtr self = asUIWidget(); if(oldParent && oldParent->hasChild(self)) oldParent->removeChild(self); // reset parent m_parent.reset(); // set new parent if(parent) { m_parent = parent; // add to parent if needed if(!parent->hasChild(self)) parent->addChild(self); } }
bool UIWidget::setRect(const Rect& rect) { if(rect.width() > 8192 || rect.height() > 8192) { logError("attempt to set huge rect size (", rect,") for ", m_id); return false; } // only update if the rect really changed Rect oldRect = m_rect; if(rect == oldRect) return false; m_rect = rect; // updates own layout updateLayout(); // avoid massive update events if(!m_updateEventScheduled) { UIWidgetPtr self = asUIWidget(); g_eventDispatcher.addEvent([self, oldRect]() { self->m_updateEventScheduled = false; if(oldRect != self->getRect()) self->onGeometryChange(oldRect, self->getRect()); }); m_updateEventScheduled = true; } return true; }
UIWidgetPtr UIWidget::getRootParent() { if(UIWidgetPtr parent = getParent()) return parent->getRootParent(); else return asUIWidget(); }
void UIWidget::removeChild(UIWidgetPtr child) { // remove from children list if(hasChild(child)) { // defocus if needed bool focusAnother = false; if(m_focusedChild == child) { focusChild(nullptr, Fw::ActiveFocusReason); focusAnother = true; } if(isChildLocked(child)) unlockChild(child); auto it = std::find(m_children.begin(), m_children.end(), child); m_children.erase(it); // reset child parent assert(child->getParent() == asUIWidget()); child->setParent(nullptr); m_layout->removeWidget(child); // update child states child->updateStates(); updateChildrenIndexStates(); if(focusAnother && !m_focusedChild) focusPreviousChild(Fw::ActiveFocusReason); g_ui.onWidgetDisappear(child); } else logError("attempt to remove an unknown child from a UIWidget"); }
void UIWidget::unlock() { if(m_destroyed) return; if(UIWidgetPtr parent = getParent()) parent->unlockChild(asUIWidget()); }
void UIWidget::breakAnchors() { if(m_destroyed) return; if(UIAnchorLayoutPtr anchorLayout = getAnchoredLayout()) anchorLayout->removeAnchors(asUIWidget()); }
void UIWidget::updateStyle() { if(m_loadingStyle && !m_updateStyleScheduled) { UIWidgetPtr self = asUIWidget(); g_dispatcher.addEvent([self] { self->m_updateStyleScheduled = false; self->updateStyle(); }); m_updateStyleScheduled = true; return; } if(!m_style) return; OTMLNodePtr newStateStyle = OTMLNode::create(); // copy only the changed styles from default style if(m_stateStyle) { for(OTMLNodePtr node : m_stateStyle->children()) { if(OTMLNodePtr otherNode = m_style->get(node->tag())) newStateStyle->addChild(otherNode->clone()); } } // checks for states combination for(const OTMLNodePtr& style : m_style->children()) { if(boost::starts_with(style->tag(), "$")) { std::string statesStr = style->tag().substr(1); std::vector<std::string> statesSplit; boost::split(statesSplit, statesStr, boost::is_any_of(std::string(" "))); bool match = true; for(std::string stateStr : statesSplit) { if(stateStr.length() == 0) continue; bool notstate = (stateStr[0] == '!'); if(notstate) stateStr = stateStr.substr(1); bool stateOn = hasState(Fw::translateState(stateStr)); if((!notstate && !stateOn) || (notstate && stateOn)) match = false; } // merge states styles if(match) { newStateStyle->merge(style); } } } //TODO: prevent setting already set proprieties applyStyle(newStateStyle); m_stateStyle = newStateStyle; }
bool UIWidget::isVisible() { if(!m_visible) return false; else if(UIWidgetPtr parent = getParent()) return parent->isVisible(); else return asUIWidget() == g_ui.getRootWidget(); }
void UIWidget::raise() { if(m_destroyed) return; UIWidgetPtr parent = getParent(); if(parent) parent->raiseChild(asUIWidget()); }
void UIWidget::lower() { if(m_destroyed) return; UIWidgetPtr parent = getParent(); if(parent) parent->lowerChild(asUIWidget()); }
bool UIWidget::onMouseMove(const Point& mousePos, const Point& mouseMoved) { if(isDragable() && isPressed() && !m_dragging && !g_ui.getDraggingWidget()) { setDragging(true); g_ui.setDraggingWidget(asUIWidget()); onDragEnter(mousePos - mouseMoved); } return callLuaField<bool>("onMouseMove", mousePos, mouseMoved); }
bool UIWidget::propagateOnMouseMove(const Point& mousePos, const Point& mouseMoved, UIWidgetList& widgetList) { for(auto it = m_children.begin(); it != m_children.end(); ++it) { const UIWidgetPtr& child = *it; if(child->isExplicitlyVisible() && child->isExplicitlyEnabled()) child->propagateOnMouseMove(mousePos, mouseMoved, widgetList); } widgetList.push_back(asUIWidget()); return true; }
void UIWidget::recursiveFocus(Fw::FocusReason reason) { if(m_destroyed) return; if(UIWidgetPtr parent = getParent()) { if(m_focusable) parent->focusChild(asUIWidget(), reason); parent->recursiveFocus(reason); } }
void UIWidget::addChild(const UIWidgetPtr& child) { if(!child) { logWarning("attempt to add a null child into a UIWidget"); return; } if(child->isDestroyed()) { logWarning("attemp to add a destroyed child into a UIWidget"); return; } if(hasChild(child)) { logWarning("attempt to add a child again into a UIWidget"); return; } UIWidgetPtr oldLastChild = getLastChild(); m_children.push_back(child); child->setParent(asUIWidget()); // create default layout if(!m_layout) m_layout = UIAnchorLayoutPtr(new UIAnchorLayout(asUIWidget())); // add to layout and updates it m_layout->addWidget(child); // update new child states child->updateStates(); // update old child index states if(oldLastChild) { oldLastChild->updateState(Fw::MiddleState); oldLastChild->updateState(Fw::LastState); } g_ui.onWidgetAppear(child); }
void UIWidget::setVisible(bool visible) { if(m_visible != visible) { m_visible = visible; // hiding a widget make it lose focus if(!visible && isFocused()) { if(UIWidgetPtr parent = getParent()) parent->focusPreviousChild(Fw::ActiveFocusReason); } // visibility can change change parent layout updateParentLayout(); updateState(Fw::ActiveState); // visibility can change the current hovered widget if(visible) g_ui.onWidgetAppear(asUIWidget()); else g_ui.onWidgetDisappear(asUIWidget()); } }
void UIWidget::destroy() { if(m_destroyed) logWarning("attempt to destroy widget '", m_id, "' two times"); // hold itself reference UIWidgetPtr self = asUIWidget(); m_destroyed = true; // remove itself from parent if(UIWidgetPtr parent = getParent()) parent->removeChild(self); internalDestroy(); }
void UIWidget::internalDestroy() { m_destroyed = true; m_visible = false; m_enabled = false; m_parent.reset(); m_focusedChild = nullptr; m_layout = nullptr; m_lockedChildren.clear(); for(const UIWidgetPtr& child : m_children) child->internalDestroy(); m_children.clear(); callLuaField("onDestroy"); releaseLuaFieldsTable(); g_ui.onWidgetDestroy(asUIWidget()); }
bool UIWidget::propagateOnMouseEvent(const Point& mousePos, UIWidgetList& widgetList) { bool ret = false; if(containsChildPoint(mousePos)) { for(auto it = m_children.rbegin(); it != m_children.rend(); ++it) { const UIWidgetPtr& child = *it; if(child->isExplicitlyEnabled() && child->isExplicitlyVisible() && child->containsPoint(mousePos)) { if(child->propagateOnMouseEvent(mousePos, widgetList)) { ret = true; break; } } } } widgetList.push_back(asUIWidget()); if(!isPhantom()) ret = true; return ret; }