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"
58 /** Width of the toolbar, shared by statusbar. */
59 uint _toolbar_width
= 0;
61 RailType _last_built_railtype
;
62 RoadType _last_built_roadtype
;
64 static ScreenshotType _confirmed_screenshot_type
; ///< Screenshot type the current query is about to confirm.
73 /** Callback functions. */
74 enum CallBackFunction
{
81 * Drop down list entry for showing a checked/unchecked toggle item.
83 class DropDownListCheckedItem
: public DropDownListStringItem
{
88 DropDownListCheckedItem(StringID string
, int result
, bool masked
, bool checked
) : DropDownListStringItem(string
, result
, masked
), checked(checked
)
90 this->checkmark_width
= GetStringBoundingBox(STR_JUST_CHECKMARK
).width
+ 3;
93 virtual ~DropDownListCheckedItem() {}
97 return DropDownListStringItem::Width() + this->checkmark_width
;
100 void Draw(int left
, int right
, int top
, int bottom
, bool sel
, int bg_colour
) const
102 bool rtl
= _current_text_dir
== TD_RTL
;
104 DrawString(left
+ WD_FRAMERECT_LEFT
, right
- WD_FRAMERECT_RIGHT
, top
, STR_JUST_CHECKMARK
, sel
? TC_WHITE
: TC_BLACK
);
106 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
);
111 * Drop down list entry for showing a company entry, with companies 'blob'.
113 class DropDownListCompanyItem
: public DropDownListItem
{
118 DropDownListCompanyItem(int result
, bool masked
, bool greyed
) : DropDownListItem(result
, masked
), greyed(greyed
)
120 this->icon_size
= GetSpriteSize(SPR_COMPANY_ICON
);
123 virtual ~DropDownListCompanyItem() {}
125 bool Selectable() const
132 CompanyID company
= (CompanyID
)this->result
;
133 SetDParam(0, company
);
134 SetDParam(1, company
);
135 return GetStringBoundingBox(STR_COMPANY_NAME_COMPANY_NUM
).width
+ this->icon_size
.width
+ 3;
138 uint
Height(uint width
) const
140 return max(this->icon_size
.height
+ 2U, (uint
)FONT_HEIGHT_NORMAL
);
143 void Draw(int left
, int right
, int top
, int bottom
, bool sel
, int bg_colour
) const
145 CompanyID company
= (CompanyID
)this->result
;
146 bool rtl
= _current_text_dir
== TD_RTL
;
148 /* It's possible the company is deleted while the dropdown is open */
149 if (!Company::IsValidID(company
)) return;
151 int icon_offset
= (bottom
- top
- icon_size
.height
) / 2;
152 int text_offset
= (bottom
- top
- FONT_HEIGHT_NORMAL
) / 2;
154 DrawCompanyIcon(company
, rtl
? right
- this->icon_size
.width
- WD_FRAMERECT_RIGHT
: left
+ WD_FRAMERECT_LEFT
, top
+ icon_offset
);
156 SetDParam(0, company
);
157 SetDParam(1, company
);
160 col
= (sel
? TC_SILVER
: TC_GREY
) | TC_NO_SHADE
;
162 col
= sel
? TC_WHITE
: TC_BLACK
;
164 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
);
169 * Pop up a generic text only menu.
171 * @param widget Toolbar button
172 * @param list List of items
173 * @param def Default item
175 static void PopupMainToolbMenu(Window
*w
, int widget
, DropDownList
*list
, int def
)
177 ShowDropDownList(w
, list
, def
, widget
, 0, true, true);
178 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
182 * Pop up a generic text only menu.
184 * @param widget Toolbar button
185 * @param string String for the first item in the menu
186 * @param count Number of items in the menu
188 static void PopupMainToolbMenu(Window
*w
, int widget
, StringID string
, int count
)
190 DropDownList
*list
= new DropDownList();
191 for (int i
= 0; i
< count
; i
++) {
192 *list
->Append() = new DropDownListStringItem(string
+ i
, i
, false);
194 PopupMainToolbMenu(w
, widget
, list
, 0);
197 /** Enum for the Company Toolbar's network related buttons */
198 static const int CTMN_CLIENT_LIST
= -1; ///< Show the client list
199 static const int CTMN_NEW_COMPANY
= -2; ///< Create a new company
200 static const int CTMN_SPECTATE
= -3; ///< Become spectator
201 static const int CTMN_SPECTATOR
= -4; ///< Show a company window as spectator
204 * Pop up a generic company list menu.
205 * @param w The toolbar window.
206 * @param widget The button widget id.
207 * @param grey A bitbask of which items to mark as disabled.
208 * @param include_spectator If true, a spectator option is included in the list.
210 static void PopupMainCompanyToolbMenu(Window
*w
, int widget
, int grey
= 0, bool include_spectator
= false)
212 DropDownList
*list
= new DropDownList();
214 #ifdef ENABLE_NETWORK
216 if (widget
== WID_TN_COMPANIES
) {
217 /* Add the client list button for the companies menu */
218 *list
->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST
, CTMN_CLIENT_LIST
, false);
221 if (include_spectator
) {
222 if (widget
== WID_TN_COMPANIES
) {
223 if (_local_company
== COMPANY_SPECTATOR
) {
224 *list
->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY
, CTMN_NEW_COMPANY
, NetworkMaxCompaniesReached());
226 *list
->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE
, CTMN_SPECTATE
, NetworkMaxSpectatorsReached());
229 *list
->Append() = new DropDownListStringItem(STR_NETWORK_TOOLBAR_LIST_SPECTATOR
, CTMN_SPECTATOR
, false);
233 #endif /* ENABLE_NETWORK */
235 for (CompanyID c
= COMPANY_FIRST
; c
< MAX_COMPANIES
; c
++) {
236 if (!Company::IsValidID(c
)) continue;
237 *list
->Append() = new DropDownListCompanyItem(c
, false, HasBit(grey
, c
));
240 PopupMainToolbMenu(w
, widget
, list
, _local_company
== COMPANY_SPECTATOR
? CTMN_CLIENT_LIST
: (int)_local_company
);
244 static ToolbarMode _toolbar_mode
;
246 static CallBackFunction
SelectSignTool()
248 if (_cursor
.sprite
== SPR_CURSOR_SIGN
) {
252 SetPointerMode (POINTER_TILE
, WC_MAIN_TOOLBAR
, 0, SPR_CURSOR_SIGN
);
253 return CBF_PLACE_SIGN
;
257 /* --- Pausing --- */
259 static CallBackFunction
ToolbarPauseClick(Window
*w
)
261 if (_networking
&& !_network_server
) return CBF_NONE
; // only server can pause the game
263 if (DoCommandP(0, PM_PAUSED_NORMAL
, _pause_mode
== PM_UNPAUSED
, CMD_PAUSE
)) {
264 if (_settings_client
.sound
.confirm
) SndPlayFx(SND_15_BEEP
);
270 * Toggle fast forward mode.
275 static CallBackFunction
ToolbarFastForwardClick(Window
*w
)
277 _fast_forward
^= true;
278 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
283 * Game Option button menu entries.
285 enum OptionMenuEntries
{
292 OME_SHOW_STATIONNAMES
,
293 OME_SHOW_WAYPOINTNAMES
,
295 OME_SHOW_COMPETITOR_SIGNS
,
298 OME_TRANSPARENTBUILDINGS
,
299 OME_SHOW_STATIONSIGNS
,
303 * Handle click on Options button in toolbar.
305 * @param w parent window the shown Drop down list is attached to.
308 static CallBackFunction
ToolbarOptionsClick(Window
*w
)
310 DropDownList
*list
= new DropDownList();
311 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS
, OME_GAMEOPTIONS
, false);
312 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE
, OME_SETTINGS
, false);
313 /* Changes to the per-AI settings don't get send from the server to the clients. Clients get
314 * the settings once they join but never update it. As such don't show the window at all
315 * to network clients. */
316 if (!_networking
|| _network_server
) *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS
, OME_SCRIPT_SETTINGS
, false);
317 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS
, OME_NEWGRFSETTINGS
, false);
318 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS
, OME_TRANSPARENCIES
, false);
319 *list
->Append() = new DropDownListItem(-1, false);
320 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED
, OME_SHOW_TOWNNAMES
, false, HasBit(_display_opt
, DO_SHOW_TOWN_NAMES
));
321 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED
, OME_SHOW_STATIONNAMES
, false, HasBit(_display_opt
, DO_SHOW_STATION_NAMES
));
322 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED
, OME_SHOW_WAYPOINTNAMES
, false, HasBit(_display_opt
, DO_SHOW_WAYPOINT_NAMES
));
323 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED
, OME_SHOW_SIGNS
, false, HasBit(_display_opt
, DO_SHOW_SIGNS
));
324 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS
, OME_SHOW_COMPETITOR_SIGNS
, false, HasBit(_display_opt
, DO_SHOW_COMPETITOR_SIGNS
));
325 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION
, OME_FULL_ANIMATION
, false, HasBit(_display_opt
, DO_FULL_ANIMATION
));
326 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL
, OME_FULL_DETAILS
, false, HasBit(_display_opt
, DO_FULL_DETAIL
));
327 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS
, OME_TRANSPARENTBUILDINGS
, false, IsTransparencySet(TO_HOUSES
));
328 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS
, OME_SHOW_STATIONSIGNS
, false, IsTransparencySet(TO_SIGNS
));
330 ShowDropDownList(w
, list
, 0, WID_TN_SETTINGS
, 140, true, true);
331 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
336 * Handle click on one of the entries in the Options button menu.
338 * @param index Index being clicked.
341 static CallBackFunction
MenuClickSettings(int index
)
344 case OME_GAMEOPTIONS
: ShowGameOptions(); return CBF_NONE
;
345 case OME_SETTINGS
: ShowGameSettings(); return CBF_NONE
;
346 case OME_SCRIPT_SETTINGS
: ShowAIConfigWindow(); return CBF_NONE
;
347 case OME_NEWGRFSETTINGS
: ShowNewGRFSettings(!_networking
&& _settings_client
.gui
.UserIsAllowedToChangeNewGRFs(), true, true, &_grfconfig
); return CBF_NONE
;
348 case OME_TRANSPARENCIES
: ShowTransparencyToolbar(); break;
350 case OME_SHOW_TOWNNAMES
: ToggleBit(_display_opt
, DO_SHOW_TOWN_NAMES
); break;
351 case OME_SHOW_STATIONNAMES
: ToggleBit(_display_opt
, DO_SHOW_STATION_NAMES
); break;
352 case OME_SHOW_WAYPOINTNAMES
: ToggleBit(_display_opt
, DO_SHOW_WAYPOINT_NAMES
); break;
353 case OME_SHOW_SIGNS
: ToggleBit(_display_opt
, DO_SHOW_SIGNS
); break;
354 case OME_SHOW_COMPETITOR_SIGNS
:
355 ToggleBit(_display_opt
, DO_SHOW_COMPETITOR_SIGNS
);
356 InvalidateWindowClassesData(WC_SIGN_LIST
, -1);
358 case OME_FULL_ANIMATION
: ToggleBit(_display_opt
, DO_FULL_ANIMATION
); CheckBlitter(); break;
359 case OME_FULL_DETAILS
: ToggleBit(_display_opt
, DO_FULL_DETAIL
); break;
360 case OME_TRANSPARENTBUILDINGS
: ToggleTransparency(TO_HOUSES
); break;
361 case OME_SHOW_STATIONSIGNS
: ToggleTransparency(TO_SIGNS
); break;
363 MarkWholeScreenDirty();
368 * SaveLoad entries in scenario editor mode.
370 enum SaveLoadEditorMenuEntries
{
371 SLEME_SAVE_SCENARIO
= 0,
373 SLEME_SAVE_HEIGHTMAP
,
374 SLEME_LOAD_HEIGHTMAP
,
381 * SaveLoad entries in normal game mode.
383 enum SaveLoadNormalMenuEntries
{
392 * Handle click on Save button in toolbar in normal game mode.
394 * @param w parent window the shown save dialogue is attached to.
397 static CallBackFunction
ToolbarSaveClick(Window
*w
)
399 PopupMainToolbMenu(w
, WID_TN_SAVE
, STR_FILE_MENU_SAVE_GAME
, SLNME_MENUCOUNT
);
404 * Handle click on SaveLoad button in toolbar in the scenario editor.
406 * @param w parent window the shown save dialogue is attached to.
409 static CallBackFunction
ToolbarScenSaveOrLoad(Window
*w
)
411 PopupMainToolbMenu(w
, WID_TE_SAVE
, STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO
, SLEME_MENUCOUNT
);
416 * Handle click on one of the entries in the SaveLoad menu.
418 * @param index Index being clicked.
421 static CallBackFunction
MenuClickSaveLoad(int index
= 0)
423 if (_game_mode
== GM_EDITOR
) {
425 case SLEME_SAVE_SCENARIO
: ShowSaveLoadDialog(SLD_SAVE_SCENARIO
); break;
426 case SLEME_LOAD_SCENARIO
: ShowSaveLoadDialog(SLD_LOAD_SCENARIO
); break;
427 case SLEME_SAVE_HEIGHTMAP
: ShowSaveLoadDialog(SLD_SAVE_HEIGHTMAP
); break;
428 case SLEME_LOAD_HEIGHTMAP
: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP
); break;
429 case SLEME_EXIT_TOINTRO
: AskExitToGameMenu(); break;
430 case SLEME_EXIT_GAME
: HandleExitGameRequest(); break;
434 case SLNME_SAVE_GAME
: ShowSaveLoadDialog(SLD_SAVE_GAME
); break;
435 case SLNME_LOAD_GAME
: ShowSaveLoadDialog(SLD_LOAD_GAME
); break;
436 case SLNME_EXIT_TOINTRO
: AskExitToGameMenu(); break;
437 case SLNME_EXIT_GAME
: HandleExitGameRequest(); break;
443 /* --- Map button menu --- */
445 enum MapMenuEntries
{
446 MME_SHOW_SMALLMAP
= 0,
447 MME_SHOW_EXTRAVIEWPORTS
,
450 MME_SHOW_TOWNDIRECTORY
,
451 MME_SHOW_INDUSTRYDIRECTORY
,
454 static CallBackFunction
ToolbarMapClick(Window
*w
)
456 DropDownList
*list
= new DropDownList();
457 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD
, MME_SHOW_SMALLMAP
, false);
458 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT
, MME_SHOW_EXTRAVIEWPORTS
, false);
459 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_LINGRAPH_LEGEND
, MME_SHOW_LINKGRAPH
, false);
460 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST
, MME_SHOW_SIGNLISTS
, false);
461 PopupMainToolbMenu(w
, WID_TN_SMALL_MAP
, list
, 0);
465 static CallBackFunction
ToolbarScenMapTownDir(Window
*w
)
467 DropDownList
*list
= new DropDownList();
468 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD
, MME_SHOW_SMALLMAP
, false);
469 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT
, MME_SHOW_EXTRAVIEWPORTS
, false);
470 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST
, MME_SHOW_SIGNLISTS
, false);
471 *list
->Append() = new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY
, MME_SHOW_TOWNDIRECTORY
, false);
472 *list
->Append() = new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY
, MME_SHOW_INDUSTRYDIRECTORY
, false);
473 PopupMainToolbMenu(w
, WID_TE_SMALL_MAP
, list
, 0);
478 * Handle click on one of the entries in the Map menu.
480 * @param index Index being clicked.
483 static CallBackFunction
MenuClickMap(int index
)
486 case MME_SHOW_SMALLMAP
: ShowSmallMap(); break;
487 case MME_SHOW_EXTRAVIEWPORTS
: ShowExtraViewPortWindow(); break;
488 case MME_SHOW_LINKGRAPH
: ShowLinkGraphLegend(); break;
489 case MME_SHOW_SIGNLISTS
: ShowSignList(); break;
490 case MME_SHOW_TOWNDIRECTORY
: ShowTownDirectory(); break;
491 case MME_SHOW_INDUSTRYDIRECTORY
: ShowIndustryDirectory(); break;
496 /* --- Town button menu --- */
498 static CallBackFunction
ToolbarTownClick(Window
*w
)
500 PopupMainToolbMenu(w
, WID_TN_TOWNS
, STR_TOWN_MENU_TOWN_DIRECTORY
, (_settings_game
.economy
.found_town
== TF_FORBIDDEN
) ? 1 : 2);
505 * Handle click on one of the entries in the Town menu.
507 * @param index Index being clicked.
510 static CallBackFunction
MenuClickTown(int index
)
513 case 0: ShowTownDirectory(); break;
514 case 1: // setting could be changed when the dropdown was open
515 if (_settings_game
.economy
.found_town
!= TF_FORBIDDEN
) ShowFoundTownWindow();
521 /* --- Subidies button menu --- */
523 static CallBackFunction
ToolbarSubsidiesClick(Window
*w
)
525 PopupMainToolbMenu(w
, WID_TN_SUBSIDIES
, STR_SUBSIDIES_MENU_SUBSIDIES
, 1);
530 * Handle click on the entry in the Subsidies menu.
532 * @param index Unused.
535 static CallBackFunction
MenuClickSubsidies(int index
)
538 case 0: ShowSubsidiesList(); break;
543 /* --- Stations button menu --- */
545 static CallBackFunction
ToolbarStationsClick(Window
*w
)
547 PopupMainCompanyToolbMenu(w
, WID_TN_STATIONS
);
552 * Handle click on the entry in the Stations menu
554 * @param index CompanyID to show station list for
557 static CallBackFunction
MenuClickStations(int index
)
559 ShowCompanyStations((CompanyID
)index
);
563 /* --- Finances button menu --- */
565 static CallBackFunction
ToolbarFinancesClick(Window
*w
)
567 PopupMainCompanyToolbMenu(w
, WID_TN_FINANCES
);
572 * Handle click on the entry in the finances overview menu.
574 * @param index CompanyID to show finances for.
577 static CallBackFunction
MenuClickFinances(int index
)
579 ShowCompanyFinances((CompanyID
)index
);
583 /* --- Company's button menu --- */
585 static CallBackFunction
ToolbarCompaniesClick(Window
*w
)
587 PopupMainCompanyToolbMenu(w
, WID_TN_COMPANIES
, 0, true);
592 * Handle click on the entry in the Company menu.
594 * @param index Menu entry to handle.
597 static CallBackFunction
MenuClickCompany(int index
)
599 #ifdef ENABLE_NETWORK
602 case CTMN_CLIENT_LIST
:
606 case CTMN_NEW_COMPANY
:
607 if (_network_server
) {
608 DoCommandP(0, 0, _network_own_client_id
, CMD_COMPANY_CTRL
);
610 NetworkSendCommand(0, 0, 0, CMD_COMPANY_CTRL
, NULL
, _local_company
);
615 if (_network_server
) {
616 NetworkServerDoMove(CLIENT_ID_SERVER
, COMPANY_SPECTATOR
);
617 MarkWholeScreenDirty();
619 NetworkClientRequestMove(COMPANY_SPECTATOR
);
624 #endif /* ENABLE_NETWORK */
625 ShowCompany((CompanyID
)index
);
629 /* --- Story button menu --- */
631 static CallBackFunction
ToolbarStoryClick(Window
*w
)
633 PopupMainCompanyToolbMenu(w
, WID_TN_STORY
, 0, true);
638 * Handle click on the entry in the Story menu
640 * @param index CompanyID to show story book for
643 static CallBackFunction
MenuClickStory(int index
)
645 ShowStoryBook(index
== CTMN_SPECTATOR
? INVALID_COMPANY
: (CompanyID
)index
);
649 /* --- Goal button menu --- */
651 static CallBackFunction
ToolbarGoalClick(Window
*w
)
653 PopupMainCompanyToolbMenu(w
, WID_TN_GOAL
, 0, true);
658 * Handle click on the entry in the Goal menu
660 * @param index CompanyID to show story book for
663 static CallBackFunction
MenuClickGoal(int index
)
665 ShowGoalsList(index
== CTMN_SPECTATOR
? INVALID_COMPANY
: (CompanyID
)index
);
669 /* --- Graphs button menu --- */
671 static CallBackFunction
ToolbarGraphsClick(Window
*w
)
673 PopupMainToolbMenu(w
, WID_TN_GRAPHS
, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH
, (_toolbar_mode
== TB_NORMAL
) ? 6 : 8);
678 * Handle click on the entry in the Graphs menu.
680 * @param index Graph to show.
683 static CallBackFunction
MenuClickGraphs(int index
)
686 case 0: ShowOperatingProfitGraph(); break;
687 case 1: ShowIncomeGraph(); break;
688 case 2: ShowDeliveredCargoGraph(); break;
689 case 3: ShowPerformanceHistoryGraph(); break;
690 case 4: ShowCompanyValueGraph(); break;
691 case 5: ShowCargoPaymentRates(); break;
692 /* functions for combined graphs/league button */
693 case 6: ShowCompanyLeagueTable(); break;
694 case 7: ShowPerformanceRatingDetail(); break;
699 /* --- League button menu --- */
701 static CallBackFunction
ToolbarLeagueClick(Window
*w
)
703 PopupMainToolbMenu(w
, WID_TN_LEAGUE
, STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE
, _networking
? 2 : 3);
708 * Handle click on the entry in the CompanyLeague menu.
710 * @param index Menu entry number.
713 static CallBackFunction
MenuClickLeague(int index
)
716 case 0: ShowCompanyLeagueTable(); break;
717 case 1: ShowPerformanceRatingDetail(); break;
718 case 2: ShowHighscoreTable(); break;
723 /* --- Industries button menu --- */
725 static CallBackFunction
ToolbarIndustryClick(Window
*w
)
727 /* Disable build-industry menu if we are a spectator */
728 PopupMainToolbMenu(w
, WID_TN_INDUSTRIES
, STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY
, (_local_company
== COMPANY_SPECTATOR
) ? 2 : 3);
733 * Handle click on the entry in the Industry menu.
735 * @param index Menu entry number.
738 static CallBackFunction
MenuClickIndustry(int index
)
741 case 0: ShowIndustryDirectory(); break;
742 case 1: ShowIndustryCargoesWindow(); break;
743 case 2: ShowBuildIndustryWindow(); break;
748 /* --- Trains button menu + 1 helper function for all vehicles. --- */
750 static void ToolbarVehicleClick(Window
*w
, VehicleType veh
)
755 FOR_ALL_VEHICLES(v
) {
756 if (v
->type
== veh
&& v
->IsPrimaryVehicle()) ClrBit(dis
, v
->owner
);
758 PopupMainCompanyToolbMenu(w
, WID_TN_VEHICLE_START
+ veh
, dis
);
762 static CallBackFunction
ToolbarTrainClick(Window
*w
)
764 ToolbarVehicleClick(w
, VEH_TRAIN
);
769 * Handle click on the entry in the Train menu.
771 * @param index CompanyID to show train list for.
774 static CallBackFunction
MenuClickShowTrains(int index
)
776 ShowVehicleListWindow((CompanyID
)index
, VEH_TRAIN
);
780 /* --- Road vehicle button menu --- */
782 static CallBackFunction
ToolbarRoadClick(Window
*w
)
784 ToolbarVehicleClick(w
, VEH_ROAD
);
789 * Handle click on the entry in the Road Vehicles menu.
791 * @param index CompanyID to show road vehicles list for.
794 static CallBackFunction
MenuClickShowRoad(int index
)
796 ShowVehicleListWindow((CompanyID
)index
, VEH_ROAD
);
800 /* --- Ship button menu --- */
802 static CallBackFunction
ToolbarShipClick(Window
*w
)
804 ToolbarVehicleClick(w
, VEH_SHIP
);
809 * Handle click on the entry in the Ships menu.
811 * @param index CompanyID to show ship list for.
814 static CallBackFunction
MenuClickShowShips(int index
)
816 ShowVehicleListWindow((CompanyID
)index
, VEH_SHIP
);
820 /* --- Aircraft button menu --- */
822 static CallBackFunction
ToolbarAirClick(Window
*w
)
824 ToolbarVehicleClick(w
, VEH_AIRCRAFT
);
829 * Handle click on the entry in the Aircraft menu.
831 * @param index CompanyID to show aircraft list for.
834 static CallBackFunction
MenuClickShowAir(int index
)
836 ShowVehicleListWindow((CompanyID
)index
, VEH_AIRCRAFT
);
840 /* --- Zoom in button --- */
842 static CallBackFunction
ToolbarZoomInClick(Window
*w
)
844 if (DoZoomInOutWindow (true, FindWindowById(WC_MAIN_WINDOW
, 0))) {
845 w
->HandleButtonClick((_game_mode
== GM_EDITOR
) ? (byte
)WID_TE_ZOOM_IN
: (byte
)WID_TN_ZOOM_IN
);
846 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
851 /* --- Zoom out button --- */
853 static CallBackFunction
ToolbarZoomOutClick(Window
*w
)
855 if (DoZoomInOutWindow (false, FindWindowById(WC_MAIN_WINDOW
, 0))) {
856 w
->HandleButtonClick((_game_mode
== GM_EDITOR
) ? (byte
)WID_TE_ZOOM_OUT
: (byte
)WID_TN_ZOOM_OUT
);
857 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
862 /* --- Rail button menu --- */
864 static CallBackFunction
ToolbarBuildRailClick(Window
*w
)
866 ShowDropDownList(w
, GetRailTypeDropDownList(), _last_built_railtype
, WID_TN_RAILS
, 140, true, true);
867 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
872 * Handle click on the entry in the Build Rail menu.
874 * @param index RailType to show the build toolbar for.
877 static CallBackFunction
MenuClickBuildRail(int index
)
879 _last_built_railtype
= (RailType
)index
;
880 ShowBuildRailToolbar(_last_built_railtype
);
884 /* --- Road button menu --- */
886 static CallBackFunction
ToolbarBuildRoadClick(Window
*w
)
888 const Company
*c
= Company::Get(_local_company
);
889 DropDownList
*list
= new DropDownList();
891 /* Road is always visible and available. */
892 *list
->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION
, ROADTYPE_ROAD
, false);
894 /* Tram is only visible when there will be a tram, and available when that has been introduced. */
896 FOR_ALL_ENGINES_OF_TYPE(e
, VEH_ROAD
) {
897 if (!HasBit(e
->info
.climates
, _settings_game
.game_creation
.landscape
)) continue;
898 if (!HasBit(e
->info
.misc_flags
, EF_ROAD_TRAM
)) continue;
900 *list
->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION
, ROADTYPE_TRAM
, !HasBit(c
->avail_roadtypes
, ROADTYPE_TRAM
));
903 ShowDropDownList(w
, list
, _last_built_roadtype
, WID_TN_ROADS
, 140, true, true);
904 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
909 * Handle click on the entry in the Build Road menu.
911 * @param index RoadType to show the build toolbar for.
914 static CallBackFunction
MenuClickBuildRoad(int index
)
916 _last_built_roadtype
= (RoadType
)index
;
917 ShowBuildRoadToolbar(_last_built_roadtype
);
921 /* --- Water button menu --- */
923 static CallBackFunction
ToolbarBuildWaterClick(Window
*w
)
925 PopupMainToolbMenu(w
, WID_TN_WATER
, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION
, 1);
930 * Handle click on the entry in the Build Waterways menu.
932 * @param index Unused.
935 static CallBackFunction
MenuClickBuildWater(int index
)
937 ShowBuildDocksToolbar();
941 /* --- Airport button menu --- */
943 static CallBackFunction
ToolbarBuildAirClick(Window
*w
)
945 PopupMainToolbMenu(w
, WID_TN_AIR
, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION
, 1);
950 * Handle click on the entry in the Build Air menu.
952 * @param index Unused.
955 static CallBackFunction
MenuClickBuildAir(int index
)
957 ShowBuildAirToolbar();
961 /* --- Forest button menu --- */
963 static CallBackFunction
ToolbarForestClick(Window
*w
)
965 PopupMainToolbMenu(w
, WID_TN_LANDSCAPE
, STR_LANDSCAPING_MENU_LANDSCAPING
, 3);
970 * Handle click on the entry in the landscaping menu.
972 * @param index Menu entry clicked.
975 static CallBackFunction
MenuClickForest(int index
)
978 case 0: ShowTerraformToolbar(); break;
979 case 1: ShowBuildTreesToolbar(); break;
980 case 2: return SelectSignTool();
985 /* --- Music button menu --- */
987 static CallBackFunction
ToolbarMusicClick(Window
*w
)
989 PopupMainToolbMenu(w
, WID_TN_MUSIC_SOUND
, STR_TOOLBAR_SOUND_MUSIC
, 1);
994 * Handle click on the entry in the Music menu.
996 * @param index Unused.
999 static CallBackFunction
MenuClickMusicWindow(int index
)
1005 /* --- Newspaper button menu --- */
1007 static CallBackFunction
ToolbarNewspaperClick(Window
*w
)
1009 PopupMainToolbMenu(w
, WID_TN_MESSAGES
, STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT
, 2);
1014 * Handle click on the entry in the Newspaper menu.
1016 * @param index Menu entry clicked.
1019 static CallBackFunction
MenuClickNewspaper(int index
)
1022 case 0: ShowLastNewsMessage(); break;
1023 case 1: ShowMessageHistory(); break;
1028 /* --- Help button menu --- */
1030 static CallBackFunction
PlaceLandBlockInfo()
1032 if (_cursor
.sprite
== SPR_CURSOR_QUERY
) {
1036 SetPointerMode (POINTER_TILE
, WC_MAIN_TOOLBAR
, 0, SPR_CURSOR_QUERY
);
1037 return CBF_PLACE_LANDINFO
;
1041 static CallBackFunction
ToolbarHelpClick(Window
*w
)
1043 PopupMainToolbMenu(w
, WID_TN_HELP
, STR_ABOUT_MENU_LAND_BLOCK_INFO
, _settings_client
.gui
.newgrf_developer_tools
? 12 : 9);
1047 static void MenuClickSmallScreenshot()
1049 MakeScreenshot(SC_VIEWPORT
, NULL
);
1053 * Callback on the confirmation window for huge screenshots.
1054 * @param w Window with viewport
1055 * @param confirmed true on confirmation
1057 static void ScreenshotConfirmCallback(Window
*w
, bool confirmed
)
1059 if (confirmed
) MakeScreenshot(_confirmed_screenshot_type
, NULL
);
1063 * Make a screenshot of the world.
1064 * Ask for confirmation if the screenshot will be huge.
1065 * @param t Screenshot type: World or viewport screenshot
1067 static void MenuClickLargeWorldScreenshot(ScreenshotType t
)
1070 SetupScreenshotViewport(t
, &vp
);
1071 if ((uint64
)vp
.width
* (uint64
)vp
.height
> 8192 * 8192) {
1072 /* Ask for confirmation */
1073 SetDParam(0, vp
.width
);
1074 SetDParam(1, vp
.height
);
1075 _confirmed_screenshot_type
= t
;
1076 ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION
, STR_WARNING_SCREENSHOT_SIZE_MESSAGE
, NULL
, ScreenshotConfirmCallback
);
1078 /* Less than 64M pixels, just do it */
1079 MakeScreenshot(t
, NULL
);
1084 * Toggle drawing of sprites' bounding boxes.
1085 * @note has only an effect when newgrf_developer_tools are active.
1087 * Function is found here and not in viewport.cpp in order to avoid
1088 * importing the settings structs to there.
1090 void ToggleBoundingBoxes()
1092 extern bool _draw_bounding_boxes
;
1093 /* Always allow to toggle them off */
1094 if (_settings_client
.gui
.newgrf_developer_tools
|| _draw_bounding_boxes
) {
1095 _draw_bounding_boxes
= !_draw_bounding_boxes
;
1096 MarkWholeScreenDirty();
1101 * Toggle drawing of the dirty blocks.
1102 * @note has only an effect when newgrf_developer_tools are active.
1104 * Function is found here and not in viewport.cpp in order to avoid
1105 * importing the settings structs to there.
1107 void ToggleDirtyBlocks()
1109 extern bool _draw_dirty_blocks
;
1110 /* Always allow to toggle them off */
1111 if (_settings_client
.gui
.newgrf_developer_tools
|| _draw_dirty_blocks
) {
1112 _draw_dirty_blocks
= !_draw_dirty_blocks
;
1113 MarkWholeScreenDirty();
1118 * Set the starting year for a scenario.
1119 * @param year New starting year.
1121 void SetStartingYear(Year year
)
1123 _settings_game
.game_creation
.starting_year
= Clamp(year
, MIN_YEAR
, MAX_YEAR
);
1124 Date new_date
= ConvertYMDToDate(_settings_game
.game_creation
.starting_year
, 0, 1);
1125 /* If you open a savegame as scenario there may already be link graphs.*/
1126 LinkGraphSchedule::instance
.ShiftDates(new_date
- _date
);
1127 SetDate(new_date
, 0);
1131 * Choose the proper callback function for the main toolbar's help menu.
1132 * @param index The menu index which was selected.
1135 static CallBackFunction
MenuClickHelp(int index
)
1138 case 0: return PlaceLandBlockInfo();
1139 case 2: IConsoleSwitch(); break;
1140 case 3: ShowAIDebugWindow(); break;
1141 case 4: MenuClickSmallScreenshot(); break;
1142 case 5: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN
); break;
1143 case 6: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM
); break;
1144 case 7: MenuClickLargeWorldScreenshot(SC_WORLD
); break;
1145 case 8: ShowAboutWindow(); break;
1146 case 9: ShowSpriteAlignerWindow(); break;
1147 case 10: ToggleBoundingBoxes(); break;
1148 case 11: ToggleDirtyBlocks(); break;
1153 /* --- Switch toolbar button --- */
1155 static CallBackFunction
ToolbarSwitchClick(Window
*w
)
1157 if (_toolbar_mode
!= TB_LOWER
) {
1158 _toolbar_mode
= TB_LOWER
;
1160 _toolbar_mode
= TB_UPPER
;
1164 w
->SetWidgetLoweredState(WID_TN_SWITCH_BAR
, _toolbar_mode
== TB_LOWER
);
1165 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1169 /* --- Scenario editor specific handlers. */
1172 * Called when clicking at the date panel of the scenario editor toolbar.
1174 static CallBackFunction
ToolbarScenDatePanel(Window
*w
)
1176 SetDParam(0, _settings_game
.game_creation
.starting_year
);
1177 ShowQueryString(STR_JUST_INT
, STR_MAPGEN_START_DATE_QUERY_CAPT
, 8, w
, CS_NUMERAL
, QSF_ENABLE_DEFAULT
);
1178 _left_button_clicked
= false;
1182 static CallBackFunction
ToolbarScenDateBackward(Window
*w
)
1184 /* don't allow too fast scrolling */
1185 if (!(w
->flags
& WF_TIMEOUT
) || w
->timeout_timer
<= 1) {
1186 w
->HandleButtonClick(WID_TE_DATE_BACKWARD
);
1189 SetStartingYear(_settings_game
.game_creation
.starting_year
- 1);
1191 _left_button_clicked
= false;
1195 static CallBackFunction
ToolbarScenDateForward(Window
*w
)
1197 /* don't allow too fast scrolling */
1198 if (!(w
->flags
& WF_TIMEOUT
) || w
->timeout_timer
<= 1) {
1199 w
->HandleButtonClick(WID_TE_DATE_FORWARD
);
1202 SetStartingYear(_settings_game
.game_creation
.starting_year
+ 1);
1204 _left_button_clicked
= false;
1208 static CallBackFunction
ToolbarScenGenLand(Window
*w
)
1210 w
->HandleButtonClick(WID_TE_LAND_GENERATE
);
1211 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1213 ShowEditorTerraformToolbar();
1218 static CallBackFunction
ToolbarScenGenTown(Window
*w
)
1220 w
->HandleButtonClick(WID_TE_TOWN_GENERATE
);
1221 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1222 ShowFoundTownWindow();
1226 static CallBackFunction
ToolbarScenGenIndustry(Window
*w
)
1228 w
->HandleButtonClick(WID_TE_INDUSTRY
);
1229 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1230 ShowBuildIndustryWindow();
1234 static CallBackFunction
ToolbarScenBuildRoad(Window
*w
)
1236 w
->HandleButtonClick(WID_TE_ROADS
);
1237 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1238 ShowBuildRoadScenToolbar();
1242 static CallBackFunction
ToolbarScenBuildDocks(Window
*w
)
1244 w
->HandleButtonClick(WID_TE_WATER
);
1245 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1246 ShowBuildDocksScenToolbar();
1250 static CallBackFunction
ToolbarScenPlantTrees(Window
*w
)
1252 w
->HandleButtonClick(WID_TE_TREES
);
1253 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1254 ShowBuildTreesToolbar();
1258 static CallBackFunction
ToolbarScenPlaceSign(Window
*w
)
1260 w
->HandleButtonClick(WID_TE_SIGNS
);
1261 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1262 return SelectSignTool();
1265 static CallBackFunction
ToolbarBtn_NULL(Window
*w
)
1270 typedef CallBackFunction
MenuClickedProc(int index
);
1272 static MenuClickedProc
* const _menu_clicked_procs
[] = {
1275 MenuClickSettings
, // 2
1276 MenuClickSaveLoad
, // 3
1279 MenuClickSubsidies
, // 6
1280 MenuClickStations
, // 7
1281 MenuClickFinances
, // 8
1282 MenuClickCompany
, // 9
1283 MenuClickStory
, // 10
1284 MenuClickGoal
, // 11
1285 MenuClickGraphs
, // 12
1286 MenuClickLeague
, // 13
1287 MenuClickIndustry
, // 14
1288 MenuClickShowTrains
, // 15
1289 MenuClickShowRoad
, // 16
1290 MenuClickShowShips
, // 17
1291 MenuClickShowAir
, // 18
1294 MenuClickBuildRail
, // 21
1295 MenuClickBuildRoad
, // 22
1296 MenuClickBuildWater
, // 23
1297 MenuClickBuildAir
, // 24
1298 MenuClickForest
, // 25
1299 MenuClickMusicWindow
, // 26
1300 MenuClickNewspaper
, // 27
1301 MenuClickHelp
, // 28
1304 /** Full blown container to make it behave exactly as we want :) */
1305 class NWidgetToolbarContainer
: public NWidgetContainer
{
1306 bool visible
[WID_TN_END
]; ///< The visible headers
1308 uint spacers
; ///< Number of spacer widgets in this toolbar
1311 NWidgetToolbarContainer() : NWidgetContainer(NWID_HORIZONTAL
)
1316 * Check whether the given widget type is a button for us.
1317 * @param type the widget type to check.
1318 * @return true if it is a button for us.
1320 bool IsButton(WidgetType type
) const
1322 return type
== WWT_IMGBTN
|| type
== WWT_IMGBTN_2
|| type
== WWT_PUSHIMGBTN
;
1325 void SetupSmallestSize(Window
*w
, bool init_array
)
1327 this->smallest_x
= 0; // Biggest child
1328 this->smallest_y
= 0; // Biggest child
1331 this->resize_x
= 1; // We only resize in this direction
1332 this->resize_y
= 0; // We never resize in this direction
1336 /* First initialise some variables... */
1337 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= NULL
; child_wid
= child_wid
->next
) {
1338 child_wid
->SetupSmallestSize(w
, init_array
);
1339 this->smallest_y
= max(this->smallest_y
, child_wid
->smallest_y
+ child_wid
->padding_top
+ child_wid
->padding_bottom
);
1340 if (this->IsButton(child_wid
->type
)) {
1342 this->smallest_x
= max(this->smallest_x
, child_wid
->smallest_x
+ child_wid
->padding_left
+ child_wid
->padding_right
);
1343 } else if (child_wid
->type
== NWID_SPACER
) {
1348 /* ... then in a second pass make sure the 'current' heights are set. Won't change ever. */
1349 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= NULL
; child_wid
= child_wid
->next
) {
1350 child_wid
->current_y
= this->smallest_y
;
1351 if (!this->IsButton(child_wid
->type
)) {
1352 child_wid
->current_x
= child_wid
->smallest_x
;
1355 _toolbar_width
= nbuttons
* this->smallest_x
;
1358 void AssignSizePosition(SizingType sizing
, uint x
, uint y
, uint given_width
, uint given_height
, bool rtl
)
1360 assert(given_width
>= this->smallest_x
&& given_height
>= this->smallest_y
);
1364 this->current_x
= given_width
;
1365 this->current_y
= given_height
;
1367 /* Figure out what are the visible buttons */
1368 memset(this->visible
, 0, sizeof(this->visible
));
1369 uint arrangable_count
, button_count
, spacer_count
;
1370 const byte
*arrangement
= GetButtonArrangement(given_width
, arrangable_count
, button_count
, spacer_count
);
1371 for (uint i
= 0; i
< arrangable_count
; i
++) {
1372 this->visible
[arrangement
[i
]] = true;
1375 /* Create us ourselves a quick lookup table */
1376 NWidgetBase
*widgets
[WID_TN_END
];
1377 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= NULL
; child_wid
= child_wid
->next
) {
1378 if (child_wid
->type
== NWID_SPACER
) continue;
1379 widgets
[((NWidgetCore
*)child_wid
)->index
] = child_wid
;
1382 /* Now assign the widgets to their rightful place */
1383 uint position
= 0; // Place to put next child relative to origin of the container.
1384 uint spacer_space
= max(0, (int)given_width
- (int)(button_count
* this->smallest_x
)); // Remaining spacing for 'spacer' widgets
1385 uint button_space
= given_width
- spacer_space
; // Remaining spacing for the buttons
1389 /* Index into the arrangement indices. The macro lastof cannot be used here! */
1390 const byte
*cur_wid
= rtl
? &arrangement
[arrangable_count
- 1] : arrangement
;
1391 for (uint i
= 0; i
< arrangable_count
; i
++) {
1392 NWidgetBase
*child_wid
= widgets
[*cur_wid
];
1393 /* If we have to give space to the spacers, do that */
1394 if (spacer_space
!= 0) {
1395 NWidgetBase
*possible_spacer
= rtl
? child_wid
->next
: child_wid
->prev
;
1396 if (possible_spacer
!= NULL
&& possible_spacer
->type
== NWID_SPACER
) {
1397 uint add
= spacer_space
/ (spacer_count
- spacer_i
);
1399 spacer_space
-= add
;
1404 /* Buttons can be scaled, the others not. */
1405 if (this->IsButton(child_wid
->type
)) {
1406 child_wid
->current_x
= button_space
/ (button_count
- button_i
);
1407 button_space
-= child_wid
->current_x
;
1410 child_wid
->AssignSizePosition(sizing
, x
+ position
, y
, child_wid
->current_x
, this->current_y
, rtl
);
1411 position
+= child_wid
->current_x
;
1421 /* virtual */ void Draw(const Window
*w
)
1423 /* Draw brown-red toolbar bg. */
1424 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
);
1425 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
);
1427 bool rtl
= _current_text_dir
== TD_RTL
;
1428 for (NWidgetBase
*child_wid
= rtl
? this->tail
: this->head
; child_wid
!= NULL
; child_wid
= rtl
? child_wid
->prev
: child_wid
->next
) {
1429 if (child_wid
->type
== NWID_SPACER
) continue;
1430 if (!this->visible
[((NWidgetCore
*)child_wid
)->index
]) continue;
1436 /* virtual */ NWidgetCore
*GetWidgetFromPos(int x
, int y
)
1438 if (!IsInsideBS(x
, this->pos_x
, this->current_x
) || !IsInsideBS(y
, this->pos_y
, this->current_y
)) return NULL
;
1440 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= NULL
; child_wid
= child_wid
->next
) {
1441 if (child_wid
->type
== NWID_SPACER
) continue;
1442 if (!this->visible
[((NWidgetCore
*)child_wid
)->index
]) continue;
1444 NWidgetCore
*nwid
= child_wid
->GetWidgetFromPos(x
, y
);
1445 if (nwid
!= NULL
) return nwid
;
1451 * Get the arrangement of the buttons for the toolbar.
1452 * @param width the new width of the toolbar.
1453 * @param arrangable_count output of the number of visible items.
1454 * @param button_count output of the number of visible buttons.
1455 * @param spacer_count output of the number of spacers.
1456 * @return the button configuration.
1458 virtual const byte
*GetButtonArrangement(uint
&width
, uint
&arrangable_count
, uint
&button_count
, uint
&spacer_count
) const = 0;
1461 /** Container for the 'normal' main toolbar */
1462 class NWidgetMainToolbarContainer
: public NWidgetToolbarContainer
{
1463 /* virtual */ const byte
*GetButtonArrangement(uint
&width
, uint
&arrangable_count
, uint
&button_count
, uint
&spacer_count
) const
1465 static const uint SMALLEST_ARRANGEMENT
= 14;
1466 static const uint BIGGEST_ARRANGEMENT
= 20;
1467 static const byte arrange14
[] = {
1468 0, 1, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 29,
1469 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 29,
1471 static const byte arrange15
[] = {
1472 0, 1, 4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
1473 0, 2, 4, 3, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 29,
1475 static const byte arrange16
[] = {
1476 0, 1, 2, 4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
1477 0, 1, 3, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 19, 20, 29,
1479 static const byte arrange17
[] = {
1480 0, 1, 2, 4, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
1481 0, 1, 3, 4, 6, 5, 7, 8, 9, 12, 14, 26, 27, 28, 19, 20, 29,
1483 static const byte arrange18
[] = {
1484 0, 1, 2, 4, 5, 6, 7, 8, 9, 14, 21, 22, 23, 24, 25, 19, 20, 29,
1485 0, 1, 3, 4, 5, 6, 7, 12, 15, 16, 17, 18, 26, 27, 28, 19, 20, 29,
1487 static const byte arrange19
[] = {
1488 0, 1, 2, 4, 5, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 19, 20, 29,
1489 0, 1, 3, 4, 7, 8, 9, 12, 14, 27, 21, 22, 23, 24, 25, 28, 19, 20, 29,
1491 static const byte arrange20
[] = {
1492 0, 1, 2, 4, 5, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 11, 19, 20, 29,
1493 0, 1, 3, 4, 7, 8, 9, 12, 14, 27, 21, 22, 23, 24, 25, 10, 28, 19, 20, 29,
1495 static const byte arrange_all
[] = {
1496 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28
1499 /* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
1500 uint full_buttons
= max(CeilDiv(width
, this->smallest_x
), SMALLEST_ARRANGEMENT
);
1501 if (full_buttons
> BIGGEST_ARRANGEMENT
) {
1502 button_count
= arrangable_count
= lengthof(arrange_all
);
1503 spacer_count
= this->spacers
;
1507 /* Introduce the split toolbar */
1508 static const byte
* const arrangements
[] = { arrange14
, arrange15
, arrange16
, arrange17
, arrange18
, arrange19
, arrange20
};
1510 button_count
= arrangable_count
= full_buttons
;
1511 spacer_count
= this->spacers
;
1512 return arrangements
[full_buttons
- SMALLEST_ARRANGEMENT
] + ((_toolbar_mode
== TB_LOWER
) ? full_buttons
: 0);
1516 /** Container for the scenario editor's toolbar */
1517 class NWidgetScenarioToolbarContainer
: public NWidgetToolbarContainer
{
1518 uint panel_widths
[2]; ///< The width of the two panels (the text panel and date panel)
1520 void SetupSmallestSize(Window
*w
, bool init_array
)
1522 this->NWidgetToolbarContainer::SetupSmallestSize(w
, init_array
);
1524 /* Find the size of panel_widths */
1526 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= NULL
; child_wid
= child_wid
->next
) {
1527 if (child_wid
->type
== NWID_SPACER
|| this->IsButton(child_wid
->type
)) continue;
1529 assert(i
< lengthof(this->panel_widths
));
1530 this->panel_widths
[i
++] = child_wid
->current_x
;
1531 _toolbar_width
+= child_wid
->current_x
;
1535 /* virtual */ const byte
*GetButtonArrangement(uint
&width
, uint
&arrangable_count
, uint
&button_count
, uint
&spacer_count
) const
1537 static const byte arrange_all
[] = {
1538 0, 1, 2, 3, 4, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 26, 28,
1540 static const byte arrange_nopanel
[] = {
1541 0, 1, 2, 3, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 26, 28,
1543 static const byte arrange_switch
[] = {
1544 18, 8, 11, 12, 13, 14, 15, 16, 17, 29,
1545 0, 1, 2, 3, 18, 9, 10, 26, 28, 29,
1548 /* If we can place all buttons *and* the panels, show them. */
1549 uint min_full_width
= (lengthof(arrange_all
) - lengthof(this->panel_widths
)) * this->smallest_x
+ this->panel_widths
[0] + this->panel_widths
[1];
1550 if (width
>= min_full_width
) {
1551 width
-= this->panel_widths
[0] + this->panel_widths
[1];
1552 arrangable_count
= lengthof(arrange_all
);
1553 button_count
= arrangable_count
- 2;
1554 spacer_count
= this->spacers
;
1558 /* 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 */
1559 uint min_small_width
= (lengthof(arrange_switch
) - lengthof(this->panel_widths
)) * this->smallest_x
/ 2 + this->panel_widths
[1];
1560 if (width
> min_small_width
) {
1561 width
-= this->panel_widths
[1];
1562 arrangable_count
= lengthof(arrange_nopanel
);
1563 button_count
= arrangable_count
- 1;
1564 spacer_count
= this->spacers
- 1;
1565 return arrange_nopanel
;
1569 width
-= this->panel_widths
[1];
1570 arrangable_count
= lengthof(arrange_switch
) / 2;
1571 button_count
= arrangable_count
- 1;
1573 return arrange_switch
+ ((_toolbar_mode
== TB_LOWER
) ? arrangable_count
: 0);
1577 /* --- Toolbar handling for the 'normal' case */
1579 typedef CallBackFunction
ToolbarButtonProc(Window
*w
);
1581 static ToolbarButtonProc
* const _toolbar_button_procs
[] = {
1583 ToolbarFastForwardClick
,
1584 ToolbarOptionsClick
,
1588 ToolbarSubsidiesClick
,
1589 ToolbarStationsClick
,
1590 ToolbarFinancesClick
,
1591 ToolbarCompaniesClick
,
1596 ToolbarIndustryClick
,
1602 ToolbarZoomOutClick
,
1603 ToolbarBuildRailClick
,
1604 ToolbarBuildRoadClick
,
1605 ToolbarBuildWaterClick
,
1606 ToolbarBuildAirClick
,
1609 ToolbarNewspaperClick
,
1614 enum MainToolbarHotkeys
{
1644 MTHK_SMALL_SCREENSHOT
,
1645 MTHK_ZOOMEDIN_SCREENSHOT
,
1646 MTHK_DEFAULTZOOM_SCREENSHOT
,
1647 MTHK_GIANT_SCREENSHOT
,
1650 MTHK_EXTRA_VIEWPORT
,
1655 /** Main toolbar. */
1656 struct MainToolbarWindow
: Window
{
1657 CallBackFunction last_started_action
; ///< Last started user action.
1659 MainToolbarWindow (const WindowDesc
*desc
) :
1660 Window (desc
), last_started_action (CBF_NONE
)
1662 this->InitNested(0);
1664 this->last_started_action
= CBF_NONE
;
1665 CLRBITS(this->flags
, WF_WHITE_BORDER
);
1666 this->SetWidgetDisabledState(WID_TN_PAUSE
, _networking
&& !_network_server
); // if not server, disable pause button
1667 this->SetWidgetDisabledState(WID_TN_FAST_FORWARD
, _networking
); // if networking, disable fast-forward button
1668 PositionMainToolbar(this);
1669 this->InvalidateData();
1672 virtual void FindWindowPlacementAndResize(int def_width
, int def_height
)
1674 Window::FindWindowPlacementAndResize(_toolbar_width
, def_height
);
1677 virtual void OnPaint()
1679 /* If spectator, disable all construction buttons
1680 * ie : Build road, rail, ships, airports and landscaping
1681 * Since enabled state is the default, just disable when needed */
1682 this->SetWidgetsDisabledState(_local_company
== COMPANY_SPECTATOR
, WID_TN_RAILS
, WID_TN_ROADS
, WID_TN_WATER
, WID_TN_AIR
, WID_TN_LANDSCAPE
, WIDGET_LIST_END
);
1683 /* disable company list drop downs, if there are no companies */
1684 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
);
1686 this->SetWidgetDisabledState(WID_TN_GOAL
, Goal::GetNumItems() == 0);
1687 this->SetWidgetDisabledState(WID_TN_STORY
, StoryPage::GetNumItems() == 0);
1689 this->SetWidgetDisabledState(WID_TN_RAILS
, !CanBuildVehicleInfrastructure(VEH_TRAIN
));
1690 this->SetWidgetDisabledState(WID_TN_AIR
, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT
));
1692 this->DrawWidgets();
1695 virtual void OnClick(Point pt
, int widget
, int click_count
)
1697 if (_game_mode
!= GM_MENU
&& !this->IsWidgetDisabled(widget
)) _toolbar_button_procs
[widget
](this);
1700 virtual void OnDropdownSelect(int widget
, int index
)
1702 CallBackFunction cbf
= _menu_clicked_procs
[widget
](index
);
1703 if (cbf
!= CBF_NONE
) this->last_started_action
= cbf
;
1706 virtual EventState
OnHotkey(int hotkey
)
1709 case MTHK_PAUSE
: ToolbarPauseClick(this); break;
1710 case MTHK_FASTFORWARD
: ToolbarFastForwardClick(this); break;
1711 case MTHK_SETTINGS
: ShowGameOptions(); break;
1712 case MTHK_SAVEGAME
: MenuClickSaveLoad(); break;
1713 case MTHK_LOADGAME
: ShowSaveLoadDialog(SLD_LOAD_GAME
); break;
1714 case MTHK_SMALLMAP
: ShowSmallMap(); break;
1715 case MTHK_TOWNDIRECTORY
: ShowTownDirectory(); break;
1716 case MTHK_SUBSIDIES
: ShowSubsidiesList(); break;
1717 case MTHK_STATIONS
: ShowCompanyStations(_local_company
); break;
1718 case MTHK_FINANCES
: ShowCompanyFinances(_local_company
); break;
1719 case MTHK_COMPANIES
: ShowCompany(_local_company
); break;
1720 case MTHK_STORY
: ShowStoryBook(_local_company
); break;
1721 case MTHK_GOAL
: ShowGoalsList(_local_company
); break;
1722 case MTHK_GRAPHS
: ShowOperatingProfitGraph(); break;
1723 case MTHK_LEAGUE
: ShowCompanyLeagueTable(); break;
1724 case MTHK_INDUSTRIES
: ShowBuildIndustryWindow(); break;
1725 case MTHK_TRAIN_LIST
: ShowVehicleListWindow(_local_company
, VEH_TRAIN
); break;
1726 case MTHK_ROADVEH_LIST
: ShowVehicleListWindow(_local_company
, VEH_ROAD
); break;
1727 case MTHK_SHIP_LIST
: ShowVehicleListWindow(_local_company
, VEH_SHIP
); break;
1728 case MTHK_AIRCRAFT_LIST
: ShowVehicleListWindow(_local_company
, VEH_AIRCRAFT
); break;
1729 case MTHK_ZOOM_IN
: ToolbarZoomInClick(this); break;
1730 case MTHK_ZOOM_OUT
: ToolbarZoomOutClick(this); break;
1731 case MTHK_BUILD_RAIL
: if (CanBuildVehicleInfrastructure(VEH_TRAIN
)) ShowBuildRailToolbar(_last_built_railtype
); break;
1732 case MTHK_BUILD_ROAD
: ShowBuildRoadToolbar(_last_built_roadtype
); break;
1733 case MTHK_BUILD_DOCKS
: ShowBuildDocksToolbar(); break;
1734 case MTHK_BUILD_AIRPORT
: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT
)) ShowBuildAirToolbar(); break;
1735 case MTHK_BUILD_TREES
: ShowBuildTreesToolbar(); break;
1736 case MTHK_MUSIC
: ShowMusicWindow(); break;
1737 case MTHK_AI_DEBUG
: ShowAIDebugWindow(); break;
1738 case MTHK_SMALL_SCREENSHOT
: MenuClickSmallScreenshot(); break;
1739 case MTHK_ZOOMEDIN_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN
); break;
1740 case MTHK_DEFAULTZOOM_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM
); break;
1741 case MTHK_GIANT_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_WORLD
); break;
1742 case MTHK_CHEATS
: if (!_networking
) ShowCheatWindow(); break;
1743 case MTHK_TERRAFORM
: ShowTerraformToolbar(); break;
1744 case MTHK_EXTRA_VIEWPORT
: ShowExtraViewPortWindowForTileUnderCursor(); break;
1745 #ifdef ENABLE_NETWORK
1746 case MTHK_CLIENT_LIST
: if (_networking
) ShowClientList(); break;
1748 case MTHK_SIGN_LIST
: ShowSignList(); break;
1749 default: return ES_NOT_HANDLED
;
1754 virtual void OnPlaceObject(Point pt
, TileIndex tile
)
1756 switch (this->last_started_action
) {
1757 case CBF_PLACE_SIGN
:
1758 PlaceProc_Sign(tile
);
1761 case CBF_PLACE_LANDINFO
:
1765 default: NOT_REACHED();
1769 virtual void OnTick()
1771 if (this->IsWidgetLowered(WID_TN_PAUSE
) != !!_pause_mode
) {
1772 this->ToggleWidgetLoweredState(WID_TN_PAUSE
);
1773 this->SetWidgetDirty(WID_TN_PAUSE
);
1776 if (this->IsWidgetLowered(WID_TN_FAST_FORWARD
) != !!_fast_forward
) {
1777 this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD
);
1778 this->SetWidgetDirty(WID_TN_FAST_FORWARD
);
1782 virtual void OnTimeout()
1784 /* We do not want to automatically raise the pause, fast forward and
1785 * switchbar buttons; they have to stay down when pressed etc. */
1786 for (uint i
= WID_TN_SETTINGS
; i
< WID_TN_SWITCH_BAR
; i
++) {
1787 if (this->IsWidgetLowered(i
)) {
1788 this->RaiseWidget(i
);
1789 this->SetWidgetDirty(i
);
1795 * Some data on this window has become invalid.
1796 * @param data Information about the changed data.
1797 * @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.
1799 virtual void OnInvalidateData(int data
= 0, bool gui_scope
= true)
1801 if (!gui_scope
) return;
1802 if (FindWindowById(WC_MAIN_WINDOW
, 0) != NULL
) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW
, 0)->viewport
, WID_TN_ZOOM_IN
, WID_TN_ZOOM_OUT
);
1805 static HotkeyList hotkeys
;
1808 static const Hotkey maintoolbar_hotkeys
[] = {
1809 Hotkey ("pause", MTHK_PAUSE
, WKC_F1
, WKC_PAUSE
),
1810 Hotkey ("fastforward", MTHK_FASTFORWARD
),
1811 Hotkey ("settings", MTHK_SETTINGS
, WKC_F2
),
1812 Hotkey ("saveload", MTHK_SAVEGAME
, WKC_F3
),
1813 Hotkey ("load_game", MTHK_LOADGAME
),
1814 Hotkey ("smallmap", MTHK_SMALLMAP
, WKC_F4
, 'M'),
1815 Hotkey ("town_list", MTHK_TOWNDIRECTORY
, WKC_F5
),
1816 Hotkey ("subsidies", MTHK_SUBSIDIES
, WKC_F6
),
1817 Hotkey ("station_list", MTHK_STATIONS
, WKC_F7
),
1818 Hotkey ("finances", MTHK_FINANCES
, WKC_F8
),
1819 Hotkey ("companies", MTHK_COMPANIES
, WKC_F9
),
1820 Hotkey ("story_book", MTHK_STORY
),
1821 Hotkey ("goal_list", MTHK_GOAL
),
1822 Hotkey ("graphs", MTHK_GRAPHS
, WKC_F10
),
1823 Hotkey ("league", MTHK_LEAGUE
, WKC_F11
),
1824 Hotkey ("industry_list", MTHK_INDUSTRIES
, WKC_F12
),
1825 Hotkey ("train_list", MTHK_TRAIN_LIST
, WKC_SHIFT
| WKC_F1
),
1826 Hotkey ("roadveh_list", MTHK_ROADVEH_LIST
, WKC_SHIFT
| WKC_F2
),
1827 Hotkey ("ship_list", MTHK_SHIP_LIST
, WKC_SHIFT
| WKC_F3
),
1828 Hotkey ("aircraft_list", MTHK_AIRCRAFT_LIST
, WKC_SHIFT
| WKC_F4
),
1829 Hotkey ("zoomin", MTHK_ZOOM_IN
, WKC_SHIFT
| WKC_F5
, WKC_NUM_PLUS
, WKC_EQUALS
, WKC_SHIFT
| WKC_EQUALS
),
1830 Hotkey ("zoomout", MTHK_ZOOM_OUT
, WKC_SHIFT
| WKC_F6
, WKC_NUM_MINUS
, WKC_MINUS
, WKC_SHIFT
| WKC_MINUS
),
1831 Hotkey ("build_rail", MTHK_BUILD_RAIL
, WKC_SHIFT
| WKC_F7
),
1832 Hotkey ("build_road", MTHK_BUILD_ROAD
, WKC_SHIFT
| WKC_F8
),
1833 Hotkey ("build_docks", MTHK_BUILD_DOCKS
, WKC_SHIFT
| WKC_F9
),
1834 Hotkey ("build_airport", MTHK_BUILD_AIRPORT
, WKC_SHIFT
| WKC_F10
),
1835 Hotkey ("build_trees", MTHK_BUILD_TREES
, WKC_SHIFT
| WKC_F11
),
1836 Hotkey ("music", MTHK_MUSIC
, WKC_SHIFT
| WKC_F12
),
1837 Hotkey ("ai_debug", MTHK_AI_DEBUG
),
1838 Hotkey ("small_screenshot", MTHK_SMALL_SCREENSHOT
, WKC_CTRL
| 'S'),
1839 Hotkey ("zoomedin_screenshot", MTHK_ZOOMEDIN_SCREENSHOT
, WKC_CTRL
| 'P'),
1840 Hotkey ("defaultzoom_screenshot", MTHK_DEFAULTZOOM_SCREENSHOT
, WKC_CTRL
| 'D'),
1841 Hotkey ("giant_screenshot", MTHK_GIANT_SCREENSHOT
),
1842 Hotkey ("cheats", MTHK_CHEATS
, WKC_CTRL
| WKC_ALT
| 'C'),
1843 Hotkey ("terraform", MTHK_TERRAFORM
, 'L'),
1844 Hotkey ("extra_viewport", MTHK_EXTRA_VIEWPORT
, 'V'),
1845 #ifdef ENABLE_NETWORK
1846 Hotkey ("client_list", MTHK_CLIENT_LIST
),
1848 Hotkey ("sign_list", MTHK_SIGN_LIST
),
1850 HotkeyList
MainToolbarWindow::hotkeys("maintoolbar", maintoolbar_hotkeys
);
1852 static NWidgetBase
*MakeMainToolbar(int *biggest_index
)
1854 /** Sprites to use for the different toolbar buttons */
1855 static const SpriteID toolbar_button_sprites
[] = {
1856 SPR_IMG_PAUSE
, // WID_TN_PAUSE
1857 SPR_IMG_FASTFORWARD
, // WID_TN_FAST_FORWARD
1858 SPR_IMG_SETTINGS
, // WID_TN_SETTINGS
1859 SPR_IMG_SAVE
, // WID_TN_SAVE
1860 SPR_IMG_SMALLMAP
, // WID_TN_SMALL_MAP
1861 SPR_IMG_TOWN
, // WID_TN_TOWNS
1862 SPR_IMG_SUBSIDIES
, // WID_TN_SUBSIDIES
1863 SPR_IMG_COMPANY_LIST
, // WID_TN_STATIONS
1864 SPR_IMG_COMPANY_FINANCE
, // WID_TN_FINANCES
1865 SPR_IMG_COMPANY_GENERAL
, // WID_TN_COMPANIES
1866 SPR_IMG_STORY_BOOK
, // WID_TN_STORY
1867 SPR_IMG_GOAL
, // WID_TN_GOAL
1868 SPR_IMG_GRAPHS
, // WID_TN_GRAPHS
1869 SPR_IMG_COMPANY_LEAGUE
, // WID_TN_LEAGUE
1870 SPR_IMG_INDUSTRY
, // WID_TN_INDUSTRIES
1871 SPR_IMG_TRAINLIST
, // WID_TN_TRAINS
1872 SPR_IMG_TRUCKLIST
, // WID_TN_ROADVEHS
1873 SPR_IMG_SHIPLIST
, // WID_TN_SHIPS
1874 SPR_IMG_AIRPLANESLIST
, // WID_TN_AIRCRAFT
1875 SPR_IMG_ZOOMIN
, // WID_TN_ZOOMIN
1876 SPR_IMG_ZOOMOUT
, // WID_TN_ZOOMOUT
1877 SPR_IMG_BUILDRAIL
, // WID_TN_RAILS
1878 SPR_IMG_BUILDROAD
, // WID_TN_ROADS
1879 SPR_IMG_BUILDWATER
, // WID_TN_WATER
1880 SPR_IMG_BUILDAIR
, // WID_TN_AIR
1881 SPR_IMG_LANDSCAPING
, // WID_TN_LANDSCAPE
1882 SPR_IMG_MUSIC
, // WID_TN_MUSIC_SOUND
1883 SPR_IMG_MESSAGES
, // WID_TN_MESSAGES
1884 SPR_IMG_QUERY
, // WID_TN_HELP
1885 SPR_IMG_SWITCH_TOOLBAR
, // WID_TN_SWITCH_BAR
1888 NWidgetMainToolbarContainer
*hor
= new NWidgetMainToolbarContainer();
1889 for (uint i
= 0; i
< WID_TN_END
; i
++) {
1891 case 4: case 8: case 15: case 19: case 21: case 26: hor
->Add(new NWidgetSpacer(0, 0)); break;
1893 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
));
1896 *biggest_index
= max
<int>(*biggest_index
, WID_TN_SWITCH_BAR
);
1900 static const NWidgetPart _nested_toolbar_normal_widgets
[] = {
1901 NWidgetFunction(MakeMainToolbar
),
1904 static const WindowDesc
_toolb_normal_desc(
1906 WC_MAIN_TOOLBAR
, WC_NONE
,
1908 _nested_toolbar_normal_widgets
, lengthof(_nested_toolbar_normal_widgets
),
1909 NULL
, &MainToolbarWindow::hotkeys
1913 /* --- Toolbar handling for the scenario editor */
1915 static ToolbarButtonProc
* const _scen_toolbar_button_procs
[] = {
1917 ToolbarFastForwardClick
,
1918 ToolbarOptionsClick
,
1919 ToolbarScenSaveOrLoad
,
1921 ToolbarScenDatePanel
,
1922 ToolbarScenDateBackward
,
1923 ToolbarScenDateForward
,
1924 ToolbarScenMapTownDir
,
1926 ToolbarZoomOutClick
,
1929 ToolbarScenGenIndustry
,
1930 ToolbarScenBuildRoad
,
1931 ToolbarScenBuildDocks
,
1932 ToolbarScenPlantTrees
,
1933 ToolbarScenPlaceSign
,
1948 enum MainToolbarEditorHotkeys
{
1962 MTEHK_SMALL_SCREENSHOT
,
1963 MTEHK_ZOOMEDIN_SCREENSHOT
,
1964 MTEHK_DEFAULTZOOM_SCREENSHOT
,
1965 MTEHK_GIANT_SCREENSHOT
,
1970 MTEHK_EXTRA_VIEWPORT
,
1973 struct ScenarioEditorToolbarWindow
: Window
{
1974 CallBackFunction last_started_action
; ///< Last started user action.
1976 ScenarioEditorToolbarWindow (const WindowDesc
*desc
) :
1977 Window (desc
), last_started_action (CBF_NONE
)
1979 this->InitNested(0);
1981 this->last_started_action
= CBF_NONE
;
1982 CLRBITS(this->flags
, WF_WHITE_BORDER
);
1983 PositionMainToolbar(this);
1984 this->InvalidateData();
1987 virtual void FindWindowPlacementAndResize(int def_width
, int def_height
)
1989 Window::FindWindowPlacementAndResize(_toolbar_width
, def_height
);
1992 virtual void OnPaint()
1994 this->SetWidgetDisabledState(WID_TE_DATE_BACKWARD
, _settings_game
.game_creation
.starting_year
<= MIN_YEAR
);
1995 this->SetWidgetDisabledState(WID_TE_DATE_FORWARD
, _settings_game
.game_creation
.starting_year
>= MAX_YEAR
);
1997 this->DrawWidgets();
2000 virtual void DrawWidget(const Rect
&r
, int widget
) const
2004 SetDParam(0, ConvertYMDToDate(_settings_game
.game_creation
.starting_year
, 0, 1));
2005 DrawString(r
.left
, r
.right
, (this->height
- FONT_HEIGHT_NORMAL
) / 2, STR_WHITE_DATE_LONG
, TC_FROMSTRING
, SA_HOR_CENTER
);
2008 case WID_TE_SPACER
: {
2009 int height
= r
.bottom
- r
.top
;
2010 if (height
> 2 * FONT_HEIGHT_NORMAL
) {
2011 DrawString(r
.left
, r
.right
, (height
+ 1) / 2 - FONT_HEIGHT_NORMAL
, STR_SCENEDIT_TOOLBAR_OPENTTD
, TC_FROMSTRING
, SA_HOR_CENTER
);
2012 DrawString(r
.left
, r
.right
, (height
+ 1) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
, TC_FROMSTRING
, SA_HOR_CENTER
);
2014 DrawString(r
.left
, r
.right
, (height
- FONT_HEIGHT_NORMAL
) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
, TC_FROMSTRING
, SA_HOR_CENTER
);
2021 virtual void UpdateWidgetSize(int widget
, Dimension
*size
, const Dimension
&padding
, Dimension
*fill
, Dimension
*resize
)
2025 size
->width
= max(GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_OPENTTD
).width
, GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
).width
) + WD_FRAMERECT_LEFT
+ WD_FRAMERECT_RIGHT
;
2029 SetDParam(0, ConvertYMDToDate(MAX_YEAR
, 0, 1));
2030 *size
= GetStringBoundingBox(STR_WHITE_DATE_LONG
);
2031 size
->height
= max(size
->height
, GetSpriteSize(SPR_IMG_SAVE
).height
+ WD_IMGBTN_TOP
+ WD_IMGBTN_BOTTOM
);
2036 virtual void OnClick(Point pt
, int widget
, int click_count
)
2038 if (_game_mode
== GM_MENU
) return;
2039 CallBackFunction cbf
= _scen_toolbar_button_procs
[widget
](this);
2040 if (cbf
!= CBF_NONE
) this->last_started_action
= cbf
;
2043 virtual void OnDropdownSelect(int widget
, int index
)
2045 /* The map button is in a different location on the scenario
2046 * editor toolbar, so we need to adjust for it. */
2047 if (widget
== WID_TE_SMALL_MAP
) widget
= WID_TN_SMALL_MAP
;
2048 CallBackFunction cbf
= _menu_clicked_procs
[widget
](index
);
2049 if (cbf
!= CBF_NONE
) this->last_started_action
= cbf
;
2050 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
2053 virtual EventState
OnHotkey(int hotkey
)
2055 CallBackFunction cbf
= CBF_NONE
;
2057 case MTEHK_PAUSE
: ToolbarPauseClick(this); break;
2058 case MTEHK_FASTFORWARD
: ToolbarFastForwardClick(this); break;
2059 case MTEHK_SETTINGS
: ShowGameOptions(); break;
2060 case MTEHK_SAVEGAME
: MenuClickSaveLoad(); break;
2061 case MTEHK_GENLAND
: ToolbarScenGenLand(this); break;
2062 case MTEHK_GENTOWN
: ToolbarScenGenTown(this); break;
2063 case MTEHK_GENINDUSTRY
: ToolbarScenGenIndustry(this); break;
2064 case MTEHK_BUILD_ROAD
: ToolbarScenBuildRoad(this); break;
2065 case MTEHK_BUILD_DOCKS
: ToolbarScenBuildDocks(this); break;
2066 case MTEHK_BUILD_TREES
: ToolbarScenPlantTrees(this); break;
2067 case MTEHK_SIGN
: cbf
= ToolbarScenPlaceSign(this); break;
2068 case MTEHK_MUSIC
: ShowMusicWindow(); break;
2069 case MTEHK_LANDINFO
: cbf
= PlaceLandBlockInfo(); break;
2070 case MTEHK_SMALL_SCREENSHOT
: MenuClickSmallScreenshot(); break;
2071 case MTEHK_ZOOMEDIN_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN
); break;
2072 case MTEHK_DEFAULTZOOM_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM
); break;
2073 case MTEHK_GIANT_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_WORLD
); break;
2074 case MTEHK_ZOOM_IN
: ToolbarZoomInClick(this); break;
2075 case MTEHK_ZOOM_OUT
: ToolbarZoomOutClick(this); break;
2076 case MTEHK_TERRAFORM
: ShowEditorTerraformToolbar(); break;
2077 case MTEHK_SMALLMAP
: ShowSmallMap(); break;
2078 case MTEHK_EXTRA_VIEWPORT
: ShowExtraViewPortWindowForTileUnderCursor(); break;
2079 default: return ES_NOT_HANDLED
;
2081 if (cbf
!= CBF_NONE
) this->last_started_action
= cbf
;
2085 virtual void OnPlaceObject(Point pt
, TileIndex tile
)
2087 switch (this->last_started_action
) {
2088 case CBF_PLACE_SIGN
:
2089 PlaceProc_Sign(tile
);
2092 case CBF_PLACE_LANDINFO
:
2096 default: NOT_REACHED();
2100 virtual void OnTimeout()
2102 this->SetWidgetsLoweredState(false, WID_TE_DATE_BACKWARD
, WID_TE_DATE_FORWARD
, WIDGET_LIST_END
);
2103 this->SetWidgetDirty(WID_TE_DATE_BACKWARD
);
2104 this->SetWidgetDirty(WID_TE_DATE_FORWARD
);
2107 virtual void OnTick()
2109 if (this->IsWidgetLowered(WID_TE_PAUSE
) != !!_pause_mode
) {
2110 this->ToggleWidgetLoweredState(WID_TE_PAUSE
);
2114 if (this->IsWidgetLowered(WID_TE_FAST_FORWARD
) != !!_fast_forward
) {
2115 this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD
);
2121 * Some data on this window has become invalid.
2122 * @param data Information about the changed data.
2123 * @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.
2125 virtual void OnInvalidateData(int data
= 0, bool gui_scope
= true)
2127 if (!gui_scope
) return;
2128 if (FindWindowById(WC_MAIN_WINDOW
, 0) != NULL
) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW
, 0)->viewport
, WID_TE_ZOOM_IN
, WID_TE_ZOOM_OUT
);
2131 virtual void OnQueryTextFinished(char *str
)
2133 /* Was 'cancel' pressed? */
2134 if (str
== NULL
) return;
2137 if (!StrEmpty(str
)) {
2140 /* An empty string means revert to the default */
2141 value
= DEF_START_YEAR
;
2143 SetStartingYear(value
);
2148 static HotkeyList hotkeys
;
2151 static const Hotkey scenedit_maintoolbar_hotkeys
[] = {
2152 Hotkey ("pause", MTEHK_PAUSE
, WKC_F1
, WKC_PAUSE
),
2153 Hotkey ("fastforward", MTEHK_FASTFORWARD
),
2154 Hotkey ("settings", MTEHK_SETTINGS
, WKC_F2
),
2155 Hotkey ("saveload", MTEHK_SAVEGAME
, WKC_F3
),
2156 Hotkey ("gen_land", MTEHK_GENLAND
, WKC_F4
),
2157 Hotkey ("gen_town", MTEHK_GENTOWN
, WKC_F5
),
2158 Hotkey ("gen_industry", MTEHK_GENINDUSTRY
, WKC_F6
),
2159 Hotkey ("build_road", MTEHK_BUILD_ROAD
, WKC_F7
),
2160 Hotkey ("build_docks", MTEHK_BUILD_DOCKS
, WKC_F8
),
2161 Hotkey ("build_trees", MTEHK_BUILD_TREES
, WKC_F9
),
2162 Hotkey ("build_sign", MTEHK_SIGN
, WKC_F10
),
2163 Hotkey ("music", MTEHK_MUSIC
, WKC_F11
),
2164 Hotkey ("land_info", MTEHK_LANDINFO
, WKC_F12
),
2165 Hotkey ("small_screenshot", MTEHK_SMALL_SCREENSHOT
, WKC_CTRL
| 'S'),
2166 Hotkey ("zoomedin_screenshot", MTEHK_ZOOMEDIN_SCREENSHOT
, WKC_CTRL
| 'P'),
2167 Hotkey ("defaultzoom_screenshot", MTEHK_DEFAULTZOOM_SCREENSHOT
, WKC_CTRL
| 'D'),
2168 Hotkey ("giant_screenshot", MTEHK_GIANT_SCREENSHOT
),
2169 Hotkey ("zoomin", MTEHK_ZOOM_IN
, WKC_SHIFT
| WKC_F5
, WKC_NUM_PLUS
, WKC_EQUALS
, WKC_SHIFT
| WKC_EQUALS
),
2170 Hotkey ("zoomout", MTEHK_ZOOM_OUT
, WKC_SHIFT
| WKC_F6
, WKC_NUM_MINUS
, WKC_MINUS
, WKC_SHIFT
| WKC_MINUS
),
2171 Hotkey ("terraform", MTEHK_TERRAFORM
, 'L'),
2172 Hotkey ("smallmap", MTEHK_SMALLMAP
, 'M'),
2173 Hotkey ("extra_viewport", MTEHK_EXTRA_VIEWPORT
, 'V'),
2175 HotkeyList
ScenarioEditorToolbarWindow::hotkeys("scenedit_maintoolbar", scenedit_maintoolbar_hotkeys
);
2177 static const NWidgetPart _nested_toolb_scen_inner_widgets
[] = {
2178 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_PAUSE
), SetDataTip(SPR_IMG_PAUSE
, STR_TOOLBAR_TOOLTIP_PAUSE_GAME
),
2179 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_FAST_FORWARD
), SetDataTip(SPR_IMG_FASTFORWARD
, STR_TOOLBAR_TOOLTIP_FORWARD
),
2180 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_SETTINGS
), SetDataTip(SPR_IMG_SETTINGS
, STR_TOOLBAR_TOOLTIP_OPTIONS
),
2181 NWidget(WWT_IMGBTN_2
, COLOUR_GREY
, WID_TE_SAVE
), SetDataTip(SPR_IMG_SAVE
, STR_SCENEDIT_TOOLBAR_TOOLTIP_SAVE_SCENARIO_LOAD_SCENARIO
),
2182 NWidget(NWID_SPACER
),
2183 NWidget(WWT_PANEL
, COLOUR_GREY
, WID_TE_SPACER
), EndContainer(),
2184 NWidget(NWID_SPACER
),
2185 NWidget(WWT_PANEL
, COLOUR_GREY
, WID_TE_DATE_PANEL
),
2186 NWidget(NWID_HORIZONTAL
), SetPIP(3, 2, 3),
2187 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_DATE_BACKWARD
), SetDataTip(SPR_ARROW_DOWN
, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD
),
2188 NWidget(WWT_EMPTY
, COLOUR_GREY
, WID_TE_DATE
), SetDataTip(STR_NULL
, STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE
),
2189 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_DATE_FORWARD
), SetDataTip(SPR_ARROW_UP
, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD
),
2192 NWidget(NWID_SPACER
),
2193 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_SMALL_MAP
), SetDataTip(SPR_IMG_SMALLMAP
, STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY
),
2194 NWidget(NWID_SPACER
),
2195 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_ZOOM_IN
), SetDataTip(SPR_IMG_ZOOMIN
, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN
),
2196 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_ZOOM_OUT
), SetDataTip(SPR_IMG_ZOOMOUT
, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT
),
2197 NWidget(NWID_SPACER
),
2198 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_LAND_GENERATE
), SetDataTip(SPR_IMG_LANDSCAPING
, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION
),
2199 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_TOWN_GENERATE
), SetDataTip(SPR_IMG_TOWN
, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION
),
2200 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_INDUSTRY
), SetDataTip(SPR_IMG_INDUSTRY
, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION
),
2201 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_ROADS
), SetDataTip(SPR_IMG_BUILDROAD
, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION
),
2202 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_WATER
), SetDataTip(SPR_IMG_BUILDWATER
, STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS
),
2203 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_TREES
), SetDataTip(SPR_IMG_PLANTTREES
, STR_SCENEDIT_TOOLBAR_PLANT_TREES
),
2204 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_SIGNS
), SetDataTip(SPR_IMG_SIGN
, STR_SCENEDIT_TOOLBAR_PLACE_SIGN
),
2205 NWidget(NWID_SPACER
),
2206 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_MUSIC_SOUND
), SetDataTip(SPR_IMG_MUSIC
, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW
),
2207 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_HELP
), SetDataTip(SPR_IMG_QUERY
, STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION
),
2208 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_SWITCH_BAR
), SetDataTip(SPR_IMG_SWITCH_TOOLBAR
, STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR
),
2211 static NWidgetBase
*MakeScenarioToolbar(int *biggest_index
)
2213 return MakeNWidgets(_nested_toolb_scen_inner_widgets
, lengthof(_nested_toolb_scen_inner_widgets
), biggest_index
, new NWidgetScenarioToolbarContainer());
2216 static const NWidgetPart _nested_toolb_scen_widgets
[] = {
2217 NWidgetFunction(MakeScenarioToolbar
),
2220 static const WindowDesc
_toolb_scen_desc(
2222 WC_MAIN_TOOLBAR
, WC_NONE
,
2224 _nested_toolb_scen_widgets
, lengthof(_nested_toolb_scen_widgets
),
2225 NULL
, &ScenarioEditorToolbarWindow::hotkeys
2228 /** Allocate the toolbar. */
2229 void AllocateToolbar()
2231 /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
2232 _last_built_roadtype
= ROADTYPE_ROAD
;
2234 if (_game_mode
== GM_EDITOR
) {
2235 new ScenarioEditorToolbarWindow(&_toolb_scen_desc
);
2237 new MainToolbarWindow(&_toolb_normal_desc
);