void UIWidget::moveChildToIndex(const UIWidgetPtr& child, int index) { if(m_destroyed) return; if(!child) return; if((uint)index - 1 > m_children.size()) { g_logger.traceError(stdext::format("moving %s to index %d on %s", child->getId(), index, m_id)); return; } // remove and push child again auto it = std::find(m_children.begin(), m_children.end(), child); if(it == m_children.end()) { g_logger.traceError("cannot find child"); return; } m_children.erase(it); m_children.insert(m_children.begin() + index - 1, child); updateChildrenIndexStates(); updateLayout(); }
bool UIAnchorLayout::updateWidget(const UIWidgetPtr& widget, UIAnchorGroup& anchorGroup, UIWidgetPtr first) { UIWidgetPtr parentWidget = getParentWidget(); if(!parentWidget) return false; if(first == widget) { g_logger.error(stdext::format("child '%s' of parent widget '%s' is recursively anchored to itself, please fix this", widget->getId(), parentWidget->getId())); return false; } if(!first) first = widget; Rect newRect = widget->getRect(); bool verticalMoved = false; bool horizontalMoved = false; // calculates new rect based on anchors for(const UIAnchor& anchor : anchorGroup.getAnchors()) { // skip invalid anchors if(anchor.getHookedEdge() == Fw::AnchorNone) continue; // determine hooked widget UIWidgetPtr hookedWidget; if(parentWidget) { if(anchor.getHookedWidgetId() == "parent") hookedWidget = parentWidget; else if(anchor.getHookedWidgetId() == "next") hookedWidget = parentWidget->getChildAfter(widget); else if(anchor.getHookedWidgetId() == "prev") hookedWidget = parentWidget->getChildBefore(widget); else hookedWidget = parentWidget->getChildById(anchor.getHookedWidgetId()); } // skip invalid anchors if(!hookedWidget) continue; if(hookedWidget != getParentWidget()) { // update this hooked widget anchors auto it = m_anchorsGroups.find(hookedWidget); if(it != m_anchorsGroups.end()) { UIAnchorGroup& hookedAnchorGroup = it->second; if(!hookedAnchorGroup.isUpdated()) updateWidget(hookedWidget, hookedAnchorGroup, first); } } // determine hooked widget edge point Rect hookedWidgetRect = hookedWidget->getRect(); if(hookedWidget == parentWidget) hookedWidgetRect = parentWidget->getPaddingRect(); int point = 0; switch(anchor.getHookedEdge()) { case Fw::AnchorLeft: point = hookedWidgetRect.left(); break; case Fw::AnchorRight: point = hookedWidgetRect.right(); break; case Fw::AnchorTop: point = hookedWidgetRect.top(); break; case Fw::AnchorBottom: point = hookedWidgetRect.bottom(); break; case Fw::AnchorHorizontalCenter: point = hookedWidgetRect.horizontalCenter(); break; case Fw::AnchorVerticalCenter: point = hookedWidgetRect.verticalCenter(); break; default: // must never happens assert(false); break; } if(hookedWidget == parentWidget) { switch(anchor.getHookedEdge()) { case Fw::AnchorLeft: case Fw::AnchorRight: case Fw::AnchorHorizontalCenter: point -= parentWidget->getVirtualOffset().x; break; case Fw::AnchorBottom: case Fw::AnchorTop: case Fw::AnchorVerticalCenter: point -= parentWidget->getVirtualOffset().y; break; default: break; } } switch(anchor.getAnchoredEdge()) { case Fw::AnchorHorizontalCenter: newRect.moveHorizontalCenter(point + widget->getMarginLeft() - widget->getMarginRight()); horizontalMoved = true; break; case Fw::AnchorLeft: if(!horizontalMoved) { newRect.moveLeft(point + widget->getMarginLeft()); horizontalMoved = true; } else newRect.setLeft(point + widget->getMarginLeft()); break; case Fw::AnchorRight: if(!horizontalMoved) { newRect.moveRight(point - widget->getMarginRight()); horizontalMoved = true; } else newRect.setRight(point - widget->getMarginRight()); break; case Fw::AnchorVerticalCenter: newRect.moveVerticalCenter(point + widget->getMarginTop() - widget->getMarginBottom()); verticalMoved = true; break; case Fw::AnchorTop: if(!verticalMoved) { newRect.moveTop(point + widget->getMarginTop()); verticalMoved = true; } else newRect.setTop(point + widget->getMarginTop()); break; case Fw::AnchorBottom: if(!verticalMoved) { newRect.moveBottom(point - widget->getMarginBottom()); verticalMoved = true; } else newRect.setBottom(point - widget->getMarginBottom()); break; default: break; } } bool changed = false; if(widget->setRect(newRect)) changed = true; anchorGroup.setUpdated(true); return changed; }
void UIManager::onWidgetDestroy(const UIWidgetPtr& widget) { // release input grabs if(m_keyboardReceiver == widget) resetKeyboardReceiver(); if(m_mouseReceiver == widget) resetMouseReceiver(); if(m_hoveredWidget == widget) updateHoveredWidget(); if(m_pressedWidget == widget) updatePressedWidget(nullptr); if(m_draggingWidget == widget) updateDraggingWidget(nullptr); #ifndef NDEBUG if(widget == m_rootWidget || !m_rootWidget) return; m_destroyedWidgets.push_back(widget); if(m_checkEvent && !m_checkEvent->isExecuted()) return; m_checkEvent = g_dispatcher.scheduleEvent([this] { g_lua.collectGarbage(); UIWidgetList backupList = m_destroyedWidgets; m_destroyedWidgets.clear(); g_dispatcher.scheduleEvent([backupList] { g_lua.collectGarbage(); for(const UIWidgetPtr& widget : backupList) { if(widget->ref_count() != 1) g_logger.warning(stdext::format("widget '%s' destroyed but still have %d reference(s) left", widget->getId(), widget->getUseCount()-1)); } }, 1); }, 1000); #endif }
bool UIAnchorLayout::updateWidget(const UIWidgetPtr& widget, const UIAnchorGroupPtr& anchorGroup, UIWidgetPtr first) { UIWidgetPtr parentWidget = getParentWidget(); if(!parentWidget) return false; if(first == widget) { g_logger.error(stdext::format("child '%s' of parent widget '%s' is recursively anchored to itself, please fix this", widget->getId(), parentWidget->getId())); return false; } if(!first) first = widget; Rect newRect = widget->getRect(); bool verticalMoved = false; bool horizontalMoved = false; // calculates new rect based on anchors for(const UIAnchorPtr& anchor : anchorGroup->getAnchors()) { // skip invalid anchors if(anchor->getHookedEdge() == Fw::AnchorNone) continue; // determine hooked widget UIWidgetPtr hookedWidget = anchor->getHookedWidget(widget, parentWidget); // skip invalid anchors if(!hookedWidget) continue; if(hookedWidget != getParentWidget()) { // update this hooked widget anchors auto it = m_anchorsGroups.find(hookedWidget); if(it != m_anchorsGroups.end()) { const UIAnchorGroupPtr& hookedAnchorGroup = it->second; if(!hookedAnchorGroup->isUpdated()) updateWidget(hookedWidget, hookedAnchorGroup, first); } } int point = anchor->getHookedPoint(hookedWidget, parentWidget); switch(anchor->getAnchoredEdge()) { case Fw::AnchorHorizontalCenter: newRect.moveHorizontalCenter(point + widget->getMarginLeft() - widget->getMarginRight()); horizontalMoved = true; break; case Fw::AnchorLeft: if(!horizontalMoved) { newRect.moveLeft(point + widget->getMarginLeft()); horizontalMoved = true; } else newRect.setLeft(point + widget->getMarginLeft()); break; case Fw::AnchorRight: if(!horizontalMoved) { newRect.moveRight(point - widget->getMarginRight()); horizontalMoved = true; } else newRect.setRight(point - widget->getMarginRight()); break; case Fw::AnchorVerticalCenter: newRect.moveVerticalCenter(point + widget->getMarginTop() - widget->getMarginBottom()); verticalMoved = true; break; case Fw::AnchorTop: if(!verticalMoved) { newRect.moveTop(point + widget->getMarginTop()); verticalMoved = true; } else newRect.setTop(point + widget->getMarginTop()); break; case Fw::AnchorBottom: if(!verticalMoved) { newRect.moveBottom(point - widget->getMarginBottom()); verticalMoved = true; } else newRect.setBottom(point - widget->getMarginBottom()); break; default: break; } } bool changed = false; if(widget->setRect(newRect)) changed = true; anchorGroup->setUpdated(true); return changed; }