UIWidgetList UIWidget::recursiveGetChildren() { UIWidgetList children; for(const UIWidgetPtr& child : m_children) { UIWidgetList subChildren = child->recursiveGetChildren(); if(!subChildren.empty()) children.insert(children.end(), subChildren.begin(), subChildren.end()); children.push_back(child); } return children; }
UIWidgetList UIWidget::recursiveGetChildrenByMarginPos(const Point& childPos) { UIWidgetList children; if(!containsPaddingPoint(childPos)) return children; for(auto it = m_children.rbegin(); it != m_children.rend(); ++it) { const UIWidgetPtr& child = (*it); if(child->isExplicitlyVisible() && child->containsMarginPoint(childPos)) { UIWidgetList subChildren = child->recursiveGetChildrenByMarginPos(childPos); if(!subChildren.empty()) children.insert(children.end(), subChildren.begin(), subChildren.end()); children.push_back(child); } } return children; }
void UIManager::inputEvent(const InputEvent& event) { UIWidgetList widgetList; switch(event.type) { case Fw::KeyTextInputEvent: m_keyboardReceiver->propagateOnKeyText(event.keyText); break; case Fw::KeyDownInputEvent: m_keyboardReceiver->propagateOnKeyDown(event.keyCode, event.keyboardModifiers); break; case Fw::KeyPressInputEvent: m_keyboardReceiver->propagateOnKeyPress(event.keyCode, event.keyboardModifiers, event.autoRepeatTicks); break; case Fw::KeyUpInputEvent: m_keyboardReceiver->propagateOnKeyUp(event.keyCode, event.keyboardModifiers); break; case Fw::MousePressInputEvent: if(event.mouseButton == Fw::MouseLeftButton && m_mouseReceiver->isVisible()) { UIWidgetPtr pressedWidget = m_mouseReceiver->recursiveGetChildByPos(event.mousePos, false); if(pressedWidget && !pressedWidget->isEnabled()) pressedWidget = nullptr; updatePressedWidget(pressedWidget, event.mousePos); } m_mouseReceiver->propagateOnMouseEvent(event.mousePos, widgetList); for(const UIWidgetPtr& widget : widgetList) { widget->recursiveFocus(Fw::MouseFocusReason); if(widget->onMousePress(event.mousePos, event.mouseButton)) break; } break; case Fw::MouseReleaseInputEvent: { // release dragging widget bool accepted = false; if(m_draggingWidget && event.mouseButton == Fw::MouseLeftButton) accepted = updateDraggingWidget(nullptr, event.mousePos); if(!accepted) { m_mouseReceiver->propagateOnMouseEvent(event.mousePos, widgetList); // mouse release is always fired first on the pressed widget if(m_pressedWidget) { auto it = std::find(widgetList.begin(), widgetList.end(), m_pressedWidget); if(it != widgetList.end()) widgetList.erase(it); widgetList.push_front(m_pressedWidget); } for(const UIWidgetPtr& widget : widgetList) { if(widget->onMouseRelease(event.mousePos, event.mouseButton)) break; } } if(m_pressedWidget && event.mouseButton == Fw::MouseLeftButton) updatePressedWidget(nullptr, event.mousePos, !accepted); break; } case Fw::MouseMoveInputEvent: { // start dragging when moving a pressed widget if(m_pressedWidget && m_pressedWidget->isDraggable() && m_draggingWidget != m_pressedWidget) { // only drags when moving more than 4 pixels if((event.mousePos - m_pressedWidget->getLastClickPosition()).length() >= 4) updateDraggingWidget(m_pressedWidget, event.mousePos - event.mouseMoved); } // mouse move can change hovered widgets updateHoveredWidget(true); // first fire dragging move if(m_draggingWidget) { if(m_draggingWidget->onDragMove(event.mousePos, event.mouseMoved)) break; } m_mouseReceiver->propagateOnMouseMove(event.mousePos, event.mouseMoved, widgetList); for(const UIWidgetPtr& widget : widgetList) { if(widget->onMouseMove(event.mousePos, event.mouseMoved)) break; } break; } case Fw::MouseWheelInputEvent: m_rootWidget->propagateOnMouseEvent(event.mousePos, widgetList); for(const UIWidgetPtr& widget : widgetList) { if(widget->onMouseWheel(event.mousePos, event.wheelDirection)) break; } break; default: break; }; }
bool UIHorizontalLayout::internalUpdate() { UIWidgetPtr parentWidget = getParentWidget(); if(!parentWidget) return false; UIWidgetList widgets = parentWidget->getChildren(); if(m_alignRight) std::reverse(widgets.begin(), widgets.end()); bool changed = false; Rect paddingRect = parentWidget->getPaddingRect(); Point pos = (m_alignRight) ? paddingRect.topRight() : paddingRect.topLeft(); int preferredWidth = 0; int gap; for(const UIWidgetPtr& widget : widgets) { if(!widget->isExplicitlyVisible()) continue; Size size = widget->getSize(); gap = (m_alignRight) ? -(widget->getMarginRight()+widget->getWidth()) : widget->getMarginLeft(); pos.x += gap; preferredWidth += gap; if(widget->isFixedSize()) { if(widget->getTextAlign() & Fw::AlignTop) { pos.y = paddingRect.top() + widget->getMarginTop(); } else if(widget->getTextAlign() & Fw::AlignBottom) { pos.y = paddingRect.bottom() - widget->getHeight() - widget->getMarginBottom(); pos.y = std::max<int>(pos.y, paddingRect.top()); } else { // center it pos.y = paddingRect.top() + (paddingRect.height() - (widget->getMarginTop() + widget->getHeight() + widget->getMarginBottom()))/2; pos.y = std::max<int>(pos.y, paddingRect.top()); } } else { // expand height size.setHeight(paddingRect.height() - (widget->getMarginTop() + widget->getMarginBottom())); pos.y = paddingRect.top() + (paddingRect.height() - size.height())/2; } if(widget->setRect(Rect(pos - parentWidget->getVirtualOffset(), size))) changed = true; gap = (m_alignRight) ? -widget->getMarginLeft() : (widget->getWidth() + widget->getMarginRight()); gap += m_spacing; pos.x += gap; preferredWidth += gap; } preferredWidth -= m_spacing; preferredWidth += parentWidget->getPaddingLeft() + parentWidget->getPaddingRight(); if(m_fitChildren && preferredWidth != parentWidget->getWidth()) { // must set the preferred width later g_dispatcher.addEvent([=] { parentWidget->setWidth(preferredWidth); }); } return changed; }