Add non-animated SSSE3 blitter
[openttd/fttd.git] / src / toolbar_gui.cpp
blobf4cb584b1ed6c8457a8676d552a18e464865d68a
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"
50 #include "widgets/toolbar_widget.h"
52 #include "network/network.h"
53 #include "network/network_gui.h"
54 #include "network/network_func.h"
57 RailType _last_built_railtype;
58 RoadType _last_built_roadtype;
60 static ScreenshotType _confirmed_screenshot_type; ///< Screenshot type the current query is about to confirm.
62 /** Toobar modes */
63 enum ToolbarMode {
64 TB_NORMAL,
65 TB_UPPER,
66 TB_LOWER
69 /** Callback functions. */
70 enum CallBackFunction {
71 CBF_NONE,
72 CBF_PLACE_SIGN,
73 CBF_PLACE_LANDINFO,
76 /**
77 * Drop down list entry for showing a checked/unchecked toggle item.
79 class DropDownListCheckedItem : public DropDownListStringItem {
80 uint checkmark_width;
81 public:
82 bool checked;
84 DropDownListCheckedItem(StringID string, int result, bool masked, bool checked) : DropDownListStringItem(string, result, masked), checked(checked)
86 this->checkmark_width = GetStringBoundingBox(STR_JUST_CHECKMARK).width + 3;
89 virtual ~DropDownListCheckedItem() {}
91 uint Width() const
93 return DropDownListStringItem::Width() + this->checkmark_width;
96 void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
98 bool rtl = _current_text_dir == TD_RTL;
99 if (this->checked) {
100 DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, STR_JUST_CHECKMARK, sel ? TC_WHITE : TC_BLACK);
102 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);
107 * Drop down list entry for showing a company entry, with companies 'blob'.
109 class DropDownListCompanyItem : public DropDownListItem {
110 Dimension icon_size;
111 public:
112 bool greyed;
114 DropDownListCompanyItem(int result, bool masked, bool greyed) : DropDownListItem(result, masked), greyed(greyed)
116 this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
119 virtual ~DropDownListCompanyItem() {}
121 bool Selectable() const
123 return true;
126 uint Width() const
128 CompanyID company = (CompanyID)this->result;
129 SetDParam(0, company);
130 SetDParam(1, company);
131 return GetStringBoundingBox(STR_COMPANY_NAME_COMPANY_NUM).width + this->icon_size.width + 3;
134 uint Height(uint width) const
136 return max(this->icon_size.height + 2U, (uint)FONT_HEIGHT_NORMAL);
139 void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
141 CompanyID company = (CompanyID)this->result;
142 bool rtl = _current_text_dir == TD_RTL;
144 /* It's possible the company is deleted while the dropdown is open */
145 if (!Company::IsValidID(company)) return;
147 int icon_offset = (bottom - top - icon_size.height) / 2;
148 int text_offset = (bottom - top - FONT_HEIGHT_NORMAL) / 2;
150 DrawCompanyIcon(company, rtl ? right - this->icon_size.width - WD_FRAMERECT_RIGHT : left + WD_FRAMERECT_LEFT, top + icon_offset);
152 SetDParam(0, company);
153 SetDParam(1, company);
154 TextColour col;
155 if (this->greyed) {
156 col = (sel ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
157 } else {
158 col = sel ? TC_WHITE : TC_BLACK;
160 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);
165 * Pop up a generic text only menu.
166 * @param w Toolbar
167 * @param widget Toolbar button
168 * @param list List of items
169 * @param def Default item
171 static void PopupMainToolbMenu(Window *w, int widget, DropDownList *list, int def)
173 ShowDropDownList(w, list, def, widget, 0, true, true);
174 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
178 * Pop up a generic text only menu.
179 * @param w Toolbar
180 * @param widget Toolbar button
181 * @param string String for the first item in the menu
182 * @param count Number of items in the menu
184 static void PopupMainToolbMenu(Window *w, int widget, StringID string, int count)
186 DropDownList *list = new DropDownList();
187 for (int i = 0; i < count; i++) {
188 *list->Append() = new DropDownListStringItem(string + i, i, false);
190 PopupMainToolbMenu(w, widget, list, 0);
193 /** Enum for the Company Toolbar's network related buttons */
194 static const int CTMN_CLIENT_LIST = -1; ///< Show the client list
195 static const int CTMN_NEW_COMPANY = -2; ///< Create a new company
196 static const int CTMN_SPECTATE = -3; ///< Become spectator
197 static const int CTMN_SPECTATOR = -4; ///< Show a company window as spectator
200 * Pop up a generic company list menu.
201 * @param w The toolbar window.
202 * @param widget The button widget id.
203 * @param grey A bitbask of which items to mark as disabled.
204 * @param include_spectator If true, a spectator option is included in the list.
206 static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0, bool include_spectator = false)
208 DropDownList *list = new DropDownList();
210 #ifdef ENABLE_NETWORK
211 if (_networking) {
212 if (widget == WID_TN_COMPANIES) {
213 /* Add the client list button for the companies menu */
214 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false);
217 if (include_spectator) {
218 if (widget == WID_TN_COMPANIES) {
219 if (_local_company == COMPANY_SPECTATOR) {
220 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached());
221 } else {
222 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, NetworkMaxSpectatorsReached());
224 } else {
225 *list->Append() = new DropDownListStringItem(STR_NETWORK_TOOLBAR_LIST_SPECTATOR, CTMN_SPECTATOR, false);
229 #endif /* ENABLE_NETWORK */
231 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
232 if (!Company::IsValidID(c)) continue;
233 *list->Append() = new DropDownListCompanyItem(c, false, HasBit(grey, c));
236 PopupMainToolbMenu(w, widget, list, _local_company == COMPANY_SPECTATOR ? CTMN_CLIENT_LIST : (int)_local_company);
240 static ToolbarMode _toolbar_mode;
242 static CallBackFunction SelectSignTool()
244 if (_cursor.sprite == SPR_CURSOR_SIGN) {
245 ResetObjectToPlace();
246 return CBF_NONE;
247 } else {
248 SetObjectToPlace(SPR_CURSOR_SIGN, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0);
249 return CBF_PLACE_SIGN;
253 /* --- Pausing --- */
255 static CallBackFunction ToolbarPauseClick(Window *w)
257 if (_networking && !_network_server) return CBF_NONE; // only server can pause the game
259 if (DoCommandP(0, PM_PAUSED_NORMAL, _pause_mode == PM_UNPAUSED, CMD_PAUSE)) {
260 if (_settings_client.sound.confirm) SndPlayFx(SND_15_BEEP);
262 return CBF_NONE;
266 * Toggle fast forward mode.
268 * @param w Unused.
269 * @return #CBF_NONE
271 static CallBackFunction ToolbarFastForwardClick(Window *w)
273 _fast_forward ^= true;
274 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
275 return CBF_NONE;
279 * Game Option button menu entries.
281 enum OptionMenuEntries {
282 OME_GAMEOPTIONS,
283 OME_SETTINGS,
284 OME_SCRIPT_SETTINGS,
285 OME_NEWGRFSETTINGS,
286 OME_TRANSPARENCIES,
287 OME_SHOW_TOWNNAMES,
288 OME_SHOW_STATIONNAMES,
289 OME_SHOW_WAYPOINTNAMES,
290 OME_SHOW_SIGNS,
291 OME_SHOW_COMPETITOR_SIGNS,
292 OME_FULL_ANIMATION,
293 OME_FULL_DETAILS,
294 OME_TRANSPARENTBUILDINGS,
295 OME_SHOW_STATIONSIGNS,
299 * Handle click on Options button in toolbar.
301 * @param w parent window the shown Drop down list is attached to.
302 * @return #CBF_NONE
304 static CallBackFunction ToolbarOptionsClick(Window *w)
306 DropDownList *list = new DropDownList();
307 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS, OME_GAMEOPTIONS, false);
308 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS, OME_SETTINGS, false);
309 /* Changes to the per-AI settings don't get send from the server to the clients. Clients get
310 * the settings once they join but never update it. As such don't show the window at all
311 * to network clients. */
312 if (!_networking || _network_server) *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS, OME_SCRIPT_SETTINGS, false);
313 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS, OME_NEWGRFSETTINGS, false);
314 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS, OME_TRANSPARENCIES, false);
315 *list->Append() = new DropDownListItem(-1, false);
316 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED, OME_SHOW_TOWNNAMES, false, HasBit(_display_opt, DO_SHOW_TOWN_NAMES));
317 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED, OME_SHOW_STATIONNAMES, false, HasBit(_display_opt, DO_SHOW_STATION_NAMES));
318 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED, OME_SHOW_WAYPOINTNAMES, false, HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES));
319 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED, OME_SHOW_SIGNS, false, HasBit(_display_opt, DO_SHOW_SIGNS));
320 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS, OME_SHOW_COMPETITOR_SIGNS, false, HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS));
321 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION, OME_FULL_ANIMATION, false, HasBit(_display_opt, DO_FULL_ANIMATION));
322 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL, OME_FULL_DETAILS, false, HasBit(_display_opt, DO_FULL_DETAIL));
323 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS, OME_TRANSPARENTBUILDINGS, false, IsTransparencySet(TO_HOUSES));
324 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS, OME_SHOW_STATIONSIGNS, false, IsTransparencySet(TO_SIGNS));
326 ShowDropDownList(w, list, 0, WID_TN_SETTINGS, 140, true, true);
327 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
328 return CBF_NONE;
332 * Handle click on one of the entries in the Options button menu.
334 * @param index Index being clicked.
335 * @return #CBF_NONE
337 static CallBackFunction MenuClickSettings(int index)
339 switch (index) {
340 case OME_GAMEOPTIONS: ShowGameOptions(); return CBF_NONE;
341 case OME_SETTINGS: ShowGameSettings(); return CBF_NONE;
342 case OME_SCRIPT_SETTINGS: ShowAIConfigWindow(); return CBF_NONE;
343 case OME_NEWGRFSETTINGS: ShowNewGRFSettings(!_networking && _settings_client.gui.UserIsAllowedToChangeNewGRFs(), true, true, &_grfconfig); return CBF_NONE;
344 case OME_TRANSPARENCIES: ShowTransparencyToolbar(); break;
346 case OME_SHOW_TOWNNAMES: ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES); break;
347 case OME_SHOW_STATIONNAMES: ToggleBit(_display_opt, DO_SHOW_STATION_NAMES); break;
348 case OME_SHOW_WAYPOINTNAMES: ToggleBit(_display_opt, DO_SHOW_WAYPOINT_NAMES); break;
349 case OME_SHOW_SIGNS: ToggleBit(_display_opt, DO_SHOW_SIGNS); break;
350 case OME_SHOW_COMPETITOR_SIGNS:
351 ToggleBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS);
352 InvalidateWindowClassesData(WC_SIGN_LIST, -1);
353 break;
354 case OME_FULL_ANIMATION: ToggleBit(_display_opt, DO_FULL_ANIMATION); break;
355 case OME_FULL_DETAILS: ToggleBit(_display_opt, DO_FULL_DETAIL); break;
356 case OME_TRANSPARENTBUILDINGS: ToggleTransparency(TO_HOUSES); break;
357 case OME_SHOW_STATIONSIGNS: ToggleTransparency(TO_SIGNS); break;
359 MarkWholeScreenDirty();
360 return CBF_NONE;
364 * SaveLoad entries in scenario editor mode.
366 enum SaveLoadEditorMenuEntries {
367 SLEME_SAVE_SCENARIO = 0,
368 SLEME_LOAD_SCENARIO,
369 SLEME_SAVE_HEIGHTMAP,
370 SLEME_LOAD_HEIGHTMAP,
371 SLEME_EXIT_TOINTRO,
372 SLEME_EXIT_GAME = 6,
373 SLEME_MENUCOUNT,
377 * SaveLoad entries in normal game mode.
379 enum SaveLoadNormalMenuEntries {
380 SLNME_SAVE_GAME = 0,
381 SLNME_LOAD_GAME,
382 SLNME_EXIT_TOINTRO,
383 SLNME_EXIT_GAME = 4,
384 SLNME_MENUCOUNT,
388 * Handle click on Save button in toolbar in normal game mode.
390 * @param w parent window the shown save dialogue is attached to.
391 * @return #CBF_NONE
393 static CallBackFunction ToolbarSaveClick(Window *w)
395 PopupMainToolbMenu(w, WID_TN_SAVE, STR_FILE_MENU_SAVE_GAME, SLNME_MENUCOUNT);
396 return CBF_NONE;
400 * Handle click on SaveLoad button in toolbar in the scenario editor.
402 * @param w parent window the shown save dialogue is attached to.
403 * @return #CBF_NONE
405 static CallBackFunction ToolbarScenSaveOrLoad(Window *w)
407 PopupMainToolbMenu(w, WID_TE_SAVE, STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO, SLEME_MENUCOUNT);
408 return CBF_NONE;
412 * Handle click on one of the entries in the SaveLoad menu.
414 * @param index Index being clicked.
415 * @return #CBF_NONE
417 static CallBackFunction MenuClickSaveLoad(int index = 0)
419 if (_game_mode == GM_EDITOR) {
420 switch (index) {
421 case SLEME_SAVE_SCENARIO: ShowSaveLoadDialog(SLD_SAVE_SCENARIO); break;
422 case SLEME_LOAD_SCENARIO: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break;
423 case SLEME_SAVE_HEIGHTMAP: ShowSaveLoadDialog(SLD_SAVE_HEIGHTMAP); break;
424 case SLEME_LOAD_HEIGHTMAP: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break;
425 case SLEME_EXIT_TOINTRO: AskExitToGameMenu(); break;
426 case SLEME_EXIT_GAME: HandleExitGameRequest(); break;
428 } else {
429 switch (index) {
430 case SLNME_SAVE_GAME: ShowSaveLoadDialog(SLD_SAVE_GAME); break;
431 case SLNME_LOAD_GAME: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
432 case SLNME_EXIT_TOINTRO: AskExitToGameMenu(); break;
433 case SLNME_EXIT_GAME: HandleExitGameRequest(); break;
436 return CBF_NONE;
439 /* --- Map button menu --- */
441 enum MapMenuEntries {
442 MME_SHOW_SMALLMAP = 0,
443 MME_SHOW_EXTRAVIEWPORTS,
444 MME_SHOW_LINKGRAPH,
445 MME_SHOW_SIGNLISTS,
446 MME_SHOW_TOWNDIRECTORY,
447 MME_SHOW_INDUSTRYDIRECTORY,
450 static CallBackFunction ToolbarMapClick(Window *w)
452 DropDownList *list = new DropDownList();
453 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false);
454 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false);
455 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_LINGRAPH_LEGEND, MME_SHOW_LINKGRAPH, false);
456 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false);
457 PopupMainToolbMenu(w, WID_TN_SMALL_MAP, list, 0);
458 return CBF_NONE;
461 static CallBackFunction ToolbarScenMapTownDir(Window *w)
463 DropDownList *list = new DropDownList();
464 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false);
465 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false);
466 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false);
467 *list->Append() = new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY, MME_SHOW_TOWNDIRECTORY, false);
468 *list->Append() = new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, MME_SHOW_INDUSTRYDIRECTORY, false);
469 PopupMainToolbMenu(w, WID_TE_SMALL_MAP, list, 0);
470 return CBF_NONE;
474 * Handle click on one of the entries in the Map menu.
476 * @param index Index being clicked.
477 * @return #CBF_NONE
479 static CallBackFunction MenuClickMap(int index)
481 switch (index) {
482 case MME_SHOW_SMALLMAP: ShowSmallMap(); break;
483 case MME_SHOW_EXTRAVIEWPORTS: ShowExtraViewPortWindow(); break;
484 case MME_SHOW_LINKGRAPH: ShowLinkGraphLegend(); break;
485 case MME_SHOW_SIGNLISTS: ShowSignList(); break;
486 case MME_SHOW_TOWNDIRECTORY: ShowTownDirectory(); break;
487 case MME_SHOW_INDUSTRYDIRECTORY: ShowIndustryDirectory(); break;
489 return CBF_NONE;
492 /* --- Town button menu --- */
494 static CallBackFunction ToolbarTownClick(Window *w)
496 PopupMainToolbMenu(w, WID_TN_TOWNS, STR_TOWN_MENU_TOWN_DIRECTORY, (_settings_game.economy.found_town == TF_FORBIDDEN) ? 1 : 2);
497 return CBF_NONE;
501 * Handle click on one of the entries in the Town menu.
503 * @param index Index being clicked.
504 * @return #CBF_NONE
506 static CallBackFunction MenuClickTown(int index)
508 switch (index) {
509 case 0: ShowTownDirectory(); break;
510 case 1: // setting could be changed when the dropdown was open
511 if (_settings_game.economy.found_town != TF_FORBIDDEN) ShowFoundTownWindow();
512 break;
514 return CBF_NONE;
517 /* --- Subidies button menu --- */
519 static CallBackFunction ToolbarSubsidiesClick(Window *w)
521 PopupMainToolbMenu(w, WID_TN_SUBSIDIES, STR_SUBSIDIES_MENU_SUBSIDIES, 1);
522 return CBF_NONE;
526 * Handle click on the entry in the Subsidies menu.
528 * @param index Unused.
529 * @return #CBF_NONE
531 static CallBackFunction MenuClickSubsidies(int index)
533 switch (index) {
534 case 0: ShowSubsidiesList(); break;
536 return CBF_NONE;
539 /* --- Stations button menu --- */
541 static CallBackFunction ToolbarStationsClick(Window *w)
543 PopupMainCompanyToolbMenu(w, WID_TN_STATIONS);
544 return CBF_NONE;
548 * Handle click on the entry in the Stations menu
550 * @param index CompanyID to show station list for
551 * @return #CBF_NONE
553 static CallBackFunction MenuClickStations(int index)
555 ShowCompanyStations((CompanyID)index);
556 return CBF_NONE;
559 /* --- Finances button menu --- */
561 static CallBackFunction ToolbarFinancesClick(Window *w)
563 PopupMainCompanyToolbMenu(w, WID_TN_FINANCES);
564 return CBF_NONE;
568 * Handle click on the entry in the finances overview menu.
570 * @param index CompanyID to show finances for.
571 * @return #CBF_NONE
573 static CallBackFunction MenuClickFinances(int index)
575 ShowCompanyFinances((CompanyID)index);
576 return CBF_NONE;
579 /* --- Company's button menu --- */
581 static CallBackFunction ToolbarCompaniesClick(Window *w)
583 PopupMainCompanyToolbMenu(w, WID_TN_COMPANIES, 0, true);
584 return CBF_NONE;
588 * Handle click on the entry in the Company menu.
590 * @param index Menu entry to handle.
591 * @return #CBF_NONE
593 static CallBackFunction MenuClickCompany(int index)
595 #ifdef ENABLE_NETWORK
596 if (_networking) {
597 switch (index) {
598 case CTMN_CLIENT_LIST:
599 ShowClientList();
600 return CBF_NONE;
602 case CTMN_NEW_COMPANY:
603 if (_network_server) {
604 DoCommandP(0, 0, _network_own_client_id, CMD_COMPANY_CTRL);
605 } else {
606 NetworkSendCommand(0, 0, 0, CMD_COMPANY_CTRL, NULL, NULL, _local_company);
608 return CBF_NONE;
610 case CTMN_SPECTATE:
611 if (_network_server) {
612 NetworkServerDoMove(CLIENT_ID_SERVER, COMPANY_SPECTATOR);
613 MarkWholeScreenDirty();
614 } else {
615 NetworkClientRequestMove(COMPANY_SPECTATOR);
617 return CBF_NONE;
620 #endif /* ENABLE_NETWORK */
621 ShowCompany((CompanyID)index);
622 return CBF_NONE;
625 /* --- Story button menu --- */
627 static CallBackFunction ToolbarStoryClick(Window *w)
629 PopupMainCompanyToolbMenu(w, WID_TN_STORY, 0, true);
630 return CBF_NONE;
634 * Handle click on the entry in the Story menu
636 * @param index CompanyID to show story book for
637 * @return #CBF_NONE
639 static CallBackFunction MenuClickStory(int index)
641 ShowStoryBook(index == CTMN_SPECTATOR ? INVALID_COMPANY : (CompanyID)index);
642 return CBF_NONE;
645 /* --- Goal button menu --- */
647 static CallBackFunction ToolbarGoalClick(Window *w)
649 PopupMainCompanyToolbMenu(w, WID_TN_GOAL, 0, true);
650 return CBF_NONE;
654 * Handle click on the entry in the Goal menu
656 * @param index CompanyID to show story book for
657 * @return #CBF_NONE
659 static CallBackFunction MenuClickGoal(int index)
661 ShowGoalsList(index == CTMN_SPECTATOR ? INVALID_COMPANY : (CompanyID)index);
662 return CBF_NONE;
665 /* --- Graphs button menu --- */
667 static CallBackFunction ToolbarGraphsClick(Window *w)
669 PopupMainToolbMenu(w, WID_TN_GRAPHS, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, (_toolbar_mode == TB_NORMAL) ? 6 : 8);
670 return CBF_NONE;
674 * Handle click on the entry in the Graphs menu.
676 * @param index Graph to show.
677 * @return #CBF_NONE
679 static CallBackFunction MenuClickGraphs(int index)
681 switch (index) {
682 case 0: ShowOperatingProfitGraph(); break;
683 case 1: ShowIncomeGraph(); break;
684 case 2: ShowDeliveredCargoGraph(); break;
685 case 3: ShowPerformanceHistoryGraph(); break;
686 case 4: ShowCompanyValueGraph(); break;
687 case 5: ShowCargoPaymentRates(); break;
688 /* functions for combined graphs/league button */
689 case 6: ShowCompanyLeagueTable(); break;
690 case 7: ShowPerformanceRatingDetail(); break;
692 return CBF_NONE;
695 /* --- League button menu --- */
697 static CallBackFunction ToolbarLeagueClick(Window *w)
699 PopupMainToolbMenu(w, WID_TN_LEAGUE, STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE, _networking ? 2 : 3);
700 return CBF_NONE;
704 * Handle click on the entry in the CompanyLeague menu.
706 * @param index Menu entry number.
707 * @return #CBF_NONE
709 static CallBackFunction MenuClickLeague(int index)
711 switch (index) {
712 case 0: ShowCompanyLeagueTable(); break;
713 case 1: ShowPerformanceRatingDetail(); break;
714 case 2: ShowHighscoreTable(); break;
716 return CBF_NONE;
719 /* --- Industries button menu --- */
721 static CallBackFunction ToolbarIndustryClick(Window *w)
723 /* Disable build-industry menu if we are a spectator */
724 PopupMainToolbMenu(w, WID_TN_INDUSTRIES, STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, (_local_company == COMPANY_SPECTATOR) ? 2 : 3);
725 return CBF_NONE;
729 * Handle click on the entry in the Industry menu.
731 * @param index Menu entry number.
732 * @return #CBF_NONE
734 static CallBackFunction MenuClickIndustry(int index)
736 switch (index) {
737 case 0: ShowIndustryDirectory(); break;
738 case 1: ShowIndustryCargoesWindow(); break;
739 case 2: ShowBuildIndustryWindow(); break;
741 return CBF_NONE;
744 /* --- Trains button menu + 1 helper function for all vehicles. --- */
746 static void ToolbarVehicleClick(Window *w, VehicleType veh)
748 const Vehicle *v;
749 int dis = ~0;
751 FOR_ALL_VEHICLES(v) {
752 if (v->type == veh && v->IsPrimaryVehicle()) ClrBit(dis, v->owner);
754 PopupMainCompanyToolbMenu(w, WID_TN_VEHICLE_START + veh, dis);
758 static CallBackFunction ToolbarTrainClick(Window *w)
760 ToolbarVehicleClick(w, VEH_TRAIN);
761 return CBF_NONE;
765 * Handle click on the entry in the Train menu.
767 * @param index CompanyID to show train list for.
768 * @return #CBF_NONE
770 static CallBackFunction MenuClickShowTrains(int index)
772 ShowVehicleListWindow((CompanyID)index, VEH_TRAIN);
773 return CBF_NONE;
776 /* --- Road vehicle button menu --- */
778 static CallBackFunction ToolbarRoadClick(Window *w)
780 ToolbarVehicleClick(w, VEH_ROAD);
781 return CBF_NONE;
785 * Handle click on the entry in the Road Vehicles menu.
787 * @param index CompanyID to show road vehicles list for.
788 * @return #CBF_NONE
790 static CallBackFunction MenuClickShowRoad(int index)
792 ShowVehicleListWindow((CompanyID)index, VEH_ROAD);
793 return CBF_NONE;
796 /* --- Ship button menu --- */
798 static CallBackFunction ToolbarShipClick(Window *w)
800 ToolbarVehicleClick(w, VEH_SHIP);
801 return CBF_NONE;
805 * Handle click on the entry in the Ships menu.
807 * @param index CompanyID to show ship list for.
808 * @return #CBF_NONE
810 static CallBackFunction MenuClickShowShips(int index)
812 ShowVehicleListWindow((CompanyID)index, VEH_SHIP);
813 return CBF_NONE;
816 /* --- Aircraft button menu --- */
818 static CallBackFunction ToolbarAirClick(Window *w)
820 ToolbarVehicleClick(w, VEH_AIRCRAFT);
821 return CBF_NONE;
825 * Handle click on the entry in the Aircraft menu.
827 * @param index CompanyID to show aircraft list for.
828 * @return #CBF_NONE
830 static CallBackFunction MenuClickShowAir(int index)
832 ShowVehicleListWindow((CompanyID)index, VEH_AIRCRAFT);
833 return CBF_NONE;
836 /* --- Zoom in button --- */
838 static CallBackFunction ToolbarZoomInClick(Window *w)
840 if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
841 w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)WID_TE_ZOOM_IN : (byte)WID_TN_ZOOM_IN);
842 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
844 return CBF_NONE;
847 /* --- Zoom out button --- */
849 static CallBackFunction ToolbarZoomOutClick(Window *w)
851 if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) {
852 w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)WID_TE_ZOOM_OUT : (byte)WID_TN_ZOOM_OUT);
853 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
855 return CBF_NONE;
858 /* --- Rail button menu --- */
860 static CallBackFunction ToolbarBuildRailClick(Window *w)
862 ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, WID_TN_RAILS, 140, true, true);
863 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
864 return CBF_NONE;
868 * Handle click on the entry in the Build Rail menu.
870 * @param index RailType to show the build toolbar for.
871 * @return #CBF_NONE
873 static CallBackFunction MenuClickBuildRail(int index)
875 _last_built_railtype = (RailType)index;
876 ShowBuildRailToolbar(_last_built_railtype);
877 return CBF_NONE;
880 /* --- Road button menu --- */
882 static CallBackFunction ToolbarBuildRoadClick(Window *w)
884 const Company *c = Company::Get(_local_company);
885 DropDownList *list = new DropDownList();
887 /* Road is always visible and available. */
888 *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION, ROADTYPE_ROAD, false);
890 /* Tram is only visible when there will be a tram, and available when that has been introduced. */
891 Engine *e;
892 FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
893 if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
894 if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
896 *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION, ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM));
897 break;
899 ShowDropDownList(w, list, _last_built_roadtype, WID_TN_ROADS, 140, true, true);
900 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
901 return CBF_NONE;
905 * Handle click on the entry in the Build Road menu.
907 * @param index RoadType to show the build toolbar for.
908 * @return #CBF_NONE
910 static CallBackFunction MenuClickBuildRoad(int index)
912 _last_built_roadtype = (RoadType)index;
913 ShowBuildRoadToolbar(_last_built_roadtype);
914 return CBF_NONE;
917 /* --- Water button menu --- */
919 static CallBackFunction ToolbarBuildWaterClick(Window *w)
921 PopupMainToolbMenu(w, WID_TN_WATER, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION, 1);
922 return CBF_NONE;
926 * Handle click on the entry in the Build Waterways menu.
928 * @param index Unused.
929 * @return #CBF_NONE
931 static CallBackFunction MenuClickBuildWater(int index)
933 ShowBuildDocksToolbar();
934 return CBF_NONE;
937 /* --- Airport button menu --- */
939 static CallBackFunction ToolbarBuildAirClick(Window *w)
941 PopupMainToolbMenu(w, WID_TN_AIR, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION, 1);
942 return CBF_NONE;
946 * Handle click on the entry in the Build Air menu.
948 * @param index Unused.
949 * @return #CBF_NONE
951 static CallBackFunction MenuClickBuildAir(int index)
953 ShowBuildAirToolbar();
954 return CBF_NONE;
957 /* --- Forest button menu --- */
959 static CallBackFunction ToolbarForestClick(Window *w)
961 PopupMainToolbMenu(w, WID_TN_LANDSCAPE, STR_LANDSCAPING_MENU_LANDSCAPING, 3);
962 return CBF_NONE;
966 * Handle click on the entry in the landscaping menu.
968 * @param index Menu entry clicked.
969 * @return #CBF_NONE
971 static CallBackFunction MenuClickForest(int index)
973 switch (index) {
974 case 0: ShowTerraformToolbar(); break;
975 case 1: ShowBuildTreesToolbar(); break;
976 case 2: return SelectSignTool();
978 return CBF_NONE;
981 /* --- Music button menu --- */
983 static CallBackFunction ToolbarMusicClick(Window *w)
985 PopupMainToolbMenu(w, WID_TN_MUSIC_SOUND, STR_TOOLBAR_SOUND_MUSIC, 1);
986 return CBF_NONE;
990 * Handle click on the entry in the Music menu.
992 * @param index Unused.
993 * @return #CBF_NONE
995 static CallBackFunction MenuClickMusicWindow(int index)
997 ShowMusicWindow();
998 return CBF_NONE;
1001 /* --- Newspaper button menu --- */
1003 static CallBackFunction ToolbarNewspaperClick(Window *w)
1005 PopupMainToolbMenu(w, WID_TN_MESSAGES, STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT, 2);
1006 return CBF_NONE;
1010 * Handle click on the entry in the Newspaper menu.
1012 * @param index Menu entry clicked.
1013 * @return #CBF_NONE
1015 static CallBackFunction MenuClickNewspaper(int index)
1017 switch (index) {
1018 case 0: ShowLastNewsMessage(); break;
1019 case 1: ShowMessageHistory(); break;
1021 return CBF_NONE;
1024 /* --- Help button menu --- */
1026 static CallBackFunction PlaceLandBlockInfo()
1028 if (_cursor.sprite == SPR_CURSOR_QUERY) {
1029 ResetObjectToPlace();
1030 return CBF_NONE;
1031 } else {
1032 SetObjectToPlace(SPR_CURSOR_QUERY, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0);
1033 return CBF_PLACE_LANDINFO;
1037 static CallBackFunction ToolbarHelpClick(Window *w)
1039 PopupMainToolbMenu(w, WID_TN_HELP, STR_ABOUT_MENU_LAND_BLOCK_INFO, _settings_client.gui.newgrf_developer_tools ? 12 : 9);
1040 return CBF_NONE;
1043 static void MenuClickSmallScreenshot()
1045 MakeScreenshot(SC_VIEWPORT, NULL);
1049 * Callback on the confirmation window for huge screenshots.
1050 * @param w Window with viewport
1051 * @param confirmed true on confirmation
1053 static void ScreenshotConfirmCallback(Window *w, bool confirmed)
1055 if (confirmed) MakeScreenshot(_confirmed_screenshot_type, NULL);
1059 * Make a screenshot of the world.
1060 * Ask for confirmation if the screenshot will be huge.
1061 * @param t Screenshot type: World or viewport screenshot
1063 static void MenuClickLargeWorldScreenshot(ScreenshotType t)
1065 ViewPort vp;
1066 SetupScreenshotViewport(t, &vp);
1067 if (vp.width * vp.height > 8192 * 8192) {
1068 /* Ask for confirmation */
1069 SetDParam(0, vp.width);
1070 SetDParam(1, vp.height);
1071 _confirmed_screenshot_type = t;
1072 ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, NULL, ScreenshotConfirmCallback);
1073 } else {
1074 /* Less than 4M pixels, just do it */
1075 MakeScreenshot(t, NULL);
1080 * Toggle drawing of sprites' bounding boxes.
1081 * @note has only an effect when newgrf_developer_tools are active.
1083 * Function is found here and not in viewport.cpp in order to avoid
1084 * importing the settings structs to there.
1086 void ToggleBoundingBoxes()
1088 extern bool _draw_bounding_boxes;
1089 /* Always allow to toggle them off */
1090 if (_settings_client.gui.newgrf_developer_tools || _draw_bounding_boxes) {
1091 _draw_bounding_boxes = !_draw_bounding_boxes;
1092 MarkWholeScreenDirty();
1097 * Toggle drawing of the dirty blocks.
1098 * @note has only an effect when newgrf_developer_tools are active.
1100 * Function is found here and not in viewport.cpp in order to avoid
1101 * importing the settings structs to there.
1103 void ToggleDirtyBlocks()
1105 extern bool _draw_dirty_blocks;
1106 /* Always allow to toggle them off */
1107 if (_settings_client.gui.newgrf_developer_tools || _draw_dirty_blocks) {
1108 _draw_dirty_blocks = !_draw_dirty_blocks;
1109 MarkWholeScreenDirty();
1114 * Set the starting year for a scenario.
1115 * @param year New starting year.
1117 void SetStartingYear(Year year)
1119 _settings_game.game_creation.starting_year = Clamp(year, MIN_YEAR, MAX_YEAR);
1120 Date new_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
1121 /* If you open a savegame as scenario there may already be link graphs.*/
1122 LinkGraphSchedule::Instance()->ShiftDates(new_date - _date);
1123 SetDate(new_date, 0);
1127 * Choose the proper callback function for the main toolbar's help menu.
1128 * @param index The menu index which was selected.
1129 * @return CBF_NONE
1131 static CallBackFunction MenuClickHelp(int index)
1133 switch (index) {
1134 case 0: return PlaceLandBlockInfo();
1135 case 2: IConsoleSwitch(); break;
1136 case 3: ShowAIDebugWindow(); break;
1137 case 4: MenuClickSmallScreenshot(); break;
1138 case 5: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
1139 case 6: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
1140 case 7: MenuClickLargeWorldScreenshot(SC_WORLD); break;
1141 case 8: ShowAboutWindow(); break;
1142 case 9: ShowSpriteAlignerWindow(); break;
1143 case 10: ToggleBoundingBoxes(); break;
1144 case 11: ToggleDirtyBlocks(); break;
1146 return CBF_NONE;
1149 /* --- Switch toolbar button --- */
1151 static CallBackFunction ToolbarSwitchClick(Window *w)
1153 if (_toolbar_mode != TB_LOWER) {
1154 _toolbar_mode = TB_LOWER;
1155 } else {
1156 _toolbar_mode = TB_UPPER;
1159 w->ReInit();
1160 w->SetWidgetLoweredState(WID_TN_SWITCH_BAR, _toolbar_mode == TB_LOWER);
1161 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1162 return CBF_NONE;
1165 /* --- Scenario editor specific handlers. */
1168 * Called when clicking at the date panel of the scenario editor toolbar.
1170 static CallBackFunction ToolbarScenDatePanel(Window *w)
1172 SetDParam(0, _settings_game.game_creation.starting_year);
1173 ShowQueryString(STR_JUST_INT, STR_MAPGEN_START_DATE_QUERY_CAPT, 8, w, CS_NUMERAL, QSF_ENABLE_DEFAULT);
1174 _left_button_clicked = false;
1175 return CBF_NONE;
1178 static CallBackFunction ToolbarScenDateBackward(Window *w)
1180 /* don't allow too fast scrolling */
1181 if (!(w->flags & WF_TIMEOUT) || w->timeout_timer <= 1) {
1182 w->HandleButtonClick(WID_TE_DATE_BACKWARD);
1183 w->SetDirty();
1185 SetStartingYear(_settings_game.game_creation.starting_year - 1);
1187 _left_button_clicked = false;
1188 return CBF_NONE;
1191 static CallBackFunction ToolbarScenDateForward(Window *w)
1193 /* don't allow too fast scrolling */
1194 if (!(w->flags & WF_TIMEOUT) || w->timeout_timer <= 1) {
1195 w->HandleButtonClick(WID_TE_DATE_FORWARD);
1196 w->SetDirty();
1198 SetStartingYear(_settings_game.game_creation.starting_year + 1);
1200 _left_button_clicked = false;
1201 return CBF_NONE;
1204 static CallBackFunction ToolbarScenGenLand(Window *w)
1206 w->HandleButtonClick(WID_TE_LAND_GENERATE);
1207 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1209 ShowEditorTerraformToolbar();
1210 return CBF_NONE;
1214 static CallBackFunction ToolbarScenGenTown(Window *w)
1216 w->HandleButtonClick(WID_TE_TOWN_GENERATE);
1217 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1218 ShowFoundTownWindow();
1219 return CBF_NONE;
1222 static CallBackFunction ToolbarScenGenIndustry(Window *w)
1224 w->HandleButtonClick(WID_TE_INDUSTRY);
1225 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1226 ShowBuildIndustryWindow();
1227 return CBF_NONE;
1230 static CallBackFunction ToolbarScenBuildRoad(Window *w)
1232 w->HandleButtonClick(WID_TE_ROADS);
1233 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1234 ShowBuildRoadScenToolbar();
1235 return CBF_NONE;
1238 static CallBackFunction ToolbarScenBuildDocks(Window *w)
1240 w->HandleButtonClick(WID_TE_WATER);
1241 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1242 ShowBuildDocksScenToolbar();
1243 return CBF_NONE;
1246 static CallBackFunction ToolbarScenPlantTrees(Window *w)
1248 w->HandleButtonClick(WID_TE_TREES);
1249 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1250 ShowBuildTreesToolbar();
1251 return CBF_NONE;
1254 static CallBackFunction ToolbarScenPlaceSign(Window *w)
1256 w->HandleButtonClick(WID_TE_SIGNS);
1257 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1258 return SelectSignTool();
1261 static CallBackFunction ToolbarBtn_NULL(Window *w)
1263 return CBF_NONE;
1266 typedef CallBackFunction MenuClickedProc(int index);
1268 static MenuClickedProc * const _menu_clicked_procs[] = {
1269 NULL, // 0
1270 NULL, // 1
1271 MenuClickSettings, // 2
1272 MenuClickSaveLoad, // 3
1273 MenuClickMap, // 4
1274 MenuClickTown, // 5
1275 MenuClickSubsidies, // 6
1276 MenuClickStations, // 7
1277 MenuClickFinances, // 8
1278 MenuClickCompany, // 9
1279 MenuClickStory, // 10
1280 MenuClickGoal, // 11
1281 MenuClickGraphs, // 12
1282 MenuClickLeague, // 13
1283 MenuClickIndustry, // 14
1284 MenuClickShowTrains, // 15
1285 MenuClickShowRoad, // 16
1286 MenuClickShowShips, // 17
1287 MenuClickShowAir, // 18
1288 MenuClickMap, // 19
1289 NULL, // 20
1290 MenuClickBuildRail, // 21
1291 MenuClickBuildRoad, // 22
1292 MenuClickBuildWater, // 23
1293 MenuClickBuildAir, // 24
1294 MenuClickForest, // 25
1295 MenuClickMusicWindow, // 26
1296 MenuClickNewspaper, // 27
1297 MenuClickHelp, // 28
1300 /** Full blown container to make it behave exactly as we want :) */
1301 class NWidgetToolbarContainer : public NWidgetContainer {
1302 bool visible[WID_TN_END]; ///< The visible headers
1303 protected:
1304 uint spacers; ///< Number of spacer widgets in this toolbar
1306 public:
1307 NWidgetToolbarContainer() : NWidgetContainer(NWID_HORIZONTAL)
1312 * Check whether the given widget type is a button for us.
1313 * @param type the widget type to check.
1314 * @return true if it is a button for us.
1316 bool IsButton(WidgetType type) const
1318 return type == WWT_IMGBTN || type == WWT_IMGBTN_2 || type == WWT_PUSHIMGBTN;
1321 void SetupSmallestSize(Window *w, bool init_array)
1323 this->smallest_x = 0; // Biggest child
1324 this->smallest_y = 0; // Biggest child
1325 this->fill_x = 1;
1326 this->fill_y = 0;
1327 this->resize_x = 1; // We only resize in this direction
1328 this->resize_y = 0; // We never resize in this direction
1329 this->spacers = 0;
1331 uint nbuttons = 0;
1332 /* First initialise some variables... */
1333 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1334 child_wid->SetupSmallestSize(w, init_array);
1335 this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
1336 if (this->IsButton(child_wid->type)) {
1337 nbuttons++;
1338 this->smallest_x = max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
1339 } else if (child_wid->type == NWID_SPACER) {
1340 this->spacers++;
1344 /* ... then in a second pass make sure the 'current' heights are set. Won't change ever. */
1345 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1346 child_wid->current_y = this->smallest_y;
1347 if (!this->IsButton(child_wid->type)) {
1348 child_wid->current_x = child_wid->smallest_x;
1351 w->window_desc->default_width = nbuttons * this->smallest_x;
1354 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
1356 assert(given_width >= this->smallest_x && given_height >= this->smallest_y);
1358 this->pos_x = x;
1359 this->pos_y = y;
1360 this->current_x = given_width;
1361 this->current_y = given_height;
1363 /* Figure out what are the visible buttons */
1364 memset(this->visible, 0, sizeof(this->visible));
1365 uint arrangable_count, button_count, spacer_count;
1366 const byte *arrangement = GetButtonArrangement(given_width, arrangable_count, button_count, spacer_count);
1367 for (uint i = 0; i < arrangable_count; i++) {
1368 this->visible[arrangement[i]] = true;
1371 /* Create us ourselves a quick lookup table */
1372 NWidgetBase *widgets[WID_TN_END];
1373 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1374 if (child_wid->type == NWID_SPACER) continue;
1375 widgets[((NWidgetCore*)child_wid)->index] = child_wid;
1378 /* Now assign the widgets to their rightful place */
1379 uint position = 0; // Place to put next child relative to origin of the container.
1380 uint spacer_space = max(0, (int)given_width - (int)(button_count * this->smallest_x)); // Remaining spacing for 'spacer' widgets
1381 uint button_space = given_width - spacer_space; // Remaining spacing for the buttons
1382 uint spacer_i = 0;
1383 uint button_i = 0;
1385 /* Index into the arrangement indices. The macro lastof cannot be used here! */
1386 const byte *cur_wid = rtl ? &arrangement[arrangable_count - 1] : arrangement;
1387 for (uint i = 0; i < arrangable_count; i++) {
1388 NWidgetBase *child_wid = widgets[*cur_wid];
1389 /* If we have to give space to the spacers, do that */
1390 if (spacer_space != 0) {
1391 NWidgetBase *possible_spacer = rtl ? child_wid->next : child_wid->prev;
1392 if (possible_spacer != NULL && possible_spacer->type == NWID_SPACER) {
1393 uint add = spacer_space / (spacer_count - spacer_i);
1394 position += add;
1395 spacer_space -= add;
1396 spacer_i++;
1400 /* Buttons can be scaled, the others not. */
1401 if (this->IsButton(child_wid->type)) {
1402 child_wid->current_x = button_space / (button_count - button_i);
1403 button_space -= child_wid->current_x;
1404 button_i++;
1406 child_wid->AssignSizePosition(sizing, x + position, y, child_wid->current_x, this->current_y, rtl);
1407 position += child_wid->current_x;
1409 if (rtl) {
1410 cur_wid--;
1411 } else {
1412 cur_wid++;
1417 /* virtual */ void Draw(const Window *w)
1419 /* Draw brown-red toolbar bg. */
1420 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);
1421 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);
1423 bool rtl = _current_text_dir == TD_RTL;
1424 for (NWidgetBase *child_wid = rtl ? this->tail : this->head; child_wid != NULL; child_wid = rtl ? child_wid->prev : child_wid->next) {
1425 if (child_wid->type == NWID_SPACER) continue;
1426 if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
1428 child_wid->Draw(w);
1432 /* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y)
1434 if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
1436 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1437 if (child_wid->type == NWID_SPACER) continue;
1438 if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
1440 NWidgetCore *nwid = child_wid->GetWidgetFromPos(x, y);
1441 if (nwid != NULL) return nwid;
1443 return NULL;
1447 * Get the arrangement of the buttons for the toolbar.
1448 * @param width the new width of the toolbar.
1449 * @param arrangable_count output of the number of visible items.
1450 * @param button_count output of the number of visible buttons.
1451 * @param spacer_count output of the number of spacers.
1452 * @return the button configuration.
1454 virtual const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const = 0;
1457 /** Container for the 'normal' main toolbar */
1458 class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
1459 /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
1461 static const uint SMALLEST_ARRANGEMENT = 14;
1462 static const uint BIGGEST_ARRANGEMENT = 20;
1463 static const byte arrange14[] = {
1464 0, 1, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 29,
1465 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 29,
1467 static const byte arrange15[] = {
1468 0, 1, 4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
1469 0, 2, 4, 3, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 29,
1471 static const byte arrange16[] = {
1472 0, 1, 2, 4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
1473 0, 1, 3, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 19, 20, 29,
1475 static const byte arrange17[] = {
1476 0, 1, 2, 4, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
1477 0, 1, 3, 4, 6, 5, 7, 8, 9, 12, 14, 26, 27, 28, 19, 20, 29,
1479 static const byte arrange18[] = {
1480 0, 1, 2, 4, 5, 6, 7, 8, 9, 14, 21, 22, 23, 24, 25, 19, 20, 29,
1481 0, 1, 3, 4, 5, 6, 7, 12, 15, 16, 17, 18, 26, 27, 28, 19, 20, 29,
1483 static const byte arrange19[] = {
1484 0, 1, 2, 4, 5, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 19, 20, 29,
1485 0, 1, 3, 4, 7, 8, 9, 12, 14, 27, 21, 22, 23, 24, 25, 28, 19, 20, 29,
1487 static const byte arrange20[] = {
1488 0, 1, 2, 4, 5, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 11, 19, 20, 29,
1489 0, 1, 3, 4, 7, 8, 9, 12, 14, 27, 21, 22, 23, 24, 25, 10, 28, 19, 20, 29,
1491 static const byte arrange_all[] = {
1492 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
1495 /* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
1496 uint full_buttons = max(CeilDiv(width, this->smallest_x), SMALLEST_ARRANGEMENT);
1497 if (full_buttons > BIGGEST_ARRANGEMENT) {
1498 button_count = arrangable_count = lengthof(arrange_all);
1499 spacer_count = this->spacers;
1500 return arrange_all;
1503 /* Introduce the split toolbar */
1504 static const byte * const arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19, arrange20 };
1506 button_count = arrangable_count = full_buttons;
1507 spacer_count = this->spacers;
1508 return arrangements[full_buttons - SMALLEST_ARRANGEMENT] + ((_toolbar_mode == TB_LOWER) ? full_buttons : 0);
1512 /** Container for the scenario editor's toolbar */
1513 class NWidgetScenarioToolbarContainer : public NWidgetToolbarContainer {
1514 uint panel_widths[2]; ///< The width of the two panels (the text panel and date panel)
1516 void SetupSmallestSize(Window *w, bool init_array)
1518 this->NWidgetToolbarContainer::SetupSmallestSize(w, init_array);
1520 /* Find the size of panel_widths */
1521 uint i = 0;
1522 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1523 if (child_wid->type == NWID_SPACER || this->IsButton(child_wid->type)) continue;
1525 assert(i < lengthof(this->panel_widths));
1526 this->panel_widths[i++] = child_wid->current_x;
1527 w->window_desc->default_width += child_wid->current_x;
1531 /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
1533 static const byte arrange_all[] = {
1534 0, 1, 2, 3, 4, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 26, 28,
1536 static const byte arrange_nopanel[] = {
1537 0, 1, 2, 3, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 26, 28,
1539 static const byte arrange_switch[] = {
1540 18, 8, 11, 12, 13, 14, 15, 16, 17, 29,
1541 0, 1, 2, 3, 18, 9, 10, 26, 28, 29,
1544 /* If we can place all buttons *and* the panels, show them. */
1545 uint min_full_width = (lengthof(arrange_all) - lengthof(this->panel_widths)) * this->smallest_x + this->panel_widths[0] + this->panel_widths[1];
1546 if (width >= min_full_width) {
1547 width -= this->panel_widths[0] + this->panel_widths[1];
1548 arrangable_count = lengthof(arrange_all);
1549 button_count = arrangable_count - 2;
1550 spacer_count = this->spacers;
1551 return arrange_all;
1554 /* 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 */
1555 uint min_small_width = (lengthof(arrange_switch) - lengthof(this->panel_widths)) * this->smallest_x / 2 + this->panel_widths[1];
1556 if (width > min_small_width) {
1557 width -= this->panel_widths[1];
1558 arrangable_count = lengthof(arrange_nopanel);
1559 button_count = arrangable_count - 1;
1560 spacer_count = this->spacers - 1;
1561 return arrange_nopanel;
1564 /* Split toolbar */
1565 width -= this->panel_widths[1];
1566 arrangable_count = lengthof(arrange_switch) / 2;
1567 button_count = arrangable_count - 1;
1568 spacer_count = 0;
1569 return arrange_switch + ((_toolbar_mode == TB_LOWER) ? arrangable_count : 0);
1573 /* --- Toolbar handling for the 'normal' case */
1575 typedef CallBackFunction ToolbarButtonProc(Window *w);
1577 static ToolbarButtonProc * const _toolbar_button_procs[] = {
1578 ToolbarPauseClick,
1579 ToolbarFastForwardClick,
1580 ToolbarOptionsClick,
1581 ToolbarSaveClick,
1582 ToolbarMapClick,
1583 ToolbarTownClick,
1584 ToolbarSubsidiesClick,
1585 ToolbarStationsClick,
1586 ToolbarFinancesClick,
1587 ToolbarCompaniesClick,
1588 ToolbarStoryClick,
1589 ToolbarGoalClick,
1590 ToolbarGraphsClick,
1591 ToolbarLeagueClick,
1592 ToolbarIndustryClick,
1593 ToolbarTrainClick,
1594 ToolbarRoadClick,
1595 ToolbarShipClick,
1596 ToolbarAirClick,
1597 ToolbarZoomInClick,
1598 ToolbarZoomOutClick,
1599 ToolbarBuildRailClick,
1600 ToolbarBuildRoadClick,
1601 ToolbarBuildWaterClick,
1602 ToolbarBuildAirClick,
1603 ToolbarForestClick,
1604 ToolbarMusicClick,
1605 ToolbarNewspaperClick,
1606 ToolbarHelpClick,
1607 ToolbarSwitchClick,
1610 enum MainToolbarHotkeys {
1611 MTHK_PAUSE,
1612 MTHK_FASTFORWARD,
1613 MTHK_SETTINGS,
1614 MTHK_SAVEGAME,
1615 MTHK_LOADGAME,
1616 MTHK_SMALLMAP,
1617 MTHK_TOWNDIRECTORY,
1618 MTHK_SUBSIDIES,
1619 MTHK_STATIONS,
1620 MTHK_FINANCES,
1621 MTHK_COMPANIES,
1622 MTHK_STORY,
1623 MTHK_GOAL,
1624 MTHK_GRAPHS,
1625 MTHK_LEAGUE,
1626 MTHK_INDUSTRIES,
1627 MTHK_TRAIN_LIST,
1628 MTHK_ROADVEH_LIST,
1629 MTHK_SHIP_LIST,
1630 MTHK_AIRCRAFT_LIST,
1631 MTHK_ZOOM_IN,
1632 MTHK_ZOOM_OUT,
1633 MTHK_BUILD_RAIL,
1634 MTHK_BUILD_ROAD,
1635 MTHK_BUILD_DOCKS,
1636 MTHK_BUILD_AIRPORT,
1637 MTHK_BUILD_TREES,
1638 MTHK_MUSIC,
1639 MTHK_AI_DEBUG,
1640 MTHK_SMALL_SCREENSHOT,
1641 MTHK_ZOOMEDIN_SCREENSHOT,
1642 MTHK_DEFAULTZOOM_SCREENSHOT,
1643 MTHK_GIANT_SCREENSHOT,
1644 MTHK_CHEATS,
1645 MTHK_TERRAFORM,
1646 MTHK_EXTRA_VIEWPORT,
1647 MTHK_CLIENT_LIST,
1648 MTHK_SIGN_LIST,
1651 /** Main toolbar. */
1652 struct MainToolbarWindow : Window {
1653 CallBackFunction last_started_action; ///< Last started user action.
1655 MainToolbarWindow(WindowDesc *desc) : Window(desc)
1657 this->InitNested(0);
1659 this->last_started_action = CBF_NONE;
1660 CLRBITS(this->flags, WF_WHITE_BORDER);
1661 this->SetWidgetDisabledState(WID_TN_PAUSE, _networking && !_network_server); // if not server, disable pause button
1662 this->SetWidgetDisabledState(WID_TN_FAST_FORWARD, _networking); // if networking, disable fast-forward button
1663 PositionMainToolbar(this);
1664 DoZoomInOutWindow(ZOOM_NONE, this);
1667 virtual void OnPaint()
1669 /* If spectator, disable all construction buttons
1670 * ie : Build road, rail, ships, airports and landscaping
1671 * Since enabled state is the default, just disable when needed */
1672 this->SetWidgetsDisabledState(_local_company == COMPANY_SPECTATOR, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, WID_TN_AIR, WID_TN_LANDSCAPE, WIDGET_LIST_END);
1673 /* disable company list drop downs, if there are no companies */
1674 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);
1676 this->SetWidgetDisabledState(WID_TN_GOAL, Goal::GetNumItems() == 0);
1677 this->SetWidgetDisabledState(WID_TN_STORY, StoryPage::GetNumItems() == 0);
1679 this->SetWidgetDisabledState(WID_TN_RAILS, !CanBuildVehicleInfrastructure(VEH_TRAIN));
1680 this->SetWidgetDisabledState(WID_TN_AIR, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT));
1682 this->DrawWidgets();
1685 virtual void OnClick(Point pt, int widget, int click_count)
1687 if (_game_mode != GM_MENU && !this->IsWidgetDisabled(widget)) _toolbar_button_procs[widget](this);
1690 virtual void OnDropdownSelect(int widget, int index)
1692 CallBackFunction cbf = _menu_clicked_procs[widget](index);
1693 if (cbf != CBF_NONE) this->last_started_action = cbf;
1696 virtual EventState OnHotkey(int hotkey)
1698 switch (hotkey) {
1699 case MTHK_PAUSE: ToolbarPauseClick(this); break;
1700 case MTHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
1701 case MTHK_SETTINGS: ShowGameOptions(); break;
1702 case MTHK_SAVEGAME: MenuClickSaveLoad(); break;
1703 case MTHK_LOADGAME: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
1704 case MTHK_SMALLMAP: ShowSmallMap(); break;
1705 case MTHK_TOWNDIRECTORY: ShowTownDirectory(); break;
1706 case MTHK_SUBSIDIES: ShowSubsidiesList(); break;
1707 case MTHK_STATIONS: ShowCompanyStations(_local_company); break;
1708 case MTHK_FINANCES: ShowCompanyFinances(_local_company); break;
1709 case MTHK_COMPANIES: ShowCompany(_local_company); break;
1710 case MTHK_STORY: ShowStoryBook(_local_company); break;
1711 case MTHK_GOAL: ShowGoalsList(_local_company); break;
1712 case MTHK_GRAPHS: ShowOperatingProfitGraph(); break;
1713 case MTHK_LEAGUE: ShowCompanyLeagueTable(); break;
1714 case MTHK_INDUSTRIES: ShowBuildIndustryWindow(); break;
1715 case MTHK_TRAIN_LIST: ShowVehicleListWindow(_local_company, VEH_TRAIN); break;
1716 case MTHK_ROADVEH_LIST: ShowVehicleListWindow(_local_company, VEH_ROAD); break;
1717 case MTHK_SHIP_LIST: ShowVehicleListWindow(_local_company, VEH_SHIP); break;
1718 case MTHK_AIRCRAFT_LIST: ShowVehicleListWindow(_local_company, VEH_AIRCRAFT); break;
1719 case MTHK_ZOOM_IN: ToolbarZoomInClick(this); break;
1720 case MTHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
1721 case MTHK_BUILD_RAIL: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype); break;
1722 case MTHK_BUILD_ROAD: ShowBuildRoadToolbar(_last_built_roadtype); break;
1723 case MTHK_BUILD_DOCKS: ShowBuildDocksToolbar(); break;
1724 case MTHK_BUILD_AIRPORT: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break;
1725 case MTHK_BUILD_TREES: ShowBuildTreesToolbar(); break;
1726 case MTHK_MUSIC: ShowMusicWindow(); break;
1727 case MTHK_AI_DEBUG: ShowAIDebugWindow(); break;
1728 case MTHK_SMALL_SCREENSHOT: MenuClickSmallScreenshot(); break;
1729 case MTHK_ZOOMEDIN_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
1730 case MTHK_DEFAULTZOOM_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
1731 case MTHK_GIANT_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_WORLD); break;
1732 case MTHK_CHEATS: if (!_networking) ShowCheatWindow(); break;
1733 case MTHK_TERRAFORM: ShowTerraformToolbar(); break;
1734 case MTHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
1735 #ifdef ENABLE_NETWORK
1736 case MTHK_CLIENT_LIST: if (_networking) ShowClientList(); break;
1737 #endif
1738 case MTHK_SIGN_LIST: ShowSignList(); break;
1739 default: return ES_NOT_HANDLED;
1741 return ES_HANDLED;
1744 virtual void OnPlaceObject(Point pt, TileIndex tile)
1746 switch (this->last_started_action) {
1747 case CBF_PLACE_SIGN:
1748 PlaceProc_Sign(tile);
1749 break;
1751 case CBF_PLACE_LANDINFO:
1752 ShowLandInfo(tile);
1753 break;
1755 default: NOT_REACHED();
1759 virtual void OnTick()
1761 if (this->IsWidgetLowered(WID_TN_PAUSE) != !!_pause_mode) {
1762 this->ToggleWidgetLoweredState(WID_TN_PAUSE);
1763 this->SetWidgetDirty(WID_TN_PAUSE);
1766 if (this->IsWidgetLowered(WID_TN_FAST_FORWARD) != !!_fast_forward) {
1767 this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD);
1768 this->SetWidgetDirty(WID_TN_FAST_FORWARD);
1772 virtual void OnTimeout()
1774 /* We do not want to automatically raise the pause, fast forward and
1775 * switchbar buttons; they have to stay down when pressed etc. */
1776 for (uint i = WID_TN_SETTINGS; i < WID_TN_SWITCH_BAR; i++) {
1777 if (this->IsWidgetLowered(i)) {
1778 this->RaiseWidget(i);
1779 this->SetWidgetDirty(i);
1785 * Some data on this window has become invalid.
1786 * @param data Information about the changed data.
1787 * @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.
1789 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
1791 if (!gui_scope) return;
1792 if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT);
1795 static HotkeyList hotkeys;
1798 const uint16 _maintoolbar_pause_keys[] = {WKC_F1, WKC_PAUSE, 0};
1799 const uint16 _maintoolbar_zoomin_keys[] = {WKC_NUM_PLUS, WKC_EQUALS, WKC_SHIFT | WKC_EQUALS, WKC_SHIFT | WKC_F5, 0};
1800 const uint16 _maintoolbar_zoomout_keys[] = {WKC_NUM_MINUS, WKC_MINUS, WKC_SHIFT | WKC_MINUS, WKC_SHIFT | WKC_F6, 0};
1801 const uint16 _maintoolbar_smallmap_keys[] = {WKC_F4, 'M', 0};
1803 static Hotkey maintoolbar_hotkeys[] = {
1804 Hotkey(_maintoolbar_pause_keys, "pause", MTHK_PAUSE),
1805 Hotkey((uint16)0, "fastforward", MTHK_FASTFORWARD),
1806 Hotkey(WKC_F2, "settings", MTHK_SETTINGS),
1807 Hotkey(WKC_F3, "saveload", MTHK_SAVEGAME),
1808 Hotkey((uint16)0, "load_game", MTHK_LOADGAME),
1809 Hotkey(_maintoolbar_smallmap_keys, "smallmap", MTHK_SMALLMAP),
1810 Hotkey(WKC_F5, "town_list", MTHK_TOWNDIRECTORY),
1811 Hotkey(WKC_F6, "subsidies", MTHK_SUBSIDIES),
1812 Hotkey(WKC_F7, "station_list", MTHK_STATIONS),
1813 Hotkey(WKC_F8, "finances", MTHK_FINANCES),
1814 Hotkey(WKC_F9, "companies", MTHK_COMPANIES),
1815 Hotkey((uint16)0, "story_book", MTHK_STORY),
1816 Hotkey((uint16)0, "goal_list", MTHK_GOAL),
1817 Hotkey(WKC_F10, "graphs", MTHK_GRAPHS),
1818 Hotkey(WKC_F11, "league", MTHK_LEAGUE),
1819 Hotkey(WKC_F12, "industry_list", MTHK_INDUSTRIES),
1820 Hotkey(WKC_SHIFT | WKC_F1, "train_list", MTHK_TRAIN_LIST),
1821 Hotkey(WKC_SHIFT | WKC_F2, "roadveh_list", MTHK_ROADVEH_LIST),
1822 Hotkey(WKC_SHIFT | WKC_F3, "ship_list", MTHK_SHIP_LIST),
1823 Hotkey(WKC_SHIFT | WKC_F4, "aircraft_list", MTHK_AIRCRAFT_LIST),
1824 Hotkey(_maintoolbar_zoomin_keys, "zoomin", MTHK_ZOOM_IN),
1825 Hotkey(_maintoolbar_zoomout_keys, "zoomout", MTHK_ZOOM_OUT),
1826 Hotkey(WKC_SHIFT | WKC_F7, "build_rail", MTHK_BUILD_RAIL),
1827 Hotkey(WKC_SHIFT | WKC_F8, "build_road", MTHK_BUILD_ROAD),
1828 Hotkey(WKC_SHIFT | WKC_F9, "build_docks", MTHK_BUILD_DOCKS),
1829 Hotkey(WKC_SHIFT | WKC_F10, "build_airport", MTHK_BUILD_AIRPORT),
1830 Hotkey(WKC_SHIFT | WKC_F11, "build_trees", MTHK_BUILD_TREES),
1831 Hotkey(WKC_SHIFT | WKC_F12, "music", MTHK_MUSIC),
1832 Hotkey((uint16)0, "ai_debug", MTHK_AI_DEBUG),
1833 Hotkey(WKC_CTRL | 'S', "small_screenshot", MTHK_SMALL_SCREENSHOT),
1834 Hotkey(WKC_CTRL | 'P', "zoomedin_screenshot", MTHK_ZOOMEDIN_SCREENSHOT),
1835 Hotkey(WKC_CTRL | 'D', "defaultzoom_screenshot", MTHK_DEFAULTZOOM_SCREENSHOT),
1836 Hotkey((uint16)0, "giant_screenshot", MTHK_GIANT_SCREENSHOT),
1837 Hotkey(WKC_CTRL | WKC_ALT | 'C', "cheats", MTHK_CHEATS),
1838 Hotkey('L', "terraform", MTHK_TERRAFORM),
1839 Hotkey('V', "extra_viewport", MTHK_EXTRA_VIEWPORT),
1840 #ifdef ENABLE_NETWORK
1841 Hotkey((uint16)0, "client_list", MTHK_CLIENT_LIST),
1842 #endif
1843 Hotkey((uint16)0, "sign_list", MTHK_SIGN_LIST),
1844 HOTKEY_LIST_END
1846 HotkeyList MainToolbarWindow::hotkeys("maintoolbar", maintoolbar_hotkeys);
1848 static NWidgetBase *MakeMainToolbar(int *biggest_index)
1850 /** Sprites to use for the different toolbar buttons */
1851 static const SpriteID toolbar_button_sprites[] = {
1852 SPR_IMG_PAUSE, // WID_TN_PAUSE
1853 SPR_IMG_FASTFORWARD, // WID_TN_FAST_FORWARD
1854 SPR_IMG_SETTINGS, // WID_TN_SETTINGS
1855 SPR_IMG_SAVE, // WID_TN_SAVE
1856 SPR_IMG_SMALLMAP, // WID_TN_SMALL_MAP
1857 SPR_IMG_TOWN, // WID_TN_TOWNS
1858 SPR_IMG_SUBSIDIES, // WID_TN_SUBSIDIES
1859 SPR_IMG_COMPANY_LIST, // WID_TN_STATIONS
1860 SPR_IMG_COMPANY_FINANCE, // WID_TN_FINANCES
1861 SPR_IMG_COMPANY_GENERAL, // WID_TN_COMPANIES
1862 SPR_IMG_STORY_BOOK, // WID_TN_STORY
1863 SPR_IMG_GOAL, // WID_TN_GOAL
1864 SPR_IMG_GRAPHS, // WID_TN_GRAPHS
1865 SPR_IMG_COMPANY_LEAGUE, // WID_TN_LEAGUE
1866 SPR_IMG_INDUSTRY, // WID_TN_INDUSTRIES
1867 SPR_IMG_TRAINLIST, // WID_TN_TRAINS
1868 SPR_IMG_TRUCKLIST, // WID_TN_ROADVEHS
1869 SPR_IMG_SHIPLIST, // WID_TN_SHIPS
1870 SPR_IMG_AIRPLANESLIST, // WID_TN_AIRCRAFT
1871 SPR_IMG_ZOOMIN, // WID_TN_ZOOMIN
1872 SPR_IMG_ZOOMOUT, // WID_TN_ZOOMOUT
1873 SPR_IMG_BUILDRAIL, // WID_TN_RAILS
1874 SPR_IMG_BUILDROAD, // WID_TN_ROADS
1875 SPR_IMG_BUILDWATER, // WID_TN_WATER
1876 SPR_IMG_BUILDAIR, // WID_TN_AIR
1877 SPR_IMG_LANDSCAPING, // WID_TN_LANDSCAPE
1878 SPR_IMG_MUSIC, // WID_TN_MUSIC_SOUND
1879 SPR_IMG_MESSAGES, // WID_TN_MESSAGES
1880 SPR_IMG_QUERY, // WID_TN_HELP
1881 SPR_IMG_SWITCH_TOOLBAR, // WID_TN_SWITCH_BAR
1884 NWidgetMainToolbarContainer *hor = new NWidgetMainToolbarContainer();
1885 for (uint i = 0; i < WID_TN_END; i++) {
1886 switch (i) {
1887 case 4: case 8: case 15: case 19: case 21: case 26: hor->Add(new NWidgetSpacer(0, 0)); break;
1889 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));
1892 *biggest_index = max<int>(*biggest_index, WID_TN_SWITCH_BAR);
1893 return hor;
1896 static const NWidgetPart _nested_toolbar_normal_widgets[] = {
1897 NWidgetFunction(MakeMainToolbar),
1900 static WindowDesc _toolb_normal_desc(
1901 WDP_MANUAL, NULL, 640, 22,
1902 WC_MAIN_TOOLBAR, WC_NONE,
1903 WDF_NO_FOCUS,
1904 _nested_toolbar_normal_widgets, lengthof(_nested_toolbar_normal_widgets),
1905 &MainToolbarWindow::hotkeys
1909 /* --- Toolbar handling for the scenario editor */
1911 static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
1912 ToolbarPauseClick,
1913 ToolbarFastForwardClick,
1914 ToolbarOptionsClick,
1915 ToolbarScenSaveOrLoad,
1916 ToolbarBtn_NULL,
1917 ToolbarScenDatePanel,
1918 ToolbarScenDateBackward,
1919 ToolbarScenDateForward,
1920 ToolbarScenMapTownDir,
1921 ToolbarZoomInClick,
1922 ToolbarZoomOutClick,
1923 ToolbarScenGenLand,
1924 ToolbarScenGenTown,
1925 ToolbarScenGenIndustry,
1926 ToolbarScenBuildRoad,
1927 ToolbarScenBuildDocks,
1928 ToolbarScenPlantTrees,
1929 ToolbarScenPlaceSign,
1930 ToolbarBtn_NULL,
1931 NULL,
1932 NULL,
1933 NULL,
1934 NULL,
1935 NULL,
1936 NULL,
1937 NULL,
1938 ToolbarMusicClick,
1939 NULL,
1940 ToolbarHelpClick,
1941 ToolbarSwitchClick,
1944 enum MainToolbarEditorHotkeys {
1945 MTEHK_PAUSE,
1946 MTEHK_FASTFORWARD,
1947 MTEHK_SETTINGS,
1948 MTEHK_SAVEGAME,
1949 MTEHK_GENLAND,
1950 MTEHK_GENTOWN,
1951 MTEHK_GENINDUSTRY,
1952 MTEHK_BUILD_ROAD,
1953 MTEHK_BUILD_DOCKS,
1954 MTEHK_BUILD_TREES,
1955 MTEHK_SIGN,
1956 MTEHK_MUSIC,
1957 MTEHK_LANDINFO,
1958 MTEHK_SMALL_SCREENSHOT,
1959 MTEHK_ZOOMEDIN_SCREENSHOT,
1960 MTEHK_DEFAULTZOOM_SCREENSHOT,
1961 MTEHK_GIANT_SCREENSHOT,
1962 MTEHK_ZOOM_IN,
1963 MTEHK_ZOOM_OUT,
1964 MTEHK_TERRAFORM,
1965 MTEHK_SMALLMAP,
1966 MTEHK_EXTRA_VIEWPORT,
1969 struct ScenarioEditorToolbarWindow : Window {
1970 CallBackFunction last_started_action; ///< Last started user action.
1972 ScenarioEditorToolbarWindow(WindowDesc *desc) : Window(desc)
1974 this->InitNested(0);
1976 this->last_started_action = CBF_NONE;
1977 CLRBITS(this->flags, WF_WHITE_BORDER);
1978 PositionMainToolbar(this);
1979 DoZoomInOutWindow(ZOOM_NONE, this);
1982 virtual void OnPaint()
1984 this->SetWidgetDisabledState(WID_TE_DATE_BACKWARD, _settings_game.game_creation.starting_year <= MIN_YEAR);
1985 this->SetWidgetDisabledState(WID_TE_DATE_FORWARD, _settings_game.game_creation.starting_year >= MAX_YEAR);
1987 this->DrawWidgets();
1990 virtual void DrawWidget(const Rect &r, int widget) const
1992 switch (widget) {
1993 case WID_TE_DATE:
1994 SetDParam(0, ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
1995 DrawString(r.left, r.right, (this->height - FONT_HEIGHT_NORMAL) / 2, STR_WHITE_DATE_LONG, TC_FROMSTRING, SA_HOR_CENTER);
1996 break;
1998 case WID_TE_SPACER: {
1999 int height = r.bottom - r.top;
2000 if (height > 2 * FONT_HEIGHT_NORMAL) {
2001 DrawString(r.left, r.right, (height + 1) / 2 - FONT_HEIGHT_NORMAL, STR_SCENEDIT_TOOLBAR_OPENTTD, TC_FROMSTRING, SA_HOR_CENTER);
2002 DrawString(r.left, r.right, (height + 1) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
2003 } else {
2004 DrawString(r.left, r.right, (height - FONT_HEIGHT_NORMAL) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
2006 break;
2011 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2013 switch (widget) {
2014 case WID_TE_SPACER:
2015 size->width = max(GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_OPENTTD).width, GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR).width) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
2016 break;
2018 case WID_TE_DATE:
2019 SetDParam(0, ConvertYMDToDate(MAX_YEAR, 0, 1));
2020 *size = GetStringBoundingBox(STR_WHITE_DATE_LONG);
2021 size->height = max(size->height, GetSpriteSize(SPR_IMG_SAVE).height + WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM);
2022 break;
2026 virtual void OnClick(Point pt, int widget, int click_count)
2028 if (_game_mode == GM_MENU) return;
2029 CallBackFunction cbf = _scen_toolbar_button_procs[widget](this);
2030 if (cbf != CBF_NONE) this->last_started_action = cbf;
2033 virtual void OnDropdownSelect(int widget, int index)
2035 /* The map button is in a different location on the scenario
2036 * editor toolbar, so we need to adjust for it. */
2037 if (widget == WID_TE_SMALL_MAP) widget = WID_TN_SMALL_MAP;
2038 CallBackFunction cbf = _menu_clicked_procs[widget](index);
2039 if (cbf != CBF_NONE) this->last_started_action = cbf;
2040 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
2043 virtual EventState OnHotkey(int hotkey)
2045 CallBackFunction cbf = CBF_NONE;
2046 switch (hotkey) {
2047 case MTEHK_PAUSE: ToolbarPauseClick(this); break;
2048 case MTEHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
2049 case MTEHK_SETTINGS: ShowGameOptions(); break;
2050 case MTEHK_SAVEGAME: MenuClickSaveLoad(); break;
2051 case MTEHK_GENLAND: ToolbarScenGenLand(this); break;
2052 case MTEHK_GENTOWN: ToolbarScenGenTown(this); break;
2053 case MTEHK_GENINDUSTRY: ToolbarScenGenIndustry(this); break;
2054 case MTEHK_BUILD_ROAD: ToolbarScenBuildRoad(this); break;
2055 case MTEHK_BUILD_DOCKS: ToolbarScenBuildDocks(this); break;
2056 case MTEHK_BUILD_TREES: ToolbarScenPlantTrees(this); break;
2057 case MTEHK_SIGN: cbf = ToolbarScenPlaceSign(this); break;
2058 case MTEHK_MUSIC: ShowMusicWindow(); break;
2059 case MTEHK_LANDINFO: cbf = PlaceLandBlockInfo(); break;
2060 case MTEHK_SMALL_SCREENSHOT: MenuClickSmallScreenshot(); break;
2061 case MTEHK_ZOOMEDIN_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
2062 case MTEHK_DEFAULTZOOM_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
2063 case MTEHK_GIANT_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_WORLD); break;
2064 case MTEHK_ZOOM_IN: ToolbarZoomInClick(this); break;
2065 case MTEHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
2066 case MTEHK_TERRAFORM: ShowEditorTerraformToolbar(); break;
2067 case MTEHK_SMALLMAP: ShowSmallMap(); break;
2068 case MTEHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
2069 default: return ES_NOT_HANDLED;
2071 if (cbf != CBF_NONE) this->last_started_action = cbf;
2072 return ES_HANDLED;
2075 virtual void OnPlaceObject(Point pt, TileIndex tile)
2077 switch (this->last_started_action) {
2078 case CBF_PLACE_SIGN:
2079 PlaceProc_Sign(tile);
2080 break;
2082 case CBF_PLACE_LANDINFO:
2083 ShowLandInfo(tile);
2084 break;
2086 default: NOT_REACHED();
2090 virtual void OnTimeout()
2092 this->SetWidgetsLoweredState(false, WID_TE_DATE_BACKWARD, WID_TE_DATE_FORWARD, WIDGET_LIST_END);
2093 this->SetWidgetDirty(WID_TE_DATE_BACKWARD);
2094 this->SetWidgetDirty(WID_TE_DATE_FORWARD);
2097 virtual void OnTick()
2099 if (this->IsWidgetLowered(WID_TE_PAUSE) != !!_pause_mode) {
2100 this->ToggleWidgetLoweredState(WID_TE_PAUSE);
2101 this->SetDirty();
2104 if (this->IsWidgetLowered(WID_TE_FAST_FORWARD) != !!_fast_forward) {
2105 this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD);
2106 this->SetDirty();
2111 * Some data on this window has become invalid.
2112 * @param data Information about the changed data.
2113 * @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.
2115 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2117 if (!gui_scope) return;
2118 if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, WID_TE_ZOOM_IN, WID_TE_ZOOM_OUT);
2121 virtual void OnQueryTextFinished(char *str)
2123 /* Was 'cancel' pressed? */
2124 if (str == NULL) return;
2126 int32 value;
2127 if (!StrEmpty(str)) {
2128 value = atoi(str);
2129 } else {
2130 /* An empty string means revert to the default */
2131 value = DEF_START_YEAR;
2133 SetStartingYear(value);
2135 this->SetDirty();
2138 static HotkeyList hotkeys;
2141 static Hotkey scenedit_maintoolbar_hotkeys[] = {
2142 Hotkey(_maintoolbar_pause_keys, "pause", MTEHK_PAUSE),
2143 Hotkey((uint16)0, "fastforward", MTEHK_FASTFORWARD),
2144 Hotkey(WKC_F2, "settings", MTEHK_SETTINGS),
2145 Hotkey(WKC_F3, "saveload", MTEHK_SAVEGAME),
2146 Hotkey(WKC_F4, "gen_land", MTEHK_GENLAND),
2147 Hotkey(WKC_F5, "gen_town", MTEHK_GENTOWN),
2148 Hotkey(WKC_F6, "gen_industry", MTEHK_GENINDUSTRY),
2149 Hotkey(WKC_F7, "build_road", MTEHK_BUILD_ROAD),
2150 Hotkey(WKC_F8, "build_docks", MTEHK_BUILD_DOCKS),
2151 Hotkey(WKC_F9, "build_trees", MTEHK_BUILD_TREES),
2152 Hotkey(WKC_F10, "build_sign", MTEHK_SIGN),
2153 Hotkey(WKC_F11, "music", MTEHK_MUSIC),
2154 Hotkey(WKC_F12, "land_info", MTEHK_LANDINFO),
2155 Hotkey(WKC_CTRL | 'S', "small_screenshot", MTEHK_SMALL_SCREENSHOT),
2156 Hotkey(WKC_CTRL | 'P', "zoomedin_screenshot", MTEHK_ZOOMEDIN_SCREENSHOT),
2157 Hotkey(WKC_CTRL | 'D', "defaultzoom_screenshot", MTEHK_DEFAULTZOOM_SCREENSHOT),
2158 Hotkey((uint16)0, "giant_screenshot", MTEHK_GIANT_SCREENSHOT),
2159 Hotkey(_maintoolbar_zoomin_keys, "zoomin", MTEHK_ZOOM_IN),
2160 Hotkey(_maintoolbar_zoomout_keys, "zoomout", MTEHK_ZOOM_OUT),
2161 Hotkey('L', "terraform", MTEHK_TERRAFORM),
2162 Hotkey('M', "smallmap", MTEHK_SMALLMAP),
2163 Hotkey('V', "extra_viewport", MTEHK_EXTRA_VIEWPORT),
2164 HOTKEY_LIST_END
2166 HotkeyList ScenarioEditorToolbarWindow::hotkeys("scenedit_maintoolbar", scenedit_maintoolbar_hotkeys);
2168 static const NWidgetPart _nested_toolb_scen_inner_widgets[] = {
2169 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_PAUSE), SetDataTip(SPR_IMG_PAUSE, STR_TOOLBAR_TOOLTIP_PAUSE_GAME),
2170 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_FAST_FORWARD), SetDataTip(SPR_IMG_FASTFORWARD, STR_TOOLBAR_TOOLTIP_FORWARD),
2171 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SETTINGS), SetDataTip(SPR_IMG_SETTINGS, STR_TOOLBAR_TOOLTIP_OPTIONS),
2172 NWidget(WWT_IMGBTN_2, COLOUR_GREY, WID_TE_SAVE), SetDataTip(SPR_IMG_SAVE, STR_SCENEDIT_TOOLBAR_TOOLTIP_SAVE_SCENARIO_LOAD_SCENARIO),
2173 NWidget(NWID_SPACER),
2174 NWidget(WWT_PANEL, COLOUR_GREY, WID_TE_SPACER), EndContainer(),
2175 NWidget(NWID_SPACER),
2176 NWidget(WWT_PANEL, COLOUR_GREY, WID_TE_DATE_PANEL),
2177 NWidget(NWID_HORIZONTAL), SetPIP(3, 2, 3),
2178 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_DATE_BACKWARD), SetDataTip(SPR_ARROW_DOWN, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD),
2179 NWidget(WWT_EMPTY, COLOUR_GREY, WID_TE_DATE), SetDataTip(STR_NULL, STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE),
2180 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_DATE_FORWARD), SetDataTip(SPR_ARROW_UP, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD),
2181 EndContainer(),
2182 EndContainer(),
2183 NWidget(NWID_SPACER),
2184 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SMALL_MAP), SetDataTip(SPR_IMG_SMALLMAP, STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY),
2185 NWidget(NWID_SPACER),
2186 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_IN), SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN),
2187 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_OUT), SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT),
2188 NWidget(NWID_SPACER),
2189 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_LAND_GENERATE), SetDataTip(SPR_IMG_LANDSCAPING, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION),
2190 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TOWN_GENERATE), SetDataTip(SPR_IMG_TOWN, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION),
2191 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_INDUSTRY), SetDataTip(SPR_IMG_INDUSTRY, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION),
2192 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ROADS), SetDataTip(SPR_IMG_BUILDROAD, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION),
2193 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_WATER), SetDataTip(SPR_IMG_BUILDWATER, STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS),
2194 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TREES), SetDataTip(SPR_IMG_PLANTTREES, STR_SCENEDIT_TOOLBAR_PLANT_TREES),
2195 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_SIGNS), SetDataTip(SPR_IMG_SIGN, STR_SCENEDIT_TOOLBAR_PLACE_SIGN),
2196 NWidget(NWID_SPACER),
2197 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_MUSIC_SOUND), SetDataTip(SPR_IMG_MUSIC, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW),
2198 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_HELP), SetDataTip(SPR_IMG_QUERY, STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION),
2199 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SWITCH_BAR), SetDataTip(SPR_IMG_SWITCH_TOOLBAR, STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR),
2202 static NWidgetBase *MakeScenarioToolbar(int *biggest_index)
2204 return MakeNWidgets(_nested_toolb_scen_inner_widgets, lengthof(_nested_toolb_scen_inner_widgets), biggest_index, new NWidgetScenarioToolbarContainer());
2207 static const NWidgetPart _nested_toolb_scen_widgets[] = {
2208 NWidgetFunction(MakeScenarioToolbar),
2211 static WindowDesc _toolb_scen_desc(
2212 WDP_MANUAL, NULL, 640, 22,
2213 WC_MAIN_TOOLBAR, WC_NONE,
2214 WDF_NO_FOCUS,
2215 _nested_toolb_scen_widgets, lengthof(_nested_toolb_scen_widgets),
2216 &ScenarioEditorToolbarWindow::hotkeys
2219 /** Allocate the toolbar. */
2220 void AllocateToolbar()
2222 /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
2223 _last_built_roadtype = ROADTYPE_ROAD;
2225 if (_game_mode == GM_EDITOR) {
2226 new ScenarioEditorToolbarWindow(&_toolb_scen_desc);
2227 } else {
2228 new MainToolbarWindow(&_toolb_normal_desc);