1 /* 2 * Copyright 2009, Alexandre Deckner, alex@zappotek.com 3 * Distributed under the terms of the MIT License. 4 */ 5 6 /*! 7 \class DragTrackingFilter 8 \brief A simple mouse drag detection filter 9 * 10 * A simple mouse filter that detects the start of a mouse drag over a 11 * threshold distance and sends a message with the 'what' field of your 12 * choice. Especially usefull for drag and drop. 13 * Allows you to free your code of encumbering mouse tracking details. 14 * 15 * It can detect fast drags spanning outside of a small view by temporarily 16 * setting the B_POINTER_EVENTS flag on the view. 17 */ 18 19 #include <DragTrackingFilter.h> 20 21 #include <Message.h> 22 #include <Messenger.h> 23 #include <View.h> 24 25 static const int kSquaredDragThreshold = 9; 26 27 DragTrackingFilter::DragTrackingFilter(BView* targetView, uint32 messageWhat) 28 : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE), 29 fTargetView(targetView), 30 fMessageWhat(messageWhat), 31 fIsTracking(false), 32 fClickButtons(0) 33 { 34 } 35 36 37 filter_result 38 DragTrackingFilter::Filter(BMessage* message, BHandler** /*_target*/) 39 { 40 if (fTargetView == NULL) 41 return B_DISPATCH_MESSAGE; 42 43 switch (message->what) { 44 case B_MOUSE_DOWN: 45 message->FindPoint("where", &fClickPoint); 46 message->FindInt32("buttons", (int32*)&fClickButtons); 47 fIsTracking = true; 48 49 fTargetView->SetMouseEventMask(B_POINTER_EVENTS); 50 51 return B_DISPATCH_MESSAGE; 52 53 case B_MOUSE_UP: 54 fIsTracking = false; 55 return B_DISPATCH_MESSAGE; 56 57 case B_MOUSE_MOVED: 58 { 59 BPoint where; 60 message->FindPoint("be:view_where", &where); 61 62 // TODO: be more flexible about buttons and pass their state 63 // in the message 64 if (fIsTracking && (fClickButtons & B_PRIMARY_MOUSE_BUTTON)) { 65 66 BPoint delta(fClickPoint - where); 67 float squaredDelta = (delta.x * delta.x) + (delta.y * delta.y); 68 69 if (squaredDelta >= kSquaredDragThreshold) { 70 BMessage dragClickMessage(fMessageWhat); 71 dragClickMessage.AddPoint("be:view_where", fClickPoint); 72 // name it "be:view_where" since BView::DragMessage 73 // positions the dragging frame/bitmap by retrieving the 74 // current message and reading that field 75 BMessenger messenger(fTargetView); 76 messenger.SendMessage(&dragClickMessage); 77 78 fIsTracking = false; 79 } 80 } 81 return B_DISPATCH_MESSAGE; 82 } 83 default: 84 break; 85 } 86 87 return B_DISPATCH_MESSAGE; 88 } 89