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;