X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9e0ed08360448630be00fb1c441fc7f024afeb6a..bca8c756a30d54ee4fade96a091d78ad8988fd23:/src/common/mousemanager.cpp diff --git a/src/common/mousemanager.cpp b/src/common/mousemanager.cpp new file mode 100644 index 0000000000..c373955038 --- /dev/null +++ b/src/common/mousemanager.cpp @@ -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 +// 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; + } +} +