2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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 /** @file toolbar_gui.cpp Code related to the (main) toolbar. */
12 #include "window_gui.h"
13 #include "window_func.h"
14 #include "viewport_func.h"
15 #include "command_func.h"
16 #include "vehicle_gui.h"
20 #include "date_func.h"
21 #include "vehicle_func.h"
22 #include "sound_func.h"
23 #include "terraform_gui.h"
24 #include "strings_func.h"
25 #include "company_func.h"
26 #include "company_gui.h"
27 #include "vehicle_base.h"
28 #include "cheat_func.h"
29 #include "transparency_gui.h"
30 #include "screenshot.h"
31 #include "signs_func.h"
33 #include "console_gui.h"
35 #include "ai/ai_gui.hpp"
36 #include "tilehighlight_func.h"
37 #include "smallmap_gui.h"
38 #include "graph_gui.h"
39 #include "textbuf_gui.h"
40 #include "linkgraph/linkgraph_gui.h"
41 #include "newgrf_debug.h"
43 #include "engine_base.h"
44 #include "highscore.h"
45 #include "game/game.hpp"
46 #include "goal_base.h"
47 #include "story_base.h"
48 #include "toolbar_gui.h"
49 #include "framerate_type.h"
50 #include "guitimer_func.h"
51 #include "screenshot_gui.h"
54 #include "widgets/toolbar_widget.h"
56 #include "network/network.h"
57 #include "network/network_gui.h"
58 #include "network/network_func.h"
60 #include "safeguards.h"
63 /** Width of the toolbar, shared by statusbar. */
64 uint _toolbar_width
= 0;
66 RailType _last_built_railtype
;
67 RoadType _last_built_roadtype
;
68 RoadType _last_built_tramtype
;
77 /** Callback functions. */
78 enum CallBackFunction
{
84 static CallBackFunction _last_started_action
= CBF_NONE
; ///< Last started user action.
88 * Drop down list entry for showing a checked/unchecked toggle item.
90 class DropDownListCheckedItem
: public DropDownListStringItem
{
95 DropDownListCheckedItem(StringID string
, int result
, bool masked
, bool checked
) : DropDownListStringItem(string
, result
, masked
), checked(checked
)
97 this->checkmark_width
= GetStringBoundingBox(STR_JUST_CHECKMARK
).width
+ 3;
102 return DropDownListStringItem::Width() + this->checkmark_width
;
105 void Draw(int left
, int right
, int top
, int bottom
, bool sel
, Colours bg_colour
) const
107 bool rtl
= _current_text_dir
== TD_RTL
;
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
{
124 DropDownListCompanyItem(int result
, bool masked
, bool greyed
) : DropDownListItem(result
, masked
), greyed(greyed
)
126 this->icon_size
= GetSpriteSize(SPR_COMPANY_ICON
);
127 this->lock_size
= GetSpriteSize(SPR_LOCK
);
130 bool Selectable() const override
135 uint
Width() const override
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
+ this->lock_size
.width
+ 6;
143 uint
Height(uint width
) const override
145 return std::max(std::max(this->icon_size
.height
, this->lock_size
.height
) + 2U, (uint
)FONT_HEIGHT_NORMAL
);
148 void Draw(int left
, int right
, int top
, int bottom
, bool sel
, Colours bg_colour
) const override
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;
158 int lock_offset
= (bottom
- top
- lock_size
.height
) / 2;
160 DrawCompanyIcon(company
, rtl
? right
- this->icon_size
.width
- WD_FRAMERECT_RIGHT
: left
+ WD_FRAMERECT_LEFT
, top
+ icon_offset
);
161 if (NetworkCompanyIsPassworded(company
)) {
162 DrawSprite(SPR_LOCK
, PAL_NONE
, rtl
? left
+ WD_FRAMERECT_LEFT
: right
- this->lock_size
.width
- WD_FRAMERECT_RIGHT
, top
+ lock_offset
);
165 SetDParam(0, company
);
166 SetDParam(1, company
);
169 col
= (sel
? TC_SILVER
: TC_GREY
) | TC_NO_SHADE
;
171 col
= sel
? TC_WHITE
: TC_BLACK
;
173 DrawString(left
+ WD_FRAMERECT_LEFT
+ (rtl
? 3 + this->lock_size
.width
: 3 + this->icon_size
.width
), right
- WD_FRAMERECT_RIGHT
- (rtl
? 3 + this->icon_size
.width
: 3 + this->lock_size
.width
), top
+ text_offset
, STR_COMPANY_NAME_COMPANY_NUM
, col
);
178 * Pop up a generic text only menu.
180 * @param widget Toolbar button
181 * @param list List of items
182 * @param def Default item
184 static void PopupMainToolbMenu(Window
*w
, int widget
, DropDownList
&&list
, int def
)
186 ShowDropDownList(w
, std::move(list
), def
, widget
, 0, true, true);
187 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
191 * Pop up a generic text only menu.
193 * @param widget Toolbar button
194 * @param string String for the first item in the menu
195 * @param count Number of items in the menu
197 static void PopupMainToolbMenu(Window
*w
, int widget
, StringID string
, int count
)
200 for (int i
= 0; i
< count
; i
++) {
201 list
.emplace_back(new DropDownListStringItem(string
+ i
, i
, false));
203 PopupMainToolbMenu(w
, widget
, std::move(list
), 0);
206 /** Enum for the Company Toolbar's network related buttons */
207 static const int CTMN_CLIENT_LIST
= -1; ///< Show the client list
208 static const int CTMN_SPECTATE
= -2; ///< Become spectator
209 static const int CTMN_SPECTATOR
= -3; ///< Show a company window as spectator
212 * Pop up a generic company list menu.
213 * @param w The toolbar window.
214 * @param widget The button widget id.
215 * @param grey A bitbask of which items to mark as disabled.
217 static void PopupMainCompanyToolbMenu(Window
*w
, int widget
, int grey
= 0)
222 case WID_TN_COMPANIES
:
223 if (!_networking
) break;
225 /* Add the client list button for the companies menu */
226 list
.emplace_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST
, CTMN_CLIENT_LIST
, false));
228 if (_local_company
!= COMPANY_SPECTATOR
) {
229 list
.emplace_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE
, CTMN_SPECTATE
, false));
233 list
.emplace_back(new DropDownListStringItem(STR_STORY_BOOK_SPECTATOR
, CTMN_SPECTATOR
, false));
237 list
.emplace_back(new DropDownListStringItem(STR_GOALS_SPECTATOR
, CTMN_SPECTATOR
, false));
241 for (CompanyID c
= COMPANY_FIRST
; c
< MAX_COMPANIES
; c
++) {
242 if (!Company::IsValidID(c
)) continue;
243 list
.emplace_back(new DropDownListCompanyItem(c
, false, HasBit(grey
, c
)));
246 PopupMainToolbMenu(w
, widget
, std::move(list
), _local_company
== COMPANY_SPECTATOR
? (widget
== WID_TN_COMPANIES
? CTMN_CLIENT_LIST
: CTMN_SPECTATOR
) : (int)_local_company
);
250 static ToolbarMode _toolbar_mode
;
252 static CallBackFunction
SelectSignTool()
254 if (_last_started_action
== CBF_PLACE_SIGN
) {
255 ResetObjectToPlace();
258 SetObjectToPlace(SPR_CURSOR_SIGN
, PAL_NONE
, HT_RECT
, WC_MAIN_TOOLBAR
, 0);
259 return CBF_PLACE_SIGN
;
263 /* --- Pausing --- */
265 static CallBackFunction
ToolbarPauseClick(Window
*w
)
267 if (_networking
&& !_network_server
) return CBF_NONE
; // only server can pause the game
269 if (Command
<CMD_PAUSE
>::Post(PM_PAUSED_NORMAL
, _pause_mode
== PM_UNPAUSED
)) {
270 if (_settings_client
.sound
.confirm
) SndPlayFx(SND_15_BEEP
);
276 * Toggle fast forward mode.
281 static CallBackFunction
ToolbarFastForwardClick(Window
*w
)
283 ChangeGameSpeed(_game_speed
== 100);
285 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
290 * Game Option button menu entries.
292 enum OptionMenuEntries
{
299 OME_SHOW_STATIONNAMES
,
300 OME_SHOW_WAYPOINTNAMES
,
302 OME_SHOW_COMPETITOR_SIGNS
,
305 OME_TRANSPARENTBUILDINGS
,
306 OME_SHOW_STATIONSIGNS
,
310 * Handle click on Options button in toolbar.
312 * @param w parent window the shown Drop down list is attached to.
315 static CallBackFunction
ToolbarOptionsClick(Window
*w
)
318 list
.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS
, OME_GAMEOPTIONS
, false));
319 list
.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE
, OME_SETTINGS
, false));
320 /* Changes to the per-AI settings don't get send from the server to the clients. Clients get
321 * the settings once they join but never update it. As such don't show the window at all
322 * to network clients. */
323 if (!_networking
|| _network_server
) list
.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS
, OME_SCRIPT_SETTINGS
, false));
324 list
.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS
, OME_NEWGRFSETTINGS
, false));
325 list
.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS
, OME_TRANSPARENCIES
, false));
326 list
.emplace_back(new DropDownListItem(-1, false));
327 list
.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED
, OME_SHOW_TOWNNAMES
, false, HasBit(_display_opt
, DO_SHOW_TOWN_NAMES
)));
328 list
.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED
, OME_SHOW_STATIONNAMES
, false, HasBit(_display_opt
, DO_SHOW_STATION_NAMES
)));
329 list
.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED
, OME_SHOW_WAYPOINTNAMES
, false, HasBit(_display_opt
, DO_SHOW_WAYPOINT_NAMES
)));
330 list
.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED
, OME_SHOW_SIGNS
, false, HasBit(_display_opt
, DO_SHOW_SIGNS
)));
331 list
.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS
, OME_SHOW_COMPETITOR_SIGNS
, false, HasBit(_display_opt
, DO_SHOW_COMPETITOR_SIGNS
)));
332 list
.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION
, OME_FULL_ANIMATION
, false, HasBit(_display_opt
, DO_FULL_ANIMATION
)));
333 list
.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL
, OME_FULL_DETAILS
, false, HasBit(_display_opt
, DO_FULL_DETAIL
)));
334 list
.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS
, OME_TRANSPARENTBUILDINGS
, false, IsTransparencySet(TO_HOUSES
)));
335 list
.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS
, OME_SHOW_STATIONSIGNS
, false, IsTransparencySet(TO_SIGNS
)));
337 ShowDropDownList(w
, std::move(list
), 0, WID_TN_SETTINGS
, 140, true, true);
338 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
343 * Handle click on one of the entries in the Options button menu.
345 * @param index Index being clicked.
348 static CallBackFunction
MenuClickSettings(int index
)
351 case OME_GAMEOPTIONS
: ShowGameOptions(); return CBF_NONE
;
352 case OME_SETTINGS
: ShowGameSettings(); return CBF_NONE
;
353 case OME_SCRIPT_SETTINGS
: ShowAIConfigWindow(); return CBF_NONE
;
354 case OME_NEWGRFSETTINGS
: ShowNewGRFSettings(!_networking
&& _settings_client
.gui
.UserIsAllowedToChangeNewGRFs(), true, true, &_grfconfig
); return CBF_NONE
;
355 case OME_TRANSPARENCIES
: ShowTransparencyToolbar(); break;
357 case OME_SHOW_TOWNNAMES
: ToggleBit(_display_opt
, DO_SHOW_TOWN_NAMES
); break;
358 case OME_SHOW_STATIONNAMES
: ToggleBit(_display_opt
, DO_SHOW_STATION_NAMES
); break;
359 case OME_SHOW_WAYPOINTNAMES
: ToggleBit(_display_opt
, DO_SHOW_WAYPOINT_NAMES
); break;
360 case OME_SHOW_SIGNS
: ToggleBit(_display_opt
, DO_SHOW_SIGNS
); break;
361 case OME_SHOW_COMPETITOR_SIGNS
:
362 ToggleBit(_display_opt
, DO_SHOW_COMPETITOR_SIGNS
);
363 InvalidateWindowClassesData(WC_SIGN_LIST
, -1);
365 case OME_FULL_ANIMATION
: ToggleBit(_display_opt
, DO_FULL_ANIMATION
); CheckBlitter(); break;
366 case OME_FULL_DETAILS
: ToggleBit(_display_opt
, DO_FULL_DETAIL
); break;
367 case OME_TRANSPARENTBUILDINGS
: ToggleTransparency(TO_HOUSES
); break;
368 case OME_SHOW_STATIONSIGNS
: ToggleTransparency(TO_SIGNS
); break;
370 MarkWholeScreenDirty();
375 * SaveLoad entries in scenario editor mode.
377 enum SaveLoadEditorMenuEntries
{
378 SLEME_SAVE_SCENARIO
= 0,
380 SLEME_SAVE_HEIGHTMAP
,
381 SLEME_LOAD_HEIGHTMAP
,
388 * SaveLoad entries in normal game mode.
390 enum SaveLoadNormalMenuEntries
{
399 * Handle click on Save button in toolbar in normal game mode.
401 * @param w parent window the shown save dialogue is attached to.
404 static CallBackFunction
ToolbarSaveClick(Window
*w
)
406 PopupMainToolbMenu(w
, WID_TN_SAVE
, STR_FILE_MENU_SAVE_GAME
, SLNME_MENUCOUNT
);
411 * Handle click on SaveLoad button in toolbar in the scenario editor.
413 * @param w parent window the shown save dialogue is attached to.
416 static CallBackFunction
ToolbarScenSaveOrLoad(Window
*w
)
418 PopupMainToolbMenu(w
, WID_TE_SAVE
, STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO
, SLEME_MENUCOUNT
);
423 * Handle click on one of the entries in the SaveLoad menu.
425 * @param index Index being clicked.
428 static CallBackFunction
MenuClickSaveLoad(int index
= 0)
430 if (_game_mode
== GM_EDITOR
) {
432 case SLEME_SAVE_SCENARIO
: ShowSaveLoadDialog(FT_SCENARIO
, SLO_SAVE
); break;
433 case SLEME_LOAD_SCENARIO
: ShowSaveLoadDialog(FT_SCENARIO
, SLO_LOAD
); break;
434 case SLEME_SAVE_HEIGHTMAP
: ShowSaveLoadDialog(FT_HEIGHTMAP
,SLO_SAVE
); break;
435 case SLEME_LOAD_HEIGHTMAP
: ShowSaveLoadDialog(FT_HEIGHTMAP
,SLO_LOAD
); break;
436 case SLEME_EXIT_TOINTRO
: AskExitToGameMenu(); break;
437 case SLEME_EXIT_GAME
: HandleExitGameRequest(); break;
441 case SLNME_SAVE_GAME
: ShowSaveLoadDialog(FT_SAVEGAME
, SLO_SAVE
); break;
442 case SLNME_LOAD_GAME
: ShowSaveLoadDialog(FT_SAVEGAME
, SLO_LOAD
); break;
443 case SLNME_EXIT_TOINTRO
: AskExitToGameMenu(); break;
444 case SLNME_EXIT_GAME
: HandleExitGameRequest(); break;
450 /* --- Map button menu --- */
452 enum MapMenuEntries
{
453 MME_SHOW_SMALLMAP
= 0,
454 MME_SHOW_EXTRAVIEWPORTS
,
457 MME_SHOW_TOWNDIRECTORY
,
458 MME_SHOW_INDUSTRYDIRECTORY
,
461 static CallBackFunction
ToolbarMapClick(Window
*w
)
464 list
.emplace_back(new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD
, MME_SHOW_SMALLMAP
, false));
465 list
.emplace_back(new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEWPORT
, MME_SHOW_EXTRAVIEWPORTS
, false));
466 list
.emplace_back(new DropDownListStringItem(STR_MAP_MENU_LINGRAPH_LEGEND
, MME_SHOW_LINKGRAPH
, false));
467 list
.emplace_back(new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST
, MME_SHOW_SIGNLISTS
, false));
468 PopupMainToolbMenu(w
, WID_TN_SMALL_MAP
, std::move(list
), 0);
472 static CallBackFunction
ToolbarScenMapTownDir(Window
*w
)
475 list
.emplace_back(new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD
, MME_SHOW_SMALLMAP
, false));
476 list
.emplace_back(new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEWPORT
, MME_SHOW_EXTRAVIEWPORTS
, false));
477 list
.emplace_back(new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST
, MME_SHOW_SIGNLISTS
, false));
478 list
.emplace_back(new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY
, MME_SHOW_TOWNDIRECTORY
, false));
479 list
.emplace_back(new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY
, MME_SHOW_INDUSTRYDIRECTORY
, false));
480 PopupMainToolbMenu(w
, WID_TE_SMALL_MAP
, std::move(list
), 0);
485 * Handle click on one of the entries in the Map menu.
487 * @param index Index being clicked.
490 static CallBackFunction
MenuClickMap(int index
)
493 case MME_SHOW_SMALLMAP
: ShowSmallMap(); break;
494 case MME_SHOW_EXTRAVIEWPORTS
: ShowExtraViewportWindow(); break;
495 case MME_SHOW_LINKGRAPH
: ShowLinkGraphLegend(); break;
496 case MME_SHOW_SIGNLISTS
: ShowSignList(); break;
497 case MME_SHOW_TOWNDIRECTORY
: ShowTownDirectory(); break;
498 case MME_SHOW_INDUSTRYDIRECTORY
: ShowIndustryDirectory(); break;
503 /* --- Town button menu --- */
505 static CallBackFunction
ToolbarTownClick(Window
*w
)
507 PopupMainToolbMenu(w
, WID_TN_TOWNS
, STR_TOWN_MENU_TOWN_DIRECTORY
, (_settings_game
.economy
.found_town
== TF_FORBIDDEN
) ? 1 : 2);
512 * Handle click on one of the entries in the Town menu.
514 * @param index Index being clicked.
517 static CallBackFunction
MenuClickTown(int index
)
520 case 0: ShowTownDirectory(); break;
521 case 1: // setting could be changed when the dropdown was open
522 if (_settings_game
.economy
.found_town
!= TF_FORBIDDEN
) ShowFoundTownWindow();
528 /* --- Subidies button menu --- */
530 static CallBackFunction
ToolbarSubsidiesClick(Window
*w
)
532 PopupMainToolbMenu(w
, WID_TN_SUBSIDIES
, STR_SUBSIDIES_MENU_SUBSIDIES
, 1);
537 * Handle click on the entry in the Subsidies menu.
539 * @param index Unused.
542 static CallBackFunction
MenuClickSubsidies(int index
)
545 case 0: ShowSubsidiesList(); break;
550 /* --- Stations button menu --- */
552 static CallBackFunction
ToolbarStationsClick(Window
*w
)
554 PopupMainCompanyToolbMenu(w
, WID_TN_STATIONS
);
559 * Handle click on the entry in the Stations menu
561 * @param index CompanyID to show station list for
564 static CallBackFunction
MenuClickStations(int index
)
566 ShowCompanyStations((CompanyID
)index
);
570 /* --- Finances button menu --- */
572 static CallBackFunction
ToolbarFinancesClick(Window
*w
)
574 PopupMainCompanyToolbMenu(w
, WID_TN_FINANCES
);
579 * Handle click on the entry in the finances overview menu.
581 * @param index CompanyID to show finances for.
584 static CallBackFunction
MenuClickFinances(int index
)
586 ShowCompanyFinances((CompanyID
)index
);
590 /* --- Company's button menu --- */
592 static CallBackFunction
ToolbarCompaniesClick(Window
*w
)
594 PopupMainCompanyToolbMenu(w
, WID_TN_COMPANIES
, 0);
599 * Handle click on the entry in the Company menu.
601 * @param index Menu entry to handle.
604 static CallBackFunction
MenuClickCompany(int index
)
608 case CTMN_CLIENT_LIST
:
613 if (_network_server
) {
614 NetworkServerDoMove(CLIENT_ID_SERVER
, COMPANY_SPECTATOR
);
615 MarkWholeScreenDirty();
617 NetworkClientRequestMove(COMPANY_SPECTATOR
);
622 ShowCompany((CompanyID
)index
);
626 /* --- Story button menu --- */
628 static CallBackFunction
ToolbarStoryClick(Window
*w
)
630 PopupMainCompanyToolbMenu(w
, WID_TN_STORY
, 0);
635 * Handle click on the entry in the Story menu
637 * @param index CompanyID to show story book for
640 static CallBackFunction
MenuClickStory(int index
)
642 ShowStoryBook(index
== CTMN_SPECTATOR
? INVALID_COMPANY
: (CompanyID
)index
);
646 /* --- Goal button menu --- */
648 static CallBackFunction
ToolbarGoalClick(Window
*w
)
650 PopupMainCompanyToolbMenu(w
, WID_TN_GOAL
, 0);
655 * Handle click on the entry in the Goal menu
657 * @param index CompanyID to show story book for
660 static CallBackFunction
MenuClickGoal(int index
)
662 ShowGoalsList(index
== CTMN_SPECTATOR
? INVALID_COMPANY
: (CompanyID
)index
);
666 /* --- Graphs button menu --- */
668 static CallBackFunction
ToolbarGraphsClick(Window
*w
)
670 PopupMainToolbMenu(w
, WID_TN_GRAPHS
, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH
, (_toolbar_mode
== TB_NORMAL
) ? 6 : 8);
675 * Handle click on the entry in the Graphs menu.
677 * @param index Graph to show.
680 static CallBackFunction
MenuClickGraphs(int index
)
683 case 0: ShowOperatingProfitGraph(); break;
684 case 1: ShowIncomeGraph(); break;
685 case 2: ShowDeliveredCargoGraph(); break;
686 case 3: ShowPerformanceHistoryGraph(); break;
687 case 4: ShowCompanyValueGraph(); break;
688 case 5: ShowCargoPaymentRates(); break;
689 /* functions for combined graphs/league button */
690 case 6: ShowCompanyLeagueTable(); break;
691 case 7: ShowPerformanceRatingDetail(); break;
696 /* --- League button menu --- */
698 static CallBackFunction
ToolbarLeagueClick(Window
*w
)
700 PopupMainToolbMenu(w
, WID_TN_LEAGUE
, STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE
, _networking
? 2 : 3);
705 * Handle click on the entry in the CompanyLeague menu.
707 * @param index Menu entry number.
710 static CallBackFunction
MenuClickLeague(int index
)
713 case 0: ShowCompanyLeagueTable(); break;
714 case 1: ShowPerformanceRatingDetail(); break;
715 case 2: ShowHighscoreTable(); break;
720 /* --- Industries button menu --- */
722 static CallBackFunction
ToolbarIndustryClick(Window
*w
)
724 /* Disable build-industry menu if we are a spectator */
725 PopupMainToolbMenu(w
, WID_TN_INDUSTRIES
, STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY
, (_local_company
== COMPANY_SPECTATOR
) ? 2 : 3);
730 * Handle click on the entry in the Industry menu.
732 * @param index Menu entry number.
735 static CallBackFunction
MenuClickIndustry(int index
)
738 case 0: ShowIndustryDirectory(); break;
739 case 1: ShowIndustryCargoesWindow(); break;
740 case 2: ShowBuildIndustryWindow(); break;
745 /* --- Trains button menu + 1 helper function for all vehicles. --- */
747 static void ToolbarVehicleClick(Window
*w
, VehicleType veh
)
751 for (const Vehicle
*v
: Vehicle::Iterate()) {
752 if (v
->type
== veh
&& v
->IsPrimaryVehicle()) ClrBit(dis
, v
->owner
);
754 PopupMainCompanyToolbMenu(w
, WID_TN_VEHICLE_START
+ veh
, dis
);
758 static CallBackFunction
ToolbarTrainClick(Window
*w
)
760 ToolbarVehicleClick(w
, VEH_TRAIN
);
765 * Handle click on the entry in the Train menu.
767 * @param index CompanyID to show train list for.
770 static CallBackFunction
MenuClickShowTrains(int index
)
772 ShowVehicleListWindow((CompanyID
)index
, VEH_TRAIN
);
776 /* --- Road vehicle button menu --- */
778 static CallBackFunction
ToolbarRoadClick(Window
*w
)
780 ToolbarVehicleClick(w
, VEH_ROAD
);
785 * Handle click on the entry in the Road Vehicles menu.
787 * @param index CompanyID to show road vehicles list for.
790 static CallBackFunction
MenuClickShowRoad(int index
)
792 ShowVehicleListWindow((CompanyID
)index
, VEH_ROAD
);
796 /* --- Ship button menu --- */
798 static CallBackFunction
ToolbarShipClick(Window
*w
)
800 ToolbarVehicleClick(w
, VEH_SHIP
);
805 * Handle click on the entry in the Ships menu.
807 * @param index CompanyID to show ship list for.
810 static CallBackFunction
MenuClickShowShips(int index
)
812 ShowVehicleListWindow((CompanyID
)index
, VEH_SHIP
);
816 /* --- Aircraft button menu --- */
818 static CallBackFunction
ToolbarAirClick(Window
*w
)
820 ToolbarVehicleClick(w
, VEH_AIRCRAFT
);
825 * Handle click on the entry in the Aircraft menu.
827 * @param index CompanyID to show aircraft list for.
830 static CallBackFunction
MenuClickShowAir(int index
)
832 ShowVehicleListWindow((CompanyID
)index
, VEH_AIRCRAFT
);
836 /* --- Zoom in button --- */
838 static CallBackFunction
ToolbarZoomInClick(Window
*w
)
840 if (DoZoomInOutWindow(ZOOM_IN
, FindWindowById(WC_MAIN_WINDOW
, 0))) {
841 w
->HandleButtonClick((_game_mode
== GM_EDITOR
) ? (byte
)WID_TE_ZOOM_IN
: (byte
)WID_TN_ZOOM_IN
);
842 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
847 /* --- Zoom out button --- */
849 static CallBackFunction
ToolbarZoomOutClick(Window
*w
)
851 if (DoZoomInOutWindow(ZOOM_OUT
, FindWindowById(WC_MAIN_WINDOW
, 0))) {
852 w
->HandleButtonClick((_game_mode
== GM_EDITOR
) ? (byte
)WID_TE_ZOOM_OUT
: (byte
)WID_TN_ZOOM_OUT
);
853 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
858 /* --- Rail button menu --- */
860 static CallBackFunction
ToolbarBuildRailClick(Window
*w
)
862 ShowDropDownList(w
, GetRailTypeDropDownList(), _last_built_railtype
, WID_TN_RAILS
, 140, true, true);
863 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
868 * Handle click on the entry in the Build Rail menu.
870 * @param index RailType to show the build toolbar for.
873 static CallBackFunction
MenuClickBuildRail(int index
)
875 _last_built_railtype
= (RailType
)index
;
876 ShowBuildRailToolbar(_last_built_railtype
);
880 /* --- Road button menu --- */
882 static CallBackFunction
ToolbarBuildRoadClick(Window
*w
)
884 ShowDropDownList(w
, GetRoadTypeDropDownList(RTTB_ROAD
), _last_built_roadtype
, WID_TN_ROADS
, 140, true, true);
885 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
890 * Handle click on the entry in the Build Road menu.
892 * @param index RoadType to show the build toolbar for.
895 static CallBackFunction
MenuClickBuildRoad(int index
)
897 _last_built_roadtype
= (RoadType
)index
;
898 ShowBuildRoadToolbar(_last_built_roadtype
);
902 /* --- Tram button menu --- */
904 static CallBackFunction
ToolbarBuildTramClick(Window
*w
)
906 ShowDropDownList(w
, GetRoadTypeDropDownList(RTTB_TRAM
), _last_built_tramtype
, WID_TN_TRAMS
, 140, true, true);
907 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
912 * Handle click on the entry in the Build Tram menu.
914 * @param index RoadType to show the build toolbar for.
917 static CallBackFunction
MenuClickBuildTram(int index
)
919 _last_built_tramtype
= (RoadType
)index
;
920 ShowBuildRoadToolbar(_last_built_tramtype
);
924 /* --- Water button menu --- */
926 static CallBackFunction
ToolbarBuildWaterClick(Window
*w
)
929 list
.emplace_back(new DropDownListIconItem(SPR_IMG_BUILD_CANAL
, PAL_NONE
, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION
, 0, false));
930 ShowDropDownList(w
, std::move(list
), 0, WID_TN_WATER
, 140, true, true);
931 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
936 * Handle click on the entry in the Build Waterways menu.
938 * @param index Unused.
941 static CallBackFunction
MenuClickBuildWater(int index
)
943 ShowBuildDocksToolbar();
947 /* --- Airport button menu --- */
949 static CallBackFunction
ToolbarBuildAirClick(Window
*w
)
952 list
.emplace_back(new DropDownListIconItem(SPR_IMG_AIRPORT
, PAL_NONE
, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION
, 0, false));
953 ShowDropDownList(w
, std::move(list
), 0, WID_TN_AIR
, 140, true, true);
954 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
959 * Handle click on the entry in the Build Air menu.
961 * @param index Unused.
964 static CallBackFunction
MenuClickBuildAir(int index
)
966 ShowBuildAirToolbar();
970 /* --- Forest button menu --- */
972 static CallBackFunction
ToolbarForestClick(Window
*w
)
975 list
.emplace_back(new DropDownListIconItem(SPR_IMG_LANDSCAPING
, PAL_NONE
, STR_LANDSCAPING_MENU_LANDSCAPING
, 0, false));
976 list
.emplace_back(new DropDownListIconItem(SPR_IMG_PLANTTREES
, PAL_NONE
, STR_LANDSCAPING_MENU_PLANT_TREES
, 1, false));
977 list
.emplace_back(new DropDownListIconItem(SPR_IMG_SIGN
, PAL_NONE
, STR_LANDSCAPING_MENU_PLACE_SIGN
, 2, false));
978 ShowDropDownList(w
, std::move(list
), 0, WID_TN_LANDSCAPE
, 100, true, true);
979 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
984 * Handle click on the entry in the landscaping menu.
986 * @param index Menu entry clicked.
989 static CallBackFunction
MenuClickForest(int index
)
992 case 0: ShowTerraformToolbar(); break;
993 case 1: ShowBuildTreesToolbar(); break;
994 case 2: return SelectSignTool();
999 /* --- Music button menu --- */
1001 static CallBackFunction
ToolbarMusicClick(Window
*w
)
1003 PopupMainToolbMenu(w
, _game_mode
== GM_EDITOR
? (int)WID_TE_MUSIC_SOUND
: (int)WID_TN_MUSIC_SOUND
, STR_TOOLBAR_SOUND_MUSIC
, 1);
1008 * Handle click on the entry in the Music menu.
1010 * @param index Unused.
1013 static CallBackFunction
MenuClickMusicWindow(int index
)
1019 /* --- Newspaper button menu --- */
1021 static CallBackFunction
ToolbarNewspaperClick(Window
*w
)
1023 PopupMainToolbMenu(w
, WID_TN_MESSAGES
, STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT
, 3);
1028 * Handle click on the entry in the Newspaper menu.
1030 * @param index Menu entry clicked.
1033 static CallBackFunction
MenuClickNewspaper(int index
)
1036 case 0: ShowLastNewsMessage(); break;
1037 case 1: ShowMessageHistory(); break;
1038 case 2: DeleteAllMessages(); break;
1043 /* --- Help button menu --- */
1045 static CallBackFunction
PlaceLandBlockInfo()
1047 if (_last_started_action
== CBF_PLACE_LANDINFO
) {
1048 ResetObjectToPlace();
1051 SetObjectToPlace(SPR_CURSOR_QUERY
, PAL_NONE
, HT_RECT
, WC_MAIN_TOOLBAR
, 0);
1052 return CBF_PLACE_LANDINFO
;
1056 static CallBackFunction
ToolbarHelpClick(Window
*w
)
1058 PopupMainToolbMenu(w
, _game_mode
== GM_EDITOR
? (int)WID_TE_HELP
: (int)WID_TN_HELP
, STR_ABOUT_MENU_LAND_BLOCK_INFO
, _settings_client
.gui
.newgrf_developer_tools
? 10 : 7);
1063 * Toggle drawing of sprites' bounding boxes.
1064 * @note has only an effect when newgrf_developer_tools are active.
1066 * Function is found here and not in viewport.cpp in order to avoid
1067 * importing the settings structs to there.
1069 void ToggleBoundingBoxes()
1071 extern bool _draw_bounding_boxes
;
1072 /* Always allow to toggle them off */
1073 if (_settings_client
.gui
.newgrf_developer_tools
|| _draw_bounding_boxes
) {
1074 _draw_bounding_boxes
= !_draw_bounding_boxes
;
1075 MarkWholeScreenDirty();
1080 * Toggle drawing of the dirty blocks.
1081 * @note has only an effect when newgrf_developer_tools are active.
1083 * Function is found here and not in viewport.cpp in order to avoid
1084 * importing the settings structs to there.
1086 void ToggleDirtyBlocks()
1088 extern bool _draw_dirty_blocks
;
1089 /* Always allow to toggle them off */
1090 if (_settings_client
.gui
.newgrf_developer_tools
|| _draw_dirty_blocks
) {
1091 _draw_dirty_blocks
= !_draw_dirty_blocks
;
1092 MarkWholeScreenDirty();
1097 * Set the starting year for a scenario.
1098 * @param year New starting year.
1100 void SetStartingYear(Year year
)
1102 _settings_game
.game_creation
.starting_year
= Clamp(year
, MIN_YEAR
, MAX_YEAR
);
1103 Date new_date
= ConvertYMDToDate(_settings_game
.game_creation
.starting_year
, 0, 1);
1104 /* If you open a savegame as scenario there may already be link graphs.*/
1105 LinkGraphSchedule::instance
.ShiftDates(new_date
- _date
);
1106 SetDate(new_date
, 0);
1110 * Choose the proper callback function for the main toolbar's help menu.
1111 * @param index The menu index which was selected.
1114 static CallBackFunction
MenuClickHelp(int index
)
1117 case 0: return PlaceLandBlockInfo();
1118 case 2: IConsoleSwitch(); break;
1119 case 3: ShowAIDebugWindow(); break;
1120 case 4: ShowScreenshotWindow(); break;
1121 case 5: ShowFramerateWindow(); break;
1122 case 6: ShowAboutWindow(); break;
1123 case 7: ShowSpriteAlignerWindow(); break;
1124 case 8: ToggleBoundingBoxes(); break;
1125 case 9: ToggleDirtyBlocks(); break;
1130 /* --- Switch toolbar button --- */
1132 static CallBackFunction
ToolbarSwitchClick(Window
*w
)
1134 if (_toolbar_mode
!= TB_LOWER
) {
1135 _toolbar_mode
= TB_LOWER
;
1137 _toolbar_mode
= TB_UPPER
;
1141 w
->SetWidgetLoweredState(_game_mode
== GM_EDITOR
? (uint
)WID_TE_SWITCH_BAR
: (uint
)WID_TN_SWITCH_BAR
, _toolbar_mode
== TB_LOWER
);
1142 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1146 /* --- Scenario editor specific handlers. */
1149 * Called when clicking at the date panel of the scenario editor toolbar.
1151 static CallBackFunction
ToolbarScenDatePanel(Window
*w
)
1153 SetDParam(0, _settings_game
.game_creation
.starting_year
);
1154 ShowQueryString(STR_JUST_INT
, STR_MAPGEN_START_DATE_QUERY_CAPT
, 8, w
, CS_NUMERAL
, QSF_ENABLE_DEFAULT
);
1158 static CallBackFunction
ToolbarScenDateBackward(Window
*w
)
1160 /* don't allow too fast scrolling */
1161 if (!(w
->flags
& WF_TIMEOUT
) || w
->timeout_timer
<= 1) {
1162 w
->HandleButtonClick(WID_TE_DATE_BACKWARD
);
1165 SetStartingYear(_settings_game
.game_creation
.starting_year
- 1);
1167 _left_button_clicked
= false;
1171 static CallBackFunction
ToolbarScenDateForward(Window
*w
)
1173 /* don't allow too fast scrolling */
1174 if (!(w
->flags
& WF_TIMEOUT
) || w
->timeout_timer
<= 1) {
1175 w
->HandleButtonClick(WID_TE_DATE_FORWARD
);
1178 SetStartingYear(_settings_game
.game_creation
.starting_year
+ 1);
1180 _left_button_clicked
= false;
1184 static CallBackFunction
ToolbarScenGenLand(Window
*w
)
1186 w
->HandleButtonClick(WID_TE_LAND_GENERATE
);
1187 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1189 ShowEditorTerraformToolbar();
1194 static CallBackFunction
ToolbarScenGenTown(Window
*w
)
1196 w
->HandleButtonClick(WID_TE_TOWN_GENERATE
);
1197 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1198 ShowFoundTownWindow();
1202 static CallBackFunction
ToolbarScenGenIndustry(Window
*w
)
1204 w
->HandleButtonClick(WID_TE_INDUSTRY
);
1205 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1206 ShowBuildIndustryWindow();
1210 static CallBackFunction
ToolbarScenBuildRoadClick(Window
*w
)
1212 ShowDropDownList(w
, GetScenRoadTypeDropDownList(RTTB_ROAD
), _last_built_roadtype
, WID_TE_ROADS
, 140, true, true);
1213 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1218 * Handle click on the entry in the Build Road menu.
1220 * @param index RoadType to show the build toolbar for.
1223 static CallBackFunction
ToolbarScenBuildRoad(int index
)
1225 _last_built_roadtype
= (RoadType
)index
;
1226 ShowBuildRoadScenToolbar(_last_built_roadtype
);
1230 static CallBackFunction
ToolbarScenBuildTramClick(Window
*w
)
1232 ShowDropDownList(w
, GetScenRoadTypeDropDownList(RTTB_TRAM
), _last_built_tramtype
, WID_TE_TRAMS
, 140, true, true);
1233 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1238 * Handle click on the entry in the Build Tram menu.
1240 * @param index RoadType to show the build toolbar for.
1243 static CallBackFunction
ToolbarScenBuildTram(int index
)
1245 _last_built_tramtype
= (RoadType
)index
;
1246 ShowBuildRoadScenToolbar(_last_built_tramtype
);
1250 static CallBackFunction
ToolbarScenBuildDocks(Window
*w
)
1252 w
->HandleButtonClick(WID_TE_WATER
);
1253 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1254 ShowBuildDocksScenToolbar();
1258 static CallBackFunction
ToolbarScenPlantTrees(Window
*w
)
1260 w
->HandleButtonClick(WID_TE_TREES
);
1261 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1262 ShowBuildTreesToolbar();
1266 static CallBackFunction
ToolbarScenPlaceSign(Window
*w
)
1268 w
->HandleButtonClick(WID_TE_SIGNS
);
1269 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1270 return SelectSignTool();
1273 static CallBackFunction
ToolbarBtn_NULL(Window
*w
)
1278 typedef CallBackFunction
MenuClickedProc(int index
);
1280 static MenuClickedProc
* const _menu_clicked_procs
[] = {
1283 MenuClickSettings
, // 2
1284 MenuClickSaveLoad
, // 3
1287 MenuClickSubsidies
, // 6
1288 MenuClickStations
, // 7
1289 MenuClickFinances
, // 8
1290 MenuClickCompany
, // 9
1291 MenuClickStory
, // 10
1292 MenuClickGoal
, // 11
1293 MenuClickGraphs
, // 12
1294 MenuClickLeague
, // 13
1295 MenuClickIndustry
, // 14
1296 MenuClickShowTrains
, // 15
1297 MenuClickShowRoad
, // 16
1298 MenuClickShowShips
, // 17
1299 MenuClickShowAir
, // 18
1302 MenuClickBuildRail
, // 21
1303 MenuClickBuildRoad
, // 22
1304 MenuClickBuildTram
, // 23
1305 MenuClickBuildWater
, // 24
1306 MenuClickBuildAir
, // 25
1307 MenuClickForest
, // 26
1308 MenuClickMusicWindow
, // 27
1309 MenuClickNewspaper
, // 28
1310 MenuClickHelp
, // 29
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
1317 uint spacers
; ///< Number of spacer widgets in this toolbar
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
) override
1336 this->smallest_x
= 0; // Biggest child
1337 this->smallest_y
= 0; // Biggest child
1340 this->resize_x
= 1; // We only resize in this direction
1341 this->resize_y
= 0; // We never resize in this direction
1345 /* First initialise some variables... */
1346 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= nullptr; child_wid
= child_wid
->next
) {
1347 child_wid
->SetupSmallestSize(w
, init_array
);
1348 this->smallest_y
= std::max(this->smallest_y
, child_wid
->smallest_y
+ child_wid
->padding_top
+ child_wid
->padding_bottom
);
1349 if (this->IsButton(child_wid
->type
)) {
1351 this->smallest_x
= std::max(this->smallest_x
, child_wid
->smallest_x
+ child_wid
->padding_left
+ child_wid
->padding_right
);
1352 } else if (child_wid
->type
== NWID_SPACER
) {
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
!= nullptr; 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
) override
1369 assert(given_width
>= this->smallest_x
&& given_height
>= this->smallest_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
!= nullptr; 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
= std::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
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
!= nullptr && possible_spacer
->type
== NWID_SPACER
) {
1406 uint add
= spacer_space
/ (spacer_count
- spacer_i
);
1408 spacer_space
-= add
;
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
;
1419 child_wid
->AssignSizePosition(sizing
, x
+ position
, y
, child_wid
->current_x
, this->current_y
, rtl
);
1420 position
+= child_wid
->current_x
;
1430 void Draw(const Window
*w
) override
1432 /* Draw brown-red toolbar bg. */
1433 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
);
1434 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
);
1436 bool rtl
= _current_text_dir
== TD_RTL
;
1437 for (NWidgetBase
*child_wid
= rtl
? this->tail
: this->head
; child_wid
!= nullptr; 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;
1445 NWidgetCore
*GetWidgetFromPos(int x
, int y
) override
1447 if (!IsInsideBS(x
, this->pos_x
, this->current_x
) || !IsInsideBS(y
, this->pos_y
, this->current_y
)) return nullptr;
1449 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= nullptr; 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
!= nullptr) return nwid
;
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 const byte
*GetButtonArrangement(uint
&width
, uint
&arrangable_count
, uint
&button_count
, uint
&spacer_count
) const override
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
1483 static const byte arrange14
[] = {
1485 WID_TN_FAST_FORWARD
,
1514 static const byte arrange15
[] = {
1516 WID_TN_FAST_FORWARD
,
1547 static const byte arrange16
[] = {
1549 WID_TN_FAST_FORWARD
,
1566 WID_TN_FAST_FORWARD
,
1582 static const byte arrange17
[] = {
1584 WID_TN_FAST_FORWARD
,
1602 WID_TN_FAST_FORWARD
,
1619 static const byte arrange18
[] = {
1621 WID_TN_FAST_FORWARD
,
1640 WID_TN_FAST_FORWARD
,
1658 static const byte arrange19
[] = {
1660 WID_TN_FAST_FORWARD
,
1680 WID_TN_FAST_FORWARD
,
1699 static const byte arrange20
[] = {
1701 WID_TN_FAST_FORWARD
,
1722 WID_TN_FAST_FORWARD
,
1742 static const byte arrange_all
[] = {
1744 WID_TN_FAST_FORWARD
,
1775 /* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
1776 uint full_buttons
= std::max(CeilDiv(width
, this->smallest_x
), SMALLEST_ARRANGEMENT
);
1777 if (full_buttons
> BIGGEST_ARRANGEMENT
) {
1778 button_count
= arrangable_count
= lengthof(arrange_all
);
1779 spacer_count
= this->spacers
;
1783 /* Introduce the split toolbar */
1784 static const byte
* const arrangements
[] = { arrange14
, arrange15
, arrange16
, arrange17
, arrange18
, arrange19
, arrange20
};
1786 button_count
= arrangable_count
= full_buttons
;
1787 spacer_count
= this->spacers
;
1788 return arrangements
[full_buttons
- SMALLEST_ARRANGEMENT
] + ((_toolbar_mode
== TB_LOWER
) ? full_buttons
: 0);
1792 /** Container for the scenario editor's toolbar */
1793 class NWidgetScenarioToolbarContainer
: public NWidgetToolbarContainer
{
1794 uint panel_widths
[2]; ///< The width of the two panels (the text panel and date panel)
1796 void SetupSmallestSize(Window
*w
, bool init_array
) override
1798 this->NWidgetToolbarContainer::SetupSmallestSize(w
, init_array
);
1800 /* Find the size of panel_widths */
1802 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= nullptr; child_wid
= child_wid
->next
) {
1803 if (child_wid
->type
== NWID_SPACER
|| this->IsButton(child_wid
->type
)) continue;
1805 assert(i
< lengthof(this->panel_widths
));
1806 this->panel_widths
[i
++] = child_wid
->current_x
;
1807 _toolbar_width
+= child_wid
->current_x
;
1811 const byte
*GetButtonArrangement(uint
&width
, uint
&arrangable_count
, uint
&button_count
, uint
&spacer_count
) const override
1813 static const byte arrange_all
[] = {
1815 WID_TE_FAST_FORWARD
,
1823 WID_TE_LAND_GENERATE
,
1824 WID_TE_TOWN_GENERATE
,
1834 static const byte arrange_nopanel
[] = {
1836 WID_TE_FAST_FORWARD
,
1843 WID_TE_LAND_GENERATE
,
1844 WID_TE_TOWN_GENERATE
,
1854 static const byte arrange_switch
[] = {
1857 WID_TE_LAND_GENERATE
,
1858 WID_TE_TOWN_GENERATE
,
1868 WID_TE_FAST_FORWARD
,
1880 /* If we can place all buttons *and* the panels, show them. */
1881 uint min_full_width
= (lengthof(arrange_all
) - lengthof(this->panel_widths
)) * this->smallest_x
+ this->panel_widths
[0] + this->panel_widths
[1];
1882 if (width
>= min_full_width
) {
1883 width
-= this->panel_widths
[0] + this->panel_widths
[1];
1884 arrangable_count
= lengthof(arrange_all
);
1885 button_count
= arrangable_count
- 2;
1886 spacer_count
= this->spacers
;
1890 /* 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 */
1891 uint min_small_width
= (lengthof(arrange_switch
) - lengthof(this->panel_widths
)) * this->smallest_x
/ 2 + this->panel_widths
[1];
1892 if (width
> min_small_width
) {
1893 width
-= this->panel_widths
[1];
1894 arrangable_count
= lengthof(arrange_nopanel
);
1895 button_count
= arrangable_count
- 1;
1896 spacer_count
= this->spacers
- 1;
1897 return arrange_nopanel
;
1901 width
-= this->panel_widths
[1];
1902 arrangable_count
= lengthof(arrange_switch
) / 2;
1903 button_count
= arrangable_count
- 1;
1905 return arrange_switch
+ ((_toolbar_mode
== TB_LOWER
) ? arrangable_count
: 0);
1909 /* --- Toolbar handling for the 'normal' case */
1911 typedef CallBackFunction
ToolbarButtonProc(Window
*w
);
1913 static ToolbarButtonProc
* const _toolbar_button_procs
[] = {
1915 ToolbarFastForwardClick
,
1916 ToolbarOptionsClick
,
1920 ToolbarSubsidiesClick
,
1921 ToolbarStationsClick
,
1922 ToolbarFinancesClick
,
1923 ToolbarCompaniesClick
,
1928 ToolbarIndustryClick
,
1934 ToolbarZoomOutClick
,
1935 ToolbarBuildRailClick
,
1936 ToolbarBuildRoadClick
,
1937 ToolbarBuildTramClick
,
1938 ToolbarBuildWaterClick
,
1939 ToolbarBuildAirClick
,
1942 ToolbarNewspaperClick
,
1947 /** Main toolbar. */
1948 struct MainToolbarWindow
: Window
{
1951 MainToolbarWindow(WindowDesc
*desc
) : Window(desc
)
1953 this->InitNested(0);
1955 _last_started_action
= CBF_NONE
;
1956 CLRBITS(this->flags
, WF_WHITE_BORDER
);
1957 this->SetWidgetDisabledState(WID_TN_PAUSE
, _networking
&& !_network_server
); // if not server, disable pause button
1958 this->SetWidgetDisabledState(WID_TN_FAST_FORWARD
, _networking
); // if networking, disable fast-forward button
1959 PositionMainToolbar(this);
1960 DoZoomInOutWindow(ZOOM_NONE
, this);
1962 this->timer
.SetInterval(MILLISECONDS_PER_TICK
);
1965 void FindWindowPlacementAndResize(int def_width
, int def_height
) override
1967 Window::FindWindowPlacementAndResize(_toolbar_width
, def_height
);
1970 void OnPaint() override
1972 /* If spectator, disable all construction buttons
1973 * ie : Build road, rail, ships, airports and landscaping
1974 * Since enabled state is the default, just disable when needed */
1975 this->SetWidgetsDisabledState(_local_company
== COMPANY_SPECTATOR
, WID_TN_RAILS
, WID_TN_ROADS
, WID_TN_TRAMS
, WID_TN_WATER
, WID_TN_AIR
, WID_TN_LANDSCAPE
, WIDGET_LIST_END
);
1976 /* disable company list drop downs, if there are no companies */
1977 this->SetWidgetsDisabledState(Company::GetNumItems() == 0, WID_TN_STATIONS
, WID_TN_FINANCES
, WID_TN_TRAINS
, WID_TN_ROADVEHS
, WID_TN_SHIPS
, WID_TN_AIRCRAFT
, WIDGET_LIST_END
);
1979 this->SetWidgetDisabledState(WID_TN_GOAL
, Goal::GetNumItems() == 0);
1980 this->SetWidgetDisabledState(WID_TN_STORY
, StoryPage::GetNumItems() == 0);
1982 this->DrawWidgets();
1985 void OnClick(Point pt
, int widget
, int click_count
) override
1987 if (_game_mode
!= GM_MENU
&& !this->IsWidgetDisabled(widget
)) _toolbar_button_procs
[widget
](this);
1990 void OnDropdownSelect(int widget
, int index
) override
1992 CallBackFunction cbf
= _menu_clicked_procs
[widget
](index
);
1993 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
1996 EventState
OnHotkey(int hotkey
) override
1998 CallBackFunction cbf
= CBF_NONE
;
2000 case MTHK_PAUSE
: ToolbarPauseClick(this); break;
2001 case MTHK_FASTFORWARD
: ToolbarFastForwardClick(this); break;
2002 case MTHK_SETTINGS
: ShowGameOptions(); break;
2003 case MTHK_SAVEGAME
: MenuClickSaveLoad(); break;
2004 case MTHK_LOADGAME
: ShowSaveLoadDialog(FT_SAVEGAME
, SLO_LOAD
); break;
2005 case MTHK_SMALLMAP
: ShowSmallMap(); break;
2006 case MTHK_TOWNDIRECTORY
: ShowTownDirectory(); break;
2007 case MTHK_SUBSIDIES
: ShowSubsidiesList(); break;
2008 case MTHK_STATIONS
: ShowCompanyStations(_local_company
); break;
2009 case MTHK_FINANCES
: ShowCompanyFinances(_local_company
); break;
2010 case MTHK_COMPANIES
: ShowCompany(_local_company
); break;
2011 case MTHK_STORY
: ShowStoryBook(_local_company
); break;
2012 case MTHK_GOAL
: ShowGoalsList(_local_company
); break;
2013 case MTHK_GRAPHS
: ShowOperatingProfitGraph(); break;
2014 case MTHK_LEAGUE
: ShowCompanyLeagueTable(); break;
2015 case MTHK_INDUSTRIES
: ShowBuildIndustryWindow(); break;
2016 case MTHK_TRAIN_LIST
: ShowVehicleListWindow(_local_company
, VEH_TRAIN
); break;
2017 case MTHK_ROADVEH_LIST
: ShowVehicleListWindow(_local_company
, VEH_ROAD
); break;
2018 case MTHK_SHIP_LIST
: ShowVehicleListWindow(_local_company
, VEH_SHIP
); break;
2019 case MTHK_AIRCRAFT_LIST
: ShowVehicleListWindow(_local_company
, VEH_AIRCRAFT
); break;
2020 case MTHK_ZOOM_IN
: ToolbarZoomInClick(this); break;
2021 case MTHK_ZOOM_OUT
: ToolbarZoomOutClick(this); break;
2022 case MTHK_BUILD_RAIL
: ShowBuildRailToolbar(_last_built_railtype
); break;
2023 case MTHK_BUILD_ROAD
: ShowBuildRoadToolbar(_last_built_roadtype
); break;
2024 case MTHK_BUILD_TRAM
: ShowBuildRoadToolbar(_last_built_tramtype
); break;
2025 case MTHK_BUILD_DOCKS
: ShowBuildDocksToolbar(); break;
2026 case MTHK_BUILD_AIRPORT
: ShowBuildAirToolbar(); break;
2027 case MTHK_BUILD_TREES
: ShowBuildTreesToolbar(); break;
2028 case MTHK_MUSIC
: ShowMusicWindow(); break;
2029 case MTHK_AI_DEBUG
: ShowAIDebugWindow(); break;
2030 case MTHK_SMALL_SCREENSHOT
: MakeScreenshotWithConfirm(SC_VIEWPORT
); break;
2031 case MTHK_ZOOMEDIN_SCREENSHOT
: MakeScreenshotWithConfirm(SC_ZOOMEDIN
); break;
2032 case MTHK_DEFAULTZOOM_SCREENSHOT
: MakeScreenshotWithConfirm(SC_DEFAULTZOOM
); break;
2033 case MTHK_GIANT_SCREENSHOT
: MakeScreenshotWithConfirm(SC_WORLD
); break;
2034 case MTHK_CHEATS
: if (!_networking
) ShowCheatWindow(); break;
2035 case MTHK_TERRAFORM
: ShowTerraformToolbar(); break;
2036 case MTHK_EXTRA_VIEWPORT
: ShowExtraViewportWindowForTileUnderCursor(); break;
2037 case MTHK_CLIENT_LIST
: if (_networking
) ShowClientList(); break;
2038 case MTHK_SIGN_LIST
: ShowSignList(); break;
2039 case MTHK_LANDINFO
: cbf
= PlaceLandBlockInfo(); break;
2040 default: return ES_NOT_HANDLED
;
2042 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
2046 void OnPlaceObject(Point pt
, TileIndex tile
) override
2048 switch (_last_started_action
) {
2049 case CBF_PLACE_SIGN
:
2050 PlaceProc_Sign(tile
);
2053 case CBF_PLACE_LANDINFO
:
2057 default: NOT_REACHED();
2061 void OnPlaceObjectAbort() override
2063 _last_started_action
= CBF_NONE
;
2066 void OnRealtimeTick(uint delta_ms
) override
2068 if (!this->timer
.Elapsed(delta_ms
)) return;
2069 this->timer
.SetInterval(MILLISECONDS_PER_TICK
);
2071 if (this->IsWidgetLowered(WID_TN_PAUSE
) != !!_pause_mode
) {
2072 this->ToggleWidgetLoweredState(WID_TN_PAUSE
);
2073 this->SetWidgetDirty(WID_TN_PAUSE
);
2076 if (this->IsWidgetLowered(WID_TN_FAST_FORWARD
) != (_game_speed
!= 100)) {
2077 this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD
);
2078 this->SetWidgetDirty(WID_TN_FAST_FORWARD
);
2082 void OnTimeout() override
2084 /* We do not want to automatically raise the pause, fast forward and
2085 * switchbar buttons; they have to stay down when pressed etc. */
2086 for (uint i
= WID_TN_SETTINGS
; i
< WID_TN_SWITCH_BAR
; i
++) {
2087 if (this->IsWidgetLowered(i
)) {
2088 this->RaiseWidget(i
);
2089 this->SetWidgetDirty(i
);
2095 * Some data on this window has become invalid.
2096 * @param data Information about the changed data.
2097 * @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.
2099 void OnInvalidateData(int data
= 0, bool gui_scope
= true) override
2101 if (!gui_scope
) return;
2102 if (FindWindowById(WC_MAIN_WINDOW
, 0) != nullptr) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW
, 0)->viewport
, WID_TN_ZOOM_IN
, WID_TN_ZOOM_OUT
);
2105 static HotkeyList hotkeys
;
2108 const uint16 _maintoolbar_pause_keys
[] = {WKC_F1
, WKC_PAUSE
, 0};
2109 const uint16 _maintoolbar_zoomin_keys
[] = {WKC_NUM_PLUS
, WKC_EQUALS
, WKC_SHIFT
| WKC_EQUALS
, WKC_SHIFT
| WKC_F5
, 0};
2110 const uint16 _maintoolbar_zoomout_keys
[] = {WKC_NUM_MINUS
, WKC_MINUS
, WKC_SHIFT
| WKC_MINUS
, WKC_SHIFT
| WKC_F6
, 0};
2111 const uint16 _maintoolbar_smallmap_keys
[] = {WKC_F4
, 'M', 0};
2113 static Hotkey maintoolbar_hotkeys
[] = {
2114 Hotkey(_maintoolbar_pause_keys
, "pause", MTHK_PAUSE
),
2115 Hotkey((uint16
)0, "fastforward", MTHK_FASTFORWARD
),
2116 Hotkey(WKC_F2
, "settings", MTHK_SETTINGS
),
2117 Hotkey(WKC_F3
, "saveload", MTHK_SAVEGAME
),
2118 Hotkey((uint16
)0, "load_game", MTHK_LOADGAME
),
2119 Hotkey(_maintoolbar_smallmap_keys
, "smallmap", MTHK_SMALLMAP
),
2120 Hotkey(WKC_F5
, "town_list", MTHK_TOWNDIRECTORY
),
2121 Hotkey(WKC_F6
, "subsidies", MTHK_SUBSIDIES
),
2122 Hotkey(WKC_F7
, "station_list", MTHK_STATIONS
),
2123 Hotkey(WKC_F8
, "finances", MTHK_FINANCES
),
2124 Hotkey(WKC_F9
, "companies", MTHK_COMPANIES
),
2125 Hotkey((uint16
)0, "story_book", MTHK_STORY
),
2126 Hotkey((uint16
)0, "goal_list", MTHK_GOAL
),
2127 Hotkey(WKC_F10
, "graphs", MTHK_GRAPHS
),
2128 Hotkey(WKC_F11
, "league", MTHK_LEAGUE
),
2129 Hotkey(WKC_F12
, "industry_list", MTHK_INDUSTRIES
),
2130 Hotkey(WKC_SHIFT
| WKC_F1
, "train_list", MTHK_TRAIN_LIST
),
2131 Hotkey(WKC_SHIFT
| WKC_F2
, "roadveh_list", MTHK_ROADVEH_LIST
),
2132 Hotkey(WKC_SHIFT
| WKC_F3
, "ship_list", MTHK_SHIP_LIST
),
2133 Hotkey(WKC_SHIFT
| WKC_F4
, "aircraft_list", MTHK_AIRCRAFT_LIST
),
2134 Hotkey(_maintoolbar_zoomin_keys
, "zoomin", MTHK_ZOOM_IN
),
2135 Hotkey(_maintoolbar_zoomout_keys
, "zoomout", MTHK_ZOOM_OUT
),
2136 Hotkey(WKC_SHIFT
| WKC_F7
, "build_rail", MTHK_BUILD_RAIL
),
2137 Hotkey(WKC_SHIFT
| WKC_F8
, "build_road", MTHK_BUILD_ROAD
),
2138 Hotkey((uint16
)0, "build_tram", MTHK_BUILD_TRAM
),
2139 Hotkey(WKC_SHIFT
| WKC_F9
, "build_docks", MTHK_BUILD_DOCKS
),
2140 Hotkey(WKC_SHIFT
| WKC_F10
, "build_airport", MTHK_BUILD_AIRPORT
),
2141 Hotkey(WKC_SHIFT
| WKC_F11
, "build_trees", MTHK_BUILD_TREES
),
2142 Hotkey(WKC_SHIFT
| WKC_F12
, "music", MTHK_MUSIC
),
2143 Hotkey((uint16
)0, "ai_debug", MTHK_AI_DEBUG
),
2144 Hotkey(WKC_CTRL
| 'S', "small_screenshot", MTHK_SMALL_SCREENSHOT
),
2145 Hotkey(WKC_CTRL
| 'P', "zoomedin_screenshot", MTHK_ZOOMEDIN_SCREENSHOT
),
2146 Hotkey(WKC_CTRL
| 'D', "defaultzoom_screenshot", MTHK_DEFAULTZOOM_SCREENSHOT
),
2147 Hotkey((uint16
)0, "giant_screenshot", MTHK_GIANT_SCREENSHOT
),
2148 Hotkey(WKC_CTRL
| WKC_ALT
| 'C', "cheats", MTHK_CHEATS
),
2149 Hotkey('L', "terraform", MTHK_TERRAFORM
),
2150 Hotkey('V', "extra_viewport", MTHK_EXTRA_VIEWPORT
),
2151 Hotkey((uint16
)0, "client_list", MTHK_CLIENT_LIST
),
2152 Hotkey((uint16
)0, "sign_list", MTHK_SIGN_LIST
),
2153 Hotkey((uint16
)0, "land_info", MTHK_LANDINFO
),
2156 HotkeyList
MainToolbarWindow::hotkeys("maintoolbar", maintoolbar_hotkeys
);
2158 static NWidgetBase
*MakeMainToolbar(int *biggest_index
)
2160 /** Sprites to use for the different toolbar buttons */
2161 static const SpriteID toolbar_button_sprites
[] = {
2162 SPR_IMG_PAUSE
, // WID_TN_PAUSE
2163 SPR_IMG_FASTFORWARD
, // WID_TN_FAST_FORWARD
2164 SPR_IMG_SETTINGS
, // WID_TN_SETTINGS
2165 SPR_IMG_SAVE
, // WID_TN_SAVE
2166 SPR_IMG_SMALLMAP
, // WID_TN_SMALL_MAP
2167 SPR_IMG_TOWN
, // WID_TN_TOWNS
2168 SPR_IMG_SUBSIDIES
, // WID_TN_SUBSIDIES
2169 SPR_IMG_COMPANY_LIST
, // WID_TN_STATIONS
2170 SPR_IMG_COMPANY_FINANCE
, // WID_TN_FINANCES
2171 SPR_IMG_COMPANY_GENERAL
, // WID_TN_COMPANIES
2172 SPR_IMG_STORY_BOOK
, // WID_TN_STORY
2173 SPR_IMG_GOAL
, // WID_TN_GOAL
2174 SPR_IMG_GRAPHS
, // WID_TN_GRAPHS
2175 SPR_IMG_COMPANY_LEAGUE
, // WID_TN_LEAGUE
2176 SPR_IMG_INDUSTRY
, // WID_TN_INDUSTRIES
2177 SPR_IMG_TRAINLIST
, // WID_TN_TRAINS
2178 SPR_IMG_TRUCKLIST
, // WID_TN_ROADVEHS
2179 SPR_IMG_SHIPLIST
, // WID_TN_SHIPS
2180 SPR_IMG_AIRPLANESLIST
, // WID_TN_AIRCRAFT
2181 SPR_IMG_ZOOMIN
, // WID_TN_ZOOMIN
2182 SPR_IMG_ZOOMOUT
, // WID_TN_ZOOMOUT
2183 SPR_IMG_BUILDRAIL
, // WID_TN_RAILS
2184 SPR_IMG_BUILDROAD
, // WID_TN_ROADS
2185 SPR_IMG_BUILDTRAMS
, // WID_TN_TRAMS
2186 SPR_IMG_BUILDWATER
, // WID_TN_WATER
2187 SPR_IMG_BUILDAIR
, // WID_TN_AIR
2188 SPR_IMG_LANDSCAPING
, // WID_TN_LANDSCAPE
2189 SPR_IMG_MUSIC
, // WID_TN_MUSIC_SOUND
2190 SPR_IMG_MESSAGES
, // WID_TN_MESSAGES
2191 SPR_IMG_QUERY
, // WID_TN_HELP
2192 SPR_IMG_SWITCH_TOOLBAR
, // WID_TN_SWITCH_BAR
2195 NWidgetMainToolbarContainer
*hor
= new NWidgetMainToolbarContainer();
2196 for (uint i
= 0; i
< WID_TN_END
; i
++) {
2198 case WID_TN_SMALL_MAP
:
2199 case WID_TN_FINANCES
:
2200 case WID_TN_VEHICLE_START
:
2201 case WID_TN_ZOOM_IN
:
2202 case WID_TN_BUILDING_TOOLS_START
:
2203 case WID_TN_MUSIC_SOUND
:
2204 hor
->Add(new NWidgetSpacer(0, 0));
2207 NWidgetLeaf
*leaf
= new NWidgetLeaf(i
== WID_TN_SAVE
? WWT_IMGBTN_2
: WWT_IMGBTN
, COLOUR_GREY
, i
, toolbar_button_sprites
[i
], STR_TOOLBAR_TOOLTIP_PAUSE_GAME
+ i
);
2208 leaf
->SetMinimalSize(20, 20);
2212 *biggest_index
= std::max
<int>(*biggest_index
, WID_TN_SWITCH_BAR
);
2216 static const NWidgetPart _nested_toolbar_normal_widgets
[] = {
2217 NWidgetFunction(MakeMainToolbar
),
2220 static WindowDesc
_toolb_normal_desc(
2221 WDP_MANUAL
, nullptr, 0, 0,
2222 WC_MAIN_TOOLBAR
, WC_NONE
,
2224 _nested_toolbar_normal_widgets
, lengthof(_nested_toolbar_normal_widgets
),
2225 &MainToolbarWindow::hotkeys
2229 /* --- Toolbar handling for the scenario editor */
2231 static MenuClickedProc
* const _scen_toolbar_dropdown_procs
[] = {
2234 MenuClickSettings
, // 2
2235 MenuClickSaveLoad
, // 3
2246 ToolbarScenBuildRoad
, // 14
2247 ToolbarScenBuildTram
, // 15
2252 MenuClickMusicWindow
, // 20
2253 MenuClickHelp
, // 21
2257 static ToolbarButtonProc
* const _scen_toolbar_button_procs
[] = {
2259 ToolbarFastForwardClick
,
2260 ToolbarOptionsClick
,
2261 ToolbarScenSaveOrLoad
,
2263 ToolbarScenDatePanel
,
2264 ToolbarScenDateBackward
,
2265 ToolbarScenDateForward
,
2266 ToolbarScenMapTownDir
,
2268 ToolbarZoomOutClick
,
2271 ToolbarScenGenIndustry
,
2272 ToolbarScenBuildRoadClick
,
2273 ToolbarScenBuildTramClick
,
2274 ToolbarScenBuildDocks
,
2275 ToolbarScenPlantTrees
,
2276 ToolbarScenPlaceSign
,
2283 enum MainToolbarEditorHotkeys
{
2298 MTEHK_SMALL_SCREENSHOT
,
2299 MTEHK_ZOOMEDIN_SCREENSHOT
,
2300 MTEHK_DEFAULTZOOM_SCREENSHOT
,
2301 MTEHK_GIANT_SCREENSHOT
,
2306 MTEHK_EXTRA_VIEWPORT
,
2309 struct ScenarioEditorToolbarWindow
: Window
{
2312 ScenarioEditorToolbarWindow(WindowDesc
*desc
) : Window(desc
)
2314 this->InitNested(0);
2316 _last_started_action
= CBF_NONE
;
2317 CLRBITS(this->flags
, WF_WHITE_BORDER
);
2318 PositionMainToolbar(this);
2319 DoZoomInOutWindow(ZOOM_NONE
, this);
2321 this->timer
.SetInterval(MILLISECONDS_PER_TICK
);
2324 void FindWindowPlacementAndResize(int def_width
, int def_height
) override
2326 Window::FindWindowPlacementAndResize(_toolbar_width
, def_height
);
2329 void OnPaint() override
2331 this->SetWidgetDisabledState(WID_TE_DATE_BACKWARD
, _settings_game
.game_creation
.starting_year
<= MIN_YEAR
);
2332 this->SetWidgetDisabledState(WID_TE_DATE_FORWARD
, _settings_game
.game_creation
.starting_year
>= MAX_YEAR
);
2333 this->SetWidgetDisabledState(WID_TE_ROADS
, (GetRoadTypes(true) & ~_roadtypes_type
) == ROADTYPES_NONE
);
2334 this->SetWidgetDisabledState(WID_TE_TRAMS
, (GetRoadTypes(true) & _roadtypes_type
) == ROADTYPES_NONE
);
2336 this->DrawWidgets();
2339 void SetStringParameters(int widget
) const override
2343 SetDParam(0, ConvertYMDToDate(_settings_game
.game_creation
.starting_year
, 0, 1));
2348 void DrawWidget(const Rect
&r
, int widget
) const override
2351 case WID_TE_SPACER
: {
2352 int height
= r
.bottom
- r
.top
;
2353 if (height
> 2 * FONT_HEIGHT_NORMAL
) {
2354 DrawString(r
.left
, r
.right
, (height
+ 1) / 2 - FONT_HEIGHT_NORMAL
, STR_SCENEDIT_TOOLBAR_OPENTTD
, TC_FROMSTRING
, SA_HOR_CENTER
);
2355 DrawString(r
.left
, r
.right
, (height
+ 1) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
, TC_FROMSTRING
, SA_HOR_CENTER
);
2357 DrawString(r
.left
, r
.right
, (height
- FONT_HEIGHT_NORMAL
) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
, TC_FROMSTRING
, SA_HOR_CENTER
);
2364 void UpdateWidgetSize(int widget
, Dimension
*size
, const Dimension
&padding
, Dimension
*fill
, Dimension
*resize
) override
2368 size
->width
= std::max(GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_OPENTTD
).width
, GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
).width
) + WD_FRAMERECT_LEFT
+ WD_FRAMERECT_RIGHT
;
2372 SetDParam(0, ConvertYMDToDate(MAX_YEAR
, 0, 1));
2373 *size
= GetStringBoundingBox(STR_WHITE_DATE_LONG
);
2378 void OnClick(Point pt
, int widget
, int click_count
) override
2380 if (_game_mode
== GM_MENU
) return;
2381 CallBackFunction cbf
= _scen_toolbar_button_procs
[widget
](this);
2382 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
2385 void OnDropdownSelect(int widget
, int index
) override
2387 CallBackFunction cbf
= _scen_toolbar_dropdown_procs
[widget
](index
);
2388 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
2389 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
2392 EventState
OnHotkey(int hotkey
) override
2394 CallBackFunction cbf
= CBF_NONE
;
2396 case MTEHK_PAUSE
: ToolbarPauseClick(this); break;
2397 case MTEHK_FASTFORWARD
: ToolbarFastForwardClick(this); break;
2398 case MTEHK_SETTINGS
: ShowGameOptions(); break;
2399 case MTEHK_SAVEGAME
: MenuClickSaveLoad(); break;
2400 case MTEHK_GENLAND
: ToolbarScenGenLand(this); break;
2401 case MTEHK_GENTOWN
: ToolbarScenGenTown(this); break;
2402 case MTEHK_GENINDUSTRY
: ToolbarScenGenIndustry(this); break;
2403 case MTEHK_BUILD_ROAD
: ToolbarScenBuildRoadClick(this); break;
2404 case MTEHK_BUILD_TRAM
: ToolbarScenBuildTramClick(this); break;
2405 case MTEHK_BUILD_DOCKS
: ToolbarScenBuildDocks(this); break;
2406 case MTEHK_BUILD_TREES
: ToolbarScenPlantTrees(this); break;
2407 case MTEHK_SIGN
: cbf
= ToolbarScenPlaceSign(this); break;
2408 case MTEHK_MUSIC
: ShowMusicWindow(); break;
2409 case MTEHK_LANDINFO
: cbf
= PlaceLandBlockInfo(); break;
2410 case MTEHK_SMALL_SCREENSHOT
: MakeScreenshotWithConfirm(SC_VIEWPORT
); break;
2411 case MTEHK_ZOOMEDIN_SCREENSHOT
: MakeScreenshotWithConfirm(SC_ZOOMEDIN
); break;
2412 case MTEHK_DEFAULTZOOM_SCREENSHOT
: MakeScreenshotWithConfirm(SC_DEFAULTZOOM
); break;
2413 case MTEHK_GIANT_SCREENSHOT
: MakeScreenshotWithConfirm(SC_WORLD
); break;
2414 case MTEHK_ZOOM_IN
: ToolbarZoomInClick(this); break;
2415 case MTEHK_ZOOM_OUT
: ToolbarZoomOutClick(this); break;
2416 case MTEHK_TERRAFORM
: ShowEditorTerraformToolbar(); break;
2417 case MTEHK_SMALLMAP
: ShowSmallMap(); break;
2418 case MTEHK_EXTRA_VIEWPORT
: ShowExtraViewportWindowForTileUnderCursor(); break;
2419 default: return ES_NOT_HANDLED
;
2421 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
2425 void OnPlaceObject(Point pt
, TileIndex tile
) override
2427 switch (_last_started_action
) {
2428 case CBF_PLACE_SIGN
:
2429 PlaceProc_Sign(tile
);
2432 case CBF_PLACE_LANDINFO
:
2436 default: NOT_REACHED();
2440 void OnPlaceObjectAbort() override
2442 _last_started_action
= CBF_NONE
;
2445 void OnTimeout() override
2447 this->SetWidgetsLoweredState(false, WID_TE_DATE_BACKWARD
, WID_TE_DATE_FORWARD
, WIDGET_LIST_END
);
2448 this->SetWidgetDirty(WID_TE_DATE_BACKWARD
);
2449 this->SetWidgetDirty(WID_TE_DATE_FORWARD
);
2452 void OnRealtimeTick(uint delta_ms
) override
2454 if (!this->timer
.Elapsed(delta_ms
)) return;
2455 this->timer
.SetInterval(MILLISECONDS_PER_TICK
);
2457 if (this->IsWidgetLowered(WID_TE_PAUSE
) != !!_pause_mode
) {
2458 this->ToggleWidgetLoweredState(WID_TE_PAUSE
);
2462 if (this->IsWidgetLowered(WID_TE_FAST_FORWARD
) != (_game_speed
!= 100)) {
2463 this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD
);
2469 * Some data on this window has become invalid.
2470 * @param data Information about the changed data.
2471 * @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.
2473 void OnInvalidateData(int data
= 0, bool gui_scope
= true) override
2475 if (!gui_scope
) return;
2476 if (FindWindowById(WC_MAIN_WINDOW
, 0) != nullptr) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW
, 0)->viewport
, WID_TE_ZOOM_IN
, WID_TE_ZOOM_OUT
);
2479 void OnQueryTextFinished(char *str
) override
2481 /* Was 'cancel' pressed? */
2482 if (str
== nullptr) return;
2485 if (!StrEmpty(str
)) {
2488 /* An empty string means revert to the default */
2489 value
= DEF_START_YEAR
;
2491 SetStartingYear(value
);
2496 static HotkeyList hotkeys
;
2499 static Hotkey scenedit_maintoolbar_hotkeys
[] = {
2500 Hotkey(_maintoolbar_pause_keys
, "pause", MTEHK_PAUSE
),
2501 Hotkey((uint16
)0, "fastforward", MTEHK_FASTFORWARD
),
2502 Hotkey(WKC_F2
, "settings", MTEHK_SETTINGS
),
2503 Hotkey(WKC_F3
, "saveload", MTEHK_SAVEGAME
),
2504 Hotkey(WKC_F4
, "gen_land", MTEHK_GENLAND
),
2505 Hotkey(WKC_F5
, "gen_town", MTEHK_GENTOWN
),
2506 Hotkey(WKC_F6
, "gen_industry", MTEHK_GENINDUSTRY
),
2507 Hotkey(WKC_F7
, "build_road", MTEHK_BUILD_ROAD
),
2508 Hotkey((uint16
)0, "build_tram", MTEHK_BUILD_TRAM
),
2509 Hotkey(WKC_F8
, "build_docks", MTEHK_BUILD_DOCKS
),
2510 Hotkey(WKC_F9
, "build_trees", MTEHK_BUILD_TREES
),
2511 Hotkey(WKC_F10
, "build_sign", MTEHK_SIGN
),
2512 Hotkey(WKC_F11
, "music", MTEHK_MUSIC
),
2513 Hotkey(WKC_F12
, "land_info", MTEHK_LANDINFO
),
2514 Hotkey(WKC_CTRL
| 'S', "small_screenshot", MTEHK_SMALL_SCREENSHOT
),
2515 Hotkey(WKC_CTRL
| 'P', "zoomedin_screenshot", MTEHK_ZOOMEDIN_SCREENSHOT
),
2516 Hotkey(WKC_CTRL
| 'D', "defaultzoom_screenshot", MTEHK_DEFAULTZOOM_SCREENSHOT
),
2517 Hotkey((uint16
)0, "giant_screenshot", MTEHK_GIANT_SCREENSHOT
),
2518 Hotkey(_maintoolbar_zoomin_keys
, "zoomin", MTEHK_ZOOM_IN
),
2519 Hotkey(_maintoolbar_zoomout_keys
, "zoomout", MTEHK_ZOOM_OUT
),
2520 Hotkey('L', "terraform", MTEHK_TERRAFORM
),
2521 Hotkey('M', "smallmap", MTEHK_SMALLMAP
),
2522 Hotkey('V', "extra_viewport", MTEHK_EXTRA_VIEWPORT
),
2525 HotkeyList
ScenarioEditorToolbarWindow::hotkeys("scenedit_maintoolbar", scenedit_maintoolbar_hotkeys
);
2527 static const NWidgetPart _nested_toolb_scen_inner_widgets
[] = {
2528 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_PAUSE
), SetDataTip(SPR_IMG_PAUSE
, STR_TOOLBAR_TOOLTIP_PAUSE_GAME
),
2529 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_FAST_FORWARD
), SetDataTip(SPR_IMG_FASTFORWARD
, STR_TOOLBAR_TOOLTIP_FORWARD
),
2530 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_SETTINGS
), SetDataTip(SPR_IMG_SETTINGS
, STR_TOOLBAR_TOOLTIP_OPTIONS
),
2531 NWidget(WWT_IMGBTN_2
, COLOUR_GREY
, WID_TE_SAVE
), SetDataTip(SPR_IMG_SAVE
, STR_SCENEDIT_TOOLBAR_TOOLTIP_SAVE_SCENARIO_LOAD_SCENARIO
),
2532 NWidget(NWID_SPACER
),
2533 NWidget(WWT_PANEL
, COLOUR_GREY
, WID_TE_SPACER
), EndContainer(),
2534 NWidget(NWID_SPACER
),
2535 NWidget(WWT_PANEL
, COLOUR_GREY
, WID_TE_DATE_PANEL
),
2536 NWidget(NWID_HORIZONTAL
), SetPIP(2, 2, 2), SetPadding(1),
2537 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_DATE_BACKWARD
), SetDataTip(SPR_ARROW_DOWN
, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD
), SetFill(0, 1),
2538 NWidget(WWT_TEXT
, COLOUR_GREY
, WID_TE_DATE
), SetDataTip(STR_WHITE_DATE_LONG
, STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE
), SetAlignment(SA_CENTER
), SetFill(0, 1),
2539 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_DATE_FORWARD
), SetDataTip(SPR_ARROW_UP
, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD
), SetFill(0, 1),
2542 NWidget(NWID_SPACER
),
2543 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_SMALL_MAP
), SetDataTip(SPR_IMG_SMALLMAP
, STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY
),
2544 NWidget(NWID_SPACER
),
2545 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_ZOOM_IN
), SetDataTip(SPR_IMG_ZOOMIN
, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN
),
2546 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_ZOOM_OUT
), SetDataTip(SPR_IMG_ZOOMOUT
, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT
),
2547 NWidget(NWID_SPACER
),
2548 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_LAND_GENERATE
), SetDataTip(SPR_IMG_LANDSCAPING
, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION
),
2549 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_TOWN_GENERATE
), SetDataTip(SPR_IMG_TOWN
, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION
),
2550 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_INDUSTRY
), SetDataTip(SPR_IMG_INDUSTRY
, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION
),
2551 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_ROADS
), SetDataTip(SPR_IMG_BUILDROAD
, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION
),
2552 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_TRAMS
), SetDataTip(SPR_IMG_BUILDTRAMS
, STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION
),
2553 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_WATER
), SetDataTip(SPR_IMG_BUILDWATER
, STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS
),
2554 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_TREES
), SetDataTip(SPR_IMG_PLANTTREES
, STR_SCENEDIT_TOOLBAR_PLANT_TREES
),
2555 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_SIGNS
), SetDataTip(SPR_IMG_SIGN
, STR_SCENEDIT_TOOLBAR_PLACE_SIGN
),
2556 NWidget(NWID_SPACER
),
2557 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_MUSIC_SOUND
), SetDataTip(SPR_IMG_MUSIC
, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW
),
2558 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_HELP
), SetDataTip(SPR_IMG_QUERY
, STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION
),
2559 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_SWITCH_BAR
), SetDataTip(SPR_IMG_SWITCH_TOOLBAR
, STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR
),
2562 static NWidgetBase
*MakeScenarioToolbar(int *biggest_index
)
2564 return MakeNWidgets(_nested_toolb_scen_inner_widgets
, lengthof(_nested_toolb_scen_inner_widgets
), biggest_index
, new NWidgetScenarioToolbarContainer());
2567 static const NWidgetPart _nested_toolb_scen_widgets
[] = {
2568 NWidgetFunction(MakeScenarioToolbar
),
2571 static WindowDesc
_toolb_scen_desc(
2572 WDP_MANUAL
, nullptr, 0, 0,
2573 WC_MAIN_TOOLBAR
, WC_NONE
,
2575 _nested_toolb_scen_widgets
, lengthof(_nested_toolb_scen_widgets
),
2576 &ScenarioEditorToolbarWindow::hotkeys
2579 /** Allocate the toolbar. */
2580 void AllocateToolbar()
2582 /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
2583 _last_built_roadtype
= ROADTYPE_ROAD
;
2584 _last_built_tramtype
= ROADTYPE_TRAM
;
2586 if (_game_mode
== GM_EDITOR
) {
2587 new ScenarioEditorToolbarWindow(&_toolb_scen_desc
);
2589 new MainToolbarWindow(&_toolb_normal_desc
);