Drag-scrolling for long dropdown menus

This commit is contained in:
Sergii Pylypenko
2019-07-19 23:45:54 +03:00
parent d10728e6e6
commit e48e4affba
2 changed files with 45 additions and 9 deletions

View File

@@ -100,6 +100,8 @@ struct DropdownWindow : Window {
bool left_button_state; ///< Close the window when the mouse button is clicked outside the window. bool left_button_state; ///< Close the window when the mouse button is clicked outside the window.
int scrolling; ///< If non-zero, auto-scroll the item list (one time). int scrolling; ///< If non-zero, auto-scroll the item list (one time).
GUITimer scrolling_timer; ///< Timer for auto-scroll of the item list. GUITimer scrolling_timer; ///< Timer for auto-scroll of the item list.
bool left_button_scrolling; ///< The list is scrolled with left mouse button
int left_button_scroll_pos; ///< Initial mouse position for left button scrolling
Point position; ///< Position of the topleft corner of the window. Point position; ///< Position of the topleft corner of the window.
Scrollbar *vscroll; Scrollbar *vscroll;
@@ -141,14 +143,18 @@ struct DropdownWindow : Window {
/* Total length of list */ /* Total length of list */
int list_height = 0; int list_height = 0;
int scroll_pos = 0;
int count = 0;
for (const DropDownListItem * const *it = list->Begin(); it != list->End(); ++it) { for (const DropDownListItem * const *it = list->Begin(); it != list->End(); ++it) {
const DropDownListItem *item = *it; const DropDownListItem *item = *it;
list_height += item->Height(items_width); list_height += item->Height(items_width);
if (item->result == selected) scroll_pos = count;
count++;
} }
/* Capacity is the average number of items visible */ /* Capacity is the average number of items visible */
this->vscroll->SetCapacity(size.height * (uint16)list->Length() / list_height); this->vscroll->SetCapacity(size.height * (uint16)list->Length() / list_height);
this->vscroll->SetCount((uint16)list->Length()); this->vscroll->SetCount((uint16)list->Length());
this->vscroll->SetPosition(scroll_pos);
this->vscroll->UpdatePosition(0); this->vscroll->UpdatePosition(0);
this->parent_wnd_class = parent->window_class; this->parent_wnd_class = parent->window_class;
@@ -161,6 +167,8 @@ struct DropdownWindow : Window {
this->instant_close = instant_close; this->instant_close = instant_close;
this->scrolling = 0; this->scrolling = 0;
this->scrolling_timer = GUITimer(MILLISECONDS_PER_TICK); this->scrolling_timer = GUITimer(MILLISECONDS_PER_TICK);
this->left_button_scrolling = false;
this->left_button_scroll_pos = -1;
this->left_button_state = _left_button_down; this->left_button_state = _left_button_down;
} }
@@ -252,6 +260,7 @@ struct DropdownWindow : Window {
virtual void OnClick(Point pt, int widget, int click_count) virtual void OnClick(Point pt, int widget, int click_count)
{ {
if (this->left_button_scrolling) return;
if (widget != WID_DM_ITEMS) return; if (widget != WID_DM_ITEMS) return;
int item; int item;
if (this->GetDropDownItem(item)) { if (this->GetDropDownItem(item)) {
@@ -269,11 +278,8 @@ struct DropdownWindow : Window {
if (this->scrolling != 0) { if (this->scrolling != 0) {
int pos = this->vscroll->GetPosition(); int pos = this->vscroll->GetPosition();
if (_scroller_click_timeout <= 1) { this->vscroll->UpdatePosition(this->scrolling);
_scroller_click_timeout = SCROLLER_CLICK_DELAY; this->scrolling = 0;
this->vscroll->UpdatePosition(this->scrolling);
this->scrolling = 0;
}
if (pos != this->vscroll->GetPosition()) { if (pos != this->vscroll->GetPosition()) {
this->SetDirty(); this->SetDirty();
@@ -337,8 +343,37 @@ struct DropdownWindow : Window {
delete this; delete this;
return; return;
} else { } else {
if (_left_button_down && !this->left_button_state) {
if (GetWidgetFromPos(this, _cursor.pos.x - this->left, _cursor.pos.y - this->top) == WID_DM_ITEMS) {
this->left_button_scroll_pos = _cursor.pos.y;
} else {
this->left_button_scroll_pos = -1;
}
}
if (!_left_button_down && this->left_button_state) {
this->left_button_scrolling = false;
this->left_button_scroll_pos = -1;
this->mouse_capture_widget = -1;
}
this->left_button_state = _left_button_down; this->left_button_state = _left_button_down;
} }
// Scroll item list with left mouse button
if (!this->left_button_scrolling &&
_left_button_down &&
this->left_button_scroll_pos != -1 &&
abs(this->left_button_scroll_pos - _cursor.pos.y) > (int)(*list)[0]->Height(this->width)) {
this->left_button_scrolling = true;
this->mouse_capture_widget = WID_DM_ITEMS;
}
if (this->left_button_scrolling) {
int height = (*list)[0]->Height(this->width);
int pos = (this->left_button_scroll_pos - _cursor.pos.y) / height;
if (pos != 0) {
this->scrolling = pos;
this->left_button_scroll_pos = _cursor.pos.y;
}
}
} }
}; };

View File

@@ -2103,15 +2103,16 @@ static void HandlePlacePresize()
static void HandleMouseDragNoTitlebars() static void HandleMouseDragNoTitlebars()
{ {
if (_settings_client.gui.windows_titlebars || _dragging_window || if (_settings_client.gui.windows_titlebars || _dragging_window ||
!_left_button_down || _focused_window == NULL || _dragging_widget) return; !_left_button_down || _focused_window == NULL ||
_dragging_widget || _focused_window->mouse_capture_widget != -1) return;
unsigned distance = abs(_cursor.pos.x - _left_button_down_pos.x) + abs(_cursor.pos.y - _left_button_down_pos.y); unsigned distance = abs(_cursor.pos.x - _left_button_down_pos.x) + abs(_cursor.pos.y - _left_button_down_pos.y);
if (distance * 2 > GetMinSizing(NWST_STEP) && if (distance * 2 > GetMinSizing(NWST_STEP) &&
_focused_window->window_class != WC_SELECT_GAME && _focused_window->window_class != WC_SELECT_GAME &&
_focused_window->window_class != WC_STATUS_BAR && _focused_window->window_class != WC_STATUS_BAR &&
_focused_window->window_class != WC_MAIN_TOOLBAR && _focused_window->window_class != WC_MAIN_TOOLBAR &&
_focused_window->window_class != WC_MAIN_TOOLBAR_RIGHT && _focused_window->window_class != WC_MAIN_TOOLBAR_RIGHT &&
_focused_window->window_class != WC_BUILD_CONFIRMATION) { _focused_window->window_class != WC_BUILD_CONFIRMATION &&
//SendLeftClickEventToWindow(_focused_window, _left_button_down_pos.x, _left_button_down_pos.y, 1); FindWindowByClass(WC_DROPDOWN_MENU) == NULL) {
StartWindowDrag(_focused_window); StartWindowDrag(_focused_window);
_drag_delta.x += _cursor.pos.x - _left_button_down_pos.x; _drag_delta.x += _cursor.pos.x - _left_button_down_pos.x;
_drag_delta.y += _cursor.pos.y - _left_button_down_pos.y; _drag_delta.y += _cursor.pos.y - _left_button_down_pos.y;