1
0
mirror of https://github.com/OpenTTD/OpenTTD.git synced 2025-08-19 20:49:11 +00:00

Codechange: Use vector/unique_ptr inside widget containers.

This replaces a C-style double-linked-list which required all widgets
to have next/prev pointers, and removes the need for manual pointer management.
This commit is contained in:
2023-12-30 07:36:21 +00:00
committed by Peter Nelson
parent 628092f133
commit 9a3934ae23
5 changed files with 98 additions and 135 deletions

View File

@@ -115,18 +115,18 @@ public:
this->resize_y = 0; // We never resize in this direction
/* First initialise some variables... */
for (NWidgetBase *child_wid = this->head; child_wid != nullptr; child_wid = child_wid->next) {
for (const auto &child_wid : this->children) {
child_wid->SetupSmallestSize(w);
this->smallest_y = std::max(this->smallest_y, child_wid->smallest_y + child_wid->padding.Vertical());
}
/* ... then in a second pass make sure the 'current' sizes are set. Won't change for most widgets. */
for (NWidgetBase *child_wid = this->head; child_wid != nullptr; child_wid = child_wid->next) {
for (const auto &child_wid : this->children) {
child_wid->current_x = child_wid->smallest_x;
child_wid->current_y = this->smallest_y;
}
this->smallest_x = this->head->smallest_x + this->tail->smallest_x; // First and last are always shown, rest not
this->smallest_x = this->children.front()->smallest_x + this->children.back()->smallest_x; // First and last are always shown, rest not
}
void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override
@@ -138,27 +138,38 @@ public:
this->current_x = given_width;
this->current_y = given_height;
given_width -= this->tail->smallest_x;
given_width -= this->children.back()->smallest_x;
/* The first and last widget are always visible, determine which other should be visible */
for (NWidgetBase *child_wid = this->head->next; child_wid->next != nullptr; child_wid = child_wid->next) {
if (given_width > ScaleGUITrad(MINIMUM_NAME_WIDTH_BEFORE_NEW_HEADER) + child_wid->smallest_x && child_wid->prev->current_x != 0) {
given_width -= child_wid->smallest_x;
child_wid->current_x = child_wid->smallest_x; /* Make visible. */
} else {
child_wid->current_x = 0; /* Make invisible. */
if (this->children.size() > 2) {
auto first = std::next(std::begin(this->children));
auto last = std::prev(std::end(this->children));
for (auto it = first; it != last; ++it) {
auto &child_wid = *it;
if (given_width > ScaleGUITrad(MINIMUM_NAME_WIDTH_BEFORE_NEW_HEADER) + child_wid->smallest_x && (*std::prev(it))->current_x != 0) {
given_width -= child_wid->smallest_x;
child_wid->current_x = child_wid->smallest_x; /* Make visible. */
} else {
child_wid->current_x = 0; /* Make invisible. */
}
}
}
/* All remaining space goes to the first (name) widget */
this->head->current_x = given_width;
this->children.front()->current_x = given_width;
/* Now assign the widgets to their rightful place */
uint position = 0; // Place to put next child relative to origin of the container.
for (NWidgetBase *child_wid = rtl ? this->tail : this->head; child_wid != nullptr; child_wid = rtl ? child_wid->prev : child_wid->next) {
auto assign_position = [&](const std::unique_ptr<NWidgetBase> &child_wid) {
if (child_wid->current_x != 0) {
child_wid->AssignSizePosition(sizing, x + position, y, child_wid->current_x, this->current_y, rtl);
position += child_wid->current_x;
}
};
if (rtl) {
std::for_each(std::rbegin(this->children), std::rend(this->children), assign_position);
} else {
std::for_each(std::begin(this->children), std::end(this->children), assign_position);
}
}
};