Mercurial > hg > openttd
comparison src/newgrf_gui.cpp @ 19078:8cb1275f2bb3 draft
(svn r23932) -Codechange: split the NewGRF text window into its own source files
author | rubidium <rubidium@openttd.org> |
---|---|
date | Sun, 12 Feb 2012 10:32:41 +0000 |
parents | f7df1757f6d9 |
children | 0af594336a81 |
comparison
equal
deleted
inserted
replaced
19077:400747be7966 | 19078:8cb1275f2bb3 |
---|---|
23 #include "network/network_content.h" | 23 #include "network/network_content.h" |
24 #include "sortlist_type.h" | 24 #include "sortlist_type.h" |
25 #include "querystring_gui.h" | 25 #include "querystring_gui.h" |
26 #include "core/geometry_func.hpp" | 26 #include "core/geometry_func.hpp" |
27 #include "newgrf_text.h" | 27 #include "newgrf_text.h" |
28 #include "fileio_func.h" | 28 #include "textfile_gui.h" |
29 #include "fontcache.h" | |
30 | 29 |
31 #include "widgets/newgrf_widget.h" | 30 #include "widgets/newgrf_widget.h" |
31 #include "widgets/misc_widget.h" | |
32 | 32 |
33 #include "table/sprites.h" | 33 #include "table/sprites.h" |
34 | 34 |
35 /** | 35 /** |
36 * Show the first NewGRF error we can find. | 36 * Show the first NewGRF error we can find. |
463 DeleteWindowByClass(WC_GRF_PARAMETERS); | 463 DeleteWindowByClass(WC_GRF_PARAMETERS); |
464 new NewGRFParametersWindow(&_newgrf_parameters_desc, c, editable); | 464 new NewGRFParametersWindow(&_newgrf_parameters_desc, c, editable); |
465 } | 465 } |
466 | 466 |
467 /** Window for displaying the textfile of a NewGRF. */ | 467 /** Window for displaying the textfile of a NewGRF. */ |
468 struct NewGRFTextfileWindow : public Window, MissingGlyphSearcher { | 468 struct NewGRFTextfileWindow : public TextfileWindow { |
469 const GRFConfig *grf_config; ///< View the textfile of this GRFConfig. | 469 const GRFConfig *grf_config; ///< View the textfile of this GRFConfig. |
470 TextfileType file_type; ///< Type of textfile to view. | 470 |
471 int line_height; ///< Height of a line in the display widget. | 471 NewGRFTextfileWindow(TextfileType file_type, const GRFConfig *c) : TextfileWindow(file_type), grf_config(c) |
472 Scrollbar *vscroll; ///< Vertical scrollbar. | 472 { |
473 Scrollbar *hscroll; ///< Horizontal scrollbar. | 473 this->GetWidget<NWidgetCore>(WID_TF_CAPTION)->SetDataTip(STR_NEWGRF_README_CAPTION + file_type, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS); |
474 char *text; ///< Lines of text from the NewGRF's textfile. | 474 |
475 SmallVector<const char *, 64> lines; ///< #text, split into lines in a table with lines. | |
476 uint max_length; ///< The longest line in the textfile (in pixels). | |
477 | |
478 static const int TOP_SPACING = WD_FRAMETEXT_TOP; ///< Additional spacing at the top of the #WID_NT_BACKGROUND widget. | |
479 static const int BOTTOM_SPACING = WD_FRAMETEXT_BOTTOM; ///< Additional spacing at the bottom of the #WID_NT_BACKGROUND widget. | |
480 | |
481 NewGRFTextfileWindow(const WindowDesc *desc, const GRFConfig *c, TextfileType file_type) : Window(), grf_config(c), file_type(file_type) | |
482 { | |
483 this->CreateNestedTree(desc); | |
484 this->GetWidget<NWidgetCore>(WID_NT_CAPTION)->SetDataTip(STR_NEWGRF_README_CAPTION + file_type, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS); | |
485 this->vscroll = this->GetScrollbar(WID_NT_VSCROLLBAR); | |
486 this->hscroll = this->GetScrollbar(WID_NT_HSCROLLBAR); | |
487 this->FinishInitNested(desc); | |
488 | |
489 this->LoadTextfile(); | |
490 } | |
491 | |
492 ~NewGRFTextfileWindow() | |
493 { | |
494 free(this->text); | |
495 } | |
496 | |
497 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) | |
498 { | |
499 switch (widget) { | |
500 case WID_NT_BACKGROUND: | |
501 this->line_height = FONT_HEIGHT_MONO + 2; | |
502 resize->height = this->line_height; | |
503 | |
504 size->height = 4 * resize->height + TOP_SPACING + BOTTOM_SPACING; // At least 4 lines are visible. | |
505 size->width = max(200u, size->width); // At least 200 pixels wide. | |
506 break; | |
507 } | |
508 } | |
509 | |
510 virtual void SetStringParameters(int widget) const | |
511 { | |
512 if (widget == WID_NT_CAPTION) SetDParamStr(0, this->grf_config->GetName()); | |
513 } | |
514 | |
515 virtual void DrawWidget(const Rect &r, int widget) const | |
516 { | |
517 if (widget != WID_NT_BACKGROUND) return; | |
518 | |
519 int width = r.right - r.left + 1 - WD_BEVEL_LEFT - WD_BEVEL_RIGHT; | |
520 int height = r.bottom - r.top + 1 - WD_BEVEL_LEFT - WD_BEVEL_RIGHT; | |
521 | |
522 DrawPixelInfo new_dpi; | |
523 if (!FillDrawPixelInfo(&new_dpi, r.left + WD_BEVEL_LEFT, r.top, width, height)) return; | |
524 DrawPixelInfo *old_dpi = _cur_dpi; | |
525 _cur_dpi = &new_dpi; | |
526 | |
527 int left, right; | |
528 if (_current_text_dir == TD_RTL) { | |
529 left = width + WD_BEVEL_RIGHT - WD_FRAMETEXT_RIGHT - this->hscroll->GetCount(); | |
530 right = width + WD_BEVEL_RIGHT - WD_FRAMETEXT_RIGHT - 1 + this->hscroll->GetPosition(); | |
531 } else { | |
532 left = WD_FRAMETEXT_LEFT - WD_BEVEL_LEFT - this->hscroll->GetPosition(); | |
533 right = WD_FRAMETEXT_LEFT - WD_BEVEL_LEFT + this->hscroll->GetCount() - 1; | |
534 } | |
535 int top = TOP_SPACING; | |
536 for (uint i = 0; i < this->vscroll->GetCapacity() && i + this->vscroll->GetPosition() < this->lines.Length(); i++) { | |
537 DrawString(left, right, top + i * this->line_height, this->lines[i + this->vscroll->GetPosition()], TC_WHITE, SA_LEFT, false, FS_MONO); | |
538 } | |
539 | |
540 _cur_dpi = old_dpi; | |
541 } | |
542 | |
543 virtual void OnResize() | |
544 { | |
545 this->vscroll->SetCapacityFromWidget(this, WID_NT_BACKGROUND, TOP_SPACING + BOTTOM_SPACING); | |
546 this->hscroll->SetCapacityFromWidget(this, WID_NT_BACKGROUND); | |
547 } | |
548 | |
549 private: | |
550 uint search_iterator; ///< Iterator for the font check search. | |
551 | |
552 /* virtual */ void Reset() | |
553 { | |
554 this->search_iterator = 0; | |
555 } | |
556 | |
557 FontSize DefaultSize() | |
558 { | |
559 return FS_MONO; | |
560 } | |
561 | |
562 const char *NextString() | |
563 { | |
564 if (this->search_iterator >= this->lines.Length()) return NULL; | |
565 | |
566 return this->lines[this->search_iterator++]; | |
567 } | |
568 | |
569 /* virtual */ bool Monospace() | |
570 { | |
571 return true; | |
572 } | |
573 | |
574 /* virtual */ void SetFontNames(FreeTypeSettings *settings, const char *font_name) | |
575 { | |
576 #ifdef WITH_FREETYPE | |
577 strecpy(settings->mono_font, font_name, lastof(settings->mono_font)); | |
578 #endif /* WITH_FREETYPE */ | |
579 } | |
580 | |
581 /** | |
582 * Load the NewGRF's textfile text from file, and setup #lines, #max_length, and both scrollbars. | |
583 */ | |
584 void LoadTextfile() | |
585 { | |
586 this->lines.Clear(); | |
587 | |
588 /* Does GRF have a file of the demanded type? */ | |
589 const char *textfile = this->grf_config->GetTextfile(file_type); | 475 const char *textfile = this->grf_config->GetTextfile(file_type); |
590 if (textfile == NULL) return; | 476 this->LoadTextfile(textfile, NEWGRF_DIR); |
591 | 477 } |
592 /* Get text from file */ | 478 |
593 size_t filesize; | 479 /* virtual */ void SetStringParameters(int widget) const |
594 FILE *handle = FioFOpenFile(textfile, "rb", NEWGRF_DIR, &filesize); | 480 { |
595 if (handle == NULL) return; | 481 if (widget == WID_TF_CAPTION) SetDParamStr(0, this->grf_config->GetName()); |
596 | |
597 this->text = ReallocT(this->text, filesize + 1); | |
598 size_t read = fread(this->text, 1, filesize, handle); | |
599 fclose(handle); | |
600 | |
601 if (read != filesize) return; | |
602 | |
603 this->text[filesize] = '\0'; | |
604 | |
605 /* Replace tabs and line feeds with a space since str_validate removes those. */ | |
606 for (char *p = this->text; *p != '\0'; p++) { | |
607 if (*p == '\t' || *p == '\r') *p = ' '; | |
608 } | |
609 | |
610 /* Check for the byte-order-mark, and skip it if needed. */ | |
611 char *p = this->text + (strncmp("\xEF\xBB\xBF", this->text, 3) == 0 ? 3 : 0); | |
612 | |
613 /* Make sure the string is a valid UTF-8 sequence. */ | |
614 str_validate(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE); | |
615 | |
616 /* Split the string on newlines. */ | |
617 *this->lines.Append() = p; | |
618 for (; *p != '\0'; p++) { | |
619 if (*p == '\n') { | |
620 *p = '\0'; | |
621 *this->lines.Append() = p + 1; | |
622 } | |
623 } | |
624 | |
625 CheckForMissingGlyphs(true, this); | |
626 | |
627 /* Initialize scrollbars */ | |
628 this->vscroll->SetCount(this->lines.Length()); | |
629 | |
630 this->max_length = 0; | |
631 for (uint i = 0; i < this->lines.Length(); i++) { | |
632 this->max_length = max(this->max_length, GetStringBoundingBox(this->lines[i], FS_MONO).width); | |
633 } | |
634 this->hscroll->SetCount(this->max_length + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT); | |
635 this->hscroll->SetStepSize(10); // Speed up horizontal scrollbar | |
636 } | 482 } |
637 }; | 483 }; |
638 | 484 |
639 static const NWidgetPart _nested_newgrf_textfile_widgets[] = { | 485 void ShowNewGRFTextfileWindow(TextfileType file_type, const GRFConfig *c) |
640 NWidget(NWID_HORIZONTAL), | |
641 NWidget(WWT_CLOSEBOX, COLOUR_MAUVE), | |
642 NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_NT_CAPTION), SetDataTip(STR_NULL, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), | |
643 EndContainer(), | |
644 NWidget(NWID_HORIZONTAL), | |
645 NWidget(WWT_PANEL, COLOUR_MAUVE, WID_NT_BACKGROUND), SetMinimalSize(200, 125), SetResize(1, 12), SetScrollbar(WID_NT_VSCROLLBAR), | |
646 EndContainer(), | |
647 NWidget(NWID_VERTICAL), | |
648 NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_NT_VSCROLLBAR), | |
649 EndContainer(), | |
650 EndContainer(), | |
651 NWidget(NWID_HORIZONTAL), | |
652 NWidget(NWID_HSCROLLBAR, COLOUR_MAUVE, WID_NT_HSCROLLBAR), | |
653 NWidget(WWT_RESIZEBOX, COLOUR_MAUVE), | |
654 EndContainer(), | |
655 }; | |
656 | |
657 /** Window definition for the grf textfile window */ | |
658 static const WindowDesc _newgrf_textfile_desc( | |
659 WDP_CENTER, 630, 460, | |
660 WC_NEWGRF_TEXTFILE, WC_NONE, | |
661 WDF_UNCLICK_BUTTONS, | |
662 _nested_newgrf_textfile_widgets, lengthof(_nested_newgrf_textfile_widgets) | |
663 ); | |
664 | |
665 void ShowNewGRFTextfileWindow(const GRFConfig *c, TextfileType file_type) | |
666 { | 486 { |
667 DeleteWindowByClass(WC_NEWGRF_TEXTFILE); | 487 DeleteWindowByClass(WC_TEXTFILE); |
668 new NewGRFTextfileWindow(&_newgrf_textfile_desc, c, file_type); | 488 new NewGRFTextfileWindow(file_type, c); |
669 } | 489 } |
670 | 490 |
671 static GRFPresetList _grf_preset_list; | 491 static GRFPresetList _grf_preset_list; |
672 | 492 |
673 class DropDownListPresetItem : public DropDownListItem { | 493 class DropDownListPresetItem : public DropDownListItem { |
754 } | 574 } |
755 | 575 |
756 ~NewGRFWindow() | 576 ~NewGRFWindow() |
757 { | 577 { |
758 DeleteWindowByClass(WC_GRF_PARAMETERS); | 578 DeleteWindowByClass(WC_GRF_PARAMETERS); |
759 DeleteWindowByClass(WC_NEWGRF_TEXTFILE); | 579 DeleteWindowByClass(WC_TEXTFILE); |
760 | 580 |
761 if (this->editable && !this->execute) { | 581 if (this->editable && !this->execute) { |
762 CopyGRFConfigList(this->orig_list, this->actives, true); | 582 CopyGRFConfigList(this->orig_list, this->actives, true); |
763 ResetGRFConfig(false); | 583 ResetGRFConfig(false); |
764 ReloadNewGRFData(); | 584 ReloadNewGRFData(); |
960 virtual void OnClick(Point pt, int widget, int click_count) | 780 virtual void OnClick(Point pt, int widget, int click_count) |
961 { | 781 { |
962 if (widget >= WID_NS_NEWGRF_TEXTFILE && widget < WID_NS_NEWGRF_TEXTFILE + TFT_END) { | 782 if (widget >= WID_NS_NEWGRF_TEXTFILE && widget < WID_NS_NEWGRF_TEXTFILE + TFT_END) { |
963 if (this->active_sel == NULL && this->avail_sel == NULL) return; | 783 if (this->active_sel == NULL && this->avail_sel == NULL) return; |
964 | 784 |
965 ShowNewGRFTextfileWindow(this->active_sel != NULL ? this->active_sel : this->avail_sel, (TextfileType)(widget - WID_NS_NEWGRF_TEXTFILE)); | 785 ShowNewGRFTextfileWindow((TextfileType)(widget - WID_NS_NEWGRF_TEXTFILE), this->active_sel != NULL ? this->active_sel : this->avail_sel); |
966 return; | 786 return; |
967 } | 787 } |
968 | 788 |
969 switch (widget) { | 789 switch (widget) { |
970 case WID_NS_PRESET_LIST: { | 790 case WID_NS_PRESET_LIST: { |
1183 virtual void OnNewGRFsScanned() | 1003 virtual void OnNewGRFsScanned() |
1184 { | 1004 { |
1185 this->avail_sel = NULL; | 1005 this->avail_sel = NULL; |
1186 this->avail_pos = -1; | 1006 this->avail_pos = -1; |
1187 this->avails.ForceRebuild(); | 1007 this->avails.ForceRebuild(); |
1188 this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window | 1008 this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window |
1189 this->DeleteChildWindows(WC_NEWGRF_TEXTFILE); // Remove the view textfile window | 1009 this->DeleteChildWindows(WC_TEXTFILE); // Remove the view textfile window |
1190 } | 1010 } |
1191 | 1011 |
1192 virtual void OnDropdownSelect(int widget, int index) | 1012 virtual void OnDropdownSelect(int widget, int index) |
1193 { | 1013 { |
1194 if (!this->editable) return; | 1014 if (!this->editable) return; |