OpenTTD Source 20241224-master-gf74b0cf984
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;
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 void SetStringParameters(WidgetID widget) const override
70 {
71 if (widget == WID_TF_CAPTION) {
72 SetDParam(0, this->GetTypeString());
73 SetDParamStr(1, this->ci->name);
74 }
75 }
76};
77
78void ShowContentTextfileWindow(TextfileType file_type, const ContentInfo *ci)
79{
80 CloseWindowById(WC_TEXTFILE, file_type);
81 new ContentTextfileWindow(file_type, ci);
82}
83
86 NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CONTENT_DOWNLOAD_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
87 NWidget(WWT_PANEL, COLOUR_GREY),
89 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NCDS_PROGRESS_BAR), SetFill(1, 0),
90 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NCDS_PROGRESS_TEXT), SetFill(1, 0), SetMinimalSize(350, 0),
91 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCDS_CANCELOK), SetDataTip(STR_BUTTON_CANCEL, STR_NULL), SetFill(1, 0),
94};
95
98 WDP_CENTER, nullptr, 0, 0,
100 WDF_MODAL,
102);
103
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 SetDParamMaxDigits(0, 8);
124 SetDParamMaxDigits(1, 8);
125 SetDParamMaxDigits(2, 8);
127 /* We need some spacing for the 'border' */
130 break;
131
134 break;
135 }
136}
137
139{
140 switch (widget) {
142 /* Draw the % complete with a bar and a text */
143 DrawFrameRect(r, COLOUR_GREY, FR_BORDERONLY | FR_LOWERED);
145 DrawFrameRect(ir.WithWidth((uint64_t)ir.Width() * this->downloaded_bytes / this->total_bytes, _current_text_dir == TD_RTL), COLOUR_MAUVE, FR_NONE);
146 SetDParam(0, this->downloaded_bytes);
147 SetDParam(1, this->total_bytes);
148 SetDParam(2, this->downloaded_bytes * 100LL / this->total_bytes);
150 break;
151 }
152
154 StringID str;
155 if (this->downloaded_bytes == this->total_bytes) {
157 } else if (!this->name.empty()) {
158 SetDParamStr(0, this->name);
159 SetDParam(1, this->downloaded_files);
160 SetDParam(2, this->total_files);
162 } else {
164 }
165 DrawStringMultiLine(r, str, TC_FROMSTRING, SA_CENTER);
166 break;
167 }
168 }
169}
170
172{
173 if (ci->id != this->cur_id) {
174 this->name = ci->filename;
175 this->cur_id = ci->id;
176 this->downloaded_files++;
177 }
178
179 /* A negative value means we are resetting; for example, when retrying or using a fallback. */
180 if (bytes < 0) {
181 this->downloaded_bytes = 0;
182 } else {
183 this->downloaded_bytes += bytes;
184 }
185
186 this->SetDirty();
187}
188
189
192private:
193 std::vector<ContentType> receivedTypes;
194
195public:
204
205 void Close([[maybe_unused]] int data = 0) override
206 {
208 for (auto ctype : this->receivedTypes) {
209 switch (ctype) {
210 case CONTENT_TYPE_AI:
212 /* AI::Rescan calls the scanner. */
213 break;
216 /* Game::Rescan calls the scanner. */
217 break;
218
222 mode |= TarScanner::BASESET;
223 break;
224
226 /* ScanNewGRFFiles calls the scanner. */
227 break;
228
231 mode |= TarScanner::SCENARIO;
232 break;
233
234 default:
235 break;
236 }
237 }
238
239 TarScanner::DoScan(mode);
240
241 /* Tell all the backends about what we've downloaded */
242 for (auto ctype : this->receivedTypes) {
243 switch (ctype) {
244 case CONTENT_TYPE_AI:
246 AI::Rescan();
247 break;
248
251 Game::Rescan();
252 break;
253
257 break;
258
262 break;
263
267 break;
268
271 break;
272
277 break;
278
279 default:
280 break;
281 }
282 }
283
284 /* Always invalidate the download window; tell it we are going to be gone */
286
288 }
289
290 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
291 {
292 if (widget == WID_NCDS_CANCELOK) {
293 if (this->downloaded_bytes != this->total_bytes) {
295 this->Close();
296 } else {
297 /* If downloading succeeded, close the online content window. This will close
298 * the current window as well. */
300 }
301 }
302 }
303
304 void OnDownloadProgress(const ContentInfo *ci, int bytes) override
305 {
307 include(this->receivedTypes, ci->type);
308
309 /* When downloading is finished change cancel in ok */
310 if (this->downloaded_bytes == this->total_bytes) {
312 }
313 }
314};
315
319 std::bitset<CONTENT_TYPE_END> types;
320};
321
327
332
333 static const uint EDITBOX_MAX_SIZE = 50;
334
335 static Listing last_sorting;
337 static const std::initializer_list<GUIContentList::SortFunction * const> sorter_funcs;
338 static const std::initializer_list<GUIContentList::FilterFunction * const> filter_funcs;
344
349
351
354 {
355 std::string url;
356 url.reserve(1024);
357
358 url += "https://grfsearch.openttd.org/?";
359
360 if (this->auto_select) {
361 url += "do=searchgrfid&q=";
362
363 bool first = true;
364 for (const ContentInfo *ci : this->content) {
365 if (ci->state != ContentInfo::DOES_NOT_EXIST) continue;
366
367 if (!first) url.push_back(',');
368 first = false;
369
370 fmt::format_to(std::back_inserter(url), "{:08X}:{}", ci->unique_id, FormatArrayAsHex(ci->md5sum));
371 }
372 } else {
373 url += "do=searchtext&q=";
374
375 /* Escape search term */
376 for (const char *search = this->filter_editbox.text.buf; *search != '\0'; search++) {
377 /* Remove quotes */
378 if (*search == '\'' || *search == '"') continue;
379
380 /* Escape special chars, such as &%,= */
381 if (*search < 0x30) {
382 fmt::format_to(std::back_inserter(url), "%{:02X}", *search);
383 } else {
384 url.push_back(*search);
385 }
386 }
387 }
388
389 OpenBrowser(url);
390 }
391
395 static void ExternalSearchDisclaimerCallback(Window *w, bool accepted)
396 {
397 if (accepted) {
399 ((NetworkContentListWindow*)w)->OpenExternalSearch();
400 }
401 }
402
408 {
409 if (!this->content.NeedRebuild()) return;
410
411 /* Create temporary array of games to use for listing */
412 this->content.clear();
413
414 bool all_available = true;
415
417 if ((*iter)->state == ContentInfo::DOES_NOT_EXIST) all_available = false;
418 this->content.push_back(*iter);
419 }
420
422
423 this->FilterContentList();
424 this->content.RebuildDone();
425 this->SortContentList();
426
427 this->vscroll->SetCount(this->content.size()); // Update the scrollbar
428 this->ScrollToSelected();
429 }
430
432 static bool NameSorter(const ContentInfo * const &a, const ContentInfo * const &b)
433 {
434 return StrNaturalCompare(a->name, b->name, true) < 0; // Sort by name (natural sorting).
435 }
436
438 static bool TypeSorter(const ContentInfo * const &a, const ContentInfo * const &b)
439 {
440 int r = 0;
441 if (a->type != b->type) {
443 }
444 if (r == 0) return NameSorter(a, b);
445 return r < 0;
446 }
447
449 static bool StateSorter(const ContentInfo * const &a, const ContentInfo * const &b)
450 {
451 int r = a->state - b->state;
452 if (r == 0) return TypeSorter(a, b);
453 return r < 0;
454 }
455
458 {
459 if (!this->content.Sort()) return;
460
461 int idx = find_index(this->content, this->selected);
462 if (idx >= 0) this->list_pos = idx;
463 }
464
466 static bool TagNameFilter(const ContentInfo * const *a, ContentListFilterData &filter)
467 {
468 if ((*a)->state == ContentInfo::SELECTED || (*a)->state == ContentInfo::AUTOSELECTED) return true;
469
470 filter.string_filter.ResetState();
471 for (auto &tag : (*a)->tags) filter.string_filter.AddLine(tag);
472
473 filter.string_filter.AddLine((*a)->name);
474 return filter.string_filter.GetState();
475 }
476
478 static bool TypeOrSelectedFilter(const ContentInfo * const *a, ContentListFilterData &filter)
479 {
480 if (filter.types.none()) return true;
481 if (filter.types[(*a)->type]) return true;
482 return ((*a)->state == ContentInfo::SELECTED || (*a)->state == ContentInfo::AUTOSELECTED);
483 }
484
487 {
488 /* Apply filters. */
489 bool changed = false;
490 if (!this->filter_data.string_filter.IsEmpty()) {
491 this->content.SetFilterType(CONTENT_FILTER_TEXT);
492 changed |= this->content.Filter(this->filter_data);
493 }
494 if (this->filter_data.types.any()) {
496 changed |= this->content.Filter(this->filter_data);
497 }
498 if (!changed) return;
499
500 /* update list position */
501 int idx = find_index(this->content, this->selected);
502 if (idx >= 0) {
503 this->list_pos = idx;
504 return;
505 }
506
507 /* previously selected item not in list anymore */
508 this->selected = nullptr;
509 this->list_pos = 0;
510 }
511
517 {
518 Filtering old_params = this->content.GetFiltering();
519 bool new_state = !this->filter_data.string_filter.IsEmpty() || this->filter_data.types.any();
520 if (new_state != old_params.state) {
521 this->content.SetFilterState(new_state);
522 }
523 return new_state != old_params.state;
524 }
525
528 {
529 if (this->selected == nullptr) return;
530
531 this->vscroll->ScrollTowards(this->list_pos);
532 }
533
535public:
545 NetworkContentListWindow(WindowDesc &desc, bool select_all, const std::bitset<CONTENT_TYPE_END> &types) :
546 Window(desc),
550 list_pos(0)
551 {
552 this->CreateNestedTree();
553 this->vscroll = this->GetScrollbar(WID_NCL_SCROLLBAR);
555
556 this->GetWidget<NWidgetStacked>(WID_NCL_SEL_ALL_UPDATE)->SetDisplayedPlane(select_all);
557
559 this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
561 this->SetWidgetDisabledState(WID_NCL_SEARCH_EXTERNAL, this->auto_select);
562 this->filter_data.types = types;
563
565 this->content.SetListing(this->last_sorting);
566 this->content.SetFiltering(this->last_filtering);
567 this->content.SetSortFuncs(this->sorter_funcs);
568 this->content.SetFilterFuncs(this->filter_funcs);
569 this->UpdateFilterState();
570 this->content.ForceRebuild();
571 this->FilterContentList();
572 this->SortContentList();
573 this->InvalidateData();
574 }
575
576 void Close([[maybe_unused]] int data = 0) override
577 {
579 this->Window::Close();
580 }
581
582 void OnInit() override
583 {
584 this->checkbox_size = maxdim(maxdim(GetScaledSpriteSize(SPR_BOX_EMPTY), GetScaledSpriteSize(SPR_BOX_CHECKED)), GetScaledSpriteSize(SPR_BLOT));
585 }
586
588 {
589 switch (widget) {
590 case WID_NCL_CHECKBOX:
591 size.width = this->checkbox_size.width + padding.width;
592 break;
593
594 case WID_NCL_TYPE: {
595 Dimension d = size;
596 for (int i = CONTENT_TYPE_BEGIN; i < CONTENT_TYPE_END; i++) {
598 }
599 size.width = d.width + padding.width;
600 break;
601 }
602
603 case WID_NCL_MATRIX:
604 resize.height = std::max(this->checkbox_size.height, (uint)GetCharacterHeight(FS_NORMAL)) + padding.height;
605 size.height = 10 * resize.height;
606 break;
607 }
608 }
609
610
611 void DrawWidget(const Rect &r, WidgetID widget) const override
612 {
613 switch (widget) {
614 case WID_NCL_DETAILS:
615 this->DrawDetails(r);
616 break;
617
618 case WID_NCL_MATRIX:
619 this->DrawMatrix(r);
620 break;
621 }
622 }
623
624 void OnPaint() override
625 {
626 const SortButtonState arrow = this->content.IsDescSortOrder() ? SBS_DOWN : SBS_UP;
627
628 if (this->content.NeedRebuild()) {
629 this->BuildContentList();
630 }
631
632 this->DrawWidgets();
633
634 switch (this->content.SortType()) {
638 }
639 }
640
645 void DrawMatrix(const Rect &r) const
646 {
647 const Rect checkbox = this->GetWidget<NWidgetBase>(WID_NCL_CHECKBOX)->GetCurrentRect();
648 const Rect name = this->GetWidget<NWidgetBase>(WID_NCL_NAME)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
649 const Rect type = this->GetWidget<NWidgetBase>(WID_NCL_TYPE)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
650
651 /* Fill the matrix with the information */
652 const uint step_height = this->GetWidget<NWidgetBase>(WID_NCL_MATRIX)->resize_y;
654
655 Rect mr = r.WithHeight(step_height);
656 auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->content);
657 for (auto iter = first; iter != last; iter++) {
658 const ContentInfo *ci = *iter;
659
660 if (ci == this->selected) GfxFillRect(mr.Shrink(WidgetDimensions::scaled.bevel), PC_GREY);
661
662 SpriteID sprite;
663 SpriteID pal = PAL_NONE;
664 switch (ci->state) {
665 case ContentInfo::UNSELECTED: sprite = SPR_BOX_EMPTY; break;
666 case ContentInfo::SELECTED: sprite = SPR_BOX_CHECKED; break;
667 case ContentInfo::AUTOSELECTED: sprite = SPR_BOX_CHECKED; break;
668 case ContentInfo::ALREADY_HERE: sprite = SPR_BLOT; pal = PALETTE_TO_GREEN; break;
669 case ContentInfo::DOES_NOT_EXIST: sprite = SPR_BLOT; pal = PALETTE_TO_RED; break;
670 default: NOT_REACHED();
671 }
672 DrawSpriteIgnorePadding(sprite, pal, {checkbox.left, mr.top, checkbox.right, mr.bottom}, SA_CENTER);
673
675 DrawString(type.left, type.right, mr.top + text_y_offset, str, TC_BLACK, SA_HOR_CENTER);
676
677 DrawString(name.left, name.right, mr.top + text_y_offset, ci->name, TC_BLACK);
678 mr = mr.Translate(0, step_height);
679 }
680 }
681
686 void DrawDetails(const Rect &r) const
687 {
688 /* Height for the title banner */
690
692 Rect tr = r.Shrink(WidgetDimensions::scaled.frametext);
693 tr.top += HEADER_HEIGHT;
694
695 /* Create the nice grayish rectangle at the details top */
697 DrawString(hr.left, hr.right, hr.top, STR_CONTENT_DETAIL_TITLE, TC_FROMSTRING, SA_HOR_CENTER);
698
699 /* Draw the total download size */
700 SetDParam(0, this->filesize_sum);
702
703 if (this->selected == nullptr) return;
704
705 /* And fill the rest of the details when there's information to place there */
706 DrawStringMultiLine(hr.left, hr.right, hr.top + GetCharacterHeight(FS_NORMAL), hr.bottom, STR_CONTENT_DETAIL_SUBTITLE_UNSELECTED + this->selected->state, TC_FROMSTRING, SA_CENTER);
707
708 /* Also show the total download size, so keep some space from the bottom */
710
711 if (this->selected->upgrade) {
715 }
716
717 SetDParamStr(0, this->selected->name);
719
720 if (!this->selected->version.empty()) {
721 SetDParamStr(0, this->selected->version);
723 }
724
725 if (!this->selected->description.empty()) {
726 SetDParamStr(0, this->selected->description);
728 }
729
730 if (!this->selected->url.empty()) {
731 SetDParamStr(0, this->selected->url);
733 }
734
737
739 SetDParam(0, this->selected->filesize);
741
742 std::string_view list_separator = GetListSeparator();
743 if (!this->selected->dependencies.empty()) {
744 /* List dependencies */
745 std::string buf;
746 for (auto &cid : this->selected->dependencies) {
747 /* Try to find the dependency */
749 for (; iter != _network_content_client.End(); iter++) {
750 const ContentInfo *ci = *iter;
751 if (ci->id != cid) continue;
752
753 if (!buf.empty()) buf += list_separator;
754 buf += (*iter)->name;
755 break;
756 }
757 }
758 SetDParamStr(0, buf);
760 }
761
762 if (!this->selected->tags.empty()) {
763 /* List all tags */
764 std::string buf;
765 for (auto &tag : this->selected->tags) {
766 if (!buf.empty()) buf += list_separator;
767 buf += tag;
768 }
769 SetDParamStr(0, buf);
771 }
772
773 if (this->selected->IsSelected()) {
774 /* When selected show all manually selected content that depends on this */
777
778 std::string buf;
779 for (const ContentInfo *ci : tree) {
780 if (ci == this->selected || ci->state != ContentInfo::SELECTED) continue;
781
782 if (!buf.empty()) buf += list_separator;
783 buf += ci->name;
784 }
785 if (!buf.empty()) {
786 SetDParamStr(0, buf);
788 }
789 }
790 }
791
792 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
793 {
794 if (widget >= WID_NCL_TEXTFILE && widget < WID_NCL_TEXTFILE + TFT_CONTENT_END) {
795 if (this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE) return;
796
797 ShowContentTextfileWindow((TextfileType)(widget - WID_NCL_TEXTFILE), this->selected);
798 return;
799 }
800
801 switch (widget) {
802 case WID_NCL_MATRIX: {
803 auto it = this->vscroll->GetScrolledItemFromWidget(this->content, pt.y, this, WID_NCL_MATRIX);
804 if (it == this->content.end()) return; // click out of bounds
805
806 this->selected = *it;
807 this->list_pos = it - this->content.begin();
808
810 if (click_count > 1 || IsInsideBS(pt.x, checkbox->pos_x, checkbox->current_x)) {
812 this->content.ForceResort();
813 this->content.ForceRebuild();
814 }
815
816 if (this->filter_data.types.any()) {
817 this->content.ForceRebuild();
818 }
819
820 this->InvalidateData();
821 break;
822 }
823
824 case WID_NCL_CHECKBOX:
825 case WID_NCL_TYPE:
826 case WID_NCL_NAME:
827 if (this->content.SortType() == widget - WID_NCL_CHECKBOX) {
828 this->content.ToggleSortOrder();
829 if (!this->content.empty()) this->list_pos = (int)this->content.size() - this->list_pos - 1;
830 } else {
831 this->content.SetSortType(widget - WID_NCL_CHECKBOX);
832 this->content.ForceResort();
833 this->SortContentList();
834 }
835 this->ScrollToSelected();
836 this->InvalidateData();
837 break;
838
841 this->InvalidateData();
842 break;
843
846 this->InvalidateData();
847 break;
848
849 case WID_NCL_UNSELECT:
851 this->InvalidateData();
852 break;
853
854 case WID_NCL_CANCEL:
855 this->Close();
856 break;
857
858 case WID_NCL_OPEN_URL:
859 if (this->selected != nullptr) {
860 OpenBrowser(this->selected->url);
861 }
862 break;
863
864 case WID_NCL_DOWNLOAD:
866 break;
867
870 this->OpenExternalSearch();
871 } else {
873 }
874 break;
875 }
876 }
877
878 EventState OnKeyPress([[maybe_unused]] char32_t key, uint16_t keycode) override
879 {
880 if (this->vscroll->UpdateListPositionOnKeyPress(this->list_pos, keycode) == ES_NOT_HANDLED) {
881 switch (keycode) {
882 case WKC_SPACE:
883 case WKC_RETURN:
884 if (keycode == WKC_RETURN || !IsWidgetFocused(WID_NCL_FILTER)) {
885 if (this->selected != nullptr) {
887 this->content.ForceResort();
888 this->InvalidateData();
889 }
890 if (this->filter_data.types.any()) {
891 this->content.ForceRebuild();
892 this->InvalidateData();
893 }
894 return ES_HANDLED;
895 }
896 /* space is pressed and filter is focused. */
897 [[fallthrough]];
898
899 default:
900 return ES_NOT_HANDLED;
901 }
902 }
903
904 if (this->content.empty()) {
905 if (this->UpdateFilterState()) {
906 this->content.ForceRebuild();
907 this->InvalidateData();
908 }
909 return ES_HANDLED;
910 }
911
912 this->selected = this->content[this->list_pos];
913
914 if (this->UpdateFilterState()) {
915 this->content.ForceRebuild();
916 } else {
917 /* Scroll to the new content if it is outside the current range. */
918 this->ScrollToSelected();
919 }
920
921 /* redraw window */
922 this->InvalidateData();
923 return ES_HANDLED;
924 }
925
927 {
928 if (wid == WID_NCL_FILTER) {
929 this->filter_data.string_filter.SetFilterTerm(this->filter_editbox.text.buf);
930 this->UpdateFilterState();
931 this->content.ForceRebuild();
932 this->InvalidateData();
933 }
934 }
935
936 void OnResize() override
937 {
938 this->vscroll->SetCapacityFromWidget(this, WID_NCL_MATRIX);
939 }
940
942 {
943 if (this->auto_select && !rci->IsSelected()) _network_content_client.ToggleSelectedState(rci);
944 this->content.ForceRebuild();
945 this->InvalidateData(0, false);
946 }
947
949 {
950 this->content.ForceResort();
951 this->InvalidateData();
952 }
953
954 void OnConnect(bool success) override
955 {
956 if (!success) {
958 this->Close();
959 return;
960 }
961
962 this->InvalidateData();
963 }
964
970 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
971 {
972 if (!gui_scope) return;
973 if (this->content.NeedRebuild()) this->BuildContentList();
974
975 /* To sum all the bytes we intend to download */
976 this->filesize_sum = 0;
977 bool show_select_all = false;
978 bool show_select_upgrade = false;
979 for (const ContentInfo *ci : this->content) {
980 switch (ci->state) {
983 this->filesize_sum += ci->filesize;
984 break;
985
987 show_select_all = true;
989 break;
990
991 default:
992 break;
993 }
994 }
995
996 /* If data == 2 then the status window caused this OnInvalidate */
998 this->SetWidgetDisabledState(WID_NCL_UNSELECT, this->filesize_sum == 0);
999 this->SetWidgetDisabledState(WID_NCL_SELECT_ALL, !show_select_all);
1000 this->SetWidgetDisabledState(WID_NCL_SELECT_UPDATE, !show_select_upgrade || !this->filter_data.string_filter.IsEmpty());
1001 this->SetWidgetDisabledState(WID_NCL_OPEN_URL, this->selected == nullptr || this->selected->url.empty());
1002 for (TextfileType tft = TFT_CONTENT_BEGIN; tft < TFT_CONTENT_END; tft++) {
1003 this->SetWidgetDisabledState(WID_NCL_TEXTFILE + tft, this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE || !this->selected->GetTextfile(tft).has_value());
1004 }
1005
1006 this->GetWidget<NWidgetCore>(WID_NCL_CANCEL)->widget_data = this->filesize_sum == 0 ? STR_AI_SETTINGS_CLOSE : STR_AI_LIST_CANCEL;
1007 }
1008};
1009
1012
1013const std::initializer_list<NetworkContentListWindow::GUIContentList::SortFunction * const> NetworkContentListWindow::sorter_funcs = {
1014 &StateSorter,
1015 &TypeSorter,
1016 &NameSorter,
1017};
1018
1019const std::initializer_list<NetworkContentListWindow::GUIContentList::FilterFunction * const> NetworkContentListWindow::filter_funcs = {
1020 &TagNameFilter,
1021 &TypeOrSelectedFilter,
1022};
1023
1025
1030{
1031 for (int i = CONTENT_TYPE_BEGIN; i < CONTENT_TYPE_END; i++) {
1032 NetworkContentListWindow::content_type_strs[i] = GetString(STR_CONTENT_TYPE_BASE_GRAPHICS + i - CONTENT_TYPE_BASE_GRAPHICS);
1033 }
1034}
1035
1039 NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
1040 NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_CONTENT_TITLE, STR_NULL),
1041 NWidget(WWT_DEFSIZEBOX, COLOUR_LIGHT_BLUE),
1042 EndContainer(),
1043 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_BACKGROUND),
1045 /* Top */
1047 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),
1048 NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NCL_FILTER), SetFill(1, 0), SetResize(1, 0),
1049 SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
1050 EndContainer(),
1051 /* Lists and info. */
1053 /* Left side. */
1058 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_CHECKBOX), SetDataTip(STR_EMPTY, STR_NULL),
1059 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TYPE),
1060 SetDataTip(STR_CONTENT_TYPE_CAPTION, STR_CONTENT_TYPE_CAPTION_TOOLTIP),
1061 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_NAME), SetResize(1, 0), SetFill(1, 0),
1062 SetDataTip(STR_CONTENT_NAME_CAPTION, STR_CONTENT_NAME_CAPTION_TOOLTIP),
1063 EndContainer(),
1064 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),
1065 EndContainer(),
1066 NWidget(NWID_VSCROLLBAR, COLOUR_LIGHT_BLUE, WID_NCL_SCROLLBAR),
1067 EndContainer(),
1070 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SELECT_UPDATE), SetResize(1, 0), SetFill(1, 0),
1071 SetDataTip(STR_CONTENT_SELECT_UPDATES_CAPTION, STR_CONTENT_SELECT_UPDATES_CAPTION_TOOLTIP),
1072 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SELECT_ALL), SetResize(1, 0), SetFill(1, 0),
1073 SetDataTip(STR_CONTENT_SELECT_ALL_CAPTION, STR_CONTENT_SELECT_ALL_CAPTION_TOOLTIP),
1074 EndContainer(),
1075 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_UNSELECT), SetResize(1, 0), SetFill(1, 0),
1076 SetDataTip(STR_CONTENT_UNSELECT_ALL_CAPTION, STR_CONTENT_UNSELECT_ALL_CAPTION_TOOLTIP),
1077 EndContainer(),
1078 EndContainer(),
1079 /* Right side. */
1081 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_DETAILS), SetResize(1, 1), SetFill(1, 1),
1082 EndContainer(),
1085 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),
1086 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),
1087 EndContainer(),
1089 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),
1090 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),
1091 EndContainer(),
1092 EndContainer(),
1093 EndContainer(),
1094 EndContainer(),
1095 /* Bottom. */
1097 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SEARCH_EXTERNAL), SetResize(1, 0), SetFill(1, 0),
1098 SetDataTip(STR_CONTENT_SEARCH_EXTERNAL, STR_CONTENT_SEARCH_EXTERNAL_TOOLTIP),
1100 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_CANCEL), SetResize(1, 0), SetFill(1, 0),
1101 SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
1102 NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_DOWNLOAD), SetResize(1, 0), SetFill(1, 0),
1103 SetDataTip(STR_CONTENT_DOWNLOAD_CAPTION, STR_CONTENT_DOWNLOAD_CAPTION_TOOLTIP),
1104 EndContainer(),
1105 EndContainer(),
1106 EndContainer(),
1107 /* Resize button. */
1109 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1110 NWidget(WWT_RESIZEBOX, COLOUR_LIGHT_BLUE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
1111 EndContainer(),
1112 EndContainer(),
1113};
1114
1117 WDP_CENTER, "list_content", 630, 460,
1119 0,
1121);
1122
1131{
1132#if defined(WITH_ZLIB)
1133 std::bitset<CONTENT_TYPE_END> types;
1135 if (cv == nullptr) {
1136 assert(type1 != CONTENT_TYPE_END || type2 == CONTENT_TYPE_END);
1137 assert(type1 == CONTENT_TYPE_END || type1 != type2);
1140
1141 if (type1 != CONTENT_TYPE_END) types[type1] = true;
1142 if (type2 != CONTENT_TYPE_END) types[type2] = true;
1143 } else {
1145 }
1146
1148 new NetworkContentListWindow(_network_content_list_desc, cv != nullptr, types);
1149#else
1150 ShowErrorMessage(STR_CONTENT_NO_ZLIB, STR_CONTENT_NO_ZLIB_SUB, WL_ERROR);
1151 /* Connection failed... clean up the mess */
1152 if (cv != nullptr) {
1153 for (ContentInfo *ci : *cv) delete ci;
1154 }
1155#endif /* WITH_ZLIB */
1156}
static void Rescan()
Rescans all searchpaths for available AIs.
Definition ai_core.cpp:326
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.
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:2451
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:2398
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.
uint DoScan(Subdirectory sd)
Perform the scanning of a particular subdirectory.
Definition fileio.cpp:375
Mode
The mode of tar scanning.
Definition fileio_func.h:63
@ BASESET
Scan for base sets.
Definition fileio_func.h:65
@ NONE
Scan nothing.
Definition fileio_func.h:64
@ SCENARIO
Scan for scenarios and heightmaps.
Definition fileio_func.h:68
RectPadding frametext
Padding inside frame with text.
Definition window_gui.h:43
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:28
int vsep_normal
Normal vertical spacing.
Definition window_gui.h:60
int vsep_wide
Wide vertical spacing.
Definition window_gui.h:62
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:96
RectPadding matrix
Padding of WWT_MATRIX items.
Definition window_gui.h:44
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition window_gui.h:40
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_...
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
@ WL_ERROR
Errors (eg. saving/loading failed)
Definition error.h:26
void ScanScenarios()
Force a (re)scan of the scenarios.
Definition fios.cpp:718
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:851
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:657
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:114
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:774
Dimension GetScaledSpriteSize(SpriteID sprid)
Scale sprite size for GUI.
Definition widget.cpp:54
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:18
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:345
@ SA_HOR_CENTER
Horizontally center the text.
Definition gfx_type.h:344
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:353
@ SA_VERT_CENTER
Vertically center the text.
Definition gfx_type.h:349
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:209
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 SetDataTip(uint32_t data, StringID tip)
Widget part function for setting the data and tooltip.
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetMatrixDataTip(uint8_t cols, uint8_t rows, StringID tip)
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
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:940
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(StringID caption, StringID 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.
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 sting.
static constexpr NWidgetPart _nested_network_content_download_status_window_widgets[]
Nested widgets for the download window.
static WindowDesc _network_content_download_status_window_desc(WDP_CENTER, nullptr, 0, 0, WC_NETWORK_STATUS_WINDOW, WC_NONE, WDF_MODAL, _nested_network_content_download_status_window_widgets)
Window description for the download window.
void ShowNetworkContentListWindow(ContentVector *cv, ContentType type1, ContentType type2)
Show the content list window with a given set of content.
static WindowDesc _network_content_list_desc(WDP_CENTER, "list_content", 630, 460, WC_NETWORK_WINDOW, WC_NONE, 0, _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:1331
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:81
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:589
std::string_view GetListSeparator()
Get the list separator string for the current language.
Definition strings.cpp:229
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition strings.cpp:104
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Definition strings.cpp:333
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
void SetDParamStr(size_t n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition strings.cpp:371
void SetDParamMaxDigits(size_t n, uint count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition strings.cpp:143
@ TD_RTL
Text is written right-to-left by default.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
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.
@ 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.
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)
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.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
const ContentInfo * ci
View the textfile of this ContentInfo.
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(const char *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.
char *const buf
buffer in which text is saved
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:159
Data structure for an opened window.
Definition window_gui.h:273
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1047
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1733
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:320
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:732
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3159
Window * parent
Parent window.
Definition window_gui.h:328
void DrawSortButtonState(WidgetID widget, SortButtonState state) const
Draw a sort button's up or down arrow symbol.
Definition widget.cpp:764
ResizeInfo resize
Resize information.
Definition window_gui.h:314
bool IsWidgetFocused(WidgetID widget_index) const
Check if given widget is focused within this window.
Definition window_gui.h:426
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1723
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:486
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:977
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1746
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:314
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:387
Subdirectory GetContentInfoSubDir(ContentType type)
Helper to get the subdirectory a ContentInfo is located in.
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.
ContentID
Unique identifier for the content.
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:283
@ NC_EQUALSIZE
Value of the NCB_EQUALSIZE flag.
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ NWID_SPACER
Invisible widget that takes some space.
Definition widget_type.h:79
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:71
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:75
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:50
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:59
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:61
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:85
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:77
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:69
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:48
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:68
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:65
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:58
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:80
@ RWV_HIDE_BEVEL
Bevel of resize box is hidden.
Definition widget_type.h:40
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:1140
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:3219
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1223
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition window.cpp:1098
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3101
SortButtonState
State of a sort direction button.
Definition window_gui.h:218
@ SBS_DOWN
Sort ascending.
Definition window_gui.h:220
@ SBS_UP
Sort descending.
Definition window_gui.h:221
@ FR_BORDERONLY
Draw border only, no background.
Definition window_gui.h:27
@ FR_LOWERED
If set the frame is lowered and the background colour brighter (ie. buttons when pressed)
Definition window_gui.h:28
@ WDF_MODAL
The window is a modal child of some other window, meaning the parent is 'inactive'.
Definition window_gui.h:204
@ WDP_CENTER
Center the window.
Definition window_gui.h:148
int WidgetID
Widget ID.
Definition window_type.h:18
@ WN_NETWORK_WINDOW_CONTENT_LIST
Network content list.
Definition window_type.h:36
@ WN_NETWORK_STATUS_WINDOW_CONTENT_DOWNLOAD
Network content download status.
Definition window_type.h:40
@ WN_GAME_OPTIONS_GAME_OPTIONS
Game options.
Definition window_type.h:26
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:45
@ 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: