Factor out OnClick dispatching in Window::HandleEditBoxKey
[openttd/fttd.git] / src / bootstrap_gui.cpp
blob4ea56eabb0466a2ce0b23b747c4c5b7f912398b4
1 /* $Id$ */
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 */
10 /** @file bootstrap_gui.cpp Barely used user interface for bootstrapping OpenTTD, i.e. downloading the required content. */
12 #include "stdafx.h"
13 #include "base_media_base.h"
14 #include "blitter/blitter.h"
16 #if defined(ENABLE_NETWORK) && defined(WITH_FREETYPE)
18 #include "core/geometry_func.hpp"
19 #include "font.h"
20 #include "gfx_func.h"
21 #include "network/network.h"
22 #include "network/network_content_gui.h"
23 #include "openttd.h"
24 #include "strings_func.h"
25 #include "video/video_driver.hpp"
26 #include "window_func.h"
28 #include "widgets/bootstrap_widget.h"
30 #include "table/strings.h"
32 /** Widgets for the background window to prevent smearing. */
33 static const struct NWidgetPart _background_widgets[] = {
34 NWidget(WWT_PANEL, COLOUR_DARK_BLUE, WID_BB_BACKGROUND), SetResize(1, 1),
37 /**
38 * Window description for the background window to prevent smearing.
40 static const WindowDesc _background_desc(
41 WDP_MANUAL, 0, 0,
42 WC_BOOTSTRAP, WC_NONE,
44 _background_widgets, lengthof(_background_widgets)
47 /** The background for the game. */
48 class BootstrapBackground : public Window {
49 public:
50 BootstrapBackground() : Window(&_background_desc)
52 this->InitNested(0);
53 CLRBITS(this->flags, WF_WHITE_BORDER);
54 ResizeWindow (this, _screen_width, _screen_height);
57 void DrawWidget (BlitArea *dpi, const Rect &r, int widget) const OVERRIDE
59 GfxFillRect (dpi, r.left, r.top, r.right, r.bottom, 4, FILLRECT_OPAQUE);
60 GfxFillRect (dpi, r.left, r.top, r.right, r.bottom, 0, FILLRECT_CHECKER);
64 /** Nested widgets for the download window. */
65 static const NWidgetPart _nested_boostrap_download_status_window_widgets[] = {
66 NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CONTENT_DOWNLOAD_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
67 NWidget(WWT_PANEL, COLOUR_GREY, WID_NCDS_BACKGROUND),
68 NWidget(NWID_SPACER), SetMinimalSize(350, 0), SetMinimalTextLines(3, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 30),
69 EndContainer(),
72 /** Window description for the download window */
73 static const WindowDesc _bootstrap_download_status_window_desc(
74 WDP_CENTER, 0, 0,
75 WC_NETWORK_STATUS_WINDOW, WC_NONE,
76 WDF_MODAL,
77 _nested_boostrap_download_status_window_widgets, lengthof(_nested_boostrap_download_status_window_widgets)
81 /** Window for showing the download status of content */
82 struct BootstrapContentDownloadStatusWindow : public BaseNetworkContentDownloadStatusWindow {
83 public:
84 /** Simple call the constructor of the superclass. */
85 BootstrapContentDownloadStatusWindow() : BaseNetworkContentDownloadStatusWindow(&_bootstrap_download_status_window_desc)
89 virtual void OnDownloadComplete(ContentID cid)
91 /* We have completed downloading. We can trigger finding the right set now. */
92 BaseGraphics::FindSets();
94 /* And continue going into the menu. */
95 _game_mode = GM_MENU;
97 /* _exit_game is used to break out of the outer video driver's MainLoop. */
98 _exit_game = true;
99 this->Delete();
103 /** The widgets for the query. It has no close box as that sprite does not exist yet. */
104 static const NWidgetPart _bootstrap_query_widgets[] = {
105 NWidget(NWID_HORIZONTAL),
106 NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_MISSING_GRAPHICS_SET_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
107 EndContainer(),
108 NWidget(WWT_PANEL, COLOUR_GREY),
109 NWidget(WWT_PANEL, COLOUR_GREY, WID_BAFD_QUESTION), EndContainer(),
110 NWidget(NWID_HORIZONTAL),
111 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BAFD_YES), SetDataTip(STR_MISSING_GRAPHICS_YES_DOWNLOAD, STR_NULL),
112 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BAFD_NO), SetDataTip(STR_MISSING_GRAPHICS_NO_QUIT, STR_NULL),
113 EndContainer(),
114 EndContainer(),
117 /** The window description for the query. */
118 static const WindowDesc _bootstrap_query_desc(
119 WDP_CENTER, 0, 0,
120 WC_CONFIRM_POPUP_QUERY, WC_NONE,
122 _bootstrap_query_widgets, lengthof(_bootstrap_query_widgets)
125 /** The window for the query. It can't use the generic query window as that uses sprites that don't exist yet. */
126 class BootstrapAskForDownloadWindow : public Window, ContentCallback {
127 Dimension button_size; ///< The dimension of the button
129 public:
130 /** Start listening to the content client events. */
131 BootstrapAskForDownloadWindow()
132 : Window (&_bootstrap_query_desc), button_size()
134 this->button_size.width = 0;
135 this->button_size.height = 0;
136 this->InitNested(WN_CONFIRM_POPUP_QUERY_BOOTSTRAP);
137 _network_content_client.AddCallback(this);
140 /** Stop listening to the content client events. */
141 ~BootstrapAskForDownloadWindow()
143 _network_content_client.RemoveCallback(this);
146 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
148 /* We cache the button size. This is safe as no reinit can happen here. */
149 if (this->button_size.width == 0) {
150 this->button_size = maxdim(GetStringBoundingBox(STR_MISSING_GRAPHICS_YES_DOWNLOAD), GetStringBoundingBox(STR_MISSING_GRAPHICS_NO_QUIT));
151 this->button_size.width += WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT;
152 this->button_size.height += WD_FRAMETEXT_TOP + WD_FRAMETEXT_BOTTOM;
155 switch (widget) {
156 case WID_BAFD_QUESTION:
157 /* The question is twice as wide as the buttons, and determine the height based on the width. */
158 size->width = this->button_size.width * 2;
159 size->height = GetStringHeight(STR_MISSING_GRAPHICS_SET_MESSAGE, size->width - WD_FRAMETEXT_LEFT - WD_FRAMETEXT_RIGHT) + WD_FRAMETEXT_BOTTOM + WD_FRAMETEXT_TOP;
160 break;
162 case WID_BAFD_YES:
163 case WID_BAFD_NO:
164 *size = this->button_size;
165 break;
169 void DrawWidget (BlitArea *dpi, const Rect &r, int widget) const OVERRIDE
171 if (widget != 0) return;
173 DrawStringMultiLine (dpi, r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, r.top + WD_FRAMETEXT_TOP, r.bottom - WD_FRAMETEXT_BOTTOM, STR_MISSING_GRAPHICS_SET_MESSAGE, TC_FROMSTRING, SA_CENTER);
176 virtual void OnClick(Point pt, int widget, int click_count)
178 switch (widget) {
179 case WID_BAFD_YES:
180 /* We got permission to connect! Yay! */
181 _network_content_client.Connect();
182 break;
184 case WID_BAFD_NO:
185 _exit_game = true;
186 break;
188 default:
189 break;
193 virtual void OnConnect(bool success)
195 /* Once connected, request the metadata. */
196 _network_content_client.RequestContentList(CONTENT_TYPE_BASE_GRAPHICS);
199 virtual void OnReceiveContentInfo(const ContentInfo *ci)
201 /* And once the meta data is received, start downloading it. */
202 _network_content_client.Select(ci->id);
203 new BootstrapContentDownloadStatusWindow();
204 this->Delete();
208 #endif /* defined(ENABLE_NETWORK) && defined(WITH_FREETYPE) */
211 * Handle all procedures for bootstrapping OpenTTD without a base graphics set.
212 * This requires all kinds of trickery that is needed to avoid the use of
213 * sprites from the base graphics set which are pretty interwoven.
214 * @return True if a base set exists, otherwise false.
216 bool HandleBootstrap()
218 if (BaseGraphics::GetUsedSet() != NULL) return true;
220 /* No user interface, bail out with an error. */
221 if (Blitter::get()->screen_depth == 0) goto failure;
223 /* If there is no network or no freetype, then there is nothing we can do. Go straight to failure. */
224 #if defined(ENABLE_NETWORK) && defined(WITH_FREETYPE) && (defined(WITH_FONTCONFIG) || defined(WIN32) || defined(__APPLE__))
225 if (!_network_available) goto failure;
227 /* First tell the game we're bootstrapping. */
228 _game_mode = GM_BOOTSTRAP;
230 /* Initialise the freetype font code. */
231 InitializeUnicodeGlyphMap();
232 /* Next "force" finding a suitable freetype font as the local font is missing. */
233 CheckForMissingGlyphs(false);
235 /* Initialise the palette. The biggest step is 'faking' some recolour sprites.
236 * This way the mauve and gray colours work and we can show the user interface. */
237 GfxInitPalettes();
238 static const int offsets[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0x04, 0x08 };
239 for (uint i = 0; i != 16; i++) {
240 for (int j = 0; j < 8; j++) {
241 _colour_gradient[i][j] = offsets[i] + j;
245 /* Finally ask the question. */
246 new BootstrapBackground();
247 new BootstrapAskForDownloadWindow();
249 /* Process the user events. */
250 VideoDriver::GetActiveDriver()->MainLoop();
252 /* _exit_game is used to get out of the video driver's main loop.
253 * In case GM_BOOTSTRAP is still set we did not exit it via the
254 * "download complete" event, so it was a manual exit. Obey it. */
255 _exit_game = _game_mode == GM_BOOTSTRAP;
256 if (_exit_game) return false;
258 /* Try to probe the graphics. Should work this time. */
259 if (!BaseGraphics::SetSet(NULL)) goto failure;
261 /* Finally we can continue heading for the menu. */
262 _game_mode = GM_MENU;
263 return true;
264 #endif
266 /* Failure to get enough working to get a graphics set. */
267 failure:
268 usererror("Failed to find a graphics set. Please acquire a graphics set for OpenTTD. See section 4.1 of readme.txt.");
269 return false;