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.
int scrolling; ///< If non-zero, auto-scroll the item list (one time).
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.
Scrollbar *vscroll;
@@ -141,14 +143,18 @@ struct DropdownWindow : Window {
/* Total length of list */
int list_height = 0;
int scroll_pos = 0;
int count = 0;
for (const DropDownListItem * const *it = list->Begin(); it != list->End(); ++it) {
const DropDownListItem *item = *it;
list_height += item->Height(items_width);
if (item->result == selected) scroll_pos = count;
count++;
}
/* Capacity is the average number of items visible */
this->vscroll->SetCapacity(size.height * (uint16)list->Length() / list_height);
this->vscroll->SetCount((uint16)list->Length());
this->vscroll->SetPosition(scroll_pos);
this->vscroll->UpdatePosition(0);
this->parent_wnd_class = parent->window_class;
@@ -161,6 +167,8 @@ struct DropdownWindow : Window {
this->instant_close = instant_close;
this->scrolling = 0;
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;
}
@@ -252,6 +260,7 @@ struct DropdownWindow : Window {
virtual void OnClick(Point pt, int widget, int click_count)
{
if (this->left_button_scrolling) return;
if (widget != WID_DM_ITEMS) return;
int item;
if (this->GetDropDownItem(item)) {
@@ -269,11 +278,8 @@ struct DropdownWindow : Window {
if (this->scrolling != 0) {
int pos = this->vscroll->GetPosition();
if (_scroller_click_timeout <= 1) {
_scroller_click_timeout = SCROLLER_CLICK_DELAY;
this->vscroll->UpdatePosition(this->scrolling);
this->scrolling = 0;
}
this->vscroll->UpdatePosition(this->scrolling);
this->scrolling = 0;
if (pos != this->vscroll->GetPosition()) {
this->SetDirty();
@@ -337,8 +343,37 @@ struct DropdownWindow : Window {
delete this;
return;
} 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;
}
// 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()
{
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);
if (distance * 2 > GetMinSizing(NWST_STEP) &&
_focused_window->window_class != WC_SELECT_GAME &&
_focused_window->window_class != WC_STATUS_BAR &&
_focused_window->window_class != WC_MAIN_TOOLBAR &&
_focused_window->window_class != WC_MAIN_TOOLBAR_RIGHT &&
_focused_window->window_class != WC_BUILD_CONFIRMATION) {
//SendLeftClickEventToWindow(_focused_window, _left_button_down_pos.x, _left_button_down_pos.y, 1);
_focused_window->window_class != WC_BUILD_CONFIRMATION &&
FindWindowByClass(WC_DROPDOWN_MENU) == NULL) {
StartWindowDrag(_focused_window);
_drag_delta.x += _cursor.pos.x - _left_button_down_pos.x;
_drag_delta.y += _cursor.pos.y - _left_button_down_pos.y;