Merge branch 'master' into jgrpp

# Conflicts:
#	cmake/SourceList.cmake
#	src/build_vehicle_gui.cpp
#	src/company_gui.cpp
#	src/console_cmds.cpp
#	src/depot_base.h
#	src/elrail.cpp
#	src/network/core/udp.cpp
#	src/network/network_admin.cpp
#	src/network/network_chat_gui.cpp
#	src/network/network_gui.cpp
#	src/network/network_server.cpp
#	src/newgrf.cpp
#	src/newgrf_engine.cpp
#	src/newgrf_railtype.cpp
#	src/newgrf_railtype.h
#	src/newgrf_storage.h
#	src/os/unix/crashlog_unix.cpp
#	src/rail.h
#	src/rail_cmd.cpp
#	src/rail_gui.cpp
#	src/road_cmd.cpp
#	src/road_map.h
#	src/saveload/labelmaps_sl.cpp
#	src/settings_gui.cpp
#	src/settings_type.h
#	src/sl/oldloader_sl.cpp
#	src/station_cmd.cpp
#	src/station_gui.cpp
#	src/table/settings/world_settings.ini
#	src/tests/test_script_admin.cpp
#	src/textfile_gui.cpp
#	src/toolbar_gui.cpp
#	src/train_cmd.cpp
#	src/tunnelbridge_cmd.cpp
#	src/vehicle_gui.cpp
#	src/widget.cpp
#	src/window.cpp
#	src/window_gui.h
#	src/window_type.h
This commit is contained in:
Jonathan G Rennison
2023-11-19 12:19:17 +00:00
230 changed files with 2458 additions and 1106 deletions

View File

@@ -3086,71 +3086,69 @@ bool NWidgetLeaf::ButtonHit(const Point &pt)
* settings that follow it, until encountering a #EndContainer, another
* #NWidget, or the end of the parts array.
*
* @param parts Array with parts of the nested widget.
* @param count Length of the \a parts array.
* @param nwid_begin Pointer to beginning of nested widget parts.
* @param nwid_end Pointer to ending of nested widget parts.
* @param dest Address of pointer to use for returning the composed widget.
* @param fill_dest Fill the composed widget with child widgets.
* @param biggest_index Pointer to biggest nested widget index in the tree encountered so far.
* @return Number of widget part elements used to compose the widget.
* @return Pointer to remaining nested widget parts.
* @pre \c biggest_index != nullptr.
*/
static int MakeNWidget(const NWidgetPart *parts, int count, NWidgetBase **dest, bool *fill_dest, int *biggest_index)
static const NWidgetPart *MakeNWidget(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, NWidgetBase **dest, bool *fill_dest, int *biggest_index)
{
int num_used = 0;
*dest = nullptr;
*fill_dest = false;
while (count > num_used) {
switch (parts->type) {
while (nwid_begin < nwid_end) {
switch (nwid_begin->type) {
case NWID_SPACER:
if (*dest != nullptr) return num_used;
if (*dest != nullptr) return nwid_begin;
*dest = new NWidgetSpacer(0, 0);
break;
case NWID_HORIZONTAL:
if (*dest != nullptr) return num_used;
*dest = new NWidgetHorizontal(parts->u.cont_flags);
if (*dest != nullptr) return nwid_begin;
*dest = new NWidgetHorizontal(nwid_begin->u.cont_flags);
*fill_dest = true;
break;
case NWID_HORIZONTAL_LTR:
if (*dest != nullptr) return num_used;
*dest = new NWidgetHorizontalLTR(parts->u.cont_flags);
if (*dest != nullptr) return nwid_begin;
*dest = new NWidgetHorizontalLTR(nwid_begin->u.cont_flags);
*fill_dest = true;
break;
case WWT_PANEL:
case WWT_INSET:
case WWT_FRAME:
if (*dest != nullptr) return num_used;
*dest = new NWidgetBackground(parts->type, parts->u.widget.colour, parts->u.widget.index);
*biggest_index = std::max(*biggest_index, (int)parts->u.widget.index);
if (*dest != nullptr) return nwid_begin;
*dest = new NWidgetBackground(nwid_begin->type, nwid_begin->u.widget.colour, nwid_begin->u.widget.index);
*biggest_index = std::max(*biggest_index, (int)nwid_begin->u.widget.index);
*fill_dest = true;
break;
case NWID_VERTICAL:
if (*dest != nullptr) return num_used;
*dest = new NWidgetVertical(parts->u.cont_flags);
if (*dest != nullptr) return nwid_begin;
*dest = new NWidgetVertical(nwid_begin->u.cont_flags);
*fill_dest = true;
break;
case NWID_MATRIX: {
if (*dest != nullptr) return num_used;
if (*dest != nullptr) return nwid_begin;
NWidgetMatrix *nwm = new NWidgetMatrix();
*dest = nwm;
*fill_dest = true;
nwm->SetIndex(parts->u.widget.index);
nwm->SetColour(parts->u.widget.colour);
*biggest_index = std::max(*biggest_index, (int)parts->u.widget.index);
nwm->SetIndex(nwid_begin->u.widget.index);
nwm->SetColour(nwid_begin->u.widget.colour);
*biggest_index = std::max(*biggest_index, (int)nwid_begin->u.widget.index);
break;
}
case WPT_FUNCTION: {
if (*dest != nullptr) return num_used;
if (*dest != nullptr) return nwid_begin;
/* Ensure proper functioning even when the called code simply writes its largest index. */
int biggest = -1;
*dest = parts->u.func_ptr(&biggest);
*dest = nwid_begin->u.func_ptr(&biggest);
*biggest_index = std::max(*biggest_index, biggest);
*fill_dest = false;
break;
@@ -3159,8 +3157,8 @@ static int MakeNWidget(const NWidgetPart *parts, int count, NWidgetBase **dest,
case WPT_RESIZE: {
NWidgetResizeBase *nwrb = dynamic_cast<NWidgetResizeBase *>(*dest);
if (nwrb != nullptr) {
assert(parts->u.xy.x >= 0 && parts->u.xy.y >= 0);
nwrb->SetResize(parts->u.xy.x, parts->u.xy.y);
assert(nwid_begin->u.xy.x >= 0 && nwid_begin->u.xy.y >= 0);
nwrb->SetResize(nwid_begin->u.xy.x, nwid_begin->u.xy.y);
}
break;
}
@@ -3168,8 +3166,8 @@ static int MakeNWidget(const NWidgetPart *parts, int count, NWidgetBase **dest,
case WPT_MINSIZE: {
NWidgetResizeBase *nwrb = dynamic_cast<NWidgetResizeBase *>(*dest);
if (nwrb != nullptr) {
assert(parts->u.xy.x >= 0 && parts->u.xy.y >= 0);
nwrb->SetMinimalSize(parts->u.xy.x, parts->u.xy.y);
assert(nwid_begin->u.xy.x >= 0 && nwid_begin->u.xy.y >= 0);
nwrb->SetMinimalSize(nwid_begin->u.xy.x, nwid_begin->u.xy.y);
}
break;
}
@@ -3177,8 +3175,8 @@ static int MakeNWidget(const NWidgetPart *parts, int count, NWidgetBase **dest,
case WPT_MINTEXTLINES: {
NWidgetResizeBase *nwrb = dynamic_cast<NWidgetResizeBase *>(*dest);
if (nwrb != nullptr) {
assert(parts->u.text_lines.size >= FS_BEGIN && parts->u.text_lines.size < FS_END);
nwrb->SetMinimalTextLines(parts->u.text_lines.lines, parts->u.text_lines.spacing, parts->u.text_lines.size);
assert(nwid_begin->u.text_lines.size >= FS_BEGIN && nwid_begin->u.text_lines.size < FS_END);
nwrb->SetMinimalTextLines(nwid_begin->u.text_lines.lines, nwid_begin->u.text_lines.spacing, nwid_begin->u.text_lines.size);
}
break;
}
@@ -3186,7 +3184,7 @@ static int MakeNWidget(const NWidgetPart *parts, int count, NWidgetBase **dest,
case WPT_TEXTSTYLE: {
NWidgetCore *nwc = dynamic_cast<NWidgetCore *>(*dest);
if (nwc != nullptr) {
nwc->SetTextStyle(parts->u.text_style.colour, parts->u.text_style.size);
nwc->SetTextStyle(nwid_begin->u.text_style.colour, nwid_begin->u.text_style.size);
}
break;
}
@@ -3194,97 +3192,96 @@ static int MakeNWidget(const NWidgetPart *parts, int count, NWidgetBase **dest,
case WPT_ALIGNMENT: {
NWidgetCore *nwc = dynamic_cast<NWidgetCore *>(*dest);
if (nwc != nullptr) {
nwc->SetAlignment(parts->u.align.align);
nwc->SetAlignment(nwid_begin->u.align.align);
}
break;
}
case WPT_FILL: {
NWidgetResizeBase *nwrb = dynamic_cast<NWidgetResizeBase *>(*dest);
if (nwrb != nullptr) nwrb->SetFill(parts->u.xy.x, parts->u.xy.y);
if (nwrb != nullptr) nwrb->SetFill(nwid_begin->u.xy.x, nwid_begin->u.xy.y);
break;
}
case WPT_DATATIP: {
NWidgetCore *nwc = dynamic_cast<NWidgetCore *>(*dest);
if (nwc != nullptr) {
nwc->widget_data = parts->u.data_tip.data;
nwc->tool_tip = parts->u.data_tip.tooltip;
nwc->widget_data = nwid_begin->u.data_tip.data;
nwc->tool_tip = nwid_begin->u.data_tip.tooltip;
}
break;
}
case WPT_PADDING:
if (*dest != nullptr) (*dest)->SetPadding(parts->u.padding);
if (*dest != nullptr) (*dest)->SetPadding(nwid_begin->u.padding);
break;
case WPT_PIPSPACE: {
NWidgetPIPContainer *nwc = dynamic_cast<NWidgetPIPContainer *>(*dest);
if (nwc != nullptr) nwc->SetPIP(parts->u.pip.pre, parts->u.pip.inter, parts->u.pip.post);
if (nwc != nullptr) nwc->SetPIP(nwid_begin->u.pip.pre, nwid_begin->u.pip.inter, nwid_begin->u.pip.post);
NWidgetBackground *nwb = dynamic_cast<NWidgetBackground *>(*dest);
if (nwb != nullptr) nwb->SetPIP(parts->u.pip.pre, parts->u.pip.inter, parts->u.pip.post);
if (nwb != nullptr) nwb->SetPIP(nwid_begin->u.pip.pre, nwid_begin->u.pip.inter, nwid_begin->u.pip.post);
break;
}
case WPT_SCROLLBAR: {
NWidgetCore *nwc = dynamic_cast<NWidgetCore *>(*dest);
if (nwc != nullptr) {
nwc->scrollbar_index = parts->u.widget.index;
nwc->scrollbar_index = nwid_begin->u.widget.index;
}
break;
}
case WPT_ENDCONTAINER:
return num_used;
return nwid_begin;
case NWID_VIEWPORT:
if (*dest != nullptr) return num_used;
*dest = new NWidgetViewport(parts->u.widget.index);
*biggest_index = std::max(*biggest_index, (int)parts->u.widget.index);
if (*dest != nullptr) return nwid_begin;
*dest = new NWidgetViewport(nwid_begin->u.widget.index);
*biggest_index = std::max(*biggest_index, (int)nwid_begin->u.widget.index);
break;
case NWID_HSCROLLBAR:
case NWID_VSCROLLBAR:
if (*dest != nullptr) return num_used;
*dest = new NWidgetScrollbar(parts->type, parts->u.widget.colour, parts->u.widget.index);
*biggest_index = std::max(*biggest_index, (int)parts->u.widget.index);
if (*dest != nullptr) return nwid_begin;
*dest = new NWidgetScrollbar(nwid_begin->type, nwid_begin->u.widget.colour, nwid_begin->u.widget.index);
*biggest_index = std::max(*biggest_index, (int)nwid_begin->u.widget.index);
break;
case NWID_SELECTION: {
if (*dest != nullptr) return num_used;
if (*dest != nullptr) return nwid_begin;
NWidgetStacked *nws = new NWidgetStacked();
*dest = nws;
*fill_dest = true;
nws->SetIndex(parts->u.widget.index);
*biggest_index = std::max(*biggest_index, (int)parts->u.widget.index);
nws->SetIndex(nwid_begin->u.widget.index);
*biggest_index = std::max(*biggest_index, (int)nwid_begin->u.widget.index);
break;
}
default:
if (*dest != nullptr) return num_used;
assert((parts->type & WWT_MASK) < WWT_LAST || (parts->type & WWT_MASK) == NWID_BUTTON_DROPDOWN);
*dest = new NWidgetLeaf(parts->type, parts->u.widget.colour, parts->u.widget.index, 0x0, STR_NULL);
*biggest_index = std::max(*biggest_index, (int)parts->u.widget.index);
if (*dest != nullptr) return nwid_begin;
assert((nwid_begin->type & WWT_MASK) < WWT_LAST || (nwid_begin->type & WWT_MASK) == NWID_BUTTON_DROPDOWN);
*dest = new NWidgetLeaf(nwid_begin->type, nwid_begin->u.widget.colour, nwid_begin->u.widget.index, 0x0, STR_NULL);
*biggest_index = std::max(*biggest_index, (int)nwid_begin->u.widget.index);
break;
}
num_used++;
parts++;
nwid_begin++;
}
return num_used;
return nwid_begin;
}
/**
* Build a nested widget tree by recursively filling containers with nested widgets read from their parts.
* @param parts Array with parts of the nested widgets.
* @param count Length of the \a parts array.
* @param nwid_begin Pointer to beginning of nested widget parts.
* @param nwid_end Pointer to ending of nested widget parts.
* @param parent Pointer or container to use for storing the child widgets (*parent == nullptr or *parent == container or background widget).
* @param biggest_index Pointer to biggest nested widget index in the tree.
* @return Number of widget part elements used to fill the container.
* @return Pointer to remaining nested widget parts.
* @post \c *biggest_index contains the largest widget index of the tree and \c -1 if no index is used.
*/
static int MakeWidgetTree(const NWidgetPart *parts, int count, NWidgetBase **parent, int *biggest_index)
static const NWidgetPart *MakeWidgetTree(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, NWidgetBase **parent, int *biggest_index)
{
/* If *parent == nullptr, only the first widget is read and returned. Otherwise, *parent must point to either
* a #NWidgetContainer or a #NWidgetBackground object, and parts are added as much as possible. */
@@ -3292,13 +3289,10 @@ static int MakeWidgetTree(const NWidgetPart *parts, int count, NWidgetBase **par
NWidgetBackground *nwid_parent = dynamic_cast<NWidgetBackground *>(*parent);
assert(*parent == nullptr || (nwid_cont != nullptr && nwid_parent == nullptr) || (nwid_cont == nullptr && nwid_parent != nullptr));
int total_used = 0;
for (;;) {
NWidgetBase *sub_widget = nullptr;
bool fill_sub = false;
int num_used = MakeNWidget(parts, count - total_used, &sub_widget, &fill_sub, biggest_index);
parts += num_used;
total_used += num_used;
nwid_begin = MakeNWidget(nwid_begin, nwid_end, &sub_widget, &fill_sub, biggest_index);
/* Break out of loop when end reached */
if (sub_widget == nullptr) break;
@@ -3308,9 +3302,7 @@ static int MakeWidgetTree(const NWidgetPart *parts, int count, NWidgetBase **par
if (fill_sub && (tp == NWID_HORIZONTAL || tp == NWID_HORIZONTAL_LTR || tp == NWID_VERTICAL || tp == NWID_MATRIX
|| tp == WWT_PANEL || tp == WWT_FRAME || tp == WWT_INSET || tp == NWID_SELECTION)) {
NWidgetBase *sub_ptr = sub_widget;
int num_used = MakeWidgetTree(parts, count - total_used, &sub_ptr, biggest_index);
parts += num_used;
total_used += num_used;
nwid_begin = MakeWidgetTree(nwid_begin, nwid_end, &sub_ptr, biggest_index);
}
/* Add sub_widget to parent container if available, otherwise return the widget to the caller. */
@@ -3318,21 +3310,21 @@ static int MakeWidgetTree(const NWidgetPart *parts, int count, NWidgetBase **par
if (nwid_parent != nullptr) nwid_parent->Add(sub_widget);
if (nwid_cont == nullptr && nwid_parent == nullptr) {
*parent = sub_widget;
return total_used;
return nwid_begin;
}
}
if (count == total_used) return total_used; // Reached the end of the array of parts?
if (nwid_begin == nwid_end) return nwid_begin; // Reached the end of the array of parts?
assert(total_used < count);
assert(parts->type == WPT_ENDCONTAINER);
return total_used + 1; // *parts is also 'used'
assert(nwid_begin < nwid_end);
assert(nwid_begin->type == WPT_ENDCONTAINER);
return nwid_begin + 1; // *nwid_begin is also 'used'
}
/**
* Construct a nested widget tree from an array of parts.
* @param parts Array with parts of the widgets.
* @param count Length of the \a parts array.
* @param nwid_begin Pointer to beginning of nested widget parts.
* @param nwid_end Pointer to ending of nested widget parts.
* @param biggest_index Pointer to biggest nested widget index collected in the tree.
* @param container Container to add the nested widgets to. In case it is nullptr a vertical container is used.
* @return Root of the nested widget tree, a vertical container containing the entire GUI.
@@ -3340,12 +3332,12 @@ static int MakeWidgetTree(const NWidgetPart *parts, int count, NWidgetBase **par
* @pre \c biggest_index != nullptr
* @post \c *biggest_index contains the largest widget index of the tree and \c -1 if no index is used.
*/
NWidgetContainer *MakeNWidgets(const NWidgetPart *parts, int count, int *biggest_index, NWidgetContainer *container)
NWidgetContainer *MakeNWidgets(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, int *biggest_index, NWidgetContainer *container)
{
*biggest_index = -1;
if (container == nullptr) container = new NWidgetVertical();
NWidgetBase *cont_ptr = container;
MakeWidgetTree(parts, count, &cont_ptr, biggest_index);
MakeWidgetTree(nwid_begin, nwid_end, &cont_ptr, biggest_index);
return container;
}
@@ -3353,8 +3345,8 @@ NWidgetContainer *MakeNWidgets(const NWidgetPart *parts, int count, int *biggest
* Make a nested widget tree for a window from a parts array. Besides loading, it inserts a shading selection widget
* between the title bar and the window body if the first widget in the parts array looks like a title bar (it is a horizontal
* container with a caption widget) and has a shade box widget.
* @param parts Array with parts of the widgets.
* @param count Length of the \a parts array.
* @param nwid_begin Pointer to beginning of nested widget parts.
* @param nwid_end Pointer to ending of nested widget parts.
* @param biggest_index Pointer to biggest nested widget index collected in the tree.
* @param[out] shade_select Pointer to the inserted shade selection widget (\c nullptr if not unserted).
* @return Root of the nested widget tree, a vertical container containing the entire GUI.
@@ -3362,20 +3354,18 @@ NWidgetContainer *MakeNWidgets(const NWidgetPart *parts, int count, int *biggest
* @pre \c biggest_index != nullptr
* @post \c *biggest_index contains the largest widget index of the tree and \c -1 if no index is used.
*/
NWidgetContainer *MakeWindowNWidgetTree(const NWidgetPart *parts, int count, int *biggest_index, NWidgetStacked **shade_select)
NWidgetContainer *MakeWindowNWidgetTree(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, int *biggest_index, NWidgetStacked **shade_select)
{
*biggest_index = -1;
/* Read the first widget recursively from the array. */
NWidgetBase *nwid = nullptr;
int num_used = MakeWidgetTree(parts, count, &nwid, biggest_index);
nwid_begin = MakeWidgetTree(nwid_begin, nwid_end, &nwid, biggest_index);
assert(nwid != nullptr);
parts += num_used;
count -= num_used;
NWidgetContainer *root = new NWidgetVertical;
root->Add(nwid);
if (count == 0) { // There is no body at all.
if (nwid_begin == nwid_end) { // There is no body at all.
*shade_select = nullptr;
return root;
}
@@ -3396,7 +3386,7 @@ NWidgetContainer *MakeWindowNWidgetTree(const NWidgetPart *parts, int count, int
/* Load the remaining parts into 'body'. */
int biggest2 = -1;
MakeNWidgets(parts, count, &biggest2, body);
MakeNWidgets(nwid_begin, nwid_end, &biggest2, body);
*biggest_index = std::max(*biggest_index, biggest2);
return root;