Turn a conditional into an assertion in ConLoad
[openttd/fttd.git] / src / toolbar_gui.cpp
blob08b521552b3e38e8adfd257d1cb6ae3e49f3c450
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 static CallBackFunction _last_started_action = CBF_NONE; ///< Last started user action.
83 /**
84 * Drop down list entry for showing a checked/unchecked toggle item.
86 class DropDownListCheckedItem : public DropDownListStringItem {
87 uint checkmark_width;
88 public:
89 bool checked;
91 DropDownListCheckedItem(StringID string, int result, bool masked, bool checked) : DropDownListStringItem(string, result, masked), checked(checked)
93 this->checkmark_width = GetStringBoundingBox(STR_JUST_CHECKMARK).width + 3;
96 virtual ~DropDownListCheckedItem() {}
98 uint Width() const
100 return DropDownListStringItem::Width() + this->checkmark_width;
103 void Draw (BlitArea *dpi, int left, int right, int top, int bottom, bool sel, int bg_colour) const OVERRIDE
105 bool rtl = _current_text_dir == TD_RTL;
106 if (this->checked) {
107 DrawString (dpi, left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, STR_JUST_CHECKMARK, sel ? TC_WHITE : TC_BLACK);
109 DrawString (dpi, 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);
114 * Drop down list entry for showing a company entry, with companies 'blob'.
116 class DropDownListCompanyItem : public DropDownListItem {
117 Dimension icon_size;
118 public:
119 bool greyed;
121 DropDownListCompanyItem(int result, bool masked, bool greyed) : DropDownListItem(result, masked), greyed(greyed)
123 this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
126 virtual ~DropDownListCompanyItem() {}
128 bool Selectable() const
130 return true;
133 uint Width() const
135 CompanyID company = (CompanyID)this->result;
136 SetDParam(0, company);
137 SetDParam(1, company);
138 return GetStringBoundingBox(STR_COMPANY_NAME_COMPANY_NUM).width + this->icon_size.width + 3;
141 uint Height(uint width) const
143 return max(this->icon_size.height + 2U, (uint)FONT_HEIGHT_NORMAL);
146 void Draw (BlitArea *dpi, int left, int right, int top, int bottom, bool sel, int bg_colour) const OVERRIDE
148 CompanyID company = (CompanyID)this->result;
149 bool rtl = _current_text_dir == TD_RTL;
151 /* It's possible the company is deleted while the dropdown is open */
152 if (!Company::IsValidID(company)) return;
154 int icon_offset = (bottom - top - icon_size.height) / 2;
155 int text_offset = (bottom - top - FONT_HEIGHT_NORMAL) / 2;
157 DrawCompanyIcon (dpi, company, rtl ? right - this->icon_size.width - WD_FRAMERECT_RIGHT : left + WD_FRAMERECT_LEFT, top + icon_offset);
159 SetDParam(0, company);
160 SetDParam(1, company);
161 TextColour col;
162 if (this->greyed) {
163 col = (sel ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
164 } else {
165 col = sel ? TC_WHITE : TC_BLACK;
167 DrawString (dpi, 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);
172 * Pop up a generic text only menu.
173 * @param w Toolbar
174 * @param widget Toolbar button
175 * @param list List of items
176 * @param def Default item
178 static void PopupMainToolbMenu(Window *w, int widget, DropDownList *list, int def)
180 ShowDropDownList(w, list, def, widget, 0, true, true);
181 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
185 * Pop up a generic text only menu.
186 * @param w Toolbar
187 * @param widget Toolbar button
188 * @param string String for the first item in the menu
189 * @param count Number of items in the menu
191 static void PopupMainToolbMenu(Window *w, int widget, StringID string, int count)
193 DropDownList *list = new DropDownList();
194 for (int i = 0; i < count; i++) {
195 *list->Append() = new DropDownListStringItem(string + i, i, false);
197 PopupMainToolbMenu(w, widget, list, 0);
200 /** Enum for the Company Toolbar's network related buttons */
201 static const int CTMN_CLIENT_LIST = -1; ///< Show the client list
202 static const int CTMN_NEW_COMPANY = -2; ///< Create a new company
203 static const int CTMN_SPECTATE = -3; ///< Become spectator
204 static const int CTMN_SPECTATOR = -4; ///< Show a company window as spectator
207 * Pop up a generic company list menu.
208 * @param w The toolbar window.
209 * @param widget The button widget id.
210 * @param grey A bitbask of which items to mark as disabled.
211 * @param include_spectator If true, a spectator option is included in the list.
213 static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0, bool include_spectator = false)
215 DropDownList *list = new DropDownList();
217 #ifdef ENABLE_NETWORK
218 if (_networking) {
219 if (widget == WID_TN_COMPANIES) {
220 /* Add the client list button for the companies menu */
221 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false);
224 if (include_spectator) {
225 if (widget == WID_TN_COMPANIES) {
226 if (_local_company == COMPANY_SPECTATOR) {
227 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached());
228 } else {
229 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, NetworkMaxSpectatorsReached());
231 } else {
232 *list->Append() = new DropDownListStringItem(STR_NETWORK_TOOLBAR_LIST_SPECTATOR, CTMN_SPECTATOR, false);
236 #endif /* ENABLE_NETWORK */
238 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
239 if (!Company::IsValidID(c)) continue;
240 *list->Append() = new DropDownListCompanyItem(c, false, HasBit(grey, c));
243 PopupMainToolbMenu(w, widget, list, _local_company == COMPANY_SPECTATOR ? CTMN_CLIENT_LIST : (int)_local_company);
247 static ToolbarMode _toolbar_mode;
249 static CallBackFunction SelectSignTool()
251 if (_last_started_action == CBF_PLACE_SIGN) {
252 ResetPointerMode();
253 return CBF_NONE;
254 } else {
255 SetPointerMode (POINTER_TILE, WC_MAIN_TOOLBAR, 0, SPR_CURSOR_SIGN);
256 return CBF_PLACE_SIGN;
260 /* --- Pausing --- */
262 static CallBackFunction ToolbarPauseClick(Window *w)
264 if (_networking && !_network_server) return CBF_NONE; // only server can pause the game
266 if (DoCommandP(0, PM_PAUSED_NORMAL, _pause_mode == PM_UNPAUSED, CMD_PAUSE)) {
267 if (_settings_client.sound.confirm) SndPlayFx(SND_15_BEEP);
269 return CBF_NONE;
273 * Toggle fast forward mode.
275 * @param w Unused.
276 * @return #CBF_NONE
278 static CallBackFunction ToolbarFastForwardClick(Window *w)
280 _fast_forward ^= true;
281 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
282 return CBF_NONE;
286 * Game Option button menu entries.
288 enum OptionMenuEntries {
289 OME_GAMEOPTIONS,
290 OME_SETTINGS,
291 OME_SCRIPT_SETTINGS,
292 OME_NEWGRFSETTINGS,
293 OME_TRANSPARENCIES,
294 OME_SHOW_TOWNNAMES,
295 OME_SHOW_STATIONNAMES,
296 OME_SHOW_WAYPOINTNAMES,
297 OME_SHOW_SIGNS,
298 OME_SHOW_COMPETITOR_SIGNS,
299 OME_FULL_ANIMATION,
300 OME_FULL_DETAILS,
301 OME_TRANSPARENTBUILDINGS,
302 OME_SHOW_STATIONSIGNS,
306 * Handle click on Options button in toolbar.
308 * @param w parent window the shown Drop down list is attached to.
309 * @return #CBF_NONE
311 static CallBackFunction ToolbarOptionsClick(Window *w)
313 DropDownList *list = new DropDownList();
314 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS, OME_GAMEOPTIONS, false);
315 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE, OME_SETTINGS, false);
316 /* Changes to the per-AI settings don't get send from the server to the clients. Clients get
317 * the settings once they join but never update it. As such don't show the window at all
318 * to network clients. */
319 if (!_networking || _network_server) *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS, OME_SCRIPT_SETTINGS, false);
320 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS, OME_NEWGRFSETTINGS, false);
321 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS, OME_TRANSPARENCIES, false);
322 *list->Append() = new DropDownListItem(-1, false);
323 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED, OME_SHOW_TOWNNAMES, false, HasBit(_display_opt, DO_SHOW_TOWN_NAMES));
324 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED, OME_SHOW_STATIONNAMES, false, HasBit(_display_opt, DO_SHOW_STATION_NAMES));
325 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED, OME_SHOW_WAYPOINTNAMES, false, HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES));
326 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED, OME_SHOW_SIGNS, false, HasBit(_display_opt, DO_SHOW_SIGNS));
327 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS, OME_SHOW_COMPETITOR_SIGNS, false, HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS));
328 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION, OME_FULL_ANIMATION, false, HasBit(_display_opt, DO_FULL_ANIMATION));
329 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL, OME_FULL_DETAILS, false, HasBit(_display_opt, DO_FULL_DETAIL));
330 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS, OME_TRANSPARENTBUILDINGS, false, IsTransparencySet(TO_HOUSES));
331 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS, OME_SHOW_STATIONSIGNS, false, IsTransparencySet(TO_SIGNS));
333 ShowDropDownList(w, list, 0, WID_TN_SETTINGS, 140, true, true);
334 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
335 return CBF_NONE;
339 * Handle click on one of the entries in the Options button menu.
341 * @param index Index being clicked.
342 * @return #CBF_NONE
344 static CallBackFunction MenuClickSettings(int index)
346 switch (index) {
347 case OME_GAMEOPTIONS: ShowGameOptions(); return CBF_NONE;
348 case OME_SETTINGS: ShowGameSettings(); return CBF_NONE;
349 case OME_SCRIPT_SETTINGS: ShowAIConfigWindow(); return CBF_NONE;
350 case OME_NEWGRFSETTINGS: ShowNewGRFSettings(!_networking && _settings_client.gui.UserIsAllowedToChangeNewGRFs(), true, true, &_grfconfig); return CBF_NONE;
351 case OME_TRANSPARENCIES: ShowTransparencyToolbar(); break;
353 case OME_SHOW_TOWNNAMES: ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES); break;
354 case OME_SHOW_STATIONNAMES: ToggleBit(_display_opt, DO_SHOW_STATION_NAMES); break;
355 case OME_SHOW_WAYPOINTNAMES: ToggleBit(_display_opt, DO_SHOW_WAYPOINT_NAMES); break;
356 case OME_SHOW_SIGNS: ToggleBit(_display_opt, DO_SHOW_SIGNS); break;
357 case OME_SHOW_COMPETITOR_SIGNS:
358 ToggleBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS);
359 InvalidateWindowClassesData(WC_SIGN_LIST, -1);
360 break;
361 case OME_FULL_ANIMATION: ToggleBit(_display_opt, DO_FULL_ANIMATION); CheckBlitter(); break;
362 case OME_FULL_DETAILS: ToggleBit(_display_opt, DO_FULL_DETAIL); break;
363 case OME_TRANSPARENTBUILDINGS: ToggleTransparency(TO_HOUSES); break;
364 case OME_SHOW_STATIONSIGNS: ToggleTransparency(TO_SIGNS); break;
366 MarkWholeScreenDirty();
367 return CBF_NONE;
371 * SaveLoad entries in scenario editor mode.
373 enum SaveLoadEditorMenuEntries {
374 SLEME_SAVE_SCENARIO = 0,
375 SLEME_LOAD_SCENARIO,
376 SLEME_SAVE_HEIGHTMAP,
377 SLEME_LOAD_HEIGHTMAP,
378 SLEME_EXIT_TOINTRO,
379 SLEME_EXIT_GAME = 6,
380 SLEME_MENUCOUNT,
384 * SaveLoad entries in normal game mode.
386 enum SaveLoadNormalMenuEntries {
387 SLNME_SAVE_GAME = 0,
388 SLNME_LOAD_GAME,
389 SLNME_EXIT_TOINTRO,
390 SLNME_EXIT_GAME = 4,
391 SLNME_MENUCOUNT,
395 * Handle click on Save button in toolbar in normal game mode.
397 * @param w parent window the shown save dialogue is attached to.
398 * @return #CBF_NONE
400 static CallBackFunction ToolbarSaveClick(Window *w)
402 PopupMainToolbMenu(w, WID_TN_SAVE, STR_FILE_MENU_SAVE_GAME, SLNME_MENUCOUNT);
403 return CBF_NONE;
407 * Handle click on SaveLoad button in toolbar in the scenario editor.
409 * @param w parent window the shown save dialogue is attached to.
410 * @return #CBF_NONE
412 static CallBackFunction ToolbarScenSaveOrLoad(Window *w)
414 PopupMainToolbMenu(w, WID_TE_SAVE, STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO, SLEME_MENUCOUNT);
415 return CBF_NONE;
419 * Handle click on one of the entries in the SaveLoad menu.
421 * @param index Index being clicked.
422 * @return #CBF_NONE
424 static CallBackFunction MenuClickSaveLoad(int index = 0)
426 if (_game_mode == GM_EDITOR) {
427 switch (index) {
428 case SLEME_SAVE_SCENARIO: ShowSaveLoadDialog (FT_SCENARIO, true); break;
429 case SLEME_LOAD_SCENARIO: ShowSaveLoadDialog (FT_SCENARIO, false); break;
430 case SLEME_SAVE_HEIGHTMAP: ShowSaveLoadDialog (FT_HEIGHTMAP, true); break;
431 case SLEME_LOAD_HEIGHTMAP: ShowSaveLoadDialog (FT_HEIGHTMAP, false); break;
432 case SLEME_EXIT_TOINTRO: AskExitToGameMenu(); break;
433 case SLEME_EXIT_GAME: HandleExitGameRequest(); break;
435 } else {
436 switch (index) {
437 case SLNME_SAVE_GAME: ShowSaveLoadDialog (FT_SAVEGAME, true); break;
438 case SLNME_LOAD_GAME: ShowSaveLoadDialog (FT_SAVEGAME, false); break;
439 case SLNME_EXIT_TOINTRO: AskExitToGameMenu(); break;
440 case SLNME_EXIT_GAME: HandleExitGameRequest(); break;
443 return CBF_NONE;
446 /* --- Map button menu --- */
448 enum MapMenuEntries {
449 MME_SHOW_SMALLMAP = 0,
450 MME_SHOW_EXTRAVIEWPORTS,
451 MME_SHOW_LINKGRAPH,
452 MME_SHOW_SIGNLISTS,
453 MME_SHOW_TOWNDIRECTORY,
454 MME_SHOW_INDUSTRYDIRECTORY,
457 static CallBackFunction ToolbarMapClick(Window *w)
459 DropDownList *list = new DropDownList();
460 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false);
461 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false);
462 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_LINGRAPH_LEGEND, MME_SHOW_LINKGRAPH, false);
463 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false);
464 PopupMainToolbMenu(w, WID_TN_SMALL_MAP, list, 0);
465 return CBF_NONE;
468 static CallBackFunction ToolbarScenMapTownDir(Window *w)
470 DropDownList *list = new DropDownList();
471 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false);
472 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false);
473 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false);
474 *list->Append() = new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY, MME_SHOW_TOWNDIRECTORY, false);
475 *list->Append() = new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, MME_SHOW_INDUSTRYDIRECTORY, false);
476 PopupMainToolbMenu(w, WID_TE_SMALL_MAP, list, 0);
477 return CBF_NONE;
481 * Handle click on one of the entries in the Map menu.
483 * @param index Index being clicked.
484 * @return #CBF_NONE
486 static CallBackFunction MenuClickMap(int index)
488 switch (index) {
489 case MME_SHOW_SMALLMAP: ShowSmallMap(); break;
490 case MME_SHOW_EXTRAVIEWPORTS: ShowExtraViewPortWindow(); break;
491 case MME_SHOW_LINKGRAPH: ShowLinkGraphLegend(); break;
492 case MME_SHOW_SIGNLISTS: ShowSignList(); break;
493 case MME_SHOW_TOWNDIRECTORY: ShowTownDirectory(); break;
494 case MME_SHOW_INDUSTRYDIRECTORY: ShowIndustryDirectory(); break;
496 return CBF_NONE;
499 /* --- Town button menu --- */
501 static CallBackFunction ToolbarTownClick(Window *w)
503 PopupMainToolbMenu(w, WID_TN_TOWNS, STR_TOWN_MENU_TOWN_DIRECTORY, (_settings_game.economy.found_town == TF_FORBIDDEN) ? 1 : 2);
504 return CBF_NONE;
508 * Handle click on one of the entries in the Town menu.
510 * @param index Index being clicked.
511 * @return #CBF_NONE
513 static CallBackFunction MenuClickTown(int index)
515 switch (index) {
516 case 0: ShowTownDirectory(); break;
517 case 1: // setting could be changed when the dropdown was open
518 if (_settings_game.economy.found_town != TF_FORBIDDEN) ShowFoundTownWindow();
519 break;
521 return CBF_NONE;
524 /* --- Subidies button menu --- */
526 static CallBackFunction ToolbarSubsidiesClick(Window *w)
528 PopupMainToolbMenu(w, WID_TN_SUBSIDIES, STR_SUBSIDIES_MENU_SUBSIDIES, 1);
529 return CBF_NONE;
533 * Handle click on the entry in the Subsidies menu.
535 * @param index Unused.
536 * @return #CBF_NONE
538 static CallBackFunction MenuClickSubsidies(int index)
540 switch (index) {
541 case 0: ShowSubsidiesList(); break;
543 return CBF_NONE;
546 /* --- Stations button menu --- */
548 static CallBackFunction ToolbarStationsClick(Window *w)
550 PopupMainCompanyToolbMenu(w, WID_TN_STATIONS);
551 return CBF_NONE;
555 * Handle click on the entry in the Stations menu
557 * @param index CompanyID to show station list for
558 * @return #CBF_NONE
560 static CallBackFunction MenuClickStations(int index)
562 ShowCompanyStations((CompanyID)index);
563 return CBF_NONE;
566 /* --- Finances button menu --- */
568 static CallBackFunction ToolbarFinancesClick(Window *w)
570 PopupMainCompanyToolbMenu(w, WID_TN_FINANCES);
571 return CBF_NONE;
575 * Handle click on the entry in the finances overview menu.
577 * @param index CompanyID to show finances for.
578 * @return #CBF_NONE
580 static CallBackFunction MenuClickFinances(int index)
582 ShowCompanyFinances((CompanyID)index);
583 return CBF_NONE;
586 /* --- Company's button menu --- */
588 static CallBackFunction ToolbarCompaniesClick(Window *w)
590 PopupMainCompanyToolbMenu(w, WID_TN_COMPANIES, 0, true);
591 return CBF_NONE;
595 * Handle click on the entry in the Company menu.
597 * @param index Menu entry to handle.
598 * @return #CBF_NONE
600 static CallBackFunction MenuClickCompany(int index)
602 #ifdef ENABLE_NETWORK
603 if (_networking) {
604 switch (index) {
605 case CTMN_CLIENT_LIST:
606 ShowClientList();
607 return CBF_NONE;
609 case CTMN_NEW_COMPANY:
610 if (_network_server) {
611 DoCommandP(0, 0, _network_own_client_id, CMD_COMPANY_CTRL);
612 } else {
613 NetworkSendCommand(0, 0, 0, CMD_COMPANY_CTRL, NULL, _local_company);
615 return CBF_NONE;
617 case CTMN_SPECTATE:
618 if (_network_server) {
619 NetworkServerDoMove(CLIENT_ID_SERVER, COMPANY_SPECTATOR);
620 MarkWholeScreenDirty();
621 } else {
622 NetworkClientRequestMove(COMPANY_SPECTATOR);
624 return CBF_NONE;
627 #endif /* ENABLE_NETWORK */
628 ShowCompany((CompanyID)index);
629 return CBF_NONE;
632 /* --- Story button menu --- */
634 static CallBackFunction ToolbarStoryClick(Window *w)
636 PopupMainCompanyToolbMenu(w, WID_TN_STORY, 0, true);
637 return CBF_NONE;
641 * Handle click on the entry in the Story menu
643 * @param index CompanyID to show story book for
644 * @return #CBF_NONE
646 static CallBackFunction MenuClickStory(int index)
648 ShowStoryBook(index == CTMN_SPECTATOR ? INVALID_COMPANY : (CompanyID)index);
649 return CBF_NONE;
652 /* --- Goal button menu --- */
654 static CallBackFunction ToolbarGoalClick(Window *w)
656 PopupMainCompanyToolbMenu(w, WID_TN_GOAL, 0, true);
657 return CBF_NONE;
661 * Handle click on the entry in the Goal menu
663 * @param index CompanyID to show story book for
664 * @return #CBF_NONE
666 static CallBackFunction MenuClickGoal(int index)
668 ShowGoalsList(index == CTMN_SPECTATOR ? INVALID_COMPANY : (CompanyID)index);
669 return CBF_NONE;
672 /* --- Graphs button menu --- */
674 static CallBackFunction ToolbarGraphsClick(Window *w)
676 PopupMainToolbMenu(w, WID_TN_GRAPHS, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, (_toolbar_mode == TB_NORMAL) ? 6 : 8);
677 return CBF_NONE;
681 * Handle click on the entry in the Graphs menu.
683 * @param index Graph to show.
684 * @return #CBF_NONE
686 static CallBackFunction MenuClickGraphs(int index)
688 switch (index) {
689 case 0: ShowOperatingProfitGraph(); break;
690 case 1: ShowIncomeGraph(); break;
691 case 2: ShowDeliveredCargoGraph(); break;
692 case 3: ShowPerformanceHistoryGraph(); break;
693 case 4: ShowCompanyValueGraph(); break;
694 case 5: ShowCargoPaymentRates(); break;
695 /* functions for combined graphs/league button */
696 case 6: ShowCompanyLeagueTable(); break;
697 case 7: ShowPerformanceRatingDetail(); break;
699 return CBF_NONE;
702 /* --- League button menu --- */
704 static CallBackFunction ToolbarLeagueClick(Window *w)
706 PopupMainToolbMenu(w, WID_TN_LEAGUE, STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE, _networking ? 2 : 3);
707 return CBF_NONE;
711 * Handle click on the entry in the CompanyLeague menu.
713 * @param index Menu entry number.
714 * @return #CBF_NONE
716 static CallBackFunction MenuClickLeague(int index)
718 switch (index) {
719 case 0: ShowCompanyLeagueTable(); break;
720 case 1: ShowPerformanceRatingDetail(); break;
721 case 2: ShowHighscoreTable(); break;
723 return CBF_NONE;
726 /* --- Industries button menu --- */
728 static CallBackFunction ToolbarIndustryClick(Window *w)
730 /* Disable build-industry menu if we are a spectator */
731 PopupMainToolbMenu(w, WID_TN_INDUSTRIES, STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, (_local_company == COMPANY_SPECTATOR) ? 2 : 3);
732 return CBF_NONE;
736 * Handle click on the entry in the Industry menu.
738 * @param index Menu entry number.
739 * @return #CBF_NONE
741 static CallBackFunction MenuClickIndustry(int index)
743 switch (index) {
744 case 0: ShowIndustryDirectory(); break;
745 case 1: ShowIndustryCargoesWindow(); break;
746 case 2: ShowBuildIndustryWindow(); break;
748 return CBF_NONE;
751 /* --- Trains button menu + 1 helper function for all vehicles. --- */
753 static void ToolbarVehicleClick(Window *w, VehicleType veh)
755 const Vehicle *v;
756 int dis = ~0;
758 FOR_ALL_VEHICLES(v) {
759 if (v->type == veh && v->IsPrimaryVehicle()) ClrBit(dis, v->owner);
761 PopupMainCompanyToolbMenu(w, WID_TN_VEHICLE_START + veh, dis);
765 static CallBackFunction ToolbarTrainClick(Window *w)
767 ToolbarVehicleClick(w, VEH_TRAIN);
768 return CBF_NONE;
772 * Handle click on the entry in the Train menu.
774 * @param index CompanyID to show train list for.
775 * @return #CBF_NONE
777 static CallBackFunction MenuClickShowTrains(int index)
779 ShowVehicleListWindow((CompanyID)index, VEH_TRAIN);
780 return CBF_NONE;
783 /* --- Road vehicle button menu --- */
785 static CallBackFunction ToolbarRoadClick(Window *w)
787 ToolbarVehicleClick(w, VEH_ROAD);
788 return CBF_NONE;
792 * Handle click on the entry in the Road Vehicles menu.
794 * @param index CompanyID to show road vehicles list for.
795 * @return #CBF_NONE
797 static CallBackFunction MenuClickShowRoad(int index)
799 ShowVehicleListWindow((CompanyID)index, VEH_ROAD);
800 return CBF_NONE;
803 /* --- Ship button menu --- */
805 static CallBackFunction ToolbarShipClick(Window *w)
807 ToolbarVehicleClick(w, VEH_SHIP);
808 return CBF_NONE;
812 * Handle click on the entry in the Ships menu.
814 * @param index CompanyID to show ship list for.
815 * @return #CBF_NONE
817 static CallBackFunction MenuClickShowShips(int index)
819 ShowVehicleListWindow((CompanyID)index, VEH_SHIP);
820 return CBF_NONE;
823 /* --- Aircraft button menu --- */
825 static CallBackFunction ToolbarAirClick(Window *w)
827 ToolbarVehicleClick(w, VEH_AIRCRAFT);
828 return CBF_NONE;
832 * Handle click on the entry in the Aircraft menu.
834 * @param index CompanyID to show aircraft list for.
835 * @return #CBF_NONE
837 static CallBackFunction MenuClickShowAir(int index)
839 ShowVehicleListWindow((CompanyID)index, VEH_AIRCRAFT);
840 return CBF_NONE;
843 /* --- Zoom in button --- */
845 static CallBackFunction ToolbarZoomInClick(Window *w)
847 Window *main = FindWindowById (WC_MAIN_WINDOW, 0);
848 if (main->viewport->zoom > _settings_client.gui.zoom_min) {
849 DoZoomInOutViewport (main->viewport, true);
850 main->InvalidateData();
851 w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)WID_TE_ZOOM_IN : (byte)WID_TN_ZOOM_IN);
852 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
854 return CBF_NONE;
857 /* --- Zoom out button --- */
859 static CallBackFunction ToolbarZoomOutClick(Window *w)
861 Window *main = FindWindowById (WC_MAIN_WINDOW, 0);
862 if (main->viewport->zoom < _settings_client.gui.zoom_max) {
863 DoZoomInOutViewport (main->viewport, false);
864 main->InvalidateData();
865 w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)WID_TE_ZOOM_OUT : (byte)WID_TN_ZOOM_OUT);
866 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
868 return CBF_NONE;
871 /* --- Rail button menu --- */
873 static CallBackFunction ToolbarBuildRailClick(Window *w)
875 ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, WID_TN_RAILS, 140, true, true);
876 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
877 return CBF_NONE;
881 * Handle click on the entry in the Build Rail menu.
883 * @param index RailType to show the build toolbar for.
884 * @return #CBF_NONE
886 static CallBackFunction MenuClickBuildRail(int index)
888 _last_built_railtype = (RailType)index;
889 ShowBuildRailToolbar(_last_built_railtype);
890 return CBF_NONE;
893 /* --- Road button menu --- */
895 static CallBackFunction ToolbarBuildRoadClick(Window *w)
897 const Company *c = Company::Get(_local_company);
898 DropDownList *list = new DropDownList();
900 /* Road is always visible and available. */
901 *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION, ROADTYPE_ROAD, false);
903 /* Tram is only visible when there will be a tram, and available when that has been introduced. */
904 Engine *e;
905 FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
906 if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
907 if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
909 *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION, ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM));
910 break;
912 ShowDropDownList(w, list, _last_built_roadtype, WID_TN_ROADS, 140, true, true);
913 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
914 return CBF_NONE;
918 * Handle click on the entry in the Build Road menu.
920 * @param index RoadType to show the build toolbar for.
921 * @return #CBF_NONE
923 static CallBackFunction MenuClickBuildRoad(int index)
925 _last_built_roadtype = (RoadType)index;
926 ShowBuildRoadToolbar(_last_built_roadtype);
927 return CBF_NONE;
930 /* --- Water button menu --- */
932 static CallBackFunction ToolbarBuildWaterClick(Window *w)
934 PopupMainToolbMenu(w, WID_TN_WATER, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION, 1);
935 return CBF_NONE;
939 * Handle click on the entry in the Build Waterways menu.
941 * @param index Unused.
942 * @return #CBF_NONE
944 static CallBackFunction MenuClickBuildWater(int index)
946 ShowBuildDocksToolbar();
947 return CBF_NONE;
950 /* --- Airport button menu --- */
952 static CallBackFunction ToolbarBuildAirClick(Window *w)
954 PopupMainToolbMenu(w, WID_TN_AIR, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION, 1);
955 return CBF_NONE;
959 * Handle click on the entry in the Build Air menu.
961 * @param index Unused.
962 * @return #CBF_NONE
964 static CallBackFunction MenuClickBuildAir(int index)
966 ShowBuildAirToolbar();
967 return CBF_NONE;
970 /* --- Forest button menu --- */
972 static CallBackFunction ToolbarForestClick(Window *w)
974 PopupMainToolbMenu(w, WID_TN_LANDSCAPE, STR_LANDSCAPING_MENU_LANDSCAPING, 3);
975 return CBF_NONE;
979 * Handle click on the entry in the landscaping menu.
981 * @param index Menu entry clicked.
982 * @return #CBF_NONE
984 static CallBackFunction MenuClickForest(int index)
986 switch (index) {
987 case 0: ShowTerraformToolbar(); break;
988 case 1: ShowBuildTreesToolbar(); break;
989 case 2: return SelectSignTool();
991 return CBF_NONE;
994 /* --- Music button menu --- */
996 static CallBackFunction ToolbarMusicClick(Window *w)
998 PopupMainToolbMenu(w, WID_TN_MUSIC_SOUND, STR_TOOLBAR_SOUND_MUSIC, 1);
999 return CBF_NONE;
1003 * Handle click on the entry in the Music menu.
1005 * @param index Unused.
1006 * @return #CBF_NONE
1008 static CallBackFunction MenuClickMusicWindow(int index)
1010 ShowMusicWindow();
1011 return CBF_NONE;
1014 /* --- Newspaper button menu --- */
1016 static CallBackFunction ToolbarNewspaperClick(Window *w)
1018 PopupMainToolbMenu(w, WID_TN_MESSAGES, STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT, 2);
1019 return CBF_NONE;
1023 * Handle click on the entry in the Newspaper menu.
1025 * @param index Menu entry clicked.
1026 * @return #CBF_NONE
1028 static CallBackFunction MenuClickNewspaper(int index)
1030 switch (index) {
1031 case 0: ShowLastNewsMessage(); break;
1032 case 1: ShowMessageHistory(); break;
1034 return CBF_NONE;
1037 /* --- Help button menu --- */
1039 static CallBackFunction PlaceLandBlockInfo()
1041 if (_last_started_action == CBF_PLACE_LANDINFO) {
1042 ResetPointerMode();
1043 return CBF_NONE;
1044 } else {
1045 SetPointerMode (POINTER_TILE, WC_MAIN_TOOLBAR, 0, SPR_CURSOR_QUERY);
1046 return CBF_PLACE_LANDINFO;
1050 static CallBackFunction ToolbarHelpClick(Window *w)
1052 PopupMainToolbMenu(w, WID_TN_HELP, STR_ABOUT_MENU_LAND_BLOCK_INFO, _settings_client.gui.newgrf_developer_tools ? 12 : 9);
1053 return CBF_NONE;
1056 static void MenuClickSmallScreenshot()
1058 MakeScreenshot(SC_VIEWPORT, NULL);
1062 * Callback on the confirmation window for huge screenshots.
1063 * @param w Window with viewport
1064 * @param confirmed true on confirmation
1066 static void ScreenshotConfirmCallback(Window *w, bool confirmed)
1068 if (confirmed) MakeScreenshot(_confirmed_screenshot_type, NULL);
1072 * Make a screenshot of the world.
1073 * Ask for confirmation if the screenshot will be huge.
1074 * @param t Screenshot type: World or viewport screenshot
1076 static void MenuClickLargeWorldScreenshot(ScreenshotType t)
1078 ViewPort vp;
1079 SetupScreenshotViewport(t, &vp);
1080 if ((uint64)vp.width * (uint64)vp.height > 8192 * 8192) {
1081 /* Ask for confirmation */
1082 SetDParam(0, vp.width);
1083 SetDParam(1, vp.height);
1084 _confirmed_screenshot_type = t;
1085 ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, NULL, ScreenshotConfirmCallback);
1086 } else {
1087 /* Less than 64M pixels, just do it */
1088 MakeScreenshot(t, NULL);
1093 * Toggle drawing of sprites' bounding boxes.
1094 * @note has only an effect when newgrf_developer_tools are active.
1096 * Function is found here and not in viewport.cpp in order to avoid
1097 * importing the settings structs to there.
1099 void ToggleBoundingBoxes()
1101 extern bool _draw_bounding_boxes;
1102 /* Always allow to toggle them off */
1103 if (_settings_client.gui.newgrf_developer_tools || _draw_bounding_boxes) {
1104 _draw_bounding_boxes = !_draw_bounding_boxes;
1105 MarkWholeScreenDirty();
1110 * Toggle drawing of the dirty blocks.
1111 * @note has only an effect when newgrf_developer_tools are active.
1113 * Function is found here and not in viewport.cpp in order to avoid
1114 * importing the settings structs to there.
1116 void ToggleDirtyBlocks()
1118 extern bool _draw_dirty_blocks;
1119 /* Always allow to toggle them off */
1120 if (_settings_client.gui.newgrf_developer_tools || _draw_dirty_blocks) {
1121 _draw_dirty_blocks = !_draw_dirty_blocks;
1122 MarkWholeScreenDirty();
1127 * Set the starting year for a scenario.
1128 * @param year New starting year.
1130 void SetStartingYear(Year year)
1132 _settings_game.game_creation.starting_year = Clamp(year, MIN_YEAR, MAX_YEAR);
1133 Date new_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
1134 /* If you open a savegame as scenario there may already be link graphs.*/
1135 LinkGraphSchedule::instance.ShiftDates(new_date - _date);
1136 SetDate(new_date, 0);
1140 * Choose the proper callback function for the main toolbar's help menu.
1141 * @param index The menu index which was selected.
1142 * @return CBF_NONE
1144 static CallBackFunction MenuClickHelp(int index)
1146 switch (index) {
1147 case 0: return PlaceLandBlockInfo();
1148 case 2: IConsoleSwitch(); break;
1149 case 3: ShowAIDebugWindow(); break;
1150 case 4: MenuClickSmallScreenshot(); break;
1151 case 5: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
1152 case 6: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
1153 case 7: MenuClickLargeWorldScreenshot(SC_WORLD); break;
1154 case 8: ShowAboutWindow(); break;
1155 case 9: ShowSpriteAlignerWindow(); break;
1156 case 10: ToggleBoundingBoxes(); break;
1157 case 11: ToggleDirtyBlocks(); break;
1159 return CBF_NONE;
1162 /* --- Switch toolbar button --- */
1164 static CallBackFunction ToolbarSwitchClick(Window *w)
1166 if (_toolbar_mode != TB_LOWER) {
1167 _toolbar_mode = TB_LOWER;
1168 } else {
1169 _toolbar_mode = TB_UPPER;
1172 w->ReInit();
1173 w->SetWidgetLoweredState(WID_TN_SWITCH_BAR, _toolbar_mode == TB_LOWER);
1174 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1175 return CBF_NONE;
1178 /* --- Scenario editor specific handlers. */
1181 * Called when clicking at the date panel of the scenario editor toolbar.
1183 static CallBackFunction ToolbarScenDatePanel(Window *w)
1185 SetDParam(0, _settings_game.game_creation.starting_year);
1186 ShowQueryString(STR_JUST_INT, STR_MAPGEN_START_DATE_QUERY_CAPT, 8, w, CS_NUMERAL, QSF_ENABLE_DEFAULT);
1187 _left_button_clicked = false;
1188 return CBF_NONE;
1191 static CallBackFunction ToolbarScenDateBackward(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_BACKWARD);
1196 w->SetDirty();
1198 SetStartingYear(_settings_game.game_creation.starting_year - 1);
1200 _left_button_clicked = false;
1201 return CBF_NONE;
1204 static CallBackFunction ToolbarScenDateForward(Window *w)
1206 /* don't allow too fast scrolling */
1207 if (!(w->flags & WF_TIMEOUT) || w->timeout_timer <= 1) {
1208 w->HandleButtonClick(WID_TE_DATE_FORWARD);
1209 w->SetDirty();
1211 SetStartingYear(_settings_game.game_creation.starting_year + 1);
1213 _left_button_clicked = false;
1214 return CBF_NONE;
1217 static CallBackFunction ToolbarScenGenLand(Window *w)
1219 w->HandleButtonClick(WID_TE_LAND_GENERATE);
1220 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1222 ShowEditorTerraformToolbar();
1223 return CBF_NONE;
1227 static CallBackFunction ToolbarScenGenTown(Window *w)
1229 w->HandleButtonClick(WID_TE_TOWN_GENERATE);
1230 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1231 ShowFoundTownWindow();
1232 return CBF_NONE;
1235 static CallBackFunction ToolbarScenGenIndustry(Window *w)
1237 w->HandleButtonClick(WID_TE_INDUSTRY);
1238 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1239 ShowBuildIndustryWindow();
1240 return CBF_NONE;
1243 static CallBackFunction ToolbarScenBuildRoad(Window *w)
1245 w->HandleButtonClick(WID_TE_ROADS);
1246 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1247 ShowBuildRoadScenToolbar();
1248 return CBF_NONE;
1251 static CallBackFunction ToolbarScenBuildDocks(Window *w)
1253 w->HandleButtonClick(WID_TE_WATER);
1254 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1255 ShowBuildDocksScenToolbar();
1256 return CBF_NONE;
1259 static CallBackFunction ToolbarScenPlantTrees(Window *w)
1261 w->HandleButtonClick(WID_TE_TREES);
1262 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1263 ShowBuildTreesToolbar();
1264 return CBF_NONE;
1267 static CallBackFunction ToolbarScenPlaceSign(Window *w)
1269 w->HandleButtonClick(WID_TE_SIGNS);
1270 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1271 return SelectSignTool();
1274 static CallBackFunction ToolbarBtn_NULL(Window *w)
1276 return CBF_NONE;
1279 typedef CallBackFunction MenuClickedProc(int index);
1281 static MenuClickedProc * const _menu_clicked_procs[] = {
1282 NULL, // 0
1283 NULL, // 1
1284 MenuClickSettings, // 2
1285 MenuClickSaveLoad, // 3
1286 MenuClickMap, // 4
1287 MenuClickTown, // 5
1288 MenuClickSubsidies, // 6
1289 MenuClickStations, // 7
1290 MenuClickFinances, // 8
1291 MenuClickCompany, // 9
1292 MenuClickStory, // 10
1293 MenuClickGoal, // 11
1294 MenuClickGraphs, // 12
1295 MenuClickLeague, // 13
1296 MenuClickIndustry, // 14
1297 MenuClickShowTrains, // 15
1298 MenuClickShowRoad, // 16
1299 MenuClickShowShips, // 17
1300 MenuClickShowAir, // 18
1301 MenuClickMap, // 19
1302 NULL, // 20
1303 MenuClickBuildRail, // 21
1304 MenuClickBuildRoad, // 22
1305 MenuClickBuildWater, // 23
1306 MenuClickBuildAir, // 24
1307 MenuClickForest, // 25
1308 MenuClickMusicWindow, // 26
1309 MenuClickNewspaper, // 27
1310 MenuClickHelp, // 28
1313 /** Full blown container to make it behave exactly as we want :) */
1314 class NWidgetToolbarContainer : public NWidgetContainer {
1315 bool visible[WID_TN_END]; ///< The visible headers
1316 protected:
1317 uint spacers; ///< Number of spacer widgets in this toolbar
1319 public:
1320 NWidgetToolbarContainer() : NWidgetContainer(NWID_HORIZONTAL)
1325 * Check whether the given widget type is a button for us.
1326 * @param type the widget type to check.
1327 * @return true if it is a button for us.
1329 bool IsButton(WidgetType type) const
1331 return type == WWT_IMGBTN || type == WWT_IMGBTN_2 || type == WWT_PUSHIMGBTN;
1334 void SetupSmallestSize(Window *w, bool init_array)
1336 this->smallest_x = 0; // Biggest child
1337 this->smallest_y = 0; // Biggest child
1338 this->fill_x = 1;
1339 this->fill_y = 0;
1340 this->resize_x = 1; // We only resize in this direction
1341 this->resize_y = 0; // We never resize in this direction
1342 this->spacers = 0;
1344 uint nbuttons = 0;
1345 /* First initialise some variables... */
1346 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1347 child_wid->SetupSmallestSize(w, init_array);
1348 this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
1349 if (this->IsButton(child_wid->type)) {
1350 nbuttons++;
1351 this->smallest_x = max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
1352 } else if (child_wid->type == NWID_SPACER) {
1353 this->spacers++;
1357 /* ... then in a second pass make sure the 'current' heights are set. Won't change ever. */
1358 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1359 child_wid->current_y = this->smallest_y;
1360 if (!this->IsButton(child_wid->type)) {
1361 child_wid->current_x = child_wid->smallest_x;
1364 _toolbar_width = nbuttons * this->smallest_x;
1367 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
1369 assert(given_width >= this->smallest_x && given_height >= this->smallest_y);
1371 this->pos_x = x;
1372 this->pos_y = y;
1373 this->current_x = given_width;
1374 this->current_y = given_height;
1376 /* Figure out what are the visible buttons */
1377 memset(this->visible, 0, sizeof(this->visible));
1378 uint arrangable_count, button_count, spacer_count;
1379 const byte *arrangement = GetButtonArrangement(given_width, arrangable_count, button_count, spacer_count);
1380 for (uint i = 0; i < arrangable_count; i++) {
1381 this->visible[arrangement[i]] = true;
1384 /* Create us ourselves a quick lookup table */
1385 NWidgetBase *widgets[WID_TN_END];
1386 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1387 if (child_wid->type == NWID_SPACER) continue;
1388 widgets[((NWidgetCore*)child_wid)->index] = child_wid;
1391 /* Now assign the widgets to their rightful place */
1392 uint position = 0; // Place to put next child relative to origin of the container.
1393 uint spacer_space = max(0, (int)given_width - (int)(button_count * this->smallest_x)); // Remaining spacing for 'spacer' widgets
1394 uint button_space = given_width - spacer_space; // Remaining spacing for the buttons
1395 uint spacer_i = 0;
1396 uint button_i = 0;
1398 /* Index into the arrangement indices. The macro lastof cannot be used here! */
1399 const byte *cur_wid = rtl ? &arrangement[arrangable_count - 1] : arrangement;
1400 for (uint i = 0; i < arrangable_count; i++) {
1401 NWidgetBase *child_wid = widgets[*cur_wid];
1402 /* If we have to give space to the spacers, do that */
1403 if (spacer_space != 0) {
1404 NWidgetBase *possible_spacer = rtl ? child_wid->next : child_wid->prev;
1405 if (possible_spacer != NULL && possible_spacer->type == NWID_SPACER) {
1406 uint add = spacer_space / (spacer_count - spacer_i);
1407 position += add;
1408 spacer_space -= add;
1409 spacer_i++;
1413 /* Buttons can be scaled, the others not. */
1414 if (this->IsButton(child_wid->type)) {
1415 child_wid->current_x = button_space / (button_count - button_i);
1416 button_space -= child_wid->current_x;
1417 button_i++;
1419 child_wid->AssignSizePosition(sizing, x + position, y, child_wid->current_x, this->current_y, rtl);
1420 position += child_wid->current_x;
1422 if (rtl) {
1423 cur_wid--;
1424 } else {
1425 cur_wid++;
1430 void Draw (BlitArea *dpi, const Window *w) OVERRIDE
1432 /* Draw brown-red toolbar bg. */
1433 GfxFillRect (dpi, this->pos_x, this->pos_y, this->pos_x + this->current_x - 1, this->pos_y + this->current_y - 1, PC_VERY_DARK_RED);
1434 GfxFillRect (dpi, 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);
1436 bool rtl = _current_text_dir == TD_RTL;
1437 for (NWidgetBase *child_wid = rtl ? this->tail : this->head; child_wid != NULL; child_wid = rtl ? child_wid->prev : child_wid->next) {
1438 if (child_wid->type == NWID_SPACER) continue;
1439 if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
1441 child_wid->Draw (dpi, w);
1445 /* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y)
1447 if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
1449 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1450 if (child_wid->type == NWID_SPACER) continue;
1451 if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
1453 NWidgetCore *nwid = child_wid->GetWidgetFromPos(x, y);
1454 if (nwid != NULL) return nwid;
1456 return NULL;
1460 * Get the arrangement of the buttons for the toolbar.
1461 * @param width the new width of the toolbar.
1462 * @param arrangable_count output of the number of visible items.
1463 * @param button_count output of the number of visible buttons.
1464 * @param spacer_count output of the number of spacers.
1465 * @return the button configuration.
1467 virtual const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const = 0;
1470 /** Container for the 'normal' main toolbar */
1471 class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
1472 /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
1474 static const uint SMALLEST_ARRANGEMENT = 14;
1475 static const uint BIGGEST_ARRANGEMENT = 20;
1477 /* The number of buttons of each row of the toolbar should match the number of items which we want to be visible.
1478 * The total number of buttons should be equal to arrangable_count * 2.
1479 * No bad things happen, but we could see strange behaviours if we have buttons < (arrangable_count * 2) like a
1480 * pause button appearing on the right of the lower toolbar and weird resizing of the widgets even if there is
1481 * enough space.
1483 static const byte arrange14[] = {
1484 WID_TN_PAUSE,
1485 WID_TN_FAST_FORWARD,
1486 WID_TN_TRAINS,
1487 WID_TN_ROADVEHS,
1488 WID_TN_SHIPS,
1489 WID_TN_AIRCRAFTS,
1490 WID_TN_ZOOM_IN,
1491 WID_TN_ZOOM_OUT,
1492 WID_TN_RAILS,
1493 WID_TN_ROADS,
1494 WID_TN_WATER,
1495 WID_TN_AIR,
1496 WID_TN_LANDSCAPE,
1497 WID_TN_SWITCH_BAR,
1498 // lower toolbar
1499 WID_TN_SETTINGS,
1500 WID_TN_SAVE,
1501 WID_TN_SMALL_MAP,
1502 WID_TN_TOWNS,
1503 WID_TN_SUBSIDIES,
1504 WID_TN_STATIONS,
1505 WID_TN_FINANCES,
1506 WID_TN_COMPANIES,
1507 WID_TN_GRAPHS,
1508 WID_TN_INDUSTRIES,
1509 WID_TN_MUSIC_SOUND,
1510 WID_TN_MESSAGES,
1511 WID_TN_HELP,
1512 WID_TN_SWITCH_BAR,
1514 static const byte arrange15[] = {
1515 WID_TN_PAUSE,
1516 WID_TN_FAST_FORWARD,
1517 WID_TN_SMALL_MAP,
1518 WID_TN_TRAINS,
1519 WID_TN_ROADVEHS,
1520 WID_TN_SHIPS,
1521 WID_TN_AIRCRAFTS,
1522 WID_TN_RAILS,
1523 WID_TN_ROADS,
1524 WID_TN_WATER,
1525 WID_TN_AIR,
1526 WID_TN_LANDSCAPE,
1527 WID_TN_ZOOM_IN,
1528 WID_TN_ZOOM_OUT,
1529 WID_TN_SWITCH_BAR,
1530 // lower toolbar
1531 WID_TN_PAUSE,
1532 WID_TN_SETTINGS,
1533 WID_TN_SMALL_MAP,
1534 WID_TN_SAVE,
1535 WID_TN_TOWNS,
1536 WID_TN_SUBSIDIES,
1537 WID_TN_STATIONS,
1538 WID_TN_FINANCES,
1539 WID_TN_COMPANIES,
1540 WID_TN_GRAPHS,
1541 WID_TN_INDUSTRIES,
1542 WID_TN_MUSIC_SOUND,
1543 WID_TN_MESSAGES,
1544 WID_TN_HELP,
1545 WID_TN_SWITCH_BAR,
1547 static const byte arrange16[] = {
1548 WID_TN_PAUSE,
1549 WID_TN_FAST_FORWARD,
1550 WID_TN_SETTINGS,
1551 WID_TN_SMALL_MAP,
1552 WID_TN_TRAINS,
1553 WID_TN_ROADVEHS,
1554 WID_TN_SHIPS,
1555 WID_TN_AIRCRAFTS,
1556 WID_TN_RAILS,
1557 WID_TN_ROADS,
1558 WID_TN_WATER,
1559 WID_TN_AIR,
1560 WID_TN_LANDSCAPE,
1561 WID_TN_ZOOM_IN,
1562 WID_TN_ZOOM_OUT,
1563 WID_TN_SWITCH_BAR,
1564 // lower toolbar
1565 WID_TN_PAUSE,
1566 WID_TN_FAST_FORWARD,
1567 WID_TN_SAVE,
1568 WID_TN_TOWNS,
1569 WID_TN_SUBSIDIES,
1570 WID_TN_STATIONS,
1571 WID_TN_FINANCES,
1572 WID_TN_COMPANIES,
1573 WID_TN_GRAPHS,
1574 WID_TN_INDUSTRIES,
1575 WID_TN_MUSIC_SOUND,
1576 WID_TN_MESSAGES,
1577 WID_TN_HELP,
1578 WID_TN_ZOOM_IN,
1579 WID_TN_ZOOM_OUT,
1580 WID_TN_SWITCH_BAR,
1582 static const byte arrange17[] = {
1583 WID_TN_PAUSE,
1584 WID_TN_FAST_FORWARD,
1585 WID_TN_SETTINGS,
1586 WID_TN_SMALL_MAP,
1587 WID_TN_SUBSIDIES,
1588 WID_TN_TRAINS,
1589 WID_TN_ROADVEHS,
1590 WID_TN_SHIPS,
1591 WID_TN_AIRCRAFTS,
1592 WID_TN_RAILS,
1593 WID_TN_ROADS,
1594 WID_TN_WATER,
1595 WID_TN_AIR,
1596 WID_TN_LANDSCAPE,
1597 WID_TN_ZOOM_IN,
1598 WID_TN_ZOOM_OUT,
1599 WID_TN_SWITCH_BAR,
1600 // lower toolbar
1601 WID_TN_PAUSE,
1602 WID_TN_FAST_FORWARD,
1603 WID_TN_SAVE,
1604 WID_TN_SMALL_MAP,
1605 WID_TN_SUBSIDIES,
1606 WID_TN_TOWNS,
1607 WID_TN_STATIONS,
1608 WID_TN_FINANCES,
1609 WID_TN_COMPANIES,
1610 WID_TN_GRAPHS,
1611 WID_TN_INDUSTRIES,
1612 WID_TN_MUSIC_SOUND,
1613 WID_TN_MESSAGES,
1614 WID_TN_HELP,
1615 WID_TN_ZOOM_IN,
1616 WID_TN_ZOOM_OUT,
1617 WID_TN_SWITCH_BAR,
1619 static const byte arrange18[] = {
1620 WID_TN_PAUSE,
1621 WID_TN_FAST_FORWARD,
1622 WID_TN_SETTINGS,
1623 WID_TN_SMALL_MAP,
1624 WID_TN_TOWNS,
1625 WID_TN_SUBSIDIES,
1626 WID_TN_STATIONS,
1627 WID_TN_FINANCES,
1628 WID_TN_COMPANIES,
1629 WID_TN_INDUSTRIES,
1630 WID_TN_RAILS,
1631 WID_TN_ROADS,
1632 WID_TN_WATER,
1633 WID_TN_AIR,
1634 WID_TN_LANDSCAPE,
1635 WID_TN_ZOOM_IN,
1636 WID_TN_ZOOM_OUT,
1637 WID_TN_SWITCH_BAR,
1638 // lower toolbar
1639 WID_TN_PAUSE,
1640 WID_TN_FAST_FORWARD,
1641 WID_TN_SAVE,
1642 WID_TN_SMALL_MAP,
1643 WID_TN_TOWNS,
1644 WID_TN_SUBSIDIES,
1645 WID_TN_STATIONS,
1646 WID_TN_GRAPHS,
1647 WID_TN_TRAINS,
1648 WID_TN_ROADVEHS,
1649 WID_TN_SHIPS,
1650 WID_TN_AIRCRAFTS,
1651 WID_TN_MUSIC_SOUND,
1652 WID_TN_MESSAGES,
1653 WID_TN_HELP,
1654 WID_TN_ZOOM_IN,
1655 WID_TN_ZOOM_OUT,
1656 WID_TN_SWITCH_BAR,
1658 static const byte arrange19[] = {
1659 WID_TN_PAUSE,
1660 WID_TN_FAST_FORWARD,
1661 WID_TN_SETTINGS,
1662 WID_TN_SMALL_MAP,
1663 WID_TN_TOWNS,
1664 WID_TN_SUBSIDIES,
1665 WID_TN_TRAINS,
1666 WID_TN_ROADVEHS,
1667 WID_TN_SHIPS,
1668 WID_TN_AIRCRAFTS,
1669 WID_TN_RAILS,
1670 WID_TN_ROADS,
1671 WID_TN_WATER,
1672 WID_TN_AIR,
1673 WID_TN_LANDSCAPE,
1674 WID_TN_MUSIC_SOUND,
1675 WID_TN_ZOOM_IN,
1676 WID_TN_ZOOM_OUT,
1677 WID_TN_SWITCH_BAR,
1678 // lower toolbar
1679 WID_TN_PAUSE,
1680 WID_TN_FAST_FORWARD,
1681 WID_TN_SAVE,
1682 WID_TN_SMALL_MAP,
1683 WID_TN_STATIONS,
1684 WID_TN_FINANCES,
1685 WID_TN_COMPANIES,
1686 WID_TN_GRAPHS,
1687 WID_TN_INDUSTRIES,
1688 WID_TN_MESSAGES,
1689 WID_TN_RAILS,
1690 WID_TN_ROADS,
1691 WID_TN_WATER,
1692 WID_TN_AIR,
1693 WID_TN_LANDSCAPE,
1694 WID_TN_HELP,
1695 WID_TN_ZOOM_IN,
1696 WID_TN_ZOOM_OUT,
1697 WID_TN_SWITCH_BAR,
1699 static const byte arrange20[] = {
1700 WID_TN_PAUSE,
1701 WID_TN_FAST_FORWARD,
1702 WID_TN_SETTINGS,
1703 WID_TN_SMALL_MAP,
1704 WID_TN_TOWNS,
1705 WID_TN_SUBSIDIES,
1706 WID_TN_TRAINS,
1707 WID_TN_ROADVEHS,
1708 WID_TN_SHIPS,
1709 WID_TN_AIRCRAFTS,
1710 WID_TN_RAILS,
1711 WID_TN_ROADS,
1712 WID_TN_WATER,
1713 WID_TN_AIR,
1714 WID_TN_LANDSCAPE,
1715 WID_TN_MUSIC_SOUND,
1716 WID_TN_GOAL,
1717 WID_TN_ZOOM_IN,
1718 WID_TN_ZOOM_OUT,
1719 WID_TN_SWITCH_BAR,
1720 // lower toolbar
1721 WID_TN_PAUSE,
1722 WID_TN_FAST_FORWARD,
1723 WID_TN_SAVE,
1724 WID_TN_SMALL_MAP,
1725 WID_TN_STATIONS,
1726 WID_TN_FINANCES,
1727 WID_TN_COMPANIES,
1728 WID_TN_GRAPHS,
1729 WID_TN_INDUSTRIES,
1730 WID_TN_MESSAGES,
1731 WID_TN_RAILS,
1732 WID_TN_ROADS,
1733 WID_TN_WATER,
1734 WID_TN_AIR,
1735 WID_TN_LANDSCAPE,
1736 WID_TN_STORY,
1737 WID_TN_HELP,
1738 WID_TN_ZOOM_IN,
1739 WID_TN_ZOOM_OUT,
1740 WID_TN_SWITCH_BAR,
1742 static const byte arrange_all[] = {
1743 WID_TN_PAUSE,
1744 WID_TN_FAST_FORWARD,
1745 WID_TN_SETTINGS,
1746 WID_TN_SAVE,
1747 WID_TN_SMALL_MAP,
1748 WID_TN_TOWNS,
1749 WID_TN_SUBSIDIES,
1750 WID_TN_STATIONS,
1751 WID_TN_FINANCES,
1752 WID_TN_COMPANIES,
1753 WID_TN_STORY,
1754 WID_TN_GOAL,
1755 WID_TN_GRAPHS,
1756 WID_TN_LEAGUE,
1757 WID_TN_INDUSTRIES,
1758 WID_TN_TRAINS,
1759 WID_TN_ROADVEHS,
1760 WID_TN_SHIPS,
1761 WID_TN_AIRCRAFTS,
1762 WID_TN_ZOOM_IN,
1763 WID_TN_ZOOM_OUT,
1764 WID_TN_RAILS,
1765 WID_TN_ROADS,
1766 WID_TN_WATER,
1767 WID_TN_AIR,
1768 WID_TN_LANDSCAPE,
1769 WID_TN_MUSIC_SOUND,
1770 WID_TN_MESSAGES,
1771 WID_TN_HELP
1774 /* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
1775 uint full_buttons = max(CeilDiv(width, this->smallest_x), SMALLEST_ARRANGEMENT);
1776 if (full_buttons > BIGGEST_ARRANGEMENT) {
1777 button_count = arrangable_count = lengthof(arrange_all);
1778 spacer_count = this->spacers;
1779 return arrange_all;
1782 /* Introduce the split toolbar */
1783 static const byte * const arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19, arrange20 };
1785 button_count = arrangable_count = full_buttons;
1786 spacer_count = this->spacers;
1787 return arrangements[full_buttons - SMALLEST_ARRANGEMENT] + ((_toolbar_mode == TB_LOWER) ? full_buttons : 0);
1791 /** Container for the scenario editor's toolbar */
1792 class NWidgetScenarioToolbarContainer : public NWidgetToolbarContainer {
1793 uint panel_widths[2]; ///< The width of the two panels (the text panel and date panel)
1795 void SetupSmallestSize(Window *w, bool init_array)
1797 this->NWidgetToolbarContainer::SetupSmallestSize(w, init_array);
1799 /* Find the size of panel_widths */
1800 uint i = 0;
1801 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1802 if (child_wid->type == NWID_SPACER || this->IsButton(child_wid->type)) continue;
1804 assert(i < lengthof(this->panel_widths));
1805 this->panel_widths[i++] = child_wid->current_x;
1806 _toolbar_width += child_wid->current_x;
1810 /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
1812 static const byte arrange_all[] = {
1813 WID_TE_PAUSE,
1814 WID_TE_FAST_FORWARD,
1815 WID_TE_SETTINGS,
1816 WID_TE_SAVE,
1817 WID_TE_SPACER,
1818 WID_TE_DATE_PANEL,
1819 WID_TE_SMALL_MAP,
1820 WID_TE_ZOOM_IN,
1821 WID_TE_ZOOM_OUT,
1822 WID_TE_LAND_GENERATE,
1823 WID_TE_TOWN_GENERATE,
1824 WID_TE_INDUSTRY,
1825 WID_TE_ROADS,
1826 WID_TE_WATER,
1827 WID_TE_TREES,
1828 WID_TE_SIGNS,
1829 WID_TE_MUSIC_SOUND,
1830 WID_TE_HELP,
1832 static const byte arrange_nopanel[] = {
1833 WID_TE_PAUSE,
1834 WID_TE_FAST_FORWARD,
1835 WID_TE_SETTINGS,
1836 WID_TE_SAVE,
1837 WID_TE_DATE_PANEL,
1838 WID_TE_SMALL_MAP,
1839 WID_TE_ZOOM_IN,
1840 WID_TE_ZOOM_OUT,
1841 WID_TE_LAND_GENERATE,
1842 WID_TE_TOWN_GENERATE,
1843 WID_TE_INDUSTRY,
1844 WID_TE_ROADS,
1845 WID_TE_WATER,
1846 WID_TE_TREES,
1847 WID_TE_SIGNS,
1848 WID_TE_MUSIC_SOUND,
1849 WID_TE_HELP,
1851 static const byte arrange_switch[] = {
1852 WID_TE_DATE_PANEL,
1853 WID_TE_SMALL_MAP,
1854 WID_TE_LAND_GENERATE,
1855 WID_TE_TOWN_GENERATE,
1856 WID_TE_INDUSTRY,
1857 WID_TE_ROADS,
1858 WID_TE_WATER,
1859 WID_TE_TREES,
1860 WID_TE_SIGNS,
1861 WID_TE_SWITCH_BAR,
1862 // lower toolbar
1863 WID_TE_PAUSE,
1864 WID_TE_FAST_FORWARD,
1865 WID_TE_SETTINGS,
1866 WID_TE_SAVE,
1867 WID_TE_DATE_PANEL,
1868 WID_TE_ZOOM_IN,
1869 WID_TE_ZOOM_OUT,
1870 WID_TE_MUSIC_SOUND,
1871 WID_TE_HELP, WID_TE_SWITCH_BAR,
1874 /* If we can place all buttons *and* the panels, show them. */
1875 uint min_full_width = (lengthof(arrange_all) - lengthof(this->panel_widths)) * this->smallest_x + this->panel_widths[0] + this->panel_widths[1];
1876 if (width >= min_full_width) {
1877 width -= this->panel_widths[0] + this->panel_widths[1];
1878 arrangable_count = lengthof(arrange_all);
1879 button_count = arrangable_count - 2;
1880 spacer_count = this->spacers;
1881 return arrange_all;
1884 /* 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 */
1885 uint min_small_width = (lengthof(arrange_switch) - lengthof(this->panel_widths)) * this->smallest_x / 2 + this->panel_widths[1];
1886 if (width > min_small_width) {
1887 width -= this->panel_widths[1];
1888 arrangable_count = lengthof(arrange_nopanel);
1889 button_count = arrangable_count - 1;
1890 spacer_count = this->spacers - 1;
1891 return arrange_nopanel;
1894 /* Split toolbar */
1895 width -= this->panel_widths[1];
1896 arrangable_count = lengthof(arrange_switch) / 2;
1897 button_count = arrangable_count - 1;
1898 spacer_count = 0;
1899 return arrange_switch + ((_toolbar_mode == TB_LOWER) ? arrangable_count : 0);
1903 /* --- Toolbar handling for the 'normal' case */
1905 typedef CallBackFunction ToolbarButtonProc(Window *w);
1907 static ToolbarButtonProc * const _toolbar_button_procs[] = {
1908 ToolbarPauseClick,
1909 ToolbarFastForwardClick,
1910 ToolbarOptionsClick,
1911 ToolbarSaveClick,
1912 ToolbarMapClick,
1913 ToolbarTownClick,
1914 ToolbarSubsidiesClick,
1915 ToolbarStationsClick,
1916 ToolbarFinancesClick,
1917 ToolbarCompaniesClick,
1918 ToolbarStoryClick,
1919 ToolbarGoalClick,
1920 ToolbarGraphsClick,
1921 ToolbarLeagueClick,
1922 ToolbarIndustryClick,
1923 ToolbarTrainClick,
1924 ToolbarRoadClick,
1925 ToolbarShipClick,
1926 ToolbarAirClick,
1927 ToolbarZoomInClick,
1928 ToolbarZoomOutClick,
1929 ToolbarBuildRailClick,
1930 ToolbarBuildRoadClick,
1931 ToolbarBuildWaterClick,
1932 ToolbarBuildAirClick,
1933 ToolbarForestClick,
1934 ToolbarMusicClick,
1935 ToolbarNewspaperClick,
1936 ToolbarHelpClick,
1937 ToolbarSwitchClick,
1940 enum MainToolbarHotkeys {
1941 MTHK_PAUSE,
1942 MTHK_FASTFORWARD,
1943 MTHK_SETTINGS,
1944 MTHK_SAVEGAME,
1945 MTHK_LOADGAME,
1946 MTHK_SMALLMAP,
1947 MTHK_TOWNDIRECTORY,
1948 MTHK_SUBSIDIES,
1949 MTHK_STATIONS,
1950 MTHK_FINANCES,
1951 MTHK_COMPANIES,
1952 MTHK_STORY,
1953 MTHK_GOAL,
1954 MTHK_GRAPHS,
1955 MTHK_LEAGUE,
1956 MTHK_INDUSTRIES,
1957 MTHK_TRAIN_LIST,
1958 MTHK_ROADVEH_LIST,
1959 MTHK_SHIP_LIST,
1960 MTHK_AIRCRAFT_LIST,
1961 MTHK_ZOOM_IN,
1962 MTHK_ZOOM_OUT,
1963 MTHK_BUILD_RAIL,
1964 MTHK_BUILD_ROAD,
1965 MTHK_BUILD_DOCKS,
1966 MTHK_BUILD_AIRPORT,
1967 MTHK_BUILD_TREES,
1968 MTHK_MUSIC,
1969 MTHK_AI_DEBUG,
1970 MTHK_SMALL_SCREENSHOT,
1971 MTHK_ZOOMEDIN_SCREENSHOT,
1972 MTHK_DEFAULTZOOM_SCREENSHOT,
1973 MTHK_GIANT_SCREENSHOT,
1974 MTHK_CHEATS,
1975 MTHK_TERRAFORM,
1976 MTHK_EXTRA_VIEWPORT,
1977 MTHK_CLIENT_LIST,
1978 MTHK_SIGN_LIST,
1981 /** Main toolbar. */
1982 struct MainToolbarWindow : Window {
1983 MainToolbarWindow (const WindowDesc *desc) : Window (desc)
1985 this->InitNested(0);
1987 _last_started_action = CBF_NONE;
1988 CLRBITS(this->flags, WF_WHITE_BORDER);
1989 this->SetWidgetDisabledState(WID_TN_PAUSE, _networking && !_network_server); // if not server, disable pause button
1990 this->SetWidgetDisabledState(WID_TN_FAST_FORWARD, _networking); // if networking, disable fast-forward button
1991 PositionMainToolbar(this);
1992 this->InvalidateData();
1995 virtual void FindWindowPlacementAndResize(int def_width, int def_height)
1997 Window::FindWindowPlacementAndResize(_toolbar_width, def_height);
2000 void OnPaint (BlitArea *dpi) OVERRIDE
2002 /* If spectator, disable all construction buttons
2003 * ie : Build road, rail, ships, airports and landscaping
2004 * Since enabled state is the default, just disable when needed */
2005 this->SetWidgetsDisabledState(_local_company == COMPANY_SPECTATOR, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, WID_TN_AIR, WID_TN_LANDSCAPE, WIDGET_LIST_END);
2006 /* disable company list drop downs, if there are no companies */
2007 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);
2009 this->SetWidgetDisabledState(WID_TN_GOAL, Goal::GetNumItems() == 0);
2010 this->SetWidgetDisabledState(WID_TN_STORY, StoryPage::GetNumItems() == 0);
2012 this->SetWidgetDisabledState(WID_TN_RAILS, !CanBuildVehicleInfrastructure(VEH_TRAIN));
2013 this->SetWidgetDisabledState(WID_TN_AIR, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT));
2015 this->DrawWidgets (dpi);
2018 virtual void OnClick(Point pt, int widget, int click_count)
2020 if (_game_mode != GM_MENU && !this->IsWidgetDisabled(widget)) _toolbar_button_procs[widget](this);
2023 virtual void OnDropdownSelect(int widget, int index)
2025 CallBackFunction cbf = _menu_clicked_procs[widget](index);
2026 if (cbf != CBF_NONE) _last_started_action = cbf;
2029 virtual EventState OnHotkey(int hotkey)
2031 switch (hotkey) {
2032 case MTHK_PAUSE: ToolbarPauseClick(this); break;
2033 case MTHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
2034 case MTHK_SETTINGS: ShowGameOptions(); break;
2035 case MTHK_SAVEGAME: MenuClickSaveLoad(); break;
2036 case MTHK_LOADGAME: ShowSaveLoadDialog (FT_SAVEGAME); break;
2037 case MTHK_SMALLMAP: ShowSmallMap(); break;
2038 case MTHK_TOWNDIRECTORY: ShowTownDirectory(); break;
2039 case MTHK_SUBSIDIES: ShowSubsidiesList(); break;
2040 case MTHK_STATIONS: ShowCompanyStations(_local_company); break;
2041 case MTHK_FINANCES: ShowCompanyFinances(_local_company); break;
2042 case MTHK_COMPANIES: ShowCompany(_local_company); break;
2043 case MTHK_STORY: ShowStoryBook(_local_company); break;
2044 case MTHK_GOAL: ShowGoalsList(_local_company); break;
2045 case MTHK_GRAPHS: ShowOperatingProfitGraph(); break;
2046 case MTHK_LEAGUE: ShowCompanyLeagueTable(); break;
2047 case MTHK_INDUSTRIES: ShowBuildIndustryWindow(); break;
2048 case MTHK_TRAIN_LIST: ShowVehicleListWindow(_local_company, VEH_TRAIN); break;
2049 case MTHK_ROADVEH_LIST: ShowVehicleListWindow(_local_company, VEH_ROAD); break;
2050 case MTHK_SHIP_LIST: ShowVehicleListWindow(_local_company, VEH_SHIP); break;
2051 case MTHK_AIRCRAFT_LIST: ShowVehicleListWindow(_local_company, VEH_AIRCRAFT); break;
2052 case MTHK_ZOOM_IN: ToolbarZoomInClick(this); break;
2053 case MTHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
2054 case MTHK_BUILD_RAIL: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype); break;
2055 case MTHK_BUILD_ROAD: ShowBuildRoadToolbar(_last_built_roadtype); break;
2056 case MTHK_BUILD_DOCKS: ShowBuildDocksToolbar(); break;
2057 case MTHK_BUILD_AIRPORT: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break;
2058 case MTHK_BUILD_TREES: ShowBuildTreesToolbar(); break;
2059 case MTHK_MUSIC: ShowMusicWindow(); break;
2060 case MTHK_AI_DEBUG: ShowAIDebugWindow(); break;
2061 case MTHK_SMALL_SCREENSHOT: MenuClickSmallScreenshot(); break;
2062 case MTHK_ZOOMEDIN_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
2063 case MTHK_DEFAULTZOOM_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
2064 case MTHK_GIANT_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_WORLD); break;
2065 case MTHK_CHEATS: if (!_networking) ShowCheatWindow(); break;
2066 case MTHK_TERRAFORM: ShowTerraformToolbar(); break;
2067 case MTHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
2068 #ifdef ENABLE_NETWORK
2069 case MTHK_CLIENT_LIST: if (_networking) ShowClientList(); break;
2070 #endif
2071 case MTHK_SIGN_LIST: ShowSignList(); break;
2072 default: return ES_NOT_HANDLED;
2074 return ES_HANDLED;
2077 virtual void OnPlaceObject(Point pt, TileIndex tile)
2079 switch (_last_started_action) {
2080 case CBF_PLACE_SIGN:
2081 PlaceProc_Sign(tile);
2082 break;
2084 case CBF_PLACE_LANDINFO:
2085 ShowLandInfo(tile);
2086 break;
2088 default: NOT_REACHED();
2092 virtual void OnPlaceObjectAbort()
2094 _last_started_action = CBF_NONE;
2097 virtual void OnTick()
2099 if (this->IsWidgetLowered(WID_TN_PAUSE) != !!_pause_mode) {
2100 this->ToggleWidgetLoweredState(WID_TN_PAUSE);
2101 this->SetWidgetDirty(WID_TN_PAUSE);
2104 if (this->IsWidgetLowered(WID_TN_FAST_FORWARD) != !!_fast_forward) {
2105 this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD);
2106 this->SetWidgetDirty(WID_TN_FAST_FORWARD);
2110 virtual void OnTimeout()
2112 /* We do not want to automatically raise the pause, fast forward and
2113 * switchbar buttons; they have to stay down when pressed etc. */
2114 for (uint i = WID_TN_SETTINGS; i < WID_TN_SWITCH_BAR; i++) {
2115 if (this->IsWidgetLowered(i)) {
2116 this->RaiseWidget(i);
2117 this->SetWidgetDirty(i);
2123 * Some data on this window has become invalid.
2124 * @param data Information about the changed data.
2125 * @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.
2127 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2129 if (!gui_scope) return;
2130 if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT);
2133 static HotkeyList hotkeys;
2136 static const Hotkey maintoolbar_hotkeys[] = {
2137 Hotkey ("pause", MTHK_PAUSE, WKC_F1, WKC_PAUSE),
2138 Hotkey ("fastforward", MTHK_FASTFORWARD),
2139 Hotkey ("settings", MTHK_SETTINGS, WKC_F2),
2140 Hotkey ("saveload", MTHK_SAVEGAME, WKC_F3),
2141 Hotkey ("load_game", MTHK_LOADGAME),
2142 Hotkey ("smallmap", MTHK_SMALLMAP, WKC_F4, 'M'),
2143 Hotkey ("town_list", MTHK_TOWNDIRECTORY, WKC_F5),
2144 Hotkey ("subsidies", MTHK_SUBSIDIES, WKC_F6),
2145 Hotkey ("station_list", MTHK_STATIONS, WKC_F7),
2146 Hotkey ("finances", MTHK_FINANCES, WKC_F8),
2147 Hotkey ("companies", MTHK_COMPANIES, WKC_F9),
2148 Hotkey ("story_book", MTHK_STORY),
2149 Hotkey ("goal_list", MTHK_GOAL),
2150 Hotkey ("graphs", MTHK_GRAPHS, WKC_F10),
2151 Hotkey ("league", MTHK_LEAGUE, WKC_F11),
2152 Hotkey ("industry_list", MTHK_INDUSTRIES, WKC_F12),
2153 Hotkey ("train_list", MTHK_TRAIN_LIST, WKC_SHIFT | WKC_F1),
2154 Hotkey ("roadveh_list", MTHK_ROADVEH_LIST, WKC_SHIFT | WKC_F2),
2155 Hotkey ("ship_list", MTHK_SHIP_LIST, WKC_SHIFT | WKC_F3),
2156 Hotkey ("aircraft_list", MTHK_AIRCRAFT_LIST, WKC_SHIFT | WKC_F4),
2157 Hotkey ("zoomin", MTHK_ZOOM_IN, WKC_SHIFT | WKC_F5, WKC_NUM_PLUS, WKC_EQUALS, WKC_SHIFT | WKC_EQUALS),
2158 Hotkey ("zoomout", MTHK_ZOOM_OUT, WKC_SHIFT | WKC_F6, WKC_NUM_MINUS, WKC_MINUS, WKC_SHIFT | WKC_MINUS),
2159 Hotkey ("build_rail", MTHK_BUILD_RAIL, WKC_SHIFT | WKC_F7),
2160 Hotkey ("build_road", MTHK_BUILD_ROAD, WKC_SHIFT | WKC_F8),
2161 Hotkey ("build_docks", MTHK_BUILD_DOCKS, WKC_SHIFT | WKC_F9),
2162 Hotkey ("build_airport", MTHK_BUILD_AIRPORT, WKC_SHIFT | WKC_F10),
2163 Hotkey ("build_trees", MTHK_BUILD_TREES, WKC_SHIFT | WKC_F11),
2164 Hotkey ("music", MTHK_MUSIC, WKC_SHIFT | WKC_F12),
2165 Hotkey ("ai_debug", MTHK_AI_DEBUG),
2166 Hotkey ("small_screenshot", MTHK_SMALL_SCREENSHOT, WKC_CTRL | 'S'),
2167 Hotkey ("zoomedin_screenshot", MTHK_ZOOMEDIN_SCREENSHOT, WKC_CTRL | 'P'),
2168 Hotkey ("defaultzoom_screenshot", MTHK_DEFAULTZOOM_SCREENSHOT, WKC_CTRL | 'D'),
2169 Hotkey ("giant_screenshot", MTHK_GIANT_SCREENSHOT),
2170 Hotkey ("cheats", MTHK_CHEATS, WKC_CTRL | WKC_ALT | 'C'),
2171 Hotkey ("terraform", MTHK_TERRAFORM, 'L'),
2172 Hotkey ("extra_viewport", MTHK_EXTRA_VIEWPORT, 'V'),
2173 #ifdef ENABLE_NETWORK
2174 Hotkey ("client_list", MTHK_CLIENT_LIST),
2175 #endif
2176 Hotkey ("sign_list", MTHK_SIGN_LIST),
2178 HotkeyList MainToolbarWindow::hotkeys("maintoolbar", maintoolbar_hotkeys);
2180 static NWidgetBase *MakeMainToolbar(int *biggest_index)
2182 /** Sprites to use for the different toolbar buttons */
2183 static const SpriteID toolbar_button_sprites[] = {
2184 SPR_IMG_PAUSE, // WID_TN_PAUSE
2185 SPR_IMG_FASTFORWARD, // WID_TN_FAST_FORWARD
2186 SPR_IMG_SETTINGS, // WID_TN_SETTINGS
2187 SPR_IMG_SAVE, // WID_TN_SAVE
2188 SPR_IMG_SMALLMAP, // WID_TN_SMALL_MAP
2189 SPR_IMG_TOWN, // WID_TN_TOWNS
2190 SPR_IMG_SUBSIDIES, // WID_TN_SUBSIDIES
2191 SPR_IMG_COMPANY_LIST, // WID_TN_STATIONS
2192 SPR_IMG_COMPANY_FINANCE, // WID_TN_FINANCES
2193 SPR_IMG_COMPANY_GENERAL, // WID_TN_COMPANIES
2194 SPR_IMG_STORY_BOOK, // WID_TN_STORY
2195 SPR_IMG_GOAL, // WID_TN_GOAL
2196 SPR_IMG_GRAPHS, // WID_TN_GRAPHS
2197 SPR_IMG_COMPANY_LEAGUE, // WID_TN_LEAGUE
2198 SPR_IMG_INDUSTRY, // WID_TN_INDUSTRIES
2199 SPR_IMG_TRAINLIST, // WID_TN_TRAINS
2200 SPR_IMG_TRUCKLIST, // WID_TN_ROADVEHS
2201 SPR_IMG_SHIPLIST, // WID_TN_SHIPS
2202 SPR_IMG_AIRPLANESLIST, // WID_TN_AIRCRAFT
2203 SPR_IMG_ZOOMIN, // WID_TN_ZOOMIN
2204 SPR_IMG_ZOOMOUT, // WID_TN_ZOOMOUT
2205 SPR_IMG_BUILDRAIL, // WID_TN_RAILS
2206 SPR_IMG_BUILDROAD, // WID_TN_ROADS
2207 SPR_IMG_BUILDWATER, // WID_TN_WATER
2208 SPR_IMG_BUILDAIR, // WID_TN_AIR
2209 SPR_IMG_LANDSCAPING, // WID_TN_LANDSCAPE
2210 SPR_IMG_MUSIC, // WID_TN_MUSIC_SOUND
2211 SPR_IMG_MESSAGES, // WID_TN_MESSAGES
2212 SPR_IMG_QUERY, // WID_TN_HELP
2213 SPR_IMG_SWITCH_TOOLBAR, // WID_TN_SWITCH_BAR
2216 NWidgetMainToolbarContainer *hor = new NWidgetMainToolbarContainer();
2217 for (uint i = 0; i < WID_TN_END; i++) {
2218 switch (i) {
2219 case WID_TN_SMALL_MAP:
2220 case WID_TN_FINANCES:
2221 case WID_TN_VEHICLE_START:
2222 case WID_TN_ZOOM_IN:
2223 case WID_TN_BUILDING_TOOLS_START:
2224 case WID_TN_MUSIC_SOUND:
2225 hor->Add(new NWidgetSpacer(0, 0));
2226 break;
2228 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));
2231 *biggest_index = max<int>(*biggest_index, WID_TN_SWITCH_BAR);
2232 return hor;
2235 static const NWidgetPart _nested_toolbar_normal_widgets[] = {
2236 NWidgetFunction(MakeMainToolbar),
2239 static const WindowDesc _toolb_normal_desc(
2240 WDP_MANUAL, 0, 0,
2241 WC_MAIN_TOOLBAR, WC_NONE,
2242 WDF_NO_FOCUS,
2243 _nested_toolbar_normal_widgets, lengthof(_nested_toolbar_normal_widgets),
2244 NULL, &MainToolbarWindow::hotkeys
2248 /* --- Toolbar handling for the scenario editor */
2250 static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
2251 ToolbarPauseClick,
2252 ToolbarFastForwardClick,
2253 ToolbarOptionsClick,
2254 ToolbarScenSaveOrLoad,
2255 ToolbarBtn_NULL,
2256 ToolbarScenDatePanel,
2257 ToolbarScenDateBackward,
2258 ToolbarScenDateForward,
2259 ToolbarScenMapTownDir,
2260 ToolbarZoomInClick,
2261 ToolbarZoomOutClick,
2262 ToolbarScenGenLand,
2263 ToolbarScenGenTown,
2264 ToolbarScenGenIndustry,
2265 ToolbarScenBuildRoad,
2266 ToolbarScenBuildDocks,
2267 ToolbarScenPlantTrees,
2268 ToolbarScenPlaceSign,
2269 ToolbarBtn_NULL,
2270 NULL,
2271 NULL,
2272 NULL,
2273 NULL,
2274 NULL,
2275 NULL,
2276 NULL,
2277 ToolbarMusicClick,
2278 NULL,
2279 ToolbarHelpClick,
2280 ToolbarSwitchClick,
2283 enum MainToolbarEditorHotkeys {
2284 MTEHK_PAUSE,
2285 MTEHK_FASTFORWARD,
2286 MTEHK_SETTINGS,
2287 MTEHK_SAVEGAME,
2288 MTEHK_GENLAND,
2289 MTEHK_GENTOWN,
2290 MTEHK_GENINDUSTRY,
2291 MTEHK_BUILD_ROAD,
2292 MTEHK_BUILD_DOCKS,
2293 MTEHK_BUILD_TREES,
2294 MTEHK_SIGN,
2295 MTEHK_MUSIC,
2296 MTEHK_LANDINFO,
2297 MTEHK_SMALL_SCREENSHOT,
2298 MTEHK_ZOOMEDIN_SCREENSHOT,
2299 MTEHK_DEFAULTZOOM_SCREENSHOT,
2300 MTEHK_GIANT_SCREENSHOT,
2301 MTEHK_ZOOM_IN,
2302 MTEHK_ZOOM_OUT,
2303 MTEHK_TERRAFORM,
2304 MTEHK_SMALLMAP,
2305 MTEHK_EXTRA_VIEWPORT,
2308 struct ScenarioEditorToolbarWindow : Window {
2309 ScenarioEditorToolbarWindow (const WindowDesc *desc) : Window (desc)
2311 this->InitNested(0);
2313 _last_started_action = CBF_NONE;
2314 CLRBITS(this->flags, WF_WHITE_BORDER);
2315 PositionMainToolbar(this);
2316 this->InvalidateData();
2319 virtual void FindWindowPlacementAndResize(int def_width, int def_height)
2321 Window::FindWindowPlacementAndResize(_toolbar_width, def_height);
2324 void OnPaint (BlitArea *dpi) OVERRIDE
2326 this->SetWidgetDisabledState(WID_TE_DATE_BACKWARD, _settings_game.game_creation.starting_year <= MIN_YEAR);
2327 this->SetWidgetDisabledState(WID_TE_DATE_FORWARD, _settings_game.game_creation.starting_year >= MAX_YEAR);
2329 this->DrawWidgets (dpi);
2332 void DrawWidget (BlitArea *dpi, const Rect &r, int widget) const OVERRIDE
2334 switch (widget) {
2335 case WID_TE_DATE:
2336 SetDParam(0, ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
2337 DrawString (dpi, r.left, r.right, (this->height - FONT_HEIGHT_NORMAL) / 2, STR_WHITE_DATE_LONG, TC_FROMSTRING, SA_HOR_CENTER);
2338 break;
2340 case WID_TE_SPACER: {
2341 int height = r.bottom - r.top;
2342 if (height > 2 * FONT_HEIGHT_NORMAL) {
2343 DrawString (dpi, r.left, r.right, (height + 1) / 2 - FONT_HEIGHT_NORMAL, STR_SCENEDIT_TOOLBAR_OPENTTD, TC_FROMSTRING, SA_HOR_CENTER);
2344 DrawString (dpi, r.left, r.right, (height + 1) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
2345 } else {
2346 DrawString (dpi, r.left, r.right, (height - FONT_HEIGHT_NORMAL) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
2348 break;
2353 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2355 switch (widget) {
2356 case WID_TE_SPACER:
2357 size->width = max(GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_OPENTTD).width, GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR).width) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
2358 break;
2360 case WID_TE_DATE:
2361 SetDParam(0, ConvertYMDToDate(MAX_YEAR, 0, 1));
2362 *size = GetStringBoundingBox(STR_WHITE_DATE_LONG);
2363 size->height = max(size->height, GetSpriteSize(SPR_IMG_SAVE).height + WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM);
2364 break;
2368 virtual void OnClick(Point pt, int widget, int click_count)
2370 if (_game_mode == GM_MENU) return;
2371 CallBackFunction cbf = _scen_toolbar_button_procs[widget](this);
2372 if (cbf != CBF_NONE) _last_started_action = cbf;
2375 virtual void OnDropdownSelect(int widget, int index)
2377 /* The map button is in a different location on the scenario
2378 * editor toolbar, so we need to adjust for it. */
2379 if (widget == WID_TE_SMALL_MAP) widget = WID_TN_SMALL_MAP;
2380 CallBackFunction cbf = _menu_clicked_procs[widget](index);
2381 if (cbf != CBF_NONE) _last_started_action = cbf;
2382 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
2385 virtual EventState OnHotkey(int hotkey)
2387 CallBackFunction cbf = CBF_NONE;
2388 switch (hotkey) {
2389 case MTEHK_PAUSE: ToolbarPauseClick(this); break;
2390 case MTEHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
2391 case MTEHK_SETTINGS: ShowGameOptions(); break;
2392 case MTEHK_SAVEGAME: MenuClickSaveLoad(); break;
2393 case MTEHK_GENLAND: ToolbarScenGenLand(this); break;
2394 case MTEHK_GENTOWN: ToolbarScenGenTown(this); break;
2395 case MTEHK_GENINDUSTRY: ToolbarScenGenIndustry(this); break;
2396 case MTEHK_BUILD_ROAD: ToolbarScenBuildRoad(this); break;
2397 case MTEHK_BUILD_DOCKS: ToolbarScenBuildDocks(this); break;
2398 case MTEHK_BUILD_TREES: ToolbarScenPlantTrees(this); break;
2399 case MTEHK_SIGN: cbf = ToolbarScenPlaceSign(this); break;
2400 case MTEHK_MUSIC: ShowMusicWindow(); break;
2401 case MTEHK_LANDINFO: cbf = PlaceLandBlockInfo(); break;
2402 case MTEHK_SMALL_SCREENSHOT: MenuClickSmallScreenshot(); break;
2403 case MTEHK_ZOOMEDIN_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
2404 case MTEHK_DEFAULTZOOM_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
2405 case MTEHK_GIANT_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_WORLD); break;
2406 case MTEHK_ZOOM_IN: ToolbarZoomInClick(this); break;
2407 case MTEHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
2408 case MTEHK_TERRAFORM: ShowEditorTerraformToolbar(); break;
2409 case MTEHK_SMALLMAP: ShowSmallMap(); break;
2410 case MTEHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
2411 default: return ES_NOT_HANDLED;
2413 if (cbf != CBF_NONE) _last_started_action = cbf;
2414 return ES_HANDLED;
2417 virtual void OnPlaceObject(Point pt, TileIndex tile)
2419 switch (_last_started_action) {
2420 case CBF_PLACE_SIGN:
2421 PlaceProc_Sign(tile);
2422 break;
2424 case CBF_PLACE_LANDINFO:
2425 ShowLandInfo(tile);
2426 break;
2428 default: NOT_REACHED();
2432 virtual void OnPlaceObjectAbort()
2434 _last_started_action = CBF_NONE;
2437 virtual void OnTimeout()
2439 this->SetWidgetsLoweredState(false, WID_TE_DATE_BACKWARD, WID_TE_DATE_FORWARD, WIDGET_LIST_END);
2440 this->SetWidgetDirty(WID_TE_DATE_BACKWARD);
2441 this->SetWidgetDirty(WID_TE_DATE_FORWARD);
2444 virtual void OnTick()
2446 if (this->IsWidgetLowered(WID_TE_PAUSE) != !!_pause_mode) {
2447 this->ToggleWidgetLoweredState(WID_TE_PAUSE);
2448 this->SetDirty();
2451 if (this->IsWidgetLowered(WID_TE_FAST_FORWARD) != !!_fast_forward) {
2452 this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD);
2453 this->SetDirty();
2458 * Some data on this window has become invalid.
2459 * @param data Information about the changed data.
2460 * @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.
2462 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2464 if (!gui_scope) return;
2465 if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, WID_TE_ZOOM_IN, WID_TE_ZOOM_OUT);
2468 virtual void OnQueryTextFinished(char *str)
2470 /* Was 'cancel' pressed? */
2471 if (str == NULL) return;
2473 int32 value;
2474 if (!StrEmpty(str)) {
2475 value = atoi(str);
2476 } else {
2477 /* An empty string means revert to the default */
2478 value = DEF_START_YEAR;
2480 SetStartingYear(value);
2482 this->SetDirty();
2485 static HotkeyList hotkeys;
2488 static const Hotkey scenedit_maintoolbar_hotkeys[] = {
2489 Hotkey ("pause", MTEHK_PAUSE, WKC_F1, WKC_PAUSE),
2490 Hotkey ("fastforward", MTEHK_FASTFORWARD),
2491 Hotkey ("settings", MTEHK_SETTINGS, WKC_F2),
2492 Hotkey ("saveload", MTEHK_SAVEGAME, WKC_F3),
2493 Hotkey ("gen_land", MTEHK_GENLAND, WKC_F4),
2494 Hotkey ("gen_town", MTEHK_GENTOWN, WKC_F5),
2495 Hotkey ("gen_industry", MTEHK_GENINDUSTRY, WKC_F6),
2496 Hotkey ("build_road", MTEHK_BUILD_ROAD, WKC_F7),
2497 Hotkey ("build_docks", MTEHK_BUILD_DOCKS, WKC_F8),
2498 Hotkey ("build_trees", MTEHK_BUILD_TREES, WKC_F9),
2499 Hotkey ("build_sign", MTEHK_SIGN, WKC_F10),
2500 Hotkey ("music", MTEHK_MUSIC, WKC_F11),
2501 Hotkey ("land_info", MTEHK_LANDINFO, WKC_F12),
2502 Hotkey ("small_screenshot", MTEHK_SMALL_SCREENSHOT, WKC_CTRL | 'S'),
2503 Hotkey ("zoomedin_screenshot", MTEHK_ZOOMEDIN_SCREENSHOT, WKC_CTRL | 'P'),
2504 Hotkey ("defaultzoom_screenshot", MTEHK_DEFAULTZOOM_SCREENSHOT, WKC_CTRL | 'D'),
2505 Hotkey ("giant_screenshot", MTEHK_GIANT_SCREENSHOT),
2506 Hotkey ("zoomin", MTEHK_ZOOM_IN, WKC_SHIFT | WKC_F5, WKC_NUM_PLUS, WKC_EQUALS, WKC_SHIFT | WKC_EQUALS),
2507 Hotkey ("zoomout", MTEHK_ZOOM_OUT, WKC_SHIFT | WKC_F6, WKC_NUM_MINUS, WKC_MINUS, WKC_SHIFT | WKC_MINUS),
2508 Hotkey ("terraform", MTEHK_TERRAFORM, 'L'),
2509 Hotkey ("smallmap", MTEHK_SMALLMAP, 'M'),
2510 Hotkey ("extra_viewport", MTEHK_EXTRA_VIEWPORT, 'V'),
2512 HotkeyList ScenarioEditorToolbarWindow::hotkeys("scenedit_maintoolbar", scenedit_maintoolbar_hotkeys);
2514 static const NWidgetPart _nested_toolb_scen_inner_widgets[] = {
2515 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_PAUSE), SetDataTip(SPR_IMG_PAUSE, STR_TOOLBAR_TOOLTIP_PAUSE_GAME),
2516 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_FAST_FORWARD), SetDataTip(SPR_IMG_FASTFORWARD, STR_TOOLBAR_TOOLTIP_FORWARD),
2517 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SETTINGS), SetDataTip(SPR_IMG_SETTINGS, STR_TOOLBAR_TOOLTIP_OPTIONS),
2518 NWidget(WWT_IMGBTN_2, COLOUR_GREY, WID_TE_SAVE), SetDataTip(SPR_IMG_SAVE, STR_SCENEDIT_TOOLBAR_TOOLTIP_SAVE_SCENARIO_LOAD_SCENARIO),
2519 NWidget(NWID_SPACER),
2520 NWidget(WWT_PANEL, COLOUR_GREY, WID_TE_SPACER), EndContainer(),
2521 NWidget(NWID_SPACER),
2522 NWidget(WWT_PANEL, COLOUR_GREY, WID_TE_DATE_PANEL),
2523 NWidget(NWID_HORIZONTAL), SetPIP(3, 2, 3),
2524 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_DATE_BACKWARD), SetDataTip(SPR_ARROW_DOWN, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD),
2525 NWidget(WWT_EMPTY, COLOUR_GREY, WID_TE_DATE), SetDataTip(STR_NULL, STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE),
2526 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_DATE_FORWARD), SetDataTip(SPR_ARROW_UP, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD),
2527 EndContainer(),
2528 EndContainer(),
2529 NWidget(NWID_SPACER),
2530 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SMALL_MAP), SetDataTip(SPR_IMG_SMALLMAP, STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY),
2531 NWidget(NWID_SPACER),
2532 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_IN), SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN),
2533 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_OUT), SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT),
2534 NWidget(NWID_SPACER),
2535 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_LAND_GENERATE), SetDataTip(SPR_IMG_LANDSCAPING, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION),
2536 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TOWN_GENERATE), SetDataTip(SPR_IMG_TOWN, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION),
2537 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_INDUSTRY), SetDataTip(SPR_IMG_INDUSTRY, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION),
2538 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ROADS), SetDataTip(SPR_IMG_BUILDROAD, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION),
2539 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_WATER), SetDataTip(SPR_IMG_BUILDWATER, STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS),
2540 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TREES), SetDataTip(SPR_IMG_PLANTTREES, STR_SCENEDIT_TOOLBAR_PLANT_TREES),
2541 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_SIGNS), SetDataTip(SPR_IMG_SIGN, STR_SCENEDIT_TOOLBAR_PLACE_SIGN),
2542 NWidget(NWID_SPACER),
2543 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_MUSIC_SOUND), SetDataTip(SPR_IMG_MUSIC, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW),
2544 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_HELP), SetDataTip(SPR_IMG_QUERY, STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION),
2545 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SWITCH_BAR), SetDataTip(SPR_IMG_SWITCH_TOOLBAR, STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR),
2548 static NWidgetBase *MakeScenarioToolbar(int *biggest_index)
2550 return MakeNWidgets(_nested_toolb_scen_inner_widgets, lengthof(_nested_toolb_scen_inner_widgets), biggest_index, new NWidgetScenarioToolbarContainer());
2553 static const NWidgetPart _nested_toolb_scen_widgets[] = {
2554 NWidgetFunction(MakeScenarioToolbar),
2557 static const WindowDesc _toolb_scen_desc(
2558 WDP_MANUAL, 0, 0,
2559 WC_MAIN_TOOLBAR, WC_NONE,
2560 WDF_NO_FOCUS,
2561 _nested_toolb_scen_widgets, lengthof(_nested_toolb_scen_widgets),
2562 NULL, &ScenarioEditorToolbarWindow::hotkeys
2565 /** Allocate the toolbar. */
2566 void AllocateToolbar()
2568 /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
2569 _last_built_roadtype = ROADTYPE_ROAD;
2571 if (_game_mode == GM_EDITOR) {
2572 new ScenarioEditorToolbarWindow(&_toolb_scen_desc);
2573 } else {
2574 new MainToolbarWindow(&_toolb_normal_desc);