Browse Source

Added UI hover start/end events.

Lasse Öörni 11 years ago
parent
commit
18217a0fdd
3 changed files with 63 additions and 9 deletions
  1. 43 7
      Source/Engine/UI/UI.cpp
  2. 4 2
      Source/Engine/UI/UI.h
  3. 16 0
      Source/Engine/UI/UIEvents.h

+ 43 - 7
Source/Engine/UI/UI.cpp

@@ -300,6 +300,10 @@ void UI::Update(float timeStep)
     bool cursorVisible;
     GetCursorPositionAndVisible(cursorPos, cursorVisible);
 
+    // Expire hovers
+    for (HashMap<WeakPtr<UIElement>, bool>::Iterator i = hoveredElements_.Begin(); i != hoveredElements_.End(); ++i)
+        i->second_ = false;
+    
     // Drag begin based on time
     if (dragElement_ && dragBeginPending_)
     {
@@ -313,7 +317,7 @@ void UI::Update(float timeStep)
             }
             else
                 dragElement_->OnDragBegin(dragElement_->ScreenToElement(dragBeginPos_), dragBeginPos_, MOUSEB_LEFT, 0, 0);
-            SendDragEvent(E_DRAGBEGIN, dragElement_, dragBeginPos_);
+            SendDragOrHoverEvent(E_DRAGBEGIN, dragElement_, dragBeginPos_);
         }
     }
     
@@ -330,6 +334,26 @@ void UI::Update(float timeStep)
         ProcessHover(touch->position_, MOUSEB_LEFT, 0, 0);
     }
     
+    // End hovers that expired without refreshing
+    for (HashMap<WeakPtr<UIElement>, bool>::Iterator i = hoveredElements_.Begin(); i != hoveredElements_.End();)
+    {
+        if (i->first_.Expired() || !i->second_)
+        {
+            UIElement* element = i->first_;
+            if (element)
+            {
+                using namespace HoverEnd;
+                
+                VariantMap& eventData = GetEventDataMap();
+                eventData[P_ELEMENT] = element;
+                element->SendEvent(E_HOVEREND, eventData);
+            }
+            i = hoveredElements_.Erase(i);
+        }
+        else
+            ++i;
+    }
+    
     Update(timeStep, rootElement_);
     Update(timeStep, rootModalElement_);
 }
@@ -910,7 +934,19 @@ void UI::ProcessHover(const IntVector2& cursorPos, int buttons, int qualifiers,
     if (element && element->IsEnabled())
     {
         if (!dragElement_ || dragElement_ == element || dragDropTest)
+        {
             element->OnHover(element->ScreenToElement(cursorPos), cursorPos, buttons, qualifiers, cursor);
+            
+            // Begin hover event
+            if (!hoveredElements_.Contains(element))
+            {
+                SendDragOrHoverEvent(E_HOVERBEGIN, element, cursorPos);
+                // Exit if element is destroyed by the event handling
+                if (!element)
+                    return;
+            }
+            hoveredElements_[element] = true;
+        }
     }
 
     // Drag and drop test
@@ -1010,7 +1046,7 @@ void UI::ProcessClickEnd(const IntVector2& cursorPos, int button, int buttons, i
             if (dragElement_->IsEnabled() && dragElement_->IsVisible() && !dragBeginPending_)
             {
                 dragElement_->OnDragEnd(dragElement_->ScreenToElement(cursorPos), cursorPos, cursor);
-                SendDragEvent(E_DRAGEND, dragElement_, cursorPos);
+                SendDragOrHoverEvent(E_DRAGEND, dragElement_, cursorPos);
 
                 bool dragSource = dragElement_ && (dragElement_->GetDragDropMode() & DD_SOURCE) != 0;
                 if (dragSource)
@@ -1059,26 +1095,26 @@ void UI::ProcessMove(const IntVector2& cursorPos, int buttons, int qualifiers, C
                 {
                     dragBeginPending_ = false;
                     dragElement_->OnDragBegin(dragElement_->ScreenToElement(dragBeginPos_), dragBeginPos_, buttons, qualifiers, cursor);
-                    SendDragEvent(E_DRAGBEGIN, dragElement_, dragBeginPos_);
+                    SendDragOrHoverEvent(E_DRAGBEGIN, dragElement_, dragBeginPos_);
                 }
             }
             
             if (!dragBeginPending_)
             {
                 dragElement_->OnDragMove(dragElement_->ScreenToElement(cursorPos), cursorPos, buttons, qualifiers, cursor);
-                SendDragEvent(E_DRAGMOVE, dragElement_, cursorPos);
+                SendDragOrHoverEvent(E_DRAGMOVE, dragElement_, cursorPos);
             }
         }
         else
         {
             dragElement_->OnDragEnd(dragElement_->ScreenToElement(cursorPos), cursorPos, cursor);
-            SendDragEvent(E_DRAGEND, dragElement_, cursorPos);
+            SendDragOrHoverEvent(E_DRAGEND, dragElement_, cursorPos);
             dragElement_.Reset();
         }
     }
 }
 
-void UI::SendDragEvent(StringHash eventType, UIElement* element, const IntVector2& screenPos)
+void UI::SendDragOrHoverEvent(StringHash eventType, UIElement* element, const IntVector2& screenPos)
 {
     if (!element)
         return;
@@ -1288,7 +1324,7 @@ void UI::HandleKeyDown(StringHash eventType, VariantMap& eventData)
         IntVector2 cursorPos;
         bool cursorVisible;
         GetCursorPositionAndVisible(cursorPos, cursorVisible);
-        SendDragEvent(E_DRAGCANCEL, dragElement_, cursorPos);
+        SendDragOrHoverEvent(E_DRAGCANCEL, dragElement_, cursorPos);
         
         dragElement_.Reset();
         dragBeginPending_ = false;

+ 4 - 2
Source/Engine/UI/UI.h

@@ -168,8 +168,8 @@ private:
     void ProcessClickEnd(const IntVector2& cursorPos, int button, int buttons, int qualifiers, Cursor* cursor, bool cursorVisible);
     /// Handle mouse or touch move.
     void ProcessMove(const IntVector2& cursorPos, int buttons, int qualifiers, Cursor* cursor, bool cursorVisible);
-    /// Send a UI element drag event.
-    void SendDragEvent(StringHash eventType, UIElement* element, const IntVector2& screenPos);
+    /// Send a UI element drag or hover begin event.
+    void SendDragOrHoverEvent(StringHash eventType, UIElement* element, const IntVector2& screenPos);
     /// Send a UI click or double click event.
     void SendClickEvent(StringHash eventType, UIElement* element, const IntVector2& pos, int button, int buttons, int qualifiers);
     /// Handle screen mode event.
@@ -274,6 +274,8 @@ private:
     WeakPtr<UIElement> clickElement_;
     /// UI element last clicked for tracking double clicks.
     WeakPtr<UIElement> doubleClickElement_;
+    /// Currently hovered elements.
+    HashMap<WeakPtr<UIElement>, bool> hoveredElements_;
 };
 
 /// Register UI library objects.

+ 16 - 0
Source/Engine/UI/UIEvents.h

@@ -298,6 +298,22 @@ EVENT(E_ELEMENTREMOVED, ElementRemoved)
     PARAM(P_ELEMENT, Element);              // UIElement pointer
 }
 
+/// Hovering on an UI element has started
+EVENT(E_HOVERBEGIN, HoverBegin)
+{
+    PARAM(P_ELEMENT, Element);              // UIElement pointer
+    PARAM(P_X, X);                          // int
+    PARAM(P_Y, Y);                          // int
+    PARAM(P_ELEMENTX, ElementX);            // int
+    PARAM(P_ELEMENTY, ElementY);            // int
+}
+
+/// Hovering on an UI element has ended
+EVENT(E_HOVEREND, HoverEnd)
+{
+    PARAM(P_ELEMENT, Element);              // UIElement pointer
+}
+
 /// Drag behavior of a UI Element has started
 EVENT(E_DRAGBEGIN, DragBegin)
 {