Update to 14.0-beta1

This commit is contained in:
dP
2024-02-04 02:18:17 +05:30
parent 79037e2c65
commit 33ef333b57
1325 changed files with 138465 additions and 70987 deletions

View File

@@ -21,6 +21,7 @@
#include "../querystring_gui.h"
#include "../core/geometry_func.hpp"
#include "../textfile_gui.h"
#include "../fios.h"
#include "network_content_gui.h"
@@ -42,8 +43,10 @@ struct ContentTextfileWindow : public TextfileWindow {
ContentTextfileWindow(TextfileType file_type, const ContentInfo *ci) : TextfileWindow(file_type), ci(ci)
{
const char *textfile = this->ci->GetTextfile(file_type);
this->LoadTextfile(textfile, GetContentInfoSubDir(this->ci->type));
this->ConstructWindow();
auto textfile = this->ci->GetTextfile(file_type);
this->LoadTextfile(textfile.value(), GetContentInfoSubDir(this->ci->type));
}
StringID GetTypeString() const
@@ -63,7 +66,7 @@ struct ContentTextfileWindow : public TextfileWindow {
}
}
void SetStringParameters(int widget) const override
void SetStringParameters(WidgetID widget) const override
{
if (widget == WID_TF_CAPTION) {
SetDParam(0, this->GetTypeString());
@@ -79,7 +82,7 @@ void ShowContentTextfileWindow(TextfileType file_type, const ContentInfo *ci)
}
/** Nested widgets for the download window. */
static const NWidgetPart _nested_network_content_download_status_window_widgets[] = {
static constexpr NWidgetPart _nested_network_content_download_status_window_widgets[] = {
NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CONTENT_DOWNLOAD_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
NWidget(WWT_PANEL, COLOUR_GREY),
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), SetPadding(WidgetDimensions::unscaled.modalpopup),
@@ -91,15 +94,15 @@ static const NWidgetPart _nested_network_content_download_status_window_widgets[
};
/** Window description for the download window */
static WindowDesc _network_content_download_status_window_desc(
static WindowDesc _network_content_download_status_window_desc(__FILE__, __LINE__,
WDP_CENTER, nullptr, 0, 0,
WC_NETWORK_STATUS_WINDOW, WC_NONE,
WDF_MODAL,
_nested_network_content_download_status_window_widgets, lengthof(_nested_network_content_download_status_window_widgets)
std::begin(_nested_network_content_download_status_window_widgets), std::end(_nested_network_content_download_status_window_widgets)
);
BaseNetworkContentDownloadStatusWindow::BaseNetworkContentDownloadStatusWindow(WindowDesc *desc) :
Window(desc), cur_id(UINT32_MAX)
Window(desc), downloaded_bytes(0), downloaded_files(0), cur_id(UINT32_MAX)
{
_network_content_client.AddCallback(this);
_network_content_client.DownloadSelectedContent(this->total_files, this->total_bytes);
@@ -107,13 +110,13 @@ BaseNetworkContentDownloadStatusWindow::BaseNetworkContentDownloadStatusWindow(W
this->InitNested(WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD);
}
void BaseNetworkContentDownloadStatusWindow::Close()
void BaseNetworkContentDownloadStatusWindow::Close([[maybe_unused]] int data)
{
_network_content_client.RemoveCallback(this);
this->Window::Close();
}
void BaseNetworkContentDownloadStatusWindow::UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
void BaseNetworkContentDownloadStatusWindow::UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize)
{
switch (widget) {
case WID_NCDS_PROGRESS_BAR:
@@ -127,23 +130,23 @@ void BaseNetworkContentDownloadStatusWindow::UpdateWidgetSize(int widget, Dimens
break;
case WID_NCDS_PROGRESS_TEXT:
size->height = FONT_HEIGHT_NORMAL * 2 + WidgetDimensions::scaled.vsep_normal;
size->height = GetCharacterHeight(FS_NORMAL) * 2 + WidgetDimensions::scaled.vsep_normal;
break;
}
}
void BaseNetworkContentDownloadStatusWindow::DrawWidget(const Rect &r, int widget) const
void BaseNetworkContentDownloadStatusWindow::DrawWidget(const Rect &r, WidgetID widget) const
{
switch (widget) {
case WID_NCDS_PROGRESS_BAR: {
/* Draw the % complete with a bar and a text */
DrawFrameRect(r, COLOUR_GREY, FR_BORDERONLY | FR_LOWERED);
Rect ir = r.Shrink(WidgetDimensions::scaled.bevel);
DrawFrameRect(ir.WithWidth((uint64)ir.Width() * this->downloaded_bytes / this->total_bytes, false), COLOUR_MAUVE, FR_NONE);
DrawFrameRect(ir.WithWidth((uint64_t)ir.Width() * this->downloaded_bytes / this->total_bytes, false), COLOUR_MAUVE, FR_NONE);
SetDParam(0, this->downloaded_bytes);
SetDParam(1, this->total_bytes);
SetDParam(2, this->downloaded_bytes * 100LL / this->total_bytes);
DrawString(ir.left, ir.right, CenterBounds(ir.top, ir.bottom, FONT_HEIGHT_NORMAL), STR_CONTENT_DOWNLOAD_PROGRESS_SIZE, TC_FROMSTRING, SA_HOR_CENTER);
DrawString(ir.left, ir.right, CenterBounds(ir.top, ir.bottom, GetCharacterHeight(FS_NORMAL)), STR_CONTENT_DOWNLOAD_PROGRESS_SIZE, TC_FROMSTRING, SA_HOR_CENTER);
break;
}
@@ -173,7 +176,13 @@ void BaseNetworkContentDownloadStatusWindow::OnDownloadProgress(const ContentInf
this->downloaded_files++;
}
this->downloaded_bytes += bytes;
/* A negative value means we are resetting; for example, when retrying or using a fallback. */
if (bytes < 0) {
this->downloaded_bytes = 0;
} else {
this->downloaded_bytes += bytes;
}
this->SetDirty();
}
@@ -193,7 +202,7 @@ public:
this->parent = FindWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_CONTENT_LIST);
}
void Close() override
void Close([[maybe_unused]] int data = 0) override
{
TarScanner::Mode mode = TarScanner::NONE;
for (auto ctype : this->receivedTypes) {
@@ -263,7 +272,6 @@ public:
case CONTENT_TYPE_SCENARIO:
case CONTENT_TYPE_HEIGHTMAP:
extern void ScanScenarios();
ScanScenarios();
InvalidateWindowData(WC_SAVELOAD, 0, 0);
break;
@@ -279,7 +287,7 @@ public:
this->BaseNetworkContentDownloadStatusWindow::Close();
}
void OnClick(Point pt, int widget, int click_count) override
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
if (widget == WID_NCDS_CANCELOK) {
if (this->downloaded_bytes != this->total_bytes) {
@@ -320,7 +328,7 @@ enum ContentListFilterCriteria {
/** Window that lists the content that's at the content server */
class NetworkContentListWindow : public Window, ContentCallback {
/** List with content infos. */
typedef GUIList<const ContentInfo *, ContentListFilterData &> GUIContentList;
typedef GUIList<const ContentInfo *, std::nullptr_t, ContentListFilterData &> GUIContentList;
static const uint EDITBOX_MAX_SIZE = 50; ///< Maximum size of the editbox in characters.
@@ -339,34 +347,30 @@ class NetworkContentListWindow : public Window, ContentCallback {
uint filesize_sum; ///< The sum of all selected file sizes
Scrollbar *vscroll; ///< Cache of the vertical scrollbar
static char content_type_strs[CONTENT_TYPE_END][64]; ///< Cached strings for all content types.
static std::string content_type_strs[CONTENT_TYPE_END]; ///< Cached strings for all content types.
/** Search external websites for content */
void OpenExternalSearch()
{
extern void OpenBrowser(const char *url);
std::string url;
url.reserve(1024);
char url[1024];
const char *last = lastof(url);
char *pos = strecpy(url, "https://grfsearch.openttd.org/?", last);
url += "https://grfsearch.openttd.org/?";
if (this->auto_select) {
pos = strecpy(pos, "do=searchgrfid&q=", last);
url += "do=searchgrfid&q=";
bool first = true;
for (const ContentInfo *ci : this->content) {
if (ci->state != ContentInfo::DOES_NOT_EXIST) continue;
if (!first) pos = strecpy(pos, ",", last);
if (!first) url.push_back(',');
first = false;
pos += seprintf(pos, last, "%08X", ci->unique_id);
pos = strecpy(pos, ":", last);
pos = md5sumToString(pos, last, ci->md5sum);
fmt::format_to(std::back_inserter(url), "{:08X}:{}", ci->unique_id, FormatArrayAsHex(ci->md5sum));
}
} else {
pos = strecpy(pos, "do=searchtext&q=", last);
url += "do=searchtext&q=";
/* Escape search term */
for (const char *search = this->filter_editbox.text.buf; *search != '\0'; search++) {
@@ -375,10 +379,9 @@ class NetworkContentListWindow : public Window, ContentCallback {
/* Escape special chars, such as &%,= */
if (*search < 0x30) {
pos += seprintf(pos, last, "%%%02X", *search);
} else if (pos < last) {
*pos = *search;
*++pos = '\0';
fmt::format_to(std::back_inserter(url), "%{:02X}", *search);
} else {
url.push_back(*search);
}
}
}
@@ -422,14 +425,14 @@ class NetworkContentListWindow : public Window, ContentCallback {
this->content.RebuildDone();
this->SortContentList();
this->vscroll->SetCount((int)this->content.size()); // Update the scrollbar
this->vscroll->SetCount(this->content.size()); // Update the scrollbar
this->ScrollToSelected();
}
/** Sort content by name. */
static bool NameSorter(const ContentInfo * const &a, const ContentInfo * const &b)
{
return strnatcmp(a->name.c_str(), b->name.c_str(), true) < 0; // Sort by name (natural sorting).
return StrNaturalCompare(a->name, b->name, true) < 0; // Sort by name (natural sorting).
}
/** Sort content by type. */
@@ -437,7 +440,7 @@ class NetworkContentListWindow : public Window, ContentCallback {
{
int r = 0;
if (a->type != b->type) {
r = strnatcmp(content_type_strs[a->type], content_type_strs[b->type]);
r = StrNaturalCompare(content_type_strs[a->type], content_type_strs[b->type]);
}
if (r == 0) return NameSorter(a, b);
return r < 0;
@@ -464,9 +467,9 @@ class NetworkContentListWindow : public Window, ContentCallback {
static bool CDECL TagNameFilter(const ContentInfo * const *a, ContentListFilterData &filter)
{
filter.string_filter.ResetState();
for (auto &tag : (*a)->tags) filter.string_filter.AddLine(tag.c_str());
for (auto &tag : (*a)->tags) filter.string_filter.AddLine(tag);
filter.string_filter.AddLine((*a)->name.c_str());
filter.string_filter.AddLine((*a)->name);
return filter.string_filter.GetState();
}
@@ -569,7 +572,7 @@ public:
this->InvalidateData();
}
void Close() override
void Close([[maybe_unused]] int data = 0) override
{
_network_content_client.RemoveCallback(this);
this->Window::Close();
@@ -580,7 +583,7 @@ public:
this->checkbox_size = maxdim(maxdim(GetSpriteSize(SPR_BOX_EMPTY), GetSpriteSize(SPR_BOX_CHECKED)), GetSpriteSize(SPR_BLOT));
}
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
{
switch (widget) {
case WID_NCL_CHECKBOX:
@@ -597,14 +600,14 @@ public:
}
case WID_NCL_MATRIX:
resize->height = std::max(this->checkbox_size.height, (uint)FONT_HEIGHT_NORMAL) + padding.height;
resize->height = std::max(this->checkbox_size.height, (uint)GetCharacterHeight(FS_NORMAL)) + padding.height;
size->height = 10 * resize->height;
break;
}
}
void DrawWidget(const Rect &r, int widget) const override
void DrawWidget(const Rect &r, WidgetID widget) const override
{
switch (widget) {
case WID_NCL_DETAILS:
@@ -646,7 +649,7 @@ public:
/* Fill the matrix with the information */
int sprite_y_offset = (this->resize.step_height - this->checkbox_size.height) / 2;
int text_y_offset = (this->resize.step_height - FONT_HEIGHT_NORMAL) / 2;
int text_y_offset = (this->resize.step_height - GetCharacterHeight(FS_NORMAL)) / 2;
Rect mr = r.WithHeight(this->resize.step_height);
auto iter = this->content.begin() + this->vscroll->GetPosition();
@@ -685,7 +688,7 @@ public:
void DrawDetails(const Rect &r) const
{
/* Height for the title banner */
int HEADER_HEIGHT = 3 * FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.frametext.Vertical();
int HEADER_HEIGHT = 3 * GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.frametext.Vertical();
Rect hr = r.WithHeight(HEADER_HEIGHT).Shrink(WidgetDimensions::scaled.frametext);
Rect tr = r.Shrink(WidgetDimensions::scaled.frametext);
@@ -697,15 +700,15 @@ public:
/* Draw the total download size */
SetDParam(0, this->filesize_sum);
DrawString(tr.left, tr.right, tr.bottom - FONT_HEIGHT_NORMAL + 1, STR_CONTENT_TOTAL_DOWNLOAD_SIZE);
DrawString(tr.left, tr.right, tr.bottom - GetCharacterHeight(FS_NORMAL) + 1, STR_CONTENT_TOTAL_DOWNLOAD_SIZE);
if (this->selected == nullptr) return;
/* And fill the rest of the details when there's information to place there */
DrawStringMultiLine(hr.left, hr.right, hr.top + FONT_HEIGHT_NORMAL, hr.bottom, STR_CONTENT_DETAIL_SUBTITLE_UNSELECTED + this->selected->state, TC_FROMSTRING, SA_CENTER);
DrawStringMultiLine(hr.left, hr.right, hr.top + GetCharacterHeight(FS_NORMAL), hr.bottom, STR_CONTENT_DETAIL_SUBTITLE_UNSELECTED + this->selected->state, TC_FROMSTRING, SA_CENTER);
/* Also show the total download size, so keep some space from the bottom */
tr.bottom -= FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_wide;
tr.bottom -= GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_wide;
if (this->selected->upgrade) {
SetDParam(0, STR_CONTENT_TYPE_BASE_GRAPHICS + this->selected->type - CONTENT_TYPE_BASE_GRAPHICS);
@@ -740,8 +743,7 @@ public:
if (!this->selected->dependencies.empty()) {
/* List dependencies */
char buf[DRAW_STRING_BUFFER] = "";
char *p = buf;
std::string buf;
for (auto &cid : this->selected->dependencies) {
/* Try to find the dependency */
ConstContentIterator iter = _network_content_client.Begin();
@@ -749,7 +751,8 @@ public:
const ContentInfo *ci = *iter;
if (ci->id != cid) continue;
p += seprintf(p, lastof(buf), p == buf ? "%s" : ", %s", (*iter)->name.c_str());
if (!buf.empty()) buf += ", ";
buf += (*iter)->name;
break;
}
}
@@ -759,10 +762,10 @@ public:
if (!this->selected->tags.empty()) {
/* List all tags */
char buf[DRAW_STRING_BUFFER] = "";
char *p = buf;
std::string buf;
for (auto &tag : this->selected->tags) {
p += seprintf(p, lastof(buf), p == buf ? "%s" : ", %s", tag.c_str());
if (!buf.empty()) buf += ", ";
buf += tag;
}
SetDParamStr(0, buf);
tr.top = DrawStringMultiLine(tr, STR_CONTENT_DETAIL_TAGS);
@@ -773,23 +776,23 @@ public:
ConstContentVector tree;
_network_content_client.ReverseLookupTreeDependency(tree, this->selected);
char buf[DRAW_STRING_BUFFER] = "";
char *p = buf;
std::string buf;
for (const ContentInfo *ci : tree) {
if (ci == this->selected || ci->state != ContentInfo::SELECTED) continue;
p += seprintf(p, lastof(buf), buf == p ? "%s" : ", %s", ci->name.c_str());
if (!buf.empty()) buf += ", ";
buf += ci->name;
}
if (p != buf) {
if (!buf.empty()) {
SetDParamStr(0, buf);
tr.top = DrawStringMultiLine(tr, STR_CONTENT_DETAIL_SELECTED_BECAUSE_OF);
}
}
}
void OnClick(Point pt, int widget, int click_count) override
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
if (widget >= WID_NCL_TEXTFILE && widget < WID_NCL_TEXTFILE + TFT_END) {
if (widget >= WID_NCL_TEXTFILE && widget < WID_NCL_TEXTFILE + TFT_CONTENT_END) {
if (this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE) return;
ShowContentTextfileWindow((TextfileType)(widget - WID_NCL_TEXTFILE), this->selected);
@@ -798,11 +801,11 @@ public:
switch (widget) {
case WID_NCL_MATRIX: {
uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NCL_MATRIX);
if (id_v >= this->content.size()) return; // click out of bounds
auto it = this->vscroll->GetScrolledItemFromWidget(this->content, pt.y, this, WID_NCL_MATRIX);
if (it == this->content.end()) return; // click out of bounds
this->selected = this->content[id_v];
this->list_pos = id_v;
this->selected = *it;
this->list_pos = it - this->content.begin();
const NWidgetBase *checkbox = this->GetWidget<NWidgetBase>(WID_NCL_CHECKBOX);
if (click_count > 1 || IsInsideBS(pt.x, checkbox->pos_x, checkbox->current_x)) {
@@ -823,7 +826,7 @@ public:
case WID_NCL_NAME:
if (this->content.SortType() == widget - WID_NCL_CHECKBOX) {
this->content.ToggleSortOrder();
if (this->content.size() > 0) this->list_pos = (int)this->content.size() - this->list_pos - 1;
if (!this->content.empty()) this->list_pos = (int)this->content.size() - this->list_pos - 1;
} else {
this->content.SetSortType(widget - WID_NCL_CHECKBOX);
this->content.ForceResort();
@@ -854,8 +857,7 @@ public:
case WID_NCL_OPEN_URL:
if (this->selected != nullptr) {
extern void OpenBrowser(const char *url);
OpenBrowser(this->selected->url.c_str());
OpenBrowser(this->selected->url);
}
break;
@@ -873,7 +875,7 @@ public:
}
}
EventState OnKeyPress(WChar key, uint16 keycode) override
EventState OnKeyPress([[maybe_unused]] char32_t key, uint16_t keycode) override
{
if (this->vscroll->UpdateListPositionOnKeyPress(this->list_pos, keycode) == ES_NOT_HANDLED) {
switch (keycode) {
@@ -892,14 +894,14 @@ public:
return ES_HANDLED;
}
/* space is pressed and filter is focused. */
FALLTHROUGH;
[[fallthrough]];
default:
return ES_NOT_HANDLED;
}
}
if (this->content.size() == 0) {
if (this->content.empty()) {
if (this->UpdateFilterState()) {
this->content.ForceRebuild();
this->InvalidateData();
@@ -921,7 +923,7 @@ public:
return ES_HANDLED;
}
void OnEditboxChanged(int wid) override
void OnEditboxChanged(WidgetID wid) override
{
if (wid == WID_NCL_FILTER) {
this->filter_data.string_filter.SetFilterTerm(this->filter_editbox.text.buf);
@@ -943,7 +945,7 @@ public:
this->InvalidateData(0, false);
}
void OnDownloadComplete(ContentID cid) override
void OnDownloadComplete(ContentID) override
{
this->content.ForceResort();
this->InvalidateData();
@@ -965,7 +967,7 @@ public:
* @param data Information about the changed data.
* @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
*/
void OnInvalidateData(int data = 0, bool gui_scope = true) override
void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
{
if (!gui_scope) return;
if (this->content.NeedRebuild()) this->BuildContentList();
@@ -997,8 +999,8 @@ public:
this->SetWidgetDisabledState(WID_NCL_SELECT_ALL, !show_select_all);
this->SetWidgetDisabledState(WID_NCL_SELECT_UPDATE, !show_select_upgrade);
this->SetWidgetDisabledState(WID_NCL_OPEN_URL, this->selected == nullptr || this->selected->url.empty());
for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
this->SetWidgetDisabledState(WID_NCL_TEXTFILE + tft, this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE || this->selected->GetTextfile(tft) == nullptr);
for (TextfileType tft = TFT_CONTENT_BEGIN; tft < TFT_CONTENT_END; tft++) {
this->SetWidgetDisabledState(WID_NCL_TEXTFILE + tft, this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE || !this->selected->GetTextfile(tft).has_value());
}
this->GetWidget<NWidgetCore>(WID_NCL_CANCEL)->widget_data = this->filesize_sum == 0 ? STR_AI_SETTINGS_CLOSE : STR_AI_LIST_CANCEL;
@@ -1019,7 +1021,7 @@ NetworkContentListWindow::GUIContentList::FilterFunction * const NetworkContentL
&TypeOrSelectedFilter,
};
char NetworkContentListWindow::content_type_strs[CONTENT_TYPE_END][64];
std::string NetworkContentListWindow::content_type_strs[CONTENT_TYPE_END];
/**
* Build array of all strings corresponding to the content types.
@@ -1027,93 +1029,95 @@ char NetworkContentListWindow::content_type_strs[CONTENT_TYPE_END][64];
void BuildContentTypeStringList()
{
for (int i = CONTENT_TYPE_BEGIN; i < CONTENT_TYPE_END; i++) {
GetString(NetworkContentListWindow::content_type_strs[i], STR_CONTENT_TYPE_BASE_GRAPHICS + i - CONTENT_TYPE_BASE_GRAPHICS, lastof(NetworkContentListWindow::content_type_strs[i]));
NetworkContentListWindow::content_type_strs[i] = GetString(STR_CONTENT_TYPE_BASE_GRAPHICS + i - CONTENT_TYPE_BASE_GRAPHICS);
}
}
/** The widgets for the content list. */
static const NWidgetPart _nested_network_content_list_widgets[] = {
static constexpr NWidgetPart _nested_network_content_list_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_CONTENT_TITLE, STR_NULL),
NWidget(WWT_DEFSIZEBOX, COLOUR_LIGHT_BLUE),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_BACKGROUND),
NWidget(NWID_SPACER), SetMinimalSize(0, 7), SetResize(1, 0),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(8, 8, 8),
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), SetPadding(WidgetDimensions::unscaled.sparse_resize),
/* Top */
NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NCL_FILTER_CAPT), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_CONTENT_FILTER_TITLE, STR_NULL), SetAlignment(SA_RIGHT),
NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NCL_FILTER), SetFill(1, 0), SetResize(1, 0),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NCL_FILTER_CAPT), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_CONTENT_FILTER_TITLE, STR_NULL), SetAlignment(SA_RIGHT | SA_VERT_CENTER),
NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NCL_FILTER), SetFill(1, 0), SetResize(1, 0),
SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 7), SetResize(1, 0),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(8, 8, 8),
/* Left side. */
NWidget(NWID_VERTICAL), SetPIP(0, 4, 0),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_VERTICAL),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_CHECKBOX), SetMinimalSize(13, 1), SetDataTip(STR_EMPTY, STR_NULL),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TYPE),
SetDataTip(STR_CONTENT_TYPE_CAPTION, STR_CONTENT_TYPE_CAPTION_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_NAME), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_CONTENT_NAME_CAPTION, STR_CONTENT_NAME_CAPTION_TOOLTIP),
EndContainer(),
/* Lists and info. */
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
/* Left side. */
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_VERTICAL),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_CHECKBOX), SetMinimalSize(13, 1), SetDataTip(STR_EMPTY, STR_NULL),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TYPE),
SetDataTip(STR_CONTENT_TYPE_CAPTION, STR_CONTENT_TYPE_CAPTION_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_NAME), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_CONTENT_NAME_CAPTION, STR_CONTENT_NAME_CAPTION_TOOLTIP),
EndContainer(),
NWidget(WWT_MATRIX, COLOUR_LIGHT_BLUE, WID_NCL_MATRIX), SetResize(1, 14), SetFill(1, 1), SetScrollbar(WID_NCL_SCROLLBAR), SetMatrixDataTip(1, 0, STR_CONTENT_MATRIX_TOOLTIP),
EndContainer(),
NWidget(WWT_MATRIX, COLOUR_LIGHT_BLUE, WID_NCL_MATRIX), SetResize(1, 14), SetFill(1, 1), SetScrollbar(WID_NCL_SCROLLBAR), SetMatrixDataTip(1, 0, STR_CONTENT_MATRIX_TOOLTIP),
NWidget(NWID_VSCROLLBAR, COLOUR_LIGHT_BLUE, WID_NCL_SCROLLBAR),
EndContainer(),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NCL_SEL_ALL_UPDATE),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SELECT_UPDATE), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_CONTENT_SELECT_UPDATES_CAPTION, STR_CONTENT_SELECT_UPDATES_CAPTION_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SELECT_ALL), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_CONTENT_SELECT_ALL_CAPTION, STR_CONTENT_SELECT_ALL_CAPTION_TOOLTIP),
EndContainer(),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_UNSELECT), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_CONTENT_UNSELECT_ALL_CAPTION, STR_CONTENT_UNSELECT_ALL_CAPTION_TOOLTIP),
EndContainer(),
NWidget(NWID_VSCROLLBAR, COLOUR_LIGHT_BLUE, WID_NCL_SCROLLBAR),
EndContainer(),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(0, 8, 0),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NCL_SEL_ALL_UPDATE), SetResize(1, 0), SetFill(1, 0),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SELECT_UPDATE), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_CONTENT_SELECT_UPDATES_CAPTION, STR_CONTENT_SELECT_UPDATES_CAPTION_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SELECT_ALL), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_CONTENT_SELECT_ALL_CAPTION, STR_CONTENT_SELECT_ALL_CAPTION_TOOLTIP),
/* Right side. */
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_DETAILS), SetResize(1, 1), SetFill(1, 1),
EndContainer(),
NWidget(NWID_VERTICAL),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_OPEN_URL), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
EndContainer(),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
EndContainer(),
EndContainer(),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_UNSELECT), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_CONTENT_UNSELECT_ALL_CAPTION, STR_CONTENT_UNSELECT_ALL_CAPTION_TOOLTIP),
EndContainer(),
EndContainer(),
/* Right side. */
NWidget(NWID_VERTICAL), SetPIP(0, 4, 0),
NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_DETAILS), SetResize(1, 1), SetFill(1, 1), EndContainer(),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(0, 8, 0),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
EndContainer(),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(0, 8, 0),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_OPEN_URL), SetResize(1, 0), SetFill(1, 0), SetDataTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
/* Bottom. */
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SEARCH_EXTERNAL), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_CONTENT_SEARCH_EXTERNAL, STR_CONTENT_SEARCH_EXTERNAL_TOOLTIP),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_CANCEL), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_DOWNLOAD), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_CONTENT_DOWNLOAD_CAPTION, STR_CONTENT_DOWNLOAD_CAPTION_TOOLTIP),
EndContainer(),
EndContainer(),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 7), SetResize(1, 0),
/* Bottom. */
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(8, 8, 8),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SEARCH_EXTERNAL), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_CONTENT_SEARCH_EXTERNAL, STR_CONTENT_SEARCH_EXTERNAL_TOOLTIP),
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(0, 8, 0),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_CANCEL), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_DOWNLOAD), SetResize(1, 0), SetFill(1, 0),
SetDataTip(STR_CONTENT_DOWNLOAD_CAPTION, STR_CONTENT_DOWNLOAD_CAPTION_TOOLTIP),
EndContainer(),
EndContainer(),
NWidget(NWID_SPACER), SetMinimalSize(0, 2), SetResize(1, 0),
/* Resize button. */
NWidget(NWID_HORIZONTAL),
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_RESIZEBOX, COLOUR_LIGHT_BLUE),
NWidget(WWT_RESIZEBOX, COLOUR_LIGHT_BLUE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
EndContainer(),
EndContainer(),
};
/** Window description of the content list */
static WindowDesc _network_content_list_desc(
static WindowDesc _network_content_list_desc(__FILE__, __LINE__,
WDP_CENTER, "list_content", 630, 460,
WC_NETWORK_WINDOW, WC_NONE,
0,
_nested_network_content_list_widgets, lengthof(_nested_network_content_list_widgets)
std::begin(_nested_network_content_list_widgets), std::end(_nested_network_content_list_widgets)
);
/**