/* * 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 #include #include #include 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; }