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.
This commit is contained in:
John Scipione 2016-08-18 15:21:19 -07:00
parent a98f98b744
commit 2446f53bc8
2 changed files with 50 additions and 16 deletions

View File

@ -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;

View File

@ -22,6 +22,7 @@
#include <PropertyInfo.h>
#include <ScrollBar.h>
#include <ScrollView.h>
#include <Thread.h>
#include <Window.h>
#include <binary_compatibility/Interface.h>
@ -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<BListView>::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);
}
}