Skip to content

Commit

Permalink
Codechange: Use single list for hierarchical group lists. (OpenTTD#12330
Browse files Browse the repository at this point in the history
)

Replace both group list implementations (vehicle group list and company colour group list) with a single implementation, using a struct to hold the group and indentation level instead of two separate lists. Parts that were previously duplicated are now shared.
  • Loading branch information
PeterN committed Mar 18, 2024
1 parent ec3c8d3 commit 107c208
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 130 deletions.
73 changes: 16 additions & 57 deletions src/company_gui.cpp
Expand Up @@ -40,6 +40,7 @@
#include "company_cmd.h"
#include "economy_cmd.h"
#include "group_cmd.h"
#include "group_gui.h"
#include "misc_cmd.h"
#include "object_cmd.h"
#include "timer/timer.h"
Expand Down Expand Up @@ -591,8 +592,6 @@ class DropDownListColourItem : public DropDownIcon<DropDownString<DropDownListIt
}
};

typedef GUIList<const Group*> GUIGroupList;

/** Company livery colour scheme window. */
struct SelectCompanyLiveryWindow : public Window {
private:
Expand All @@ -602,7 +601,6 @@ struct SelectCompanyLiveryWindow : public Window {
uint rows;
uint line_height;
GUIGroupList groups;
std::vector<int> indents;
Scrollbar *vscroll;

void ShowColourDropDownMenu(uint32_t widget)
Expand Down Expand Up @@ -660,57 +658,15 @@ struct SelectCompanyLiveryWindow : public Window {
ShowDropDownList(this, std::move(list), sel, widget);
}

void AddChildren(GUIGroupList &source, GroupID parent, int indent)
{
for (const Group *g : source) {
if (g->parent != parent) continue;
this->groups.push_back(g);
this->indents.push_back(indent);
AddChildren(source, g->index, indent + 1);
}
}

void BuildGroupList(CompanyID owner)
{
if (!this->groups.NeedRebuild()) return;

this->groups.clear();
this->indents.clear();

if (this->livery_class >= LC_GROUP_RAIL) {
GUIGroupList list;
VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);

for (const Group *g : Group::Iterate()) {
if (g->owner == owner && g->vehicle_type == vtype) {
list.push_back(g);
}
}

list.ForceResort();

/* Sort the groups by their name */
const Group *last_group[2] = { nullptr, nullptr };
std::string last_name[2] = { {}, {} };
list.Sort([&](const Group * const &a, const Group * const &b) -> bool {
if (a != last_group[0]) {
last_group[0] = a;
SetDParam(0, a->index);
last_name[0] = GetString(STR_GROUP_NAME);
}

if (b != last_group[1]) {
last_group[1] = b;
SetDParam(0, b->index);
last_name[1] = GetString(STR_GROUP_NAME);
}

int r = StrNaturalCompare(last_name[0], last_name[1]); // Sort by name (natural sorting).
if (r == 0) return a->index < b->index;
return r < 0;
});

AddChildren(list, INVALID_GROUP, 0);
BuildGuiGroupList(this->groups, false, owner, vtype);
}

this->groups.shrink_to_fit();
Expand Down Expand Up @@ -774,7 +730,7 @@ struct SelectCompanyLiveryWindow : public Window {

/* Position scrollbar to selected group */
for (uint i = 0; i < this->rows; i++) {
if (this->groups[i]->index == sel) {
if (this->groups[i].group->index == sel) {
this->vscroll->SetPosition(i - this->vscroll->GetCapacity() / 2);
break;
}
Expand Down Expand Up @@ -944,11 +900,11 @@ struct SelectCompanyLiveryWindow : public Window {
}
}
} else {
uint max = static_cast<uint>(std::min<size_t>(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->groups.size()));
for (uint i = this->vscroll->GetPosition(); i < max; ++i) {
const Group *g = this->groups[i];
auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->groups);
for (auto it = first; it != last; ++it) {
const Group *g = it->group;
SetDParam(0, g->index);
draw_livery(STR_GROUP_NAME, g->livery, this->sel == g->index, false, this->indents[i] * WidgetDimensions::scaled.hsep_indent);
draw_livery(STR_GROUP_NAME, g->livery, this->sel == g->index, false, it->indent * WidgetDimensions::scaled.hsep_indent);
}

if (this->vscroll->GetCount() == 0) {
Expand Down Expand Up @@ -991,7 +947,7 @@ struct SelectCompanyLiveryWindow : public Window {
this->BuildGroupList((CompanyID)this->window_number);

if (!this->groups.empty()) {
this->sel = this->groups[0]->index;
this->sel = this->groups[0].group->index;
}
}

Expand All @@ -1008,10 +964,10 @@ struct SelectCompanyLiveryWindow : public Window {
break;

case WID_SCL_MATRIX: {
uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SCL_MATRIX);
if (row >= this->rows) return;

if (this->livery_class < LC_GROUP_RAIL) {
uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, widget);
if (row >= this->rows) return;

LiveryScheme j = (LiveryScheme)row;

for (LiveryScheme scheme = LS_BEGIN; scheme <= j && scheme < LS_END; scheme++) {
Expand All @@ -1025,7 +981,10 @@ struct SelectCompanyLiveryWindow : public Window {
this->sel = 1 << j;
}
} else {
this->sel = this->groups[row]->index;
auto it = this->vscroll->GetScrolledItemFromWidget(this->groups, pt.y, this, widget);
if (it == std::end(this->groups)) return;

this->sel = it->group->index;
}
this->SetDirty();
break;
Expand Down Expand Up @@ -1078,7 +1037,7 @@ struct SelectCompanyLiveryWindow : public Window {

if (!Group::IsValidID(this->sel)) {
this->sel = INVALID_GROUP;
if (!this->groups.empty()) this->sel = this->groups[0]->index;
if (!this->groups.empty()) this->sel = this->groups[0].group->index;
}

this->SetDirty();
Expand Down

0 comments on commit 107c208

Please sign in to comment.