89 lines
2.3 KiB
C++
89 lines
2.3 KiB
C++
/*
|
|
* Copyright 2009, Alexandre Deckner, alex@zappotek.com
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
/*!
|
|
\class DragTrackingFilter
|
|
\brief A simple mouse drag detection filter
|
|
*
|
|
* A simple mouse filter that detects the start of a mouse drag over a
|
|
* threshold distance and sends a message with the 'what' field of your
|
|
* choice. Especially useful for drag and drop.
|
|
* Allows you to free your code of encumbering mouse tracking details.
|
|
*
|
|
* It can detect fast drags spanning outside of a small view by temporarily
|
|
* setting the B_POINTER_EVENTS flag on the view.
|
|
*/
|
|
|
|
#include <DragTrackingFilter.h>
|
|
|
|
#include <Message.h>
|
|
#include <Messenger.h>
|
|
#include <View.h>
|
|
|
|
static const int kSquaredDragThreshold = 9;
|
|
|
|
DragTrackingFilter::DragTrackingFilter(BView* targetView, uint32 messageWhat)
|
|
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
|
|
fTargetView(targetView),
|
|
fMessageWhat(messageWhat),
|
|
fIsTracking(false),
|
|
fClickButtons(0)
|
|
{
|
|
}
|
|
|
|
|
|
filter_result
|
|
DragTrackingFilter::Filter(BMessage* message, BHandler** /*_target*/)
|
|
{
|
|
if (fTargetView == NULL)
|
|
return B_DISPATCH_MESSAGE;
|
|
|
|
switch (message->what) {
|
|
case B_MOUSE_DOWN:
|
|
message->FindPoint("where", &fClickPoint);
|
|
message->FindInt32("buttons", (int32*)&fClickButtons);
|
|
fIsTracking = true;
|
|
|
|
fTargetView->SetMouseEventMask(B_POINTER_EVENTS);
|
|
|
|
return B_DISPATCH_MESSAGE;
|
|
|
|
case B_MOUSE_UP:
|
|
fIsTracking = false;
|
|
return B_DISPATCH_MESSAGE;
|
|
|
|
case B_MOUSE_MOVED:
|
|
{
|
|
BPoint where;
|
|
message->FindPoint("be:view_where", &where);
|
|
|
|
// TODO: be more flexible about buttons and pass their state
|
|
// in the message
|
|
if (fIsTracking && (fClickButtons & B_PRIMARY_MOUSE_BUTTON)) {
|
|
|
|
BPoint delta(fClickPoint - where);
|
|
float squaredDelta = (delta.x * delta.x) + (delta.y * delta.y);
|
|
|
|
if (squaredDelta >= kSquaredDragThreshold) {
|
|
BMessage dragClickMessage(fMessageWhat);
|
|
dragClickMessage.AddPoint("be:view_where", fClickPoint);
|
|
// name it "be:view_where" since BView::DragMessage
|
|
// positions the dragging frame/bitmap by retrieving the
|
|
// current message and reading that field
|
|
BMessenger messenger(fTargetView);
|
|
messenger.SendMessage(&dragClickMessage);
|
|
|
|
fIsTracking = false;
|
|
}
|
|
}
|
|
return B_DISPATCH_MESSAGE;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return B_DISPATCH_MESSAGE;
|
|
}
|