Doc: update changelog
[openttd-github.git] / src / help_gui.cpp
blobed7a65b65249dd6b108246d9a0cc8482ed47918e
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 */
8 /** @file help_gui.cpp GUI to access manuals and related. */
10 #include "stdafx.h"
11 #include "gui.h"
12 #include "window_gui.h"
13 #include "textfile_gui.h"
14 #include "fileio_func.h"
15 #include "table/control_codes.h"
16 #include "string_func.h"
17 #include "openttd.h"
18 #include "help_gui.h"
20 #include "widgets/help_widget.h"
21 #include "widgets/misc_widget.h"
23 #include "safeguards.h"
25 static const std::string README_FILENAME = "README.md";
26 static const std::string CHANGELOG_FILENAME = "changelog.md";
27 static const std::string KNOWN_BUGS_FILENAME = "known-bugs.md";
28 static const std::string LICENSE_FILENAME = "COPYING.md";
30 static const std::string WEBSITE_LINK = "https://www.openttd.org/";
31 static const std::string WIKI_LINK = "https://wiki.openttd.org/";
32 static const std::string BUGTRACKER_LINK = "https://bugs.openttd.org/";
33 static const std::string COMMUNITY_LINK = "https://community.openttd.org/";
35 /** Only show the first 20 changelog versions in the textfile viewer. */
36 static constexpr size_t CHANGELOG_VERSIONS_LIMIT = 20;
38 /**
39 * Find the path to the game manual file.
41 * @param filename The filename to find.
42 * @return std::string The path to the filename if found.
44 static std::optional<std::string> FindGameManualFilePath(std::string_view filename)
46 static const Searchpath searchpaths[] = {
47 SP_APPLICATION_BUNDLE_DIR, SP_INSTALLATION_DIR, SP_SHARED_DIR, SP_BINARY_DIR, SP_WORKING_DIR
50 for (Searchpath sp : searchpaths) {
51 auto file_path = FioGetDirectory(sp, BASE_DIR) + filename.data();
52 if (FioCheckFileExists(file_path, NO_DIRECTORY)) return file_path;
55 return {};
58 /** Window class displaying the game manual textfile viewer. */
59 struct GameManualTextfileWindow : public TextfileWindow {
60 GameManualTextfileWindow(std::string_view filename) : TextfileWindow(TFT_GAME_MANUAL)
62 this->ConstructWindow();
64 /* Mark the content of these files as trusted. */
65 this->trusted = true;
67 auto filepath = FindGameManualFilePath(filename);
68 /* The user could, in theory, have moved the file. So just show an empty window if that is the case. */
69 if (!filepath.has_value()) {
70 return;
73 this->filepath = filepath.value();
74 this->LoadTextfile(this->filepath, NO_DIRECTORY);
75 this->OnClick({ 0, 0 }, WID_TF_WRAPTEXT, 1);
78 void SetStringParameters(WidgetID widget) const override
80 if (widget == WID_TF_CAPTION) {
81 SetDParamStr(0, this->filename);
85 void AfterLoadText() override
87 if (this->filename == CHANGELOG_FILENAME) {
88 this->link_anchors.clear();
89 this->AfterLoadChangelog();
91 this->TextfileWindow::AfterLoadText();
94 /**
95 * For changelog files, truncate the file after CHANGELOG_VERSIONS_LIMIT versions.
97 * This is hardcoded and assumes "###" is used to separate versions.
99 void AfterLoadChangelog()
101 uint versions = 0;
103 /* Look for lines beginning with ###, they indicate a release name. */
104 for (size_t line_index = 0; line_index < this->lines.size(); ++line_index) {
105 const Line &line = this->lines[line_index];
106 if (!line.text.starts_with("###")) continue;
108 if (versions >= CHANGELOG_VERSIONS_LIMIT) {
109 this->lines.resize(line_index - 2);
110 break;
113 ++versions;
118 /** Window class displaying the help window. */
119 struct HelpWindow : public Window {
121 HelpWindow(WindowDesc &desc, WindowNumber number) : Window(desc)
123 this->InitNested(number);
125 this->EnableTextfileButton(README_FILENAME, WID_HW_README);
126 this->EnableTextfileButton(CHANGELOG_FILENAME, WID_HW_CHANGELOG);
127 this->EnableTextfileButton(KNOWN_BUGS_FILENAME, WID_HW_KNOWN_BUGS);
128 this->EnableTextfileButton(LICENSE_FILENAME, WID_HW_LICENSE);
131 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
133 switch (widget) {
134 case WID_HW_README:
135 new GameManualTextfileWindow(README_FILENAME);
136 break;
137 case WID_HW_CHANGELOG:
138 new GameManualTextfileWindow(CHANGELOG_FILENAME);
139 break;
140 case WID_HW_KNOWN_BUGS:
141 new GameManualTextfileWindow(KNOWN_BUGS_FILENAME);
142 break;
143 case WID_HW_LICENSE:
144 new GameManualTextfileWindow(LICENSE_FILENAME);
145 break;
146 case WID_HW_WEBSITE:
147 OpenBrowser(WEBSITE_LINK);
148 break;
149 case WID_HW_WIKI:
150 OpenBrowser(WIKI_LINK);
151 break;
152 case WID_HW_BUGTRACKER:
153 OpenBrowser(BUGTRACKER_LINK);
154 break;
155 case WID_HW_COMMUNITY:
156 OpenBrowser(COMMUNITY_LINK);
157 break;
161 private:
162 void EnableTextfileButton(std::string_view filename, WidgetID button_widget)
164 this->GetWidget<NWidgetLeaf>(button_widget)->SetDisabled(!FindGameManualFilePath(filename).has_value());
168 static constexpr NWidgetPart _nested_helpwin_widgets[] = {
169 NWidget(NWID_HORIZONTAL),
170 NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
171 NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_HELP_WINDOW_CAPTION, STR_NULL),
172 EndContainer(),
174 NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
175 NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0), SetPadding(WidgetDimensions::unscaled.sparse),
176 NWidget(WWT_FRAME, COLOUR_DARK_GREEN), SetDataTip(STR_HELP_WINDOW_WEBSITES, STR_NULL),
177 NWidget(WWT_PUSHTXTBTN, COLOUR_GREEN, WID_HW_WEBSITE), SetDataTip(STR_HELP_WINDOW_MAIN_WEBSITE, STR_NULL), SetMinimalSize(128, 12), SetFill(1, 0),
178 NWidget(WWT_PUSHTXTBTN, COLOUR_GREEN, WID_HW_WIKI), SetDataTip(STR_HELP_WINDOW_MANUAL_WIKI, STR_NULL), SetMinimalSize(128, 12), SetFill(1, 0),
179 NWidget(WWT_PUSHTXTBTN, COLOUR_GREEN, WID_HW_BUGTRACKER), SetDataTip(STR_HELP_WINDOW_BUGTRACKER, STR_NULL), SetMinimalSize(128, 12), SetFill(1, 0),
180 NWidget(WWT_PUSHTXTBTN, COLOUR_GREEN, WID_HW_COMMUNITY), SetDataTip(STR_HELP_WINDOW_COMMUNITY, STR_NULL), SetMinimalSize(128, 12), SetFill(1, 0),
181 EndContainer(),
183 NWidget(WWT_FRAME, COLOUR_DARK_GREEN), SetDataTip(STR_HELP_WINDOW_DOCUMENTS, STR_NULL),
184 NWidget(WWT_PUSHTXTBTN, COLOUR_GREEN, WID_HW_README), SetDataTip(STR_HELP_WINDOW_README, STR_NULL), SetMinimalSize(128, 12), SetFill(1, 0),
185 NWidget(WWT_PUSHTXTBTN, COLOUR_GREEN, WID_HW_CHANGELOG), SetDataTip(STR_HELP_WINDOW_CHANGELOG, STR_NULL), SetMinimalSize(128, 12), SetFill(1, 0),
186 NWidget(WWT_PUSHTXTBTN, COLOUR_GREEN, WID_HW_KNOWN_BUGS),SetDataTip(STR_HELP_WINDOW_KNOWN_BUGS, STR_NULL), SetMinimalSize(128, 12), SetFill(1, 0),
187 NWidget(WWT_PUSHTXTBTN, COLOUR_GREEN, WID_HW_LICENSE), SetDataTip(STR_HELP_WINDOW_LICENSE, STR_NULL), SetMinimalSize(128, 12), SetFill(1, 0),
188 EndContainer(),
189 EndContainer(),
190 EndContainer(),
193 static WindowDesc _helpwin_desc(
194 WDP_CENTER, nullptr, 0, 0,
195 WC_HELPWIN, WC_NONE,
197 _nested_helpwin_widgets
200 void ShowHelpWindow()
202 AllocateWindowDescFront<HelpWindow>(_helpwin_desc, 0);