Remove ZeroedMemoryAllocator as a base class of Window
[openttd/fttd.git] / src / toolbar_gui.cpp
blobbb47bd1940496db51086ad037423fe8bc43dc092
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 toolbar_gui.cpp Code related to the (main) toolbar. */
12 #include "stdafx.h"
13 #include "gui.h"
14 #include "window_gui.h"
15 #include "window_func.h"
16 #include "viewport_func.h"
17 #include "command_func.h"
18 #include "vehicle_gui.h"
19 #include "rail_gui.h"
20 #include "road_gui.h"
21 #include "date_func.h"
22 #include "vehicle_func.h"
23 #include "sound_func.h"
24 #include "terraform_gui.h"
25 #include "strings_func.h"
26 #include "company_func.h"
27 #include "company_gui.h"
28 #include "vehicle_base.h"
29 #include "cheat_func.h"
30 #include "transparency_gui.h"
31 #include "screenshot.h"
32 #include "signs_func.h"
33 #include "fios.h"
34 #include "console_gui.h"
35 #include "news_gui.h"
36 #include "ai/ai_gui.hpp"
37 #include "tilehighlight_func.h"
38 #include "smallmap_gui.h"
39 #include "graph_gui.h"
40 #include "textbuf_gui.h"
41 #include "linkgraph/linkgraph_gui.h"
42 #include "newgrf_debug.h"
43 #include "hotkeys.h"
44 #include "engine_base.h"
45 #include "highscore.h"
46 #include "game/game.hpp"
47 #include "goal_base.h"
48 #include "story_base.h"
49 #include "toolbar_gui.h"
51 #include "widgets/toolbar_widget.h"
53 #include "network/network.h"
54 #include "network/network_gui.h"
55 #include "network/network_func.h"
58 /** Width of the toolbar, shared by statusbar. */
59 uint _toolbar_width = 0;
61 RailType _last_built_railtype;
62 RoadType _last_built_roadtype;
64 static ScreenshotType _confirmed_screenshot_type; ///< Screenshot type the current query is about to confirm.
66 /** Toobar modes */
67 enum ToolbarMode {
68 TB_NORMAL,
69 TB_UPPER,
70 TB_LOWER
73 /** Callback functions. */
74 enum CallBackFunction {
75 CBF_NONE,
76 CBF_PLACE_SIGN,
77 CBF_PLACE_LANDINFO,
80 /**
81 * Drop down list entry for showing a checked/unchecked toggle item.
83 class DropDownListCheckedItem : public DropDownListStringItem {
84 uint checkmark_width;
85 public:
86 bool checked;
88 DropDownListCheckedItem(StringID string, int result, bool masked, bool checked) : DropDownListStringItem(string, result, masked), checked(checked)
90 this->checkmark_width = GetStringBoundingBox(STR_JUST_CHECKMARK).width + 3;
93 virtual ~DropDownListCheckedItem() {}
95 uint Width() const
97 return DropDownListStringItem::Width() + this->checkmark_width;
100 void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
102 bool rtl = _current_text_dir == TD_RTL;
103 if (this->checked) {
104 DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, STR_JUST_CHECKMARK, sel ? TC_WHITE : TC_BLACK);
106 DrawString(left + WD_FRAMERECT_LEFT + (rtl ? 0 : this->checkmark_width), right - WD_FRAMERECT_RIGHT - (rtl ? this->checkmark_width : 0), top, this->String(), sel ? TC_WHITE : TC_BLACK);
111 * Drop down list entry for showing a company entry, with companies 'blob'.
113 class DropDownListCompanyItem : public DropDownListItem {
114 Dimension icon_size;
115 public:
116 bool greyed;
118 DropDownListCompanyItem(int result, bool masked, bool greyed) : DropDownListItem(result, masked), greyed(greyed)
120 this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
123 virtual ~DropDownListCompanyItem() {}
125 bool Selectable() const
127 return true;
130 uint Width() const
132 CompanyID company = (CompanyID)this->result;
133 SetDParam(0, company);
134 SetDParam(1, company);
135 return GetStringBoundingBox(STR_COMPANY_NAME_COMPANY_NUM).width + this->icon_size.width + 3;
138 uint Height(uint width) const
140 return max(this->icon_size.height + 2U, (uint)FONT_HEIGHT_NORMAL);
143 void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
145 CompanyID company = (CompanyID)this->result;
146 bool rtl = _current_text_dir == TD_RTL;
148 /* It's possible the company is deleted while the dropdown is open */
149 if (!Company::IsValidID(company)) return;
151 int icon_offset = (bottom - top - icon_size.height) / 2;
152 int text_offset = (bottom - top - FONT_HEIGHT_NORMAL) / 2;
154 DrawCompanyIcon(company, rtl ? right - this->icon_size.width - WD_FRAMERECT_RIGHT : left + WD_FRAMERECT_LEFT, top + icon_offset);
156 SetDParam(0, company);
157 SetDParam(1, company);
158 TextColour col;
159 if (this->greyed) {
160 col = (sel ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
161 } else {
162 col = sel ? TC_WHITE : TC_BLACK;
164 DrawString(left + WD_FRAMERECT_LEFT + (rtl ? 0 : 3 + this->icon_size.width), right - WD_FRAMERECT_RIGHT - (rtl ? 3 + this->icon_size.width : 0), top + text_offset, STR_COMPANY_NAME_COMPANY_NUM, col);
169 * Pop up a generic text only menu.
170 * @param w Toolbar
171 * @param widget Toolbar button
172 * @param list List of items
173 * @param def Default item
175 static void PopupMainToolbMenu(Window *w, int widget, DropDownList *list, int def)
177 ShowDropDownList(w, list, def, widget, 0, true, true);
178 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
182 * Pop up a generic text only menu.
183 * @param w Toolbar
184 * @param widget Toolbar button
185 * @param string String for the first item in the menu
186 * @param count Number of items in the menu
188 static void PopupMainToolbMenu(Window *w, int widget, StringID string, int count)
190 DropDownList *list = new DropDownList();
191 for (int i = 0; i < count; i++) {
192 *list->Append() = new DropDownListStringItem(string + i, i, false);
194 PopupMainToolbMenu(w, widget, list, 0);
197 /** Enum for the Company Toolbar's network related buttons */
198 static const int CTMN_CLIENT_LIST = -1; ///< Show the client list
199 static const int CTMN_NEW_COMPANY = -2; ///< Create a new company
200 static const int CTMN_SPECTATE = -3; ///< Become spectator
201 static const int CTMN_SPECTATOR = -4; ///< Show a company window as spectator
204 * Pop up a generic company list menu.
205 * @param w The toolbar window.
206 * @param widget The button widget id.
207 * @param grey A bitbask of which items to mark as disabled.
208 * @param include_spectator If true, a spectator option is included in the list.
210 static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0, bool include_spectator = false)
212 DropDownList *list = new DropDownList();
214 #ifdef ENABLE_NETWORK
215 if (_networking) {
216 if (widget == WID_TN_COMPANIES) {
217 /* Add the client list button for the companies menu */
218 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false);
221 if (include_spectator) {
222 if (widget == WID_TN_COMPANIES) {
223 if (_local_company == COMPANY_SPECTATOR) {
224 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached());
225 } else {
226 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, NetworkMaxSpectatorsReached());
228 } else {
229 *list->Append() = new DropDownListStringItem(STR_NETWORK_TOOLBAR_LIST_SPECTATOR, CTMN_SPECTATOR, false);
233 #endif /* ENABLE_NETWORK */
235 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
236 if (!Company::IsValidID(c)) continue;
237 *list->Append() = new DropDownListCompanyItem(c, false, HasBit(grey, c));
240 PopupMainToolbMenu(w, widget, list, _local_company == COMPANY_SPECTATOR ? CTMN_CLIENT_LIST : (int)_local_company);
244 static ToolbarMode _toolbar_mode;
246 static CallBackFunction SelectSignTool()
248 if (_cursor.sprite == SPR_CURSOR_SIGN) {
249 ResetPointerMode();
250 return CBF_NONE;
251 } else {
252 SetPointerMode (POINTER_TILE, WC_MAIN_TOOLBAR, 0, SPR_CURSOR_SIGN);
253 return CBF_PLACE_SIGN;
257 /* --- Pausing --- */
259 static CallBackFunction ToolbarPauseClick(Window *w)
261 if (_networking && !_network_server) return CBF_NONE; // only server can pause the game
263 if (DoCommandP(0, PM_PAUSED_NORMAL, _pause_mode == PM_UNPAUSED, CMD_PAUSE)) {
264 if (_settings_client.sound.confirm) SndPlayFx(SND_15_BEEP);
266 return CBF_NONE;
270 * Toggle fast forward mode.
272 * @param w Unused.
273 * @return #CBF_NONE
275 static CallBackFunction ToolbarFastForwardClick(Window *w)
277 _fast_forward ^= true;
278 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
279 return CBF_NONE;
283 * Game Option button menu entries.
285 enum OptionMenuEntries {
286 OME_GAMEOPTIONS,
287 OME_SETTINGS,
288 OME_SCRIPT_SETTINGS,
289 OME_NEWGRFSETTINGS,
290 OME_TRANSPARENCIES,
291 OME_SHOW_TOWNNAMES,
292 OME_SHOW_STATIONNAMES,
293 OME_SHOW_WAYPOINTNAMES,
294 OME_SHOW_SIGNS,
295 OME_SHOW_COMPETITOR_SIGNS,
296 OME_FULL_ANIMATION,
297 OME_FULL_DETAILS,
298 OME_TRANSPARENTBUILDINGS,
299 OME_SHOW_STATIONSIGNS,
303 * Handle click on Options button in toolbar.
305 * @param w parent window the shown Drop down list is attached to.
306 * @return #CBF_NONE
308 static CallBackFunction ToolbarOptionsClick(Window *w)
310 DropDownList *list = new DropDownList();
311 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS, OME_GAMEOPTIONS, false);
312 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE, OME_SETTINGS, false);
313 /* Changes to the per-AI settings don't get send from the server to the clients. Clients get
314 * the settings once they join but never update it. As such don't show the window at all
315 * to network clients. */
316 if (!_networking || _network_server) *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS, OME_SCRIPT_SETTINGS, false);
317 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS, OME_NEWGRFSETTINGS, false);
318 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS, OME_TRANSPARENCIES, false);
319 *list->Append() = new DropDownListItem(-1, false);
320 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED, OME_SHOW_TOWNNAMES, false, HasBit(_display_opt, DO_SHOW_TOWN_NAMES));
321 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED, OME_SHOW_STATIONNAMES, false, HasBit(_display_opt, DO_SHOW_STATION_NAMES));
322 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED, OME_SHOW_WAYPOINTNAMES, false, HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES));
323 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED, OME_SHOW_SIGNS, false, HasBit(_display_opt, DO_SHOW_SIGNS));
324 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS, OME_SHOW_COMPETITOR_SIGNS, false, HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS));
325 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION, OME_FULL_ANIMATION, false, HasBit(_display_opt, DO_FULL_ANIMATION));
326 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL, OME_FULL_DETAILS, false, HasBit(_display_opt, DO_FULL_DETAIL));
327 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS, OME_TRANSPARENTBUILDINGS, false, IsTransparencySet(TO_HOUSES));
328 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS, OME_SHOW_STATIONSIGNS, false, IsTransparencySet(TO_SIGNS));
330 ShowDropDownList(w, list, 0, WID_TN_SETTINGS, 140, true, true);
331 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
332 return CBF_NONE;
336 * Handle click on one of the entries in the Options button menu.
338 * @param index Index being clicked.
339 * @return #CBF_NONE
341 static CallBackFunction MenuClickSettings(int index)
343 switch (index) {
344 case OME_GAMEOPTIONS: ShowGameOptions(); return CBF_NONE;
345 case OME_SETTINGS: ShowGameSettings(); return CBF_NONE;
346 case OME_SCRIPT_SETTINGS: ShowAIConfigWindow(); return CBF_NONE;
347 case OME_NEWGRFSETTINGS: ShowNewGRFSettings(!_networking && _settings_client.gui.UserIsAllowedToChangeNewGRFs(), true, true, &_grfconfig); return CBF_NONE;
348 case OME_TRANSPARENCIES: ShowTransparencyToolbar(); break;
350 case OME_SHOW_TOWNNAMES: ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES); break;
351 case OME_SHOW_STATIONNAMES: ToggleBit(_display_opt, DO_SHOW_STATION_NAMES); break;
352 case OME_SHOW_WAYPOINTNAMES: ToggleBit(_display_opt, DO_SHOW_WAYPOINT_NAMES); break;
353 case OME_SHOW_SIGNS: ToggleBit(_display_opt, DO_SHOW_SIGNS); break;
354 case OME_SHOW_COMPETITOR_SIGNS:
355 ToggleBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS);
356 InvalidateWindowClassesData(WC_SIGN_LIST, -1);
357 break;
358 case OME_FULL_ANIMATION: ToggleBit(_display_opt, DO_FULL_ANIMATION); CheckBlitter(); break;
359 case OME_FULL_DETAILS: ToggleBit(_display_opt, DO_FULL_DETAIL); break;
360 case OME_TRANSPARENTBUILDINGS: ToggleTransparency(TO_HOUSES); break;
361 case OME_SHOW_STATIONSIGNS: ToggleTransparency(TO_SIGNS); break;
363 MarkWholeScreenDirty();
364 return CBF_NONE;
368 * SaveLoad entries in scenario editor mode.
370 enum SaveLoadEditorMenuEntries {
371 SLEME_SAVE_SCENARIO = 0,
372 SLEME_LOAD_SCENARIO,
373 SLEME_SAVE_HEIGHTMAP,
374 SLEME_LOAD_HEIGHTMAP,
375 SLEME_EXIT_TOINTRO,
376 SLEME_EXIT_GAME = 6,
377 SLEME_MENUCOUNT,
381 * SaveLoad entries in normal game mode.
383 enum SaveLoadNormalMenuEntries {
384 SLNME_SAVE_GAME = 0,
385 SLNME_LOAD_GAME,
386 SLNME_EXIT_TOINTRO,
387 SLNME_EXIT_GAME = 4,
388 SLNME_MENUCOUNT,
392 * Handle click on Save button in toolbar in normal game mode.
394 * @param w parent window the shown save dialogue is attached to.
395 * @return #CBF_NONE
397 static CallBackFunction ToolbarSaveClick(Window *w)
399 PopupMainToolbMenu(w, WID_TN_SAVE, STR_FILE_MENU_SAVE_GAME, SLNME_MENUCOUNT);
400 return CBF_NONE;
404 * Handle click on SaveLoad button in toolbar in the scenario editor.
406 * @param w parent window the shown save dialogue is attached to.
407 * @return #CBF_NONE
409 static CallBackFunction ToolbarScenSaveOrLoad(Window *w)
411 PopupMainToolbMenu(w, WID_TE_SAVE, STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO, SLEME_MENUCOUNT);
412 return CBF_NONE;
416 * Handle click on one of the entries in the SaveLoad menu.
418 * @param index Index being clicked.
419 * @return #CBF_NONE
421 static CallBackFunction MenuClickSaveLoad(int index = 0)
423 if (_game_mode == GM_EDITOR) {
424 switch (index) {
425 case SLEME_SAVE_SCENARIO: ShowSaveLoadDialog(SLD_SAVE_SCENARIO); break;
426 case SLEME_LOAD_SCENARIO: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
427 case SLEME_SAVE_HEIGHTMAP: ShowSaveLoadDialog(SLD_SAVE_HEIGHTMAP); break;
428 case SLEME_LOAD_HEIGHTMAP: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break;
429 case SLEME_EXIT_TOINTRO: AskExitToGameMenu(); break;
430 case SLEME_EXIT_GAME: HandleExitGameRequest(); break;
432 } else {
433 switch (index) {
434 case SLNME_SAVE_GAME: ShowSaveLoadDialog(SLD_SAVE_GAME); break;
435 case SLNME_LOAD_GAME: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
436 case SLNME_EXIT_TOINTRO: AskExitToGameMenu(); break;
437 case SLNME_EXIT_GAME: HandleExitGameRequest(); break;
440 return CBF_NONE;
443 /* --- Map button menu --- */
445 enum MapMenuEntries {
446 MME_SHOW_SMALLMAP = 0,
447 MME_SHOW_EXTRAVIEWPORTS,
448 MME_SHOW_LINKGRAPH,
449 MME_SHOW_SIGNLISTS,
450 MME_SHOW_TOWNDIRECTORY,
451 MME_SHOW_INDUSTRYDIRECTORY,
454 static CallBackFunction ToolbarMapClick(Window *w)
456 DropDownList *list = new DropDownList();
457 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false);
458 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false);
459 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_LINGRAPH_LEGEND, MME_SHOW_LINKGRAPH, false);
460 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false);
461 PopupMainToolbMenu(w, WID_TN_SMALL_MAP, list, 0);
462 return CBF_NONE;
465 static CallBackFunction ToolbarScenMapTownDir(Window *w)
467 DropDownList *list = new DropDownList();
468 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false);
469 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false);
470 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false);
471 *list->Append() = new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY, MME_SHOW_TOWNDIRECTORY, false);
472 *list->Append() = new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, MME_SHOW_INDUSTRYDIRECTORY, false);
473 PopupMainToolbMenu(w, WID_TE_SMALL_MAP, list, 0);
474 return CBF_NONE;
478 * Handle click on one of the entries in the Map menu.
480 * @param index Index being clicked.
481 * @return #CBF_NONE
483 static CallBackFunction MenuClickMap(int index)
485 switch (index) {
486 case MME_SHOW_SMALLMAP: ShowSmallMap(); break;
487 case MME_SHOW_EXTRAVIEWPORTS: ShowExtraViewPortWindow(); break;
488 case MME_SHOW_LINKGRAPH: ShowLinkGraphLegend(); break;
489 case MME_SHOW_SIGNLISTS: ShowSignList(); break;
490 case MME_SHOW_TOWNDIRECTORY: ShowTownDirectory(); break;
491 case MME_SHOW_INDUSTRYDIRECTORY: ShowIndustryDirectory(); break;
493 return CBF_NONE;
496 /* --- Town button menu --- */
498 static CallBackFunction ToolbarTownClick(Window *w)
500 PopupMainToolbMenu(w, WID_TN_TOWNS, STR_TOWN_MENU_TOWN_DIRECTORY, (_settings_game.economy.found_town == TF_FORBIDDEN) ? 1 : 2);
501 return CBF_NONE;
505 * Handle click on one of the entries in the Town menu.
507 * @param index Index being clicked.
508 * @return #CBF_NONE
510 static CallBackFunction MenuClickTown(int index)
512 switch (index) {
513 case 0: ShowTownDirectory(); break;
514 case 1: // setting could be changed when the dropdown was open
515 if (_settings_game.economy.found_town != TF_FORBIDDEN) ShowFoundTownWindow();
516 break;
518 return CBF_NONE;
521 /* --- Subidies button menu --- */
523 static CallBackFunction ToolbarSubsidiesClick(Window *w)
525 PopupMainToolbMenu(w, WID_TN_SUBSIDIES, STR_SUBSIDIES_MENU_SUBSIDIES, 1);
526 return CBF_NONE;
530 * Handle click on the entry in the Subsidies menu.
532 * @param index Unused.
533 * @return #CBF_NONE
535 static CallBackFunction MenuClickSubsidies(int index)
537 switch (index) {
538 case 0: ShowSubsidiesList(); break;
540 return CBF_NONE;
543 /* --- Stations button menu --- */
545 static CallBackFunction ToolbarStationsClick(Window *w)
547 PopupMainCompanyToolbMenu(w, WID_TN_STATIONS);
548 return CBF_NONE;
552 * Handle click on the entry in the Stations menu
554 * @param index CompanyID to show station list for
555 * @return #CBF_NONE
557 static CallBackFunction MenuClickStations(int index)
559 ShowCompanyStations((CompanyID)index);
560 return CBF_NONE;
563 /* --- Finances button menu --- */
565 static CallBackFunction ToolbarFinancesClick(Window *w)
567 PopupMainCompanyToolbMenu(w, WID_TN_FINANCES);
568 return CBF_NONE;
572 * Handle click on the entry in the finances overview menu.
574 * @param index CompanyID to show finances for.
575 * @return #CBF_NONE
577 static CallBackFunction MenuClickFinances(int index)
579 ShowCompanyFinances((CompanyID)index);
580 return CBF_NONE;
583 /* --- Company's button menu --- */
585 static CallBackFunction ToolbarCompaniesClick(Window *w)
587 PopupMainCompanyToolbMenu(w, WID_TN_COMPANIES, 0, true);
588 return CBF_NONE;
592 * Handle click on the entry in the Company menu.
594 * @param index Menu entry to handle.
595 * @return #CBF_NONE
597 static CallBackFunction MenuClickCompany(int index)
599 #ifdef ENABLE_NETWORK
600 if (_networking) {
601 switch (index) {
602 case CTMN_CLIENT_LIST:
603 ShowClientList();
604 return CBF_NONE;
606 case CTMN_NEW_COMPANY:
607 if (_network_server) {
608 DoCommandP(0, 0, _network_own_client_id, CMD_COMPANY_CTRL);
609 } else {
610 NetworkSendCommand(0, 0, 0, CMD_COMPANY_CTRL, NULL, _local_company);
612 return CBF_NONE;
614 case CTMN_SPECTATE:
615 if (_network_server) {
616 NetworkServerDoMove(CLIENT_ID_SERVER, COMPANY_SPECTATOR);
617 MarkWholeScreenDirty();
618 } else {
619 NetworkClientRequestMove(COMPANY_SPECTATOR);
621 return CBF_NONE;
624 #endif /* ENABLE_NETWORK */
625 ShowCompany((CompanyID)index);
626 return CBF_NONE;
629 /* --- Story button menu --- */
631 static CallBackFunction ToolbarStoryClick(Window *w)
633 PopupMainCompanyToolbMenu(w, WID_TN_STORY, 0, true);
634 return CBF_NONE;
638 * Handle click on the entry in the Story menu
640 * @param index CompanyID to show story book for
641 * @return #CBF_NONE
643 static CallBackFunction MenuClickStory(int index)
645 ShowStoryBook(index == CTMN_SPECTATOR ? INVALID_COMPANY : (CompanyID)index);
646 return CBF_NONE;
649 /* --- Goal button menu --- */
651 static CallBackFunction ToolbarGoalClick(Window *w)
653 PopupMainCompanyToolbMenu(w, WID_TN_GOAL, 0, true);
654 return CBF_NONE;
658 * Handle click on the entry in the Goal menu
660 * @param index CompanyID to show story book for
661 * @return #CBF_NONE
663 static CallBackFunction MenuClickGoal(int index)
665 ShowGoalsList(index == CTMN_SPECTATOR ? INVALID_COMPANY : (CompanyID)index);
666 return CBF_NONE;
669 /* --- Graphs button menu --- */
671 static CallBackFunction ToolbarGraphsClick(Window *w)
673 PopupMainToolbMenu(w, WID_TN_GRAPHS, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, (_toolbar_mode == TB_NORMAL) ? 6 : 8);
674 return CBF_NONE;
678 * Handle click on the entry in the Graphs menu.
680 * @param index Graph to show.
681 * @return #CBF_NONE
683 static CallBackFunction MenuClickGraphs(int index)
685 switch (index) {
686 case 0: ShowOperatingProfitGraph(); break;
687 case 1: ShowIncomeGraph(); break;
688 case 2: ShowDeliveredCargoGraph(); break;
689 case 3: ShowPerformanceHistoryGraph(); break;
690 case 4: ShowCompanyValueGraph(); break;
691 case 5: ShowCargoPaymentRates(); break;
692 /* functions for combined graphs/league button */
693 case 6: ShowCompanyLeagueTable(); break;
694 case 7: ShowPerformanceRatingDetail(); break;
696 return CBF_NONE;
699 /* --- League button menu --- */
701 static CallBackFunction ToolbarLeagueClick(Window *w)
703 PopupMainToolbMenu(w, WID_TN_LEAGUE, STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE, _networking ? 2 : 3);
704 return CBF_NONE;
708 * Handle click on the entry in the CompanyLeague menu.
710 * @param index Menu entry number.
711 * @return #CBF_NONE
713 static CallBackFunction MenuClickLeague(int index)
715 switch (index) {
716 case 0: ShowCompanyLeagueTable(); break;
717 case 1: ShowPerformanceRatingDetail(); break;
718 case 2: ShowHighscoreTable(); break;
720 return CBF_NONE;
723 /* --- Industries button menu --- */
725 static CallBackFunction ToolbarIndustryClick(Window *w)
727 /* Disable build-industry menu if we are a spectator */
728 PopupMainToolbMenu(w, WID_TN_INDUSTRIES, STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, (_local_company == COMPANY_SPECTATOR) ? 2 : 3);
729 return CBF_NONE;
733 * Handle click on the entry in the Industry menu.
735 * @param index Menu entry number.
736 * @return #CBF_NONE
738 static CallBackFunction MenuClickIndustry(int index)
740 switch (index) {
741 case 0: ShowIndustryDirectory(); break;
742 case 1: ShowIndustryCargoesWindow(); break;
743 case 2: ShowBuildIndustryWindow(); break;
745 return CBF_NONE;
748 /* --- Trains button menu + 1 helper function for all vehicles. --- */
750 static void ToolbarVehicleClick(Window *w, VehicleType veh)
752 const Vehicle *v;
753 int dis = ~0;
755 FOR_ALL_VEHICLES(v) {
756 if (v->type == veh && v->IsPrimaryVehicle()) ClrBit(dis, v->owner);
758 PopupMainCompanyToolbMenu(w, WID_TN_VEHICLE_START + veh, dis);
762 static CallBackFunction ToolbarTrainClick(Window *w)
764 ToolbarVehicleClick(w, VEH_TRAIN);
765 return CBF_NONE;
769 * Handle click on the entry in the Train menu.
771 * @param index CompanyID to show train list for.
772 * @return #CBF_NONE
774 static CallBackFunction MenuClickShowTrains(int index)
776 ShowVehicleListWindow((CompanyID)index, VEH_TRAIN);
777 return CBF_NONE;
780 /* --- Road vehicle button menu --- */
782 static CallBackFunction ToolbarRoadClick(Window *w)
784 ToolbarVehicleClick(w, VEH_ROAD);
785 return CBF_NONE;
789 * Handle click on the entry in the Road Vehicles menu.
791 * @param index CompanyID to show road vehicles list for.
792 * @return #CBF_NONE
794 static CallBackFunction MenuClickShowRoad(int index)
796 ShowVehicleListWindow((CompanyID)index, VEH_ROAD);
797 return CBF_NONE;
800 /* --- Ship button menu --- */
802 static CallBackFunction ToolbarShipClick(Window *w)
804 ToolbarVehicleClick(w, VEH_SHIP);
805 return CBF_NONE;
809 * Handle click on the entry in the Ships menu.
811 * @param index CompanyID to show ship list for.
812 * @return #CBF_NONE
814 static CallBackFunction MenuClickShowShips(int index)
816 ShowVehicleListWindow((CompanyID)index, VEH_SHIP);
817 return CBF_NONE;
820 /* --- Aircraft button menu --- */
822 static CallBackFunction ToolbarAirClick(Window *w)
824 ToolbarVehicleClick(w, VEH_AIRCRAFT);
825 return CBF_NONE;
829 * Handle click on the entry in the Aircraft menu.
831 * @param index CompanyID to show aircraft list for.
832 * @return #CBF_NONE
834 static CallBackFunction MenuClickShowAir(int index)
836 ShowVehicleListWindow((CompanyID)index, VEH_AIRCRAFT);
837 return CBF_NONE;
840 /* --- Zoom in button --- */
842 static CallBackFunction ToolbarZoomInClick(Window *w)
844 if (DoZoomInOutWindow (true, FindWindowById(WC_MAIN_WINDOW, 0))) {
845 w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)WID_TE_ZOOM_IN : (byte)WID_TN_ZOOM_IN);
846 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
848 return CBF_NONE;
851 /* --- Zoom out button --- */
853 static CallBackFunction ToolbarZoomOutClick(Window *w)
855 if (DoZoomInOutWindow (false, FindWindowById(WC_MAIN_WINDOW, 0))) {
856 w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)WID_TE_ZOOM_OUT : (byte)WID_TN_ZOOM_OUT);
857 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
859 return CBF_NONE;
862 /* --- Rail button menu --- */
864 static CallBackFunction ToolbarBuildRailClick(Window *w)
866 ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, WID_TN_RAILS, 140, true, true);
867 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
868 return CBF_NONE;
872 * Handle click on the entry in the Build Rail menu.
874 * @param index RailType to show the build toolbar for.
875 * @return #CBF_NONE
877 static CallBackFunction MenuClickBuildRail(int index)
879 _last_built_railtype = (RailType)index;
880 ShowBuildRailToolbar(_last_built_railtype);
881 return CBF_NONE;
884 /* --- Road button menu --- */
886 static CallBackFunction ToolbarBuildRoadClick(Window *w)
888 const Company *c = Company::Get(_local_company);
889 DropDownList *list = new DropDownList();
891 /* Road is always visible and available. */
892 *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION, ROADTYPE_ROAD, false);
894 /* Tram is only visible when there will be a tram, and available when that has been introduced. */
895 Engine *e;
896 FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
897 if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
898 if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
900 *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION, ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM));
901 break;
903 ShowDropDownList(w, list, _last_built_roadtype, WID_TN_ROADS, 140, true, true);
904 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
905 return CBF_NONE;
909 * Handle click on the entry in the Build Road menu.
911 * @param index RoadType to show the build toolbar for.
912 * @return #CBF_NONE
914 static CallBackFunction MenuClickBuildRoad(int index)
916 _last_built_roadtype = (RoadType)index;
917 ShowBuildRoadToolbar(_last_built_roadtype);
918 return CBF_NONE;
921 /* --- Water button menu --- */
923 static CallBackFunction ToolbarBuildWaterClick(Window *w)
925 PopupMainToolbMenu(w, WID_TN_WATER, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION, 1);
926 return CBF_NONE;
930 * Handle click on the entry in the Build Waterways menu.
932 * @param index Unused.
933 * @return #CBF_NONE
935 static CallBackFunction MenuClickBuildWater(int index)
937 ShowBuildDocksToolbar();
938 return CBF_NONE;
941 /* --- Airport button menu --- */
943 static CallBackFunction ToolbarBuildAirClick(Window *w)
945 PopupMainToolbMenu(w, WID_TN_AIR, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION, 1);
946 return CBF_NONE;
950 * Handle click on the entry in the Build Air menu.
952 * @param index Unused.
953 * @return #CBF_NONE
955 static CallBackFunction MenuClickBuildAir(int index)
957 ShowBuildAirToolbar();
958 return CBF_NONE;
961 /* --- Forest button menu --- */
963 static CallBackFunction ToolbarForestClick(Window *w)
965 PopupMainToolbMenu(w, WID_TN_LANDSCAPE, STR_LANDSCAPING_MENU_LANDSCAPING, 3);
966 return CBF_NONE;
970 * Handle click on the entry in the landscaping menu.
972 * @param index Menu entry clicked.
973 * @return #CBF_NONE
975 static CallBackFunction MenuClickForest(int index)
977 switch (index) {
978 case 0: ShowTerraformToolbar(); break;
979 case 1: ShowBuildTreesToolbar(); break;
980 case 2: return SelectSignTool();
982 return CBF_NONE;
985 /* --- Music button menu --- */
987 static CallBackFunction ToolbarMusicClick(Window *w)
989 PopupMainToolbMenu(w, WID_TN_MUSIC_SOUND, STR_TOOLBAR_SOUND_MUSIC, 1);
990 return CBF_NONE;
994 * Handle click on the entry in the Music menu.
996 * @param index Unused.
997 * @return #CBF_NONE
999 static CallBackFunction MenuClickMusicWindow(int index)
1001 ShowMusicWindow();
1002 return CBF_NONE;
1005 /* --- Newspaper button menu --- */
1007 static CallBackFunction ToolbarNewspaperClick(Window *w)
1009 PopupMainToolbMenu(w, WID_TN_MESSAGES, STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT, 2);
1010 return CBF_NONE;
1014 * Handle click on the entry in the Newspaper menu.
1016 * @param index Menu entry clicked.
1017 * @return #CBF_NONE
1019 static CallBackFunction MenuClickNewspaper(int index)
1021 switch (index) {
1022 case 0: ShowLastNewsMessage(); break;
1023 case 1: ShowMessageHistory(); break;
1025 return CBF_NONE;
1028 /* --- Help button menu --- */
1030 static CallBackFunction PlaceLandBlockInfo()
1032 if (_cursor.sprite == SPR_CURSOR_QUERY) {
1033 ResetPointerMode();
1034 return CBF_NONE;
1035 } else {
1036 SetPointerMode (POINTER_TILE, WC_MAIN_TOOLBAR, 0, SPR_CURSOR_QUERY);
1037 return CBF_PLACE_LANDINFO;
1041 static CallBackFunction ToolbarHelpClick(Window *w)
1043 PopupMainToolbMenu(w, WID_TN_HELP, STR_ABOUT_MENU_LAND_BLOCK_INFO, _settings_client.gui.newgrf_developer_tools ? 12 : 9);
1044 return CBF_NONE;
1047 static void MenuClickSmallScreenshot()
1049 MakeScreenshot(SC_VIEWPORT, NULL);
1053 * Callback on the confirmation window for huge screenshots.
1054 * @param w Window with viewport
1055 * @param confirmed true on confirmation
1057 static void ScreenshotConfirmCallback(Window *w, bool confirmed)
1059 if (confirmed) MakeScreenshot(_confirmed_screenshot_type, NULL);
1063 * Make a screenshot of the world.
1064 * Ask for confirmation if the screenshot will be huge.
1065 * @param t Screenshot type: World or viewport screenshot
1067 static void MenuClickLargeWorldScreenshot(ScreenshotType t)
1069 ViewPort vp;
1070 SetupScreenshotViewport(t, &vp);
1071 if ((uint64)vp.width * (uint64)vp.height > 8192 * 8192) {
1072 /* Ask for confirmation */
1073 SetDParam(0, vp.width);
1074 SetDParam(1, vp.height);
1075 _confirmed_screenshot_type = t;
1076 ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, NULL, ScreenshotConfirmCallback);
1077 } else {
1078 /* Less than 64M pixels, just do it */
1079 MakeScreenshot(t, NULL);
1084 * Toggle drawing of sprites' bounding boxes.
1085 * @note has only an effect when newgrf_developer_tools are active.
1087 * Function is found here and not in viewport.cpp in order to avoid
1088 * importing the settings structs to there.
1090 void ToggleBoundingBoxes()
1092 extern bool _draw_bounding_boxes;
1093 /* Always allow to toggle them off */
1094 if (_settings_client.gui.newgrf_developer_tools || _draw_bounding_boxes) {
1095 _draw_bounding_boxes = !_draw_bounding_boxes;
1096 MarkWholeScreenDirty();
1101 * Toggle drawing of the dirty blocks.
1102 * @note has only an effect when newgrf_developer_tools are active.
1104 * Function is found here and not in viewport.cpp in order to avoid
1105 * importing the settings structs to there.
1107 void ToggleDirtyBlocks()
1109 extern bool _draw_dirty_blocks;
1110 /* Always allow to toggle them off */
1111 if (_settings_client.gui.newgrf_developer_tools || _draw_dirty_blocks) {
1112 _draw_dirty_blocks = !_draw_dirty_blocks;
1113 MarkWholeScreenDirty();
1118 * Set the starting year for a scenario.
1119 * @param year New starting year.
1121 void SetStartingYear(Year year)
1123 _settings_game.game_creation.starting_year = Clamp(year, MIN_YEAR, MAX_YEAR);
1124 Date new_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
1125 /* If you open a savegame as scenario there may already be link graphs.*/
1126 LinkGraphSchedule::instance.ShiftDates(new_date - _date);
1127 SetDate(new_date, 0);
1131 * Choose the proper callback function for the main toolbar's help menu.
1132 * @param index The menu index which was selected.
1133 * @return CBF_NONE
1135 static CallBackFunction MenuClickHelp(int index)
1137 switch (index) {
1138 case 0: return PlaceLandBlockInfo();
1139 case 2: IConsoleSwitch(); break;
1140 case 3: ShowAIDebugWindow(); break;
1141 case 4: MenuClickSmallScreenshot(); break;
1142 case 5: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
1143 case 6: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
1144 case 7: MenuClickLargeWorldScreenshot(SC_WORLD); break;
1145 case 8: ShowAboutWindow(); break;
1146 case 9: ShowSpriteAlignerWindow(); break;
1147 case 10: ToggleBoundingBoxes(); break;
1148 case 11: ToggleDirtyBlocks(); break;
1150 return CBF_NONE;
1153 /* --- Switch toolbar button --- */
1155 static CallBackFunction ToolbarSwitchClick(Window *w)
1157 if (_toolbar_mode != TB_LOWER) {
1158 _toolbar_mode = TB_LOWER;
1159 } else {
1160 _toolbar_mode = TB_UPPER;
1163 w->ReInit();
1164 w->SetWidgetLoweredState(WID_TN_SWITCH_BAR, _toolbar_mode == TB_LOWER);
1165 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1166 return CBF_NONE;
1169 /* --- Scenario editor specific handlers. */
1172 * Called when clicking at the date panel of the scenario editor toolbar.
1174 static CallBackFunction ToolbarScenDatePanel(Window *w)
1176 SetDParam(0, _settings_game.game_creation.starting_year);
1177 ShowQueryString(STR_JUST_INT, STR_MAPGEN_START_DATE_QUERY_CAPT, 8, w, CS_NUMERAL, QSF_ENABLE_DEFAULT);
1178 _left_button_clicked = false;
1179 return CBF_NONE;
1182 static CallBackFunction ToolbarScenDateBackward(Window *w)
1184 /* don't allow too fast scrolling */
1185 if (!(w->flags & WF_TIMEOUT) || w->timeout_timer <= 1) {
1186 w->HandleButtonClick(WID_TE_DATE_BACKWARD);
1187 w->SetDirty();
1189 SetStartingYear(_settings_game.game_creation.starting_year - 1);
1191 _left_button_clicked = false;
1192 return CBF_NONE;
1195 static CallBackFunction ToolbarScenDateForward(Window *w)
1197 /* don't allow too fast scrolling */
1198 if (!(w->flags & WF_TIMEOUT) || w->timeout_timer <= 1) {
1199 w->HandleButtonClick(WID_TE_DATE_FORWARD);
1200 w->SetDirty();
1202 SetStartingYear(_settings_game.game_creation.starting_year + 1);
1204 _left_button_clicked = false;
1205 return CBF_NONE;
1208 static CallBackFunction ToolbarScenGenLand(Window *w)
1210 w->HandleButtonClick(WID_TE_LAND_GENERATE);
1211 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1213 ShowEditorTerraformToolbar();
1214 return CBF_NONE;
1218 static CallBackFunction ToolbarScenGenTown(Window *w)
1220 w->HandleButtonClick(WID_TE_TOWN_GENERATE);
1221 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1222 ShowFoundTownWindow();
1223 return CBF_NONE;
1226 static CallBackFunction ToolbarScenGenIndustry(Window *w)
1228 w->HandleButtonClick(WID_TE_INDUSTRY);
1229 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1230 ShowBuildIndustryWindow();
1231 return CBF_NONE;
1234 static CallBackFunction ToolbarScenBuildRoad(Window *w)
1236 w->HandleButtonClick(WID_TE_ROADS);
1237 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1238 ShowBuildRoadScenToolbar();
1239 return CBF_NONE;
1242 static CallBackFunction ToolbarScenBuildDocks(Window *w)
1244 w->HandleButtonClick(WID_TE_WATER);
1245 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1246 ShowBuildDocksScenToolbar();
1247 return CBF_NONE;
1250 static CallBackFunction ToolbarScenPlantTrees(Window *w)
1252 w->HandleButtonClick(WID_TE_TREES);
1253 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1254 ShowBuildTreesToolbar();
1255 return CBF_NONE;
1258 static CallBackFunction ToolbarScenPlaceSign(Window *w)
1260 w->HandleButtonClick(WID_TE_SIGNS);
1261 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1262 return SelectSignTool();
1265 static CallBackFunction ToolbarBtn_NULL(Window *w)
1267 return CBF_NONE;
1270 typedef CallBackFunction MenuClickedProc(int index);
1272 static MenuClickedProc * const _menu_clicked_procs[] = {
1273 NULL, // 0
1274 NULL, // 1
1275 MenuClickSettings, // 2
1276 MenuClickSaveLoad, // 3
1277 MenuClickMap, // 4
1278 MenuClickTown, // 5
1279 MenuClickSubsidies, // 6
1280 MenuClickStations, // 7
1281 MenuClickFinances, // 8
1282 MenuClickCompany, // 9
1283 MenuClickStory, // 10
1284 MenuClickGoal, // 11
1285 MenuClickGraphs, // 12
1286 MenuClickLeague, // 13
1287 MenuClickIndustry, // 14
1288 MenuClickShowTrains, // 15
1289 MenuClickShowRoad, // 16
1290 MenuClickShowShips, // 17
1291 MenuClickShowAir, // 18
1292 MenuClickMap, // 19
1293 NULL, // 20
1294 MenuClickBuildRail, // 21
1295 MenuClickBuildRoad, // 22
1296 MenuClickBuildWater, // 23
1297 MenuClickBuildAir, // 24
1298 MenuClickForest, // 25
1299 MenuClickMusicWindow, // 26
1300 MenuClickNewspaper, // 27
1301 MenuClickHelp, // 28
1304 /** Full blown container to make it behave exactly as we want :) */
1305 class NWidgetToolbarContainer : public NWidgetContainer {
1306 bool visible[WID_TN_END]; ///< The visible headers
1307 protected:
1308 uint spacers; ///< Number of spacer widgets in this toolbar
1310 public:
1311 NWidgetToolbarContainer() : NWidgetContainer(NWID_HORIZONTAL)
1316 * Check whether the given widget type is a button for us.
1317 * @param type the widget type to check.
1318 * @return true if it is a button for us.
1320 bool IsButton(WidgetType type) const
1322 return type == WWT_IMGBTN || type == WWT_IMGBTN_2 || type == WWT_PUSHIMGBTN;
1325 void SetupSmallestSize(Window *w, bool init_array)
1327 this->smallest_x = 0; // Biggest child
1328 this->smallest_y = 0; // Biggest child
1329 this->fill_x = 1;
1330 this->fill_y = 0;
1331 this->resize_x = 1; // We only resize in this direction
1332 this->resize_y = 0; // We never resize in this direction
1333 this->spacers = 0;
1335 uint nbuttons = 0;
1336 /* First initialise some variables... */
1337 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1338 child_wid->SetupSmallestSize(w, init_array);
1339 this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
1340 if (this->IsButton(child_wid->type)) {
1341 nbuttons++;
1342 this->smallest_x = max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
1343 } else if (child_wid->type == NWID_SPACER) {
1344 this->spacers++;
1348 /* ... then in a second pass make sure the 'current' heights are set. Won't change ever. */
1349 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1350 child_wid->current_y = this->smallest_y;
1351 if (!this->IsButton(child_wid->type)) {
1352 child_wid->current_x = child_wid->smallest_x;
1355 _toolbar_width = nbuttons * this->smallest_x;
1358 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
1360 assert(given_width >= this->smallest_x && given_height >= this->smallest_y);
1362 this->pos_x = x;
1363 this->pos_y = y;
1364 this->current_x = given_width;
1365 this->current_y = given_height;
1367 /* Figure out what are the visible buttons */
1368 memset(this->visible, 0, sizeof(this->visible));
1369 uint arrangable_count, button_count, spacer_count;
1370 const byte *arrangement = GetButtonArrangement(given_width, arrangable_count, button_count, spacer_count);
1371 for (uint i = 0; i < arrangable_count; i++) {
1372 this->visible[arrangement[i]] = true;
1375 /* Create us ourselves a quick lookup table */
1376 NWidgetBase *widgets[WID_TN_END];
1377 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1378 if (child_wid->type == NWID_SPACER) continue;
1379 widgets[((NWidgetCore*)child_wid)->index] = child_wid;
1382 /* Now assign the widgets to their rightful place */
1383 uint position = 0; // Place to put next child relative to origin of the container.
1384 uint spacer_space = max(0, (int)given_width - (int)(button_count * this->smallest_x)); // Remaining spacing for 'spacer' widgets
1385 uint button_space = given_width - spacer_space; // Remaining spacing for the buttons
1386 uint spacer_i = 0;
1387 uint button_i = 0;
1389 /* Index into the arrangement indices. The macro lastof cannot be used here! */
1390 const byte *cur_wid = rtl ? &arrangement[arrangable_count - 1] : arrangement;
1391 for (uint i = 0; i < arrangable_count; i++) {
1392 NWidgetBase *child_wid = widgets[*cur_wid];
1393 /* If we have to give space to the spacers, do that */
1394 if (spacer_space != 0) {
1395 NWidgetBase *possible_spacer = rtl ? child_wid->next : child_wid->prev;
1396 if (possible_spacer != NULL && possible_spacer->type == NWID_SPACER) {
1397 uint add = spacer_space / (spacer_count - spacer_i);
1398 position += add;
1399 spacer_space -= add;
1400 spacer_i++;
1404 /* Buttons can be scaled, the others not. */
1405 if (this->IsButton(child_wid->type)) {
1406 child_wid->current_x = button_space / (button_count - button_i);
1407 button_space -= child_wid->current_x;
1408 button_i++;
1410 child_wid->AssignSizePosition(sizing, x + position, y, child_wid->current_x, this->current_y, rtl);
1411 position += child_wid->current_x;
1413 if (rtl) {
1414 cur_wid--;
1415 } else {
1416 cur_wid++;
1421 /* virtual */ void Draw(const Window *w)
1423 /* Draw brown-red toolbar bg. */
1424 GfxFillRect(this->pos_x, this->pos_y, this->pos_x + this->current_x - 1, this->pos_y + this->current_y - 1, PC_VERY_DARK_RED);
1425 GfxFillRect(this->pos_x, this->pos_y, this->pos_x + this->current_x - 1, this->pos_y + this->current_y - 1, PC_DARK_RED, FILLRECT_CHECKER);
1427 bool rtl = _current_text_dir == TD_RTL;
1428 for (NWidgetBase *child_wid = rtl ? this->tail : this->head; child_wid != NULL; child_wid = rtl ? child_wid->prev : child_wid->next) {
1429 if (child_wid->type == NWID_SPACER) continue;
1430 if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
1432 child_wid->Draw(w);
1436 /* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y)
1438 if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
1440 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1441 if (child_wid->type == NWID_SPACER) continue;
1442 if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
1444 NWidgetCore *nwid = child_wid->GetWidgetFromPos(x, y);
1445 if (nwid != NULL) return nwid;
1447 return NULL;
1451 * Get the arrangement of the buttons for the toolbar.
1452 * @param width the new width of the toolbar.
1453 * @param arrangable_count output of the number of visible items.
1454 * @param button_count output of the number of visible buttons.
1455 * @param spacer_count output of the number of spacers.
1456 * @return the button configuration.
1458 virtual const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const = 0;
1461 /** Container for the 'normal' main toolbar */
1462 class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
1463 /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
1465 static const uint SMALLEST_ARRANGEMENT = 14;
1466 static const uint BIGGEST_ARRANGEMENT = 20;
1467 static const byte arrange14[] = {
1468 0, 1, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 29,
1469 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 29,
1471 static const byte arrange15[] = {
1472 0, 1, 4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
1473 0, 2, 4, 3, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 29,
1475 static const byte arrange16[] = {
1476 0, 1, 2, 4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
1477 0, 1, 3, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 19, 20, 29,
1479 static const byte arrange17[] = {
1480 0, 1, 2, 4, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
1481 0, 1, 3, 4, 6, 5, 7, 8, 9, 12, 14, 26, 27, 28, 19, 20, 29,
1483 static const byte arrange18[] = {
1484 0, 1, 2, 4, 5, 6, 7, 8, 9, 14, 21, 22, 23, 24, 25, 19, 20, 29,
1485 0, 1, 3, 4, 5, 6, 7, 12, 15, 16, 17, 18, 26, 27, 28, 19, 20, 29,
1487 static const byte arrange19[] = {
1488 0, 1, 2, 4, 5, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 19, 20, 29,
1489 0, 1, 3, 4, 7, 8, 9, 12, 14, 27, 21, 22, 23, 24, 25, 28, 19, 20, 29,
1491 static const byte arrange20[] = {
1492 0, 1, 2, 4, 5, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 11, 19, 20, 29,
1493 0, 1, 3, 4, 7, 8, 9, 12, 14, 27, 21, 22, 23, 24, 25, 10, 28, 19, 20, 29,
1495 static const byte arrange_all[] = {
1496 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28
1499 /* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
1500 uint full_buttons = max(CeilDiv(width, this->smallest_x), SMALLEST_ARRANGEMENT);
1501 if (full_buttons > BIGGEST_ARRANGEMENT) {
1502 button_count = arrangable_count = lengthof(arrange_all);
1503 spacer_count = this->spacers;
1504 return arrange_all;
1507 /* Introduce the split toolbar */
1508 static const byte * const arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19, arrange20 };
1510 button_count = arrangable_count = full_buttons;
1511 spacer_count = this->spacers;
1512 return arrangements[full_buttons - SMALLEST_ARRANGEMENT] + ((_toolbar_mode == TB_LOWER) ? full_buttons : 0);
1516 /** Container for the scenario editor's toolbar */
1517 class NWidgetScenarioToolbarContainer : public NWidgetToolbarContainer {
1518 uint panel_widths[2]; ///< The width of the two panels (the text panel and date panel)
1520 void SetupSmallestSize(Window *w, bool init_array)
1522 this->NWidgetToolbarContainer::SetupSmallestSize(w, init_array);
1524 /* Find the size of panel_widths */
1525 uint i = 0;
1526 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1527 if (child_wid->type == NWID_SPACER || this->IsButton(child_wid->type)) continue;
1529 assert(i < lengthof(this->panel_widths));
1530 this->panel_widths[i++] = child_wid->current_x;
1531 _toolbar_width += child_wid->current_x;
1535 /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
1537 static const byte arrange_all[] = {
1538 0, 1, 2, 3, 4, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 26, 28,
1540 static const byte arrange_nopanel[] = {
1541 0, 1, 2, 3, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 26, 28,
1543 static const byte arrange_switch[] = {
1544 18, 8, 11, 12, 13, 14, 15, 16, 17, 29,
1545 0, 1, 2, 3, 18, 9, 10, 26, 28, 29,
1548 /* If we can place all buttons *and* the panels, show them. */
1549 uint min_full_width = (lengthof(arrange_all) - lengthof(this->panel_widths)) * this->smallest_x + this->panel_widths[0] + this->panel_widths[1];
1550 if (width >= min_full_width) {
1551 width -= this->panel_widths[0] + this->panel_widths[1];
1552 arrangable_count = lengthof(arrange_all);
1553 button_count = arrangable_count - 2;
1554 spacer_count = this->spacers;
1555 return arrange_all;
1558 /* Otherwise don't show the date panel and if we can't fit half the buttons and the panels anymore, split the toolbar in two */
1559 uint min_small_width = (lengthof(arrange_switch) - lengthof(this->panel_widths)) * this->smallest_x / 2 + this->panel_widths[1];
1560 if (width > min_small_width) {
1561 width -= this->panel_widths[1];
1562 arrangable_count = lengthof(arrange_nopanel);
1563 button_count = arrangable_count - 1;
1564 spacer_count = this->spacers - 1;
1565 return arrange_nopanel;
1568 /* Split toolbar */
1569 width -= this->panel_widths[1];
1570 arrangable_count = lengthof(arrange_switch) / 2;
1571 button_count = arrangable_count - 1;
1572 spacer_count = 0;
1573 return arrange_switch + ((_toolbar_mode == TB_LOWER) ? arrangable_count : 0);
1577 /* --- Toolbar handling for the 'normal' case */
1579 typedef CallBackFunction ToolbarButtonProc(Window *w);
1581 static ToolbarButtonProc * const _toolbar_button_procs[] = {
1582 ToolbarPauseClick,
1583 ToolbarFastForwardClick,
1584 ToolbarOptionsClick,
1585 ToolbarSaveClick,
1586 ToolbarMapClick,
1587 ToolbarTownClick,
1588 ToolbarSubsidiesClick,
1589 ToolbarStationsClick,
1590 ToolbarFinancesClick,
1591 ToolbarCompaniesClick,
1592 ToolbarStoryClick,
1593 ToolbarGoalClick,
1594 ToolbarGraphsClick,
1595 ToolbarLeagueClick,
1596 ToolbarIndustryClick,
1597 ToolbarTrainClick,
1598 ToolbarRoadClick,
1599 ToolbarShipClick,
1600 ToolbarAirClick,
1601 ToolbarZoomInClick,
1602 ToolbarZoomOutClick,
1603 ToolbarBuildRailClick,
1604 ToolbarBuildRoadClick,
1605 ToolbarBuildWaterClick,
1606 ToolbarBuildAirClick,
1607 ToolbarForestClick,
1608 ToolbarMusicClick,
1609 ToolbarNewspaperClick,
1610 ToolbarHelpClick,
1611 ToolbarSwitchClick,
1614 enum MainToolbarHotkeys {
1615 MTHK_PAUSE,
1616 MTHK_FASTFORWARD,
1617 MTHK_SETTINGS,
1618 MTHK_SAVEGAME,
1619 MTHK_LOADGAME,
1620 MTHK_SMALLMAP,
1621 MTHK_TOWNDIRECTORY,
1622 MTHK_SUBSIDIES,
1623 MTHK_STATIONS,
1624 MTHK_FINANCES,
1625 MTHK_COMPANIES,
1626 MTHK_STORY,
1627 MTHK_GOAL,
1628 MTHK_GRAPHS,
1629 MTHK_LEAGUE,
1630 MTHK_INDUSTRIES,
1631 MTHK_TRAIN_LIST,
1632 MTHK_ROADVEH_LIST,
1633 MTHK_SHIP_LIST,
1634 MTHK_AIRCRAFT_LIST,
1635 MTHK_ZOOM_IN,
1636 MTHK_ZOOM_OUT,
1637 MTHK_BUILD_RAIL,
1638 MTHK_BUILD_ROAD,
1639 MTHK_BUILD_DOCKS,
1640 MTHK_BUILD_AIRPORT,
1641 MTHK_BUILD_TREES,
1642 MTHK_MUSIC,
1643 MTHK_AI_DEBUG,
1644 MTHK_SMALL_SCREENSHOT,
1645 MTHK_ZOOMEDIN_SCREENSHOT,
1646 MTHK_DEFAULTZOOM_SCREENSHOT,
1647 MTHK_GIANT_SCREENSHOT,
1648 MTHK_CHEATS,
1649 MTHK_TERRAFORM,
1650 MTHK_EXTRA_VIEWPORT,
1651 MTHK_CLIENT_LIST,
1652 MTHK_SIGN_LIST,
1655 /** Main toolbar. */
1656 struct MainToolbarWindow : Window {
1657 CallBackFunction last_started_action; ///< Last started user action.
1659 MainToolbarWindow (const WindowDesc *desc) :
1660 Window (desc), last_started_action (CBF_NONE)
1662 this->InitNested(0);
1664 this->last_started_action = CBF_NONE;
1665 CLRBITS(this->flags, WF_WHITE_BORDER);
1666 this->SetWidgetDisabledState(WID_TN_PAUSE, _networking && !_network_server); // if not server, disable pause button
1667 this->SetWidgetDisabledState(WID_TN_FAST_FORWARD, _networking); // if networking, disable fast-forward button
1668 PositionMainToolbar(this);
1669 this->InvalidateData();
1672 virtual void FindWindowPlacementAndResize(int def_width, int def_height)
1674 Window::FindWindowPlacementAndResize(_toolbar_width, def_height);
1677 virtual void OnPaint()
1679 /* If spectator, disable all construction buttons
1680 * ie : Build road, rail, ships, airports and landscaping
1681 * Since enabled state is the default, just disable when needed */
1682 this->SetWidgetsDisabledState(_local_company == COMPANY_SPECTATOR, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, WID_TN_AIR, WID_TN_LANDSCAPE, WIDGET_LIST_END);
1683 /* disable company list drop downs, if there are no companies */
1684 this->SetWidgetsDisabledState(Company::GetNumItems() == 0, WID_TN_STATIONS, WID_TN_FINANCES, WID_TN_TRAINS, WID_TN_ROADVEHS, WID_TN_SHIPS, WID_TN_AIRCRAFTS, WIDGET_LIST_END);
1686 this->SetWidgetDisabledState(WID_TN_GOAL, Goal::GetNumItems() == 0);
1687 this->SetWidgetDisabledState(WID_TN_STORY, StoryPage::GetNumItems() == 0);
1689 this->SetWidgetDisabledState(WID_TN_RAILS, !CanBuildVehicleInfrastructure(VEH_TRAIN));
1690 this->SetWidgetDisabledState(WID_TN_AIR, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT));
1692 this->DrawWidgets();
1695 virtual void OnClick(Point pt, int widget, int click_count)
1697 if (_game_mode != GM_MENU && !this->IsWidgetDisabled(widget)) _toolbar_button_procs[widget](this);
1700 virtual void OnDropdownSelect(int widget, int index)
1702 CallBackFunction cbf = _menu_clicked_procs[widget](index);
1703 if (cbf != CBF_NONE) this->last_started_action = cbf;
1706 virtual EventState OnHotkey(int hotkey)
1708 switch (hotkey) {
1709 case MTHK_PAUSE: ToolbarPauseClick(this); break;
1710 case MTHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
1711 case MTHK_SETTINGS: ShowGameOptions(); break;
1712 case MTHK_SAVEGAME: MenuClickSaveLoad(); break;
1713 case MTHK_LOADGAME: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
1714 case MTHK_SMALLMAP: ShowSmallMap(); break;
1715 case MTHK_TOWNDIRECTORY: ShowTownDirectory(); break;
1716 case MTHK_SUBSIDIES: ShowSubsidiesList(); break;
1717 case MTHK_STATIONS: ShowCompanyStations(_local_company); break;
1718 case MTHK_FINANCES: ShowCompanyFinances(_local_company); break;
1719 case MTHK_COMPANIES: ShowCompany(_local_company); break;
1720 case MTHK_STORY: ShowStoryBook(_local_company); break;
1721 case MTHK_GOAL: ShowGoalsList(_local_company); break;
1722 case MTHK_GRAPHS: ShowOperatingProfitGraph(); break;
1723 case MTHK_LEAGUE: ShowCompanyLeagueTable(); break;
1724 case MTHK_INDUSTRIES: ShowBuildIndustryWindow(); break;
1725 case MTHK_TRAIN_LIST: ShowVehicleListWindow(_local_company, VEH_TRAIN); break;
1726 case MTHK_ROADVEH_LIST: ShowVehicleListWindow(_local_company, VEH_ROAD); break;
1727 case MTHK_SHIP_LIST: ShowVehicleListWindow(_local_company, VEH_SHIP); break;
1728 case MTHK_AIRCRAFT_LIST: ShowVehicleListWindow(_local_company, VEH_AIRCRAFT); break;
1729 case MTHK_ZOOM_IN: ToolbarZoomInClick(this); break;
1730 case MTHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
1731 case MTHK_BUILD_RAIL: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype); break;
1732 case MTHK_BUILD_ROAD: ShowBuildRoadToolbar(_last_built_roadtype); break;
1733 case MTHK_BUILD_DOCKS: ShowBuildDocksToolbar(); break;
1734 case MTHK_BUILD_AIRPORT: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break;
1735 case MTHK_BUILD_TREES: ShowBuildTreesToolbar(); break;
1736 case MTHK_MUSIC: ShowMusicWindow(); break;
1737 case MTHK_AI_DEBUG: ShowAIDebugWindow(); break;
1738 case MTHK_SMALL_SCREENSHOT: MenuClickSmallScreenshot(); break;
1739 case MTHK_ZOOMEDIN_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
1740 case MTHK_DEFAULTZOOM_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
1741 case MTHK_GIANT_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_WORLD); break;
1742 case MTHK_CHEATS: if (!_networking) ShowCheatWindow(); break;
1743 case MTHK_TERRAFORM: ShowTerraformToolbar(); break;
1744 case MTHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
1745 #ifdef ENABLE_NETWORK
1746 case MTHK_CLIENT_LIST: if (_networking) ShowClientList(); break;
1747 #endif
1748 case MTHK_SIGN_LIST: ShowSignList(); break;
1749 default: return ES_NOT_HANDLED;
1751 return ES_HANDLED;
1754 virtual void OnPlaceObject(Point pt, TileIndex tile)
1756 switch (this->last_started_action) {
1757 case CBF_PLACE_SIGN:
1758 PlaceProc_Sign(tile);
1759 break;
1761 case CBF_PLACE_LANDINFO:
1762 ShowLandInfo(tile);
1763 break;
1765 default: NOT_REACHED();
1769 virtual void OnTick()
1771 if (this->IsWidgetLowered(WID_TN_PAUSE) != !!_pause_mode) {
1772 this->ToggleWidgetLoweredState(WID_TN_PAUSE);
1773 this->SetWidgetDirty(WID_TN_PAUSE);
1776 if (this->IsWidgetLowered(WID_TN_FAST_FORWARD) != !!_fast_forward) {
1777 this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD);
1778 this->SetWidgetDirty(WID_TN_FAST_FORWARD);
1782 virtual void OnTimeout()
1784 /* We do not want to automatically raise the pause, fast forward and
1785 * switchbar buttons; they have to stay down when pressed etc. */
1786 for (uint i = WID_TN_SETTINGS; i < WID_TN_SWITCH_BAR; i++) {
1787 if (this->IsWidgetLowered(i)) {
1788 this->RaiseWidget(i);
1789 this->SetWidgetDirty(i);
1795 * Some data on this window has become invalid.
1796 * @param data Information about the changed data.
1797 * @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
1799 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
1801 if (!gui_scope) return;
1802 if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT);
1805 static HotkeyList hotkeys;
1808 static const Hotkey maintoolbar_hotkeys[] = {
1809 Hotkey ("pause", MTHK_PAUSE, WKC_F1, WKC_PAUSE),
1810 Hotkey ("fastforward", MTHK_FASTFORWARD),
1811 Hotkey ("settings", MTHK_SETTINGS, WKC_F2),
1812 Hotkey ("saveload", MTHK_SAVEGAME, WKC_F3),
1813 Hotkey ("load_game", MTHK_LOADGAME),
1814 Hotkey ("smallmap", MTHK_SMALLMAP, WKC_F4, 'M'),
1815 Hotkey ("town_list", MTHK_TOWNDIRECTORY, WKC_F5),
1816 Hotkey ("subsidies", MTHK_SUBSIDIES, WKC_F6),
1817 Hotkey ("station_list", MTHK_STATIONS, WKC_F7),
1818 Hotkey ("finances", MTHK_FINANCES, WKC_F8),
1819 Hotkey ("companies", MTHK_COMPANIES, WKC_F9),
1820 Hotkey ("story_book", MTHK_STORY),
1821 Hotkey ("goal_list", MTHK_GOAL),
1822 Hotkey ("graphs", MTHK_GRAPHS, WKC_F10),
1823 Hotkey ("league", MTHK_LEAGUE, WKC_F11),
1824 Hotkey ("industry_list", MTHK_INDUSTRIES, WKC_F12),
1825 Hotkey ("train_list", MTHK_TRAIN_LIST, WKC_SHIFT | WKC_F1),
1826 Hotkey ("roadveh_list", MTHK_ROADVEH_LIST, WKC_SHIFT | WKC_F2),
1827 Hotkey ("ship_list", MTHK_SHIP_LIST, WKC_SHIFT | WKC_F3),
1828 Hotkey ("aircraft_list", MTHK_AIRCRAFT_LIST, WKC_SHIFT | WKC_F4),
1829 Hotkey ("zoomin", MTHK_ZOOM_IN, WKC_SHIFT | WKC_F5, WKC_NUM_PLUS, WKC_EQUALS, WKC_SHIFT | WKC_EQUALS),
1830 Hotkey ("zoomout", MTHK_ZOOM_OUT, WKC_SHIFT | WKC_F6, WKC_NUM_MINUS, WKC_MINUS, WKC_SHIFT | WKC_MINUS),
1831 Hotkey ("build_rail", MTHK_BUILD_RAIL, WKC_SHIFT | WKC_F7),
1832 Hotkey ("build_road", MTHK_BUILD_ROAD, WKC_SHIFT | WKC_F8),
1833 Hotkey ("build_docks", MTHK_BUILD_DOCKS, WKC_SHIFT | WKC_F9),
1834 Hotkey ("build_airport", MTHK_BUILD_AIRPORT, WKC_SHIFT | WKC_F10),
1835 Hotkey ("build_trees", MTHK_BUILD_TREES, WKC_SHIFT | WKC_F11),
1836 Hotkey ("music", MTHK_MUSIC, WKC_SHIFT | WKC_F12),
1837 Hotkey ("ai_debug", MTHK_AI_DEBUG),
1838 Hotkey ("small_screenshot", MTHK_SMALL_SCREENSHOT, WKC_CTRL | 'S'),
1839 Hotkey ("zoomedin_screenshot", MTHK_ZOOMEDIN_SCREENSHOT, WKC_CTRL | 'P'),
1840 Hotkey ("defaultzoom_screenshot", MTHK_DEFAULTZOOM_SCREENSHOT, WKC_CTRL | 'D'),
1841 Hotkey ("giant_screenshot", MTHK_GIANT_SCREENSHOT),
1842 Hotkey ("cheats", MTHK_CHEATS, WKC_CTRL | WKC_ALT | 'C'),
1843 Hotkey ("terraform", MTHK_TERRAFORM, 'L'),
1844 Hotkey ("extra_viewport", MTHK_EXTRA_VIEWPORT, 'V'),
1845 #ifdef ENABLE_NETWORK
1846 Hotkey ("client_list", MTHK_CLIENT_LIST),
1847 #endif
1848 Hotkey ("sign_list", MTHK_SIGN_LIST),
1850 HotkeyList MainToolbarWindow::hotkeys("maintoolbar", maintoolbar_hotkeys);
1852 static NWidgetBase *MakeMainToolbar(int *biggest_index)
1854 /** Sprites to use for the different toolbar buttons */
1855 static const SpriteID toolbar_button_sprites[] = {
1856 SPR_IMG_PAUSE, // WID_TN_PAUSE
1857 SPR_IMG_FASTFORWARD, // WID_TN_FAST_FORWARD
1858 SPR_IMG_SETTINGS, // WID_TN_SETTINGS
1859 SPR_IMG_SAVE, // WID_TN_SAVE
1860 SPR_IMG_SMALLMAP, // WID_TN_SMALL_MAP
1861 SPR_IMG_TOWN, // WID_TN_TOWNS
1862 SPR_IMG_SUBSIDIES, // WID_TN_SUBSIDIES
1863 SPR_IMG_COMPANY_LIST, // WID_TN_STATIONS
1864 SPR_IMG_COMPANY_FINANCE, // WID_TN_FINANCES
1865 SPR_IMG_COMPANY_GENERAL, // WID_TN_COMPANIES
1866 SPR_IMG_STORY_BOOK, // WID_TN_STORY
1867 SPR_IMG_GOAL, // WID_TN_GOAL
1868 SPR_IMG_GRAPHS, // WID_TN_GRAPHS
1869 SPR_IMG_COMPANY_LEAGUE, // WID_TN_LEAGUE
1870 SPR_IMG_INDUSTRY, // WID_TN_INDUSTRIES
1871 SPR_IMG_TRAINLIST, // WID_TN_TRAINS
1872 SPR_IMG_TRUCKLIST, // WID_TN_ROADVEHS
1873 SPR_IMG_SHIPLIST, // WID_TN_SHIPS
1874 SPR_IMG_AIRPLANESLIST, // WID_TN_AIRCRAFT
1875 SPR_IMG_ZOOMIN, // WID_TN_ZOOMIN
1876 SPR_IMG_ZOOMOUT, // WID_TN_ZOOMOUT
1877 SPR_IMG_BUILDRAIL, // WID_TN_RAILS
1878 SPR_IMG_BUILDROAD, // WID_TN_ROADS
1879 SPR_IMG_BUILDWATER, // WID_TN_WATER
1880 SPR_IMG_BUILDAIR, // WID_TN_AIR
1881 SPR_IMG_LANDSCAPING, // WID_TN_LANDSCAPE
1882 SPR_IMG_MUSIC, // WID_TN_MUSIC_SOUND
1883 SPR_IMG_MESSAGES, // WID_TN_MESSAGES
1884 SPR_IMG_QUERY, // WID_TN_HELP
1885 SPR_IMG_SWITCH_TOOLBAR, // WID_TN_SWITCH_BAR
1888 NWidgetMainToolbarContainer *hor = new NWidgetMainToolbarContainer();
1889 for (uint i = 0; i < WID_TN_END; i++) {
1890 switch (i) {
1891 case 4: case 8: case 15: case 19: case 21: case 26: hor->Add(new NWidgetSpacer(0, 0)); break;
1893 hor->Add(new NWidgetLeaf(i == WID_TN_SAVE ? WWT_IMGBTN_2 : WWT_IMGBTN, COLOUR_GREY, i, toolbar_button_sprites[i], STR_TOOLBAR_TOOLTIP_PAUSE_GAME + i));
1896 *biggest_index = max<int>(*biggest_index, WID_TN_SWITCH_BAR);
1897 return hor;
1900 static const NWidgetPart _nested_toolbar_normal_widgets[] = {
1901 NWidgetFunction(MakeMainToolbar),
1904 static const WindowDesc _toolb_normal_desc(
1905 WDP_MANUAL, 0, 0,
1906 WC_MAIN_TOOLBAR, WC_NONE,
1907 WDF_NO_FOCUS,
1908 _nested_toolbar_normal_widgets, lengthof(_nested_toolbar_normal_widgets),
1909 NULL, &MainToolbarWindow::hotkeys
1913 /* --- Toolbar handling for the scenario editor */
1915 static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
1916 ToolbarPauseClick,
1917 ToolbarFastForwardClick,
1918 ToolbarOptionsClick,
1919 ToolbarScenSaveOrLoad,
1920 ToolbarBtn_NULL,
1921 ToolbarScenDatePanel,
1922 ToolbarScenDateBackward,
1923 ToolbarScenDateForward,
1924 ToolbarScenMapTownDir,
1925 ToolbarZoomInClick,
1926 ToolbarZoomOutClick,
1927 ToolbarScenGenLand,
1928 ToolbarScenGenTown,
1929 ToolbarScenGenIndustry,
1930 ToolbarScenBuildRoad,
1931 ToolbarScenBuildDocks,
1932 ToolbarScenPlantTrees,
1933 ToolbarScenPlaceSign,
1934 ToolbarBtn_NULL,
1935 NULL,
1936 NULL,
1937 NULL,
1938 NULL,
1939 NULL,
1940 NULL,
1941 NULL,
1942 ToolbarMusicClick,
1943 NULL,
1944 ToolbarHelpClick,
1945 ToolbarSwitchClick,
1948 enum MainToolbarEditorHotkeys {
1949 MTEHK_PAUSE,
1950 MTEHK_FASTFORWARD,
1951 MTEHK_SETTINGS,
1952 MTEHK_SAVEGAME,
1953 MTEHK_GENLAND,
1954 MTEHK_GENTOWN,
1955 MTEHK_GENINDUSTRY,
1956 MTEHK_BUILD_ROAD,
1957 MTEHK_BUILD_DOCKS,
1958 MTEHK_BUILD_TREES,
1959 MTEHK_SIGN,
1960 MTEHK_MUSIC,
1961 MTEHK_LANDINFO,
1962 MTEHK_SMALL_SCREENSHOT,
1963 MTEHK_ZOOMEDIN_SCREENSHOT,
1964 MTEHK_DEFAULTZOOM_SCREENSHOT,
1965 MTEHK_GIANT_SCREENSHOT,
1966 MTEHK_ZOOM_IN,
1967 MTEHK_ZOOM_OUT,
1968 MTEHK_TERRAFORM,
1969 MTEHK_SMALLMAP,
1970 MTEHK_EXTRA_VIEWPORT,
1973 struct ScenarioEditorToolbarWindow : Window {
1974 CallBackFunction last_started_action; ///< Last started user action.
1976 ScenarioEditorToolbarWindow (const WindowDesc *desc) :
1977 Window (desc), last_started_action (CBF_NONE)
1979 this->InitNested(0);
1981 this->last_started_action = CBF_NONE;
1982 CLRBITS(this->flags, WF_WHITE_BORDER);
1983 PositionMainToolbar(this);
1984 this->InvalidateData();
1987 virtual void FindWindowPlacementAndResize(int def_width, int def_height)
1989 Window::FindWindowPlacementAndResize(_toolbar_width, def_height);
1992 virtual void OnPaint()
1994 this->SetWidgetDisabledState(WID_TE_DATE_BACKWARD, _settings_game.game_creation.starting_year <= MIN_YEAR);
1995 this->SetWidgetDisabledState(WID_TE_DATE_FORWARD, _settings_game.game_creation.starting_year >= MAX_YEAR);
1997 this->DrawWidgets();
2000 virtual void DrawWidget(const Rect &r, int widget) const
2002 switch (widget) {
2003 case WID_TE_DATE:
2004 SetDParam(0, ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
2005 DrawString(r.left, r.right, (this->height - FONT_HEIGHT_NORMAL) / 2, STR_WHITE_DATE_LONG, TC_FROMSTRING, SA_HOR_CENTER);
2006 break;
2008 case WID_TE_SPACER: {
2009 int height = r.bottom - r.top;
2010 if (height > 2 * FONT_HEIGHT_NORMAL) {
2011 DrawString(r.left, r.right, (height + 1) / 2 - FONT_HEIGHT_NORMAL, STR_SCENEDIT_TOOLBAR_OPENTTD, TC_FROMSTRING, SA_HOR_CENTER);
2012 DrawString(r.left, r.right, (height + 1) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
2013 } else {
2014 DrawString(r.left, r.right, (height - FONT_HEIGHT_NORMAL) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
2016 break;
2021 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2023 switch (widget) {
2024 case WID_TE_SPACER:
2025 size->width = max(GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_OPENTTD).width, GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR).width) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
2026 break;
2028 case WID_TE_DATE:
2029 SetDParam(0, ConvertYMDToDate(MAX_YEAR, 0, 1));
2030 *size = GetStringBoundingBox(STR_WHITE_DATE_LONG);
2031 size->height = max(size->height, GetSpriteSize(SPR_IMG_SAVE).height + WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM);
2032 break;
2036 virtual void OnClick(Point pt, int widget, int click_count)
2038 if (_game_mode == GM_MENU) return;
2039 CallBackFunction cbf = _scen_toolbar_button_procs[widget](this);
2040 if (cbf != CBF_NONE) this->last_started_action = cbf;
2043 virtual void OnDropdownSelect(int widget, int index)
2045 /* The map button is in a different location on the scenario
2046 * editor toolbar, so we need to adjust for it. */
2047 if (widget == WID_TE_SMALL_MAP) widget = WID_TN_SMALL_MAP;
2048 CallBackFunction cbf = _menu_clicked_procs[widget](index);
2049 if (cbf != CBF_NONE) this->last_started_action = cbf;
2050 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
2053 virtual EventState OnHotkey(int hotkey)
2055 CallBackFunction cbf = CBF_NONE;
2056 switch (hotkey) {
2057 case MTEHK_PAUSE: ToolbarPauseClick(this); break;
2058 case MTEHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
2059 case MTEHK_SETTINGS: ShowGameOptions(); break;
2060 case MTEHK_SAVEGAME: MenuClickSaveLoad(); break;
2061 case MTEHK_GENLAND: ToolbarScenGenLand(this); break;
2062 case MTEHK_GENTOWN: ToolbarScenGenTown(this); break;
2063 case MTEHK_GENINDUSTRY: ToolbarScenGenIndustry(this); break;
2064 case MTEHK_BUILD_ROAD: ToolbarScenBuildRoad(this); break;
2065 case MTEHK_BUILD_DOCKS: ToolbarScenBuildDocks(this); break;
2066 case MTEHK_BUILD_TREES: ToolbarScenPlantTrees(this); break;
2067 case MTEHK_SIGN: cbf = ToolbarScenPlaceSign(this); break;
2068 case MTEHK_MUSIC: ShowMusicWindow(); break;
2069 case MTEHK_LANDINFO: cbf = PlaceLandBlockInfo(); break;
2070 case MTEHK_SMALL_SCREENSHOT: MenuClickSmallScreenshot(); break;
2071 case MTEHK_ZOOMEDIN_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
2072 case MTEHK_DEFAULTZOOM_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
2073 case MTEHK_GIANT_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_WORLD); break;
2074 case MTEHK_ZOOM_IN: ToolbarZoomInClick(this); break;
2075 case MTEHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
2076 case MTEHK_TERRAFORM: ShowEditorTerraformToolbar(); break;
2077 case MTEHK_SMALLMAP: ShowSmallMap(); break;
2078 case MTEHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
2079 default: return ES_NOT_HANDLED;
2081 if (cbf != CBF_NONE) this->last_started_action = cbf;
2082 return ES_HANDLED;
2085 virtual void OnPlaceObject(Point pt, TileIndex tile)
2087 switch (this->last_started_action) {
2088 case CBF_PLACE_SIGN:
2089 PlaceProc_Sign(tile);
2090 break;
2092 case CBF_PLACE_LANDINFO:
2093 ShowLandInfo(tile);
2094 break;
2096 default: NOT_REACHED();
2100 virtual void OnTimeout()
2102 this->SetWidgetsLoweredState(false, WID_TE_DATE_BACKWARD, WID_TE_DATE_FORWARD, WIDGET_LIST_END);
2103 this->SetWidgetDirty(WID_TE_DATE_BACKWARD);
2104 this->SetWidgetDirty(WID_TE_DATE_FORWARD);
2107 virtual void OnTick()
2109 if (this->IsWidgetLowered(WID_TE_PAUSE) != !!_pause_mode) {
2110 this->ToggleWidgetLoweredState(WID_TE_PAUSE);
2111 this->SetDirty();
2114 if (this->IsWidgetLowered(WID_TE_FAST_FORWARD) != !!_fast_forward) {
2115 this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD);
2116 this->SetDirty();
2121 * Some data on this window has become invalid.
2122 * @param data Information about the changed data.
2123 * @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
2125 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2127 if (!gui_scope) return;
2128 if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, WID_TE_ZOOM_IN, WID_TE_ZOOM_OUT);
2131 virtual void OnQueryTextFinished(char *str)
2133 /* Was 'cancel' pressed? */
2134 if (str == NULL) return;
2136 int32 value;
2137 if (!StrEmpty(str)) {
2138 value = atoi(str);
2139 } else {
2140 /* An empty string means revert to the default */
2141 value = DEF_START_YEAR;
2143 SetStartingYear(value);
2145 this->SetDirty();
2148 static HotkeyList hotkeys;
2151 static const Hotkey scenedit_maintoolbar_hotkeys[] = {
2152 Hotkey ("pause", MTEHK_PAUSE, WKC_F1, WKC_PAUSE),
2153 Hotkey ("fastforward", MTEHK_FASTFORWARD),
2154 Hotkey ("settings", MTEHK_SETTINGS, WKC_F2),
2155 Hotkey ("saveload", MTEHK_SAVEGAME, WKC_F3),
2156 Hotkey ("gen_land", MTEHK_GENLAND, WKC_F4),
2157 Hotkey ("gen_town", MTEHK_GENTOWN, WKC_F5),
2158 Hotkey ("gen_industry", MTEHK_GENINDUSTRY, WKC_F6),
2159 Hotkey ("build_road", MTEHK_BUILD_ROAD, WKC_F7),
2160 Hotkey ("build_docks", MTEHK_BUILD_DOCKS, WKC_F8),
2161 Hotkey ("build_trees", MTEHK_BUILD_TREES, WKC_F9),
2162 Hotkey ("build_sign", MTEHK_SIGN, WKC_F10),
2163 Hotkey ("music", MTEHK_MUSIC, WKC_F11),
2164 Hotkey ("land_info", MTEHK_LANDINFO, WKC_F12),
2165 Hotkey ("small_screenshot", MTEHK_SMALL_SCREENSHOT, WKC_CTRL | 'S'),
2166 Hotkey ("zoomedin_screenshot", MTEHK_ZOOMEDIN_SCREENSHOT, WKC_CTRL | 'P'),
2167 Hotkey ("defaultzoom_screenshot", MTEHK_DEFAULTZOOM_SCREENSHOT, WKC_CTRL | 'D'),
2168 Hotkey ("giant_screenshot", MTEHK_GIANT_SCREENSHOT),
2169 Hotkey ("zoomin", MTEHK_ZOOM_IN, WKC_SHIFT | WKC_F5, WKC_NUM_PLUS, WKC_EQUALS, WKC_SHIFT | WKC_EQUALS),
2170 Hotkey ("zoomout", MTEHK_ZOOM_OUT, WKC_SHIFT | WKC_F6, WKC_NUM_MINUS, WKC_MINUS, WKC_SHIFT | WKC_MINUS),
2171 Hotkey ("terraform", MTEHK_TERRAFORM, 'L'),
2172 Hotkey ("smallmap", MTEHK_SMALLMAP, 'M'),
2173 Hotkey ("extra_viewport", MTEHK_EXTRA_VIEWPORT, 'V'),
2175 HotkeyList ScenarioEditorToolbarWindow::hotkeys("scenedit_maintoolbar", scenedit_maintoolbar_hotkeys);
2177 static const NWidgetPart _nested_toolb_scen_inner_widgets[] = {
2178 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_PAUSE), SetDataTip(SPR_IMG_PAUSE, STR_TOOLBAR_TOOLTIP_PAUSE_GAME),
2179 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_FAST_FORWARD), SetDataTip(SPR_IMG_FASTFORWARD, STR_TOOLBAR_TOOLTIP_FORWARD),
2180 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SETTINGS), SetDataTip(SPR_IMG_SETTINGS, STR_TOOLBAR_TOOLTIP_OPTIONS),
2181 NWidget(WWT_IMGBTN_2, COLOUR_GREY, WID_TE_SAVE), SetDataTip(SPR_IMG_SAVE, STR_SCENEDIT_TOOLBAR_TOOLTIP_SAVE_SCENARIO_LOAD_SCENARIO),
2182 NWidget(NWID_SPACER),
2183 NWidget(WWT_PANEL, COLOUR_GREY, WID_TE_SPACER), EndContainer(),
2184 NWidget(NWID_SPACER),
2185 NWidget(WWT_PANEL, COLOUR_GREY, WID_TE_DATE_PANEL),
2186 NWidget(NWID_HORIZONTAL), SetPIP(3, 2, 3),
2187 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_DATE_BACKWARD), SetDataTip(SPR_ARROW_DOWN, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD),
2188 NWidget(WWT_EMPTY, COLOUR_GREY, WID_TE_DATE), SetDataTip(STR_NULL, STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE),
2189 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_DATE_FORWARD), SetDataTip(SPR_ARROW_UP, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD),
2190 EndContainer(),
2191 EndContainer(),
2192 NWidget(NWID_SPACER),
2193 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SMALL_MAP), SetDataTip(SPR_IMG_SMALLMAP, STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY),
2194 NWidget(NWID_SPACER),
2195 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_IN), SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN),
2196 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_OUT), SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT),
2197 NWidget(NWID_SPACER),
2198 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_LAND_GENERATE), SetDataTip(SPR_IMG_LANDSCAPING, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION),
2199 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TOWN_GENERATE), SetDataTip(SPR_IMG_TOWN, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION),
2200 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_INDUSTRY), SetDataTip(SPR_IMG_INDUSTRY, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION),
2201 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ROADS), SetDataTip(SPR_IMG_BUILDROAD, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION),
2202 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_WATER), SetDataTip(SPR_IMG_BUILDWATER, STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS),
2203 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TREES), SetDataTip(SPR_IMG_PLANTTREES, STR_SCENEDIT_TOOLBAR_PLANT_TREES),
2204 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_SIGNS), SetDataTip(SPR_IMG_SIGN, STR_SCENEDIT_TOOLBAR_PLACE_SIGN),
2205 NWidget(NWID_SPACER),
2206 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_MUSIC_SOUND), SetDataTip(SPR_IMG_MUSIC, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW),
2207 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_HELP), SetDataTip(SPR_IMG_QUERY, STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION),
2208 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SWITCH_BAR), SetDataTip(SPR_IMG_SWITCH_TOOLBAR, STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR),
2211 static NWidgetBase *MakeScenarioToolbar(int *biggest_index)
2213 return MakeNWidgets(_nested_toolb_scen_inner_widgets, lengthof(_nested_toolb_scen_inner_widgets), biggest_index, new NWidgetScenarioToolbarContainer());
2216 static const NWidgetPart _nested_toolb_scen_widgets[] = {
2217 NWidgetFunction(MakeScenarioToolbar),
2220 static const WindowDesc _toolb_scen_desc(
2221 WDP_MANUAL, 0, 0,
2222 WC_MAIN_TOOLBAR, WC_NONE,
2223 WDF_NO_FOCUS,
2224 _nested_toolb_scen_widgets, lengthof(_nested_toolb_scen_widgets),
2225 NULL, &ScenarioEditorToolbarWindow::hotkeys
2228 /** Allocate the toolbar. */
2229 void AllocateToolbar()
2231 /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
2232 _last_built_roadtype = ROADTYPE_ROAD;
2234 if (_game_mode == GM_EDITOR) {
2235 new ScenarioEditorToolbarWindow(&_toolb_scen_desc);
2236 } else {
2237 new MainToolbarWindow(&_toolb_normal_desc);