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
{
80 static CallBackFunction _last_started_action
= CBF_NONE
; ///< Last started user action.
84 * Drop down list entry for showing a checked/unchecked toggle item.
86 class DropDownListCheckedItem
: public DropDownListStringItem
{
91 DropDownListCheckedItem(StringID string
, int result
, bool masked
, bool checked
) : DropDownListStringItem(string
, result
, masked
), checked(checked
)
93 this->checkmark_width
= GetStringBoundingBox(STR_JUST_CHECKMARK
).width
+ 3;
96 virtual ~DropDownListCheckedItem() {}
100 return DropDownListStringItem::Width() + this->checkmark_width
;
103 void Draw (BlitArea
*dpi
, int left
, int right
, int top
, int bottom
, bool sel
, int bg_colour
) const OVERRIDE
105 bool rtl
= _current_text_dir
== TD_RTL
;
107 DrawString (dpi
, left
+ WD_FRAMERECT_LEFT
, right
- WD_FRAMERECT_RIGHT
, top
, STR_JUST_CHECKMARK
, sel
? TC_WHITE
: TC_BLACK
);
109 DrawString (dpi
, left
+ WD_FRAMERECT_LEFT
+ (rtl
? 0 : this->checkmark_width
), right
- WD_FRAMERECT_RIGHT
- (rtl
? this->checkmark_width
: 0), top
, this->String(), sel
? TC_WHITE
: TC_BLACK
);
114 * Drop down list entry for showing a company entry, with companies 'blob'.
116 class DropDownListCompanyItem
: public DropDownListItem
{
121 DropDownListCompanyItem(int result
, bool masked
, bool greyed
) : DropDownListItem(result
, masked
), greyed(greyed
)
123 this->icon_size
= GetSpriteSize(SPR_COMPANY_ICON
);
126 virtual ~DropDownListCompanyItem() {}
128 bool Selectable() const
135 CompanyID company
= (CompanyID
)this->result
;
136 SetDParam(0, company
);
137 SetDParam(1, company
);
138 return GetStringBoundingBox(STR_COMPANY_NAME_COMPANY_NUM
).width
+ this->icon_size
.width
+ 3;
141 uint
Height(uint width
) const
143 return max(this->icon_size
.height
+ 2U, (uint
)FONT_HEIGHT_NORMAL
);
146 void Draw (BlitArea
*dpi
, int left
, int right
, int top
, int bottom
, bool sel
, int bg_colour
) const OVERRIDE
148 CompanyID company
= (CompanyID
)this->result
;
149 bool rtl
= _current_text_dir
== TD_RTL
;
151 /* It's possible the company is deleted while the dropdown is open */
152 if (!Company::IsValidID(company
)) return;
154 int icon_offset
= (bottom
- top
- icon_size
.height
) / 2;
155 int text_offset
= (bottom
- top
- FONT_HEIGHT_NORMAL
) / 2;
157 DrawCompanyIcon (dpi
, company
, rtl
? right
- this->icon_size
.width
- WD_FRAMERECT_RIGHT
: left
+ WD_FRAMERECT_LEFT
, top
+ icon_offset
);
159 SetDParam(0, company
);
160 SetDParam(1, company
);
163 col
= (sel
? TC_SILVER
: TC_GREY
) | TC_NO_SHADE
;
165 col
= sel
? TC_WHITE
: TC_BLACK
;
167 DrawString (dpi
, left
+ WD_FRAMERECT_LEFT
+ (rtl
? 0 : 3 + this->icon_size
.width
), right
- WD_FRAMERECT_RIGHT
- (rtl
? 3 + this->icon_size
.width
: 0), top
+ text_offset
, STR_COMPANY_NAME_COMPANY_NUM
, col
);
172 * Pop up a generic text only menu.
174 * @param widget Toolbar button
175 * @param list List of items
176 * @param def Default item
178 static void PopupMainToolbMenu(Window
*w
, int widget
, DropDownList
*list
, int def
)
180 ShowDropDownList(w
, list
, def
, widget
, 0, true, true);
181 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
185 * Pop up a generic text only menu.
187 * @param widget Toolbar button
188 * @param string String for the first item in the menu
189 * @param count Number of items in the menu
191 static void PopupMainToolbMenu(Window
*w
, int widget
, StringID string
, int count
)
193 DropDownList
*list
= new DropDownList();
194 for (int i
= 0; i
< count
; i
++) {
195 *list
->Append() = new DropDownListStringItem(string
+ i
, i
, false);
197 PopupMainToolbMenu(w
, widget
, list
, 0);
200 /** Enum for the Company Toolbar's network related buttons */
201 static const int CTMN_CLIENT_LIST
= -1; ///< Show the client list
202 static const int CTMN_NEW_COMPANY
= -2; ///< Create a new company
203 static const int CTMN_SPECTATE
= -3; ///< Become spectator
204 static const int CTMN_SPECTATOR
= -4; ///< Show a company window as spectator
207 * Pop up a generic company list menu.
208 * @param w The toolbar window.
209 * @param widget The button widget id.
210 * @param grey A bitbask of which items to mark as disabled.
211 * @param include_spectator If true, a spectator option is included in the list.
213 static void PopupMainCompanyToolbMenu(Window
*w
, int widget
, int grey
= 0, bool include_spectator
= false)
215 DropDownList
*list
= new DropDownList();
217 #ifdef ENABLE_NETWORK
219 if (widget
== WID_TN_COMPANIES
) {
220 /* Add the client list button for the companies menu */
221 *list
->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST
, CTMN_CLIENT_LIST
, false);
224 if (include_spectator
) {
225 if (widget
== WID_TN_COMPANIES
) {
226 if (_local_company
== COMPANY_SPECTATOR
) {
227 *list
->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY
, CTMN_NEW_COMPANY
, NetworkMaxCompaniesReached());
229 *list
->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE
, CTMN_SPECTATE
, NetworkMaxSpectatorsReached());
232 *list
->Append() = new DropDownListStringItem(STR_NETWORK_TOOLBAR_LIST_SPECTATOR
, CTMN_SPECTATOR
, false);
236 #endif /* ENABLE_NETWORK */
238 for (CompanyID c
= COMPANY_FIRST
; c
< MAX_COMPANIES
; c
++) {
239 if (!Company::IsValidID(c
)) continue;
240 *list
->Append() = new DropDownListCompanyItem(c
, false, HasBit(grey
, c
));
243 PopupMainToolbMenu(w
, widget
, list
, _local_company
== COMPANY_SPECTATOR
? CTMN_CLIENT_LIST
: (int)_local_company
);
247 static ToolbarMode _toolbar_mode
;
249 static CallBackFunction
SelectSignTool()
251 if (_last_started_action
== CBF_PLACE_SIGN
) {
255 SetPointerMode (POINTER_TILE
, WC_MAIN_TOOLBAR
, 0, SPR_CURSOR_SIGN
);
256 return CBF_PLACE_SIGN
;
260 /* --- Pausing --- */
262 static CallBackFunction
ToolbarPauseClick(Window
*w
)
264 if (_networking
&& !_network_server
) return CBF_NONE
; // only server can pause the game
266 if (DoCommandP(0, PM_PAUSED_NORMAL
, _pause_mode
== PM_UNPAUSED
, CMD_PAUSE
)) {
267 if (_settings_client
.sound
.confirm
) SndPlayFx(SND_15_BEEP
);
273 * Toggle fast forward mode.
278 static CallBackFunction
ToolbarFastForwardClick(Window
*w
)
280 _fast_forward
^= true;
281 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
286 * Game Option button menu entries.
288 enum OptionMenuEntries
{
295 OME_SHOW_STATIONNAMES
,
296 OME_SHOW_WAYPOINTNAMES
,
298 OME_SHOW_COMPETITOR_SIGNS
,
301 OME_TRANSPARENTBUILDINGS
,
302 OME_SHOW_STATIONSIGNS
,
306 * Handle click on Options button in toolbar.
308 * @param w parent window the shown Drop down list is attached to.
311 static CallBackFunction
ToolbarOptionsClick(Window
*w
)
313 DropDownList
*list
= new DropDownList();
314 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS
, OME_GAMEOPTIONS
, false);
315 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE
, OME_SETTINGS
, false);
316 /* Changes to the per-AI settings don't get send from the server to the clients. Clients get
317 * the settings once they join but never update it. As such don't show the window at all
318 * to network clients. */
319 if (!_networking
|| _network_server
) *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS
, OME_SCRIPT_SETTINGS
, false);
320 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS
, OME_NEWGRFSETTINGS
, false);
321 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS
, OME_TRANSPARENCIES
, false);
322 *list
->Append() = new DropDownListItem(-1, false);
323 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED
, OME_SHOW_TOWNNAMES
, false, HasBit(_display_opt
, DO_SHOW_TOWN_NAMES
));
324 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED
, OME_SHOW_STATIONNAMES
, false, HasBit(_display_opt
, DO_SHOW_STATION_NAMES
));
325 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED
, OME_SHOW_WAYPOINTNAMES
, false, HasBit(_display_opt
, DO_SHOW_WAYPOINT_NAMES
));
326 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED
, OME_SHOW_SIGNS
, false, HasBit(_display_opt
, DO_SHOW_SIGNS
));
327 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS
, OME_SHOW_COMPETITOR_SIGNS
, false, HasBit(_display_opt
, DO_SHOW_COMPETITOR_SIGNS
));
328 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION
, OME_FULL_ANIMATION
, false, HasBit(_display_opt
, DO_FULL_ANIMATION
));
329 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL
, OME_FULL_DETAILS
, false, HasBit(_display_opt
, DO_FULL_DETAIL
));
330 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS
, OME_TRANSPARENTBUILDINGS
, false, IsTransparencySet(TO_HOUSES
));
331 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS
, OME_SHOW_STATIONSIGNS
, false, IsTransparencySet(TO_SIGNS
));
333 ShowDropDownList(w
, list
, 0, WID_TN_SETTINGS
, 140, true, true);
334 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
339 * Handle click on one of the entries in the Options button menu.
341 * @param index Index being clicked.
344 static CallBackFunction
MenuClickSettings(int index
)
347 case OME_GAMEOPTIONS
: ShowGameOptions(); return CBF_NONE
;
348 case OME_SETTINGS
: ShowGameSettings(); return CBF_NONE
;
349 case OME_SCRIPT_SETTINGS
: ShowAIConfigWindow(); return CBF_NONE
;
350 case OME_NEWGRFSETTINGS
: ShowNewGRFSettings(!_networking
&& _settings_client
.gui
.UserIsAllowedToChangeNewGRFs(), true, true, &_grfconfig
); return CBF_NONE
;
351 case OME_TRANSPARENCIES
: ShowTransparencyToolbar(); break;
353 case OME_SHOW_TOWNNAMES
: ToggleBit(_display_opt
, DO_SHOW_TOWN_NAMES
); break;
354 case OME_SHOW_STATIONNAMES
: ToggleBit(_display_opt
, DO_SHOW_STATION_NAMES
); break;
355 case OME_SHOW_WAYPOINTNAMES
: ToggleBit(_display_opt
, DO_SHOW_WAYPOINT_NAMES
); break;
356 case OME_SHOW_SIGNS
: ToggleBit(_display_opt
, DO_SHOW_SIGNS
); break;
357 case OME_SHOW_COMPETITOR_SIGNS
:
358 ToggleBit(_display_opt
, DO_SHOW_COMPETITOR_SIGNS
);
359 InvalidateWindowClassesData(WC_SIGN_LIST
, -1);
361 case OME_FULL_ANIMATION
: ToggleBit(_display_opt
, DO_FULL_ANIMATION
); CheckBlitter(); break;
362 case OME_FULL_DETAILS
: ToggleBit(_display_opt
, DO_FULL_DETAIL
); break;
363 case OME_TRANSPARENTBUILDINGS
: ToggleTransparency(TO_HOUSES
); break;
364 case OME_SHOW_STATIONSIGNS
: ToggleTransparency(TO_SIGNS
); break;
366 MarkWholeScreenDirty();
371 * SaveLoad entries in scenario editor mode.
373 enum SaveLoadEditorMenuEntries
{
374 SLEME_SAVE_SCENARIO
= 0,
376 SLEME_SAVE_HEIGHTMAP
,
377 SLEME_LOAD_HEIGHTMAP
,
384 * SaveLoad entries in normal game mode.
386 enum SaveLoadNormalMenuEntries
{
395 * Handle click on Save button in toolbar in normal game mode.
397 * @param w parent window the shown save dialogue is attached to.
400 static CallBackFunction
ToolbarSaveClick(Window
*w
)
402 PopupMainToolbMenu(w
, WID_TN_SAVE
, STR_FILE_MENU_SAVE_GAME
, SLNME_MENUCOUNT
);
407 * Handle click on SaveLoad button in toolbar in the scenario editor.
409 * @param w parent window the shown save dialogue is attached to.
412 static CallBackFunction
ToolbarScenSaveOrLoad(Window
*w
)
414 PopupMainToolbMenu(w
, WID_TE_SAVE
, STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO
, SLEME_MENUCOUNT
);
419 * Handle click on one of the entries in the SaveLoad menu.
421 * @param index Index being clicked.
424 static CallBackFunction
MenuClickSaveLoad(int index
= 0)
426 if (_game_mode
== GM_EDITOR
) {
428 case SLEME_SAVE_SCENARIO
: ShowSaveLoadDialog (FT_SCENARIO
, true); break;
429 case SLEME_LOAD_SCENARIO
: ShowSaveLoadDialog (FT_SCENARIO
, false); break;
430 case SLEME_SAVE_HEIGHTMAP
: ShowSaveLoadDialog (FT_HEIGHTMAP
, true); break;
431 case SLEME_LOAD_HEIGHTMAP
: ShowSaveLoadDialog (FT_HEIGHTMAP
, false); break;
432 case SLEME_EXIT_TOINTRO
: AskExitToGameMenu(); break;
433 case SLEME_EXIT_GAME
: HandleExitGameRequest(); break;
437 case SLNME_SAVE_GAME
: ShowSaveLoadDialog (FT_SAVEGAME
, true); break;
438 case SLNME_LOAD_GAME
: ShowSaveLoadDialog (FT_SAVEGAME
, false); break;
439 case SLNME_EXIT_TOINTRO
: AskExitToGameMenu(); break;
440 case SLNME_EXIT_GAME
: HandleExitGameRequest(); break;
446 /* --- Map button menu --- */
448 enum MapMenuEntries
{
449 MME_SHOW_SMALLMAP
= 0,
450 MME_SHOW_EXTRAVIEWPORTS
,
453 MME_SHOW_TOWNDIRECTORY
,
454 MME_SHOW_INDUSTRYDIRECTORY
,
457 static CallBackFunction
ToolbarMapClick(Window
*w
)
459 DropDownList
*list
= new DropDownList();
460 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD
, MME_SHOW_SMALLMAP
, false);
461 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT
, MME_SHOW_EXTRAVIEWPORTS
, false);
462 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_LINGRAPH_LEGEND
, MME_SHOW_LINKGRAPH
, false);
463 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST
, MME_SHOW_SIGNLISTS
, false);
464 PopupMainToolbMenu(w
, WID_TN_SMALL_MAP
, list
, 0);
468 static CallBackFunction
ToolbarScenMapTownDir(Window
*w
)
470 DropDownList
*list
= new DropDownList();
471 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD
, MME_SHOW_SMALLMAP
, false);
472 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT
, MME_SHOW_EXTRAVIEWPORTS
, false);
473 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST
, MME_SHOW_SIGNLISTS
, false);
474 *list
->Append() = new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY
, MME_SHOW_TOWNDIRECTORY
, false);
475 *list
->Append() = new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY
, MME_SHOW_INDUSTRYDIRECTORY
, false);
476 PopupMainToolbMenu(w
, WID_TE_SMALL_MAP
, list
, 0);
481 * Handle click on one of the entries in the Map menu.
483 * @param index Index being clicked.
486 static CallBackFunction
MenuClickMap(int index
)
489 case MME_SHOW_SMALLMAP
: ShowSmallMap(); break;
490 case MME_SHOW_EXTRAVIEWPORTS
: ShowExtraViewPortWindow(); break;
491 case MME_SHOW_LINKGRAPH
: ShowLinkGraphLegend(); break;
492 case MME_SHOW_SIGNLISTS
: ShowSignList(); break;
493 case MME_SHOW_TOWNDIRECTORY
: ShowTownDirectory(); break;
494 case MME_SHOW_INDUSTRYDIRECTORY
: ShowIndustryDirectory(); break;
499 /* --- Town button menu --- */
501 static CallBackFunction
ToolbarTownClick(Window
*w
)
503 PopupMainToolbMenu(w
, WID_TN_TOWNS
, STR_TOWN_MENU_TOWN_DIRECTORY
, (_settings_game
.economy
.found_town
== TF_FORBIDDEN
) ? 1 : 2);
508 * Handle click on one of the entries in the Town menu.
510 * @param index Index being clicked.
513 static CallBackFunction
MenuClickTown(int index
)
516 case 0: ShowTownDirectory(); break;
517 case 1: // setting could be changed when the dropdown was open
518 if (_settings_game
.economy
.found_town
!= TF_FORBIDDEN
) ShowFoundTownWindow();
524 /* --- Subidies button menu --- */
526 static CallBackFunction
ToolbarSubsidiesClick(Window
*w
)
528 PopupMainToolbMenu(w
, WID_TN_SUBSIDIES
, STR_SUBSIDIES_MENU_SUBSIDIES
, 1);
533 * Handle click on the entry in the Subsidies menu.
535 * @param index Unused.
538 static CallBackFunction
MenuClickSubsidies(int index
)
541 case 0: ShowSubsidiesList(); break;
546 /* --- Stations button menu --- */
548 static CallBackFunction
ToolbarStationsClick(Window
*w
)
550 PopupMainCompanyToolbMenu(w
, WID_TN_STATIONS
);
555 * Handle click on the entry in the Stations menu
557 * @param index CompanyID to show station list for
560 static CallBackFunction
MenuClickStations(int index
)
562 ShowCompanyStations((CompanyID
)index
);
566 /* --- Finances button menu --- */
568 static CallBackFunction
ToolbarFinancesClick(Window
*w
)
570 PopupMainCompanyToolbMenu(w
, WID_TN_FINANCES
);
575 * Handle click on the entry in the finances overview menu.
577 * @param index CompanyID to show finances for.
580 static CallBackFunction
MenuClickFinances(int index
)
582 ShowCompanyFinances((CompanyID
)index
);
586 /* --- Company's button menu --- */
588 static CallBackFunction
ToolbarCompaniesClick(Window
*w
)
590 PopupMainCompanyToolbMenu(w
, WID_TN_COMPANIES
, 0, true);
595 * Handle click on the entry in the Company menu.
597 * @param index Menu entry to handle.
600 static CallBackFunction
MenuClickCompany(int index
)
602 #ifdef ENABLE_NETWORK
605 case CTMN_CLIENT_LIST
:
609 case CTMN_NEW_COMPANY
:
610 if (_network_server
) {
611 DoCommandP(0, 0, _network_own_client_id
, CMD_COMPANY_CTRL
);
613 NetworkSendCommand(0, 0, 0, CMD_COMPANY_CTRL
, NULL
, _local_company
);
618 if (_network_server
) {
619 NetworkServerDoMove(CLIENT_ID_SERVER
, COMPANY_SPECTATOR
);
620 MarkWholeScreenDirty();
622 NetworkClientRequestMove(COMPANY_SPECTATOR
);
627 #endif /* ENABLE_NETWORK */
628 ShowCompany((CompanyID
)index
);
632 /* --- Story button menu --- */
634 static CallBackFunction
ToolbarStoryClick(Window
*w
)
636 PopupMainCompanyToolbMenu(w
, WID_TN_STORY
, 0, true);
641 * Handle click on the entry in the Story menu
643 * @param index CompanyID to show story book for
646 static CallBackFunction
MenuClickStory(int index
)
648 ShowStoryBook(index
== CTMN_SPECTATOR
? INVALID_COMPANY
: (CompanyID
)index
);
652 /* --- Goal button menu --- */
654 static CallBackFunction
ToolbarGoalClick(Window
*w
)
656 PopupMainCompanyToolbMenu(w
, WID_TN_GOAL
, 0, true);
661 * Handle click on the entry in the Goal menu
663 * @param index CompanyID to show story book for
666 static CallBackFunction
MenuClickGoal(int index
)
668 ShowGoalsList(index
== CTMN_SPECTATOR
? INVALID_COMPANY
: (CompanyID
)index
);
672 /* --- Graphs button menu --- */
674 static CallBackFunction
ToolbarGraphsClick(Window
*w
)
676 PopupMainToolbMenu(w
, WID_TN_GRAPHS
, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH
, (_toolbar_mode
== TB_NORMAL
) ? 6 : 8);
681 * Handle click on the entry in the Graphs menu.
683 * @param index Graph to show.
686 static CallBackFunction
MenuClickGraphs(int index
)
689 case 0: ShowOperatingProfitGraph(); break;
690 case 1: ShowIncomeGraph(); break;
691 case 2: ShowDeliveredCargoGraph(); break;
692 case 3: ShowPerformanceHistoryGraph(); break;
693 case 4: ShowCompanyValueGraph(); break;
694 case 5: ShowCargoPaymentRates(); break;
695 /* functions for combined graphs/league button */
696 case 6: ShowCompanyLeagueTable(); break;
697 case 7: ShowPerformanceRatingDetail(); break;
702 /* --- League button menu --- */
704 static CallBackFunction
ToolbarLeagueClick(Window
*w
)
706 PopupMainToolbMenu(w
, WID_TN_LEAGUE
, STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE
, _networking
? 2 : 3);
711 * Handle click on the entry in the CompanyLeague menu.
713 * @param index Menu entry number.
716 static CallBackFunction
MenuClickLeague(int index
)
719 case 0: ShowCompanyLeagueTable(); break;
720 case 1: ShowPerformanceRatingDetail(); break;
721 case 2: ShowHighscoreTable(); break;
726 /* --- Industries button menu --- */
728 static CallBackFunction
ToolbarIndustryClick(Window
*w
)
730 /* Disable build-industry menu if we are a spectator */
731 PopupMainToolbMenu(w
, WID_TN_INDUSTRIES
, STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY
, (_local_company
== COMPANY_SPECTATOR
) ? 2 : 3);
736 * Handle click on the entry in the Industry menu.
738 * @param index Menu entry number.
741 static CallBackFunction
MenuClickIndustry(int index
)
744 case 0: ShowIndustryDirectory(); break;
745 case 1: ShowIndustryCargoesWindow(); break;
746 case 2: ShowBuildIndustryWindow(); break;
751 /* --- Trains button menu + 1 helper function for all vehicles. --- */
753 static void ToolbarVehicleClick(Window
*w
, VehicleType veh
)
758 FOR_ALL_VEHICLES(v
) {
759 if (v
->type
== veh
&& v
->IsPrimaryVehicle()) ClrBit(dis
, v
->owner
);
761 PopupMainCompanyToolbMenu(w
, WID_TN_VEHICLE_START
+ veh
, dis
);
765 static CallBackFunction
ToolbarTrainClick(Window
*w
)
767 ToolbarVehicleClick(w
, VEH_TRAIN
);
772 * Handle click on the entry in the Train menu.
774 * @param index CompanyID to show train list for.
777 static CallBackFunction
MenuClickShowTrains(int index
)
779 ShowVehicleListWindow((CompanyID
)index
, VEH_TRAIN
);
783 /* --- Road vehicle button menu --- */
785 static CallBackFunction
ToolbarRoadClick(Window
*w
)
787 ToolbarVehicleClick(w
, VEH_ROAD
);
792 * Handle click on the entry in the Road Vehicles menu.
794 * @param index CompanyID to show road vehicles list for.
797 static CallBackFunction
MenuClickShowRoad(int index
)
799 ShowVehicleListWindow((CompanyID
)index
, VEH_ROAD
);
803 /* --- Ship button menu --- */
805 static CallBackFunction
ToolbarShipClick(Window
*w
)
807 ToolbarVehicleClick(w
, VEH_SHIP
);
812 * Handle click on the entry in the Ships menu.
814 * @param index CompanyID to show ship list for.
817 static CallBackFunction
MenuClickShowShips(int index
)
819 ShowVehicleListWindow((CompanyID
)index
, VEH_SHIP
);
823 /* --- Aircraft button menu --- */
825 static CallBackFunction
ToolbarAirClick(Window
*w
)
827 ToolbarVehicleClick(w
, VEH_AIRCRAFT
);
832 * Handle click on the entry in the Aircraft menu.
834 * @param index CompanyID to show aircraft list for.
837 static CallBackFunction
MenuClickShowAir(int index
)
839 ShowVehicleListWindow((CompanyID
)index
, VEH_AIRCRAFT
);
843 /* --- Zoom in button --- */
845 static CallBackFunction
ToolbarZoomInClick(Window
*w
)
847 Window
*main
= FindWindowById (WC_MAIN_WINDOW
, 0);
848 if (main
->viewport
->zoom
> _settings_client
.gui
.zoom_min
) {
849 DoZoomInOutViewport (main
->viewport
, true);
850 main
->InvalidateData();
851 w
->HandleButtonClick((_game_mode
== GM_EDITOR
) ? (byte
)WID_TE_ZOOM_IN
: (byte
)WID_TN_ZOOM_IN
);
852 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
857 /* --- Zoom out button --- */
859 static CallBackFunction
ToolbarZoomOutClick(Window
*w
)
861 Window
*main
= FindWindowById (WC_MAIN_WINDOW
, 0);
862 if (main
->viewport
->zoom
< _settings_client
.gui
.zoom_max
) {
863 DoZoomInOutViewport (main
->viewport
, false);
864 main
->InvalidateData();
865 w
->HandleButtonClick((_game_mode
== GM_EDITOR
) ? (byte
)WID_TE_ZOOM_OUT
: (byte
)WID_TN_ZOOM_OUT
);
866 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
871 /* --- Rail button menu --- */
873 static CallBackFunction
ToolbarBuildRailClick(Window
*w
)
875 ShowDropDownList(w
, GetRailTypeDropDownList(), _last_built_railtype
, WID_TN_RAILS
, 140, true, true);
876 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
881 * Handle click on the entry in the Build Rail menu.
883 * @param index RailType to show the build toolbar for.
886 static CallBackFunction
MenuClickBuildRail(int index
)
888 _last_built_railtype
= (RailType
)index
;
889 ShowBuildRailToolbar(_last_built_railtype
);
893 /* --- Road button menu --- */
895 static CallBackFunction
ToolbarBuildRoadClick(Window
*w
)
897 const Company
*c
= Company::Get(_local_company
);
898 DropDownList
*list
= new DropDownList();
900 /* Road is always visible and available. */
901 *list
->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION
, ROADTYPE_ROAD
, false);
903 /* Tram is only visible when there will be a tram, and available when that has been introduced. */
905 FOR_ALL_ENGINES_OF_TYPE(e
, VEH_ROAD
) {
906 if (!HasBit(e
->info
.climates
, _settings_game
.game_creation
.landscape
)) continue;
907 if (!HasBit(e
->info
.misc_flags
, EF_ROAD_TRAM
)) continue;
909 *list
->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION
, ROADTYPE_TRAM
, !HasBit(c
->avail_roadtypes
, ROADTYPE_TRAM
));
912 ShowDropDownList(w
, list
, _last_built_roadtype
, WID_TN_ROADS
, 140, true, true);
913 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
918 * Handle click on the entry in the Build Road menu.
920 * @param index RoadType to show the build toolbar for.
923 static CallBackFunction
MenuClickBuildRoad(int index
)
925 _last_built_roadtype
= (RoadType
)index
;
926 ShowBuildRoadToolbar(_last_built_roadtype
);
930 /* --- Water button menu --- */
932 static CallBackFunction
ToolbarBuildWaterClick(Window
*w
)
934 PopupMainToolbMenu(w
, WID_TN_WATER
, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION
, 1);
939 * Handle click on the entry in the Build Waterways menu.
941 * @param index Unused.
944 static CallBackFunction
MenuClickBuildWater(int index
)
946 ShowBuildDocksToolbar();
950 /* --- Airport button menu --- */
952 static CallBackFunction
ToolbarBuildAirClick(Window
*w
)
954 PopupMainToolbMenu(w
, WID_TN_AIR
, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION
, 1);
959 * Handle click on the entry in the Build Air menu.
961 * @param index Unused.
964 static CallBackFunction
MenuClickBuildAir(int index
)
966 ShowBuildAirToolbar();
970 /* --- Forest button menu --- */
972 static CallBackFunction
ToolbarForestClick(Window
*w
)
974 PopupMainToolbMenu(w
, WID_TN_LANDSCAPE
, STR_LANDSCAPING_MENU_LANDSCAPING
, 3);
979 * Handle click on the entry in the landscaping menu.
981 * @param index Menu entry clicked.
984 static CallBackFunction
MenuClickForest(int index
)
987 case 0: ShowTerraformToolbar(); break;
988 case 1: ShowBuildTreesToolbar(); break;
989 case 2: return SelectSignTool();
994 /* --- Music button menu --- */
996 static CallBackFunction
ToolbarMusicClick(Window
*w
)
998 PopupMainToolbMenu(w
, WID_TN_MUSIC_SOUND
, STR_TOOLBAR_SOUND_MUSIC
, 1);
1003 * Handle click on the entry in the Music menu.
1005 * @param index Unused.
1008 static CallBackFunction
MenuClickMusicWindow(int index
)
1014 /* --- Newspaper button menu --- */
1016 static CallBackFunction
ToolbarNewspaperClick(Window
*w
)
1018 PopupMainToolbMenu(w
, WID_TN_MESSAGES
, STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT
, 2);
1023 * Handle click on the entry in the Newspaper menu.
1025 * @param index Menu entry clicked.
1028 static CallBackFunction
MenuClickNewspaper(int index
)
1031 case 0: ShowLastNewsMessage(); break;
1032 case 1: ShowMessageHistory(); break;
1037 /* --- Help button menu --- */
1039 static CallBackFunction
PlaceLandBlockInfo()
1041 if (_last_started_action
== CBF_PLACE_LANDINFO
) {
1045 SetPointerMode (POINTER_TILE
, WC_MAIN_TOOLBAR
, 0, SPR_CURSOR_QUERY
);
1046 return CBF_PLACE_LANDINFO
;
1050 static CallBackFunction
ToolbarHelpClick(Window
*w
)
1052 PopupMainToolbMenu(w
, WID_TN_HELP
, STR_ABOUT_MENU_LAND_BLOCK_INFO
, _settings_client
.gui
.newgrf_developer_tools
? 12 : 9);
1056 static void MenuClickSmallScreenshot()
1058 MakeScreenshot(SC_VIEWPORT
, NULL
);
1062 * Callback on the confirmation window for huge screenshots.
1063 * @param w Window with viewport
1064 * @param confirmed true on confirmation
1066 static void ScreenshotConfirmCallback(Window
*w
, bool confirmed
)
1068 if (confirmed
) MakeScreenshot(_confirmed_screenshot_type
, NULL
);
1072 * Make a screenshot of the world.
1073 * Ask for confirmation if the screenshot will be huge.
1074 * @param t Screenshot type: World or viewport screenshot
1076 static void MenuClickLargeWorldScreenshot(ScreenshotType t
)
1079 SetupScreenshotViewport(t
, &vp
);
1080 if ((uint64
)vp
.width
* (uint64
)vp
.height
> 8192 * 8192) {
1081 /* Ask for confirmation */
1082 SetDParam(0, vp
.width
);
1083 SetDParam(1, vp
.height
);
1084 _confirmed_screenshot_type
= t
;
1085 ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION
, STR_WARNING_SCREENSHOT_SIZE_MESSAGE
, NULL
, ScreenshotConfirmCallback
);
1087 /* Less than 64M pixels, just do it */
1088 MakeScreenshot(t
, NULL
);
1093 * Toggle drawing of sprites' bounding boxes.
1094 * @note has only an effect when newgrf_developer_tools are active.
1096 * Function is found here and not in viewport.cpp in order to avoid
1097 * importing the settings structs to there.
1099 void ToggleBoundingBoxes()
1101 extern bool _draw_bounding_boxes
;
1102 /* Always allow to toggle them off */
1103 if (_settings_client
.gui
.newgrf_developer_tools
|| _draw_bounding_boxes
) {
1104 _draw_bounding_boxes
= !_draw_bounding_boxes
;
1105 MarkWholeScreenDirty();
1110 * Toggle drawing of the dirty blocks.
1111 * @note has only an effect when newgrf_developer_tools are active.
1113 * Function is found here and not in viewport.cpp in order to avoid
1114 * importing the settings structs to there.
1116 void ToggleDirtyBlocks()
1118 extern bool _draw_dirty_blocks
;
1119 /* Always allow to toggle them off */
1120 if (_settings_client
.gui
.newgrf_developer_tools
|| _draw_dirty_blocks
) {
1121 _draw_dirty_blocks
= !_draw_dirty_blocks
;
1122 MarkWholeScreenDirty();
1127 * Set the starting year for a scenario.
1128 * @param year New starting year.
1130 void SetStartingYear(Year year
)
1132 _settings_game
.game_creation
.starting_year
= Clamp(year
, MIN_YEAR
, MAX_YEAR
);
1133 Date new_date
= ConvertYMDToDate(_settings_game
.game_creation
.starting_year
, 0, 1);
1134 /* If you open a savegame as scenario there may already be link graphs.*/
1135 LinkGraphSchedule::instance
.ShiftDates(new_date
- _date
);
1136 SetDate(new_date
, 0);
1140 * Choose the proper callback function for the main toolbar's help menu.
1141 * @param index The menu index which was selected.
1144 static CallBackFunction
MenuClickHelp(int index
)
1147 case 0: return PlaceLandBlockInfo();
1148 case 2: IConsoleSwitch(); break;
1149 case 3: ShowAIDebugWindow(); break;
1150 case 4: MenuClickSmallScreenshot(); break;
1151 case 5: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN
); break;
1152 case 6: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM
); break;
1153 case 7: MenuClickLargeWorldScreenshot(SC_WORLD
); break;
1154 case 8: ShowAboutWindow(); break;
1155 case 9: ShowSpriteAlignerWindow(); break;
1156 case 10: ToggleBoundingBoxes(); break;
1157 case 11: ToggleDirtyBlocks(); break;
1162 /* --- Switch toolbar button --- */
1164 static CallBackFunction
ToolbarSwitchClick(Window
*w
)
1166 if (_toolbar_mode
!= TB_LOWER
) {
1167 _toolbar_mode
= TB_LOWER
;
1169 _toolbar_mode
= TB_UPPER
;
1173 w
->SetWidgetLoweredState(WID_TN_SWITCH_BAR
, _toolbar_mode
== TB_LOWER
);
1174 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1178 /* --- Scenario editor specific handlers. */
1181 * Called when clicking at the date panel of the scenario editor toolbar.
1183 static CallBackFunction
ToolbarScenDatePanel(Window
*w
)
1185 SetDParam(0, _settings_game
.game_creation
.starting_year
);
1186 ShowQueryString(STR_JUST_INT
, STR_MAPGEN_START_DATE_QUERY_CAPT
, 8, w
, CS_NUMERAL
, QSF_ENABLE_DEFAULT
);
1187 _left_button_clicked
= false;
1191 static CallBackFunction
ToolbarScenDateBackward(Window
*w
)
1193 /* don't allow too fast scrolling */
1194 if (!(w
->flags
& WF_TIMEOUT
) || w
->timeout_timer
<= 1) {
1195 w
->HandleButtonClick(WID_TE_DATE_BACKWARD
);
1198 SetStartingYear(_settings_game
.game_creation
.starting_year
- 1);
1200 _left_button_clicked
= false;
1204 static CallBackFunction
ToolbarScenDateForward(Window
*w
)
1206 /* don't allow too fast scrolling */
1207 if (!(w
->flags
& WF_TIMEOUT
) || w
->timeout_timer
<= 1) {
1208 w
->HandleButtonClick(WID_TE_DATE_FORWARD
);
1211 SetStartingYear(_settings_game
.game_creation
.starting_year
+ 1);
1213 _left_button_clicked
= false;
1217 static CallBackFunction
ToolbarScenGenLand(Window
*w
)
1219 w
->HandleButtonClick(WID_TE_LAND_GENERATE
);
1220 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1222 ShowEditorTerraformToolbar();
1227 static CallBackFunction
ToolbarScenGenTown(Window
*w
)
1229 w
->HandleButtonClick(WID_TE_TOWN_GENERATE
);
1230 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1231 ShowFoundTownWindow();
1235 static CallBackFunction
ToolbarScenGenIndustry(Window
*w
)
1237 w
->HandleButtonClick(WID_TE_INDUSTRY
);
1238 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1239 ShowBuildIndustryWindow();
1243 static CallBackFunction
ToolbarScenBuildRoad(Window
*w
)
1245 w
->HandleButtonClick(WID_TE_ROADS
);
1246 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1247 ShowBuildRoadScenToolbar();
1251 static CallBackFunction
ToolbarScenBuildDocks(Window
*w
)
1253 w
->HandleButtonClick(WID_TE_WATER
);
1254 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1255 ShowBuildDocksScenToolbar();
1259 static CallBackFunction
ToolbarScenPlantTrees(Window
*w
)
1261 w
->HandleButtonClick(WID_TE_TREES
);
1262 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1263 ShowBuildTreesToolbar();
1267 static CallBackFunction
ToolbarScenPlaceSign(Window
*w
)
1269 w
->HandleButtonClick(WID_TE_SIGNS
);
1270 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1271 return SelectSignTool();
1274 static CallBackFunction
ToolbarBtn_NULL(Window
*w
)
1279 typedef CallBackFunction
MenuClickedProc(int index
);
1281 static MenuClickedProc
* const _menu_clicked_procs
[] = {
1284 MenuClickSettings
, // 2
1285 MenuClickSaveLoad
, // 3
1288 MenuClickSubsidies
, // 6
1289 MenuClickStations
, // 7
1290 MenuClickFinances
, // 8
1291 MenuClickCompany
, // 9
1292 MenuClickStory
, // 10
1293 MenuClickGoal
, // 11
1294 MenuClickGraphs
, // 12
1295 MenuClickLeague
, // 13
1296 MenuClickIndustry
, // 14
1297 MenuClickShowTrains
, // 15
1298 MenuClickShowRoad
, // 16
1299 MenuClickShowShips
, // 17
1300 MenuClickShowAir
, // 18
1303 MenuClickBuildRail
, // 21
1304 MenuClickBuildRoad
, // 22
1305 MenuClickBuildWater
, // 23
1306 MenuClickBuildAir
, // 24
1307 MenuClickForest
, // 25
1308 MenuClickMusicWindow
, // 26
1309 MenuClickNewspaper
, // 27
1310 MenuClickHelp
, // 28
1313 /** Full blown container to make it behave exactly as we want :) */
1314 class NWidgetToolbarContainer
: public NWidgetContainer
{
1315 bool visible
[WID_TN_END
]; ///< The visible headers
1317 uint spacers
; ///< Number of spacer widgets in this toolbar
1320 NWidgetToolbarContainer() : NWidgetContainer(NWID_HORIZONTAL
)
1325 * Check whether the given widget type is a button for us.
1326 * @param type the widget type to check.
1327 * @return true if it is a button for us.
1329 bool IsButton(WidgetType type
) const
1331 return type
== WWT_IMGBTN
|| type
== WWT_IMGBTN_2
|| type
== WWT_PUSHIMGBTN
;
1334 void SetupSmallestSize(Window
*w
, bool init_array
)
1336 this->smallest_x
= 0; // Biggest child
1337 this->smallest_y
= 0; // Biggest child
1340 this->resize_x
= 1; // We only resize in this direction
1341 this->resize_y
= 0; // We never resize in this direction
1345 /* First initialise some variables... */
1346 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= NULL
; child_wid
= child_wid
->next
) {
1347 child_wid
->SetupSmallestSize(w
, init_array
);
1348 this->smallest_y
= max(this->smallest_y
, child_wid
->smallest_y
+ child_wid
->padding_top
+ child_wid
->padding_bottom
);
1349 if (this->IsButton(child_wid
->type
)) {
1351 this->smallest_x
= max(this->smallest_x
, child_wid
->smallest_x
+ child_wid
->padding_left
+ child_wid
->padding_right
);
1352 } else if (child_wid
->type
== NWID_SPACER
) {
1357 /* ... then in a second pass make sure the 'current' heights are set. Won't change ever. */
1358 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= NULL
; child_wid
= child_wid
->next
) {
1359 child_wid
->current_y
= this->smallest_y
;
1360 if (!this->IsButton(child_wid
->type
)) {
1361 child_wid
->current_x
= child_wid
->smallest_x
;
1364 _toolbar_width
= nbuttons
* this->smallest_x
;
1367 void AssignSizePosition(SizingType sizing
, uint x
, uint y
, uint given_width
, uint given_height
, bool rtl
)
1369 assert(given_width
>= this->smallest_x
&& given_height
>= this->smallest_y
);
1373 this->current_x
= given_width
;
1374 this->current_y
= given_height
;
1376 /* Figure out what are the visible buttons */
1377 memset(this->visible
, 0, sizeof(this->visible
));
1378 uint arrangable_count
, button_count
, spacer_count
;
1379 const byte
*arrangement
= GetButtonArrangement(given_width
, arrangable_count
, button_count
, spacer_count
);
1380 for (uint i
= 0; i
< arrangable_count
; i
++) {
1381 this->visible
[arrangement
[i
]] = true;
1384 /* Create us ourselves a quick lookup table */
1385 NWidgetBase
*widgets
[WID_TN_END
];
1386 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= NULL
; child_wid
= child_wid
->next
) {
1387 if (child_wid
->type
== NWID_SPACER
) continue;
1388 widgets
[((NWidgetCore
*)child_wid
)->index
] = child_wid
;
1391 /* Now assign the widgets to their rightful place */
1392 uint position
= 0; // Place to put next child relative to origin of the container.
1393 uint spacer_space
= max(0, (int)given_width
- (int)(button_count
* this->smallest_x
)); // Remaining spacing for 'spacer' widgets
1394 uint button_space
= given_width
- spacer_space
; // Remaining spacing for the buttons
1398 /* Index into the arrangement indices. The macro lastof cannot be used here! */
1399 const byte
*cur_wid
= rtl
? &arrangement
[arrangable_count
- 1] : arrangement
;
1400 for (uint i
= 0; i
< arrangable_count
; i
++) {
1401 NWidgetBase
*child_wid
= widgets
[*cur_wid
];
1402 /* If we have to give space to the spacers, do that */
1403 if (spacer_space
!= 0) {
1404 NWidgetBase
*possible_spacer
= rtl
? child_wid
->next
: child_wid
->prev
;
1405 if (possible_spacer
!= NULL
&& possible_spacer
->type
== NWID_SPACER
) {
1406 uint add
= spacer_space
/ (spacer_count
- spacer_i
);
1408 spacer_space
-= add
;
1413 /* Buttons can be scaled, the others not. */
1414 if (this->IsButton(child_wid
->type
)) {
1415 child_wid
->current_x
= button_space
/ (button_count
- button_i
);
1416 button_space
-= child_wid
->current_x
;
1419 child_wid
->AssignSizePosition(sizing
, x
+ position
, y
, child_wid
->current_x
, this->current_y
, rtl
);
1420 position
+= child_wid
->current_x
;
1430 void Draw (BlitArea
*dpi
, const Window
*w
) OVERRIDE
1432 /* Draw brown-red toolbar bg. */
1433 GfxFillRect (dpi
, this->pos_x
, this->pos_y
, this->pos_x
+ this->current_x
- 1, this->pos_y
+ this->current_y
- 1, PC_VERY_DARK_RED
);
1434 GfxFillRect (dpi
, this->pos_x
, this->pos_y
, this->pos_x
+ this->current_x
- 1, this->pos_y
+ this->current_y
- 1, PC_DARK_RED
, FILLRECT_CHECKER
);
1436 bool rtl
= _current_text_dir
== TD_RTL
;
1437 for (NWidgetBase
*child_wid
= rtl
? this->tail
: this->head
; child_wid
!= NULL
; child_wid
= rtl
? child_wid
->prev
: child_wid
->next
) {
1438 if (child_wid
->type
== NWID_SPACER
) continue;
1439 if (!this->visible
[((NWidgetCore
*)child_wid
)->index
]) continue;
1441 child_wid
->Draw (dpi
, w
);
1445 /* virtual */ NWidgetCore
*GetWidgetFromPos(int x
, int y
)
1447 if (!IsInsideBS(x
, this->pos_x
, this->current_x
) || !IsInsideBS(y
, this->pos_y
, this->current_y
)) return NULL
;
1449 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= NULL
; child_wid
= child_wid
->next
) {
1450 if (child_wid
->type
== NWID_SPACER
) continue;
1451 if (!this->visible
[((NWidgetCore
*)child_wid
)->index
]) continue;
1453 NWidgetCore
*nwid
= child_wid
->GetWidgetFromPos(x
, y
);
1454 if (nwid
!= NULL
) return nwid
;
1460 * Get the arrangement of the buttons for the toolbar.
1461 * @param width the new width of the toolbar.
1462 * @param arrangable_count output of the number of visible items.
1463 * @param button_count output of the number of visible buttons.
1464 * @param spacer_count output of the number of spacers.
1465 * @return the button configuration.
1467 virtual const byte
*GetButtonArrangement(uint
&width
, uint
&arrangable_count
, uint
&button_count
, uint
&spacer_count
) const = 0;
1470 /** Container for the 'normal' main toolbar */
1471 class NWidgetMainToolbarContainer
: public NWidgetToolbarContainer
{
1472 /* virtual */ const byte
*GetButtonArrangement(uint
&width
, uint
&arrangable_count
, uint
&button_count
, uint
&spacer_count
) const
1474 static const uint SMALLEST_ARRANGEMENT
= 14;
1475 static const uint BIGGEST_ARRANGEMENT
= 20;
1477 /* The number of buttons of each row of the toolbar should match the number of items which we want to be visible.
1478 * The total number of buttons should be equal to arrangable_count * 2.
1479 * No bad things happen, but we could see strange behaviours if we have buttons < (arrangable_count * 2) like a
1480 * pause button appearing on the right of the lower toolbar and weird resizing of the widgets even if there is
1483 static const byte arrange14
[] = {
1485 WID_TN_FAST_FORWARD
,
1514 static const byte arrange15
[] = {
1516 WID_TN_FAST_FORWARD
,
1547 static const byte arrange16
[] = {
1549 WID_TN_FAST_FORWARD
,
1566 WID_TN_FAST_FORWARD
,
1582 static const byte arrange17
[] = {
1584 WID_TN_FAST_FORWARD
,
1602 WID_TN_FAST_FORWARD
,
1619 static const byte arrange18
[] = {
1621 WID_TN_FAST_FORWARD
,
1640 WID_TN_FAST_FORWARD
,
1658 static const byte arrange19
[] = {
1660 WID_TN_FAST_FORWARD
,
1680 WID_TN_FAST_FORWARD
,
1699 static const byte arrange20
[] = {
1701 WID_TN_FAST_FORWARD
,
1722 WID_TN_FAST_FORWARD
,
1742 static const byte arrange_all
[] = {
1744 WID_TN_FAST_FORWARD
,
1774 /* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
1775 uint full_buttons
= max(CeilDiv(width
, this->smallest_x
), SMALLEST_ARRANGEMENT
);
1776 if (full_buttons
> BIGGEST_ARRANGEMENT
) {
1777 button_count
= arrangable_count
= lengthof(arrange_all
);
1778 spacer_count
= this->spacers
;
1782 /* Introduce the split toolbar */
1783 static const byte
* const arrangements
[] = { arrange14
, arrange15
, arrange16
, arrange17
, arrange18
, arrange19
, arrange20
};
1785 button_count
= arrangable_count
= full_buttons
;
1786 spacer_count
= this->spacers
;
1787 return arrangements
[full_buttons
- SMALLEST_ARRANGEMENT
] + ((_toolbar_mode
== TB_LOWER
) ? full_buttons
: 0);
1791 /** Container for the scenario editor's toolbar */
1792 class NWidgetScenarioToolbarContainer
: public NWidgetToolbarContainer
{
1793 uint panel_widths
[2]; ///< The width of the two panels (the text panel and date panel)
1795 void SetupSmallestSize(Window
*w
, bool init_array
)
1797 this->NWidgetToolbarContainer::SetupSmallestSize(w
, init_array
);
1799 /* Find the size of panel_widths */
1801 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= NULL
; child_wid
= child_wid
->next
) {
1802 if (child_wid
->type
== NWID_SPACER
|| this->IsButton(child_wid
->type
)) continue;
1804 assert(i
< lengthof(this->panel_widths
));
1805 this->panel_widths
[i
++] = child_wid
->current_x
;
1806 _toolbar_width
+= child_wid
->current_x
;
1810 /* virtual */ const byte
*GetButtonArrangement(uint
&width
, uint
&arrangable_count
, uint
&button_count
, uint
&spacer_count
) const
1812 static const byte arrange_all
[] = {
1814 WID_TE_FAST_FORWARD
,
1822 WID_TE_LAND_GENERATE
,
1823 WID_TE_TOWN_GENERATE
,
1832 static const byte arrange_nopanel
[] = {
1834 WID_TE_FAST_FORWARD
,
1841 WID_TE_LAND_GENERATE
,
1842 WID_TE_TOWN_GENERATE
,
1851 static const byte arrange_switch
[] = {
1854 WID_TE_LAND_GENERATE
,
1855 WID_TE_TOWN_GENERATE
,
1864 WID_TE_FAST_FORWARD
,
1871 WID_TE_HELP
, WID_TE_SWITCH_BAR
,
1874 /* If we can place all buttons *and* the panels, show them. */
1875 uint min_full_width
= (lengthof(arrange_all
) - lengthof(this->panel_widths
)) * this->smallest_x
+ this->panel_widths
[0] + this->panel_widths
[1];
1876 if (width
>= min_full_width
) {
1877 width
-= this->panel_widths
[0] + this->panel_widths
[1];
1878 arrangable_count
= lengthof(arrange_all
);
1879 button_count
= arrangable_count
- 2;
1880 spacer_count
= this->spacers
;
1884 /* Otherwise don't show the date panel and if we can't fit half the buttons and the panels anymore, split the toolbar in two */
1885 uint min_small_width
= (lengthof(arrange_switch
) - lengthof(this->panel_widths
)) * this->smallest_x
/ 2 + this->panel_widths
[1];
1886 if (width
> min_small_width
) {
1887 width
-= this->panel_widths
[1];
1888 arrangable_count
= lengthof(arrange_nopanel
);
1889 button_count
= arrangable_count
- 1;
1890 spacer_count
= this->spacers
- 1;
1891 return arrange_nopanel
;
1895 width
-= this->panel_widths
[1];
1896 arrangable_count
= lengthof(arrange_switch
) / 2;
1897 button_count
= arrangable_count
- 1;
1899 return arrange_switch
+ ((_toolbar_mode
== TB_LOWER
) ? arrangable_count
: 0);
1903 /* --- Toolbar handling for the 'normal' case */
1905 typedef CallBackFunction
ToolbarButtonProc(Window
*w
);
1907 static ToolbarButtonProc
* const _toolbar_button_procs
[] = {
1909 ToolbarFastForwardClick
,
1910 ToolbarOptionsClick
,
1914 ToolbarSubsidiesClick
,
1915 ToolbarStationsClick
,
1916 ToolbarFinancesClick
,
1917 ToolbarCompaniesClick
,
1922 ToolbarIndustryClick
,
1928 ToolbarZoomOutClick
,
1929 ToolbarBuildRailClick
,
1930 ToolbarBuildRoadClick
,
1931 ToolbarBuildWaterClick
,
1932 ToolbarBuildAirClick
,
1935 ToolbarNewspaperClick
,
1940 enum MainToolbarHotkeys
{
1970 MTHK_SMALL_SCREENSHOT
,
1971 MTHK_ZOOMEDIN_SCREENSHOT
,
1972 MTHK_DEFAULTZOOM_SCREENSHOT
,
1973 MTHK_GIANT_SCREENSHOT
,
1976 MTHK_EXTRA_VIEWPORT
,
1981 /** Main toolbar. */
1982 struct MainToolbarWindow
: Window
{
1983 MainToolbarWindow (const WindowDesc
*desc
) : Window (desc
)
1985 this->InitNested(0);
1987 _last_started_action
= CBF_NONE
;
1988 CLRBITS(this->flags
, WF_WHITE_BORDER
);
1989 this->SetWidgetDisabledState(WID_TN_PAUSE
, _networking
&& !_network_server
); // if not server, disable pause button
1990 this->SetWidgetDisabledState(WID_TN_FAST_FORWARD
, _networking
); // if networking, disable fast-forward button
1991 PositionMainToolbar(this);
1992 this->InvalidateData();
1995 virtual void FindWindowPlacementAndResize(int def_width
, int def_height
)
1997 Window::FindWindowPlacementAndResize(_toolbar_width
, def_height
);
2000 void OnPaint (BlitArea
*dpi
) OVERRIDE
2002 /* If spectator, disable all construction buttons
2003 * ie : Build road, rail, ships, airports and landscaping
2004 * Since enabled state is the default, just disable when needed */
2005 this->SetWidgetsDisabledState(_local_company
== COMPANY_SPECTATOR
, WID_TN_RAILS
, WID_TN_ROADS
, WID_TN_WATER
, WID_TN_AIR
, WID_TN_LANDSCAPE
, WIDGET_LIST_END
);
2006 /* disable company list drop downs, if there are no companies */
2007 this->SetWidgetsDisabledState(Company::GetNumItems() == 0, WID_TN_STATIONS
, WID_TN_FINANCES
, WID_TN_TRAINS
, WID_TN_ROADVEHS
, WID_TN_SHIPS
, WID_TN_AIRCRAFTS
, WIDGET_LIST_END
);
2009 this->SetWidgetDisabledState(WID_TN_GOAL
, Goal::GetNumItems() == 0);
2010 this->SetWidgetDisabledState(WID_TN_STORY
, StoryPage::GetNumItems() == 0);
2012 this->SetWidgetDisabledState(WID_TN_RAILS
, !CanBuildVehicleInfrastructure(VEH_TRAIN
));
2013 this->SetWidgetDisabledState(WID_TN_AIR
, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT
));
2015 this->DrawWidgets (dpi
);
2018 virtual void OnClick(Point pt
, int widget
, int click_count
)
2020 if (_game_mode
!= GM_MENU
&& !this->IsWidgetDisabled(widget
)) _toolbar_button_procs
[widget
](this);
2023 virtual void OnDropdownSelect(int widget
, int index
)
2025 CallBackFunction cbf
= _menu_clicked_procs
[widget
](index
);
2026 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
2029 virtual EventState
OnHotkey(int hotkey
)
2032 case MTHK_PAUSE
: ToolbarPauseClick(this); break;
2033 case MTHK_FASTFORWARD
: ToolbarFastForwardClick(this); break;
2034 case MTHK_SETTINGS
: ShowGameOptions(); break;
2035 case MTHK_SAVEGAME
: MenuClickSaveLoad(); break;
2036 case MTHK_LOADGAME
: ShowSaveLoadDialog (FT_SAVEGAME
); break;
2037 case MTHK_SMALLMAP
: ShowSmallMap(); break;
2038 case MTHK_TOWNDIRECTORY
: ShowTownDirectory(); break;
2039 case MTHK_SUBSIDIES
: ShowSubsidiesList(); break;
2040 case MTHK_STATIONS
: ShowCompanyStations(_local_company
); break;
2041 case MTHK_FINANCES
: ShowCompanyFinances(_local_company
); break;
2042 case MTHK_COMPANIES
: ShowCompany(_local_company
); break;
2043 case MTHK_STORY
: ShowStoryBook(_local_company
); break;
2044 case MTHK_GOAL
: ShowGoalsList(_local_company
); break;
2045 case MTHK_GRAPHS
: ShowOperatingProfitGraph(); break;
2046 case MTHK_LEAGUE
: ShowCompanyLeagueTable(); break;
2047 case MTHK_INDUSTRIES
: ShowBuildIndustryWindow(); break;
2048 case MTHK_TRAIN_LIST
: ShowVehicleListWindow(_local_company
, VEH_TRAIN
); break;
2049 case MTHK_ROADVEH_LIST
: ShowVehicleListWindow(_local_company
, VEH_ROAD
); break;
2050 case MTHK_SHIP_LIST
: ShowVehicleListWindow(_local_company
, VEH_SHIP
); break;
2051 case MTHK_AIRCRAFT_LIST
: ShowVehicleListWindow(_local_company
, VEH_AIRCRAFT
); break;
2052 case MTHK_ZOOM_IN
: ToolbarZoomInClick(this); break;
2053 case MTHK_ZOOM_OUT
: ToolbarZoomOutClick(this); break;
2054 case MTHK_BUILD_RAIL
: if (CanBuildVehicleInfrastructure(VEH_TRAIN
)) ShowBuildRailToolbar(_last_built_railtype
); break;
2055 case MTHK_BUILD_ROAD
: ShowBuildRoadToolbar(_last_built_roadtype
); break;
2056 case MTHK_BUILD_DOCKS
: ShowBuildDocksToolbar(); break;
2057 case MTHK_BUILD_AIRPORT
: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT
)) ShowBuildAirToolbar(); break;
2058 case MTHK_BUILD_TREES
: ShowBuildTreesToolbar(); break;
2059 case MTHK_MUSIC
: ShowMusicWindow(); break;
2060 case MTHK_AI_DEBUG
: ShowAIDebugWindow(); break;
2061 case MTHK_SMALL_SCREENSHOT
: MenuClickSmallScreenshot(); break;
2062 case MTHK_ZOOMEDIN_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN
); break;
2063 case MTHK_DEFAULTZOOM_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM
); break;
2064 case MTHK_GIANT_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_WORLD
); break;
2065 case MTHK_CHEATS
: if (!_networking
) ShowCheatWindow(); break;
2066 case MTHK_TERRAFORM
: ShowTerraformToolbar(); break;
2067 case MTHK_EXTRA_VIEWPORT
: ShowExtraViewPortWindowForTileUnderCursor(); break;
2068 #ifdef ENABLE_NETWORK
2069 case MTHK_CLIENT_LIST
: if (_networking
) ShowClientList(); break;
2071 case MTHK_SIGN_LIST
: ShowSignList(); break;
2072 default: return ES_NOT_HANDLED
;
2077 virtual void OnPlaceObject(Point pt
, TileIndex tile
)
2079 switch (_last_started_action
) {
2080 case CBF_PLACE_SIGN
:
2081 PlaceProc_Sign(tile
);
2084 case CBF_PLACE_LANDINFO
:
2088 default: NOT_REACHED();
2092 virtual void OnPlaceObjectAbort()
2094 _last_started_action
= CBF_NONE
;
2097 virtual void OnTick()
2099 if (this->IsWidgetLowered(WID_TN_PAUSE
) != !!_pause_mode
) {
2100 this->ToggleWidgetLoweredState(WID_TN_PAUSE
);
2101 this->SetWidgetDirty(WID_TN_PAUSE
);
2104 if (this->IsWidgetLowered(WID_TN_FAST_FORWARD
) != !!_fast_forward
) {
2105 this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD
);
2106 this->SetWidgetDirty(WID_TN_FAST_FORWARD
);
2110 virtual void OnTimeout()
2112 /* We do not want to automatically raise the pause, fast forward and
2113 * switchbar buttons; they have to stay down when pressed etc. */
2114 for (uint i
= WID_TN_SETTINGS
; i
< WID_TN_SWITCH_BAR
; i
++) {
2115 if (this->IsWidgetLowered(i
)) {
2116 this->RaiseWidget(i
);
2117 this->SetWidgetDirty(i
);
2123 * Some data on this window has become invalid.
2124 * @param data Information about the changed data.
2125 * @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
2127 virtual void OnInvalidateData(int data
= 0, bool gui_scope
= true)
2129 if (!gui_scope
) return;
2130 if (FindWindowById(WC_MAIN_WINDOW
, 0) != NULL
) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW
, 0)->viewport
, WID_TN_ZOOM_IN
, WID_TN_ZOOM_OUT
);
2133 static HotkeyList hotkeys
;
2136 static const Hotkey maintoolbar_hotkeys
[] = {
2137 Hotkey ("pause", MTHK_PAUSE
, WKC_F1
, WKC_PAUSE
),
2138 Hotkey ("fastforward", MTHK_FASTFORWARD
),
2139 Hotkey ("settings", MTHK_SETTINGS
, WKC_F2
),
2140 Hotkey ("saveload", MTHK_SAVEGAME
, WKC_F3
),
2141 Hotkey ("load_game", MTHK_LOADGAME
),
2142 Hotkey ("smallmap", MTHK_SMALLMAP
, WKC_F4
, 'M'),
2143 Hotkey ("town_list", MTHK_TOWNDIRECTORY
, WKC_F5
),
2144 Hotkey ("subsidies", MTHK_SUBSIDIES
, WKC_F6
),
2145 Hotkey ("station_list", MTHK_STATIONS
, WKC_F7
),
2146 Hotkey ("finances", MTHK_FINANCES
, WKC_F8
),
2147 Hotkey ("companies", MTHK_COMPANIES
, WKC_F9
),
2148 Hotkey ("story_book", MTHK_STORY
),
2149 Hotkey ("goal_list", MTHK_GOAL
),
2150 Hotkey ("graphs", MTHK_GRAPHS
, WKC_F10
),
2151 Hotkey ("league", MTHK_LEAGUE
, WKC_F11
),
2152 Hotkey ("industry_list", MTHK_INDUSTRIES
, WKC_F12
),
2153 Hotkey ("train_list", MTHK_TRAIN_LIST
, WKC_SHIFT
| WKC_F1
),
2154 Hotkey ("roadveh_list", MTHK_ROADVEH_LIST
, WKC_SHIFT
| WKC_F2
),
2155 Hotkey ("ship_list", MTHK_SHIP_LIST
, WKC_SHIFT
| WKC_F3
),
2156 Hotkey ("aircraft_list", MTHK_AIRCRAFT_LIST
, WKC_SHIFT
| WKC_F4
),
2157 Hotkey ("zoomin", MTHK_ZOOM_IN
, WKC_SHIFT
| WKC_F5
, WKC_NUM_PLUS
, WKC_EQUALS
, WKC_SHIFT
| WKC_EQUALS
),
2158 Hotkey ("zoomout", MTHK_ZOOM_OUT
, WKC_SHIFT
| WKC_F6
, WKC_NUM_MINUS
, WKC_MINUS
, WKC_SHIFT
| WKC_MINUS
),
2159 Hotkey ("build_rail", MTHK_BUILD_RAIL
, WKC_SHIFT
| WKC_F7
),
2160 Hotkey ("build_road", MTHK_BUILD_ROAD
, WKC_SHIFT
| WKC_F8
),
2161 Hotkey ("build_docks", MTHK_BUILD_DOCKS
, WKC_SHIFT
| WKC_F9
),
2162 Hotkey ("build_airport", MTHK_BUILD_AIRPORT
, WKC_SHIFT
| WKC_F10
),
2163 Hotkey ("build_trees", MTHK_BUILD_TREES
, WKC_SHIFT
| WKC_F11
),
2164 Hotkey ("music", MTHK_MUSIC
, WKC_SHIFT
| WKC_F12
),
2165 Hotkey ("ai_debug", MTHK_AI_DEBUG
),
2166 Hotkey ("small_screenshot", MTHK_SMALL_SCREENSHOT
, WKC_CTRL
| 'S'),
2167 Hotkey ("zoomedin_screenshot", MTHK_ZOOMEDIN_SCREENSHOT
, WKC_CTRL
| 'P'),
2168 Hotkey ("defaultzoom_screenshot", MTHK_DEFAULTZOOM_SCREENSHOT
, WKC_CTRL
| 'D'),
2169 Hotkey ("giant_screenshot", MTHK_GIANT_SCREENSHOT
),
2170 Hotkey ("cheats", MTHK_CHEATS
, WKC_CTRL
| WKC_ALT
| 'C'),
2171 Hotkey ("terraform", MTHK_TERRAFORM
, 'L'),
2172 Hotkey ("extra_viewport", MTHK_EXTRA_VIEWPORT
, 'V'),
2173 #ifdef ENABLE_NETWORK
2174 Hotkey ("client_list", MTHK_CLIENT_LIST
),
2176 Hotkey ("sign_list", MTHK_SIGN_LIST
),
2178 HotkeyList
MainToolbarWindow::hotkeys("maintoolbar", maintoolbar_hotkeys
);
2180 static NWidgetBase
*MakeMainToolbar(int *biggest_index
)
2182 /** Sprites to use for the different toolbar buttons */
2183 static const SpriteID toolbar_button_sprites
[] = {
2184 SPR_IMG_PAUSE
, // WID_TN_PAUSE
2185 SPR_IMG_FASTFORWARD
, // WID_TN_FAST_FORWARD
2186 SPR_IMG_SETTINGS
, // WID_TN_SETTINGS
2187 SPR_IMG_SAVE
, // WID_TN_SAVE
2188 SPR_IMG_SMALLMAP
, // WID_TN_SMALL_MAP
2189 SPR_IMG_TOWN
, // WID_TN_TOWNS
2190 SPR_IMG_SUBSIDIES
, // WID_TN_SUBSIDIES
2191 SPR_IMG_COMPANY_LIST
, // WID_TN_STATIONS
2192 SPR_IMG_COMPANY_FINANCE
, // WID_TN_FINANCES
2193 SPR_IMG_COMPANY_GENERAL
, // WID_TN_COMPANIES
2194 SPR_IMG_STORY_BOOK
, // WID_TN_STORY
2195 SPR_IMG_GOAL
, // WID_TN_GOAL
2196 SPR_IMG_GRAPHS
, // WID_TN_GRAPHS
2197 SPR_IMG_COMPANY_LEAGUE
, // WID_TN_LEAGUE
2198 SPR_IMG_INDUSTRY
, // WID_TN_INDUSTRIES
2199 SPR_IMG_TRAINLIST
, // WID_TN_TRAINS
2200 SPR_IMG_TRUCKLIST
, // WID_TN_ROADVEHS
2201 SPR_IMG_SHIPLIST
, // WID_TN_SHIPS
2202 SPR_IMG_AIRPLANESLIST
, // WID_TN_AIRCRAFT
2203 SPR_IMG_ZOOMIN
, // WID_TN_ZOOMIN
2204 SPR_IMG_ZOOMOUT
, // WID_TN_ZOOMOUT
2205 SPR_IMG_BUILDRAIL
, // WID_TN_RAILS
2206 SPR_IMG_BUILDROAD
, // WID_TN_ROADS
2207 SPR_IMG_BUILDWATER
, // WID_TN_WATER
2208 SPR_IMG_BUILDAIR
, // WID_TN_AIR
2209 SPR_IMG_LANDSCAPING
, // WID_TN_LANDSCAPE
2210 SPR_IMG_MUSIC
, // WID_TN_MUSIC_SOUND
2211 SPR_IMG_MESSAGES
, // WID_TN_MESSAGES
2212 SPR_IMG_QUERY
, // WID_TN_HELP
2213 SPR_IMG_SWITCH_TOOLBAR
, // WID_TN_SWITCH_BAR
2216 NWidgetMainToolbarContainer
*hor
= new NWidgetMainToolbarContainer();
2217 for (uint i
= 0; i
< WID_TN_END
; i
++) {
2219 case WID_TN_SMALL_MAP
:
2220 case WID_TN_FINANCES
:
2221 case WID_TN_VEHICLE_START
:
2222 case WID_TN_ZOOM_IN
:
2223 case WID_TN_BUILDING_TOOLS_START
:
2224 case WID_TN_MUSIC_SOUND
:
2225 hor
->Add(new NWidgetSpacer(0, 0));
2228 hor
->Add(new NWidgetLeaf(i
== WID_TN_SAVE
? WWT_IMGBTN_2
: WWT_IMGBTN
, COLOUR_GREY
, i
, toolbar_button_sprites
[i
], STR_TOOLBAR_TOOLTIP_PAUSE_GAME
+ i
));
2231 *biggest_index
= max
<int>(*biggest_index
, WID_TN_SWITCH_BAR
);
2235 static const NWidgetPart _nested_toolbar_normal_widgets
[] = {
2236 NWidgetFunction(MakeMainToolbar
),
2239 static const WindowDesc
_toolb_normal_desc(
2241 WC_MAIN_TOOLBAR
, WC_NONE
,
2243 _nested_toolbar_normal_widgets
, lengthof(_nested_toolbar_normal_widgets
),
2244 NULL
, &MainToolbarWindow::hotkeys
2248 /* --- Toolbar handling for the scenario editor */
2250 static ToolbarButtonProc
* const _scen_toolbar_button_procs
[] = {
2252 ToolbarFastForwardClick
,
2253 ToolbarOptionsClick
,
2254 ToolbarScenSaveOrLoad
,
2256 ToolbarScenDatePanel
,
2257 ToolbarScenDateBackward
,
2258 ToolbarScenDateForward
,
2259 ToolbarScenMapTownDir
,
2261 ToolbarZoomOutClick
,
2264 ToolbarScenGenIndustry
,
2265 ToolbarScenBuildRoad
,
2266 ToolbarScenBuildDocks
,
2267 ToolbarScenPlantTrees
,
2268 ToolbarScenPlaceSign
,
2283 enum MainToolbarEditorHotkeys
{
2297 MTEHK_SMALL_SCREENSHOT
,
2298 MTEHK_ZOOMEDIN_SCREENSHOT
,
2299 MTEHK_DEFAULTZOOM_SCREENSHOT
,
2300 MTEHK_GIANT_SCREENSHOT
,
2305 MTEHK_EXTRA_VIEWPORT
,
2308 struct ScenarioEditorToolbarWindow
: Window
{
2309 ScenarioEditorToolbarWindow (const WindowDesc
*desc
) : Window (desc
)
2311 this->InitNested(0);
2313 _last_started_action
= CBF_NONE
;
2314 CLRBITS(this->flags
, WF_WHITE_BORDER
);
2315 PositionMainToolbar(this);
2316 this->InvalidateData();
2319 virtual void FindWindowPlacementAndResize(int def_width
, int def_height
)
2321 Window::FindWindowPlacementAndResize(_toolbar_width
, def_height
);
2324 void OnPaint (BlitArea
*dpi
) OVERRIDE
2326 this->SetWidgetDisabledState(WID_TE_DATE_BACKWARD
, _settings_game
.game_creation
.starting_year
<= MIN_YEAR
);
2327 this->SetWidgetDisabledState(WID_TE_DATE_FORWARD
, _settings_game
.game_creation
.starting_year
>= MAX_YEAR
);
2329 this->DrawWidgets (dpi
);
2332 void DrawWidget (BlitArea
*dpi
, const Rect
&r
, int widget
) const OVERRIDE
2336 SetDParam(0, ConvertYMDToDate(_settings_game
.game_creation
.starting_year
, 0, 1));
2337 DrawString (dpi
, r
.left
, r
.right
, (this->height
- FONT_HEIGHT_NORMAL
) / 2, STR_WHITE_DATE_LONG
, TC_FROMSTRING
, SA_HOR_CENTER
);
2340 case WID_TE_SPACER
: {
2341 int height
= r
.bottom
- r
.top
;
2342 if (height
> 2 * FONT_HEIGHT_NORMAL
) {
2343 DrawString (dpi
, r
.left
, r
.right
, (height
+ 1) / 2 - FONT_HEIGHT_NORMAL
, STR_SCENEDIT_TOOLBAR_OPENTTD
, TC_FROMSTRING
, SA_HOR_CENTER
);
2344 DrawString (dpi
, r
.left
, r
.right
, (height
+ 1) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
, TC_FROMSTRING
, SA_HOR_CENTER
);
2346 DrawString (dpi
, r
.left
, r
.right
, (height
- FONT_HEIGHT_NORMAL
) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
, TC_FROMSTRING
, SA_HOR_CENTER
);
2353 virtual void UpdateWidgetSize(int widget
, Dimension
*size
, const Dimension
&padding
, Dimension
*fill
, Dimension
*resize
)
2357 size
->width
= max(GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_OPENTTD
).width
, GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
).width
) + WD_FRAMERECT_LEFT
+ WD_FRAMERECT_RIGHT
;
2361 SetDParam(0, ConvertYMDToDate(MAX_YEAR
, 0, 1));
2362 *size
= GetStringBoundingBox(STR_WHITE_DATE_LONG
);
2363 size
->height
= max(size
->height
, GetSpriteSize(SPR_IMG_SAVE
).height
+ WD_IMGBTN_TOP
+ WD_IMGBTN_BOTTOM
);
2368 virtual void OnClick(Point pt
, int widget
, int click_count
)
2370 if (_game_mode
== GM_MENU
) return;
2371 CallBackFunction cbf
= _scen_toolbar_button_procs
[widget
](this);
2372 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
2375 virtual void OnDropdownSelect(int widget
, int index
)
2377 /* The map button is in a different location on the scenario
2378 * editor toolbar, so we need to adjust for it. */
2379 if (widget
== WID_TE_SMALL_MAP
) widget
= WID_TN_SMALL_MAP
;
2380 CallBackFunction cbf
= _menu_clicked_procs
[widget
](index
);
2381 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
2382 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
2385 virtual EventState
OnHotkey(int hotkey
)
2387 CallBackFunction cbf
= CBF_NONE
;
2389 case MTEHK_PAUSE
: ToolbarPauseClick(this); break;
2390 case MTEHK_FASTFORWARD
: ToolbarFastForwardClick(this); break;
2391 case MTEHK_SETTINGS
: ShowGameOptions(); break;
2392 case MTEHK_SAVEGAME
: MenuClickSaveLoad(); break;
2393 case MTEHK_GENLAND
: ToolbarScenGenLand(this); break;
2394 case MTEHK_GENTOWN
: ToolbarScenGenTown(this); break;
2395 case MTEHK_GENINDUSTRY
: ToolbarScenGenIndustry(this); break;
2396 case MTEHK_BUILD_ROAD
: ToolbarScenBuildRoad(this); break;
2397 case MTEHK_BUILD_DOCKS
: ToolbarScenBuildDocks(this); break;
2398 case MTEHK_BUILD_TREES
: ToolbarScenPlantTrees(this); break;
2399 case MTEHK_SIGN
: cbf
= ToolbarScenPlaceSign(this); break;
2400 case MTEHK_MUSIC
: ShowMusicWindow(); break;
2401 case MTEHK_LANDINFO
: cbf
= PlaceLandBlockInfo(); break;
2402 case MTEHK_SMALL_SCREENSHOT
: MenuClickSmallScreenshot(); break;
2403 case MTEHK_ZOOMEDIN_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN
); break;
2404 case MTEHK_DEFAULTZOOM_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM
); break;
2405 case MTEHK_GIANT_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_WORLD
); break;
2406 case MTEHK_ZOOM_IN
: ToolbarZoomInClick(this); break;
2407 case MTEHK_ZOOM_OUT
: ToolbarZoomOutClick(this); break;
2408 case MTEHK_TERRAFORM
: ShowEditorTerraformToolbar(); break;
2409 case MTEHK_SMALLMAP
: ShowSmallMap(); break;
2410 case MTEHK_EXTRA_VIEWPORT
: ShowExtraViewPortWindowForTileUnderCursor(); break;
2411 default: return ES_NOT_HANDLED
;
2413 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
2417 virtual void OnPlaceObject(Point pt
, TileIndex tile
)
2419 switch (_last_started_action
) {
2420 case CBF_PLACE_SIGN
:
2421 PlaceProc_Sign(tile
);
2424 case CBF_PLACE_LANDINFO
:
2428 default: NOT_REACHED();
2432 virtual void OnPlaceObjectAbort()
2434 _last_started_action
= CBF_NONE
;
2437 virtual void OnTimeout()
2439 this->SetWidgetsLoweredState(false, WID_TE_DATE_BACKWARD
, WID_TE_DATE_FORWARD
, WIDGET_LIST_END
);
2440 this->SetWidgetDirty(WID_TE_DATE_BACKWARD
);
2441 this->SetWidgetDirty(WID_TE_DATE_FORWARD
);
2444 virtual void OnTick()
2446 if (this->IsWidgetLowered(WID_TE_PAUSE
) != !!_pause_mode
) {
2447 this->ToggleWidgetLoweredState(WID_TE_PAUSE
);
2451 if (this->IsWidgetLowered(WID_TE_FAST_FORWARD
) != !!_fast_forward
) {
2452 this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD
);
2458 * Some data on this window has become invalid.
2459 * @param data Information about the changed data.
2460 * @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
2462 virtual void OnInvalidateData(int data
= 0, bool gui_scope
= true)
2464 if (!gui_scope
) return;
2465 if (FindWindowById(WC_MAIN_WINDOW
, 0) != NULL
) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW
, 0)->viewport
, WID_TE_ZOOM_IN
, WID_TE_ZOOM_OUT
);
2468 virtual void OnQueryTextFinished(char *str
)
2470 /* Was 'cancel' pressed? */
2471 if (str
== NULL
) return;
2474 if (!StrEmpty(str
)) {
2477 /* An empty string means revert to the default */
2478 value
= DEF_START_YEAR
;
2480 SetStartingYear(value
);
2485 static HotkeyList hotkeys
;
2488 static const Hotkey scenedit_maintoolbar_hotkeys
[] = {
2489 Hotkey ("pause", MTEHK_PAUSE
, WKC_F1
, WKC_PAUSE
),
2490 Hotkey ("fastforward", MTEHK_FASTFORWARD
),
2491 Hotkey ("settings", MTEHK_SETTINGS
, WKC_F2
),
2492 Hotkey ("saveload", MTEHK_SAVEGAME
, WKC_F3
),
2493 Hotkey ("gen_land", MTEHK_GENLAND
, WKC_F4
),
2494 Hotkey ("gen_town", MTEHK_GENTOWN
, WKC_F5
),
2495 Hotkey ("gen_industry", MTEHK_GENINDUSTRY
, WKC_F6
),
2496 Hotkey ("build_road", MTEHK_BUILD_ROAD
, WKC_F7
),
2497 Hotkey ("build_docks", MTEHK_BUILD_DOCKS
, WKC_F8
),
2498 Hotkey ("build_trees", MTEHK_BUILD_TREES
, WKC_F9
),
2499 Hotkey ("build_sign", MTEHK_SIGN
, WKC_F10
),
2500 Hotkey ("music", MTEHK_MUSIC
, WKC_F11
),
2501 Hotkey ("land_info", MTEHK_LANDINFO
, WKC_F12
),
2502 Hotkey ("small_screenshot", MTEHK_SMALL_SCREENSHOT
, WKC_CTRL
| 'S'),
2503 Hotkey ("zoomedin_screenshot", MTEHK_ZOOMEDIN_SCREENSHOT
, WKC_CTRL
| 'P'),
2504 Hotkey ("defaultzoom_screenshot", MTEHK_DEFAULTZOOM_SCREENSHOT
, WKC_CTRL
| 'D'),
2505 Hotkey ("giant_screenshot", MTEHK_GIANT_SCREENSHOT
),
2506 Hotkey ("zoomin", MTEHK_ZOOM_IN
, WKC_SHIFT
| WKC_F5
, WKC_NUM_PLUS
, WKC_EQUALS
, WKC_SHIFT
| WKC_EQUALS
),
2507 Hotkey ("zoomout", MTEHK_ZOOM_OUT
, WKC_SHIFT
| WKC_F6
, WKC_NUM_MINUS
, WKC_MINUS
, WKC_SHIFT
| WKC_MINUS
),
2508 Hotkey ("terraform", MTEHK_TERRAFORM
, 'L'),
2509 Hotkey ("smallmap", MTEHK_SMALLMAP
, 'M'),
2510 Hotkey ("extra_viewport", MTEHK_EXTRA_VIEWPORT
, 'V'),
2512 HotkeyList
ScenarioEditorToolbarWindow::hotkeys("scenedit_maintoolbar", scenedit_maintoolbar_hotkeys
);
2514 static const NWidgetPart _nested_toolb_scen_inner_widgets
[] = {
2515 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_PAUSE
), SetDataTip(SPR_IMG_PAUSE
, STR_TOOLBAR_TOOLTIP_PAUSE_GAME
),
2516 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_FAST_FORWARD
), SetDataTip(SPR_IMG_FASTFORWARD
, STR_TOOLBAR_TOOLTIP_FORWARD
),
2517 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_SETTINGS
), SetDataTip(SPR_IMG_SETTINGS
, STR_TOOLBAR_TOOLTIP_OPTIONS
),
2518 NWidget(WWT_IMGBTN_2
, COLOUR_GREY
, WID_TE_SAVE
), SetDataTip(SPR_IMG_SAVE
, STR_SCENEDIT_TOOLBAR_TOOLTIP_SAVE_SCENARIO_LOAD_SCENARIO
),
2519 NWidget(NWID_SPACER
),
2520 NWidget(WWT_PANEL
, COLOUR_GREY
, WID_TE_SPACER
), EndContainer(),
2521 NWidget(NWID_SPACER
),
2522 NWidget(WWT_PANEL
, COLOUR_GREY
, WID_TE_DATE_PANEL
),
2523 NWidget(NWID_HORIZONTAL
), SetPIP(3, 2, 3),
2524 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_DATE_BACKWARD
), SetDataTip(SPR_ARROW_DOWN
, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD
),
2525 NWidget(WWT_EMPTY
, COLOUR_GREY
, WID_TE_DATE
), SetDataTip(STR_NULL
, STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE
),
2526 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_DATE_FORWARD
), SetDataTip(SPR_ARROW_UP
, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD
),
2529 NWidget(NWID_SPACER
),
2530 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_SMALL_MAP
), SetDataTip(SPR_IMG_SMALLMAP
, STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY
),
2531 NWidget(NWID_SPACER
),
2532 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_ZOOM_IN
), SetDataTip(SPR_IMG_ZOOMIN
, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN
),
2533 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_ZOOM_OUT
), SetDataTip(SPR_IMG_ZOOMOUT
, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT
),
2534 NWidget(NWID_SPACER
),
2535 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_LAND_GENERATE
), SetDataTip(SPR_IMG_LANDSCAPING
, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION
),
2536 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_TOWN_GENERATE
), SetDataTip(SPR_IMG_TOWN
, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION
),
2537 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_INDUSTRY
), SetDataTip(SPR_IMG_INDUSTRY
, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION
),
2538 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_ROADS
), SetDataTip(SPR_IMG_BUILDROAD
, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION
),
2539 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_WATER
), SetDataTip(SPR_IMG_BUILDWATER
, STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS
),
2540 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_TREES
), SetDataTip(SPR_IMG_PLANTTREES
, STR_SCENEDIT_TOOLBAR_PLANT_TREES
),
2541 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_SIGNS
), SetDataTip(SPR_IMG_SIGN
, STR_SCENEDIT_TOOLBAR_PLACE_SIGN
),
2542 NWidget(NWID_SPACER
),
2543 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_MUSIC_SOUND
), SetDataTip(SPR_IMG_MUSIC
, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW
),
2544 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_HELP
), SetDataTip(SPR_IMG_QUERY
, STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION
),
2545 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_SWITCH_BAR
), SetDataTip(SPR_IMG_SWITCH_TOOLBAR
, STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR
),
2548 static NWidgetBase
*MakeScenarioToolbar(int *biggest_index
)
2550 return MakeNWidgets(_nested_toolb_scen_inner_widgets
, lengthof(_nested_toolb_scen_inner_widgets
), biggest_index
, new NWidgetScenarioToolbarContainer());
2553 static const NWidgetPart _nested_toolb_scen_widgets
[] = {
2554 NWidgetFunction(MakeScenarioToolbar
),
2557 static const WindowDesc
_toolb_scen_desc(
2559 WC_MAIN_TOOLBAR
, WC_NONE
,
2561 _nested_toolb_scen_widgets
, lengthof(_nested_toolb_scen_widgets
),
2562 NULL
, &ScenarioEditorToolbarWindow::hotkeys
2565 /** Allocate the toolbar. */
2566 void AllocateToolbar()
2568 /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
2569 _last_built_roadtype
= ROADTYPE_ROAD
;
2571 if (_game_mode
== GM_EDITOR
) {
2572 new ScenarioEditorToolbarWindow(&_toolb_scen_desc
);
2574 new MainToolbarWindow(&_toolb_normal_desc
);