drag fixes

This commit is contained in:
Eduardo Bart 2012-02-09 16:38:50 -02:00
parent 1145eb7e42
commit 96358b317d
7 changed files with 82 additions and 123 deletions

View File

@ -2,7 +2,7 @@ function UIItem:onDragEnter(mousePos)
if self:isVirtual() then return false end if self:isVirtual() then return false end
local item = self:getItem() local item = self:getItem()
if not item then return true end if not item then return false end
self:setBorderWidth(1) self:setBorderWidth(1)

View File

@ -24,6 +24,7 @@ function UIMiniWindow:onDragEnter(mousePos)
local oldPos = self:getPosition() local oldPos = self:getPosition()
self.movingReference = { x = mousePos.x - oldPos.x, y = mousePos.y - oldPos.y } self.movingReference = { x = mousePos.x - oldPos.x, y = mousePos.y - oldPos.y }
self:setPosition(oldPos) self:setPosition(oldPos)
return true
end end
function UIMiniWindow:onDragLeave(droppedWidget, mousePos) function UIMiniWindow:onDragLeave(droppedWidget, mousePos)

View File

@ -25,6 +25,7 @@ end
function UIWindow:onDragEnter(mousePos) function UIWindow:onDragEnter(mousePos)
self:breakAnchors() self:breakAnchors()
self.movingReference = { x = mousePos.x - self:getX(), y = mousePos.y - self:getY() } self.movingReference = { x = mousePos.x - self:getX(), y = mousePos.y - self:getY() }
return true
end end
function UIWindow:onDragLeave(droppedWidget, mousePos) function UIWindow:onDragLeave(droppedWidget, mousePos)

View File

@ -26,6 +26,7 @@
#include <framework/otml/otml.h> #include <framework/otml/otml.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/platform/platformwindow.h> #include <framework/platform/platformwindow.h>
#include <framework/core/eventdispatcher.h>
UIManager g_ui; UIManager g_ui;
@ -78,8 +79,12 @@ void UIManager::inputEvent(const InputEvent& event)
break; break;
case Fw::MousePressInputEvent: case Fw::MousePressInputEvent:
m_mouseReceiver->propagateOnMousePress(event.mousePos, event.mouseButton); m_mouseReceiver->propagateOnMousePress(event.mousePos, event.mouseButton);
if(event.mouseButton == Fw::MouseLeftButton) if(event.mouseButton == Fw::MouseLeftButton && m_mouseReceiver->isVisible()) {
updatePressedWidget(m_mouseReceiver->recursiveGetChildByPos(event.mousePos), event.mousePos); UIWidgetPtr pressedWidget = m_mouseReceiver->recursiveGetChildByPos(event.mousePos);
if(pressedWidget && !pressedWidget->isEnabled())
pressedWidget = nullptr;
updatePressedWidget(pressedWidget, event.mousePos);
}
break; break;
case Fw::MouseReleaseInputEvent: case Fw::MouseReleaseInputEvent:
m_mouseReceiver->propagateOnMouseRelease(event.mousePos, event.mouseButton); m_mouseReceiver->propagateOnMouseRelease(event.mousePos, event.mouseButton);
@ -123,74 +128,80 @@ void UIManager::updatePressedWidget(const UIWidgetPtr& newPressedWidget, const P
if(oldPressedWidget) { if(oldPressedWidget) {
oldPressedWidget->updateState(Fw::PressedState); oldPressedWidget->updateState(Fw::PressedState);
// when releasing mouse inside pressed widget area send onClick event if(oldPressedWidget->isEnabled()) {
if(!clickedPos.isNull() && oldPressedWidget->containsPoint(clickedPos)) // when releasing mouse inside pressed widget area send onClick event
oldPressedWidget->onClick(clickedPos); if(!clickedPos.isNull() && oldPressedWidget->containsPoint(clickedPos)) {
// must send mouse events even if the mouse is outside widget area when releasing a pressed widget // onMouseRelease will be already fired by mouseReceiver
else oldPressedWidget->onClick(clickedPos);
oldPressedWidget->onMouseRelease(clickedPos, Fw::MouseLeftButton); // must send mouse events even if the mouse is outside widget area when releasing a pressed widget
} else
oldPressedWidget->onMouseRelease(clickedPos, Fw::MouseLeftButton);
}
} }
} }
void UIManager::updateHoveredWidget() void UIManager::updateHoveredWidget()
{ {
UIWidgetPtr hoveredWidget = m_rootWidget->recursiveGetChildByPos(g_window.getMousePosition()); if(m_hoverUpdateScheduled)
if(hoveredWidget != m_hoveredWidget) { return;
UIWidgetPtr oldHovered = m_hoveredWidget;
m_hoveredWidget = hoveredWidget; g_dispatcher.addEvent([this] {
if(oldHovered) if(!m_rootWidget)
oldHovered->updateState(Fw::HoverState); return;
if(hoveredWidget)
hoveredWidget->updateState(Fw::HoverState); m_hoverUpdateScheduled = false;
} UIWidgetPtr hoveredWidget = m_rootWidget->recursiveGetChildByPos(g_window.getMousePosition());
if(hoveredWidget && !hoveredWidget->isEnabled())
hoveredWidget = nullptr;
if(hoveredWidget != m_hoveredWidget) {
UIWidgetPtr oldHovered = m_hoveredWidget;
m_hoveredWidget = hoveredWidget;
if(oldHovered)
oldHovered->updateState(Fw::HoverState);
if(hoveredWidget)
hoveredWidget->updateState(Fw::HoverState);
}
});
m_hoverUpdateScheduled = true;
} }
void UIManager::updateDraggingWidget(const UIWidgetPtr& draggingWidget, const Point& clickedPos) void UIManager::updateDraggingWidget(const UIWidgetPtr& draggingWidget, const Point& clickedPos)
{ {
UIWidgetPtr oldDraggingWidget = m_draggingWidget; UIWidgetPtr oldDraggingWidget = m_draggingWidget;
m_draggingWidget = nullptr;
if(oldDraggingWidget) { if(oldDraggingWidget) {
auto clickedChildren = m_rootWidget->recursiveGetChildrenByPos(clickedPos);
UIWidgetPtr droppedWidget; UIWidgetPtr droppedWidget;
for(const UIWidgetPtr& child : clickedChildren) { if(!clickedPos.isNull()) {
if(child->onDrop(oldDraggingWidget, clickedPos)) { auto clickedChildren = m_rootWidget->recursiveGetChildrenByPos(clickedPos);
droppedWidget = child; for(const UIWidgetPtr& child : clickedChildren) {
break; if(child->onDrop(oldDraggingWidget, clickedPos)) {
droppedWidget = child;
break;
}
} }
} }
oldDraggingWidget->onDragLeave(droppedWidget, clickedPos); oldDraggingWidget->onDragLeave(droppedWidget, clickedPos);
oldDraggingWidget->updateState(Fw::DraggingState);
} }
m_draggingWidget = draggingWidget;
if(oldDraggingWidget)
oldDraggingWidget->updateState(Fw::DraggingState);
if(draggingWidget) { if(draggingWidget) {
draggingWidget->updateState(Fw::DraggingState); if(draggingWidget->onDragEnter(clickedPos)) {
draggingWidget->onDragEnter(clickedPos); m_draggingWidget = draggingWidget;
draggingWidget->updateState(Fw::DraggingState);
}
} }
} }
void UIManager::onWidgetAppear(const UIWidgetPtr& widget) void UIManager::onWidgetAppear(const UIWidgetPtr& widget)
{ {
if(widget->getRootParent() != m_rootWidget || !widget->isVisible()) updateHoveredWidget();
return;
if(widget->getRect().contains(g_window.getMousePosition()))
updateHoveredWidget();
} }
void UIManager::onWidgetDisappear(const UIWidgetPtr& widget) void UIManager::onWidgetDisappear(const UIWidgetPtr& widget)
{ {
if(widget->getRootParent() != m_rootWidget || widget->isVisible()) updateHoveredWidget();
return;
if(m_hoveredWidget == widget)
updateHoveredWidget();
if(m_pressedWidget == widget)
updatePressedWidget(nullptr);
} }
void UIManager::onWidgetDestroy(const UIWidgetPtr& widget) void UIManager::onWidgetDestroy(const UIWidgetPtr& widget)
@ -207,6 +218,9 @@ void UIManager::onWidgetDestroy(const UIWidgetPtr& widget)
if(m_pressedWidget == widget) if(m_pressedWidget == widget)
updatePressedWidget(nullptr); updatePressedWidget(nullptr);
if(m_draggingWidget == widget)
updateDraggingWidget(nullptr);
} }
bool UIManager::importStyle(const std::string& file) bool UIManager::importStyle(const std::string& file)

View File

@ -39,7 +39,7 @@ public:
void updatePressedWidget(const UIWidgetPtr& newPressedWidget, const Point& clickedPos = Point()); void updatePressedWidget(const UIWidgetPtr& newPressedWidget, const Point& clickedPos = Point());
void updateHoveredWidget(); void updateHoveredWidget();
void updateDraggingWidget(const UIWidgetPtr& draggingWidget, const Point& clickedPos); void updateDraggingWidget(const UIWidgetPtr& draggingWidget, const Point& clickedPos = Point());
bool importStyle(const std::string& file); bool importStyle(const std::string& file);
void importStyleFromOTML(const OTMLNodePtr& styleNode); void importStyleFromOTML(const OTMLNodePtr& styleNode);
@ -78,6 +78,7 @@ private:
UIWidgetPtr m_draggingWidget; UIWidgetPtr m_draggingWidget;
UIWidgetPtr m_hoveredWidget; UIWidgetPtr m_hoveredWidget;
UIWidgetPtr m_pressedWidget; UIWidgetPtr m_pressedWidget;
Boolean<false> m_hoverUpdateScheduled;
bool m_isOnInputEvent; bool m_isOnInputEvent;
Boolean<false> m_drawDebugBoxes; Boolean<false> m_drawDebugBoxes;
std::map<std::string, OTMLNodePtr> m_styles; std::map<std::string, OTMLNodePtr> m_styles;

View File

@ -571,9 +571,6 @@ void UIWidget::grabMouse()
void UIWidget::ungrabMouse() void UIWidget::ungrabMouse()
{ {
if(m_destroyed)
return;
if(g_ui.getMouseReceiver() == asUIWidget()) if(g_ui.getMouseReceiver() == asUIWidget())
g_ui.resetMouseReceiver(); g_ui.resetMouseReceiver();
} }
@ -588,9 +585,6 @@ void UIWidget::grabKeyboard()
void UIWidget::ungrabKeyboard() void UIWidget::ungrabKeyboard()
{ {
if(m_destroyed)
return;
if(g_ui.getKeyboardReceiver() == asUIWidget()) if(g_ui.getKeyboardReceiver() == asUIWidget())
g_ui.resetKeyboardReceiver(); g_ui.resetKeyboardReceiver();
} }
@ -756,6 +750,7 @@ void UIWidget::setEnabled(bool enabled)
updateState(Fw::DisabledState); updateState(Fw::DisabledState);
updateState(Fw::ActiveState); updateState(Fw::ActiveState);
updateState(Fw::HoverState);
} }
} }
@ -764,12 +759,6 @@ void UIWidget::setVisible(bool visible)
if(m_visible != visible) { if(m_visible != visible) {
m_visible = visible; m_visible = visible;
// visibility can change the current hovered widget
if(visible)
g_ui.onWidgetAppear(asUIWidget());
else
g_ui.onWidgetDisappear(asUIWidget());
// hiding a widget make it lose focus // hiding a widget make it lose focus
if(!visible && isFocused()) { if(!visible && isFocused()) {
if(UIWidgetPtr parent = getParent()) if(UIWidgetPtr parent = getParent())
@ -780,6 +769,12 @@ void UIWidget::setVisible(bool visible)
updateParentLayout(); updateParentLayout();
updateState(Fw::ActiveState); updateState(Fw::ActiveState);
// visibility can change the current hovered widget
if(visible)
g_ui.onWidgetAppear(asUIWidget());
else
g_ui.onWidgetDisappear(asUIWidget());
} }
} }
@ -1033,7 +1028,7 @@ void UIWidget::updateState(Fw::WidgetState state)
} }
} while(widget = parent); } while(widget = parent);
updateChildren = true; updateChildren = newStatus != oldStatus;
break; break;
} }
case Fw::FocusState: { case Fw::FocusState: {
@ -1041,7 +1036,8 @@ void UIWidget::updateState(Fw::WidgetState state)
break; break;
} }
case Fw::HoverState: { case Fw::HoverState: {
newStatus = (g_ui.getHoveredWidget() == asUIWidget()); updateChildren = true;
newStatus = (g_ui.getHoveredWidget() == asUIWidget() && isEnabled());
break; break;
} }
case Fw::PressedState: { case Fw::PressedState: {
@ -1054,7 +1050,6 @@ void UIWidget::updateState(Fw::WidgetState state)
} }
case Fw::DisabledState: { case Fw::DisabledState: {
bool enabled = true; bool enabled = true;
updateChildren = true;
UIWidgetPtr widget = asUIWidget(); UIWidgetPtr widget = asUIWidget();
do { do {
if(!widget->isExplicitlyEnabled()) { if(!widget->isExplicitlyEnabled()) {
@ -1063,6 +1058,7 @@ void UIWidget::updateState(Fw::WidgetState state)
} }
} while(widget = widget->getParent()); } while(widget = widget->getParent());
newStatus = !enabled; newStatus = !enabled;
updateChildren = newStatus != oldStatus;
break; break;
} }
case Fw::FirstState: { case Fw::FirstState: {
@ -1085,14 +1081,14 @@ void UIWidget::updateState(Fw::WidgetState state)
return; return;
} }
if(setState(state, newStatus)) { if(updateChildren) {
if(updateChildren) { // do a backup of children list, because it may change while looping it
// do a backup of children list, because it may change while looping it UIWidgetList children = m_children;
UIWidgetList children = m_children; for(const UIWidgetPtr& child : children)
for(const UIWidgetPtr& child : children) child->updateState(state);
child->updateState(state); }
}
if(setState(state, newStatus)) {
if(state == Fw::FocusState) { if(state == Fw::FocusState) {
g_dispatcher.addEvent(std::bind(&UIWidget::onFocusChange, asUIWidget(), newStatus, m_lastFocusReason)); g_dispatcher.addEvent(std::bind(&UIWidget::onFocusChange, asUIWidget(), newStatus, m_lastFocusReason));
} else if(state == Fw::HoverState) } else if(state == Fw::HoverState)
@ -1200,105 +1196,66 @@ void UIWidget::onStyleApply(const std::string& styleName, const OTMLNodePtr& sty
void UIWidget::onGeometryChange(const Rect& oldRect, const Rect& newRect) void UIWidget::onGeometryChange(const Rect& oldRect, const Rect& newRect)
{ {
if(m_destroyed)
return;
callLuaField("onGeometryChange", oldRect, newRect); callLuaField("onGeometryChange", oldRect, newRect);
} }
void UIWidget::onFocusChange(bool focused, Fw::FocusReason reason) void UIWidget::onFocusChange(bool focused, Fw::FocusReason reason)
{ {
if(m_destroyed)
return;
callLuaField("onFocusChange", focused, reason); callLuaField("onFocusChange", focused, reason);
} }
void UIWidget::onChildFocusChange(const UIWidgetPtr& focusedChild, const UIWidgetPtr& unfocusedChild, Fw::FocusReason reason) void UIWidget::onChildFocusChange(const UIWidgetPtr& focusedChild, const UIWidgetPtr& unfocusedChild, Fw::FocusReason reason)
{ {
if(m_destroyed)
return;
callLuaField("onChildFocusChange", focusedChild, unfocusedChild, reason); callLuaField("onChildFocusChange", focusedChild, unfocusedChild, reason);
} }
void UIWidget::onHoverChange(bool hovered) void UIWidget::onHoverChange(bool hovered)
{ {
if(m_destroyed)
return;
callLuaField("onHoverChange", hovered); callLuaField("onHoverChange", hovered);
} }
void UIWidget::onDragEnter(const Point& mousePos) bool UIWidget::onDragEnter(const Point& mousePos)
{ {
if(m_destroyed) return callLuaField<bool>("onDragEnter", mousePos);
return;
callLuaField("onDragEnter", mousePos);
} }
void UIWidget::onDragLeave(UIWidgetPtr droppedWidget, const Point& mousePos) void UIWidget::onDragLeave(UIWidgetPtr droppedWidget, const Point& mousePos)
{ {
if(m_destroyed)
return;
callLuaField("onDragLeave", droppedWidget, mousePos); callLuaField("onDragLeave", droppedWidget, mousePos);
} }
bool UIWidget::onDragMove(const Point& mousePos, const Point& mouseMoved) bool UIWidget::onDragMove(const Point& mousePos, const Point& mouseMoved)
{ {
if(m_destroyed)
return false;
return callLuaField("onDragMove", mousePos, mouseMoved); return callLuaField("onDragMove", mousePos, mouseMoved);
} }
bool UIWidget::onDrop(UIWidgetPtr draggedWidget, const Point& mousePos) bool UIWidget::onDrop(UIWidgetPtr draggedWidget, const Point& mousePos)
{ {
if(m_destroyed)
return false;
return callLuaField<bool>("onDrop", draggedWidget, mousePos); return callLuaField<bool>("onDrop", draggedWidget, mousePos);
} }
bool UIWidget::onKeyText(const std::string& keyText) bool UIWidget::onKeyText(const std::string& keyText)
{ {
if(m_destroyed)
return false;
return callLuaField<bool>("onKeyText", keyText); return callLuaField<bool>("onKeyText", keyText);
} }
bool UIWidget::onKeyDown(uchar keyCode, int keyboardModifiers) bool UIWidget::onKeyDown(uchar keyCode, int keyboardModifiers)
{ {
if(m_destroyed)
return false;
return callLuaField<bool>("onKeyDown", keyCode, keyboardModifiers); return callLuaField<bool>("onKeyDown", keyCode, keyboardModifiers);
} }
bool UIWidget::onKeyPress(uchar keyCode, int keyboardModifiers, int autoRepeatTicks) bool UIWidget::onKeyPress(uchar keyCode, int keyboardModifiers, int autoRepeatTicks)
{ {
if(m_destroyed)
return false;
return callLuaField<bool>("onKeyPress", keyCode, keyboardModifiers, autoRepeatTicks); return callLuaField<bool>("onKeyPress", keyCode, keyboardModifiers, autoRepeatTicks);
} }
bool UIWidget::onKeyUp(uchar keyCode, int keyboardModifiers) bool UIWidget::onKeyUp(uchar keyCode, int keyboardModifiers)
{ {
if(m_destroyed)
return false;
return callLuaField<bool>("onKeyUp", keyCode, keyboardModifiers); return callLuaField<bool>("onKeyUp", keyCode, keyboardModifiers);
} }
bool UIWidget::onMousePress(const Point& mousePos, Fw::MouseButton button) bool UIWidget::onMousePress(const Point& mousePos, Fw::MouseButton button)
{ {
if(m_destroyed)
return false;
if(button == Fw::MouseLeftButton) { if(button == Fw::MouseLeftButton) {
if(m_clickTimer.running() && m_clickTimer.ticksElapsed() <= 500) { if(m_clickTimer.running() && m_clickTimer.ticksElapsed() <= 500) {
if(onDoubleClick(mousePos)) if(onDoubleClick(mousePos))
@ -1315,41 +1272,26 @@ bool UIWidget::onMousePress(const Point& mousePos, Fw::MouseButton button)
bool UIWidget::onMouseRelease(const Point& mousePos, Fw::MouseButton button) bool UIWidget::onMouseRelease(const Point& mousePos, Fw::MouseButton button)
{ {
if(m_destroyed)
return false;
return callLuaField<bool>("onMouseRelease", mousePos, button); return callLuaField<bool>("onMouseRelease", mousePos, button);
} }
bool UIWidget::onMouseMove(const Point& mousePos, const Point& mouseMoved) bool UIWidget::onMouseMove(const Point& mousePos, const Point& mouseMoved)
{ {
if(m_destroyed)
return false;
return callLuaField<bool>("onMouseMove", mousePos, mouseMoved); return callLuaField<bool>("onMouseMove", mousePos, mouseMoved);
} }
bool UIWidget::onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direction) bool UIWidget::onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direction)
{ {
if(m_destroyed)
return false;
return callLuaField<bool>("onMouseWheel", mousePos, direction); return callLuaField<bool>("onMouseWheel", mousePos, direction);
} }
bool UIWidget::onClick(const Point& mousePos) bool UIWidget::onClick(const Point& mousePos)
{ {
if(m_destroyed)
return false;
return callLuaField<bool>("onClick", mousePos); return callLuaField<bool>("onClick", mousePos);
} }
bool UIWidget::onDoubleClick(const Point& mousePos) bool UIWidget::onDoubleClick(const Point& mousePos)
{ {
if(m_destroyed)
return false;
return callLuaField<bool>("onDoubleClick", mousePos); return callLuaField<bool>("onDoubleClick", mousePos);
} }

View File

@ -170,7 +170,7 @@ protected:
virtual void onFocusChange(bool focused, Fw::FocusReason reason); virtual void onFocusChange(bool focused, Fw::FocusReason reason);
virtual void onChildFocusChange(const UIWidgetPtr& focusedChild, const UIWidgetPtr& unfocusedChild, Fw::FocusReason reason); virtual void onChildFocusChange(const UIWidgetPtr& focusedChild, const UIWidgetPtr& unfocusedChild, Fw::FocusReason reason);
virtual void onHoverChange(bool hovered); virtual void onHoverChange(bool hovered);
virtual void onDragEnter(const Point& mousePos); virtual bool onDragEnter(const Point& mousePos);
virtual void onDragLeave(UIWidgetPtr droppedWidget, const Point& mousePos); virtual void onDragLeave(UIWidgetPtr droppedWidget, const Point& mousePos);
virtual bool onDragMove(const Point& mousePos, const Point& mouseMoved); virtual bool onDragMove(const Point& mousePos, const Point& mouseMoved);
virtual bool onDrop(UIWidgetPtr draggedWidget, const Point& mousePos); virtual bool onDrop(UIWidgetPtr draggedWidget, const Point& mousePos);