OpenTTD
network_content_gui.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "../stdafx.h"
13 #include "../strings_func.h"
14 #include "../gfx_func.h"
15 #include "../window_func.h"
16 #include "../error.h"
17 #include "../ai/ai.hpp"
18 #include "../game/game.hpp"
19 #include "../base_media_base.h"
20 #include "../sortlist_type.h"
21 #include "../stringfilter_type.h"
22 #include "../querystring_gui.h"
23 #include "../core/geometry_func.hpp"
24 #include "../textfile_gui.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 
37 static bool _accepted_external_search = false;
38 
39 
42  const ContentInfo *ci;
43 
45  {
46  const char *textfile = this->ci->GetTextfile(file_type);
47  this->LoadTextfile(textfile, GetContentInfoSubDir(this->ci->type));
48  }
49 
50  StringID GetTypeString() const
51  {
52  switch (this->ci->type) {
53  case CONTENT_TYPE_NEWGRF: return STR_CONTENT_TYPE_NEWGRF;
54  case CONTENT_TYPE_BASE_GRAPHICS: return STR_CONTENT_TYPE_BASE_GRAPHICS;
55  case CONTENT_TYPE_BASE_SOUNDS: return STR_CONTENT_TYPE_BASE_SOUNDS;
56  case CONTENT_TYPE_BASE_MUSIC: return STR_CONTENT_TYPE_BASE_MUSIC;
57  case CONTENT_TYPE_AI: return STR_CONTENT_TYPE_AI;
58  case CONTENT_TYPE_AI_LIBRARY: return STR_CONTENT_TYPE_AI_LIBRARY;
59  case CONTENT_TYPE_GAME: return STR_CONTENT_TYPE_GAME_SCRIPT;
60  case CONTENT_TYPE_GAME_LIBRARY: return STR_CONTENT_TYPE_GS_LIBRARY;
61  case CONTENT_TYPE_SCENARIO: return STR_CONTENT_TYPE_SCENARIO;
62  case CONTENT_TYPE_HEIGHTMAP: return STR_CONTENT_TYPE_HEIGHTMAP;
63  default: NOT_REACHED();
64  }
65  }
66 
67  void SetStringParameters(int widget) const override
68  {
69  if (widget == WID_TF_CAPTION) {
70  SetDParam(0, this->GetTypeString());
71  SetDParamStr(1, this->ci->name);
72  }
73  }
74 };
75 
76 void ShowContentTextfileWindow(TextfileType file_type, const ContentInfo *ci)
77 {
80 }
81 
84  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CONTENT_DOWNLOAD_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
85  NWidget(WWT_PANEL, COLOUR_GREY, WID_NCDS_BACKGROUND),
89  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCDS_CANCELOK), SetMinimalSize(101, 12), SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
90  NWidget(NWID_SPACER), SetFill(1, 0),
91  EndContainer(),
93  EndContainer(),
94 };
95 
98  WDP_CENTER, nullptr, 0, 0,
100  WDF_MODAL,
101  _nested_network_content_download_status_window_widgets, lengthof(_nested_network_content_download_status_window_widgets)
102 );
103 
105  Window(desc), cur_id(UINT32_MAX)
106 {
109 
111 }
112 
114 {
116 }
117 
119 {
120  if (widget != WID_NCDS_BACKGROUND) return;
121 
122  /* Draw nice progress bar :) */
123  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);
124 
125  int y = r.top + 20;
126  SetDParam(0, this->downloaded_bytes);
127  SetDParam(1, this->total_bytes);
128  SetDParam(2, this->downloaded_bytes * 100LL / this->total_bytes);
129  DrawString(r.left + 2, r.right - 2, y, STR_CONTENT_DOWNLOAD_PROGRESS_SIZE, TC_FROMSTRING, SA_HOR_CENTER);
130 
131  StringID str;
132  if (this->downloaded_bytes == this->total_bytes) {
133  str = STR_CONTENT_DOWNLOAD_COMPLETE;
134  } else if (!StrEmpty(this->name)) {
135  SetDParamStr(0, this->name);
136  SetDParam(1, this->downloaded_files);
137  SetDParam(2, this->total_files);
138  str = STR_CONTENT_DOWNLOAD_FILE;
139  } else {
140  str = STR_CONTENT_DOWNLOAD_INITIALISE;
141  }
142 
143  y += FONT_HEIGHT_NORMAL + 5;
144  DrawStringMultiLine(r.left + 2, r.right - 2, y, y + FONT_HEIGHT_NORMAL * 2, str, TC_FROMSTRING, SA_CENTER);
145 }
146 
148 {
149  if (ci->id != this->cur_id) {
150  strecpy(this->name, ci->filename, lastof(this->name));
151  this->cur_id = ci->id;
152  this->downloaded_files++;
153  }
154 
155  this->downloaded_bytes += bytes;
156  this->SetDirty();
157 }
158 
159 
162 private:
163  std::vector<ContentType> receivedTypes;
164 
165 public:
170  NetworkContentDownloadStatusWindow() : BaseNetworkContentDownloadStatusWindow(&_network_content_download_status_window_desc)
171  {
173  }
174 
177  {
179  for (auto ctype : this->receivedTypes) {
180  switch (ctype) {
181  case CONTENT_TYPE_AI:
183  /* AI::Rescan calls the scanner. */
184  break;
185  case CONTENT_TYPE_GAME:
187  /* Game::Rescan calls the scanner. */
188  break;
189 
193  mode |= TarScanner::BASESET;
194  break;
195 
196  case CONTENT_TYPE_NEWGRF:
197  /* ScanNewGRFFiles calls the scanner. */
198  break;
199 
202  mode |= TarScanner::SCENARIO;
203  break;
204 
205  default:
206  break;
207  }
208  }
209 
210  TarScanner::DoScan(mode);
211 
212  /* Tell all the backends about what we've downloaded */
213  for (auto ctype : this->receivedTypes) {
214  switch (ctype) {
215  case CONTENT_TYPE_AI:
217  AI::Rescan();
218  break;
219 
220  case CONTENT_TYPE_GAME:
222  Game::Rescan();
223  break;
224 
228  break;
229 
233  break;
234 
238  break;
239 
240  case CONTENT_TYPE_NEWGRF:
241  ScanNewGRFFiles(nullptr);
242  break;
243 
246  extern void ScanScenarios();
247  ScanScenarios();
249  break;
250 
251  default:
252  break;
253  }
254  }
255 
256  /* Always invalidate the download window; tell it we are going to be gone */
258  }
259 
260  void OnClick(Point pt, int widget, int click_count) override
261  {
262  if (widget == WID_NCDS_CANCELOK) {
263  if (this->downloaded_bytes != this->total_bytes) {
265  delete this;
266  } else {
267  /* If downloading succeeded, close the online content window. This will close
268  * the current window as well. */
270  }
271  }
272  }
273 
274  void OnDownloadProgress(const ContentInfo *ci, int bytes) override
275  {
277  include(this->receivedTypes, ci->type);
278 
279  /* When downloading is finished change cancel in ok */
280  if (this->downloaded_bytes == this->total_bytes) {
281  this->GetWidget<NWidgetCore>(WID_NCDS_CANCELOK)->widget_data = STR_BUTTON_OK;
282  }
283  }
284 };
285 
289  std::bitset<CONTENT_TYPE_END> types;
290 };
291 
296 };
297 
302 
303  static const uint EDITBOX_MAX_SIZE = 50;
304 
307  static GUIContentList::SortFunction * const sorter_funcs[];
308  static GUIContentList::FilterFunction * const filter_funcs[];
309  GUIContentList content;
310  bool auto_select;
314 
316  int list_pos;
319 
320  static char content_type_strs[CONTENT_TYPE_END][64];
321 
324  {
325  extern void OpenBrowser(const char *url);
326 
327  char url[1024];
328  const char *last = lastof(url);
329 
330  char *pos = strecpy(url, "http://grfsearch.openttd.org/?", last);
331 
332  if (this->auto_select) {
333  pos = strecpy(pos, "do=searchgrfid&q=", last);
334 
335  bool first = true;
336  for (const ContentInfo *ci : this->content) {
337  if (ci->state != ContentInfo::DOES_NOT_EXIST) continue;
338 
339  if (!first) pos = strecpy(pos, ",", last);
340  first = false;
341 
342  pos += seprintf(pos, last, "%08X", ci->unique_id);
343  pos = strecpy(pos, ":", last);
344  pos = md5sumToString(pos, last, ci->md5sum);
345  }
346  } else {
347  pos = strecpy(pos, "do=searchtext&q=", last);
348 
349  /* Escape search term */
350  for (const char *search = this->filter_editbox.text.buf; *search != '\0'; search++) {
351  /* Remove quotes */
352  if (*search == '\'' || *search == '"') continue;
353 
354  /* Escape special chars, such as &%,= */
355  if (*search < 0x30) {
356  pos += seprintf(pos, last, "%%%02X", *search);
357  } else if (pos < last) {
358  *pos = *search;
359  *++pos = '\0';
360  }
361  }
362  }
363 
364  OpenBrowser(url);
365  }
366 
370  static void ExternalSearchDisclaimerCallback(Window *w, bool accepted)
371  {
372  if (accepted) {
374  ((NetworkContentListWindow*)w)->OpenExternalSearch();
375  }
376  }
377 
383  {
384  if (!this->content.NeedRebuild()) return;
385 
386  /* Create temporary array of games to use for listing */
387  this->content.clear();
388 
389  bool all_available = true;
390 
392  if ((*iter)->state == ContentInfo::DOES_NOT_EXIST) all_available = false;
393  this->content.push_back(*iter);
394  }
395 
396  this->SetWidgetDisabledState(WID_NCL_SEARCH_EXTERNAL, this->auto_select && all_available);
397 
398  this->FilterContentList();
399  this->content.shrink_to_fit();
400  this->content.RebuildDone();
401  this->SortContentList();
402 
403  this->vscroll->SetCount((int)this->content.size()); // Update the scrollbar
404  this->ScrollToSelected();
405  }
406 
408  static bool NameSorter(const ContentInfo * const &a, const ContentInfo * const &b)
409  {
410  return strnatcmp(a->name, b->name, true) < 0; // Sort by name (natural sorting).
411  }
412 
414  static bool TypeSorter(const ContentInfo * const &a, const ContentInfo * const &b)
415  {
416  int r = 0;
417  if (a->type != b->type) {
418  r = strnatcmp(content_type_strs[a->type], content_type_strs[b->type]);
419  }
420  if (r == 0) return NameSorter(a, b);
421  return r < 0;
422  }
423 
425  static bool StateSorter(const ContentInfo * const &a, const ContentInfo * const &b)
426  {
427  int r = a->state - b->state;
428  if (r == 0) return TypeSorter(a, b);
429  return r < 0;
430  }
431 
434  {
435  if (!this->content.Sort()) return;
436 
437  int idx = find_index(this->content, this->selected);
438  if (idx >= 0) this->list_pos = idx;
439  }
440 
442  static bool CDECL TagNameFilter(const ContentInfo * const *a, ContentListFilterData &filter)
443  {
444  filter.string_filter.ResetState();
445  for (int i = 0; i < (*a)->tag_count; i++) {
446  filter.string_filter.AddLine((*a)->tags[i]);
447  }
448  filter.string_filter.AddLine((*a)->name);
449  return filter.string_filter.GetState();
450  }
451 
453  static bool CDECL TypeOrSelectedFilter(const ContentInfo * const *a, ContentListFilterData &filter)
454  {
455  if (filter.types.none()) return true;
456  if (filter.types[(*a)->type]) return true;
457  return ((*a)->state == ContentInfo::SELECTED || (*a)->state == ContentInfo::AUTOSELECTED);
458  }
459 
462  {
463  /* Apply filters. */
464  bool changed = false;
465  if (!this->filter_data.string_filter.IsEmpty()) {
466  this->content.SetFilterType(CONTENT_FILTER_TEXT);
467  changed |= this->content.Filter(this->filter_data);
468  }
469  if (this->filter_data.types.any()) {
471  changed |= this->content.Filter(this->filter_data);
472  }
473  if (!changed) return;
474 
475  /* update list position */
476  int idx = find_index(this->content, this->selected);
477  if (idx >= 0) {
478  this->list_pos = idx;
479  return;
480  }
481 
482  /* previously selected item not in list anymore */
483  this->selected = nullptr;
484  this->list_pos = 0;
485  }
486 
492  {
493  Filtering old_params = this->content.GetFiltering();
494  bool new_state = !this->filter_data.string_filter.IsEmpty() || this->filter_data.types.any();
495  if (new_state != old_params.state) {
496  this->content.SetFilterState(new_state);
497  }
498  return new_state != old_params.state;
499  }
500 
503  {
504  if (this->selected == nullptr) return;
505 
506  this->vscroll->ScrollTowards(this->list_pos);
507  }
508 
509  friend void BuildContentTypeStringList();
510 public:
520  NetworkContentListWindow(WindowDesc *desc, bool select_all, const std::bitset<CONTENT_TYPE_END> &types) :
521  Window(desc),
522  auto_select(select_all),
523  filter_editbox(EDITBOX_MAX_SIZE),
524  selected(nullptr),
525  list_pos(0)
526  {
527  this->checkbox_size = maxdim(maxdim(GetSpriteSize(SPR_BOX_EMPTY), GetSpriteSize(SPR_BOX_CHECKED)), GetSpriteSize(SPR_BLOT));
528 
529  this->CreateNestedTree();
530  this->vscroll = this->GetScrollbar(WID_NCL_SCROLLBAR);
532 
533  this->GetWidget<NWidgetStacked>(WID_NCL_SEL_ALL_UPDATE)->SetDisplayedPlane(select_all);
534 
535  this->querystrings[WID_NCL_FILTER] = &this->filter_editbox;
536  this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
538  this->SetWidgetDisabledState(WID_NCL_SEARCH_EXTERNAL, this->auto_select);
539  this->filter_data.types = types;
540 
542  this->content.SetListing(this->last_sorting);
543  this->content.SetFiltering(this->last_filtering);
544  this->content.SetSortFuncs(this->sorter_funcs);
545  this->content.SetFilterFuncs(this->filter_funcs);
546  this->UpdateFilterState();
547  this->content.ForceRebuild();
548  this->FilterContentList();
549  this->SortContentList();
550  this->InvalidateData();
551  }
552 
555  {
557  }
558 
559  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
560  {
561  switch (widget) {
562  case WID_NCL_FILTER_CAPT:
563  *size = maxdim(*size, GetStringBoundingBox(STR_CONTENT_FILTER_TITLE));
564  break;
565 
566  case WID_NCL_CHECKBOX:
567  size->width = this->checkbox_size.width + WD_MATRIX_RIGHT + WD_MATRIX_LEFT;
568  break;
569 
570  case WID_NCL_TYPE: {
571  Dimension d = *size;
572  for (int i = CONTENT_TYPE_BEGIN; i < CONTENT_TYPE_END; i++) {
573  d = maxdim(d, GetStringBoundingBox(STR_CONTENT_TYPE_BASE_GRAPHICS + i - CONTENT_TYPE_BASE_GRAPHICS));
574  }
575  size->width = d.width + WD_MATRIX_RIGHT + WD_MATRIX_LEFT;
576  break;
577  }
578 
579  case WID_NCL_MATRIX:
580  resize->height = max(this->checkbox_size.height, (uint)FONT_HEIGHT_NORMAL) + WD_MATRIX_TOP + WD_MATRIX_BOTTOM;
581  size->height = 10 * resize->height;
582  break;
583  }
584  }
585 
586 
587  void DrawWidget(const Rect &r, int widget) const override
588  {
589  switch (widget) {
590  case WID_NCL_FILTER_CAPT:
591  DrawString(r.left, r.right, r.top, STR_CONTENT_FILTER_TITLE, TC_FROMSTRING, SA_RIGHT);
592  break;
593 
594  case WID_NCL_DETAILS:
595  this->DrawDetails(r);
596  break;
597 
598  case WID_NCL_MATRIX:
599  this->DrawMatrix(r);
600  break;
601  }
602  }
603 
604  void OnPaint() override
605  {
606  const SortButtonState arrow = this->content.IsDescSortOrder() ? SBS_DOWN : SBS_UP;
607 
608  if (this->content.NeedRebuild()) {
609  this->BuildContentList();
610  }
611 
612  this->DrawWidgets();
613 
614  switch (this->content.SortType()) {
616  case WID_NCL_TYPE - WID_NCL_CHECKBOX: this->DrawSortButtonState(WID_NCL_TYPE, arrow); break;
617  case WID_NCL_NAME - WID_NCL_CHECKBOX: this->DrawSortButtonState(WID_NCL_NAME, arrow); break;
618  }
619  }
620 
625  void DrawMatrix(const Rect &r) const
626  {
627  const NWidgetBase *nwi_checkbox = this->GetWidget<NWidgetBase>(WID_NCL_CHECKBOX);
628  const NWidgetBase *nwi_name = this->GetWidget<NWidgetBase>(WID_NCL_NAME);
629  const NWidgetBase *nwi_type = this->GetWidget<NWidgetBase>(WID_NCL_TYPE);
630 
631  int line_height = max(this->checkbox_size.height, (uint)FONT_HEIGHT_NORMAL);
632 
633  /* Fill the matrix with the information */
634  int sprite_y_offset = WD_MATRIX_TOP + (line_height - this->checkbox_size.height) / 2 - 1;
635  int text_y_offset = WD_MATRIX_TOP + (line_height - FONT_HEIGHT_NORMAL) / 2;
636  uint y = r.top;
637 
638  auto iter = this->content.begin() + this->vscroll->GetPosition();
639  size_t last = this->vscroll->GetPosition() + this->vscroll->GetCapacity();
640  auto end = (last < this->content.size()) ? this->content.begin() + last : this->content.end();
641 
642  for (; iter != end; iter++) {
643  const ContentInfo *ci = *iter;
644 
645  if (ci == this->selected) GfxFillRect(r.left + 1, y + 1, r.right - 1, y + this->resize.step_height - 1, PC_GREY);
646 
647  SpriteID sprite;
648  SpriteID pal = PAL_NONE;
649  switch (ci->state) {
650  case ContentInfo::UNSELECTED: sprite = SPR_BOX_EMPTY; break;
651  case ContentInfo::SELECTED: sprite = SPR_BOX_CHECKED; break;
652  case ContentInfo::AUTOSELECTED: sprite = SPR_BOX_CHECKED; break;
653  case ContentInfo::ALREADY_HERE: sprite = SPR_BLOT; pal = PALETTE_TO_GREEN; break;
654  case ContentInfo::DOES_NOT_EXIST: sprite = SPR_BLOT; pal = PALETTE_TO_RED; break;
655  default: NOT_REACHED();
656  }
657  DrawSprite(sprite, pal, nwi_checkbox->pos_x + (pal == PAL_NONE ? 2 : 3), y + sprite_y_offset + (pal == PAL_NONE ? 1 : 0));
658 
659  StringID str = STR_CONTENT_TYPE_BASE_GRAPHICS + ci->type - CONTENT_TYPE_BASE_GRAPHICS;
660  DrawString(nwi_type->pos_x, nwi_type->pos_x + nwi_type->current_x - 1, y + text_y_offset, str, TC_BLACK, SA_HOR_CENTER);
661 
662  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);
663  y += this->resize.step_height;
664  }
665  }
666 
671  void DrawDetails(const Rect &r) const
672  {
673  static const int DETAIL_LEFT = 5;
674  static const int DETAIL_RIGHT = 5;
675  static const int DETAIL_TOP = 5;
676 
677  /* Height for the title banner */
678  int DETAIL_TITLE_HEIGHT = 5 * FONT_HEIGHT_NORMAL;
679 
680  /* Create the nice grayish rectangle at the details top */
681  GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.top + DETAIL_TITLE_HEIGHT, PC_DARK_BLUE);
682  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);
683 
684  /* Draw the total download size */
685  SetDParam(0, this->filesize_sum);
686  DrawString(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, r.bottom - FONT_HEIGHT_NORMAL - WD_PAR_VSEP_NORMAL, STR_CONTENT_TOTAL_DOWNLOAD_SIZE);
687 
688  if (this->selected == nullptr) return;
689 
690  /* And fill the rest of the details when there's information to place there */
691  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);
692 
693  /* Also show the total download size, so keep some space from the bottom */
694  const uint max_y = r.bottom - FONT_HEIGHT_NORMAL - WD_PAR_VSEP_WIDE;
695  int y = r.top + DETAIL_TITLE_HEIGHT + DETAIL_TOP;
696 
697  if (this->selected->upgrade) {
698  SetDParam(0, STR_CONTENT_TYPE_BASE_GRAPHICS + this->selected->type - CONTENT_TYPE_BASE_GRAPHICS);
699  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_UPDATE);
700  y += WD_PAR_VSEP_WIDE;
701  }
702 
703  SetDParamStr(0, this->selected->name);
704  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_NAME);
705 
706  if (!StrEmpty(this->selected->version)) {
707  SetDParamStr(0, this->selected->version);
708  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_VERSION);
709  }
710 
711  if (!StrEmpty(this->selected->description)) {
712  SetDParamStr(0, this->selected->description);
713  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_DESCRIPTION);
714  }
715 
716  if (!StrEmpty(this->selected->url)) {
717  SetDParamStr(0, this->selected->url);
718  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_URL);
719  }
720 
721  SetDParam(0, STR_CONTENT_TYPE_BASE_GRAPHICS + this->selected->type - CONTENT_TYPE_BASE_GRAPHICS);
722  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_TYPE);
723 
724  y += WD_PAR_VSEP_WIDE;
725  SetDParam(0, this->selected->filesize);
726  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_FILESIZE);
727 
728  if (this->selected->dependency_count != 0) {
729  /* List dependencies */
730  char buf[DRAW_STRING_BUFFER] = "";
731  char *p = buf;
732  for (uint i = 0; i < this->selected->dependency_count; i++) {
733  ContentID cid = this->selected->dependencies[i];
734 
735  /* Try to find the dependency */
737  for (; iter != _network_content_client.End(); iter++) {
738  const ContentInfo *ci = *iter;
739  if (ci->id != cid) continue;
740 
741  p += seprintf(p, lastof(buf), p == buf ? "%s" : ", %s", (*iter)->name);
742  break;
743  }
744  }
745  SetDParamStr(0, buf);
746  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_DEPENDENCIES);
747  }
748 
749  if (this->selected->tag_count != 0) {
750  /* List all tags */
751  char buf[DRAW_STRING_BUFFER] = "";
752  char *p = buf;
753  for (uint i = 0; i < this->selected->tag_count; i++) {
754  p += seprintf(p, lastof(buf), i == 0 ? "%s" : ", %s", this->selected->tags[i]);
755  }
756  SetDParamStr(0, buf);
757  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_TAGS);
758  }
759 
760  if (this->selected->IsSelected()) {
761  /* When selected show all manually selected content that depends on this */
762  ConstContentVector tree;
764 
765  char buf[DRAW_STRING_BUFFER] = "";
766  char *p = buf;
767  for (const ContentInfo *ci : tree) {
768  if (ci == this->selected || ci->state != ContentInfo::SELECTED) continue;
769 
770  p += seprintf(p, lastof(buf), buf == p ? "%s" : ", %s", ci->name);
771  }
772  if (p != buf) {
773  SetDParamStr(0, buf);
774  y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_SELECTED_BECAUSE_OF);
775  }
776  }
777  }
778 
779  void OnClick(Point pt, int widget, int click_count) override
780  {
781  if (widget >= WID_NCL_TEXTFILE && widget < WID_NCL_TEXTFILE + TFT_END) {
782  if (this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE) return;
783 
784  ShowContentTextfileWindow((TextfileType)(widget - WID_NCL_TEXTFILE), this->selected);
785  return;
786  }
787 
788  switch (widget) {
789  case WID_NCL_MATRIX: {
790  uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NCL_MATRIX);
791  if (id_v >= this->content.size()) return; // click out of bounds
792 
793  this->selected = this->content[id_v];
794  this->list_pos = id_v;
795 
796  const NWidgetBase *checkbox = this->GetWidget<NWidgetBase>(WID_NCL_CHECKBOX);
797  if (click_count > 1 || IsInsideBS(pt.x, checkbox->pos_x, checkbox->current_x)) {
799  this->content.ForceResort();
800  }
801 
802  if (this->filter_data.types.any()) {
803  this->content.ForceRebuild();
804  }
805 
806  this->InvalidateData();
807  break;
808  }
809 
810  case WID_NCL_CHECKBOX:
811  case WID_NCL_TYPE:
812  case WID_NCL_NAME:
813  if (this->content.SortType() == widget - WID_NCL_CHECKBOX) {
814  this->content.ToggleSortOrder();
815  if (this->content.size() > 0) this->list_pos = (int)this->content.size() - this->list_pos - 1;
816  } else {
817  this->content.SetSortType(widget - WID_NCL_CHECKBOX);
818  this->content.ForceResort();
819  this->SortContentList();
820  }
821  this->ScrollToSelected();
822  this->InvalidateData();
823  break;
824 
825  case WID_NCL_SELECT_ALL:
827  this->InvalidateData();
828  break;
829 
832  this->InvalidateData();
833  break;
834 
835  case WID_NCL_UNSELECT:
837  this->InvalidateData();
838  break;
839 
840  case WID_NCL_CANCEL:
841  delete this;
842  break;
843 
844  case WID_NCL_OPEN_URL:
845  if (this->selected != nullptr) {
846  extern void OpenBrowser(const char *url);
847  OpenBrowser(this->selected->url);
848  }
849  break;
850 
851  case WID_NCL_DOWNLOAD:
853  break;
854 
857  this->OpenExternalSearch();
858  } else {
859  ShowQuery(STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER_CAPTION, STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER, this, ExternalSearchDisclaimerCallback);
860  }
861  break;
862  }
863  }
864 
865  EventState OnKeyPress(WChar key, uint16 keycode) override
866  {
867  switch (keycode) {
868  case WKC_UP:
869  /* scroll up by one */
870  if (this->list_pos > 0) this->list_pos--;
871  break;
872  case WKC_DOWN:
873  /* scroll down by one */
874  if (this->list_pos < (int)this->content.size() - 1) this->list_pos++;
875  break;
876  case WKC_PAGEUP:
877  /* scroll up a page */
878  this->list_pos = (this->list_pos < this->vscroll->GetCapacity()) ? 0 : this->list_pos - this->vscroll->GetCapacity();
879  break;
880  case WKC_PAGEDOWN:
881  /* scroll down a page */
882  this->list_pos = min(this->list_pos + this->vscroll->GetCapacity(), (int)this->content.size() - 1);
883  break;
884  case WKC_HOME:
885  /* jump to beginning */
886  this->list_pos = 0;
887  break;
888  case WKC_END:
889  /* jump to end */
890  this->list_pos = (int)this->content.size() - 1;
891  break;
892 
893  case WKC_SPACE:
894  case WKC_RETURN:
895  if (keycode == WKC_RETURN || !IsWidgetFocused(WID_NCL_FILTER)) {
896  if (this->selected != nullptr) {
898  this->content.ForceResort();
899  this->InvalidateData();
900  }
901  if (this->filter_data.types.any()) {
902  this->content.ForceRebuild();
903  this->InvalidateData();
904  }
905  return ES_HANDLED;
906  }
907  /* space is pressed and filter is focused. */
908  FALLTHROUGH;
909 
910  default:
911  return ES_NOT_HANDLED;
912  }
913 
914  if (this->content.size() == 0) {
915  this->list_pos = 0; // above stuff may result in "-1".
916  if (this->UpdateFilterState()) {
917  this->content.ForceRebuild();
918  this->InvalidateData();
919  }
920  return ES_HANDLED;
921  }
922 
923  this->selected = this->content[this->list_pos];
924 
925  if (this->UpdateFilterState()) {
926  this->content.ForceRebuild();
927  } else {
928  /* Scroll to the new content if it is outside the current range. */
929  this->ScrollToSelected();
930  }
931 
932  /* redraw window */
933  this->InvalidateData();
934  return ES_HANDLED;
935  }
936 
937  void OnEditboxChanged(int wid) override
938  {
939  if (wid == WID_NCL_FILTER) {
940  this->filter_data.string_filter.SetFilterTerm(this->filter_editbox.text.buf);
941  this->UpdateFilterState();
942  this->content.ForceRebuild();
943  this->InvalidateData();
944  }
945  }
946 
947  void OnResize() override
948  {
949  this->vscroll->SetCapacityFromWidget(this, WID_NCL_MATRIX);
950  }
951 
952  void OnReceiveContentInfo(const ContentInfo *rci) override
953  {
954  if (this->auto_select && !rci->IsSelected()) _network_content_client.ToggleSelectedState(rci);
955  this->content.ForceRebuild();
956  this->InvalidateData();
957  }
958 
959  void OnDownloadComplete(ContentID cid) override
960  {
961  this->content.ForceResort();
962  this->InvalidateData();
963  }
964 
965  void OnConnect(bool success) override
966  {
967  if (!success) {
968  ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_CONNECT, INVALID_STRING_ID, WL_ERROR);
969  delete this;
970  return;
971  }
972 
973  this->InvalidateData();
974  }
975 
981  void OnInvalidateData(int data = 0, bool gui_scope = true) override
982  {
983  if (!gui_scope) return;
984  if (this->content.NeedRebuild()) this->BuildContentList();
985 
986  /* To sum all the bytes we intend to download */
987  this->filesize_sum = 0;
988  bool show_select_all = false;
989  bool show_select_upgrade = false;
990  for (const ContentInfo *ci : this->content) {
991  switch (ci->state) {
994  this->filesize_sum += ci->filesize;
995  break;
996 
998  show_select_all = true;
999  show_select_upgrade |= ci->upgrade;
1000  break;
1001 
1002  default:
1003  break;
1004  }
1005  }
1006 
1007  /* If data == 2 then the status window caused this OnInvalidate */
1009  this->SetWidgetDisabledState(WID_NCL_UNSELECT, this->filesize_sum == 0);
1010  this->SetWidgetDisabledState(WID_NCL_SELECT_ALL, !show_select_all);
1011  this->SetWidgetDisabledState(WID_NCL_SELECT_UPDATE, !show_select_upgrade);
1012  this->SetWidgetDisabledState(WID_NCL_OPEN_URL, this->selected == nullptr || StrEmpty(this->selected->url));
1013  for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
1014  this->SetWidgetDisabledState(WID_NCL_TEXTFILE + tft, this->selected == nullptr || this->selected->state != ContentInfo::ALREADY_HERE || this->selected->GetTextfile(tft) == nullptr);
1015  }
1016 
1017  this->GetWidget<NWidgetCore>(WID_NCL_CANCEL)->widget_data = this->filesize_sum == 0 ? STR_AI_SETTINGS_CLOSE : STR_AI_LIST_CANCEL;
1018  }
1019 };
1020 
1023 
1025  &StateSorter,
1026  &TypeSorter,
1027  &NameSorter,
1028 };
1029 
1031  &TagNameFilter,
1032  &TypeOrSelectedFilter,
1033 };
1034 
1036 
1041 {
1042  for (int i = CONTENT_TYPE_BEGIN; i < CONTENT_TYPE_END; i++) {
1044  }
1045 }
1046 
1050  NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
1051  NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_CONTENT_TITLE, STR_NULL),
1052  NWidget(WWT_DEFSIZEBOX, COLOUR_LIGHT_BLUE),
1053  EndContainer(),
1054  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_BACKGROUND),
1057  /* Top */
1058  NWidget(WWT_EMPTY, COLOUR_LIGHT_BLUE, WID_NCL_FILTER_CAPT), SetFill(1, 0), SetResize(1, 0),
1059  NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NCL_FILTER), SetFill(1, 0), SetResize(1, 0),
1060  SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
1061  EndContainer(),
1064  /* Left side. */
1065  NWidget(NWID_VERTICAL), SetPIP(0, 4, 0),
1069  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_CHECKBOX), SetMinimalSize(13, 1), SetDataTip(STR_EMPTY, STR_NULL),
1070  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TYPE),
1071  SetDataTip(STR_CONTENT_TYPE_CAPTION, STR_CONTENT_TYPE_CAPTION_TOOLTIP),
1072  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_NAME), SetResize(1, 0), SetFill(1, 0),
1073  SetDataTip(STR_CONTENT_NAME_CAPTION, STR_CONTENT_NAME_CAPTION_TOOLTIP),
1074  EndContainer(),
1075  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),
1076  EndContainer(),
1077  NWidget(NWID_VSCROLLBAR, COLOUR_LIGHT_BLUE, WID_NCL_SCROLLBAR),
1078  EndContainer(),
1080  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NCL_SEL_ALL_UPDATE), SetResize(1, 0), SetFill(1, 0),
1081  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SELECT_UPDATE), SetResize(1, 0), SetFill(1, 0),
1082  SetDataTip(STR_CONTENT_SELECT_UPDATES_CAPTION, STR_CONTENT_SELECT_UPDATES_CAPTION_TOOLTIP),
1083  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SELECT_ALL), SetResize(1, 0), SetFill(1, 0),
1084  SetDataTip(STR_CONTENT_SELECT_ALL_CAPTION, STR_CONTENT_SELECT_ALL_CAPTION_TOOLTIP),
1085  EndContainer(),
1086  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_UNSELECT), SetResize(1, 0), SetFill(1, 0),
1087  SetDataTip(STR_CONTENT_UNSELECT_ALL_CAPTION, STR_CONTENT_UNSELECT_ALL_CAPTION_TOOLTIP),
1088  EndContainer(),
1089  EndContainer(),
1090  /* Right side. */
1091  NWidget(NWID_VERTICAL), SetPIP(0, 4, 0),
1092  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NCL_DETAILS), SetResize(1, 1), SetFill(1, 1), EndContainer(),
1094  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
1095  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
1096  EndContainer(),
1098  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),
1099  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
1100  EndContainer(),
1101  EndContainer(),
1102  EndContainer(),
1104  /* Bottom. */
1106  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_SEARCH_EXTERNAL), SetResize(1, 0), SetFill(1, 0),
1107  SetDataTip(STR_CONTENT_SEARCH_EXTERNAL, STR_CONTENT_SEARCH_EXTERNAL_TOOLTIP),
1109  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_CANCEL), SetResize(1, 0), SetFill(1, 0),
1110  SetDataTip(STR_BUTTON_CANCEL, STR_NULL),
1111  NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NCL_DOWNLOAD), SetResize(1, 0), SetFill(1, 0),
1112  SetDataTip(STR_CONTENT_DOWNLOAD_CAPTION, STR_CONTENT_DOWNLOAD_CAPTION_TOOLTIP),
1113  EndContainer(),
1114  EndContainer(),
1116  /* Resize button. */
1118  NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1119  NWidget(WWT_RESIZEBOX, COLOUR_LIGHT_BLUE),
1120  EndContainer(),
1121  EndContainer(),
1122 };
1123 
1126  WDP_CENTER, "list_content", 630, 460,
1128  0,
1129  _nested_network_content_list_widgets, lengthof(_nested_network_content_list_widgets)
1130 );
1131 
1140 {
1141 #if defined(WITH_ZLIB)
1142  std::bitset<CONTENT_TYPE_END> types;
1144  if (cv == nullptr) {
1145  assert(type1 != CONTENT_TYPE_END || type2 == CONTENT_TYPE_END);
1146  assert(type1 == CONTENT_TYPE_END || type1 != type2);
1149 
1150  if (type1 != CONTENT_TYPE_END) types[type1] = true;
1151  if (type2 != CONTENT_TYPE_END) types[type2] = true;
1152  } else {
1154  }
1155 
1157  new NetworkContentListWindow(&_network_content_list_desc, cv != nullptr, types);
1158 #else
1159  ShowErrorMessage(STR_CONTENT_NO_ZLIB, STR_CONTENT_NO_ZLIB_SUB, WL_ERROR);
1160  /* Connection failed... clean up the mess */
1161  if (cv != nullptr) {
1162  for (ContentInfo *ci : *cv) delete ci;
1163  }
1164 #endif /* WITH_ZLIB */
1165 }
EventState
State of handling an event.
Definition: window_type.h:713
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:35
Empty widget, place holder to reserve space in widget array.
Definition: widget_type.h:48
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:25
Panel with content details.
bool IsSelected() const
Is the state either selected or autoselected?
Definition: tcp_content.cpp:75
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:70
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:97
ResizeInfo resize
Resize information.
Definition: window_gui.h:324
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:100
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:731
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:930
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:75
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:112
void SetWidgetDisabledState(byte widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition: window_gui.h:394
Offset at right of a matrix cell.
Definition: window_gui.h:79
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3199
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
Window * parent
Parent window.
Definition: window_gui.h:339
const ContentInfo * selected
The selected content info.
High level window description.
Definition: window_gui.h:168
Saveload window; Window numbers:
Definition: window_type.h:139
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:604
static uint FindSets()
Do the scan for files.
Scrollbar data structure.
Definition: widget_type.h:589
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
Definition: string.cpp:409
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:278
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:64
Dimension checkbox_size
Size of checkbox/"blot" sprite.
Normal amount of vertical space between two paragraphs of text.
Definition: window_gui.h:139
textfile; Window numbers:
Definition: window_type.h:182
Horizontal container.
Definition: widget_type.h:75
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1114
void ResetState()
Reset the matching state to process a new item.
The passed event is not handled.
Definition: window_type.h:715
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:69
The content consists of a scenario.
Definition: tcp_content.h:29
uint8 dependency_count
Number of dependencies.
Definition: tcp_content.h:77
&#39;Name&#39; button.
char(* tags)[32]
Malloced array of tags (strings)
Definition: tcp_content.h:80
char * md5sumToString(char *buf, const char *last, const uint8 md5sum[16])
Convert the md5sum to a hexadecimal string representation.
Definition: string.cpp:427
a textbox for typing
Definition: widget_type.h:71
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:68
void SetFilterType(uint8 n_type)
Set the filtertype of the list.
static const int ACTION_CLEAR
Clear editbox.
NewGRF changelog.
Definition: textfile_type.h:20
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:382
GUIContentList content
List with content.
ContentID * dependencies
Malloced array of dependencies (unique server side ids)
Definition: tcp_content.h:78
Close box (at top-left of a window)
Definition: widget_type.h:69
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:85
Offset at top of a matrix cell.
Definition: window_gui.h:80
ContentListFilterData filter_data
Filter for content list.
Scrollbar of matrix.
The content has been selected as dependency.
Definition: tcp_content.h:61
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:965
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:50
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:19
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
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:51
void OnEditboxChanged(int wid) override
The text in an editbox has been edited.
The content has not been selected.
Definition: tcp_content.h:59
void CreateNestedTree(bool fill_nested=true)
Perform the first part of the initialization of a nested widget tree.
Definition: window.cpp:1812
void SetListing(Listing l)
Import sort conditions.
Large amount of vertical space between two paragraphs of text.
Definition: window_gui.h:140
Data structure describing what to show in the list (filter criteria).
Definition: sortlist_type.h:38
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:250
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition: widget.cpp:177
void SetCount(int num)
Sets the number of elements in the list.
Definition: widget_type.h:670
The content does not exist in the content system.
Definition: tcp_content.h:63
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:910
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:21
Data structure for an opened window.
Definition: window_gui.h:278
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:1828
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:1032
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:1841
&#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:281
~NetworkContentDownloadStatusWindow()
Free whatever we&#39;ve allocated.
char name[32]
Name of the content.
Definition: tcp_content.h:71
The content consists of a game script.
Definition: tcp_content.h:33
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:79
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:81
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX) ...
Definition: widget_type.h:65
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:1959
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:79
char version[16]
Version of the content.
Definition: tcp_content.h:72
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:1262
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
Sort descending.
Definition: window_gui.h:227
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:330
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:178
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1014
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:947
Left offset of string.
Definition: window_gui.h:46
Center both horizontally and vertically.
Definition: gfx_func.h:106
The content is already at the client side.
Definition: tcp_content.h:62
ContentID id
Unique (server side) ID for the content.
Definition: tcp_content.h:68
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:104
Simple depressed panel.
Definition: widget_type.h:50
&#39;Unselect all&#39; button.
bool state
Filter on/off.
Definition: sortlist_type.h:39
void ScanScenarios()
Force a (re)scan of the scenarios.
Definition: fios.cpp:771
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:103
void DrawSortButtonState(int widget, SortButtonState state) const
Draw a sort button&#39;s up or down arrow symbol.
Definition: widget.cpp:638
uint step_height
Step-size of height resize changes.
Definition: window_gui.h:220
const Scrollbar * GetScrollbar(uint widnum) const
Return the Scrollbar to a widget index.
Definition: window.cpp:311
int pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:177
Offset at left of a matrix cell.
Definition: window_gui.h:78
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:81
Background of the window.
Center the window.
Definition: window_gui.h:157
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:224
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:1114
Offset at bottom to draw the frame rectangular area.
Definition: window_gui.h:65
Baseclass for nested widgets.
Definition: widget_type.h:126
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:499
const ContentInfo * ci
View the textfile of this ContentInfo.
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
TextfileType
Additional text files accompanying Tar archives.
Definition: textfile_type.h:16
Grid of rows and columns.
Definition: widget_type.h:59
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
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:18
&#39;Type&#39; button.
byte md5sum[16]
The MD5 checksum.
Definition: tcp_content.h:76
uint total_bytes
Number of bytes to download.
The content consists of a GS library.
Definition: tcp_content.h:34
&#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:211
uint DoScan(Subdirectory sd)
Perform the scanning of a particular subdirectory.
Definition: fileio.cpp:610
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition: window.cpp:968
The content consists of a NewGRF.
Definition: tcp_content.h:26
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:698
ContentType
The values in the enum are important; they are used as database &#39;keys&#39;.
Definition: tcp_content.h:23
Network status window; Window numbers:
Definition: window_type.h:487
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:40
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1146
NWID_SELECTION widget for select all/update buttons..
static const uint8 PC_GREY
Grey palette colour.
Definition: gfx_func.h:207
static const uint8 PC_DARK_BLUE
Dark blue palette colour.
Definition: gfx_func.h:224
The content consists of an AI library.
Definition: tcp_content.h:28
Mode
The mode of tar scanning.
Definition: fileio_func.h:98
User interface for downloading files.
char *const buf
buffer in which text is saved
Definition: textbuf_type.h:34
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:61
Window for displaying a textfile.
Definition: textfile_gui.h:23
int strnatcmp(const char *s1, const char *s2, bool ignore_garbage_at_front)
Compares two strings using case insensitive natural sort.
Definition: string.cpp:580
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:19
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:59
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:30
The content consists of an AI.
Definition: tcp_content.h:27
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:67
bool upgrade
This item is an upgrade.
Definition: tcp_content.h:82
bool CDECL FilterFunction(const T *, F)
Signature of filter function.
Definition: sortlist_type.h:52
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:226
&#39;Open url&#39; button.
Button above checkboxes.
TextfileType file_type
Type of textfile to view.
Definition: textfile_gui.h:24
static void Rescan()
Rescans all searchpaths for available AIs.
Definition: ai_core.cpp:352
Vertical container.
Definition: widget_type.h:77
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:999
Network window; Window numbers:
Definition: window_type.h:468
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: depend.cpp:68
static GUIContentList::FilterFunction *const filter_funcs[]
Filter functions.
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:174
Helper to mark the begin of the types.
Definition: tcp_content.h:24
The content consists of base music.
Definition: tcp_content.h:32
Right offset of string.
Definition: window_gui.h:47
bool SetFocusedWidget(int widget_index)
Set focus within this window to the given widget.
Definition: window.cpp:488
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:767
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:33
uint16 GetCapacity() const
Gets the number of visible elements of the scrollbar.
Definition: widget_type.h:622
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:19
The content has been manually selected.
Definition: tcp_content.h:60
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:63
void SetFiltering(Filtering f)
Import filter conditions.
The caption of the window.
Definition: misc_widget.h:51
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:983
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:31
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:1973
Specification of a rectangle with absolute coordinates of all edges.
Vertical scrollbar.
Definition: widget_type.h:84
void OnConnect(bool success) override
Callback for when the connection has finished.
The passed event is handled.
Definition: window_type.h:714
Right align the text (must be a single bit).
Definition: gfx_func.h:98
BaseNetworkContentDownloadStatusWindow(WindowDesc *desc)
Create the window with the given description.
Scan nothing.
Definition: fileio_func.h:99
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:80
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:51
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:73
Errors (eg. saving/loading failed)
Definition: error.h:25
GUIList< const ContentInfo *, ContentListFilterData & > GUIContentList
List with content infos.
uint32 WChar
Type for wide characters, i.e.
Definition: string_type.h:37
char description[512]
Description of the content.
Definition: tcp_content.h:74
bool IsWidgetFocused(byte widget_index) const
Check if given widget is focused within this window.
Definition: window_gui.h:434
static NWidgetPart SetScrollbar(int index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1095
Dimensions (a width and height) of a rectangle in 2D.
Container for all important information about a piece of content.
Definition: tcp_content.h:56
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:429
bool IsEmpty() const
Check whether any filter words were entered.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:62
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:1243
Game options window; Window numbers:
Definition: window_type.h:608
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:832
static NWidgetPart SetPIP(uint8 pre, uint8 inter, uint8 post)
Widget part function for setting a pre/inter/post spaces.
Definition: widget_type.h:1076
Network content download status.
Definition: window_type.h:35
~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:3240
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:3300
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:620
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:31
Top offset of string.
Definition: window_gui.h:48
uint16 GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:631
uint8 SortType() const
Get the sorttype of the list.
Definition: sortlist_type.h:96
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:201