--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// 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;
+ }
+}
+