OpenTTD Source 20250312-master-gcdcc6b491d
network_content_gui.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "../stdafx.h"
11#include "../strings_func.h"
12#include "../gfx_func.h"
13#include "../window_func.h"
14#include "../error.h"
15#include "../ai/ai.hpp"
16#include "../game/game.hpp"
17#include "../base_media_base.h"
18#include "../openttd.h"
19#include "../sortlist_type.h"
20#include "../stringfilter_type.h"
21#include "../querystring_gui.h"
22#include "../core/geometry_func.hpp"
23#include "../textfile_gui.h"
24#include "../fios.h"
25#include "network_content_gui.h"
26
27
28#include "table/strings.h"
29#include "../table/sprites.h"
30
31#include <bitset>
32
33#include "../safeguards.h"
34
35
37static bool _accepted_external_search = false;
38
39
42 const ContentInfo *ci = nullptr;
43
45 {
46 this->ConstructWindow();
47
48 auto textfile = this->ci->GetTextfile(file_type);
49 this->LoadTextfile(textfile.value(), GetContentInfoSubDir(this->ci->type));
50 }
51
52 StringID GetTypeString() const
53 {
54 switch (this->ci->type) {
65 default: NOT_REACHED();
66 }
67 }
68
69 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
70 {
71 if (widget == WID_TF_CAPTION) {
72 return GetString(stringid, this->GetTypeString(), this->ci->name);
73 }
74
75 return this->Window::GetWidgetString(widget, stringid);
76 }
77};
78
79void ShowContentTextfileWindow(TextfileType file_type, const ContentInfo *ci)
80{
81 CloseWindowById(WC_TEXTFILE, file_type);
82 new ContentTextfileWindow(file_type, ci);
83}
84
87 NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_CONTENT_DOWNLOAD_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
88 NWidget(WWT_PANEL, COLOUR_GREY),
90 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NCDS_PROGRESS_BAR), SetFill(1, 0),
91 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NCDS_PROGRESS_TEXT), SetFill(1, 0), SetMinimalSize(350, 0),
92 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCDS_CANCELOK), SetStringTip(STR_BUTTON_CANCEL), SetFill(1, 0),
95};
96
99 WDP_CENTER, nullptr, 0, 0,
103);
104
112
114{
116 this->Window::Close();
117}
118
119void BaseNetworkContentDownloadStatusWindow::UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize)
120{
121 switch (widget) {
123 auto max_value = GetParamMaxDigits(8);
124 size = GetStringBoundingBox(GetString(STR_CONTENT_DOWNLOAD_PROGRESS_SIZE, max_value, max_value, max_value));
125 /* We need some spacing for the 'border' */
128 break;
129 }
130
133 break;
134 }
135}
136
138{
139 switch (widget) {
141 /* Draw the % complete with a bar and a text */
144 DrawFrameRect(ir.WithWidth((uint64_t)ir.Width() * this->downloaded_bytes / this->total_bytes, _current_text_dir == TD_RTL), COLOUR_MAUVE, {});
145 DrawString(ir.left, ir.right, CenterBounds(ir.top, ir.bottom, GetCharacterHeight(FS_NORMAL)),
147 TC_FROMSTRING, SA_HOR_CENTER);
148 break;
149 }
150
152 if (this->downloaded_bytes == this->total_bytes) {
154 } else if (!this->name.empty()) {
157 TC_FROMSTRING, SA_CENTER);
158 } else {
160 }
161 break;
162 }
163}
164
166{
167 if (ci->id != this->cur_id) {
168 this->name = ci->filename;
169 this->cur_id = ci->id;
170 this->downloaded_files++;
171 }
172
173 /* A negative value means we are resetting; for example, when retrying or using a fallback. */
174 if (bytes < 0) {
175 this->downloaded_bytes = 0;
176 } else {
177 this->downloaded_bytes += bytes;
178 }
179
180 this->SetDirty();
181}
182
183
186private:
187 std::vector<ContentType> receivedTypes{};
188
189public:
198
199 void Close([[maybe_unused]] int data = 0) override
200 {
202 for (auto ctype : this->receivedTypes) {
203 switch (ctype) {
204 case CONTENT_TYPE_AI:
206 /* AI::Rescan calls the scanner. */
207 break;
210 /* Game::Rescan calls the scanner. */
211 break;
212
217 break;
218
220 /* ScanNewGRFFiles calls the scanner. */
221 break;
222
226 break;
227
228 default:
229 break;
230 }
231 }
232
234
235 /* Tell all the backends about what we've downloaded */
236 for (auto ctype : this->receivedTypes) {
237 switch (ctype) {
238 case CONTENT_TYPE_AI:
240 AI::Rescan();
241 break;
242
245 Game::Rescan();
246 break;
247
251 break;
252
256 break;
257
261 break;
262
265 break;
266
271 break;
272
273 default:
274 break;
275 }
276 }
277
278 /* Always invalidate the download window; tell it we are going to be gone */
280
282 }
283
284 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
285 {
286 if (widget == WID_NCDS_CANCELOK) {
287 if (this->downloaded_bytes != this->total_bytes) {
289 this->Close();
290 } else {
291 /* If downloading succeeded, close the online content window. This will close
292 * the current window as well. */
294 }
295 }
296 }
297
298 void OnDownloadProgress(const ContentInfo *ci, int bytes) override
299 {
301 include(this->receivedTypes, ci->type);
302
303 /* When downloading is finished change cancel in ok */
304 if (this->downloaded_bytes == this->total_bytes) {
306 }
307 }
308};
309
313 std::bitset<CONTENT_TYPE_END> types;
314};
315
321
326
327 static const uint EDITBOX_MAX_SIZE = 50;
328
329 static Listing last_sorting;
331 static const std::initializer_list<GUIContentList::SortFunction * const> sorter_funcs;
332 static const std::initializer_list<GUIContentList::FilterFunction * const> filter_funcs;
334 bool auto_select = false;
338
339 const ContentInfo *selected = nullptr;
340 int list_pos = 0;
341 uint filesize_sum = 0;
342 Scrollbar *vscroll = nullptr;
343
345
348 {
349 std::string url;
350 url.reserve(1024);
351
352 url += "https://grfsearch.openttd.org/?";
353
354 if (this->auto_select) {
355 url += "do=searchgrfid&q=";
356
357 bool first = true;
358 for (const ContentInfo *ci : this->content) {
359 if (ci->state != ContentInfo::DOES_NOT_EXIST) continue;
360
361 if (!first) url.push_back(',');
362 first = false;
363
364 fmt::format_to(std::back_inserter(url), "{:08X}:{}", ci->unique_id, FormatArrayAsHex(ci->md5sum));
365 }
366 } else {
367 url += "do=searchtext&q=";
368
369 /* Escape search term */
370 for (const char *search = this->filter_editbox.text.GetText(); *search != '\0'; search++) {
371 /* Remove quotes */
372 if (*search == '\'' || *search == '"') continue;
373
374 /* Escape special chars, such as &%,= */
375 if (*search < 0x30) {
376 fmt::format_to(std::back_inserter(url), "%{:02X}", *search);
377 } else {
378 url.push_back(*search);
379 }
380 }
381 }
382
383 OpenBrowser(url);
384 }
385
389 static void ExternalSearchDisclaimerCallback(Window *w, bool accepted)
390 {
391 if (accepted) {
393 ((NetworkContentListWindow*)w)->OpenExternalSearch();
394 }
395 }
396
402 {
403 if (!this->content.NeedRebuild()) return;
404
405 /* Create temporary array of games to use for listing */
406 this->content.clear();
407
408 bool all_available = true;
409
411 if ((*iter)->state == ContentInfo::DOES_NOT_EXIST) all_available = false;
412 this->content.push_back(*iter);
413 }
414
416
417 this->FilterContentList();
418 this->content.RebuildDone();
419 this->SortContentList();
420
421 this->vscroll->SetCount(this->content.size()); // Update the scrollbar
422 this->ScrollToSelected();
423 }
424
426 static bool NameSorter(const ContentInfo * const &a, const ContentInfo * const &b)
427 {
428 return StrNaturalCompare(a->name, b->name, true) < 0; // Sort by name (natural sorting).
429 }
430
432 static bool TypeSorter(const ContentInfo * const &a, const ContentInfo * const &b)
433 {
434 int r = 0;
435 if (a->type != b->type) {
437 }
438 if (r == 0) return NameSorter(a, b);
439 return r < 0;
440 }
441
443 static bool StateSorter(const ContentInfo * const &a, const ContentInfo * const &b)
444 {
445 int r = a->state - b->state;
446 if (r == 0) return TypeSorter(a, b);
447 return r < 0;
448 }
449
452 {
453 if (!this->content.Sort()) return;
454
455 int idx = find_index(this->content, this->selected);
456 if (idx >= 0) this->list_pos = idx;
457 }
458
460 static bool TagNameFilter(const ContentInfo * const *a, ContentListFilterData &filter)
461 {
462 if ((*a)->state == ContentInfo::SELECTED || (*a)->state == ContentInfo::AUTOSELECTED) return true;
463
464 filter.string_filter.ResetState();
465 for (auto &tag : (*a)->tags) filter.string_filter.AddLine(tag);
466
467 filter.string_filter.AddLine((*a)->name);
468 return filter.string_filter.GetState();
469 }
470
472 static bool TypeOrSelectedFilter(const ContentInfo * const *a, ContentListFilterData &filter)
473 {
474 if (filter.types.none()) return true;
475 if (filter.types[(*a)->type]) return true;
476 return ((*a)->state == ContentInfo::SELECTED || (*a)->state == ContentInfo::AUTOSELECTED);
477 }
478
481 {
482 /* Apply filters. */
483 bool changed = false;
484 if (!this->filter_data.string_filter.IsEmpty()) {
486 changed |= this->content.Filter(this->filter_data);
487 }
488 if (this->filter_data.types.any()) {
490 changed |= this->content.Filter(this->filter_data);
491 }
492 if (!changed) return;
493
494 /* update list position */
495 int idx = find_index(this->content, this->selected);
496 if (idx >= 0) {
497 this->list_pos = idx;
498 return;
499 }
500
501 /* previously selected item not in list anymore */
502 this->selected = nullptr;
503 this->list_pos = 0;
504 }
505
511 {
513 bool new_state = !this->filter_data.string_filter.IsEmpty() || this->filter_data.types.any();
514 if (new_state != old_params.state) {
515 this->content.SetFilterState(new_state);
516 }
517 return new_state != old_params.state;
518 }
519
522 {
523 if (this->selected == nullptr) return;
524
525 this->vscroll->ScrollTowards(this->list_pos);
526 }
527
529public:
539 NetworkContentListWindow(WindowDesc &desc, bool select_all, const std::bitset<CONTENT_TYPE_END> &types) :
540 Window(desc),
543 {
544 this->CreateNestedTree();
545 this->vscroll = this->GetScrollbar(WID_NCL_SCROLLBAR);
547
548 this->GetWidget<NWidgetStacked>(WID_NCL_SEL_ALL_UPDATE)->SetDisplayedPlane(select_all);
549
551 this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
553 this->SetWidgetDisabledState(WID_NCL_SEARCH_EXTERNAL, this->auto_select);
554 this->filter_data.types = types;
555
557 this->content.SetListing(this->last_sorting);
558 this->content.SetFiltering(this->last_filtering);
559 this->content.SetSortFuncs(this->sorter_funcs);
560 this->content.SetFilterFuncs(this->filter_funcs);
561 this->UpdateFilterState();
562 this->content.ForceRebuild();
563 this->FilterContentList();
564 this->SortContentList();
565 this->InvalidateData();
566 }
567
568 void Close([[maybe_unused]] int data = 0) override
569 {
571 this->Window::Close();
572 }
573
574 void OnInit() override
575 {
576 this->checkbox_size = maxdim(maxdim(GetScaledSpriteSize(SPR_BOX_EMPTY), GetScaledSpriteSize(SPR_BOX_CHECKED)), GetScaledSpriteSize(SPR_BLOT));
577 }
578
580 {
581 switch (widget) {
582 case WID_NCL_CHECKBOX:
583 size.width = this->checkbox_size.width + padding.width;
584 break;
585
586 case WID_NCL_TYPE: {
587 Dimension d = size;
588 for (int i = CONTENT_TYPE_BEGIN; i < CONTENT_TYPE_END; i++) {
590 }
591 size.width = d.width + padding.width;
592 break;
593 }
594
595 case WID_NCL_MATRIX:
596 resize.height = std::max(this->checkbox_size.height, (uint)GetCharacterHeight(FS_NORMAL)) + padding.height;
597 size.height = 10 * resize.height;
598 break;
599 }
600 }
601
602
603 void DrawWidget(const Rect &r, WidgetID widget) const override
604 {
605 switch (widget) {
606 case WID_NCL_DETAILS:
607 this->DrawDetails(r);
608 break;
609
610 case WID_NCL_MATRIX:
611 this->DrawMatrix(r);
612 break;
613 }
614 }
615
616 void OnPaint() override
617 {
619
620 if (this->content.NeedRebuild()) {
621 this->BuildContentList();
622 }
623
624 this->DrawWidgets();
625
626 switch (this->content.SortType()) {
630 }
631 }
632
637 void DrawMatrix(const Rect &r) const
638 {
639 const Rect checkbox = this->GetWidget<NWidgetBase>(WID_NCL_CHECKBOX)->GetCurrentRect();
640 const Rect name = this->GetWidget<NWidgetBase>(WID_NCL_NAME)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
641 const Rect type = this->GetWidget<NWidgetBase>(WID_NCL_TYPE)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
642
643 /* Fill the matrix with the information */
644 const uint step_height = this->GetWidget<NWidgetBase>(WID_NCL_MATRIX)->resize_y;
646
647 Rect mr = r.WithHeight(step_height);
648 auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->content);
649 for (auto iter = first; iter != last; iter++) {
650 const ContentInfo *ci = *iter;
651
652 if (ci == this->selected) GfxFillRect(mr.Shrink(WidgetDimensions::scaled.bevel), PC_GREY);
653
654 SpriteID sprite;
655 SpriteID pal = PAL_NONE;
656 switch (ci->state) {
657 case ContentInfo::UNSELECTED: sprite = SPR_BOX_EMPTY; break;
658 case ContentInfo::SELECTED: sprite = SPR_BOX_CHECKED; break;
659 case ContentInfo::AUTOSELECTED: sprite = SPR_BOX_CHECKED; break;
660 case ContentInfo::ALREADY_HERE: sprite = SPR_BLOT; pal = PALETTE_TO_GREEN; break;
661 case ContentInfo::DOES_NOT_EXIST: sprite = SPR_BLOT; pal = PALETTE_TO_RED; break;
662 default: NOT_REACHED();
663 }
664 DrawSpriteIgnorePadding(sprite, pal, {checkbox.left, mr.top, checkbox.right, mr.bottom}, SA_CENTER);
665
667 DrawString(type.left, type.right, mr.top + text_y_offset, str, TC_BLACK, SA_HOR_CENTER);
668
669 DrawString(name.left, name.right, mr.top + text_y_offset, ci->name, TC_BLACK);
670 mr = mr.Translate(0, step_height);
671 }
672 }
673
678 void DrawDetails(const Rect &r) const
679 {
680 /* Height for the title banner */
682
684 Rect tr = r.Shrink(WidgetDimensions::scaled.frametext);
685 tr.top += HEADER_HEIGHT;
686
687 /* Create the nice grayish rectangle at the details top */
689 DrawString(hr.left, hr.right, hr.top, STR_CONTENT_DETAIL_TITLE, TC_FROMSTRING, SA_HOR_CENTER);
690
691 /* Draw the total download size */
692 DrawString(tr.left, tr.right, tr.bottom - GetCharacterHeight(FS_NORMAL) + 1, GetString(STR_CONTENT_TOTAL_DOWNLOAD_SIZE, this->filesize_sum));
693
694 if (this->selected == nullptr) return;
695
696 /* And fill the rest of the details when there's information to place there */
697 DrawStringMultiLine(hr.left, hr.right, hr.top + GetCharacterHeight(FS_NORMAL), hr.bottom, STR_CONTENT_DETAIL_SUBTITLE_UNSELECTED + this->selected->state, TC_FROMSTRING, SA_CENTER);
698
699 /* Also show the total download size, so keep some space from the bottom */
701
702 if (this->selected->upgrade) {
705 }
706
708
709 if (!this->selected->version.empty()) {
711 }
712
713 if (!this->selected->description.empty()) {
715 }
716
717 if (!this->selected->url.empty()) {
719 }
720
722
725
726 std::string_view list_separator = GetListSeparator();
727 if (!this->selected->dependencies.empty()) {
728 /* List dependencies */
729 std::string buf;
730 for (auto &cid : this->selected->dependencies) {
731 /* Try to find the dependency */
733 for (; iter != _network_content_client.End(); iter++) {
734 const ContentInfo *ci = *iter;
735 if (ci->id != cid) continue;
736
737 if (!buf.empty()) buf += list_separator;
738 buf += (*iter)->name;
739 break;
740 }
741 }
743 }
744
745 if (!this->selected->tags.empty()) {
746 /* List all tags */
747 std::string buf;
748 for (auto &tag : this->selected->tags) {
749 if (!buf.empty()) buf += list_separator;
750 buf += tag;
751 }
753 }
754
755 if (this->selected->IsSelected()) {
756 /* When selected show all manually selected content that depends on this */
759
760 std::string buf;
761 for (const ContentInfo *ci : tree) {
762 if (ci == this->selected || ci->state != ContentInfo::SELECTED) continue;
763
764 if (!buf.empty()) buf += list_separator;
765 buf += ci->name;
766 }
767 if (!buf.empty()) {
769 }
770 }
771 }
772
773 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
774 {
775 if (widget >= WID_NCL_TEXTFILE && widget < WID_NCL_TEXTFILE + TFT_CONTENT_END) {
776 if (this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE) return;
777
778 ShowContentTextfileWindow((TextfileType)(widget - WID_NCL_TEXTFILE), this->selected);
779 return;
780 }
781
782 switch (widget) {
783 case WID_NCL_MATRIX: {
784 auto it = this->vscroll->GetScrolledItemFromWidget(this->content, pt.y, this, WID_NCL_MATRIX);
785 if (it == this->content.end()) return; // click out of bounds
786
787 this->selected = *it;
788 this->list_pos = it - this->content.begin();
789
791 if (click_count > 1 || IsInsideBS(pt.x, checkbox->pos_x, checkbox->current_x)) {
793 this->content.ForceResort();
794 this->content.ForceRebuild();
795 }
796
797 if (this->filter_data.types.any()) {
798 this->content.ForceRebuild();
799 }
800
801 this->InvalidateData();
802 break;
803 }
804
805 case WID_NCL_CHECKBOX:
806 case WID_NCL_TYPE:
807 case WID_NCL_NAME:
808 if (this->content.SortType() == widget - WID_NCL_CHECKBOX) {
809 this->content.ToggleSortOrder();
810 if (!this->content.empty()) this->list_pos = (int)this->content.size() - this->list_pos - 1;
811 } else {
812 this->content.SetSortType(widget - WID_NCL_CHECKBOX);
813 this->content.ForceResort();
814 this->SortContentList();
815 }
816 this->ScrollToSelected();
817 this->InvalidateData();
818 break;
819
822 this->InvalidateData();
823 break;
824
827 this->InvalidateData();
828 break;
829
830 case WID_NCL_UNSELECT:
832 this->InvalidateData();
833 break;
834
835 case WID_NCL_CANCEL:
836 this->Close();
837 break;
838
839 case WID_NCL_OPEN_URL:
840 if (this->selected != nullptr) {
841 OpenBrowser(this->selected->url);
842 }
843 break;
844
845 case WID_NCL_DOWNLOAD:
847 break;
848
851 this->OpenExternalSearch();
852 } else {
853 ShowQuery(
857 }
858 break;
859 }
860 }
861
862 EventState OnKeyPress([[maybe_unused]] char32_t key, uint16_t keycode) override
863 {
864 if (this->vscroll->UpdateListPositionOnKeyPress(this->list_pos, keycode) == ES_NOT_HANDLED) {
865 switch (keycode) {
866 case WKC_SPACE:
867 case WKC_RETURN:
868 if (keycode == WKC_RETURN || !IsWidgetFocused(WID_NCL_FILTER)) {
869 if (this->selected != nullptr) {
871 this->content.ForceResort();
872 this->InvalidateData();
873 }
874 if (this->filter_data.types.any()) {
875 this->content.ForceRebuild();
876 this->InvalidateData();
877 }
878 return ES_HANDLED;
879 }
880 /* space is pressed and filter is focused. */
881 [[fallthrough]];
882
883 default:
884 return ES_NOT_HANDLED;
885 }
886 }
887
888 if (this->content.empty()) {
889 if (this->UpdateFilterState()) {
890 this->content.ForceRebuild();
891 this->InvalidateData();
892 }
893 return ES_HANDLED;
894 }
895
896 this->selected = this->content[this->list_pos];
897
898 if (this->UpdateFilterState()) {
899 this->content.ForceRebuild();
900 } else {
901 /* Scroll to the new content if it is outside the current range. */
902 this->ScrollToSelected();
903 }
904
905 /* redraw window */
906 this->InvalidateData();
907 return ES_HANDLED;
908 }
909
911 {
912 if (wid == WID_NCL_FILTER) {
913 this->filter_data.string_filter.SetFilterTerm(this->filter_editbox.text.GetText());
914 this->UpdateFilterState();
915 this->content.ForceRebuild();
916 this->InvalidateData();
917 }
918 }
919
920 void OnResize() override
921 {
922 this->vscroll->SetCapacityFromWidget(this, WID_NCL_MATRIX);
923 }
924
926 {
927 if (this->auto_select && !rci->IsSelected()) _network_content_client.ToggleSelectedState(rci);
928 this->content.ForceRebuild();
929 this->InvalidateData(0, false);
930 }
931
933 {
934 this->content.ForceResort();
935 this->InvalidateData();
936 }
937
938 void OnConnect(bool success) override
939 {
940 if (!success) {
942 this->Close();
943 return;
944 }
945
946 this->InvalidateData();
947 }
948
954 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
955 {
956 if (!gui_scope) return;
957 if (this->content.NeedRebuild()) this->BuildContentList();
958
959 /* To sum all the bytes we intend to download */
960 this->filesize_sum = 0;
961 bool show_select_all = false;
962 bool show_select_upgrade = false;
963 for (const ContentInfo *ci : this->content) {
964 switch (ci->state) {
967 this->filesize_sum += ci->filesize;
968 break;
969
971 show_select_all = true;
973 break;
974
975 default:
976 break;
977 }
978 }
979
980 /* If data == 2 then the status window caused this OnInvalidate */
982 this->SetWidgetDisabledState(WID_NCL_UNSELECT, this->filesize_sum == 0);
983 this->SetWidgetDisabledState(WID_NCL_SELECT_ALL, !show_select_all);
984 this->SetWidgetDisabledState(WID_NCL_SELECT_UPDATE, !show_select_upgrade || !this->filter_data.string_filter.IsEmpty());
985 this->SetWidgetDisabledState(WID_NCL_OPEN_URL, this->selected == nullptr || this->selected->url.empty());
986 for (TextfileType tft = TFT_CONTENT_BEGIN; tft < TFT_CONTENT_END; tft++) {
987 this->SetWidgetDisabledState(WID_NCL_TEXTFILE + tft, this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE || !this->selected->GetTextfile(tft).has_value());
988 }
989
990 this->GetWidget<NWidgetCore>(WID_NCL_CANCEL)->SetString(this->filesize_sum == 0 ? STR_AI_SETTINGS_CLOSE : STR_AI_LIST_CANCEL);
991 }
992};
993
996
997const std::initializer_list<NetworkContentListWindow::GUIContentList::SortFunction * const> NetworkContentListWindow::sorter_funcs = {
998 &StateSorter,
999 &TypeSorter,
1000 &NameSorter,
1001};
1002
1003const std::initializer_list<NetworkContentListWindow::GUIContentList::FilterFunction * const> NetworkContentListWindow::filter_funcs = {
1004 &TagNameFilter,
1005 &TypeOrSelectedFilter,
1006};
1007
1009
1014{
1015 for (int i = CONTENT_TYPE_BEGIN; i < CONTENT_TYPE_END; i++) {
1016 NetworkContentListWindow::content_type_strs[i] = GetString(STR_CONTENT_TYPE_BASE_GRAPHICS + i - CONTENT_TYPE_BASE_GRAPHICS);
1017 }
1018}
1019
1023 NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
1024 NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetStringTip(STR_CONTENT_TITLE),
1025 NWidget(WWT_DEFSIZEBOX, COLOUR_LIGHT_BLUE),
1026 EndContainer(),
1027 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_BACKGROUND),
1029 /* Top */
1031 NWidget(WWT_TEXT, INVALID_COLOUR, WID_NCL_FILTER_CAPT), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_CONTENT_FILTER_TITLE), SetAlignment(SA_RIGHT | SA_VERT_CENTER),
1032 NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NCL_FILTER), SetFill(1, 0), SetResize(1, 0),
1033 SetStringTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
1034 EndContainer(),
1035 /* Lists and info. */
1037 /* Left side. */
1042 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_CHECKBOX), SetStringTip(STR_EMPTY),
1043 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TYPE),
1044 SetStringTip(STR_CONTENT_TYPE_CAPTION, STR_CONTENT_TYPE_CAPTION_TOOLTIP),
1045 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_NAME), SetResize(1, 0), SetFill(1, 0),
1046 SetStringTip(STR_CONTENT_NAME_CAPTION, STR_CONTENT_NAME_CAPTION_TOOLTIP),
1047 EndContainer(),
1048 NWidget(WWT_MATRIX, COLOUR_LIGHT_BLUE, WID_NCL_MATRIX), SetResize(1, 1), SetFill(1, 1), SetScrollbar(WID_NCL_SCROLLBAR), SetMatrixDataTip(1, 0, STR_CONTENT_MATRIX_TOOLTIP),
1049 EndContainer(),
1050 NWidget(NWID_VSCROLLBAR, COLOUR_LIGHT_BLUE, WID_NCL_SCROLLBAR),
1051 EndContainer(),
1054 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SELECT_UPDATE), SetResize(1, 0), SetFill(1, 0),
1055 SetStringTip(STR_CONTENT_SELECT_UPDATES_CAPTION, STR_CONTENT_SELECT_UPDATES_CAPTION_TOOLTIP),
1056 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SELECT_ALL), SetResize(1, 0), SetFill(1, 0),
1057 SetStringTip(STR_CONTENT_SELECT_ALL_CAPTION, STR_CONTENT_SELECT_ALL_CAPTION_TOOLTIP),
1058 EndContainer(),
1059 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_UNSELECT), SetResize(1, 0), SetFill(1, 0),
1060 SetStringTip(STR_CONTENT_UNSELECT_ALL_CAPTION, STR_CONTENT_UNSELECT_ALL_CAPTION_TOOLTIP),
1061 EndContainer(),
1062 EndContainer(),
1063 /* Right side. */
1065 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_DETAILS), SetResize(1, 1), SetFill(1, 1),
1066 EndContainer(),
1069 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_OPEN_URL), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
1070 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
1071 EndContainer(),
1073 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
1074 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
1075 EndContainer(),
1076 EndContainer(),
1077 EndContainer(),
1078 EndContainer(),
1079 /* Bottom. */
1081 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SEARCH_EXTERNAL), SetResize(1, 0), SetFill(1, 0),
1082 SetStringTip(STR_CONTENT_SEARCH_EXTERNAL, STR_CONTENT_SEARCH_EXTERNAL_TOOLTIP),
1084 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_CANCEL), SetResize(1, 0), SetFill(1, 0),
1085 SetStringTip(STR_BUTTON_CANCEL),
1086 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_DOWNLOAD), SetResize(1, 0), SetFill(1, 0),
1087 SetStringTip(STR_CONTENT_DOWNLOAD_CAPTION, STR_CONTENT_DOWNLOAD_CAPTION_TOOLTIP),
1088 EndContainer(),
1089 EndContainer(),
1090 EndContainer(),
1091 /* Resize button. */
1093 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1094 NWidget(WWT_RESIZEBOX, COLOUR_LIGHT_BLUE), SetResizeWidgetTypeTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
1095 EndContainer(),
1096 EndContainer(),
1097};
1098
1101 WDP_CENTER, "list_content", 630, 460,
1103 {},
1105);
1106
1115{
1116#if defined(WITH_ZLIB)
1117 std::bitset<CONTENT_TYPE_END> types;
1119 if (cv == nullptr) {
1120 assert(type1 != CONTENT_TYPE_END || type2 == CONTENT_TYPE_END);
1121 assert(type1 == CONTENT_TYPE_END || type1 != type2);
1124
1125 if (type1 != CONTENT_TYPE_END) types[type1] = true;
1126 if (type2 != CONTENT_TYPE_END) types[type2] = true;
1127 } else {
1129 }
1130
1132 new NetworkContentListWindow(_network_content_list_desc, cv != nullptr, types);
1133#else
1135 GetEncodedString(STR_CONTENT_NO_ZLIB),
1136 GetEncodedString(STR_CONTENT_NO_ZLIB_SUB),
1137 WL_ERROR);
1138 /* Connection failed... clean up the mess */
1139 if (cv != nullptr) {
1140 for (ContentInfo *ci : *cv) delete ci;
1141 }
1142#endif /* WITH_ZLIB */
1143}
static void Rescan()
Rescans all searchpaths for available AIs.
Definition ai_core.cpp:326
constexpr Timpl & Set()
Set all bits.
static uint FindSets()
Do the scan for files.
Base window for showing the download status of content.
uint32_t cur_id
The current ID of the downloaded file.
BaseNetworkContentDownloadStatusWindow(WindowDesc &desc)
Create the window with the given description.
void OnDownloadProgress(const ContentInfo *ci, int bytes) override
We have progress in the download of a file.
uint downloaded_bytes
Number of bytes downloaded.
uint total_files
Number of files to download.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
std::string name
The current name of the downloaded file.
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
uint downloaded_files
Number of files downloaded.
uint total_bytes
Number of bytes to download.
ConstContentIterator Begin() const
Get the begin of the content inf iterator.
void SelectUpgrade()
Select everything that's an update for something we've got.
void DownloadSelectedContent(uint &files, uint &bytes, bool fallback=false)
Actually begin downloading the content we selected.
void ToggleSelectedState(const ContentInfo *ci)
Toggle the state of a content info and check its dependencies.
void RemoveCallback(ContentCallback *cb)
Remove a callback.
void UnselectAll()
Unselect everything that we've not downloaded so far.
void RequestContentList(ContentType type)
Request the content list for the given type.
void ReverseLookupTreeDependency(ConstContentVector &tree, const ContentInfo *child) const
Reverse lookup the dependencies of all parents over a given child.
void AddCallback(ContentCallback *cb)
Add a callback to this class.
void Clear()
Clear all downloaded content information.
ConstContentIterator End() const
Get the end of the content inf iterator.
void Cancel()
Cancel the current download.
void SelectAll()
Select everything we can select.
Enum-as-bit-set wrapper.
List template of 'things' T to sort in a GUI.
bool Filter(FilterFunction *decide, F filter_data)
Filter the list.
void RebuildDone()
Notify the sortlist that the rebuild is done.
void SetFiltering(Filtering f)
Import filter conditions.
void SetListing(Listing l)
Import sort conditions.
void SetFilterState(bool state)
Enable or disable the filter.
bool IsDescSortOrder() const
Check if the sort order is descending.
void ToggleSortOrder()
Toggle the sort order Since that is the worst condition for the sort function reverse the list here.
void SetFilterFuncs(std::span< FilterFunction *const > n_funcs)
Hand the filter function pointers to the GUIList.
Filtering GetFiltering() const
Export current filter conditions.
bool NeedRebuild() const
Check if a rebuild is needed.
void SetFilterType(uint8_t n_type)
Set the filtertype of the list.
void ForceRebuild()
Force that a rebuild is needed.
bool Sort(Comp compare)
Sort the list.
void ForceResort()
Force a resort next Sort call Reset the resort timer if used too.
uint8_t SortType() const
Get the sorttype of the list.
void SetSortFuncs(std::span< SortFunction *const > n_funcs)
Hand the sort function pointers to the GUIList.
void SetSortType(uint8_t n_type)
Set the sorttype of the list.
Baseclass for nested widgets.
Window that lists the content that's at the content server.
EventState OnKeyPress(char32_t key, uint16_t keycode) override
A key has been pressed.
static bool NameSorter(const ContentInfo *const &a, const ContentInfo *const &b)
Sort content by name.
void OnReceiveContentInfo(const ContentInfo *rci) override
We received a content info.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void DrawDetails(const Rect &r) const
Helper function to draw the details part of this window.
void OpenExternalSearch()
Search external websites for content.
void DrawMatrix(const Rect &r) const
Draw/fill the matrix with the list of content to download.
void OnResize() override
Called after the window got resized.
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
static std::string content_type_strs[CONTENT_TYPE_END]
Cached strings for all content types.
GUIContentList content
List with content.
uint filesize_sum
The sum of all selected file sizes.
bool auto_select
Automatically select all content when the meta-data becomes available.
ContentListFilterData filter_data
Filter for content list.
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
static Filtering last_filtering
The last filtering setting.
QueryString filter_editbox
Filter editbox;.
static const std::initializer_list< GUIContentList::SortFunction *const > sorter_funcs
Sorter functions.
static Listing last_sorting
The last sorting setting.
static bool TagNameFilter(const ContentInfo *const *a, ContentListFilterData &filter)
Filter content by tags/name.
int list_pos
Our position in the list.
static bool TypeOrSelectedFilter(const ContentInfo *const *a, ContentListFilterData &filter)
Filter content by type, but still show content selected for download.
const ContentInfo * selected
The selected content info.
void OnInit() override
Notification that the nested widget tree gets initialized.
static const std::initializer_list< GUIContentList::FilterFunction *const > filter_funcs
Filter functions.
static bool TypeSorter(const ContentInfo *const &a, const ContentInfo *const &b)
Sort content by type.
void SortContentList()
Sort the content list.
static void ExternalSearchDisclaimerCallback(Window *w, bool accepted)
Callback function for disclaimer about entering external websites.
bool UpdateFilterState()
Update filter state based on current window state.
void OnPaint() override
The window must be repainted.
GUIList< const ContentInfo *, std::nullptr_t, ContentListFilterData & > GUIContentList
List with content infos.
static const uint EDITBOX_MAX_SIZE
Maximum size of the editbox in characters.
void OnEditboxChanged(WidgetID wid) override
The text in an editbox has been edited.
void OnDownloadComplete(ContentID) override
We have finished downloading a file.
void BuildContentList()
(Re)build the network game list as its amount has changed because an item has been added or deleted f...
void OnConnect(bool success) override
Callback for when the connection has finished.
NetworkContentListWindow(WindowDesc &desc, bool select_all, const std::bitset< CONTENT_TYPE_END > &types)
Create the content list window.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Scrollbar * vscroll
Cache of the vertical scrollbar.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
friend void BuildContentTypeStringList()
Build array of all strings corresponding to the content types.
void FilterContentList()
Filter the content list.
Dimension checkbox_size
Size of checkbox/"blot" sprite.
void ScrollToSelected()
Make sure that the currently selected content info is within the visible part of the matrix.
static bool StateSorter(const ContentInfo *const &a, const ContentInfo *const &b)
Sort content by state.
Scrollbar data structure.
void SetCount(size_t num)
Sets the number of elements in the list.
auto GetScrolledItemFromWidget(Tcontainer &container, int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Return an iterator pointing to the element of a scrolled widget that a user clicked in.
void SetCapacityFromWidget(Window *w, WidgetID widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget.
Definition widget.cpp:2521
EventState UpdateListPositionOnKeyPress(int &list_position, uint16_t keycode) const
Update the given list position as if it were on this scroll bar when the given keycode was pressed.
Definition widget.cpp:2468
void ScrollTowards(size_type position)
Scroll towards the given position; if the item is visible nothing happens, otherwise it will be shown...
auto GetVisibleRangeIterators(Tcontainer &container) const
Get a pair of iterators for the range of visible elements in a container.
@ Scenario
Scan for scenarios and heightmaps.
@ Baseset
Scan for base sets.
uint DoScan(Subdirectory sd)
Perform the scanning of a particular subdirectory.
Definition fileio.cpp:375
RectPadding frametext
Padding inside frame with text.
Definition window_gui.h:41
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:29
int vsep_normal
Normal vertical spacing.
Definition window_gui.h:58
int vsep_wide
Wide vertical spacing.
Definition window_gui.h:60
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:94
RectPadding matrix
Padding of WWT_MATRIX items.
Definition window_gui.h:42
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition window_gui.h:38
bool include(Container &container, typename Container::const_reference &item)
Helper function to append an item to a container if it is not already contained.
int find_index(Container const &container, typename Container::const_reference item)
Helper function to get the index of an item Consider using std::set, std::unordered_set or std::flat_...
@ WL_ERROR
Errors (eg. saving/loading failed)
Definition error.h:26
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, const CommandCost &cc)
Display an error message in a window.
void ScanScenarios()
Force a (re)scan of the scenarios.
Definition fios.cpp:711
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:77
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:852
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:658
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Definition gfx.cpp:115
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:775
Dimension GetScaledSpriteSize(SpriteID sprid)
Scale sprite size for GUI.
Definition widget.cpp:67
int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Definition gfx_func.h:166
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:243
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:377
@ SA_HOR_CENTER
Horizontally center the text.
Definition gfx_type.h:376
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:385
@ SA_VERT_CENTER
Vertically center the text.
Definition gfx_type.h:381
constexpr NWidgetPart SetMatrixDataTip(uint32_t cols, uint32_t rows, StringID tip={})
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetPIP(uint8_t pre, uint8_t inter, uint8_t post)
Widget part function for setting a pre/inter/post spaces.
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
constexpr NWidgetPart SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
Widget part function for setting additional space around a widget.
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
constexpr NWidgetPart SetResizeWidgetTypeTip(ResizeWidgetValues widget_type, StringID tip)
Widget part function for setting the resize widget type and tooltip.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart SetAlignment(StringAlignment align)
Widget part function for setting the alignment of text/images.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition window.cpp:943
constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
void ShowQuery(EncodedString &&caption, EncodedString &&message, Window *parent, QueryCallbackProc *callback, bool focus)
Show a confirmation window with standard 'yes' and 'no' buttons The window is aligned to the centre o...
@ WID_TF_CAPTION
The caption of the window.
Definition misc_widget.h:50
ClientNetworkContentSocketHandler _network_content_client
The client we use to connect to the server.
std::vector< const ContentInfo * > ConstContentVector
Vector with constant content info.
std::vector< ContentInfo * > ContentVector
Vector with content info.
const ContentInfo *const * ConstContentIterator
Iterator for the constant content vector.
static bool _accepted_external_search
Whether the user accepted to enter external websites during this session.
static constexpr NWidgetPart _nested_network_content_list_widgets[]
The widgets for the content list.
static WindowDesc _network_content_download_status_window_desc(WDP_CENTER, nullptr, 0, 0, WC_NETWORK_STATUS_WINDOW, WC_NONE, WindowDefaultFlag::Modal, _nested_network_content_download_status_window_widgets)
Window description for the download window.
static constexpr NWidgetPart _nested_network_content_download_status_window_widgets[]
Nested widgets for the download window.
void ShowNetworkContentListWindow(ContentVector *cv, ContentType type1, ContentType type2)
Show the content list window with a given set of content.
ContentListFilterCriteria
Filter criteria for NetworkContentListWindow.
@ CONTENT_FILTER_TYPE_OR_SELECTED
Filter by being of displayed type or selected for download.
@ CONTENT_FILTER_TEXT
Filter by query string.
static WindowDesc _network_content_list_desc(WDP_CENTER, "list_content", 630, 460, WC_NETWORK_WINDOW, WC_NONE, {}, _nested_network_content_list_widgets)
Window description of the content list.
void BuildContentTypeStringList()
Build array of all strings corresponding to the content types.
User interface for downloading files.
@ WID_NCL_CHECKBOX
Button above checkboxes.
@ WID_NCL_NAME
'Name' button.
@ WID_NCL_TYPE
'Type' button.
@ WID_NCL_SEARCH_EXTERNAL
Search external sites for missing NewGRF.
@ WID_NCL_CANCEL
'Cancel' button.
@ WID_NCL_DETAILS
Panel with content details.
@ WID_NCL_SEL_ALL_UPDATE
NWID_SELECTION widget for select all/update buttons..
@ WID_NCL_SELECT_ALL
'Select all' button.
@ WID_NCL_FILTER
Filter editbox.
@ WID_NCL_FILTER_CAPT
Caption for the filter editbox.
@ WID_NCL_DOWNLOAD
'Download' button.
@ WID_NCL_SCROLLBAR
Scrollbar of matrix.
@ WID_NCL_SELECT_UPDATE
'Select updates' button.
@ WID_NCL_TEXTFILE
Open readme, changelog (+1) or license (+2) of a file in the content window.
@ WID_NCL_MATRIX
Panel with list of content.
@ WID_NCL_BACKGROUND
Resize button.
@ WID_NCL_UNSELECT
'Unselect all' button.
@ WID_NCL_OPEN_URL
'Open url' button.
@ WID_NCDS_CANCELOK
(Optional) Cancel/OK button.
@ WID_NCDS_PROGRESS_TEXT
Text explaining what is happening.
@ WID_NCDS_PROGRESS_BAR
Simple progress bar.
bool RequestNewGRFScan(NewGRFScanCallback *callback)
Request a new NewGRF scan.
Definition openttd.cpp:1325
static const uint8_t PC_GREY
Grey palette colour.
static const uint8_t PC_DARK_BLUE
Dark blue palette colour.
std::string FormatArrayAsHex(std::span< const uint8_t > data)
Format a byte array into a continuous hex string.
Definition string.cpp:80
int StrNaturalCompare(std::string_view s1, std::string_view s2, bool ignore_garbage_at_front)
Compares two strings using case insensitive natural sort.
Definition string.cpp:607
std::string_view GetListSeparator()
Get the list separator string for the current language.
Definition strings.cpp:310
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:426
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
uint64_t GetParamMaxDigits(uint count, FontSize size)
Get some number that is suitable for string size computations.
Definition strings.cpp:230
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
@ TD_RTL
Text is written right-to-left by default.
Callbacks for notifying others about incoming data.
Container for all important information about a piece of content.
uint32_t unique_id
Unique ID; either GRF ID or shortname.
uint32_t filesize
Size of the file.
MD5Hash md5sum
The MD5 checksum.
std::string url
URL related to the content.
State state
Whether the content info is selected (for download)
std::string name
Name of the content.
std::string description
Description of the content.
std::optional< std::string > GetTextfile(TextfileType type) const
Search a textfile file next to this file in the content list.
std::string version
Version of the content.
ContentID id
Unique (server side) ID for the content.
std::string filename
Filename (for the .tar.gz; only valid on download)
bool IsSelected() const
Is the state either selected or autoselected?
ContentType type
Type of content.
std::vector< ContentID > dependencies
The dependencies (unique server side ids)
@ DOES_NOT_EXIST
The content does not exist in the content system.
@ ALREADY_HERE
The content is already at the client side.
@ AUTOSELECTED
The content has been selected as dependency.
@ UNSELECTED
The content has not been selected.
@ SELECTED
The content has been manually selected.
StringList tags
Tags associated with the content.
bool upgrade
This item is an upgrade.
Filter data for NetworkContentListWindow.
std::bitset< CONTENT_TYPE_END > types
Content types displayed.
StringFilter string_filter
Text filter of content list.
Window for displaying the textfile of an item in the content list.
const ContentInfo * ci
View the textfile of this ContentInfo.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
Dimensions (a width and height) of a rectangle in 2D.
Data structure describing what to show in the list (filter criteria).
Data structure describing how to show the list (what sort direction and criteria).
Partial widget specification to allow NWidgets to be written nested.
Window for showing the download status of content.
std::vector< ContentType > receivedTypes
Types we received so we can update their cache.
void OnDownloadProgress(const ContentInfo *ci, int bytes) override
We have progress in the download of a file.
NetworkContentDownloadStatusWindow()
Create a new download window based on a list of content information with flags whether to download th...
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
Coordinates of a point in 2D.
Data stored about a string that can be modified in the GUI.
int cancel_button
Widget button of parent window to simulate when pressing CANCEL in OSK.
static const int ACTION_CLEAR
Clear editbox.
constexpr uint Horizontal() const
Get total horizontal padding of RectPadding.
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Specification of a rectangle with absolute coordinates of all edges.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Rect WithHeight(int height, bool end=false) const
Copy Rect and set its height.
String filter and state.
bool IsEmpty() const
Check whether any filter words were entered.
void SetFilterTerm(std::string_view str)
Set the term to filter on.
void ResetState()
Reset the matching state to process a new item.
void AddLine(const char *str)
Pass another text line from the current item to the filter.
bool GetState() const
Get the matching state of the current item.
const char * GetText() const
Get the current text.
Definition textbuf.cpp:286
Window for displaying a textfile.
TextfileType file_type
Type of textfile to view.
virtual void LoadTextfile(const std::string &textfile, Subdirectory dir)
Loads the textfile text from file and setup lines.
High level window description.
Definition window_gui.h:168
Data structure for an opened window.
Definition window_gui.h:274
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1050
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1736
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:321
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:744
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3164
Window * parent
Parent window.
Definition window_gui.h:329
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:502
void DrawSortButtonState(WidgetID widget, SortButtonState state) const
Draw a sort button's up or down arrow symbol.
Definition widget.cpp:776
ResizeInfo resize
Resize information.
Definition window_gui.h:315
bool IsWidgetFocused(WidgetID widget_index) const
Check if given widget is focused within this window.
Definition window_gui.h:421
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1726
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:483
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:973
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1749
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:311
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:382
Subdirectory GetContentInfoSubDir(ContentType type)
Helper to get the subdirectory a ContentInfo is located in.
uint32_t ContentID
Unique identifier for the content.
ContentType
The values in the enum are important; they are used as database 'keys'.
@ CONTENT_TYPE_AI_LIBRARY
The content consists of an AI library.
@ CONTENT_TYPE_BASE_SOUNDS
The content consists of base sounds.
@ CONTENT_TYPE_GAME_LIBRARY
The content consists of a GS library.
@ CONTENT_TYPE_BASE_GRAPHICS
The content consists of base graphics.
@ CONTENT_TYPE_AI
The content consists of an AI.
@ CONTENT_TYPE_SCENARIO
The content consists of a scenario.
@ CONTENT_TYPE_NEWGRF
The content consists of a NewGRF.
@ CONTENT_TYPE_BEGIN
Helper to mark the begin of the types.
@ CONTENT_TYPE_BASE_MUSIC
The content consists of base music.
@ CONTENT_TYPE_GAME
The content consists of a game script.
@ CONTENT_TYPE_END
Helper to mark the end of the types.
@ CONTENT_TYPE_HEIGHTMAP
The content consists of a heightmap.
TextfileType
Additional text files accompanying Tar archives.
@ TFT_LICENSE
Content license.
@ TFT_README
Content readme.
@ TFT_CHANGELOG
Content changelog.
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition widget.cpp:296
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ NWID_SPACER
Invisible widget that takes some space.
Definition widget_type.h:69
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:61
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:65
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:40
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:49
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:51
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:75
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:67
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:59
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:38
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:58
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:55
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:48
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:70
@ EqualSize
Containers should keep all their (resizing) children equally large.
@ RWV_HIDE_BEVEL
Bevel of resize box is hidden.
Definition widget_type.h:30
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1143
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition window.cpp:3224
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1226
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition window.cpp:1101
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3106
@ Modal
The window is a modal child of some other window, meaning the parent is 'inactive'.
@ BorderOnly
Draw border only, no background.
@ Lowered
If set the frame is lowered and the background colour brighter (ie. buttons when pressed)
SortButtonState
State of a sort direction button.
Definition window_gui.h:217
@ SBS_DOWN
Sort ascending.
Definition window_gui.h:219
@ SBS_UP
Sort descending.
Definition window_gui.h:220
@ WDP_CENTER
Center the window.
Definition window_gui.h:146
int WidgetID
Widget ID.
Definition window_type.h:20
@ WN_NETWORK_WINDOW_CONTENT_LIST
Network content list.
Definition window_type.h:38
@ WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD
Network content download status.
Definition window_type.h:42
@ WN_GAME_OPTIONS_GAME_OPTIONS
Game options.
Definition window_type.h:28
EventState
State of handling an event.
@ ES_HANDLED
The passed event is handled.
@ ES_NOT_HANDLED
The passed event is not handled.
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:47
@ WC_GAME_OPTIONS
Game options window; Window numbers:
@ WC_NETWORK_WINDOW
Network window; Window numbers:
@ WC_TEXTFILE
textfile; Window numbers:
@ WC_SAVELOAD
Saveload window; Window numbers:
@ WC_NETWORK_STATUS_WINDOW
Network status window; Window numbers: