Merge remote-tracking branch 'upstream/master'

This commit is contained in:
dP
2025-09-28 02:33:49 +05:00
926 changed files with 37901 additions and 27368 deletions
+31 -20
View File
@@ -11,6 +11,7 @@
#include "dropdown_type.h"
#include "dropdown_func.h"
#include "strings_func.h"
#include "sound_func.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "window_gui.h"
@@ -70,7 +71,7 @@ static constexpr NWidgetPart _nested_dropdown_menu_widgets[] = {
};
static WindowDesc _dropdown_desc(
WDP_MANUAL, nullptr, 0, 0,
WDP_MANUAL, {}, 0, 0,
WC_DROPDOWN_MENU, WC_NONE,
WindowDefaultFlag::NoFocus,
_nested_dropdown_menu_widgets
@@ -82,6 +83,7 @@ struct DropdownWindow : Window {
Rect wi_rect{}; ///< Rect of the button that opened the dropdown.
DropDownList list{}; ///< List with dropdown menu items.
int selected_result = 0; ///< Result value of the selected item in the list.
int selected_click_result = -1; ///< Click result value, from the OnClick handler of the selected item.
uint8_t click_delay = 0; ///< Timer to delay selection.
bool drag_mode = true;
bool instant_close = false; ///< Close the window when the mouse button is raised.
@@ -136,7 +138,7 @@ struct DropdownWindow : Window {
Point pt = _cursor.pos;
pt.x -= this->parent->left;
pt.y -= this->parent->top;
this->parent->OnDropdownClose(pt, this->parent_button, this->selected_result, this->instant_close);
this->parent->OnDropdownClose(pt, this->parent_button, this->selected_result, this->selected_click_result, this->instant_close);
/* Set flag on parent widget to indicate that we have just closed. */
NWidgetCore *nwc = this->parent->GetWidget<NWidgetCore>(this->parent_button);
@@ -230,14 +232,15 @@ struct DropdownWindow : Window {
/**
* Find the dropdown item under the cursor.
* @param[out] value Selected item, if function returns \c true.
* @param[out] result Selected item, if function returns \c true.
* @param[out] click_result Click result from OnClick of Selected item, if function returns \c true.
* @return Cursor points to a dropdown item.
*/
bool GetDropDownItem(int &value)
bool GetDropDownItem(int &result, int &click_result)
{
if (GetWidgetFromPos(this, _cursor.pos.x - this->left, _cursor.pos.y - this->top) < 0) return false;
const Rect &r = this->GetWidget<NWidgetBase>(WID_DM_ITEMS)->GetCurrentRect().Shrink(WidgetDimensions::scaled.dropdownlist);
const Rect &r = this->GetWidget<NWidgetBase>(WID_DM_ITEMS)->GetCurrentRect().Shrink(WidgetDimensions::scaled.dropdownlist).Shrink(WidgetDimensions::scaled.dropdowntext, RectPadding::zero);
int y = _cursor.pos.y - this->top - r.top;
int pos = this->vscroll->GetPosition();
@@ -249,7 +252,8 @@ struct DropdownWindow : Window {
if (y < item_height) {
if (item->masked || !item->Selectable()) return false;
value = item->result;
result = item->result;
click_result = item->OnClick({r.left, 0, r.right, item_height - 1}, {_cursor.pos.x - this->left, y});
return true;
}
@@ -280,7 +284,7 @@ struct DropdownWindow : Window {
bool selected = (this->selected_result == item->result) && item->Selectable();
if (selected) GfxFillRect(full, PC_BLACK);
item->Draw(full, full.Shrink(WidgetDimensions::scaled.dropdowntext, RectPadding::zero), selected, colour);
item->Draw(full, full.Shrink(WidgetDimensions::scaled.dropdowntext, RectPadding::zero), selected, selected ? this->selected_click_result : -1, colour);
}
y += item_height;
}
@@ -289,16 +293,17 @@ struct DropdownWindow : Window {
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
if (widget != WID_DM_ITEMS) return;
int item;
if (this->GetDropDownItem(item)) {
int result, click_result;
if (this->GetDropDownItem(result, click_result)) {
this->click_delay = 4;
this->selected_result = item;
this->selected_result = result;
this->selected_click_result = click_result;
this->SetDirty();
}
}
/** Rate limit how fast scrolling happens. */
IntervalTimer<TimerWindow> scroll_interval = {std::chrono::milliseconds(30), [this](auto) {
const IntervalTimer<TimerWindow> scroll_interval = {std::chrono::milliseconds(30), [this](auto) {
if (this->scrolling == 0) return;
if (this->vscroll->UpdatePosition(this->scrolling)) this->SetDirty();
@@ -312,16 +317,16 @@ struct DropdownWindow : Window {
/* Close the dropdown, so it doesn't affect new window placement.
* Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */
if (!this->persist) this->Close();
this->parent->OnDropdownSelect(this->parent_button, this->selected_result);
this->parent->OnDropdownSelect(this->parent_button, this->selected_result, this->selected_click_result);
return;
}
if (this->drag_mode) {
int item;
int result, click_result;
if (!_left_button_clicked) {
this->drag_mode = false;
if (!this->GetDropDownItem(item)) {
if (!this->GetDropDownItem(result, click_result)) {
if (this->instant_close) this->Close();
return;
}
@@ -337,30 +342,33 @@ struct DropdownWindow : Window {
return;
}
if (!this->GetDropDownItem(item)) return;
if (!this->GetDropDownItem(result, click_result)) return;
}
if (this->selected_result != item) {
this->selected_result = item;
if (this->selected_result != result || this->selected_click_result != click_result) {
this->selected_result = result;
this->selected_click_result = click_result;
this->SetDirty();
}
}
}
void ReplaceList(DropDownList &&list)
void ReplaceList(DropDownList &&list, std::optional<int> selected_result)
{
this->list = std::move(list);
if (selected_result.has_value()) this->selected_result = *selected_result;
this->UpdateSizeAndPosition();
this->ReInit(0, 0);
this->InitializePositionSize(this->position.x, this->position.y, this->nested_root->smallest_x, this->nested_root->smallest_y);
this->FindWindowPlacementAndResize(this->window_desc.GetDefaultWidth(), this->window_desc.GetDefaultHeight(), true);
this->SetDirty();
}
};
void ReplaceDropDownList(Window *parent, DropDownList &&list)
void ReplaceDropDownList(Window *parent, DropDownList &&list, std::optional<int> selected_result)
{
DropdownWindow *ddw = dynamic_cast<DropdownWindow *>(parent->FindChildWindow(WC_DROPDOWN_MENU));
if (ddw != nullptr) ddw->ReplaceList(std::move(list));
if (ddw != nullptr) ddw->ReplaceList(std::move(list), selected_result);
}
/**
@@ -411,6 +419,9 @@ void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID b
*/
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, bool instant_close, bool persist)
{
/* Handle the beep of the player's click. */
SndClickBeep();
/* Our parent's button widget is used to determine where to place the drop
* down list window. */
NWidgetCore *nwi = w->GetWidget<NWidgetCore>(button);