mirror of https://github.com/OpenTTD/OpenTTD
Codechange: improve dropdown mouse interactions to fix hovering when not using instant-close and also make logic more readable
parent
20fdf410d6
commit
daf96d4c4f
|
@ -74,7 +74,6 @@ struct DropdownWindow : Window {
|
||||||
Rect wi_rect; ///< Rect of the button that opened the dropdown.
|
Rect wi_rect; ///< Rect of the button that opened the dropdown.
|
||||||
DropDownList list; ///< List with dropdown menu items.
|
DropDownList list; ///< List with dropdown menu items.
|
||||||
int selected_result; ///< Result value of the selected item in the list.
|
int selected_result; ///< Result value of the selected item in the list.
|
||||||
uint8_t click_delay = 0; ///< Timer to delay selection.
|
|
||||||
bool drag_mode = true;
|
bool drag_mode = true;
|
||||||
bool instant_close; ///< Close the window when the mouse button is raised.
|
bool instant_close; ///< Close the window when the mouse button is raised.
|
||||||
bool persist; ///< Persist dropdown menu.
|
bool persist; ///< Persist dropdown menu.
|
||||||
|
@ -281,12 +280,7 @@ struct DropdownWindow : Window {
|
||||||
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
||||||
{
|
{
|
||||||
if (widget != WID_DM_ITEMS) return;
|
if (widget != WID_DM_ITEMS) return;
|
||||||
int item;
|
this->drag_mode = true;
|
||||||
if (this->GetDropDownItem(item)) {
|
|
||||||
this->click_delay = 4;
|
|
||||||
this->selected_result = item;
|
|
||||||
this->SetDirty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Rate limit how fast scrolling happens. */
|
/** Rate limit how fast scrolling happens. */
|
||||||
|
@ -300,43 +294,41 @@ struct DropdownWindow : Window {
|
||||||
|
|
||||||
void OnMouseLoop() override
|
void OnMouseLoop() override
|
||||||
{
|
{
|
||||||
if (this->click_delay != 0 && --this->click_delay == 0) {
|
/* Scrolling logic */
|
||||||
/* Close the dropdown, so it doesn't affect new window placement.
|
if (_cursor.pos.y <= this->top + WidgetDimensions::scaled.dropdownlist.top) {
|
||||||
* Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */
|
/* Cursor is above the list, set scroll up */
|
||||||
if (!this->persist) this->Close();
|
this->scrolling = -1;
|
||||||
this->parent->OnDropdownSelect(this->parent_button, this->selected_result);
|
} else if (_cursor.pos.y >= this->top + this->height - WidgetDimensions::scaled.dropdownlist.bottom) {
|
||||||
return;
|
/* Cursor is below list, set scroll down */
|
||||||
|
this->scrolling = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->drag_mode) {
|
/* Hover item under the cursor */
|
||||||
int item;
|
int item = -1;
|
||||||
|
const bool item_is_valid = this->GetDropDownItem(item);
|
||||||
if (!_left_button_clicked) {
|
if (item_is_valid) {
|
||||||
this->drag_mode = false;
|
if (item != this->selected_result) {
|
||||||
if (!this->GetDropDownItem(item)) {
|
|
||||||
if (this->instant_close) this->Close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->click_delay = 2;
|
|
||||||
} else {
|
|
||||||
if (_cursor.pos.y <= this->top + WidgetDimensions::scaled.dropdownlist.top) {
|
|
||||||
/* Cursor is above the list, set scroll up */
|
|
||||||
this->scrolling = -1;
|
|
||||||
return;
|
|
||||||
} else if (_cursor.pos.y >= this->top + this->height - WidgetDimensions::scaled.dropdownlist.bottom) {
|
|
||||||
/* Cursor is below list, set scroll down */
|
|
||||||
this->scrolling = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this->GetDropDownItem(item)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->selected_result != item) {
|
|
||||||
this->selected_result = item;
|
this->selected_result = item;
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Select option logic */
|
||||||
|
if (!_left_button_clicked) {
|
||||||
|
bool released_on_item = false;
|
||||||
|
|
||||||
|
if (this->drag_mode) {
|
||||||
|
this->drag_mode = false;
|
||||||
|
|
||||||
|
if ((instant_close || item_is_valid) && !this->persist) {
|
||||||
|
this->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item_is_valid) {
|
||||||
|
this->parent->OnDropdownSelect(this->parent_button, this->selected_result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplaceList(DropDownList &&list)
|
void ReplaceList(DropDownList &&list)
|
||||||
|
|
Loading…
Reference in New Issue