OpenTTD
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 "../sortlist_type.h"
19 #include "../stringfilter_type.h"
20 #include "../querystring_gui.h"
21 #include "../core/geometry_func.hpp"
22 #include "../textfile_gui.h"
23 #include "network_content_gui.h"
24 
25 
26 #include "table/strings.h"
27 #include "../table/sprites.h"
28 
29 #include <bitset>
30 
31 #include "../safeguards.h"
32 
33 
35 static bool _accepted_external_search = false;
36 
37 
40  const ContentInfo *ci;
41 
43  {
44  const char *textfile = this->ci->GetTextfile(file_type);
45  this->LoadTextfile(textfile, GetContentInfoSubDir(this->ci->type));
46  }
47 
48  StringID GetTypeString() const
49  {
50  switch (this->ci->type) {
51  case CONTENT_TYPE_NEWGRF: return STR_CONTENT_TYPE_NEWGRF;
52  case CONTENT_TYPE_BASE_GRAPHICS: return STR_CONTENT_TYPE_BASE_GRAPHICS;
53  case CONTENT_TYPE_BASE_SOUNDS: return STR_CONTENT_TYPE_BASE_SOUNDS;
54  case CONTENT_TYPE_BASE_MUSIC: return STR_CONTENT_TYPE_BASE_MUSIC;
55  case CONTENT_TYPE_AI: return STR_CONTENT_TYPE_AI;
56  case CONTENT_TYPE_AI_LIBRARY: return STR_CONTENT_TYPE_AI_LIBRARY;
57  case CONTENT_TYPE_GAME: return STR_CONTENT_TYPE_GAME_SCRIPT;
58  case CONTENT_TYPE_GAME_LIBRARY: return STR_CONTENT_TYPE_GS_LIBRARY;
59  case CONTENT_TYPE_SCENARIO: return STR_CONTENT_TYPE_SCENARIO;
60  case CONTENT_TYPE_HEIGHTMAP: return STR_CONTENT_TYPE_HEIGHTMAP;
61  default: NOT_REACHED();
62  }
63  }
64 
65  void SetStringParameters(int widget) const override
66  {
67  if (widget == WID_TF_CAPTION) {
68  SetDParam(0, this->GetTypeString());
69  SetDParamStr(1, this->ci->name);
70  }
71  }
72 };
73 
74 void ShowContentTextfileWindow(TextfileType file_type, const ContentInfo *ci)
75 {
78 }
79 
82  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CONTENT_DOWNLOAD_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
83  NWidget(WWT_PANEL, COLOUR_GREY, WID_NCDS_BACKGROUND),
87  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCDS_CANCELOK), SetMinimalSize(101, 12), SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
88  NWidget(NWID_SPACER), SetFill(1, 0),
89  EndContainer(),
91  EndContainer(),
92 };
93 
96  WDP_CENTER, nullptr, 0, 0,
98  WDF_MODAL,
99  _nested_network_content_download_status_window_widgets, lengthof(_nested_network_content_download_status_window_widgets)
100 );
101 
103  Window(desc), cur_id(UINT32_MAX)
104 {
107 
109 }
110 
112 {
114 }
115 
117 {
118  if (widget != WID_NCDS_BACKGROUND) return;
119 
120  /* Draw nice progress bar :) */
121  DrawFrameRect(r.left + 20, r.top + 4, r.left + 20 + (int)((this->width - 40LL) * this->downloaded_bytes / this->total_bytes), r.top + 14, COLOUR_MAUVE, FR_NONE);
122 
123  int y = r.top + 20;
124  SetDParam(0, this->downloaded_bytes);
125  SetDParam(1, this->total_bytes);
126  SetDParam(2, this->downloaded_bytes * 100LL / this->total_bytes);
127  DrawString(r.left + 2, r.right - 2, y, STR_CONTENT_DOWNLOAD_PROGRESS_SIZE, TC_FROMSTRING, SA_HOR_CENTER);
128 
129  StringID str;
130  if (this->downloaded_bytes == this->total_bytes) {
131  str = STR_CONTENT_DOWNLOAD_COMPLETE;
132  } else if (!StrEmpty(this->name)) {
133  SetDParamStr(0, this->name);
134  SetDParam(1, this->downloaded_files);
135  SetDParam(2, this->total_files);
136  str = STR_CONTENT_DOWNLOAD_FILE;
137  } else {
138  str = STR_CONTENT_DOWNLOAD_INITIALISE;
139  }
140 
141  y += FONT_HEIGHT_NORMAL + 5;
142  DrawStringMultiLine(r.left + 2, r.right - 2, y, y + FONT_HEIGHT_NORMAL * 2, str, TC_FROMSTRING, SA_CENTER);
143 }
144 
146 {
147  if (ci->id != this->cur_id) {
148  strecpy(this->name, ci->filename, lastof(this->name));
149  this->cur_id = ci->id;
150  this->downloaded_files++;
151  }
152 
153  this->downloaded_bytes += bytes;
154  this->SetDirty();
155 }
156 
157 
160 private:
161  std::vector<ContentType> receivedTypes;
162 
163 public:
168  NetworkContentDownloadStatusWindow() : BaseNetworkContentDownloadStatusWindow(&_network_content_download_status_window_desc)
169  {
171  }
172 
175  {
177  for (auto ctype : this->receivedTypes) {
178  switch (ctype) {
179  case CONTENT_TYPE_AI:
181  /* AI::Rescan calls the scanner. */
182  break;
183  case CONTENT_TYPE_GAME:
185  /* Game::Rescan calls the scanner. */
186  break;
187 
191  mode |= TarScanner::BASESET;
192  break;
193 
194  case CONTENT_TYPE_NEWGRF:
195  /* ScanNewGRFFiles calls the scanner. */
196  break;
197 
200  mode |= TarScanner::SCENARIO;
201  break;
202 
203  default:
204  break;
205  }
206  }
207 
208  TarScanner::DoScan(mode);
209 
210  /* Tell all the backends about what we've downloaded */
211  for (auto ctype : this->receivedTypes) {
212  switch (ctype) {
213  case CONTENT_TYPE_AI:
215  AI::Rescan();
216  break;
217 
218  case CONTENT_TYPE_GAME:
220  Game::Rescan();
221  break;
222 
226  break;
227 
231  break;
232 
236  break;
237 
238  case CONTENT_TYPE_NEWGRF:
239  ScanNewGRFFiles(nullptr);
240  break;
241 
244  extern void ScanScenarios();
245  ScanScenarios();
247  break;
248 
249  default:
250  break;
251  }
252  }
253 
254  /* Always invalidate the download window; tell it we are going to be gone */
256  }
257 
258  void OnClick(Point pt, int widget, int click_count) override
259  {
260  if (widget == WID_NCDS_CANCELOK) {
261  if (this->downloaded_bytes != this->total_bytes) {
263  delete this;
264  } else {
265  /* If downloading succeeded, close the online content window. This will close
266  * the current window as well. */
268  }
269  }
270  }
271 
272  void OnDownloadProgress(const ContentInfo *ci, int bytes) override
273  {
275  include(this->receivedTypes, ci->type);
276 
277  /* When downloading is finished change cancel in ok */
278  if (this->downloaded_bytes == this->total_bytes) {
279  this->GetWidget<NWidgetCore>(WID_NCDS_CANCELOK)->widget_data = STR_BUTTON_OK;
280  }
281  }
282 };
283 
287  std::bitset<CONTENT_TYPE_END> types;
288 };
289 
294 };
295 
300 
301  static const uint EDITBOX_MAX_SIZE = 50;
302 
305  static GUIContentList::SortFunction * const sorter_funcs[];
306  static GUIContentList::FilterFunction * const filter_funcs[];
307  GUIContentList content;
308  bool auto_select;
312 
314  int list_pos;
317 
318  static char content_type_strs[CONTENT_TYPE_END][64];
319 
322  {
323  extern void OpenBrowser(const char *url);
324 
325  char url[1024];
326  const char *last = lastof(url);
327 
328  char *pos = strecpy(url, "http://grfsearch.openttd.org/?", last);
329 
330  if (this->auto_select) {
331  pos = strecpy(pos, "do=searchgrfid&q=", last);
332 
333  bool first = true;
334  for (const ContentInfo *ci : this->content) {
335  if (ci->state != ContentInfo::DOES_NOT_EXIST) continue;
336 
337  if (!first) pos = strecpy(pos, ",", last);
338  first = false;
339 
340  pos += seprintf(pos, last, "%08X", ci->unique_id);
341  pos = strecpy(pos, ":", last);
342  pos = md5sumToString(pos, last, ci->md5sum);
343  }
344  } else {
345  pos = strecpy(pos, "do=searchtext&q=", last);
346 
347  /* Escape search term */
348  for (const char *search = this->filter_editbox.text.buf; *search != '\0'; search++) {
349  /* Remove quotes */
350  if (*search == '\'' || *search == '"') continue;
351 
352  /* Escape special chars, such as &%,= */
353  if (*search < 0x30) {
354  pos += seprintf(pos, last, "%%%02X", *search);
355  } else if (pos < last) {
356  *pos = *search;
357  *++pos = '\0';
358  }
359  }
360  }
361 
362  OpenBrowser(url);
363  }
364 
368  static void ExternalSearchDisclaimerCallback(Window *w, bool accepted)
369  {
370  if (accepted) {
372  ((NetworkContentListWindow*)w)->OpenExternalSearch();
373  }
374  }
375 
381  {
382  if (!this->content.NeedRebuild()) return;
383 
384  /* Create temporary array of games to use for listing */
385  this->content.clear();
386 
387  bool all_available = true;
388 
390  if ((*iter)->state == ContentInfo::DOES_NOT_EXIST) all_available = false;
391  this->content.push_back(*iter);
392  }
393 
394  this->SetWidgetDisabledState(WID_NCL_SEARCH_EXTERNAL, this->auto_select && all_available);
395 
396  this->FilterContentList();
397  this->content.shrink_to_fit();
398  this->content.RebuildDone();
399  this->SortContentList();
400 
401  this->vscroll->SetCount((int)this->content.size()); // Update the scrollbar
402  this->ScrollToSelected();
403  }
404 
406  static bool NameSorter(const ContentInfo * const &a, const ContentInfo * const &b)
407  {
408  return strnatcmp(a->name, b->name, true) < 0; // Sort by name (natural sorting).
409  }
410 
412  static bool TypeSorter(const ContentInfo * const &a, const ContentInfo * const &b)
413  {
414  int r = 0;
415  if (a->type != b->type) {
416  r = strnatcmp(content_type_strs[a->type], content_type_strs[b->type]);
417  }
418  if (r == 0) return NameSorter(a, b);
419  return r < 0;
420  }
421 
423  static bool StateSorter(const ContentInfo * const &a, const ContentInfo * const &b)
424  {
425  int r = a->state - b->state;
426  if (r == 0) return TypeSorter(a, b);
427  return r < 0;
428  }
429 
432  {
433  if (!this->content.Sort()) return;
434 
435  int idx = find_index(this->content, this->selected);
436  if (idx >= 0) this->list_pos = idx;
437  }
438 
440  static bool CDECL TagNameFilter(const ContentInfo * const *a, ContentListFilterData &filter)
441  {
442  filter.string_filter.ResetState();
443  for (int i = 0; i < (*a)->tag_count; i++) {
444  filter.string_filter.AddLine((*a)->tags[i]);
445  }
446  filter.string_filter.AddLine((*a)->name);
447  return filter.string_filter.GetState();
448  }
449 
451  static bool CDECL TypeOrSelectedFilter(const ContentInfo * const *a, ContentListFilterData &filter)
452  {
453  if (filter.types.none()) return true;
454  if (filter.types[(*a)->type]) return true;
455  return ((*a)->state == ContentInfo::SELECTED || (*a)->state == ContentInfo::AUTOSELECTED);
456  }
457 
460  {
461  /* Apply filters. */
462  bool changed = false;
463  if (!this->filter_data.string_filter.IsEmpty()) {
464  this->content.SetFilterType(CONTENT_FILTER_TEXT);
465  changed |= this->content.Filter(this->filter_data);
466  }
467  if (this->filter_data.types.any()) {
469  changed |= this->content.Filter(this->filter_data);
470  }
471  if (!changed) return;
472 
473  /* update list position */
474  int idx = find_index(this->content, this->selected);
475  if (idx >= 0) {
476  this->list_pos = idx;
477  return;
478  }
479 
480  /* previously selected item not in list anymore */
481  this->selected = nullptr;
482  this->list_pos = 0;
483  }
484 
490  {
491  Filtering old_params = this->content.GetFiltering();
492  bool new_state = !this->filter_data.string_filter.IsEmpty() || this->filter_data.types.any();
493  if (new_state != old_params.state) {
494  this->content.SetFilterState(new_state);
495  }
496  return new_state != old_params.state;
497  }
498 
501  {
502  if (this->selected == nullptr) return;
503 
504  this->vscroll->ScrollTowards(this->list_pos);
505  }
506 
507  friend void BuildContentTypeStringList();
508 public:
518  NetworkContentListWindow(WindowDesc *desc, bool select_all, const std::bitset<CONTENT_TYPE_END> &types) :
519  Window(desc),
520  auto_select(select_all),
521  filter_editbox(EDITBOX_MAX_SIZE),
522  selected(nullptr),
523  list_pos(0)
524  {
525  this->checkbox_size = maxdim(maxdim(GetSpriteSize(SPR_BOX_EMPTY), GetSpriteSize(SPR_BOX_CHECKED)), GetSpriteSize(SPR_BLOT));
526 
527  this->CreateNestedTree();
528  this->vscroll = this->GetScrollbar(WID_NCL_SCROLLBAR);
530 
531  this->GetWidget<NWidgetStacked>(WID_NCL_SEL_ALL_UPDATE)->SetDisplayedPlane(select_all);
532 
533  this->querystrings[WID_NCL_FILTER] = &this->filter_editbox;
534  this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
536  this->SetWidgetDisabledState(WID_NCL_SEARCH_EXTERNAL, this->auto_select);
537  this->filter_data.types = types;
538 
540  this->content.SetListing(this->last_sorting);
541  this->content.SetFiltering(this->last_filtering);
542  this->content.SetSortFuncs(this->sorter_funcs);
543  this->content.SetFilterFuncs(this->filter_funcs);
544  this->UpdateFilterState();
545  this->content.ForceRebuild();
546  this->FilterContentList();
547  this->SortContentList();
548  this->InvalidateData();
549  }
550 
553  {
555  }
556 
557  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
558  {
559  switch (widget) {
560  case WID_NCL_FILTER_CAPT:
561  *size = maxdim(*size, GetStringBoundingBox(STR_CONTENT_FILTER_TITLE));
562  break;
563 
564  case WID_NCL_CHECKBOX:
565  size->width = this->checkbox_size.width + WD_MATRIX_RIGHT + WD_MATRIX_LEFT;
566  break;
567 
568  case WID_NCL_TYPE: {
569  Dimension d = *size;
570  for (int i = CONTENT_TYPE_BEGIN; i < CONTENT_TYPE_END; i++) {
571  d = maxdim(d, GetStringBoundingBox(STR_CONTENT_TYPE_BASE_GRAPHICS + i - CONTENT_TYPE_BASE_GRAPHICS));
572  }
573  size->width = d.width + WD_MATRIX_RIGHT + WD_MATRIX_LEFT;
574  break;
575  }
576 
577  case WID_NCL_MATRIX:
578  resize->height = max(this->checkbox_size.height, (uint)FONT_HEIGHT_NORMAL) + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
579  size->height = 10 * resize->height;
580  break;
581  }
582  }
583 
584 
585  void DrawWidget(const Rect &r, int widget) const override
586  {
587  switch (widget) {
588  case WID_NCL_FILTER_CAPT:
589  DrawString(r.left, r.right, r.top, STR_CONTENT_FILTER_TITLE, TC_FROMSTRING, SA_RIGHT);
590  break;
591 
592  case WID_NCL_DETAILS:
593  this->DrawDetails(r);
594  break;
595 
596  case WID_NCL_MATRIX:
597  this->DrawMatrix(r);
598  break;
599  }
600  }
601 
602  void OnPaint() override
603  {
604  const SortButtonState arrow = this->content.IsDescSortOrder() ? SBS_DOWN : SBS_UP;
605 
606  if (this->content.NeedRebuild()) {
607  this->BuildContentList();
608  }
609 
610  this->DrawWidgets();
611 
612  switch (this->content.SortType()) {
614  case WID_NCL_TYPE - WID_NCL_CHECKBOX: this->DrawSortButtonState(WID_NCL_TYPE, arrow); break;
615  case WID_NCL_NAME - WID_NCL_CHECKBOX: this->DrawSortButtonState(WID_NCL_NAME, arrow); break;
616  }
617  }
618 
623  void DrawMatrix(const Rect &r) const
624  {
625  const NWidgetBase *nwi_checkbox = this->GetWidget<NWidgetBase>(WID_NCL_CHECKBOX);
626  const NWidgetBase *nwi_name = this->GetWidget<NWidgetBase>(WID_NCL_NAME);
627  const NWidgetBase *nwi_type = this->GetWidget<NWidgetBase>(WID_NCL_TYPE);
628 
629  int line_height = max(this->checkbox_size.height, (uint)FONT_HEIGHT_NORMAL);
630 
631  /* Fill the matrix with the information */
632  int sprite_y_offset = WD_MATRIX_TOP + (line_height - this->checkbox_size.height) / 2 - 1;
633  int text_y_offset = WD_MATRIX_TOP + (line_height - FONT_HEIGHT_NORMAL) / 2;
634  uint y = r.top;
635 
636  auto iter = this->content.begin() + this->vscroll->GetPosition();
637  size_t last = this->vscroll->GetPosition() + this->vscroll->GetCapacity();
638  auto end = (last < this->content.size()) ? this->content.begin() + last : this->content.end();
639 
640  for (; iter != end; iter++) {
641  const ContentInfo *ci = *iter;
642 
643  if (ci == this->selected) GfxFillRect(r.left + 1, y + 1, r.right - 1, y + this->resize.step_height - 1, PC_GREY);
644 
645  SpriteID sprite;
646  SpriteID pal = PAL_NONE;
647  switch (ci->state) {
648  case ContentInfo::UNSELECTED: sprite = SPR_BOX_EMPTY; break;
649  case ContentInfo::SELECTED: sprite = SPR_BOX_CHECKED; break;
650  case ContentInfo::AUTOSELECTED: sprite = SPR_BOX_CHECKED; break;
651  case ContentInfo::ALREADY_HERE: sprite = SPR_BLOT; pal = PALETTE_TO_GREEN; break;
652  case ContentInfo::DOES_NOT_EXIST: sprite = SPR_BLOT; pal = PALETTE_TO_RED; break;
653  default: NOT_REACHED();
654  }
655  DrawSprite(sprite, pal, nwi_checkbox->pos_x + (pal == PAL_NONE ? 2 : 3), y + sprite_y_offset + (pal == PAL_NONE ? 1 : 0));
656 
657  StringID str = STR_CONTENT_TYPE_BASE_GRAPHICS + ci->type - CONTENT_TYPE_BASE_GRAPHICS;
658  DrawString(nwi_type->pos_x, nwi_type->pos_x + nwi_type->current_x - 1, y + text_y_offset, str, TC_BLACK, SA_HOR_CENTER);
659 
660  DrawString(nwi_name->pos_x + WD_FRAMERECT_LEFT, nwi_name->pos_x + nwi_name->current_x - WD_FRAMERECT_RIGHT, y + text_y_offset, ci->name, TC_BLACK);
661  y += this->resize.step_height;
662  }
663  }
664 
669  void DrawDetails(const Rect &r) const
670  {
671  static const int DETAIL_LEFT = 5;
672  static const int DETAIL_RIGHT = 5;
673  static const int DETAIL_TOP = 5;
674 
675  /* Height for the title banner */
676  int DETAIL_TITLE_HEIGHT = 5 * FONT_HEIGHT_NORMAL;
677 
678  /* Create the nice grayish rectangle at the details top */
679  GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.top + DETAIL_TITLE_HEIGHT, PC_DARK_BLUE);
680  DrawString(r.left + WD_INSET_LEFT, r.right - WD_INSET_RIGHT, r.top + FONT_HEIGHT_NORMAL + WD_INSET_TOP, STR_CONTENT_DETAIL_TITLE, TC_FROMSTRING, SA_HOR_CENTER);
681 
682  /* Draw the total download size */
683  SetDParam(0, this->filesize_sum);
684  DrawString(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, r.bottom - FONT_HEIGHT_NORMAL - WD_PAR_VSEP_NORMAL, STR_CONTENT_TOTAL_DOWNLOAD_SIZE);
685 
686  if (this->selected == nullptr) return;
687 
688  /* And fill the rest of the details when there's information to place there */
689  DrawStringMultiLine(r.left + WD_INSET_LEFT, r.right - WD_INSET_RIGHT, r.top + DETAIL_TITLE_HEIGHT / 2, r.top + DETAIL_TITLE_HEIGHT, STR_CONTENT_DETAIL_SUBTITLE_UNSELECTED + this->selected->state, TC_FROMSTRING, SA_CENTER);
690 
691  /* Also show the total download size, so keep some space from the bottom */
692  const uint max_y = r.bottom - FONT_HEIGHT_NORMAL - WD_PAR_VSEP_WIDE;
693  int y = r.top + DETAIL_TITLE_HEIGHT + DETAIL_TOP;
694 
695  if (this->selected->upgrade) {
696  SetDParam(0, STR_CONTENT_TYPE_BASE_GRAPHICS + this->selected->type - CONTENT_TYPE_BASE_GRAPHICS);
697  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_UPDATE);
698  y += WD_PAR_VSEP_WIDE;
699  }
700 
701  SetDParamStr(0, this->selected->name);
702  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_NAME);
703 
704  if (!StrEmpty(this->selected->version)) {
705  SetDParamStr(0, this->selected->version);
706  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_VERSION);
707  }
708 
709  if (!StrEmpty(this->selected->description)) {
710  SetDParamStr(0, this->selected->description);
711  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_DESCRIPTION);
712  }
713 
714  if (!StrEmpty(this->selected->url)) {
715  SetDParamStr(0, this->selected->url);
716  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_URL);
717  }
718 
719  SetDParam(0, STR_CONTENT_TYPE_BASE_GRAPHICS + this->selected->type - CONTENT_TYPE_BASE_GRAPHICS);
720  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_TYPE);
721 
722  y += WD_PAR_VSEP_WIDE;
723  SetDParam(0, this->selected->filesize);
724  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_FILESIZE);
725 
726  if (this->selected->dependency_count != 0) {
727  /* List dependencies */
728  char buf[DRAW_STRING_BUFFER] = "";
729  char *p = buf;
730  for (uint i = 0; i < this->selected->dependency_count; i++) {
731  ContentID cid = this->selected->dependencies[i];
732 
733  /* Try to find the dependency */
735  for (; iter != _network_content_client.End(); iter++) {
736  const ContentInfo *ci = *iter;
737  if (ci->id != cid) continue;
738 
739  p += seprintf(p, lastof(buf), p == buf ? "%s" : ", %s", (*iter)->name);
740  break;
741  }
742  }
743  SetDParamStr(0, buf);
744  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_DEPENDENCIES);
745  }
746 
747  if (this->selected->tag_count != 0) {
748  /* List all tags */
749  char buf[DRAW_STRING_BUFFER] = "";
750  char *p = buf;
751  for (uint i = 0; i < this->selected->tag_count; i++) {
752  p += seprintf(p, lastof(buf), i == 0 ? "%s" : ", %s", this->selected->tags[i]);
753  }
754  SetDParamStr(0, buf);
755  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_TAGS);
756  }
757 
758  if (this->selected->IsSelected()) {
759  /* When selected show all manually selected content that depends on this */
760  ConstContentVector tree;
762 
763  char buf[DRAW_STRING_BUFFER] = "";
764  char *p = buf;
765  for (const ContentInfo *ci : tree) {
766  if (ci == this->selected || ci->state != ContentInfo::SELECTED) continue;
767 
768  p += seprintf(p, lastof(buf), buf == p ? "%s" : ", %s", ci->name);
769  }
770  if (p != buf) {
771  SetDParamStr(0, buf);
772  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_SELECTED_BECAUSE_OF);
773  }
774  }
775  }
776 
777  void OnClick(Point pt, int widget, int click_count) override
778  {
779  if (widget >= WID_NCL_TEXTFILE && widget < WID_NCL_TEXTFILE + TFT_END) {
780  if (this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE) return;
781 
782  ShowContentTextfileWindow((TextfileType)(widget - WID_NCL_TEXTFILE), this->selected);
783  return;
784  }
785 
786  switch (widget) {
787  case WID_NCL_MATRIX: {
788  uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NCL_MATRIX);
789  if (id_v >= this->content.size()) return; // click out of bounds
790 
791  this->selected = this->content[id_v];
792  this->list_pos = id_v;
793 
794  const NWidgetBase *checkbox = this->GetWidget<NWidgetBase>(WID_NCL_CHECKBOX);
795  if (click_count > 1 || IsInsideBS(pt.x, checkbox->pos_x, checkbox->current_x)) {
797  this->content.ForceResort();
798  }
799 
800  if (this->filter_data.types.any()) {
801  this->content.ForceRebuild();
802  }
803 
804  this->InvalidateData();
805  break;
806  }
807 
808  case WID_NCL_CHECKBOX:
809  case WID_NCL_TYPE:
810  case WID_NCL_NAME:
811  if (this->content.SortType() == widget - WID_NCL_CHECKBOX) {
812  this->content.ToggleSortOrder();
813  if (this->content.size() > 0) this->list_pos = (int)this->content.size() - this->list_pos - 1;
814  } else {
815  this->content.SetSortType(widget - WID_NCL_CHECKBOX);
816  this->content.ForceResort();
817  this->SortContentList();
818  }
819  this->ScrollToSelected();
820  this->InvalidateData();
821  break;
822 
823  case WID_NCL_SELECT_ALL:
825  this->InvalidateData();
826  break;
827 
830  this->InvalidateData();
831  break;
832 
833  case WID_NCL_UNSELECT:
835  this->InvalidateData();
836  break;
837 
838  case WID_NCL_CANCEL:
839  delete this;
840  break;
841 
842  case WID_NCL_OPEN_URL:
843  if (this->selected != nullptr) {
844  extern void OpenBrowser(const char *url);
845  OpenBrowser(this->selected->url);
846  }
847  break;
848 
849  case WID_NCL_DOWNLOAD:
851  break;
852 
855  this->OpenExternalSearch();
856  } else {
857  ShowQuery(STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER_CAPTION, STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER, this, ExternalSearchDisclaimerCallback);
858  }
859  break;
860  }
861  }
862 
863  EventState OnKeyPress(WChar key, uint16 keycode) override
864  {
865  switch (keycode) {
866  case WKC_UP:
867  /* scroll up by one */
868  if (this->list_pos > 0) this->list_pos--;
869  break;
870  case WKC_DOWN:
871  /* scroll down by one */
872  if (this->list_pos < (int)this->content.size() - 1) this->list_pos++;
873  break;
874  case WKC_PAGEUP:
875  /* scroll up a page */
876  this->list_pos = (this->list_pos < this->vscroll->GetCapacity()) ? 0 : this->list_pos - this->vscroll->GetCapacity();
877  break;
878  case WKC_PAGEDOWN:
879  /* scroll down a page */
880  this->list_pos = min(this->list_pos + this->vscroll->GetCapacity(), (int)this->content.size() - 1);
881  break;
882  case WKC_HOME:
883  /* jump to beginning */
884  this->list_pos = 0;
885  break;
886  case WKC_END:
887  /* jump to end */
888  this->list_pos = (int)this->content.size() - 1;
889  break;
890 
891  case WKC_SPACE:
892  case WKC_RETURN:
893  if (keycode == WKC_RETURN || !IsWidgetFocused(WID_NCL_FILTER)) {
894  if (this->selected != nullptr) {
896  this->content.ForceResort();
897  this->InvalidateData();
898  }
899  if (this->filter_data.types.any()) {
900  this->content.ForceRebuild();
901  this->InvalidateData();
902  }
903  return ES_HANDLED;
904  }
905  /* space is pressed and filter is focused. */
906  FALLTHROUGH;
907 
908  default:
909  return ES_NOT_HANDLED;
910  }
911 
912  if (this->content.size() == 0) {
913  this->list_pos = 0; // above stuff may result in "-1".
914  if (this->UpdateFilterState()) {
915  this->content.ForceRebuild();
916  this->InvalidateData();
917  }
918  return ES_HANDLED;
919  }
920 
921  this->selected = this->content[this->list_pos];
922 
923  if (this->UpdateFilterState()) {
924  this->content.ForceRebuild();
925  } else {
926  /* Scroll to the new content if it is outside the current range. */
927  this->ScrollToSelected();
928  }
929 
930  /* redraw window */
931  this->InvalidateData();
932  return ES_HANDLED;
933  }
934 
935  void OnEditboxChanged(int wid) override
936  {
937  if (wid == WID_NCL_FILTER) {
938  this->filter_data.string_filter.SetFilterTerm(this->filter_editbox.text.buf);
939  this->UpdateFilterState();
940  this->content.ForceRebuild();
941  this->InvalidateData();
942  }
943  }
944 
945  void OnResize() override
946  {
947  this->vscroll->SetCapacityFromWidget(this, WID_NCL_MATRIX);
948  }
949 
950  void OnReceiveContentInfo(const ContentInfo *rci) override
951  {
952  if (this->auto_select && !rci->IsSelected()) _network_content_client.ToggleSelectedState(rci);
953  this->content.ForceRebuild();
954  this->InvalidateData();
955  }
956 
957  void OnDownloadComplete(ContentID cid) override
958  {
959  this->content.ForceResort();
960  this->InvalidateData();
961  }
962 
963  void OnConnect(bool success) override
964  {
965  if (!success) {
966  ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_CONNECT, INVALID_STRING_ID, WL_ERROR);
967  delete this;
968  return;
969  }
970 
971  this->InvalidateData();
972  }
973 
979  void OnInvalidateData(int data = 0, bool gui_scope = true) override
980  {
981  if (!gui_scope) return;
982  if (this->content.NeedRebuild()) this->BuildContentList();
983 
984  /* To sum all the bytes we intend to download */
985  this->filesize_sum = 0;
986  bool show_select_all = false;
987  bool show_select_upgrade = false;
988  for (const ContentInfo *ci : this->content) {
989  switch (ci->state) {
992  this->filesize_sum += ci->filesize;
993  break;
994 
996  show_select_all = true;
997  show_select_upgrade |= ci->upgrade;
998  break;
999 
1000  default:
1001  break;
1002  }
1003  }
1004 
1005  /* If data == 2 then the status window caused this OnInvalidate */
1007  this->SetWidgetDisabledState(WID_NCL_UNSELECT, this->filesize_sum == 0);
1008  this->SetWidgetDisabledState(WID_NCL_SELECT_ALL, !show_select_all);
1009  this->SetWidgetDisabledState(WID_NCL_SELECT_UPDATE, !show_select_upgrade);
1010  this->SetWidgetDisabledState(WID_NCL_OPEN_URL, this->selected == nullptr || StrEmpty(this->selected->url));
1011  for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
1012  this->SetWidgetDisabledState(WID_NCL_TEXTFILE + tft, this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE || this->selected->GetTextfile(tft) == nullptr);
1013  }
1014 
1015  this->GetWidget<NWidgetCore>(WID_NCL_CANCEL)->widget_data = this->filesize_sum == 0 ? STR_AI_SETTINGS_CLOSE : STR_AI_LIST_CANCEL;
1016  }
1017 };
1018 
1021 
1023  &StateSorter,
1024  &TypeSorter,
1025  &NameSorter,
1026 };
1027 
1029  &TagNameFilter,
1030  &TypeOrSelectedFilter,
1031 };
1032 
1034 
1039 {
1040  for (int i = CONTENT_TYPE_BEGIN; i < CONTENT_TYPE_END; i++) {
1042  }
1043 }
1044 
1048  NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
1049  NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_CONTENT_TITLE, STR_NULL),
1050  NWidget(WWT_DEFSIZEBOX, COLOUR_LIGHT_BLUE),
1051  EndContainer(),
1052  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_BACKGROUND),
1055  /* Top */
1056  NWidget(WWT_EMPTY, COLOUR_LIGHT_BLUE, WID_NCL_FILTER_CAPT), SetFill(1, 0), SetResize(1, 0),
1057  NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NCL_FILTER), SetFill(1, 0), SetResize(1, 0),
1058  SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
1059  EndContainer(),
1062  /* Left side. */
1063  NWidget(NWID_VERTICAL), SetPIP(0, 4, 0),
1067  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_CHECKBOX), SetMinimalSize(13, 1), SetDataTip(STR_EMPTY, STR_NULL),
1068  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TYPE),
1069  SetDataTip(STR_CONTENT_TYPE_CAPTION, STR_CONTENT_TYPE_CAPTION_TOOLTIP),
1070  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_NAME), SetResize(1, 0), SetFill(1, 0),
1071  SetDataTip(STR_CONTENT_NAME_CAPTION, STR_CONTENT_NAME_CAPTION_TOOLTIP),
1072  EndContainer(),
1073  NWidget(WWT_MATRIX, COLOUR_LIGHT_BLUE, WID_NCL_MATRIX), SetResize(1, 14), SetFill(1, 1), SetScrollbar(WID_NCL_SCROLLBAR), SetMatrixDataTip(1, 0, STR_CONTENT_MATRIX_TOOLTIP),
1074  EndContainer(),
1075  NWidget(NWID_VSCROLLBAR, COLOUR_LIGHT_BLUE, WID_NCL_SCROLLBAR),
1076  EndContainer(),
1078  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NCL_SEL_ALL_UPDATE), SetResize(1, 0), SetFill(1, 0),
1079  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SELECT_UPDATE), SetResize(1, 0), SetFill(1, 0),
1080  SetDataTip(STR_CONTENT_SELECT_UPDATES_CAPTION, STR_CONTENT_SELECT_UPDATES_CAPTION_TOOLTIP),
1081  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SELECT_ALL), SetResize(1, 0), SetFill(1, 0),
1082  SetDataTip(STR_CONTENT_SELECT_ALL_CAPTION, STR_CONTENT_SELECT_ALL_CAPTION_TOOLTIP),
1083  EndContainer(),
1084  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_UNSELECT), SetResize(1, 0), SetFill(1, 0),
1085  SetDataTip(STR_CONTENT_UNSELECT_ALL_CAPTION, STR_CONTENT_UNSELECT_ALL_CAPTION_TOOLTIP),
1086  EndContainer(),
1087  EndContainer(),
1088  /* Right side. */
1089  NWidget(NWID_VERTICAL), SetPIP(0, 4, 0),
1090  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_DETAILS), SetResize(1, 1), SetFill(1, 1), EndContainer(),
1092  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
1093  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
1094  EndContainer(),
1096  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),
1097  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
1098  EndContainer(),
1099  EndContainer(),
1100  EndContainer(),
1102  /* Bottom. */
1104  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SEARCH_EXTERNAL), SetResize(1, 0), SetFill(1, 0),
1105  SetDataTip(STR_CONTENT_SEARCH_EXTERNAL, STR_CONTENT_SEARCH_EXTERNAL_TOOLTIP),
1107  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_CANCEL), SetResize(1, 0), SetFill(1, 0),
1108  SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
1109  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_DOWNLOAD), SetResize(1, 0), SetFill(1, 0),
1110  SetDataTip(STR_CONTENT_DOWNLOAD_CAPTION, STR_CONTENT_DOWNLOAD_CAPTION_TOOLTIP),
1111  EndContainer(),
1112  EndContainer(),
1114  /* Resize button. */
1116  NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1117  NWidget(WWT_RESIZEBOX, COLOUR_LIGHT_BLUE),
1118  EndContainer(),
1119  EndContainer(),
1120 };
1121 
1124  WDP_CENTER, "list_content", 630, 460,
1126  0,
1127  _nested_network_content_list_widgets, lengthof(_nested_network_content_list_widgets)
1128 );
1129 
1138 {
1139 #if defined(WITH_ZLIB)
1140  std::bitset<CONTENT_TYPE_END> types;
1142  if (cv == nullptr) {
1143  assert(type1 != CONTENT_TYPE_END || type2 == CONTENT_TYPE_END);
1144  assert(type1 == CONTENT_TYPE_END || type1 != type2);
1147 
1148  if (type1 != CONTENT_TYPE_END) types[type1] = true;
1149  if (type2 != CONTENT_TYPE_END) types[type2] = true;
1150  } else {
1152  }
1153 
1155  new NetworkContentListWindow(&_network_content_list_desc, cv != nullptr, types);
1156 #else
1157  ShowErrorMessage(STR_CONTENT_NO_ZLIB, STR_CONTENT_NO_ZLIB_SUB, WL_ERROR);
1158  /* Connection failed... clean up the mess */
1159  if (cv != nullptr) {
1160  for (ContentInfo *ci : *cv) delete ci;
1161  }
1162 #endif /* WITH_ZLIB */
1163 }
EventState
State of handling an event.
Definition: window_type.h:711
static WindowDesc _network_content_list_desc(WDP_CENTER, "list_content", 630, 460, WC_NETWORK_WINDOW, WC_NONE, 0, _nested_network_content_list_widgets, lengthof(_nested_network_content_list_widgets))
Window description of the content list.
void Close() override
Disconnect from the content server.
Helper to mark the end of the types.
Definition: tcp_content.h:33
Empty widget, place holder to reserve space in widget array.
Definition: widget_type.h:46
const ContentInfo *const * ConstContentIterator
Iterator for the constant content vector.
void RebuildDone()
Notify the sortlist that the rebuild is done.
The content consists of base graphics.
Definition: tcp_content.h:23
Panel with content details.
bool IsSelected() const
Is the state either selected or autoselected?
Definition: tcp_content.cpp:73
std::vector< ContentType > receivedTypes
Types we received so we can update their cache.
void DownloadSelectedContent(uint &files, uint &bytes, bool fallback=false)
Actually begin downloading the content we selected.
char filename[48]
Filename (for the .tar.gz; only valid on download)
Definition: tcp_content.h:68
ConstContentIterator Begin() const
Get the begin of the content inf iterator.
~BaseNetworkContentDownloadStatusWindow()
Free everything associated with this window.
Horizontally center the text.
Definition: gfx_func.h:95
ResizeInfo resize
Resize information.
Definition: window_gui.h:322
static bool _accepted_external_search
Whether the user accepted to enter external websites during this session.
Panel with list of content.
Scan for base sets.
Definition: fileio_func.h:98
void ScrollTowards(int position)
Scroll towards the given position; if the item is visible nothing happens, otherwise it will be shown...
Definition: widget_type.h:729
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:928
Window that lists the content that&#39;s at the content server.
uint32 unique_id
Unique ID; either GRF ID or shortname.
Definition: tcp_content.h:73
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:110
void SetWidgetDisabledState(byte widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition: window_gui.h:392
Offset at right of a matrix cell.
Definition: window_gui.h:77
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3215
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
Window * parent
Parent window.
Definition: window_gui.h:337
const ContentInfo * selected
The selected content info.
High level window description.
Definition: window_gui.h:166
Saveload window; Window numbers:
Definition: window_type.h:137
void OnDownloadProgress(const ContentInfo *ci, int bytes) override
We have progress in the download of a file.
bool Filter(FilterFunction *decide, F filter_data)
Filter the list.
void DrawWidgets() const
Paint all widgets of a window.
Definition: widget.cpp:602
static uint FindSets()
Do the scan for files.
Scrollbar data structure.
Definition: widget_type.h:587
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
Definition: string.cpp:407
static void DrawMatrix(const Rect &r, Colours colour, bool clicked, uint16 data, uint resize_x, uint resize_y)
Draw a matrix widget.
Definition: widget.cpp:276
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:62
Dimension checkbox_size
Size of checkbox/"blot" sprite.
Normal amount of vertical space between two paragraphs of text.
Definition: window_gui.h:137
textfile; Window numbers:
Definition: window_type.h:180
Horizontal container.
Definition: widget_type.h:73
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1130
void ResetState()
Reset the matching state to process a new item.
The passed event is not handled.
Definition: window_type.h:713
void SetSortFuncs(SortFunction *const *n_funcs)
Hand the array of sort function pointers to the sort list.
bool GetState() const
Get the matching state of the current item.
Callbacks for notifying others about incoming data.
Filter data for NetworkContentListWindow.
uint32 filesize
Size of the file.
Definition: tcp_content.h:67
The content consists of a scenario.
Definition: tcp_content.h:27
uint8 dependency_count
Number of dependencies.
Definition: tcp_content.h:75
&#39;Name&#39; button.
char(* tags)[32]
Malloced array of tags (strings)
Definition: tcp_content.h:78
char * md5sumToString(char *buf, const char *last, const uint8 md5sum[16])
Convert the md5sum to a hexadecimal string representation.
Definition: string.cpp:425
a textbox for typing
Definition: widget_type.h:69
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:66
void SetFilterType(uint8 n_type)
Set the filtertype of the list.
static const int ACTION_CLEAR
Clear editbox.
NewGRF changelog.
Definition: textfile_type.h:18
void OnPaint() override
The window must be repainted.
void ReverseLookupTreeDependency(ConstContentVector &tree, const ContentInfo *child) const
Reverse lookup the dependencies of all parents over a given child.
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=nullptr, uint textref_stack_size=0, const uint32 *textref_stack=nullptr)
Display an error message in a window.
Definition: error_gui.cpp:380
GUIContentList content
List with content.
ContentID * dependencies
Malloced array of dependencies (unique server side ids)
Definition: tcp_content.h:76
Close box (at top-left of a window)
Definition: widget_type.h:67
Scrollbar * vscroll
Cache of the vertical scrollbar.
static const int DRAW_STRING_BUFFER
Size of the buffer used for drawing strings.
Definition: gfx_func.h:83
Offset at top of a matrix cell.
Definition: window_gui.h:78
ContentListFilterData filter_data
Filter for content list.
Scrollbar of matrix.
The content has been selected as dependency.
Definition: tcp_content.h:59
std::bitset< CONTENT_TYPE_END > types
Content types displayed.
static NWidgetPart SetMinimalTextLines(uint8 lines, uint8 spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
Definition: widget_type.h:963
NetworkContentDownloadStatusWindow()
Create a new download window based on a list of content information with flags whether to download th...
String filter and state.
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:48
static bool StateSorter(const ContentInfo *const &a, const ContentInfo *const &b)
Sort content by state.
void SetFilterFuncs(FilterFunction *const *n_funcs)
Hand the array of filter function pointers to the sort list.
Filter by query sting.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
NewGRF readme.
Definition: textfile_type.h:17
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:24
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
ContentID
Unique identifier for the content.
Definition: tcp_content.h:49
void OnEditboxChanged(int wid) override
The text in an editbox has been edited.
The content has not been selected.
Definition: tcp_content.h:57
void CreateNestedTree(bool fill_nested=true)
Perform the first part of the initialization of a nested widget tree.
Definition: window.cpp:1828
void SetListing(Listing l)
Import sort conditions.
Large amount of vertical space between two paragraphs of text.
Definition: window_gui.h:138
Data structure describing what to show in the list (filter criteria).
Definition: sortlist_type.h:36
Search external sites for missing NewGRF.
bool NeedRebuild() const
Check if a rebuild is needed.
static 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.
Definition: math_func.hpp:248
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition: widget.cpp:175
void SetCount(int num)
Sets the number of elements in the list.
Definition: widget_type.h:668
The content does not exist in the content system.
Definition: tcp_content.h:61
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:908
void ForceRebuild()
Force that a rebuild is needed.
void ScrollToSelected()
Make sure that the currently selected content info is within the visible part of the matrix...
&#39;Cancel&#39; button.
NewGRF license.
Definition: textfile_type.h:19
Data structure for an opened window.
Definition: window_gui.h:276
void UnselectAll()
Unselect everything that we&#39;ve not downloaded so far.
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1844
static NWidgetPart SetMatrixDataTip(uint8 cols, uint8 rows, StringID tip)
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
Definition: widget_type.h:1030
void BuildContentTypeStringList()
Build array of all strings corresponding to the content types.
void SetFilterTerm(const char *str)
Set the term to filter on.
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition: window.cpp:1857
&#39;Download&#39; button.
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:279
~NetworkContentDownloadStatusWindow()
Free whatever we&#39;ve allocated.
char name[32]
Name of the content.
Definition: tcp_content.h:69
The content consists of a game script.
Definition: tcp_content.h:31
void OnDownloadProgress(const ContentInfo *ci, int bytes) override
We have progress in the download of a file.
void AddCallback(ContentCallback *cb)
Add a callback to this class.
StringFilter string_filter
Text filter of content list.
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
Invisible widget that takes some space.
Definition: widget_type.h:77
static void ExternalSearchDisclaimerCallback(Window *w, bool accepted)
Callback function for disclaimer about entering external websites.
ConstContentIterator End() const
Get the end of the content inf iterator.
Offset at bottom of a matrix cell.
Definition: window_gui.h:79
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX) ...
Definition: widget_type.h:63
int GetScrolledRowFromWidget(int clickpos, const Window *const w, int widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition: widget.cpp:1957
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, lengthof(_nested_network_content_download_status_window_widgets))
Window description for the download window.
std::vector< ContentInfo * > ContentVector
Vector with content info.
uint8 tag_count
Number of tags.
Definition: tcp_content.h:77
char version[16]
Version of the content.
Definition: tcp_content.h:70
static bool CDECL TypeOrSelectedFilter(const ContentInfo *const *a, ContentListFilterData &filter)
Filter content by type, but still show content selected for download.
void SelectUpgrade()
Select everything that&#39;s an update for something we&#39;ve got.
void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallbackProc *callback)
Show a modal confirmation window with standard &#39;yes&#39; and &#39;no&#39; buttons The window is aligned to the ce...
Definition: misc_gui.cpp:1260
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
Sort descending.
Definition: window_gui.h:225
static const NWidgetPart _nested_network_content_list_widgets[]
The widgets for the content list.
SmallMap< int, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition: window_gui.h:328
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:176
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1012
NetworkContentListWindow(WindowDesc *desc, bool select_all, const std::bitset< CONTENT_TYPE_END > &types)
Create the content list window.
Data stored about a string that can be modified in the GUI.
Window for displaying the textfile of an item in the content list.
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:945
Left offset of string.
Definition: window_gui.h:44
Center both horizontally and vertically.
Definition: gfx_func.h:104
The content is already at the client side.
Definition: tcp_content.h:60
ContentID id
Unique (server side) ID for the content.
Definition: tcp_content.h:66
int list_pos
Our position in the list.
static bool CDECL TagNameFilter(const ContentInfo *const *a, ContentListFilterData &filter)
Filter content by tags/name.
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:102
Simple depressed panel.
Definition: widget_type.h:48
&#39;Unselect all&#39; button.
bool state
Filter on/off.
Definition: sortlist_type.h:37
void ScanScenarios()
Force a (re)scan of the scenarios.
Definition: fios.cpp:769
bool UpdateFilterState()
Update filter state based on current window state.
void Clear()
Clear all downloaded content information.
static const NWidgetPart _nested_network_content_download_status_window_widgets[]
Nested widgets for the download window.
static bool TypeSorter(const ContentInfo *const &a, const ContentInfo *const &b)
Sort content by type.
Scan for scenarios and heightmaps.
Definition: fileio_func.h:101
void DrawSortButtonState(int widget, SortButtonState state) const
Draw a sort button&#39;s up or down arrow symbol.
Definition: widget.cpp:636
uint step_height
Step-size of height resize changes.
Definition: window_gui.h:218
const Scrollbar * GetScrollbar(uint widnum) const
Return the Scrollbar to a widget index.
Definition: window.cpp:309
int pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:175
Offset at left of a matrix cell.
Definition: window_gui.h:76
void RequestContentList(ContentType type)
Request the content list for the given type.
State state
Whether the content info is selected (for download)
Definition: tcp_content.h:79
Background of the window.
Center the window.
Definition: window_gui.h:155
void OnReceiveContentInfo(const ContentInfo *rci) override
We received a content info.
virtual void LoadTextfile(const char *textfile, Subdirectory dir)
Loads the textfile text from file and setup lines.
SortButtonState
State of a sort direction button.
Definition: window_gui.h:222
static NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx=-1)
Widget part function for starting a new &#39;real&#39; widget.
Definition: widget_type.h:1112
Offset at bottom to draw the frame rectangular area.
Definition: window_gui.h:63
Baseclass for nested widgets.
Definition: widget_type.h:124
int DrawString(int left, int right, int top, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition: gfx.cpp:498
const ContentInfo * ci
View the textfile of this ContentInfo.
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
TextfileType
Additional text files accompanying Tar archives.
Definition: textfile_type.h:14
Grid of rows and columns.
Definition: widget_type.h:57
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:40
void DrawMatrix(const Rect &r) const
Draw/fill the matrix with the list of content to download.
int cancel_button
Widget button of parent window to simulate when pressing CANCEL in OSK.
void SetSortType(uint8 n_type)
Set the sorttype of the list.
bool Sort(SortFunction *compare)
Sort the list.
void BuildContentList()
(Re)build the network game list as its amount has changed because an item has been added or deleted f...
QueryString filter_editbox
Filter editbox;.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
&#39;Type&#39; button.
byte md5sum[16]
The MD5 checksum.
Definition: tcp_content.h:74
uint total_bytes
Number of bytes to download.
The content consists of a GS library.
Definition: tcp_content.h:32
&#39;Select updates&#39; button.
void SortContentList()
Sort the content list.
Window for showing the download status of content.
bool auto_select
Automatically select all content when the meta-data becomes available.
The window is a modal child of some other window, meaning the parent is &#39;inactive&#39;.
Definition: window_gui.h:209
uint DoScan(Subdirectory sd)
Perform the scanning of a particular subdirectory.
Definition: fileio.cpp:608
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition: window.cpp:984
The content consists of a NewGRF.
Definition: tcp_content.h:24
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:700
ContentType
The values in the enum are important; they are used as database &#39;keys&#39;.
Definition: tcp_content.h:21
Network status window; Window numbers:
Definition: window_type.h:485
void AddLine(const char *str)
Pass another text line from the current item to the filter.
void ForceResort()
Force a resort next Sort call Reset the resort timer if used too.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:38
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1162
NWID_SELECTION widget for select all/update buttons..
static const uint8 PC_GREY
Grey palette colour.
Definition: gfx_func.h:205
static const uint8 PC_DARK_BLUE
Dark blue palette colour.
Definition: gfx_func.h:222
The content consists of an AI library.
Definition: tcp_content.h:26
Mode
The mode of tar scanning.
Definition: fileio_func.h:96
User interface for downloading files.
char *const buf
buffer in which text is saved
Definition: textbuf_type.h:32
void FilterContentList()
Filter the content list.
void SelectAll()
Select everything we can select.
(Optional) Cancel/OK button.
char name[48]
The current name of the downloaded file.
ContentListFilterCriteria
Filter criteria for NetworkContentListWindow.
uint downloaded_files
Number of files downloaded.
Filter editbox.
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:59
Window for displaying a textfile.
Definition: textfile_gui.h:21
int strnatcmp(const char *s1, const char *s2, bool ignore_garbage_at_front)
Compares two strings using case insensitive natural sort.
Definition: string.cpp:578
void RemoveCallback(ContentCallback *cb)
Remove a callback.
&#39;Select all&#39; button.
uint32 SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:17
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:57
void SetFilterState(bool state)
Enable or disable the filter.
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
uint total_files
Number of files to download.
The content consists of a heightmap.
Definition: tcp_content.h:28
The content consists of an AI.
Definition: tcp_content.h:25
bool include(std::vector< T > &vec, const T &item)
Helper function to append an item to a vector if it is not already contained Consider using std::set...
const char * GetTextfile(TextfileType type) const
Search a textfile file next to this file in the content list.
void ToggleSortOrder()
Toggle the sort order Since that is the worst condition for the sort function reverse the list here...
ContentType type
Type of content.
Definition: tcp_content.h:65
bool upgrade
This item is an upgrade.
Definition: tcp_content.h:80
bool CDECL FilterFunction(const T *, F)
Signature of filter function.
Definition: sortlist_type.h:50
void ShowNetworkContentListWindow(ContentVector *cv, ContentType type1, ContentType type2)
Show the content list window with a given set of content.
Sort ascending.
Definition: window_gui.h:224
&#39;Open url&#39; button.
Button above checkboxes.
TextfileType file_type
Type of textfile to view.
Definition: textfile_gui.h:22
static void Rescan()
Rescans all searchpaths for available AIs.
Definition: ai_core.cpp:348
Vertical container.
Definition: widget_type.h:75
static bool NameSorter(const ContentInfo *const &a, const ContentInfo *const &b)
Sort content by name.
static NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
Definition: widget_type.h:997
Network window; Window numbers:
Definition: window_type.h:466
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: depend.cpp:66
static GUIContentList::FilterFunction *const filter_funcs[]
Filter functions.
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:172
Helper to mark the begin of the types.
Definition: tcp_content.h:22
The content consists of base music.
Definition: tcp_content.h:30
Right offset of string.
Definition: window_gui.h:45
bool SetFocusedWidget(int widget_index)
Set focus within this window to the given widget.
Definition: window.cpp:495
void ScanNewGRFFiles(NewGRFScanCallback *callback)
Scan for all NewGRFs.
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
Coordinates of a point in 2D.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:770
static Listing last_sorting
The last sorting setting.
Data structure describing how to show the list (what sort direction and criteria).
Definition: sortlist_type.h:31
uint16 GetCapacity() const
Gets the number of visible elements of the scrollbar.
Definition: widget_type.h:620
Open readme, changelog (+1) or license (+2) of a file in the content window.
static char content_type_strs[CONTENT_TYPE_END][64]
Cached strings for all content types.
uint downloaded_bytes
Number of bytes downloaded.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
The content has been manually selected.
Definition: tcp_content.h:58
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:61
void SetFiltering(Filtering f)
Import filter conditions.
The caption of the window.
Definition: misc_widget.h:49
static GUIContentList::SortFunction *const sorter_funcs[]
Sorter functions.
static NWidgetPart SetFill(uint fill_x, uint fill_y)
Widget part function for setting filling.
Definition: widget_type.h:981
bool IsDescSortOrder() const
Check if the sort order is descending.
Caption for the filter editbox.
static Filtering last_filtering
The last filtering setting.
Network content list.
Definition: window_type.h:29
void SetCapacityFromWidget(Window *w, int widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget. ...
Definition: widget.cpp:1971
Specification of a rectangle with absolute coordinates of all edges.
Vertical scrollbar.
Definition: widget_type.h:82
void OnConnect(bool success) override
Callback for when the connection has finished.
The passed event is handled.
Definition: window_type.h:712
Right align the text (must be a single bit).
Definition: gfx_func.h:96
BaseNetworkContentDownloadStatusWindow(WindowDesc *desc)
Create the window with the given description.
Scan nothing.
Definition: fileio_func.h:97
Filtering GetFiltering() const
Export current filter conditions.
Base window for showing the download status of content.
Filter by being of displayed type or selected for download.
uint32 cur_id
The current ID of the downloaded file.
void OnResize() override
Called after the window got resized.
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition: widget_type.h:78
void OnDownloadComplete(ContentID cid) override
We have finished downloading a file.
bool SortFunction(const T &, const T &)
Signature of sort function.
Definition: sortlist_type.h:49
Subdirectory GetContentInfoSubDir(ContentType type)
Helper to get the subdirectory a ContentInfo is located in.
char url[96]
URL related to the content.
Definition: tcp_content.h:71
Errors (eg. saving/loading failed)
Definition: error.h:23
GUIList< const ContentInfo *, ContentListFilterData & > GUIContentList
List with content infos.
uint32 WChar
Type for wide characters, i.e.
Definition: string_type.h:35
char description[512]
Description of the content.
Definition: tcp_content.h:72
bool IsWidgetFocused(byte widget_index) const
Check if given widget is focused within this window.
Definition: window_gui.h:432
static NWidgetPart SetScrollbar(int index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1093
Dimensions (a width and height) of a rectangle in 2D.
Container for all important information about a piece of content.
Definition: tcp_content.h:54
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:427
bool IsEmpty() const
Check whether any filter words were entered.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:60
void DrawDetails(const Rect &r) const
Helper function to draw the details part of this window.
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition: window.cpp:1259
Game options window; Window numbers:
Definition: window_type.h:606
void OpenExternalSearch()
Search external websites for content.
int find_index(std::vector< T > const &vec, T const &item)
Helper function to get the index of an item Consider using std::set, std::unordered_set or std::flat_...
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition: gfx.cpp:835
static NWidgetPart SetPIP(uint8 pre, uint8 inter, uint8 post)
Widget part function for setting a pre/inter/post spaces.
Definition: widget_type.h:1074
Network content download status.
Definition: window_type.h:33
~NetworkContentListWindow()
Free everything we allocated.
EventState OnKeyPress(WChar key, uint16 keycode) override
A key has been pressed.
ClientNetworkContentSocketHandler _network_content_client
The client we use to connect to the server.
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window&#39;s data as invalid (in need of re-computing)
Definition: window.cpp:3256
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:3316
uint filesize_sum
The sum of all selected file sizes.
int DrawStringMultiLine(int left, int right, int top, int bottom, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition: gfx.cpp:621
std::vector< const ContentInfo * > ConstContentVector
Vector with constant content info.
void ToggleSelectedState(const ContentInfo *ci)
Toggle the state of a content info and check its dependencies.
The content consists of base sounds.
Definition: tcp_content.h:29
Top offset of string.
Definition: window_gui.h:46
uint16 GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:629
uint8 SortType() const
Get the sorttype of the list.
Definition: sortlist_type.h:94
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:199