From 2446f53bc8a707b504bb69f930222ab891be89ff Mon Sep 17 00:00:00 2001 From: John Scipione Date: Thu, 18 Aug 2016 15:21:19 -0700 Subject: [PATCH] BListView: Impliment autoscroll BeOS had a feature where you could click on a list and while holding down the mouse button scroll through the list items selecting them as you went. I implemented the same feature on Haiku. Did the work in separate thread which makes sure that the mouse is held down the whole time even if you leave the view. Thanks Diver for bringing this feature to my attention. --- headers/os/interface/ListView.h | 3 ++ src/kits/interface/ListView.cpp | 63 ++++++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/headers/os/interface/ListView.h b/headers/os/interface/ListView.h index ef5b6b5be4..56878a945e 100644 --- a/headers/os/interface/ListView.h +++ b/headers/os/interface/ListView.h @@ -189,6 +189,9 @@ private: bool _ReplaceItem(int32 index, BListItem* item); void _RescanSelection(int32 from, int32 to); + void _DoneTracking(BPoint where); + void _Track(BPoint where, uint32); + private: BList fList; list_view_type fListType; diff --git a/src/kits/interface/ListView.cpp b/src/kits/interface/ListView.cpp index bc8f091f1c..f26e2e7484 100644 --- a/src/kits/interface/ListView.cpp +++ b/src/kits/interface/ListView.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -568,7 +569,7 @@ BListView::MouseDown(BPoint where) if (doubleClick && index >= fFirstSelected && index <= fLastSelected) { fTrack->drag_start.Set(INT32_MAX, INT32_MAX); Invoke(); - return; + return BView::MouseDown(where); } if (!doubleClick) { @@ -577,6 +578,9 @@ BListView::MouseDown(BPoint where) fTrack->item_index = index; fTrack->was_selected = index >= 0 ? ItemAt(index)->IsSelected() : false; fTrack->try_drag = true; + + MouseDownThread::TrackMouse(this, + &BListView::_DoneTracking, &BListView::_Track); } if (index >= 0) { @@ -613,33 +617,22 @@ BListView::MouseDown(BPoint where) } } else if ((modifiers & B_COMMAND_KEY) == 0) DeselectAll(); + + BView::MouseDown(where); } void BListView::MouseUp(BPoint where) { - fTrack->try_drag = false; + BView::MouseUp(where); } void BListView::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) { - if (fTrack->item_index == -1 || !fTrack->try_drag) { - // mouse was not clicked above any item - // or no mouse button pressed - return; - } - - // Initiate a drag if the mouse was moved far enough - BPoint offset = where - fTrack->drag_start; - float dragDistance = sqrtf(offset.x * offset.x + offset.y * offset.y); - if (dragDistance >= 5.0f) { - fTrack->try_drag = false; - InitiateDrag(fTrack->drag_start, fTrack->item_index, - fTrack->was_selected); - } + BView::MouseMoved(where, code, dragMessage); } @@ -1945,3 +1938,41 @@ BListView::_RecalcItemTops(int32 start, int32 end) top += ceilf(item->Height()); } } + + +void +BListView::_DoneTracking(BPoint where) +{ + fTrack->try_drag = false; +} + + +void +BListView::_Track(BPoint where, uint32) +{ + int32 index = IndexOf(where); + BListItem* item = ItemAt(index); + + if (item != NULL && !item->IsSelected() && item->IsEnabled()) { + Select(index, fListType == B_MULTIPLE_SELECTION_LIST + && (modifiers() & B_SHIFT_KEY) != 0); + ScrollToSelection(); + fTrack->try_drag = false; + // don't try to initiate a drag once selection changes + } + + if (fTrack->item_index < 0 || !fTrack->try_drag) { + // mouse was not clicked above any item + // or no mouse button pressed + return; + } + + // Initiate a drag if the mouse was moved far enough + BPoint offset = where - fTrack->drag_start; + float dragDistance = sqrtf(offset.x * offset.x + offset.y * offset.y); + if (dragDistance >= 5.0f) { + fTrack->try_drag = false; + InitiateDrag(fTrack->drag_start, fTrack->item_index, + fTrack->was_selected); + } +}