(svn r28004) -Update from Eints:
[openttd.git] / src / toolbar_gui.cpp
blobf253be8b3aa28d4e656983765d5d58d84de507c4
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"
57 #include "safeguards.h"
60 /** Width of the toolbar, shared by statusbar. */
61 uint _toolbar_width = 0;
63 RailType _last_built_railtype;
64 RoadType _last_built_roadtype;
66 static ScreenshotType _confirmed_screenshot_type; ///< Screenshot type the current query is about to confirm.
68 /** Toobar modes */
69 enum ToolbarMode {
70 TB_NORMAL,
71 TB_UPPER,
72 TB_LOWER
75 /** Callback functions. */
76 enum CallBackFunction {
77 CBF_NONE,
78 CBF_PLACE_SIGN,
79 CBF_PLACE_LANDINFO,
82 static CallBackFunction _last_started_action = CBF_NONE; ///< Last started user action.
85 /**
86 * Drop down list entry for showing a checked/unchecked toggle item.
88 class DropDownListCheckedItem : public DropDownListStringItem {
89 uint checkmark_width;
90 public:
91 bool checked;
93 DropDownListCheckedItem(StringID string, int result, bool masked, bool checked) : DropDownListStringItem(string, result, masked), checked(checked)
95 this->checkmark_width = GetStringBoundingBox(STR_JUST_CHECKMARK).width + 3;
98 virtual ~DropDownListCheckedItem() {}
100 uint Width() const
102 return DropDownListStringItem::Width() + this->checkmark_width;
105 void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
107 bool rtl = _current_text_dir == TD_RTL;
108 if (this->checked) {
109 DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, STR_JUST_CHECKMARK, sel ? TC_WHITE : TC_BLACK);
111 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);
116 * Drop down list entry for showing a company entry, with companies 'blob'.
118 class DropDownListCompanyItem : public DropDownListItem {
119 Dimension icon_size;
120 public:
121 bool greyed;
123 DropDownListCompanyItem(int result, bool masked, bool greyed) : DropDownListItem(result, masked), greyed(greyed)
125 this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
128 virtual ~DropDownListCompanyItem() {}
130 bool Selectable() const
132 return true;
135 uint Width() const
137 CompanyID company = (CompanyID)this->result;
138 SetDParam(0, company);
139 SetDParam(1, company);
140 return GetStringBoundingBox(STR_COMPANY_NAME_COMPANY_NUM).width + this->icon_size.width + 3;
143 uint Height(uint width) const
145 return max(this->icon_size.height + 2U, (uint)FONT_HEIGHT_NORMAL);
148 void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
150 CompanyID company = (CompanyID)this->result;
151 bool rtl = _current_text_dir == TD_RTL;
153 /* It's possible the company is deleted while the dropdown is open */
154 if (!Company::IsValidID(company)) return;
156 int icon_offset = (bottom - top - icon_size.height) / 2;
157 int text_offset = (bottom - top - FONT_HEIGHT_NORMAL) / 2;
159 DrawCompanyIcon(company, rtl ? right - this->icon_size.width - WD_FRAMERECT_RIGHT : left + WD_FRAMERECT_LEFT, top + icon_offset);
161 SetDParam(0, company);
162 SetDParam(1, company);
163 TextColour col;
164 if (this->greyed) {
165 col = (sel ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
166 } else {
167 col = sel ? TC_WHITE : TC_BLACK;
169 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);
174 * Pop up a generic text only menu.
175 * @param w Toolbar
176 * @param widget Toolbar button
177 * @param list List of items
178 * @param def Default item
180 static void PopupMainToolbMenu(Window *w, int widget, DropDownList *list, int def)
182 ShowDropDownList(w, list, def, widget, 0, true, true);
183 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
187 * Pop up a generic text only menu.
188 * @param w Toolbar
189 * @param widget Toolbar button
190 * @param string String for the first item in the menu
191 * @param count Number of items in the menu
193 static void PopupMainToolbMenu(Window *w, int widget, StringID string, int count)
195 DropDownList *list = new DropDownList();
196 for (int i = 0; i < count; i++) {
197 *list->Append() = new DropDownListStringItem(string + i, i, false);
199 PopupMainToolbMenu(w, widget, list, 0);
202 /** Enum for the Company Toolbar's network related buttons */
203 static const int CTMN_CLIENT_LIST = -1; ///< Show the client list
204 static const int CTMN_NEW_COMPANY = -2; ///< Create a new company
205 static const int CTMN_SPECTATE = -3; ///< Become spectator
206 static const int CTMN_SPECTATOR = -4; ///< Show a company window as spectator
209 * Pop up a generic company list menu.
210 * @param w The toolbar window.
211 * @param widget The button widget id.
212 * @param grey A bitbask of which items to mark as disabled.
213 * @param include_spectator If true, a spectator option is included in the list.
215 static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0, bool include_spectator = false)
217 DropDownList *list = new DropDownList();
219 #ifdef ENABLE_NETWORK
220 if (_networking) {
221 if (widget == WID_TN_COMPANIES) {
222 /* Add the client list button for the companies menu */
223 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false);
226 if (include_spectator) {
227 if (widget == WID_TN_COMPANIES) {
228 if (_local_company == COMPANY_SPECTATOR) {
229 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached());
230 } else {
231 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, NetworkMaxSpectatorsReached());
233 } else {
234 *list->Append() = new DropDownListStringItem(STR_NETWORK_TOOLBAR_LIST_SPECTATOR, CTMN_SPECTATOR, false);
238 #endif /* ENABLE_NETWORK */
240 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
241 if (!Company::IsValidID(c)) continue;
242 *list->Append() = new DropDownListCompanyItem(c, false, HasBit(grey, c));
245 PopupMainToolbMenu(w, widget, list, _local_company == COMPANY_SPECTATOR ? CTMN_CLIENT_LIST : (int)_local_company);
249 static ToolbarMode _toolbar_mode;
251 static CallBackFunction SelectSignTool()
253 if (_last_started_action == CBF_PLACE_SIGN) {
254 ResetObjectToPlace();
255 return CBF_NONE;
256 } else {
257 SetObjectToPlace(SPR_CURSOR_SIGN, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0);
258 return CBF_PLACE_SIGN;
262 /* --- Pausing --- */
264 static CallBackFunction ToolbarPauseClick(Window *w)
266 if (_networking && !_network_server) return CBF_NONE; // only server can pause the game
268 if (DoCommandP(0, PM_PAUSED_NORMAL, _pause_mode == PM_UNPAUSED, CMD_PAUSE)) {
269 if (_settings_client.sound.confirm) SndPlayFx(SND_15_BEEP);
271 return CBF_NONE;
275 * Toggle fast forward mode.
277 * @param w Unused.
278 * @return #CBF_NONE
280 static CallBackFunction ToolbarFastForwardClick(Window *w)
282 _fast_forward ^= true;
283 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
284 return CBF_NONE;
288 * Game Option button menu entries.
290 enum OptionMenuEntries {
291 OME_GAMEOPTIONS,
292 OME_SETTINGS,
293 OME_SCRIPT_SETTINGS,
294 OME_NEWGRFSETTINGS,
295 OME_TRANSPARENCIES,
296 OME_SHOW_TOWNNAMES,
297 OME_SHOW_STATIONNAMES,
298 OME_SHOW_WAYPOINTNAMES,
299 OME_SHOW_SIGNS,
300 OME_SHOW_COMPETITOR_SIGNS,
301 OME_FULL_ANIMATION,
302 OME_FULL_DETAILS,
303 OME_TRANSPARENTBUILDINGS,
304 OME_SHOW_STATIONSIGNS,
308 * Handle click on Options button in toolbar.
310 * @param w parent window the shown Drop down list is attached to.
311 * @return #CBF_NONE
313 static CallBackFunction ToolbarOptionsClick(Window *w)
315 DropDownList *list = new DropDownList();
316 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS, OME_GAMEOPTIONS, false);
317 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE, OME_SETTINGS, false);
318 /* Changes to the per-AI settings don't get send from the server to the clients. Clients get
319 * the settings once they join but never update it. As such don't show the window at all
320 * to network clients. */
321 if (!_networking || _network_server) *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS, OME_SCRIPT_SETTINGS, false);
322 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS, OME_NEWGRFSETTINGS, false);
323 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS, OME_TRANSPARENCIES, false);
324 *list->Append() = new DropDownListItem(-1, false);
325 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED, OME_SHOW_TOWNNAMES, false, HasBit(_display_opt, DO_SHOW_TOWN_NAMES));
326 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED, OME_SHOW_STATIONNAMES, false, HasBit(_display_opt, DO_SHOW_STATION_NAMES));
327 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED, OME_SHOW_WAYPOINTNAMES, false, HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES));
328 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED, OME_SHOW_SIGNS, false, HasBit(_display_opt, DO_SHOW_SIGNS));
329 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS, OME_SHOW_COMPETITOR_SIGNS, false, HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS));
330 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION, OME_FULL_ANIMATION, false, HasBit(_display_opt, DO_FULL_ANIMATION));
331 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL, OME_FULL_DETAILS, false, HasBit(_display_opt, DO_FULL_DETAIL));
332 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS, OME_TRANSPARENTBUILDINGS, false, IsTransparencySet(TO_HOUSES));
333 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS, OME_SHOW_STATIONSIGNS, false, IsTransparencySet(TO_SIGNS));
335 ShowDropDownList(w, list, 0, WID_TN_SETTINGS, 140, true, true);
336 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
337 return CBF_NONE;
341 * Handle click on one of the entries in the Options button menu.
343 * @param index Index being clicked.
344 * @return #CBF_NONE
346 static CallBackFunction MenuClickSettings(int index)
348 switch (index) {
349 case OME_GAMEOPTIONS: ShowGameOptions(); return CBF_NONE;
350 case OME_SETTINGS: ShowGameSettings(); return CBF_NONE;
351 case OME_SCRIPT_SETTINGS: ShowAIConfigWindow(); return CBF_NONE;
352 case OME_NEWGRFSETTINGS: ShowNewGRFSettings(!_networking && _settings_client.gui.UserIsAllowedToChangeNewGRFs(), true, true, &_grfconfig); return CBF_NONE;
353 case OME_TRANSPARENCIES: ShowTransparencyToolbar(); break;
355 case OME_SHOW_TOWNNAMES: ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES); break;
356 case OME_SHOW_STATIONNAMES: ToggleBit(_display_opt, DO_SHOW_STATION_NAMES); break;
357 case OME_SHOW_WAYPOINTNAMES: ToggleBit(_display_opt, DO_SHOW_WAYPOINT_NAMES); break;
358 case OME_SHOW_SIGNS: ToggleBit(_display_opt, DO_SHOW_SIGNS); break;
359 case OME_SHOW_COMPETITOR_SIGNS:
360 ToggleBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS);
361 InvalidateWindowClassesData(WC_SIGN_LIST, -1);
362 break;
363 case OME_FULL_ANIMATION: ToggleBit(_display_opt, DO_FULL_ANIMATION); CheckBlitter(); break;
364 case OME_FULL_DETAILS: ToggleBit(_display_opt, DO_FULL_DETAIL); break;
365 case OME_TRANSPARENTBUILDINGS: ToggleTransparency(TO_HOUSES); break;
366 case OME_SHOW_STATIONSIGNS: ToggleTransparency(TO_SIGNS); break;
368 MarkWholeScreenDirty();
369 return CBF_NONE;
373 * SaveLoad entries in scenario editor mode.
375 enum SaveLoadEditorMenuEntries {
376 SLEME_SAVE_SCENARIO = 0,
377 SLEME_LOAD_SCENARIO,
378 SLEME_SAVE_HEIGHTMAP,
379 SLEME_LOAD_HEIGHTMAP,
380 SLEME_EXIT_TOINTRO,
381 SLEME_EXIT_GAME = 6,
382 SLEME_MENUCOUNT,
386 * SaveLoad entries in normal game mode.
388 enum SaveLoadNormalMenuEntries {
389 SLNME_SAVE_GAME = 0,
390 SLNME_LOAD_GAME,
391 SLNME_EXIT_TOINTRO,
392 SLNME_EXIT_GAME = 4,
393 SLNME_MENUCOUNT,
397 * Handle click on Save button in toolbar in normal game mode.
399 * @param w parent window the shown save dialogue is attached to.
400 * @return #CBF_NONE
402 static CallBackFunction ToolbarSaveClick(Window *w)
404 PopupMainToolbMenu(w, WID_TN_SAVE, STR_FILE_MENU_SAVE_GAME, SLNME_MENUCOUNT);
405 return CBF_NONE;
409 * Handle click on SaveLoad button in toolbar in the scenario editor.
411 * @param w parent window the shown save dialogue is attached to.
412 * @return #CBF_NONE
414 static CallBackFunction ToolbarScenSaveOrLoad(Window *w)
416 PopupMainToolbMenu(w, WID_TE_SAVE, STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO, SLEME_MENUCOUNT);
417 return CBF_NONE;
421 * Handle click on one of the entries in the SaveLoad menu.
423 * @param index Index being clicked.
424 * @return #CBF_NONE
426 static CallBackFunction MenuClickSaveLoad(int index = 0)
428 if (_game_mode == GM_EDITOR) {
429 switch (index) {
430 case SLEME_SAVE_SCENARIO: ShowSaveLoadDialog(FT_SCENARIO, SLO_SAVE); break;
431 case SLEME_LOAD_SCENARIO: ShowSaveLoadDialog(FT_SCENARIO, SLO_LOAD); break;
432 case SLEME_SAVE_HEIGHTMAP: ShowSaveLoadDialog(FT_HEIGHTMAP,SLO_SAVE); break;
433 case SLEME_LOAD_HEIGHTMAP: ShowSaveLoadDialog(FT_HEIGHTMAP,SLO_LOAD); break;
434 case SLEME_EXIT_TOINTRO: AskExitToGameMenu(); break;
435 case SLEME_EXIT_GAME: HandleExitGameRequest(); break;
437 } else {
438 switch (index) {
439 case SLNME_SAVE_GAME: ShowSaveLoadDialog(FT_SAVEGAME, SLO_SAVE); break;
440 case SLNME_LOAD_GAME: ShowSaveLoadDialog(FT_SAVEGAME, SLO_LOAD); break;
441 case SLNME_EXIT_TOINTRO: AskExitToGameMenu(); break;
442 case SLNME_EXIT_GAME: HandleExitGameRequest(); break;
445 return CBF_NONE;
448 /* --- Map button menu --- */
450 enum MapMenuEntries {
451 MME_SHOW_SMALLMAP = 0,
452 MME_SHOW_EXTRAVIEWPORTS,
453 MME_SHOW_LINKGRAPH,
454 MME_SHOW_SIGNLISTS,
455 MME_SHOW_TOWNDIRECTORY,
456 MME_SHOW_INDUSTRYDIRECTORY,
459 static CallBackFunction ToolbarMapClick(Window *w)
461 DropDownList *list = new DropDownList();
462 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false);
463 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false);
464 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_LINGRAPH_LEGEND, MME_SHOW_LINKGRAPH, false);
465 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false);
466 PopupMainToolbMenu(w, WID_TN_SMALL_MAP, list, 0);
467 return CBF_NONE;
470 static CallBackFunction ToolbarScenMapTownDir(Window *w)
472 DropDownList *list = new DropDownList();
473 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false);
474 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false);
475 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false);
476 *list->Append() = new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY, MME_SHOW_TOWNDIRECTORY, false);
477 *list->Append() = new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, MME_SHOW_INDUSTRYDIRECTORY, false);
478 PopupMainToolbMenu(w, WID_TE_SMALL_MAP, list, 0);
479 return CBF_NONE;
483 * Handle click on one of the entries in the Map menu.
485 * @param index Index being clicked.
486 * @return #CBF_NONE
488 static CallBackFunction MenuClickMap(int index)
490 switch (index) {
491 case MME_SHOW_SMALLMAP: ShowSmallMap(); break;
492 case MME_SHOW_EXTRAVIEWPORTS: ShowExtraViewPortWindow(); break;
493 case MME_SHOW_LINKGRAPH: ShowLinkGraphLegend(); break;
494 case MME_SHOW_SIGNLISTS: ShowSignList(); break;
495 case MME_SHOW_TOWNDIRECTORY: ShowTownDirectory(); break;
496 case MME_SHOW_INDUSTRYDIRECTORY: ShowIndustryDirectory(); break;
498 return CBF_NONE;
501 /* --- Town button menu --- */
503 static CallBackFunction ToolbarTownClick(Window *w)
505 PopupMainToolbMenu(w, WID_TN_TOWNS, STR_TOWN_MENU_TOWN_DIRECTORY, (_settings_game.economy.found_town == TF_FORBIDDEN) ? 1 : 2);
506 return CBF_NONE;
510 * Handle click on one of the entries in the Town menu.
512 * @param index Index being clicked.
513 * @return #CBF_NONE
515 static CallBackFunction MenuClickTown(int index)
517 switch (index) {
518 case 0: ShowTownDirectory(); break;
519 case 1: // setting could be changed when the dropdown was open
520 if (_settings_game.economy.found_town != TF_FORBIDDEN) ShowFoundTownWindow();
521 break;
523 return CBF_NONE;
526 /* --- Subidies button menu --- */
528 static CallBackFunction ToolbarSubsidiesClick(Window *w)
530 PopupMainToolbMenu(w, WID_TN_SUBSIDIES, STR_SUBSIDIES_MENU_SUBSIDIES, 1);
531 return CBF_NONE;
535 * Handle click on the entry in the Subsidies menu.
537 * @param index Unused.
538 * @return #CBF_NONE
540 static CallBackFunction MenuClickSubsidies(int index)
542 switch (index) {
543 case 0: ShowSubsidiesList(); break;
545 return CBF_NONE;
548 /* --- Stations button menu --- */
550 static CallBackFunction ToolbarStationsClick(Window *w)
552 PopupMainCompanyToolbMenu(w, WID_TN_STATIONS);
553 return CBF_NONE;
557 * Handle click on the entry in the Stations menu
559 * @param index CompanyID to show station list for
560 * @return #CBF_NONE
562 static CallBackFunction MenuClickStations(int index)
564 ShowCompanyStations((CompanyID)index);
565 return CBF_NONE;
568 /* --- Finances button menu --- */
570 static CallBackFunction ToolbarFinancesClick(Window *w)
572 PopupMainCompanyToolbMenu(w, WID_TN_FINANCES);
573 return CBF_NONE;
577 * Handle click on the entry in the finances overview menu.
579 * @param index CompanyID to show finances for.
580 * @return #CBF_NONE
582 static CallBackFunction MenuClickFinances(int index)
584 ShowCompanyFinances((CompanyID)index);
585 return CBF_NONE;
588 /* --- Company's button menu --- */
590 static CallBackFunction ToolbarCompaniesClick(Window *w)
592 PopupMainCompanyToolbMenu(w, WID_TN_COMPANIES, 0, true);
593 return CBF_NONE;
597 * Handle click on the entry in the Company menu.
599 * @param index Menu entry to handle.
600 * @return #CBF_NONE
602 static CallBackFunction MenuClickCompany(int index)
604 #ifdef ENABLE_NETWORK
605 if (_networking) {
606 switch (index) {
607 case CTMN_CLIENT_LIST:
608 ShowClientList();
609 return CBF_NONE;
611 case CTMN_NEW_COMPANY:
612 if (_network_server) {
613 DoCommandP(0, 0, _network_own_client_id, CMD_COMPANY_CTRL);
614 } else {
615 NetworkSendCommand(0, 0, 0, CMD_COMPANY_CTRL, NULL, NULL, _local_company);
617 return CBF_NONE;
619 case CTMN_SPECTATE:
620 if (_network_server) {
621 NetworkServerDoMove(CLIENT_ID_SERVER, COMPANY_SPECTATOR);
622 MarkWholeScreenDirty();
623 } else {
624 NetworkClientRequestMove(COMPANY_SPECTATOR);
626 return CBF_NONE;
629 #endif /* ENABLE_NETWORK */
630 ShowCompany((CompanyID)index);
631 return CBF_NONE;
634 /* --- Story button menu --- */
636 static CallBackFunction ToolbarStoryClick(Window *w)
638 PopupMainCompanyToolbMenu(w, WID_TN_STORY, 0, true);
639 return CBF_NONE;
643 * Handle click on the entry in the Story menu
645 * @param index CompanyID to show story book for
646 * @return #CBF_NONE
648 static CallBackFunction MenuClickStory(int index)
650 ShowStoryBook(index == CTMN_SPECTATOR ? INVALID_COMPANY : (CompanyID)index);
651 return CBF_NONE;
654 /* --- Goal button menu --- */
656 static CallBackFunction ToolbarGoalClick(Window *w)
658 PopupMainCompanyToolbMenu(w, WID_TN_GOAL, 0, true);
659 return CBF_NONE;
663 * Handle click on the entry in the Goal menu
665 * @param index CompanyID to show story book for
666 * @return #CBF_NONE
668 static CallBackFunction MenuClickGoal(int index)
670 ShowGoalsList(index == CTMN_SPECTATOR ? INVALID_COMPANY : (CompanyID)index);
671 return CBF_NONE;
674 /* --- Graphs button menu --- */
676 static CallBackFunction ToolbarGraphsClick(Window *w)
678 PopupMainToolbMenu(w, WID_TN_GRAPHS, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, (_toolbar_mode == TB_NORMAL) ? 6 : 8);
679 return CBF_NONE;
683 * Handle click on the entry in the Graphs menu.
685 * @param index Graph to show.
686 * @return #CBF_NONE
688 static CallBackFunction MenuClickGraphs(int index)
690 switch (index) {
691 case 0: ShowOperatingProfitGraph(); break;
692 case 1: ShowIncomeGraph(); break;
693 case 2: ShowDeliveredCargoGraph(); break;
694 case 3: ShowPerformanceHistoryGraph(); break;
695 case 4: ShowCompanyValueGraph(); break;
696 case 5: ShowCargoPaymentRates(); break;
697 /* functions for combined graphs/league button */
698 case 6: ShowCompanyLeagueTable(); break;
699 case 7: ShowPerformanceRatingDetail(); break;
701 return CBF_NONE;
704 /* --- League button menu --- */
706 static CallBackFunction ToolbarLeagueClick(Window *w)
708 PopupMainToolbMenu(w, WID_TN_LEAGUE, STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE, _networking ? 2 : 3);
709 return CBF_NONE;
713 * Handle click on the entry in the CompanyLeague menu.
715 * @param index Menu entry number.
716 * @return #CBF_NONE
718 static CallBackFunction MenuClickLeague(int index)
720 switch (index) {
721 case 0: ShowCompanyLeagueTable(); break;
722 case 1: ShowPerformanceRatingDetail(); break;
723 case 2: ShowHighscoreTable(); break;
725 return CBF_NONE;
728 /* --- Industries button menu --- */
730 static CallBackFunction ToolbarIndustryClick(Window *w)
732 /* Disable build-industry menu if we are a spectator */
733 PopupMainToolbMenu(w, WID_TN_INDUSTRIES, STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, (_local_company == COMPANY_SPECTATOR) ? 2 : 3);
734 return CBF_NONE;
738 * Handle click on the entry in the Industry menu.
740 * @param index Menu entry number.
741 * @return #CBF_NONE
743 static CallBackFunction MenuClickIndustry(int index)
745 switch (index) {
746 case 0: ShowIndustryDirectory(); break;
747 case 1: ShowIndustryCargoesWindow(); break;
748 case 2: ShowBuildIndustryWindow(); break;
750 return CBF_NONE;
753 /* --- Trains button menu + 1 helper function for all vehicles. --- */
755 static void ToolbarVehicleClick(Window *w, VehicleType veh)
757 const Vehicle *v;
758 int dis = ~0;
760 FOR_ALL_VEHICLES(v) {
761 if (v->type == veh && v->IsPrimaryVehicle()) ClrBit(dis, v->owner);
763 PopupMainCompanyToolbMenu(w, WID_TN_VEHICLE_START + veh, dis);
767 static CallBackFunction ToolbarTrainClick(Window *w)
769 ToolbarVehicleClick(w, VEH_TRAIN);
770 return CBF_NONE;
774 * Handle click on the entry in the Train menu.
776 * @param index CompanyID to show train list for.
777 * @return #CBF_NONE
779 static CallBackFunction MenuClickShowTrains(int index)
781 ShowVehicleListWindow((CompanyID)index, VEH_TRAIN);
782 return CBF_NONE;
785 /* --- Road vehicle button menu --- */
787 static CallBackFunction ToolbarRoadClick(Window *w)
789 ToolbarVehicleClick(w, VEH_ROAD);
790 return CBF_NONE;
794 * Handle click on the entry in the Road Vehicles menu.
796 * @param index CompanyID to show road vehicles list for.
797 * @return #CBF_NONE
799 static CallBackFunction MenuClickShowRoad(int index)
801 ShowVehicleListWindow((CompanyID)index, VEH_ROAD);
802 return CBF_NONE;
805 /* --- Ship button menu --- */
807 static CallBackFunction ToolbarShipClick(Window *w)
809 ToolbarVehicleClick(w, VEH_SHIP);
810 return CBF_NONE;
814 * Handle click on the entry in the Ships menu.
816 * @param index CompanyID to show ship list for.
817 * @return #CBF_NONE
819 static CallBackFunction MenuClickShowShips(int index)
821 ShowVehicleListWindow((CompanyID)index, VEH_SHIP);
822 return CBF_NONE;
825 /* --- Aircraft button menu --- */
827 static CallBackFunction ToolbarAirClick(Window *w)
829 ToolbarVehicleClick(w, VEH_AIRCRAFT);
830 return CBF_NONE;
834 * Handle click on the entry in the Aircraft menu.
836 * @param index CompanyID to show aircraft list for.
837 * @return #CBF_NONE
839 static CallBackFunction MenuClickShowAir(int index)
841 ShowVehicleListWindow((CompanyID)index, VEH_AIRCRAFT);
842 return CBF_NONE;
845 /* --- Zoom in button --- */
847 static CallBackFunction ToolbarZoomInClick(Window *w)
849 if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
850 w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)WID_TE_ZOOM_IN : (byte)WID_TN_ZOOM_IN);
851 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
853 return CBF_NONE;
856 /* --- Zoom out button --- */
858 static CallBackFunction ToolbarZoomOutClick(Window *w)
860 if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) {
861 w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)WID_TE_ZOOM_OUT : (byte)WID_TN_ZOOM_OUT);
862 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
864 return CBF_NONE;
867 /* --- Rail button menu --- */
869 static CallBackFunction ToolbarBuildRailClick(Window *w)
871 ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, WID_TN_RAILS, 140, true, true);
872 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
873 return CBF_NONE;
877 * Handle click on the entry in the Build Rail menu.
879 * @param index RailType to show the build toolbar for.
880 * @return #CBF_NONE
882 static CallBackFunction MenuClickBuildRail(int index)
884 _last_built_railtype = (RailType)index;
885 ShowBuildRailToolbar(_last_built_railtype);
886 return CBF_NONE;
889 /* --- Road button menu --- */
891 static CallBackFunction ToolbarBuildRoadClick(Window *w)
893 const Company *c = Company::Get(_local_company);
894 DropDownList *list = new DropDownList();
896 /* Road is always visible and available. */
897 *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION, ROADTYPE_ROAD, false);
899 /* Tram is only visible when there will be a tram, and available when that has been introduced. */
900 Engine *e;
901 FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
902 if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
903 if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
905 *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION, ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM));
906 break;
908 ShowDropDownList(w, list, _last_built_roadtype, WID_TN_ROADS, 140, true, true);
909 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
910 return CBF_NONE;
914 * Handle click on the entry in the Build Road menu.
916 * @param index RoadType to show the build toolbar for.
917 * @return #CBF_NONE
919 static CallBackFunction MenuClickBuildRoad(int index)
921 _last_built_roadtype = (RoadType)index;
922 ShowBuildRoadToolbar(_last_built_roadtype);
923 return CBF_NONE;
926 /* --- Water button menu --- */
928 static CallBackFunction ToolbarBuildWaterClick(Window *w)
930 PopupMainToolbMenu(w, WID_TN_WATER, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION, 1);
931 return CBF_NONE;
935 * Handle click on the entry in the Build Waterways menu.
937 * @param index Unused.
938 * @return #CBF_NONE
940 static CallBackFunction MenuClickBuildWater(int index)
942 ShowBuildDocksToolbar();
943 return CBF_NONE;
946 /* --- Airport button menu --- */
948 static CallBackFunction ToolbarBuildAirClick(Window *w)
950 PopupMainToolbMenu(w, WID_TN_AIR, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION, 1);
951 return CBF_NONE;
955 * Handle click on the entry in the Build Air menu.
957 * @param index Unused.
958 * @return #CBF_NONE
960 static CallBackFunction MenuClickBuildAir(int index)
962 ShowBuildAirToolbar();
963 return CBF_NONE;
966 /* --- Forest button menu --- */
968 static CallBackFunction ToolbarForestClick(Window *w)
970 PopupMainToolbMenu(w, WID_TN_LANDSCAPE, STR_LANDSCAPING_MENU_LANDSCAPING, 3);
971 return CBF_NONE;
975 * Handle click on the entry in the landscaping menu.
977 * @param index Menu entry clicked.
978 * @return #CBF_NONE
980 static CallBackFunction MenuClickForest(int index)
982 switch (index) {
983 case 0: ShowTerraformToolbar(); break;
984 case 1: ShowBuildTreesToolbar(); break;
985 case 2: return SelectSignTool();
987 return CBF_NONE;
990 /* --- Music button menu --- */
992 static CallBackFunction ToolbarMusicClick(Window *w)
994 PopupMainToolbMenu(w, WID_TN_MUSIC_SOUND, STR_TOOLBAR_SOUND_MUSIC, 1);
995 return CBF_NONE;
999 * Handle click on the entry in the Music menu.
1001 * @param index Unused.
1002 * @return #CBF_NONE
1004 static CallBackFunction MenuClickMusicWindow(int index)
1006 ShowMusicWindow();
1007 return CBF_NONE;
1010 /* --- Newspaper button menu --- */
1012 static CallBackFunction ToolbarNewspaperClick(Window *w)
1014 PopupMainToolbMenu(w, WID_TN_MESSAGES, STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT, 2);
1015 return CBF_NONE;
1019 * Handle click on the entry in the Newspaper menu.
1021 * @param index Menu entry clicked.
1022 * @return #CBF_NONE
1024 static CallBackFunction MenuClickNewspaper(int index)
1026 switch (index) {
1027 case 0: ShowLastNewsMessage(); break;
1028 case 1: ShowMessageHistory(); break;
1030 return CBF_NONE;
1033 /* --- Help button menu --- */
1035 static CallBackFunction PlaceLandBlockInfo()
1037 if (_last_started_action == CBF_PLACE_LANDINFO) {
1038 ResetObjectToPlace();
1039 return CBF_NONE;
1040 } else {
1041 SetObjectToPlace(SPR_CURSOR_QUERY, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0);
1042 return CBF_PLACE_LANDINFO;
1046 static CallBackFunction ToolbarHelpClick(Window *w)
1048 PopupMainToolbMenu(w, WID_TN_HELP, STR_ABOUT_MENU_LAND_BLOCK_INFO, _settings_client.gui.newgrf_developer_tools ? 12 : 9);
1049 return CBF_NONE;
1052 static void MenuClickSmallScreenshot()
1054 MakeScreenshot(SC_VIEWPORT, NULL);
1058 * Callback on the confirmation window for huge screenshots.
1059 * @param w Window with viewport
1060 * @param confirmed true on confirmation
1062 static void ScreenshotConfirmCallback(Window *w, bool confirmed)
1064 if (confirmed) MakeScreenshot(_confirmed_screenshot_type, NULL);
1068 * Make a screenshot of the world.
1069 * Ask for confirmation if the screenshot will be huge.
1070 * @param t Screenshot type: World or viewport screenshot
1072 static void MenuClickLargeWorldScreenshot(ScreenshotType t)
1074 ViewPort vp;
1075 SetupScreenshotViewport(t, &vp);
1076 if ((uint64)vp.width * (uint64)vp.height > 8192 * 8192) {
1077 /* Ask for confirmation */
1078 SetDParam(0, vp.width);
1079 SetDParam(1, vp.height);
1080 _confirmed_screenshot_type = t;
1081 ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, NULL, ScreenshotConfirmCallback);
1082 } else {
1083 /* Less than 64M pixels, just do it */
1084 MakeScreenshot(t, NULL);
1089 * Toggle drawing of sprites' bounding boxes.
1090 * @note has only an effect when newgrf_developer_tools are active.
1092 * Function is found here and not in viewport.cpp in order to avoid
1093 * importing the settings structs to there.
1095 void ToggleBoundingBoxes()
1097 extern bool _draw_bounding_boxes;
1098 /* Always allow to toggle them off */
1099 if (_settings_client.gui.newgrf_developer_tools || _draw_bounding_boxes) {
1100 _draw_bounding_boxes = !_draw_bounding_boxes;
1101 MarkWholeScreenDirty();
1106 * Toggle drawing of the dirty blocks.
1107 * @note has only an effect when newgrf_developer_tools are active.
1109 * Function is found here and not in viewport.cpp in order to avoid
1110 * importing the settings structs to there.
1112 void ToggleDirtyBlocks()
1114 extern bool _draw_dirty_blocks;
1115 /* Always allow to toggle them off */
1116 if (_settings_client.gui.newgrf_developer_tools || _draw_dirty_blocks) {
1117 _draw_dirty_blocks = !_draw_dirty_blocks;
1118 MarkWholeScreenDirty();
1123 * Set the starting year for a scenario.
1124 * @param year New starting year.
1126 void SetStartingYear(Year year)
1128 _settings_game.game_creation.starting_year = Clamp(year, MIN_YEAR, MAX_YEAR);
1129 Date new_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
1130 /* If you open a savegame as scenario there may already be link graphs.*/
1131 LinkGraphSchedule::instance.ShiftDates(new_date - _date);
1132 SetDate(new_date, 0);
1136 * Choose the proper callback function for the main toolbar's help menu.
1137 * @param index The menu index which was selected.
1138 * @return CBF_NONE
1140 static CallBackFunction MenuClickHelp(int index)
1142 switch (index) {
1143 case 0: return PlaceLandBlockInfo();
1144 case 2: IConsoleSwitch(); break;
1145 case 3: ShowAIDebugWindow(); break;
1146 case 4: MenuClickSmallScreenshot(); break;
1147 case 5: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
1148 case 6: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
1149 case 7: MenuClickLargeWorldScreenshot(SC_WORLD); break;
1150 case 8: ShowAboutWindow(); break;
1151 case 9: ShowSpriteAlignerWindow(); break;
1152 case 10: ToggleBoundingBoxes(); break;
1153 case 11: ToggleDirtyBlocks(); break;
1155 return CBF_NONE;
1158 /* --- Switch toolbar button --- */
1160 static CallBackFunction ToolbarSwitchClick(Window *w)
1162 if (_toolbar_mode != TB_LOWER) {
1163 _toolbar_mode = TB_LOWER;
1164 } else {
1165 _toolbar_mode = TB_UPPER;
1168 w->ReInit();
1169 w->SetWidgetLoweredState(WID_TN_SWITCH_BAR, _toolbar_mode == TB_LOWER);
1170 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1171 return CBF_NONE;
1174 /* --- Scenario editor specific handlers. */
1177 * Called when clicking at the date panel of the scenario editor toolbar.
1179 static CallBackFunction ToolbarScenDatePanel(Window *w)
1181 SetDParam(0, _settings_game.game_creation.starting_year);
1182 ShowQueryString(STR_JUST_INT, STR_MAPGEN_START_DATE_QUERY_CAPT, 8, w, CS_NUMERAL, QSF_ENABLE_DEFAULT);
1183 _left_button_clicked = false;
1184 return CBF_NONE;
1187 static CallBackFunction ToolbarScenDateBackward(Window *w)
1189 /* don't allow too fast scrolling */
1190 if (!(w->flags & WF_TIMEOUT) || w->timeout_timer <= 1) {
1191 w->HandleButtonClick(WID_TE_DATE_BACKWARD);
1192 w->SetDirty();
1194 SetStartingYear(_settings_game.game_creation.starting_year - 1);
1196 _left_button_clicked = false;
1197 return CBF_NONE;
1200 static CallBackFunction ToolbarScenDateForward(Window *w)
1202 /* don't allow too fast scrolling */
1203 if (!(w->flags & WF_TIMEOUT) || w->timeout_timer <= 1) {
1204 w->HandleButtonClick(WID_TE_DATE_FORWARD);
1205 w->SetDirty();
1207 SetStartingYear(_settings_game.game_creation.starting_year + 1);
1209 _left_button_clicked = false;
1210 return CBF_NONE;
1213 static CallBackFunction ToolbarScenGenLand(Window *w)
1215 w->HandleButtonClick(WID_TE_LAND_GENERATE);
1216 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1218 ShowEditorTerraformToolbar();
1219 return CBF_NONE;
1223 static CallBackFunction ToolbarScenGenTown(Window *w)
1225 w->HandleButtonClick(WID_TE_TOWN_GENERATE);
1226 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1227 ShowFoundTownWindow();
1228 return CBF_NONE;
1231 static CallBackFunction ToolbarScenGenIndustry(Window *w)
1233 w->HandleButtonClick(WID_TE_INDUSTRY);
1234 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1235 ShowBuildIndustryWindow();
1236 return CBF_NONE;
1239 static CallBackFunction ToolbarScenBuildRoad(Window *w)
1241 w->HandleButtonClick(WID_TE_ROADS);
1242 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1243 ShowBuildRoadScenToolbar();
1244 return CBF_NONE;
1247 static CallBackFunction ToolbarScenBuildDocks(Window *w)
1249 w->HandleButtonClick(WID_TE_WATER);
1250 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1251 ShowBuildDocksScenToolbar();
1252 return CBF_NONE;
1255 static CallBackFunction ToolbarScenPlantTrees(Window *w)
1257 w->HandleButtonClick(WID_TE_TREES);
1258 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1259 ShowBuildTreesToolbar();
1260 return CBF_NONE;
1263 static CallBackFunction ToolbarScenPlaceSign(Window *w)
1265 w->HandleButtonClick(WID_TE_SIGNS);
1266 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1267 return SelectSignTool();
1270 static CallBackFunction ToolbarBtn_NULL(Window *w)
1272 return CBF_NONE;
1275 typedef CallBackFunction MenuClickedProc(int index);
1277 static MenuClickedProc * const _menu_clicked_procs[] = {
1278 NULL, // 0
1279 NULL, // 1
1280 MenuClickSettings, // 2
1281 MenuClickSaveLoad, // 3
1282 MenuClickMap, // 4
1283 MenuClickTown, // 5
1284 MenuClickSubsidies, // 6
1285 MenuClickStations, // 7
1286 MenuClickFinances, // 8
1287 MenuClickCompany, // 9
1288 MenuClickStory, // 10
1289 MenuClickGoal, // 11
1290 MenuClickGraphs, // 12
1291 MenuClickLeague, // 13
1292 MenuClickIndustry, // 14
1293 MenuClickShowTrains, // 15
1294 MenuClickShowRoad, // 16
1295 MenuClickShowShips, // 17
1296 MenuClickShowAir, // 18
1297 MenuClickMap, // 19
1298 NULL, // 20
1299 MenuClickBuildRail, // 21
1300 MenuClickBuildRoad, // 22
1301 MenuClickBuildWater, // 23
1302 MenuClickBuildAir, // 24
1303 MenuClickForest, // 25
1304 MenuClickMusicWindow, // 26
1305 MenuClickNewspaper, // 27
1306 MenuClickHelp, // 28
1309 /** Full blown container to make it behave exactly as we want :) */
1310 class NWidgetToolbarContainer : public NWidgetContainer {
1311 bool visible[WID_TN_END]; ///< The visible headers
1312 protected:
1313 uint spacers; ///< Number of spacer widgets in this toolbar
1315 public:
1316 NWidgetToolbarContainer() : NWidgetContainer(NWID_HORIZONTAL)
1321 * Check whether the given widget type is a button for us.
1322 * @param type the widget type to check.
1323 * @return true if it is a button for us.
1325 bool IsButton(WidgetType type) const
1327 return type == WWT_IMGBTN || type == WWT_IMGBTN_2 || type == WWT_PUSHIMGBTN;
1330 void SetupSmallestSize(Window *w, bool init_array)
1332 this->smallest_x = 0; // Biggest child
1333 this->smallest_y = 0; // Biggest child
1334 this->fill_x = 1;
1335 this->fill_y = 0;
1336 this->resize_x = 1; // We only resize in this direction
1337 this->resize_y = 0; // We never resize in this direction
1338 this->spacers = 0;
1340 uint nbuttons = 0;
1341 /* First initialise some variables... */
1342 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1343 child_wid->SetupSmallestSize(w, init_array);
1344 this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
1345 if (this->IsButton(child_wid->type)) {
1346 nbuttons++;
1347 this->smallest_x = max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
1348 } else if (child_wid->type == NWID_SPACER) {
1349 this->spacers++;
1353 /* ... then in a second pass make sure the 'current' heights are set. Won't change ever. */
1354 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1355 child_wid->current_y = this->smallest_y;
1356 if (!this->IsButton(child_wid->type)) {
1357 child_wid->current_x = child_wid->smallest_x;
1360 _toolbar_width = nbuttons * this->smallest_x;
1363 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
1365 assert(given_width >= this->smallest_x && given_height >= this->smallest_y);
1367 this->pos_x = x;
1368 this->pos_y = y;
1369 this->current_x = given_width;
1370 this->current_y = given_height;
1372 /* Figure out what are the visible buttons */
1373 memset(this->visible, 0, sizeof(this->visible));
1374 uint arrangable_count, button_count, spacer_count;
1375 const byte *arrangement = GetButtonArrangement(given_width, arrangable_count, button_count, spacer_count);
1376 for (uint i = 0; i < arrangable_count; i++) {
1377 this->visible[arrangement[i]] = true;
1380 /* Create us ourselves a quick lookup table */
1381 NWidgetBase *widgets[WID_TN_END];
1382 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1383 if (child_wid->type == NWID_SPACER) continue;
1384 widgets[((NWidgetCore*)child_wid)->index] = child_wid;
1387 /* Now assign the widgets to their rightful place */
1388 uint position = 0; // Place to put next child relative to origin of the container.
1389 uint spacer_space = max(0, (int)given_width - (int)(button_count * this->smallest_x)); // Remaining spacing for 'spacer' widgets
1390 uint button_space = given_width - spacer_space; // Remaining spacing for the buttons
1391 uint spacer_i = 0;
1392 uint button_i = 0;
1394 /* Index into the arrangement indices. The macro lastof cannot be used here! */
1395 const byte *cur_wid = rtl ? &arrangement[arrangable_count - 1] : arrangement;
1396 for (uint i = 0; i < arrangable_count; i++) {
1397 NWidgetBase *child_wid = widgets[*cur_wid];
1398 /* If we have to give space to the spacers, do that */
1399 if (spacer_space != 0) {
1400 NWidgetBase *possible_spacer = rtl ? child_wid->next : child_wid->prev;
1401 if (possible_spacer != NULL && possible_spacer->type == NWID_SPACER) {
1402 uint add = spacer_space / (spacer_count - spacer_i);
1403 position += add;
1404 spacer_space -= add;
1405 spacer_i++;
1409 /* Buttons can be scaled, the others not. */
1410 if (this->IsButton(child_wid->type)) {
1411 child_wid->current_x = button_space / (button_count - button_i);
1412 button_space -= child_wid->current_x;
1413 button_i++;
1415 child_wid->AssignSizePosition(sizing, x + position, y, child_wid->current_x, this->current_y, rtl);
1416 position += child_wid->current_x;
1418 if (rtl) {
1419 cur_wid--;
1420 } else {
1421 cur_wid++;
1426 /* virtual */ void Draw(const Window *w)
1428 /* Draw brown-red toolbar bg. */
1429 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);
1430 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);
1432 bool rtl = _current_text_dir == TD_RTL;
1433 for (NWidgetBase *child_wid = rtl ? this->tail : this->head; child_wid != NULL; child_wid = rtl ? child_wid->prev : child_wid->next) {
1434 if (child_wid->type == NWID_SPACER) continue;
1435 if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
1437 child_wid->Draw(w);
1441 /* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y)
1443 if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
1445 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1446 if (child_wid->type == NWID_SPACER) continue;
1447 if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
1449 NWidgetCore *nwid = child_wid->GetWidgetFromPos(x, y);
1450 if (nwid != NULL) return nwid;
1452 return NULL;
1456 * Get the arrangement of the buttons for the toolbar.
1457 * @param width the new width of the toolbar.
1458 * @param arrangable_count output of the number of visible items.
1459 * @param button_count output of the number of visible buttons.
1460 * @param spacer_count output of the number of spacers.
1461 * @return the button configuration.
1463 virtual const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const = 0;
1466 /** Container for the 'normal' main toolbar */
1467 class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
1468 /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
1470 static const uint SMALLEST_ARRANGEMENT = 14;
1471 static const uint BIGGEST_ARRANGEMENT = 20;
1473 /* The number of buttons of each row of the toolbar should match the number of items which we want to be visible.
1474 * The total number of buttons should be equal to arrangable_count * 2.
1475 * No bad things happen, but we could see strange behaviours if we have buttons < (arrangable_count * 2) like a
1476 * pause button appearing on the right of the lower toolbar and weird resizing of the widgets even if there is
1477 * enough space.
1479 static const byte arrange14[] = {
1480 WID_TN_PAUSE,
1481 WID_TN_FAST_FORWARD,
1482 WID_TN_TRAINS,
1483 WID_TN_ROADVEHS,
1484 WID_TN_SHIPS,
1485 WID_TN_AIRCRAFTS,
1486 WID_TN_ZOOM_IN,
1487 WID_TN_ZOOM_OUT,
1488 WID_TN_RAILS,
1489 WID_TN_ROADS,
1490 WID_TN_WATER,
1491 WID_TN_AIR,
1492 WID_TN_LANDSCAPE,
1493 WID_TN_SWITCH_BAR,
1494 // lower toolbar
1495 WID_TN_SETTINGS,
1496 WID_TN_SAVE,
1497 WID_TN_SMALL_MAP,
1498 WID_TN_TOWNS,
1499 WID_TN_SUBSIDIES,
1500 WID_TN_STATIONS,
1501 WID_TN_FINANCES,
1502 WID_TN_COMPANIES,
1503 WID_TN_GRAPHS,
1504 WID_TN_INDUSTRIES,
1505 WID_TN_MUSIC_SOUND,
1506 WID_TN_MESSAGES,
1507 WID_TN_HELP,
1508 WID_TN_SWITCH_BAR,
1510 static const byte arrange15[] = {
1511 WID_TN_PAUSE,
1512 WID_TN_FAST_FORWARD,
1513 WID_TN_SMALL_MAP,
1514 WID_TN_TRAINS,
1515 WID_TN_ROADVEHS,
1516 WID_TN_SHIPS,
1517 WID_TN_AIRCRAFTS,
1518 WID_TN_RAILS,
1519 WID_TN_ROADS,
1520 WID_TN_WATER,
1521 WID_TN_AIR,
1522 WID_TN_LANDSCAPE,
1523 WID_TN_ZOOM_IN,
1524 WID_TN_ZOOM_OUT,
1525 WID_TN_SWITCH_BAR,
1526 // lower toolbar
1527 WID_TN_PAUSE,
1528 WID_TN_SETTINGS,
1529 WID_TN_SMALL_MAP,
1530 WID_TN_SAVE,
1531 WID_TN_TOWNS,
1532 WID_TN_SUBSIDIES,
1533 WID_TN_STATIONS,
1534 WID_TN_FINANCES,
1535 WID_TN_COMPANIES,
1536 WID_TN_GRAPHS,
1537 WID_TN_INDUSTRIES,
1538 WID_TN_MUSIC_SOUND,
1539 WID_TN_MESSAGES,
1540 WID_TN_HELP,
1541 WID_TN_SWITCH_BAR,
1543 static const byte arrange16[] = {
1544 WID_TN_PAUSE,
1545 WID_TN_FAST_FORWARD,
1546 WID_TN_SETTINGS,
1547 WID_TN_SMALL_MAP,
1548 WID_TN_TRAINS,
1549 WID_TN_ROADVEHS,
1550 WID_TN_SHIPS,
1551 WID_TN_AIRCRAFTS,
1552 WID_TN_RAILS,
1553 WID_TN_ROADS,
1554 WID_TN_WATER,
1555 WID_TN_AIR,
1556 WID_TN_LANDSCAPE,
1557 WID_TN_ZOOM_IN,
1558 WID_TN_ZOOM_OUT,
1559 WID_TN_SWITCH_BAR,
1560 // lower toolbar
1561 WID_TN_PAUSE,
1562 WID_TN_FAST_FORWARD,
1563 WID_TN_SAVE,
1564 WID_TN_TOWNS,
1565 WID_TN_SUBSIDIES,
1566 WID_TN_STATIONS,
1567 WID_TN_FINANCES,
1568 WID_TN_COMPANIES,
1569 WID_TN_GRAPHS,
1570 WID_TN_INDUSTRIES,
1571 WID_TN_MUSIC_SOUND,
1572 WID_TN_MESSAGES,
1573 WID_TN_HELP,
1574 WID_TN_ZOOM_IN,
1575 WID_TN_ZOOM_OUT,
1576 WID_TN_SWITCH_BAR,
1578 static const byte arrange17[] = {
1579 WID_TN_PAUSE,
1580 WID_TN_FAST_FORWARD,
1581 WID_TN_SETTINGS,
1582 WID_TN_SMALL_MAP,
1583 WID_TN_SUBSIDIES,
1584 WID_TN_TRAINS,
1585 WID_TN_ROADVEHS,
1586 WID_TN_SHIPS,
1587 WID_TN_AIRCRAFTS,
1588 WID_TN_RAILS,
1589 WID_TN_ROADS,
1590 WID_TN_WATER,
1591 WID_TN_AIR,
1592 WID_TN_LANDSCAPE,
1593 WID_TN_ZOOM_IN,
1594 WID_TN_ZOOM_OUT,
1595 WID_TN_SWITCH_BAR,
1596 // lower toolbar
1597 WID_TN_PAUSE,
1598 WID_TN_FAST_FORWARD,
1599 WID_TN_SAVE,
1600 WID_TN_SMALL_MAP,
1601 WID_TN_SUBSIDIES,
1602 WID_TN_TOWNS,
1603 WID_TN_STATIONS,
1604 WID_TN_FINANCES,
1605 WID_TN_COMPANIES,
1606 WID_TN_GRAPHS,
1607 WID_TN_INDUSTRIES,
1608 WID_TN_MUSIC_SOUND,
1609 WID_TN_MESSAGES,
1610 WID_TN_HELP,
1611 WID_TN_ZOOM_IN,
1612 WID_TN_ZOOM_OUT,
1613 WID_TN_SWITCH_BAR,
1615 static const byte arrange18[] = {
1616 WID_TN_PAUSE,
1617 WID_TN_FAST_FORWARD,
1618 WID_TN_SETTINGS,
1619 WID_TN_SMALL_MAP,
1620 WID_TN_TOWNS,
1621 WID_TN_SUBSIDIES,
1622 WID_TN_STATIONS,
1623 WID_TN_FINANCES,
1624 WID_TN_COMPANIES,
1625 WID_TN_INDUSTRIES,
1626 WID_TN_RAILS,
1627 WID_TN_ROADS,
1628 WID_TN_WATER,
1629 WID_TN_AIR,
1630 WID_TN_LANDSCAPE,
1631 WID_TN_ZOOM_IN,
1632 WID_TN_ZOOM_OUT,
1633 WID_TN_SWITCH_BAR,
1634 // lower toolbar
1635 WID_TN_PAUSE,
1636 WID_TN_FAST_FORWARD,
1637 WID_TN_SAVE,
1638 WID_TN_SMALL_MAP,
1639 WID_TN_TOWNS,
1640 WID_TN_SUBSIDIES,
1641 WID_TN_STATIONS,
1642 WID_TN_GRAPHS,
1643 WID_TN_TRAINS,
1644 WID_TN_ROADVEHS,
1645 WID_TN_SHIPS,
1646 WID_TN_AIRCRAFTS,
1647 WID_TN_MUSIC_SOUND,
1648 WID_TN_MESSAGES,
1649 WID_TN_HELP,
1650 WID_TN_ZOOM_IN,
1651 WID_TN_ZOOM_OUT,
1652 WID_TN_SWITCH_BAR,
1654 static const byte arrange19[] = {
1655 WID_TN_PAUSE,
1656 WID_TN_FAST_FORWARD,
1657 WID_TN_SETTINGS,
1658 WID_TN_SMALL_MAP,
1659 WID_TN_TOWNS,
1660 WID_TN_SUBSIDIES,
1661 WID_TN_TRAINS,
1662 WID_TN_ROADVEHS,
1663 WID_TN_SHIPS,
1664 WID_TN_AIRCRAFTS,
1665 WID_TN_RAILS,
1666 WID_TN_ROADS,
1667 WID_TN_WATER,
1668 WID_TN_AIR,
1669 WID_TN_LANDSCAPE,
1670 WID_TN_MUSIC_SOUND,
1671 WID_TN_ZOOM_IN,
1672 WID_TN_ZOOM_OUT,
1673 WID_TN_SWITCH_BAR,
1674 // lower toolbar
1675 WID_TN_PAUSE,
1676 WID_TN_FAST_FORWARD,
1677 WID_TN_SAVE,
1678 WID_TN_SMALL_MAP,
1679 WID_TN_STATIONS,
1680 WID_TN_FINANCES,
1681 WID_TN_COMPANIES,
1682 WID_TN_GRAPHS,
1683 WID_TN_INDUSTRIES,
1684 WID_TN_MESSAGES,
1685 WID_TN_RAILS,
1686 WID_TN_ROADS,
1687 WID_TN_WATER,
1688 WID_TN_AIR,
1689 WID_TN_LANDSCAPE,
1690 WID_TN_HELP,
1691 WID_TN_ZOOM_IN,
1692 WID_TN_ZOOM_OUT,
1693 WID_TN_SWITCH_BAR,
1695 static const byte arrange20[] = {
1696 WID_TN_PAUSE,
1697 WID_TN_FAST_FORWARD,
1698 WID_TN_SETTINGS,
1699 WID_TN_SMALL_MAP,
1700 WID_TN_TOWNS,
1701 WID_TN_SUBSIDIES,
1702 WID_TN_TRAINS,
1703 WID_TN_ROADVEHS,
1704 WID_TN_SHIPS,
1705 WID_TN_AIRCRAFTS,
1706 WID_TN_RAILS,
1707 WID_TN_ROADS,
1708 WID_TN_WATER,
1709 WID_TN_AIR,
1710 WID_TN_LANDSCAPE,
1711 WID_TN_MUSIC_SOUND,
1712 WID_TN_GOAL,
1713 WID_TN_ZOOM_IN,
1714 WID_TN_ZOOM_OUT,
1715 WID_TN_SWITCH_BAR,
1716 // lower toolbar
1717 WID_TN_PAUSE,
1718 WID_TN_FAST_FORWARD,
1719 WID_TN_SAVE,
1720 WID_TN_SMALL_MAP,
1721 WID_TN_STATIONS,
1722 WID_TN_FINANCES,
1723 WID_TN_COMPANIES,
1724 WID_TN_GRAPHS,
1725 WID_TN_INDUSTRIES,
1726 WID_TN_MESSAGES,
1727 WID_TN_RAILS,
1728 WID_TN_ROADS,
1729 WID_TN_WATER,
1730 WID_TN_AIR,
1731 WID_TN_LANDSCAPE,
1732 WID_TN_STORY,
1733 WID_TN_HELP,
1734 WID_TN_ZOOM_IN,
1735 WID_TN_ZOOM_OUT,
1736 WID_TN_SWITCH_BAR,
1738 static const byte arrange_all[] = {
1739 WID_TN_PAUSE,
1740 WID_TN_FAST_FORWARD,
1741 WID_TN_SETTINGS,
1742 WID_TN_SAVE,
1743 WID_TN_SMALL_MAP,
1744 WID_TN_TOWNS,
1745 WID_TN_SUBSIDIES,
1746 WID_TN_STATIONS,
1747 WID_TN_FINANCES,
1748 WID_TN_COMPANIES,
1749 WID_TN_STORY,
1750 WID_TN_GOAL,
1751 WID_TN_GRAPHS,
1752 WID_TN_LEAGUE,
1753 WID_TN_INDUSTRIES,
1754 WID_TN_TRAINS,
1755 WID_TN_ROADVEHS,
1756 WID_TN_SHIPS,
1757 WID_TN_AIRCRAFTS,
1758 WID_TN_ZOOM_IN,
1759 WID_TN_ZOOM_OUT,
1760 WID_TN_RAILS,
1761 WID_TN_ROADS,
1762 WID_TN_WATER,
1763 WID_TN_AIR,
1764 WID_TN_LANDSCAPE,
1765 WID_TN_MUSIC_SOUND,
1766 WID_TN_MESSAGES,
1767 WID_TN_HELP
1770 /* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
1771 uint full_buttons = max(CeilDiv(width, this->smallest_x), SMALLEST_ARRANGEMENT);
1772 if (full_buttons > BIGGEST_ARRANGEMENT) {
1773 button_count = arrangable_count = lengthof(arrange_all);
1774 spacer_count = this->spacers;
1775 return arrange_all;
1778 /* Introduce the split toolbar */
1779 static const byte * const arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19, arrange20 };
1781 button_count = arrangable_count = full_buttons;
1782 spacer_count = this->spacers;
1783 return arrangements[full_buttons - SMALLEST_ARRANGEMENT] + ((_toolbar_mode == TB_LOWER) ? full_buttons : 0);
1787 /** Container for the scenario editor's toolbar */
1788 class NWidgetScenarioToolbarContainer : public NWidgetToolbarContainer {
1789 uint panel_widths[2]; ///< The width of the two panels (the text panel and date panel)
1791 void SetupSmallestSize(Window *w, bool init_array)
1793 this->NWidgetToolbarContainer::SetupSmallestSize(w, init_array);
1795 /* Find the size of panel_widths */
1796 uint i = 0;
1797 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1798 if (child_wid->type == NWID_SPACER || this->IsButton(child_wid->type)) continue;
1800 assert(i < lengthof(this->panel_widths));
1801 this->panel_widths[i++] = child_wid->current_x;
1802 _toolbar_width += child_wid->current_x;
1806 /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
1808 static const byte arrange_all[] = {
1809 WID_TE_PAUSE,
1810 WID_TE_FAST_FORWARD,
1811 WID_TE_SETTINGS,
1812 WID_TE_SAVE,
1813 WID_TE_SPACER,
1814 WID_TE_DATE_PANEL,
1815 WID_TE_SMALL_MAP,
1816 WID_TE_ZOOM_IN,
1817 WID_TE_ZOOM_OUT,
1818 WID_TE_LAND_GENERATE,
1819 WID_TE_TOWN_GENERATE,
1820 WID_TE_INDUSTRY,
1821 WID_TE_ROADS,
1822 WID_TE_WATER,
1823 WID_TE_TREES,
1824 WID_TE_SIGNS,
1825 WID_TE_MUSIC_SOUND,
1826 WID_TE_HELP,
1828 static const byte arrange_nopanel[] = {
1829 WID_TE_PAUSE,
1830 WID_TE_FAST_FORWARD,
1831 WID_TE_SETTINGS,
1832 WID_TE_SAVE,
1833 WID_TE_DATE_PANEL,
1834 WID_TE_SMALL_MAP,
1835 WID_TE_ZOOM_IN,
1836 WID_TE_ZOOM_OUT,
1837 WID_TE_LAND_GENERATE,
1838 WID_TE_TOWN_GENERATE,
1839 WID_TE_INDUSTRY,
1840 WID_TE_ROADS,
1841 WID_TE_WATER,
1842 WID_TE_TREES,
1843 WID_TE_SIGNS,
1844 WID_TE_MUSIC_SOUND,
1845 WID_TE_HELP,
1847 static const byte arrange_switch[] = {
1848 WID_TE_DATE_PANEL,
1849 WID_TE_SMALL_MAP,
1850 WID_TE_LAND_GENERATE,
1851 WID_TE_TOWN_GENERATE,
1852 WID_TE_INDUSTRY,
1853 WID_TE_ROADS,
1854 WID_TE_WATER,
1855 WID_TE_TREES,
1856 WID_TE_SIGNS,
1857 WID_TE_SWITCH_BAR,
1858 // lower toolbar
1859 WID_TE_PAUSE,
1860 WID_TE_FAST_FORWARD,
1861 WID_TE_SETTINGS,
1862 WID_TE_SAVE,
1863 WID_TE_DATE_PANEL,
1864 WID_TE_ZOOM_IN,
1865 WID_TE_ZOOM_OUT,
1866 WID_TE_MUSIC_SOUND,
1867 WID_TE_HELP, WID_TE_SWITCH_BAR,
1870 /* If we can place all buttons *and* the panels, show them. */
1871 uint min_full_width = (lengthof(arrange_all) - lengthof(this->panel_widths)) * this->smallest_x + this->panel_widths[0] + this->panel_widths[1];
1872 if (width >= min_full_width) {
1873 width -= this->panel_widths[0] + this->panel_widths[1];
1874 arrangable_count = lengthof(arrange_all);
1875 button_count = arrangable_count - 2;
1876 spacer_count = this->spacers;
1877 return arrange_all;
1880 /* 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 */
1881 uint min_small_width = (lengthof(arrange_switch) - lengthof(this->panel_widths)) * this->smallest_x / 2 + this->panel_widths[1];
1882 if (width > min_small_width) {
1883 width -= this->panel_widths[1];
1884 arrangable_count = lengthof(arrange_nopanel);
1885 button_count = arrangable_count - 1;
1886 spacer_count = this->spacers - 1;
1887 return arrange_nopanel;
1890 /* Split toolbar */
1891 width -= this->panel_widths[1];
1892 arrangable_count = lengthof(arrange_switch) / 2;
1893 button_count = arrangable_count - 1;
1894 spacer_count = 0;
1895 return arrange_switch + ((_toolbar_mode == TB_LOWER) ? arrangable_count : 0);
1899 /* --- Toolbar handling for the 'normal' case */
1901 typedef CallBackFunction ToolbarButtonProc(Window *w);
1903 static ToolbarButtonProc * const _toolbar_button_procs[] = {
1904 ToolbarPauseClick,
1905 ToolbarFastForwardClick,
1906 ToolbarOptionsClick,
1907 ToolbarSaveClick,
1908 ToolbarMapClick,
1909 ToolbarTownClick,
1910 ToolbarSubsidiesClick,
1911 ToolbarStationsClick,
1912 ToolbarFinancesClick,
1913 ToolbarCompaniesClick,
1914 ToolbarStoryClick,
1915 ToolbarGoalClick,
1916 ToolbarGraphsClick,
1917 ToolbarLeagueClick,
1918 ToolbarIndustryClick,
1919 ToolbarTrainClick,
1920 ToolbarRoadClick,
1921 ToolbarShipClick,
1922 ToolbarAirClick,
1923 ToolbarZoomInClick,
1924 ToolbarZoomOutClick,
1925 ToolbarBuildRailClick,
1926 ToolbarBuildRoadClick,
1927 ToolbarBuildWaterClick,
1928 ToolbarBuildAirClick,
1929 ToolbarForestClick,
1930 ToolbarMusicClick,
1931 ToolbarNewspaperClick,
1932 ToolbarHelpClick,
1933 ToolbarSwitchClick,
1936 enum MainToolbarHotkeys {
1937 MTHK_PAUSE,
1938 MTHK_FASTFORWARD,
1939 MTHK_SETTINGS,
1940 MTHK_SAVEGAME,
1941 MTHK_LOADGAME,
1942 MTHK_SMALLMAP,
1943 MTHK_TOWNDIRECTORY,
1944 MTHK_SUBSIDIES,
1945 MTHK_STATIONS,
1946 MTHK_FINANCES,
1947 MTHK_COMPANIES,
1948 MTHK_STORY,
1949 MTHK_GOAL,
1950 MTHK_GRAPHS,
1951 MTHK_LEAGUE,
1952 MTHK_INDUSTRIES,
1953 MTHK_TRAIN_LIST,
1954 MTHK_ROADVEH_LIST,
1955 MTHK_SHIP_LIST,
1956 MTHK_AIRCRAFT_LIST,
1957 MTHK_ZOOM_IN,
1958 MTHK_ZOOM_OUT,
1959 MTHK_BUILD_RAIL,
1960 MTHK_BUILD_ROAD,
1961 MTHK_BUILD_DOCKS,
1962 MTHK_BUILD_AIRPORT,
1963 MTHK_BUILD_TREES,
1964 MTHK_MUSIC,
1965 MTHK_AI_DEBUG,
1966 MTHK_SMALL_SCREENSHOT,
1967 MTHK_ZOOMEDIN_SCREENSHOT,
1968 MTHK_DEFAULTZOOM_SCREENSHOT,
1969 MTHK_GIANT_SCREENSHOT,
1970 MTHK_CHEATS,
1971 MTHK_TERRAFORM,
1972 MTHK_EXTRA_VIEWPORT,
1973 MTHK_CLIENT_LIST,
1974 MTHK_SIGN_LIST,
1977 /** Main toolbar. */
1978 struct MainToolbarWindow : Window {
1979 MainToolbarWindow(WindowDesc *desc) : Window(desc)
1981 this->InitNested(0);
1983 _last_started_action = CBF_NONE;
1984 CLRBITS(this->flags, WF_WHITE_BORDER);
1985 this->SetWidgetDisabledState(WID_TN_PAUSE, _networking && !_network_server); // if not server, disable pause button
1986 this->SetWidgetDisabledState(WID_TN_FAST_FORWARD, _networking); // if networking, disable fast-forward button
1987 PositionMainToolbar(this);
1988 DoZoomInOutWindow(ZOOM_NONE, this);
1991 virtual void FindWindowPlacementAndResize(int def_width, int def_height)
1993 Window::FindWindowPlacementAndResize(_toolbar_width, def_height);
1996 virtual void OnPaint()
1998 /* If spectator, disable all construction buttons
1999 * ie : Build road, rail, ships, airports and landscaping
2000 * Since enabled state is the default, just disable when needed */
2001 this->SetWidgetsDisabledState(_local_company == COMPANY_SPECTATOR, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, WID_TN_AIR, WID_TN_LANDSCAPE, WIDGET_LIST_END);
2002 /* disable company list drop downs, if there are no companies */
2003 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);
2005 this->SetWidgetDisabledState(WID_TN_GOAL, Goal::GetNumItems() == 0);
2006 this->SetWidgetDisabledState(WID_TN_STORY, StoryPage::GetNumItems() == 0);
2008 this->SetWidgetDisabledState(WID_TN_RAILS, !CanBuildVehicleInfrastructure(VEH_TRAIN));
2009 this->SetWidgetDisabledState(WID_TN_AIR, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT));
2011 this->DrawWidgets();
2014 virtual void OnClick(Point pt, int widget, int click_count)
2016 if (_game_mode != GM_MENU && !this->IsWidgetDisabled(widget)) _toolbar_button_procs[widget](this);
2019 virtual void OnDropdownSelect(int widget, int index)
2021 CallBackFunction cbf = _menu_clicked_procs[widget](index);
2022 if (cbf != CBF_NONE) _last_started_action = cbf;
2025 virtual EventState OnHotkey(int hotkey)
2027 switch (hotkey) {
2028 case MTHK_PAUSE: ToolbarPauseClick(this); break;
2029 case MTHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
2030 case MTHK_SETTINGS: ShowGameOptions(); break;
2031 case MTHK_SAVEGAME: MenuClickSaveLoad(); break;
2032 case MTHK_LOADGAME: ShowSaveLoadDialog(FT_SAVEGAME, SLO_LOAD); break;
2033 case MTHK_SMALLMAP: ShowSmallMap(); break;
2034 case MTHK_TOWNDIRECTORY: ShowTownDirectory(); break;
2035 case MTHK_SUBSIDIES: ShowSubsidiesList(); break;
2036 case MTHK_STATIONS: ShowCompanyStations(_local_company); break;
2037 case MTHK_FINANCES: ShowCompanyFinances(_local_company); break;
2038 case MTHK_COMPANIES: ShowCompany(_local_company); break;
2039 case MTHK_STORY: ShowStoryBook(_local_company); break;
2040 case MTHK_GOAL: ShowGoalsList(_local_company); break;
2041 case MTHK_GRAPHS: ShowOperatingProfitGraph(); break;
2042 case MTHK_LEAGUE: ShowCompanyLeagueTable(); break;
2043 case MTHK_INDUSTRIES: ShowBuildIndustryWindow(); break;
2044 case MTHK_TRAIN_LIST: ShowVehicleListWindow(_local_company, VEH_TRAIN); break;
2045 case MTHK_ROADVEH_LIST: ShowVehicleListWindow(_local_company, VEH_ROAD); break;
2046 case MTHK_SHIP_LIST: ShowVehicleListWindow(_local_company, VEH_SHIP); break;
2047 case MTHK_AIRCRAFT_LIST: ShowVehicleListWindow(_local_company, VEH_AIRCRAFT); break;
2048 case MTHK_ZOOM_IN: ToolbarZoomInClick(this); break;
2049 case MTHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
2050 case MTHK_BUILD_RAIL: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype); break;
2051 case MTHK_BUILD_ROAD: ShowBuildRoadToolbar(_last_built_roadtype); break;
2052 case MTHK_BUILD_DOCKS: ShowBuildDocksToolbar(); break;
2053 case MTHK_BUILD_AIRPORT: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break;
2054 case MTHK_BUILD_TREES: ShowBuildTreesToolbar(); break;
2055 case MTHK_MUSIC: ShowMusicWindow(); break;
2056 case MTHK_AI_DEBUG: ShowAIDebugWindow(); break;
2057 case MTHK_SMALL_SCREENSHOT: MenuClickSmallScreenshot(); break;
2058 case MTHK_ZOOMEDIN_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
2059 case MTHK_DEFAULTZOOM_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
2060 case MTHK_GIANT_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_WORLD); break;
2061 case MTHK_CHEATS: if (!_networking) ShowCheatWindow(); break;
2062 case MTHK_TERRAFORM: ShowTerraformToolbar(); break;
2063 case MTHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
2064 #ifdef ENABLE_NETWORK
2065 case MTHK_CLIENT_LIST: if (_networking) ShowClientList(); break;
2066 #endif
2067 case MTHK_SIGN_LIST: ShowSignList(); break;
2068 default: return ES_NOT_HANDLED;
2070 return ES_HANDLED;
2073 virtual void OnPlaceObject(Point pt, TileIndex tile)
2075 switch (_last_started_action) {
2076 case CBF_PLACE_SIGN:
2077 PlaceProc_Sign(tile);
2078 break;
2080 case CBF_PLACE_LANDINFO:
2081 ShowLandInfo(tile);
2082 break;
2084 default: NOT_REACHED();
2088 virtual void OnPlaceObjectAbort()
2090 _last_started_action = CBF_NONE;
2093 virtual void OnTick()
2095 if (this->IsWidgetLowered(WID_TN_PAUSE) != !!_pause_mode) {
2096 this->ToggleWidgetLoweredState(WID_TN_PAUSE);
2097 this->SetWidgetDirty(WID_TN_PAUSE);
2100 if (this->IsWidgetLowered(WID_TN_FAST_FORWARD) != !!_fast_forward) {
2101 this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD);
2102 this->SetWidgetDirty(WID_TN_FAST_FORWARD);
2106 virtual void OnTimeout()
2108 /* We do not want to automatically raise the pause, fast forward and
2109 * switchbar buttons; they have to stay down when pressed etc. */
2110 for (uint i = WID_TN_SETTINGS; i < WID_TN_SWITCH_BAR; i++) {
2111 if (this->IsWidgetLowered(i)) {
2112 this->RaiseWidget(i);
2113 this->SetWidgetDirty(i);
2119 * Some data on this window has become invalid.
2120 * @param data Information about the changed data.
2121 * @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.
2123 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2125 if (!gui_scope) return;
2126 if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT);
2129 static HotkeyList hotkeys;
2132 const uint16 _maintoolbar_pause_keys[] = {WKC_F1, WKC_PAUSE, 0};
2133 const uint16 _maintoolbar_zoomin_keys[] = {WKC_NUM_PLUS, WKC_EQUALS, WKC_SHIFT | WKC_EQUALS, WKC_SHIFT | WKC_F5, 0};
2134 const uint16 _maintoolbar_zoomout_keys[] = {WKC_NUM_MINUS, WKC_MINUS, WKC_SHIFT | WKC_MINUS, WKC_SHIFT | WKC_F6, 0};
2135 const uint16 _maintoolbar_smallmap_keys[] = {WKC_F4, 'M', 0};
2137 static Hotkey maintoolbar_hotkeys[] = {
2138 Hotkey(_maintoolbar_pause_keys, "pause", MTHK_PAUSE),
2139 Hotkey((uint16)0, "fastforward", MTHK_FASTFORWARD),
2140 Hotkey(WKC_F2, "settings", MTHK_SETTINGS),
2141 Hotkey(WKC_F3, "saveload", MTHK_SAVEGAME),
2142 Hotkey((uint16)0, "load_game", MTHK_LOADGAME),
2143 Hotkey(_maintoolbar_smallmap_keys, "smallmap", MTHK_SMALLMAP),
2144 Hotkey(WKC_F5, "town_list", MTHK_TOWNDIRECTORY),
2145 Hotkey(WKC_F6, "subsidies", MTHK_SUBSIDIES),
2146 Hotkey(WKC_F7, "station_list", MTHK_STATIONS),
2147 Hotkey(WKC_F8, "finances", MTHK_FINANCES),
2148 Hotkey(WKC_F9, "companies", MTHK_COMPANIES),
2149 Hotkey((uint16)0, "story_book", MTHK_STORY),
2150 Hotkey((uint16)0, "goal_list", MTHK_GOAL),
2151 Hotkey(WKC_F10, "graphs", MTHK_GRAPHS),
2152 Hotkey(WKC_F11, "league", MTHK_LEAGUE),
2153 Hotkey(WKC_F12, "industry_list", MTHK_INDUSTRIES),
2154 Hotkey(WKC_SHIFT | WKC_F1, "train_list", MTHK_TRAIN_LIST),
2155 Hotkey(WKC_SHIFT | WKC_F2, "roadveh_list", MTHK_ROADVEH_LIST),
2156 Hotkey(WKC_SHIFT | WKC_F3, "ship_list", MTHK_SHIP_LIST),
2157 Hotkey(WKC_SHIFT | WKC_F4, "aircraft_list", MTHK_AIRCRAFT_LIST),
2158 Hotkey(_maintoolbar_zoomin_keys, "zoomin", MTHK_ZOOM_IN),
2159 Hotkey(_maintoolbar_zoomout_keys, "zoomout", MTHK_ZOOM_OUT),
2160 Hotkey(WKC_SHIFT | WKC_F7, "build_rail", MTHK_BUILD_RAIL),
2161 Hotkey(WKC_SHIFT | WKC_F8, "build_road", MTHK_BUILD_ROAD),
2162 Hotkey(WKC_SHIFT | WKC_F9, "build_docks", MTHK_BUILD_DOCKS),
2163 Hotkey(WKC_SHIFT | WKC_F10, "build_airport", MTHK_BUILD_AIRPORT),
2164 Hotkey(WKC_SHIFT | WKC_F11, "build_trees", MTHK_BUILD_TREES),
2165 Hotkey(WKC_SHIFT | WKC_F12, "music", MTHK_MUSIC),
2166 Hotkey((uint16)0, "ai_debug", MTHK_AI_DEBUG),
2167 Hotkey(WKC_CTRL | 'S', "small_screenshot", MTHK_SMALL_SCREENSHOT),
2168 Hotkey(WKC_CTRL | 'P', "zoomedin_screenshot", MTHK_ZOOMEDIN_SCREENSHOT),
2169 Hotkey(WKC_CTRL | 'D', "defaultzoom_screenshot", MTHK_DEFAULTZOOM_SCREENSHOT),
2170 Hotkey((uint16)0, "giant_screenshot", MTHK_GIANT_SCREENSHOT),
2171 Hotkey(WKC_CTRL | WKC_ALT | 'C', "cheats", MTHK_CHEATS),
2172 Hotkey('L', "terraform", MTHK_TERRAFORM),
2173 Hotkey('V', "extra_viewport", MTHK_EXTRA_VIEWPORT),
2174 #ifdef ENABLE_NETWORK
2175 Hotkey((uint16)0, "client_list", MTHK_CLIENT_LIST),
2176 #endif
2177 Hotkey((uint16)0, "sign_list", MTHK_SIGN_LIST),
2178 HOTKEY_LIST_END
2180 HotkeyList MainToolbarWindow::hotkeys("maintoolbar", maintoolbar_hotkeys);
2182 static NWidgetBase *MakeMainToolbar(int *biggest_index)
2184 /** Sprites to use for the different toolbar buttons */
2185 static const SpriteID toolbar_button_sprites[] = {
2186 SPR_IMG_PAUSE, // WID_TN_PAUSE
2187 SPR_IMG_FASTFORWARD, // WID_TN_FAST_FORWARD
2188 SPR_IMG_SETTINGS, // WID_TN_SETTINGS
2189 SPR_IMG_SAVE, // WID_TN_SAVE
2190 SPR_IMG_SMALLMAP, // WID_TN_SMALL_MAP
2191 SPR_IMG_TOWN, // WID_TN_TOWNS
2192 SPR_IMG_SUBSIDIES, // WID_TN_SUBSIDIES
2193 SPR_IMG_COMPANY_LIST, // WID_TN_STATIONS
2194 SPR_IMG_COMPANY_FINANCE, // WID_TN_FINANCES
2195 SPR_IMG_COMPANY_GENERAL, // WID_TN_COMPANIES
2196 SPR_IMG_STORY_BOOK, // WID_TN_STORY
2197 SPR_IMG_GOAL, // WID_TN_GOAL
2198 SPR_IMG_GRAPHS, // WID_TN_GRAPHS
2199 SPR_IMG_COMPANY_LEAGUE, // WID_TN_LEAGUE
2200 SPR_IMG_INDUSTRY, // WID_TN_INDUSTRIES
2201 SPR_IMG_TRAINLIST, // WID_TN_TRAINS
2202 SPR_IMG_TRUCKLIST, // WID_TN_ROADVEHS
2203 SPR_IMG_SHIPLIST, // WID_TN_SHIPS
2204 SPR_IMG_AIRPLANESLIST, // WID_TN_AIRCRAFT
2205 SPR_IMG_ZOOMIN, // WID_TN_ZOOMIN
2206 SPR_IMG_ZOOMOUT, // WID_TN_ZOOMOUT
2207 SPR_IMG_BUILDRAIL, // WID_TN_RAILS
2208 SPR_IMG_BUILDROAD, // WID_TN_ROADS
2209 SPR_IMG_BUILDWATER, // WID_TN_WATER
2210 SPR_IMG_BUILDAIR, // WID_TN_AIR
2211 SPR_IMG_LANDSCAPING, // WID_TN_LANDSCAPE
2212 SPR_IMG_MUSIC, // WID_TN_MUSIC_SOUND
2213 SPR_IMG_MESSAGES, // WID_TN_MESSAGES
2214 SPR_IMG_QUERY, // WID_TN_HELP
2215 SPR_IMG_SWITCH_TOOLBAR, // WID_TN_SWITCH_BAR
2218 NWidgetMainToolbarContainer *hor = new NWidgetMainToolbarContainer();
2219 for (uint i = 0; i < WID_TN_END; i++) {
2220 switch (i) {
2221 case WID_TN_SMALL_MAP:
2222 case WID_TN_FINANCES:
2223 case WID_TN_VEHICLE_START:
2224 case WID_TN_ZOOM_IN:
2225 case WID_TN_BUILDING_TOOLS_START:
2226 case WID_TN_MUSIC_SOUND:
2227 hor->Add(new NWidgetSpacer(0, 0));
2228 break;
2230 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));
2233 *biggest_index = max<int>(*biggest_index, WID_TN_SWITCH_BAR);
2234 return hor;
2237 static const NWidgetPart _nested_toolbar_normal_widgets[] = {
2238 NWidgetFunction(MakeMainToolbar),
2241 static WindowDesc _toolb_normal_desc(
2242 WDP_MANUAL, NULL, 0, 0,
2243 WC_MAIN_TOOLBAR, WC_NONE,
2244 WDF_NO_FOCUS,
2245 _nested_toolbar_normal_widgets, lengthof(_nested_toolbar_normal_widgets),
2246 &MainToolbarWindow::hotkeys
2250 /* --- Toolbar handling for the scenario editor */
2252 static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
2253 ToolbarPauseClick,
2254 ToolbarFastForwardClick,
2255 ToolbarOptionsClick,
2256 ToolbarScenSaveOrLoad,
2257 ToolbarBtn_NULL,
2258 ToolbarScenDatePanel,
2259 ToolbarScenDateBackward,
2260 ToolbarScenDateForward,
2261 ToolbarScenMapTownDir,
2262 ToolbarZoomInClick,
2263 ToolbarZoomOutClick,
2264 ToolbarScenGenLand,
2265 ToolbarScenGenTown,
2266 ToolbarScenGenIndustry,
2267 ToolbarScenBuildRoad,
2268 ToolbarScenBuildDocks,
2269 ToolbarScenPlantTrees,
2270 ToolbarScenPlaceSign,
2271 ToolbarBtn_NULL,
2272 NULL,
2273 NULL,
2274 NULL,
2275 NULL,
2276 NULL,
2277 NULL,
2278 NULL,
2279 ToolbarMusicClick,
2280 NULL,
2281 ToolbarHelpClick,
2282 ToolbarSwitchClick,
2285 enum MainToolbarEditorHotkeys {
2286 MTEHK_PAUSE,
2287 MTEHK_FASTFORWARD,
2288 MTEHK_SETTINGS,
2289 MTEHK_SAVEGAME,
2290 MTEHK_GENLAND,
2291 MTEHK_GENTOWN,
2292 MTEHK_GENINDUSTRY,
2293 MTEHK_BUILD_ROAD,
2294 MTEHK_BUILD_DOCKS,
2295 MTEHK_BUILD_TREES,
2296 MTEHK_SIGN,
2297 MTEHK_MUSIC,
2298 MTEHK_LANDINFO,
2299 MTEHK_SMALL_SCREENSHOT,
2300 MTEHK_ZOOMEDIN_SCREENSHOT,
2301 MTEHK_DEFAULTZOOM_SCREENSHOT,
2302 MTEHK_GIANT_SCREENSHOT,
2303 MTEHK_ZOOM_IN,
2304 MTEHK_ZOOM_OUT,
2305 MTEHK_TERRAFORM,
2306 MTEHK_SMALLMAP,
2307 MTEHK_EXTRA_VIEWPORT,
2310 struct ScenarioEditorToolbarWindow : Window {
2311 ScenarioEditorToolbarWindow(WindowDesc *desc) : Window(desc)
2313 this->InitNested(0);
2315 _last_started_action = CBF_NONE;
2316 CLRBITS(this->flags, WF_WHITE_BORDER);
2317 PositionMainToolbar(this);
2318 DoZoomInOutWindow(ZOOM_NONE, this);
2321 virtual void FindWindowPlacementAndResize(int def_width, int def_height)
2323 Window::FindWindowPlacementAndResize(_toolbar_width, def_height);
2326 virtual void OnPaint()
2328 this->SetWidgetDisabledState(WID_TE_DATE_BACKWARD, _settings_game.game_creation.starting_year <= MIN_YEAR);
2329 this->SetWidgetDisabledState(WID_TE_DATE_FORWARD, _settings_game.game_creation.starting_year >= MAX_YEAR);
2331 this->DrawWidgets();
2334 virtual void DrawWidget(const Rect &r, int widget) const
2336 switch (widget) {
2337 case WID_TE_DATE:
2338 SetDParam(0, ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
2339 DrawString(r.left, r.right, (this->height - FONT_HEIGHT_NORMAL) / 2, STR_WHITE_DATE_LONG, TC_FROMSTRING, SA_HOR_CENTER);
2340 break;
2342 case WID_TE_SPACER: {
2343 int height = r.bottom - r.top;
2344 if (height > 2 * FONT_HEIGHT_NORMAL) {
2345 DrawString(r.left, r.right, (height + 1) / 2 - FONT_HEIGHT_NORMAL, STR_SCENEDIT_TOOLBAR_OPENTTD, TC_FROMSTRING, SA_HOR_CENTER);
2346 DrawString(r.left, r.right, (height + 1) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
2347 } else {
2348 DrawString(r.left, r.right, (height - FONT_HEIGHT_NORMAL) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
2350 break;
2355 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2357 switch (widget) {
2358 case WID_TE_SPACER:
2359 size->width = max(GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_OPENTTD).width, GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR).width) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
2360 break;
2362 case WID_TE_DATE:
2363 SetDParam(0, ConvertYMDToDate(MAX_YEAR, 0, 1));
2364 *size = GetStringBoundingBox(STR_WHITE_DATE_LONG);
2365 size->height = max(size->height, GetSpriteSize(SPR_IMG_SAVE).height + WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM);
2366 break;
2370 virtual void OnClick(Point pt, int widget, int click_count)
2372 if (_game_mode == GM_MENU) return;
2373 CallBackFunction cbf = _scen_toolbar_button_procs[widget](this);
2374 if (cbf != CBF_NONE) _last_started_action = cbf;
2377 virtual void OnDropdownSelect(int widget, int index)
2379 /* The map button is in a different location on the scenario
2380 * editor toolbar, so we need to adjust for it. */
2381 if (widget == WID_TE_SMALL_MAP) widget = WID_TN_SMALL_MAP;
2382 CallBackFunction cbf = _menu_clicked_procs[widget](index);
2383 if (cbf != CBF_NONE) _last_started_action = cbf;
2384 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
2387 virtual EventState OnHotkey(int hotkey)
2389 CallBackFunction cbf = CBF_NONE;
2390 switch (hotkey) {
2391 case MTEHK_PAUSE: ToolbarPauseClick(this); break;
2392 case MTEHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
2393 case MTEHK_SETTINGS: ShowGameOptions(); break;
2394 case MTEHK_SAVEGAME: MenuClickSaveLoad(); break;
2395 case MTEHK_GENLAND: ToolbarScenGenLand(this); break;
2396 case MTEHK_GENTOWN: ToolbarScenGenTown(this); break;
2397 case MTEHK_GENINDUSTRY: ToolbarScenGenIndustry(this); break;
2398 case MTEHK_BUILD_ROAD: ToolbarScenBuildRoad(this); break;
2399 case MTEHK_BUILD_DOCKS: ToolbarScenBuildDocks(this); break;
2400 case MTEHK_BUILD_TREES: ToolbarScenPlantTrees(this); break;
2401 case MTEHK_SIGN: cbf = ToolbarScenPlaceSign(this); break;
2402 case MTEHK_MUSIC: ShowMusicWindow(); break;
2403 case MTEHK_LANDINFO: cbf = PlaceLandBlockInfo(); break;
2404 case MTEHK_SMALL_SCREENSHOT: MenuClickSmallScreenshot(); break;
2405 case MTEHK_ZOOMEDIN_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
2406 case MTEHK_DEFAULTZOOM_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
2407 case MTEHK_GIANT_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_WORLD); break;
2408 case MTEHK_ZOOM_IN: ToolbarZoomInClick(this); break;
2409 case MTEHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
2410 case MTEHK_TERRAFORM: ShowEditorTerraformToolbar(); break;
2411 case MTEHK_SMALLMAP: ShowSmallMap(); break;
2412 case MTEHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
2413 default: return ES_NOT_HANDLED;
2415 if (cbf != CBF_NONE) _last_started_action = cbf;
2416 return ES_HANDLED;
2419 virtual void OnPlaceObject(Point pt, TileIndex tile)
2421 switch (_last_started_action) {
2422 case CBF_PLACE_SIGN:
2423 PlaceProc_Sign(tile);
2424 break;
2426 case CBF_PLACE_LANDINFO:
2427 ShowLandInfo(tile);
2428 break;
2430 default: NOT_REACHED();
2434 virtual void OnPlaceObjectAbort()
2436 _last_started_action = CBF_NONE;
2439 virtual void OnTimeout()
2441 this->SetWidgetsLoweredState(false, WID_TE_DATE_BACKWARD, WID_TE_DATE_FORWARD, WIDGET_LIST_END);
2442 this->SetWidgetDirty(WID_TE_DATE_BACKWARD);
2443 this->SetWidgetDirty(WID_TE_DATE_FORWARD);
2446 virtual void OnTick()
2448 if (this->IsWidgetLowered(WID_TE_PAUSE) != !!_pause_mode) {
2449 this->ToggleWidgetLoweredState(WID_TE_PAUSE);
2450 this->SetDirty();
2453 if (this->IsWidgetLowered(WID_TE_FAST_FORWARD) != !!_fast_forward) {
2454 this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD);
2455 this->SetDirty();
2460 * Some data on this window has become invalid.
2461 * @param data Information about the changed data.
2462 * @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.
2464 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2466 if (!gui_scope) return;
2467 if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, WID_TE_ZOOM_IN, WID_TE_ZOOM_OUT);
2470 virtual void OnQueryTextFinished(char *str)
2472 /* Was 'cancel' pressed? */
2473 if (str == NULL) return;
2475 int32 value;
2476 if (!StrEmpty(str)) {
2477 value = atoi(str);
2478 } else {
2479 /* An empty string means revert to the default */
2480 value = DEF_START_YEAR;
2482 SetStartingYear(value);
2484 this->SetDirty();
2487 static HotkeyList hotkeys;
2490 static Hotkey scenedit_maintoolbar_hotkeys[] = {
2491 Hotkey(_maintoolbar_pause_keys, "pause", MTEHK_PAUSE),
2492 Hotkey((uint16)0, "fastforward", MTEHK_FASTFORWARD),
2493 Hotkey(WKC_F2, "settings", MTEHK_SETTINGS),
2494 Hotkey(WKC_F3, "saveload", MTEHK_SAVEGAME),
2495 Hotkey(WKC_F4, "gen_land", MTEHK_GENLAND),
2496 Hotkey(WKC_F5, "gen_town", MTEHK_GENTOWN),
2497 Hotkey(WKC_F6, "gen_industry", MTEHK_GENINDUSTRY),
2498 Hotkey(WKC_F7, "build_road", MTEHK_BUILD_ROAD),
2499 Hotkey(WKC_F8, "build_docks", MTEHK_BUILD_DOCKS),
2500 Hotkey(WKC_F9, "build_trees", MTEHK_BUILD_TREES),
2501 Hotkey(WKC_F10, "build_sign", MTEHK_SIGN),
2502 Hotkey(WKC_F11, "music", MTEHK_MUSIC),
2503 Hotkey(WKC_F12, "land_info", MTEHK_LANDINFO),
2504 Hotkey(WKC_CTRL | 'S', "small_screenshot", MTEHK_SMALL_SCREENSHOT),
2505 Hotkey(WKC_CTRL | 'P', "zoomedin_screenshot", MTEHK_ZOOMEDIN_SCREENSHOT),
2506 Hotkey(WKC_CTRL | 'D', "defaultzoom_screenshot", MTEHK_DEFAULTZOOM_SCREENSHOT),
2507 Hotkey((uint16)0, "giant_screenshot", MTEHK_GIANT_SCREENSHOT),
2508 Hotkey(_maintoolbar_zoomin_keys, "zoomin", MTEHK_ZOOM_IN),
2509 Hotkey(_maintoolbar_zoomout_keys, "zoomout", MTEHK_ZOOM_OUT),
2510 Hotkey('L', "terraform", MTEHK_TERRAFORM),
2511 Hotkey('M', "smallmap", MTEHK_SMALLMAP),
2512 Hotkey('V', "extra_viewport", MTEHK_EXTRA_VIEWPORT),
2513 HOTKEY_LIST_END
2515 HotkeyList ScenarioEditorToolbarWindow::hotkeys("scenedit_maintoolbar", scenedit_maintoolbar_hotkeys);
2517 static const NWidgetPart _nested_toolb_scen_inner_widgets[] = {
2518 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_PAUSE), SetDataTip(SPR_IMG_PAUSE, STR_TOOLBAR_TOOLTIP_PAUSE_GAME),
2519 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_FAST_FORWARD), SetDataTip(SPR_IMG_FASTFORWARD, STR_TOOLBAR_TOOLTIP_FORWARD),
2520 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SETTINGS), SetDataTip(SPR_IMG_SETTINGS, STR_TOOLBAR_TOOLTIP_OPTIONS),
2521 NWidget(WWT_IMGBTN_2, COLOUR_GREY, WID_TE_SAVE), SetDataTip(SPR_IMG_SAVE, STR_SCENEDIT_TOOLBAR_TOOLTIP_SAVE_SCENARIO_LOAD_SCENARIO),
2522 NWidget(NWID_SPACER),
2523 NWidget(WWT_PANEL, COLOUR_GREY, WID_TE_SPACER), EndContainer(),
2524 NWidget(NWID_SPACER),
2525 NWidget(WWT_PANEL, COLOUR_GREY, WID_TE_DATE_PANEL),
2526 NWidget(NWID_HORIZONTAL), SetPIP(3, 2, 3),
2527 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_DATE_BACKWARD), SetDataTip(SPR_ARROW_DOWN, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD),
2528 NWidget(WWT_EMPTY, COLOUR_GREY, WID_TE_DATE), SetDataTip(STR_NULL, STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE),
2529 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_DATE_FORWARD), SetDataTip(SPR_ARROW_UP, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD),
2530 EndContainer(),
2531 EndContainer(),
2532 NWidget(NWID_SPACER),
2533 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SMALL_MAP), SetDataTip(SPR_IMG_SMALLMAP, STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY),
2534 NWidget(NWID_SPACER),
2535 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_IN), SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN),
2536 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_OUT), SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT),
2537 NWidget(NWID_SPACER),
2538 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_LAND_GENERATE), SetDataTip(SPR_IMG_LANDSCAPING, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION),
2539 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TOWN_GENERATE), SetDataTip(SPR_IMG_TOWN, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION),
2540 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_INDUSTRY), SetDataTip(SPR_IMG_INDUSTRY, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION),
2541 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ROADS), SetDataTip(SPR_IMG_BUILDROAD, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION),
2542 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_WATER), SetDataTip(SPR_IMG_BUILDWATER, STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS),
2543 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TREES), SetDataTip(SPR_IMG_PLANTTREES, STR_SCENEDIT_TOOLBAR_PLANT_TREES),
2544 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_SIGNS), SetDataTip(SPR_IMG_SIGN, STR_SCENEDIT_TOOLBAR_PLACE_SIGN),
2545 NWidget(NWID_SPACER),
2546 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_MUSIC_SOUND), SetDataTip(SPR_IMG_MUSIC, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW),
2547 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_HELP), SetDataTip(SPR_IMG_QUERY, STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION),
2548 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SWITCH_BAR), SetDataTip(SPR_IMG_SWITCH_TOOLBAR, STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR),
2551 static NWidgetBase *MakeScenarioToolbar(int *biggest_index)
2553 return MakeNWidgets(_nested_toolb_scen_inner_widgets, lengthof(_nested_toolb_scen_inner_widgets), biggest_index, new NWidgetScenarioToolbarContainer());
2556 static const NWidgetPart _nested_toolb_scen_widgets[] = {
2557 NWidgetFunction(MakeScenarioToolbar),
2560 static WindowDesc _toolb_scen_desc(
2561 WDP_MANUAL, NULL, 0, 0,
2562 WC_MAIN_TOOLBAR, WC_NONE,
2563 WDF_NO_FOCUS,
2564 _nested_toolb_scen_widgets, lengthof(_nested_toolb_scen_widgets),
2565 &ScenarioEditorToolbarWindow::hotkeys
2568 /** Allocate the toolbar. */
2569 void AllocateToolbar()
2571 /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
2572 _last_built_roadtype = ROADTYPE_ROAD;
2574 if (_game_mode == GM_EDITOR) {
2575 new ScenarioEditorToolbarWindow(&_toolb_scen_desc);
2576 } else {
2577 new MainToolbarWindow(&_toolb_normal_desc);