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/>.
10 /** @file toolbar_gui.cpp Code related to the (main) toolbar. */
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"
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"
34 #include "console_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"
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.
75 /** Callback functions. */
76 enum CallBackFunction
{
82 static CallBackFunction _last_started_action
= CBF_NONE
; ///< Last started user action.
86 * Drop down list entry for showing a checked/unchecked toggle item.
88 class DropDownListCheckedItem
: public DropDownListStringItem
{
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() {}
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
;
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
{
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
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
);
165 col
= (sel
? TC_SILVER
: TC_GREY
) | TC_NO_SHADE
;
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.
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.
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
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());
231 *list
->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE
, CTMN_SPECTATE
, NetworkMaxSpectatorsReached());
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();
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
);
275 * Toggle fast forward mode.
280 static CallBackFunction
ToolbarFastForwardClick(Window
*w
)
282 _fast_forward
^= true;
283 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
288 * Game Option button menu entries.
290 enum OptionMenuEntries
{
297 OME_SHOW_STATIONNAMES
,
298 OME_SHOW_WAYPOINTNAMES
,
300 OME_SHOW_COMPETITOR_SIGNS
,
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.
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
);
341 * Handle click on one of the entries in the Options button menu.
343 * @param index Index being clicked.
346 static CallBackFunction
MenuClickSettings(int 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);
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();
373 * SaveLoad entries in scenario editor mode.
375 enum SaveLoadEditorMenuEntries
{
376 SLEME_SAVE_SCENARIO
= 0,
378 SLEME_SAVE_HEIGHTMAP
,
379 SLEME_LOAD_HEIGHTMAP
,
386 * SaveLoad entries in normal game mode.
388 enum SaveLoadNormalMenuEntries
{
397 * Handle click on Save button in toolbar in normal game mode.
399 * @param w parent window the shown save dialogue is attached to.
402 static CallBackFunction
ToolbarSaveClick(Window
*w
)
404 PopupMainToolbMenu(w
, WID_TN_SAVE
, STR_FILE_MENU_SAVE_GAME
, SLNME_MENUCOUNT
);
409 * Handle click on SaveLoad button in toolbar in the scenario editor.
411 * @param w parent window the shown save dialogue is attached to.
414 static CallBackFunction
ToolbarScenSaveOrLoad(Window
*w
)
416 PopupMainToolbMenu(w
, WID_TE_SAVE
, STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO
, SLEME_MENUCOUNT
);
421 * Handle click on one of the entries in the SaveLoad menu.
423 * @param index Index being clicked.
426 static CallBackFunction
MenuClickSaveLoad(int index
= 0)
428 if (_game_mode
== GM_EDITOR
) {
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;
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;
448 /* --- Map button menu --- */
450 enum MapMenuEntries
{
451 MME_SHOW_SMALLMAP
= 0,
452 MME_SHOW_EXTRAVIEWPORTS
,
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);
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);
483 * Handle click on one of the entries in the Map menu.
485 * @param index Index being clicked.
488 static CallBackFunction
MenuClickMap(int 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;
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);
510 * Handle click on one of the entries in the Town menu.
512 * @param index Index being clicked.
515 static CallBackFunction
MenuClickTown(int 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();
526 /* --- Subidies button menu --- */
528 static CallBackFunction
ToolbarSubsidiesClick(Window
*w
)
530 PopupMainToolbMenu(w
, WID_TN_SUBSIDIES
, STR_SUBSIDIES_MENU_SUBSIDIES
, 1);
535 * Handle click on the entry in the Subsidies menu.
537 * @param index Unused.
540 static CallBackFunction
MenuClickSubsidies(int index
)
543 case 0: ShowSubsidiesList(); break;
548 /* --- Stations button menu --- */
550 static CallBackFunction
ToolbarStationsClick(Window
*w
)
552 PopupMainCompanyToolbMenu(w
, WID_TN_STATIONS
);
557 * Handle click on the entry in the Stations menu
559 * @param index CompanyID to show station list for
562 static CallBackFunction
MenuClickStations(int index
)
564 ShowCompanyStations((CompanyID
)index
);
568 /* --- Finances button menu --- */
570 static CallBackFunction
ToolbarFinancesClick(Window
*w
)
572 PopupMainCompanyToolbMenu(w
, WID_TN_FINANCES
);
577 * Handle click on the entry in the finances overview menu.
579 * @param index CompanyID to show finances for.
582 static CallBackFunction
MenuClickFinances(int index
)
584 ShowCompanyFinances((CompanyID
)index
);
588 /* --- Company's button menu --- */
590 static CallBackFunction
ToolbarCompaniesClick(Window
*w
)
592 PopupMainCompanyToolbMenu(w
, WID_TN_COMPANIES
, 0, true);
597 * Handle click on the entry in the Company menu.
599 * @param index Menu entry to handle.
602 static CallBackFunction
MenuClickCompany(int index
)
604 #ifdef ENABLE_NETWORK
607 case CTMN_CLIENT_LIST
:
611 case CTMN_NEW_COMPANY
:
612 if (_network_server
) {
613 DoCommandP(0, 0, _network_own_client_id
, CMD_COMPANY_CTRL
);
615 NetworkSendCommand(0, 0, 0, CMD_COMPANY_CTRL
, NULL
, NULL
, _local_company
);
620 if (_network_server
) {
621 NetworkServerDoMove(CLIENT_ID_SERVER
, COMPANY_SPECTATOR
);
622 MarkWholeScreenDirty();
624 NetworkClientRequestMove(COMPANY_SPECTATOR
);
629 #endif /* ENABLE_NETWORK */
630 ShowCompany((CompanyID
)index
);
634 /* --- Story button menu --- */
636 static CallBackFunction
ToolbarStoryClick(Window
*w
)
638 PopupMainCompanyToolbMenu(w
, WID_TN_STORY
, 0, true);
643 * Handle click on the entry in the Story menu
645 * @param index CompanyID to show story book for
648 static CallBackFunction
MenuClickStory(int index
)
650 ShowStoryBook(index
== CTMN_SPECTATOR
? INVALID_COMPANY
: (CompanyID
)index
);
654 /* --- Goal button menu --- */
656 static CallBackFunction
ToolbarGoalClick(Window
*w
)
658 PopupMainCompanyToolbMenu(w
, WID_TN_GOAL
, 0, true);
663 * Handle click on the entry in the Goal menu
665 * @param index CompanyID to show story book for
668 static CallBackFunction
MenuClickGoal(int index
)
670 ShowGoalsList(index
== CTMN_SPECTATOR
? INVALID_COMPANY
: (CompanyID
)index
);
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);
683 * Handle click on the entry in the Graphs menu.
685 * @param index Graph to show.
688 static CallBackFunction
MenuClickGraphs(int 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;
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);
713 * Handle click on the entry in the CompanyLeague menu.
715 * @param index Menu entry number.
718 static CallBackFunction
MenuClickLeague(int index
)
721 case 0: ShowCompanyLeagueTable(); break;
722 case 1: ShowPerformanceRatingDetail(); break;
723 case 2: ShowHighscoreTable(); break;
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);
738 * Handle click on the entry in the Industry menu.
740 * @param index Menu entry number.
743 static CallBackFunction
MenuClickIndustry(int index
)
746 case 0: ShowIndustryDirectory(); break;
747 case 1: ShowIndustryCargoesWindow(); break;
748 case 2: ShowBuildIndustryWindow(); break;
753 /* --- Trains button menu + 1 helper function for all vehicles. --- */
755 static void ToolbarVehicleClick(Window
*w
, VehicleType veh
)
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
);
774 * Handle click on the entry in the Train menu.
776 * @param index CompanyID to show train list for.
779 static CallBackFunction
MenuClickShowTrains(int index
)
781 ShowVehicleListWindow((CompanyID
)index
, VEH_TRAIN
);
785 /* --- Road vehicle button menu --- */
787 static CallBackFunction
ToolbarRoadClick(Window
*w
)
789 ToolbarVehicleClick(w
, VEH_ROAD
);
794 * Handle click on the entry in the Road Vehicles menu.
796 * @param index CompanyID to show road vehicles list for.
799 static CallBackFunction
MenuClickShowRoad(int index
)
801 ShowVehicleListWindow((CompanyID
)index
, VEH_ROAD
);
805 /* --- Ship button menu --- */
807 static CallBackFunction
ToolbarShipClick(Window
*w
)
809 ToolbarVehicleClick(w
, VEH_SHIP
);
814 * Handle click on the entry in the Ships menu.
816 * @param index CompanyID to show ship list for.
819 static CallBackFunction
MenuClickShowShips(int index
)
821 ShowVehicleListWindow((CompanyID
)index
, VEH_SHIP
);
825 /* --- Aircraft button menu --- */
827 static CallBackFunction
ToolbarAirClick(Window
*w
)
829 ToolbarVehicleClick(w
, VEH_AIRCRAFT
);
834 * Handle click on the entry in the Aircraft menu.
836 * @param index CompanyID to show aircraft list for.
839 static CallBackFunction
MenuClickShowAir(int index
)
841 ShowVehicleListWindow((CompanyID
)index
, VEH_AIRCRAFT
);
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
);
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
);
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
);
877 * Handle click on the entry in the Build Rail menu.
879 * @param index RailType to show the build toolbar for.
882 static CallBackFunction
MenuClickBuildRail(int index
)
884 _last_built_railtype
= (RailType
)index
;
885 ShowBuildRailToolbar(_last_built_railtype
);
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. */
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
));
908 ShowDropDownList(w
, list
, _last_built_roadtype
, WID_TN_ROADS
, 140, true, true);
909 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
914 * Handle click on the entry in the Build Road menu.
916 * @param index RoadType to show the build toolbar for.
919 static CallBackFunction
MenuClickBuildRoad(int index
)
921 _last_built_roadtype
= (RoadType
)index
;
922 ShowBuildRoadToolbar(_last_built_roadtype
);
926 /* --- Water button menu --- */
928 static CallBackFunction
ToolbarBuildWaterClick(Window
*w
)
930 PopupMainToolbMenu(w
, WID_TN_WATER
, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION
, 1);
935 * Handle click on the entry in the Build Waterways menu.
937 * @param index Unused.
940 static CallBackFunction
MenuClickBuildWater(int index
)
942 ShowBuildDocksToolbar();
946 /* --- Airport button menu --- */
948 static CallBackFunction
ToolbarBuildAirClick(Window
*w
)
950 PopupMainToolbMenu(w
, WID_TN_AIR
, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION
, 1);
955 * Handle click on the entry in the Build Air menu.
957 * @param index Unused.
960 static CallBackFunction
MenuClickBuildAir(int index
)
962 ShowBuildAirToolbar();
966 /* --- Forest button menu --- */
968 static CallBackFunction
ToolbarForestClick(Window
*w
)
970 PopupMainToolbMenu(w
, WID_TN_LANDSCAPE
, STR_LANDSCAPING_MENU_LANDSCAPING
, 3);
975 * Handle click on the entry in the landscaping menu.
977 * @param index Menu entry clicked.
980 static CallBackFunction
MenuClickForest(int index
)
983 case 0: ShowTerraformToolbar(); break;
984 case 1: ShowBuildTreesToolbar(); break;
985 case 2: return SelectSignTool();
990 /* --- Music button menu --- */
992 static CallBackFunction
ToolbarMusicClick(Window
*w
)
994 PopupMainToolbMenu(w
, WID_TN_MUSIC_SOUND
, STR_TOOLBAR_SOUND_MUSIC
, 1);
999 * Handle click on the entry in the Music menu.
1001 * @param index Unused.
1004 static CallBackFunction
MenuClickMusicWindow(int index
)
1010 /* --- Newspaper button menu --- */
1012 static CallBackFunction
ToolbarNewspaperClick(Window
*w
)
1014 PopupMainToolbMenu(w
, WID_TN_MESSAGES
, STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT
, 2);
1019 * Handle click on the entry in the Newspaper menu.
1021 * @param index Menu entry clicked.
1024 static CallBackFunction
MenuClickNewspaper(int index
)
1027 case 0: ShowLastNewsMessage(); break;
1028 case 1: ShowMessageHistory(); break;
1033 /* --- Help button menu --- */
1035 static CallBackFunction
PlaceLandBlockInfo()
1037 if (_last_started_action
== CBF_PLACE_LANDINFO
) {
1038 ResetObjectToPlace();
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);
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
)
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
);
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.
1140 static CallBackFunction
MenuClickHelp(int 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;
1158 /* --- Switch toolbar button --- */
1160 static CallBackFunction
ToolbarSwitchClick(Window
*w
)
1162 if (_toolbar_mode
!= TB_LOWER
) {
1163 _toolbar_mode
= TB_LOWER
;
1165 _toolbar_mode
= TB_UPPER
;
1169 w
->SetWidgetLoweredState(WID_TN_SWITCH_BAR
, _toolbar_mode
== TB_LOWER
);
1170 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
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;
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
);
1194 SetStartingYear(_settings_game
.game_creation
.starting_year
- 1);
1196 _left_button_clicked
= false;
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
);
1207 SetStartingYear(_settings_game
.game_creation
.starting_year
+ 1);
1209 _left_button_clicked
= false;
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();
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();
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();
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();
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();
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();
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
)
1275 typedef CallBackFunction
MenuClickedProc(int index
);
1277 static MenuClickedProc
* const _menu_clicked_procs
[] = {
1280 MenuClickSettings
, // 2
1281 MenuClickSaveLoad
, // 3
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
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
1313 uint spacers
; ///< Number of spacer widgets in this toolbar
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
1336 this->resize_x
= 1; // We only resize in this direction
1337 this->resize_y
= 0; // We never resize in this direction
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
)) {
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
) {
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
);
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
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
);
1404 spacer_space
-= add
;
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
;
1415 child_wid
->AssignSizePosition(sizing
, x
+ position
, y
, child_wid
->current_x
, this->current_y
, rtl
);
1416 position
+= child_wid
->current_x
;
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;
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
;
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
1479 static const byte arrange14
[] = {
1481 WID_TN_FAST_FORWARD
,
1510 static const byte arrange15
[] = {
1512 WID_TN_FAST_FORWARD
,
1543 static const byte arrange16
[] = {
1545 WID_TN_FAST_FORWARD
,
1562 WID_TN_FAST_FORWARD
,
1578 static const byte arrange17
[] = {
1580 WID_TN_FAST_FORWARD
,
1598 WID_TN_FAST_FORWARD
,
1615 static const byte arrange18
[] = {
1617 WID_TN_FAST_FORWARD
,
1636 WID_TN_FAST_FORWARD
,
1654 static const byte arrange19
[] = {
1656 WID_TN_FAST_FORWARD
,
1676 WID_TN_FAST_FORWARD
,
1695 static const byte arrange20
[] = {
1697 WID_TN_FAST_FORWARD
,
1718 WID_TN_FAST_FORWARD
,
1738 static const byte arrange_all
[] = {
1740 WID_TN_FAST_FORWARD
,
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
;
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 */
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
[] = {
1810 WID_TE_FAST_FORWARD
,
1818 WID_TE_LAND_GENERATE
,
1819 WID_TE_TOWN_GENERATE
,
1828 static const byte arrange_nopanel
[] = {
1830 WID_TE_FAST_FORWARD
,
1837 WID_TE_LAND_GENERATE
,
1838 WID_TE_TOWN_GENERATE
,
1847 static const byte arrange_switch
[] = {
1850 WID_TE_LAND_GENERATE
,
1851 WID_TE_TOWN_GENERATE
,
1860 WID_TE_FAST_FORWARD
,
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
;
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
;
1891 width
-= this->panel_widths
[1];
1892 arrangable_count
= lengthof(arrange_switch
) / 2;
1893 button_count
= arrangable_count
- 1;
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
[] = {
1905 ToolbarFastForwardClick
,
1906 ToolbarOptionsClick
,
1910 ToolbarSubsidiesClick
,
1911 ToolbarStationsClick
,
1912 ToolbarFinancesClick
,
1913 ToolbarCompaniesClick
,
1918 ToolbarIndustryClick
,
1924 ToolbarZoomOutClick
,
1925 ToolbarBuildRailClick
,
1926 ToolbarBuildRoadClick
,
1927 ToolbarBuildWaterClick
,
1928 ToolbarBuildAirClick
,
1931 ToolbarNewspaperClick
,
1936 enum MainToolbarHotkeys
{
1966 MTHK_SMALL_SCREENSHOT
,
1967 MTHK_ZOOMEDIN_SCREENSHOT
,
1968 MTHK_DEFAULTZOOM_SCREENSHOT
,
1969 MTHK_GIANT_SCREENSHOT
,
1972 MTHK_EXTRA_VIEWPORT
,
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
)
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;
2067 case MTHK_SIGN_LIST
: ShowSignList(); break;
2068 default: return ES_NOT_HANDLED
;
2073 virtual void OnPlaceObject(Point pt
, TileIndex tile
)
2075 switch (_last_started_action
) {
2076 case CBF_PLACE_SIGN
:
2077 PlaceProc_Sign(tile
);
2080 case CBF_PLACE_LANDINFO
:
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
),
2177 Hotkey((uint16
)0, "sign_list", MTHK_SIGN_LIST
),
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
++) {
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));
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
);
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
,
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
[] = {
2254 ToolbarFastForwardClick
,
2255 ToolbarOptionsClick
,
2256 ToolbarScenSaveOrLoad
,
2258 ToolbarScenDatePanel
,
2259 ToolbarScenDateBackward
,
2260 ToolbarScenDateForward
,
2261 ToolbarScenMapTownDir
,
2263 ToolbarZoomOutClick
,
2266 ToolbarScenGenIndustry
,
2267 ToolbarScenBuildRoad
,
2268 ToolbarScenBuildDocks
,
2269 ToolbarScenPlantTrees
,
2270 ToolbarScenPlaceSign
,
2285 enum MainToolbarEditorHotkeys
{
2299 MTEHK_SMALL_SCREENSHOT
,
2300 MTEHK_ZOOMEDIN_SCREENSHOT
,
2301 MTEHK_DEFAULTZOOM_SCREENSHOT
,
2302 MTEHK_GIANT_SCREENSHOT
,
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
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
);
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
);
2348 DrawString(r
.left
, r
.right
, (height
- FONT_HEIGHT_NORMAL
) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
, TC_FROMSTRING
, SA_HOR_CENTER
);
2355 virtual void UpdateWidgetSize(int widget
, Dimension
*size
, const Dimension
&padding
, Dimension
*fill
, Dimension
*resize
)
2359 size
->width
= max(GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_OPENTTD
).width
, GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
).width
) + WD_FRAMERECT_LEFT
+ WD_FRAMERECT_RIGHT
;
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
);
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
;
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
;
2419 virtual void OnPlaceObject(Point pt
, TileIndex tile
)
2421 switch (_last_started_action
) {
2422 case CBF_PLACE_SIGN
:
2423 PlaceProc_Sign(tile
);
2426 case CBF_PLACE_LANDINFO
:
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
);
2453 if (this->IsWidgetLowered(WID_TE_FAST_FORWARD
) != !!_fast_forward
) {
2454 this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD
);
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;
2476 if (!StrEmpty(str
)) {
2479 /* An empty string means revert to the default */
2480 value
= DEF_START_YEAR
;
2482 SetStartingYear(value
);
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
),
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
),
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
,
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
);
2577 new MainToolbarWindow(&_toolb_normal_desc
);