BListView: More auto-scroll fixes from hrev57439
Only auto-scroll if button clicked inside view, not if clicked outside and then dragged in. Save MouseDown() button state to compare against in MouseMoved(). Don't alter selection on first click of selected item on multi-select lists. This eats a click on multi-select lists when you click on a selected item with no modifiers held down to allow for drag and drop. It will update the selection on the second click (and there-after). https://www.haiku-os.org/legacy-docs/bebook/BListView.html InitiateDrag() "... derived classes typically permit users to drag items only if they're already selected (if wasSelected is true). In other words, it takes *two* mouse-down events to drag an item—one to select it and one to begin dragging it." (emphasis mine) Technically this should only happen on draggable multi-select lists, but it doesn't hurt (much) on non-draggable multi-select lists and I can't easily tell if a list view is draggable or not until InitiateDrag() is called. By then it's too late to eat the click in MouseDown(). BeOS R5 solved this problem by selecting on mouse up insted of down but we don't want to do this so we'll just have to accept that the first click in this case doesn't count. Simplify invalid and disabled item logic. If clicked on invalid (somehow) don't alter selection, if clicked on disabled deselect all. Change-Id: I6bf40de85da442ee7acd86ab6d91ff0cac7ab106 Reviewed-on: https://review.haiku-os.org/c/haiku/+/7279 Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
ec595170fb
commit
879e5f5a80
@ -30,6 +30,8 @@
|
||||
struct track_data {
|
||||
BPoint drag_start;
|
||||
int32 item_index;
|
||||
int32 buttons;
|
||||
uint32 selected_click_count;
|
||||
bool was_selected;
|
||||
bool try_drag;
|
||||
bool is_dragging;
|
||||
@ -625,6 +627,13 @@ BListView::MouseDown(BPoint where)
|
||||
Window()->UpdateIfNeeded();
|
||||
}
|
||||
|
||||
int32 buttons = 0;
|
||||
if (Window() != NULL) {
|
||||
BMessage* currentMessage = Window()->CurrentMessage();
|
||||
if (currentMessage != NULL)
|
||||
currentMessage->FindInt32("buttons", &buttons);
|
||||
}
|
||||
|
||||
int32 index = IndexOf(where);
|
||||
|
||||
// If the user double (or more) clicked within the current selection,
|
||||
@ -663,6 +672,13 @@ BListView::MouseDown(BPoint where)
|
||||
SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
|
||||
}
|
||||
|
||||
// increment/reset selected click count
|
||||
fTrack->buttons = buttons;
|
||||
if (fTrack->buttons > 0 && fTrack->was_selected)
|
||||
fTrack->selected_click_count++;
|
||||
else
|
||||
fTrack->selected_click_count = 0;
|
||||
|
||||
_DoSelection(index);
|
||||
|
||||
BView::MouseDown(where);
|
||||
@ -673,6 +689,7 @@ void
|
||||
BListView::MouseUp(BPoint where)
|
||||
{
|
||||
// drag is over
|
||||
fTrack->buttons = 0;
|
||||
fTrack->try_drag = false;
|
||||
fTrack->is_dragging = false;
|
||||
|
||||
@ -719,14 +736,6 @@ BListView::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
|
||||
}
|
||||
}
|
||||
|
||||
// get mouse buttons from current message in case of change
|
||||
int32 buttons = 0;
|
||||
if (Window() != NULL) {
|
||||
BMessage* currentMessage = Window()->CurrentMessage();
|
||||
if (currentMessage != NULL)
|
||||
currentMessage->FindInt32("buttons", &buttons);
|
||||
}
|
||||
|
||||
int32 index = IndexOf(where);
|
||||
if (index == -1) {
|
||||
// If where is above top, scroll to the first item,
|
||||
@ -739,7 +748,7 @@ BListView::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
|
||||
|
||||
// don't scroll if button not pressed or index is invalid
|
||||
int32 lastIndex = fFirstSelected;
|
||||
if (buttons == 0 || index == -1)
|
||||
if (fTrack->buttons == 0 || index == -1)
|
||||
return BView::MouseMoved(where, code, dragMessage);
|
||||
|
||||
// don't scroll if mouse is left or right of the view
|
||||
@ -1598,6 +1607,8 @@ BListView::_InitObject(list_view_type type)
|
||||
fTrack = new track_data;
|
||||
fTrack->drag_start = B_ORIGIN;
|
||||
fTrack->item_index = -1;
|
||||
fTrack->buttons = 0;
|
||||
fTrack->selected_click_count = 0;
|
||||
fTrack->was_selected = false;
|
||||
fTrack->try_drag = false;
|
||||
fTrack->is_dragging = false;
|
||||
@ -2109,40 +2120,43 @@ void
|
||||
BListView::_DoSelection(int32 index)
|
||||
{
|
||||
BListItem* item = ItemAt(index);
|
||||
if (index >= 0 && item != NULL) {
|
||||
if (fListType == B_MULTIPLE_SELECTION_LIST) {
|
||||
// multiple-selection list
|
||||
|
||||
if ((modifiers() & B_SHIFT_KEY) != 0) {
|
||||
// extend or contract selection
|
||||
if (index >= fFirstSelected && index < fLastSelected) {
|
||||
// clicked inside of selected items block, deselect all
|
||||
// except from the first selected index to item index
|
||||
DeselectExcept(fFirstSelected, index);
|
||||
} else {
|
||||
// extend selection up or down
|
||||
Select(std::min(index, fFirstSelected),
|
||||
std::max(index, fLastSelected));
|
||||
}
|
||||
// don't alter selection if invalid item clicked
|
||||
if (index < 0 || item == NULL)
|
||||
return;
|
||||
|
||||
// deselect all if clicked on disabled
|
||||
if (!item->IsEnabled())
|
||||
return DeselectAll();
|
||||
|
||||
if (fListType == B_MULTIPLE_SELECTION_LIST) {
|
||||
// multiple-selection list
|
||||
|
||||
if ((modifiers() & B_SHIFT_KEY) != 0) {
|
||||
if (index >= fFirstSelected && index < fLastSelected) {
|
||||
// clicked inside of selected items block, deselect all
|
||||
// except from the first selected index to item index
|
||||
DeselectExcept(fFirstSelected, index);
|
||||
} else {
|
||||
if ((modifiers() & B_COMMAND_KEY) != 0) {
|
||||
// toggle selection state (like in Tracker)
|
||||
if (item->IsSelected())
|
||||
Deselect(index);
|
||||
else
|
||||
Select(index, true);
|
||||
} else if (item->IsEnabled()) // only select enabled item
|
||||
Select(index);
|
||||
// extend or contract selection
|
||||
Select(std::min(index, fFirstSelected),
|
||||
std::max(index, fLastSelected));
|
||||
}
|
||||
} else {
|
||||
// single-selection list
|
||||
|
||||
} else if ((modifiers() & B_COMMAND_KEY) != 0) {
|
||||
// toggle selection state
|
||||
if ((modifiers() & B_COMMAND_KEY) != 0 && item->IsSelected())
|
||||
if (item->IsSelected())
|
||||
Deselect(index);
|
||||
else if (item->IsEnabled()) // only select enabled item
|
||||
Select(index);
|
||||
}
|
||||
} else if ((modifiers() & B_COMMAND_KEY) == 0)
|
||||
DeselectAll();
|
||||
else
|
||||
Select(index, true);
|
||||
} else if (fTrack->selected_click_count != 1)
|
||||
Select(index); // eat a click on selected for drag and drop
|
||||
} else {
|
||||
// single-selection list
|
||||
|
||||
// toggle selection state
|
||||
if ((modifiers() & B_COMMAND_KEY) != 0 && item->IsSelected())
|
||||
Deselect(index);
|
||||
else
|
||||
Select(index);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user