Drag-scrolling for long dropdown menus
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user