void Layer::removedWidget(Widget& widget) { if (activeWidget) { if (activeWidget == &widget || activeWidget->isChildOf(widget)) setActiveWidget(widget.parent); } if (hoveredWidget) { if (hoveredWidget == &widget || hoveredWidget->isChildOf(widget)) updateHoveredWidget(); } if (captureWidget) { if (captureWidget == &widget || captureWidget->isChildOf(widget)) releaseCursor(); } if (dragging) { if (draggedWidget) { if (draggedWidget == &widget || draggedWidget->isChildOf(widget)) cancelDragging(); } } }
void Layer::releaseCursor() { if (captureWidget) { captureWidget = NULL; window.releaseCursor(); updateHoveredWidget(); } }
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 }
void Layer::onCursorMoved(const ivec2& position) { updateHoveredWidget(); vec2 cursorPosition = vec2(window.getCursorPosition()); cursorPosition.y = window.getHeight() - cursorPosition.y; if (hoveredWidget) hoveredWidget->cursorMovedSignal(*hoveredWidget, cursorPosition); if (draggedWidget) { if (dragging) draggedWidget->dragMovedSignal(*draggedWidget, cursorPosition); else { // TODO: Add insensitivity radius. dragging = true; draggedWidget->dragBegunSignal(*draggedWidget, cursorPosition); } } }
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; }; }
void UIManager::onWidgetDisappear(const UIWidgetPtr& widget) { if(widget->containsPoint(g_window.getMousePosition())) updateHoveredWidget(); }