]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/mousemanager.cpp
added wxMouseEventsManager
[wxWidgets.git] / src / common / mousemanager.cpp
diff --git a/src/common/mousemanager.cpp b/src/common/mousemanager.cpp
new file mode 100644 (file)
index 0000000..c373955
--- /dev/null
@@ -0,0 +1,176 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        src/common/mousemanager.cpp
+// Purpose:     implementation of wxMouseEventsManager class
+// Author:      Vadim Zeitlin
+// Created:     2009-04-21
+// RCS-ID:      $Id$
+// Copyright:   (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#endif // WX_PRECOMP
+
+#include "wx/mousemanager.h"
+
+// ----------------------------------------------------------------------------
+// event tables
+// ----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(wxMouseEventsManager, wxEvtHandler)
+    EVT_MOUSE_CAPTURE_LOST(wxMouseEventsManager::OnCaptureLost)
+    EVT_LEFT_DOWN(wxMouseEventsManager::OnLeftDown)
+    EVT_LEFT_UP(wxMouseEventsManager::OnLeftUp)
+    EVT_MOTION(wxMouseEventsManager::OnMove)
+END_EVENT_TABLE()
+
+// ============================================================================
+// wxMouseEventsManager implementation
+// ============================================================================
+
+wxMouseEventsManager::wxMouseEventsManager(wxWindow *win)
+    : m_win(win)
+{
+    m_state = State_Normal;
+    m_item = wxNOT_FOUND;
+
+    win->PushEventHandler(this);
+}
+
+wxMouseEventsManager::~wxMouseEventsManager()
+{
+    m_win->RemoveEventHandler(this);
+}
+
+void wxMouseEventsManager::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
+{
+    switch ( m_state )
+    {
+        case State_Normal:
+            wxFAIL_MSG( "mouse shouldn't be captured in normal state" );
+            break;
+
+        case State_Pressed:
+            MouseClickCancelled(m_item);
+            break;
+
+        case State_Dragging:
+            MouseDragCancelled(m_item);
+            break;
+    }
+
+    m_state = State_Normal;
+    m_item = wxNOT_FOUND;
+}
+
+void wxMouseEventsManager::OnLeftDown(wxMouseEvent& event)
+{
+    wxASSERT_MSG( m_state == State_Normal,
+                  "state hasn't been reset to normal somehow" );
+
+    m_posLast = event.GetPosition();
+    m_item = MouseHitTest(m_posLast);
+    if ( m_item == wxNOT_FOUND )
+    {
+        event.Skip();
+        return;
+    }
+
+    m_state = State_Pressed;
+    m_win->CaptureMouse();
+    MouseClickBegin(m_item);
+}
+
+void wxMouseEventsManager::OnLeftUp(wxMouseEvent& event)
+{
+    switch ( m_state )
+    {
+        case State_Normal:
+            // ignore it, the mouse hasn't been pressed over any item initially
+            // so releasing it shouldn't do anything
+            event.Skip();
+
+            // skip releasing the capture below
+            return;
+
+        case State_Pressed:
+            if ( MouseHitTest(event.GetPosition()) == m_item )
+            {
+                // mouse released over the same item, so it was a click
+                MouseClicked(m_item);
+            }
+            break;
+
+        case State_Dragging:
+            MouseDragEnd(m_item, event.GetPosition());
+            break;
+    }
+
+    m_state = State_Normal;
+    m_item = wxNOT_FOUND;
+    m_win->ReleaseMouse();
+}
+
+void wxMouseEventsManager::OnMove(wxMouseEvent& event)
+{
+    switch ( m_state )
+    {
+        case State_Normal:
+            event.Skip();
+            break;
+
+        case State_Pressed:
+            wxASSERT_MSG( event.LeftIsDown(),
+                          "should have detected mouse being released" );
+
+            {
+                // it's probably a bad idea to query the system for these
+                // values every time the mouse is moved so cache them on the
+                // assumption that they don't change -- which is wrong, of
+                // course, the user can change them but it doesn't happen often
+                static const int
+                    dragMinX = wxSystemSettings::GetMetric(wxSYS_DRAG_X);
+                static const int
+                    dragMinY = wxSystemSettings::GetMetric(wxSYS_DRAG_Y);
+
+                const wxPoint& pos = event.GetPosition();
+                const wxPoint ofs = pos - m_posLast;
+                if ( abs(ofs.x) > dragMinX || abs(ofs.y) > dragMinY )
+                {
+                    // the mouse left the rectangle inside which its movements
+                    // are considered to be too small to constitute a start of
+                    // drag operation, do [attempt to] start it now
+                    if ( MouseDragBegin(m_item, pos) )
+                    {
+                        m_state = State_Dragging;
+                    }
+                }
+                else // still didn't move far enough away
+                {
+                    event.Skip();
+                }
+            }
+            break;
+
+        case State_Dragging:
+            m_posLast = event.GetPosition();
+            MouseDragging(m_item, m_posLast);
+            break;
+    }
+}
+