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"
50 #include "plans_func.h"
53 #include "widgets/toolbar_widget.h"
55 #include "network/network.h"
56 #include "network/network_gui.h"
57 #include "network/network_func.h"
59 #include "safeguards.h"
62 /** Width of the toolbar, shared by statusbar. */
63 uint _toolbar_width
= 0;
65 RailType _last_built_railtype
;
66 RoadType _last_built_roadtype
;
68 static ScreenshotType _confirmed_screenshot_type
; ///< Screenshot type the current query is about to confirm.
77 /** Callback functions. */
78 enum CallBackFunction
{
84 static CallBackFunction _last_started_action
= CBF_NONE
; ///< Last started user action.
88 * Drop down list entry for showing a checked/unchecked toggle item.
90 class DropDownListCheckedItem
: public DropDownListStringItem
{
95 DropDownListCheckedItem(StringID string
, int result
, bool masked
, bool checked
) : DropDownListStringItem(string
, result
, masked
), checked(checked
)
97 this->checkmark_width
= GetStringBoundingBox(STR_JUST_CHECKMARK
).width
+ 3;
100 virtual ~DropDownListCheckedItem() {}
104 return DropDownListStringItem::Width() + this->checkmark_width
;
107 void Draw(int left
, int right
, int top
, int bottom
, bool sel
, int bg_colour
) const
109 bool rtl
= _current_text_dir
== TD_RTL
;
111 DrawString(left
+ WD_FRAMERECT_LEFT
, right
- WD_FRAMERECT_RIGHT
, top
, STR_JUST_CHECKMARK
, sel
? TC_WHITE
: TC_BLACK
);
113 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
);
118 * Drop down list entry for showing a company entry, with companies 'blob'.
120 class DropDownListCompanyItem
: public DropDownListItem
{
125 DropDownListCompanyItem(int result
, bool masked
, bool greyed
) : DropDownListItem(result
, masked
), greyed(greyed
)
127 this->icon_size
= GetSpriteSize(SPR_COMPANY_ICON
);
130 virtual ~DropDownListCompanyItem() {}
132 bool Selectable() const
139 CompanyID company
= (CompanyID
)this->result
;
140 SetDParam(0, company
);
141 SetDParam(1, company
);
142 return GetStringBoundingBox(STR_COMPANY_NAME_COMPANY_NUM
).width
+ this->icon_size
.width
+ 3;
145 uint
Height(uint width
) const
147 return max(this->icon_size
.height
+ 2U, (uint
)FONT_HEIGHT_NORMAL
);
150 void Draw(int left
, int right
, int top
, int bottom
, bool sel
, int bg_colour
) const
152 CompanyID company
= (CompanyID
)this->result
;
153 bool rtl
= _current_text_dir
== TD_RTL
;
155 /* It's possible the company is deleted while the dropdown is open */
156 if (!Company::IsValidID(company
)) return;
158 int icon_offset
= (bottom
- top
- icon_size
.height
) / 2;
159 int text_offset
= (bottom
- top
- FONT_HEIGHT_NORMAL
) / 2;
161 DrawCompanyIcon(company
, rtl
? right
- this->icon_size
.width
- WD_FRAMERECT_RIGHT
: left
+ WD_FRAMERECT_LEFT
, top
+ icon_offset
);
163 SetDParam(0, company
);
164 SetDParam(1, company
);
167 col
= (sel
? TC_SILVER
: TC_GREY
) | TC_NO_SHADE
;
169 col
= sel
? TC_WHITE
: TC_BLACK
;
171 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
);
176 * Pop up a generic text only menu.
178 * @param widget Toolbar button
179 * @param list List of items
180 * @param def Default item
182 static void PopupMainToolbMenu(Window
*w
, int widget
, DropDownList
*list
, int def
)
184 ShowDropDownList(w
, list
, def
, widget
, 0, true, true);
185 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
189 * Pop up a generic text only menu.
191 * @param widget Toolbar button
192 * @param string String for the first item in the menu
193 * @param count Number of items in the menu
195 static void PopupMainToolbMenu(Window
*w
, int widget
, StringID string
, int count
)
197 DropDownList
*list
= new DropDownList();
198 for (int i
= 0; i
< count
; i
++) {
199 *list
->Append() = new DropDownListStringItem(string
+ i
, i
, false);
201 PopupMainToolbMenu(w
, widget
, list
, 0);
204 /** Enum for the Company Toolbar's network related buttons */
205 static const int CTMN_CLIENT_LIST
= -1; ///< Show the client list
206 static const int CTMN_NEW_COMPANY
= -2; ///< Create a new company
207 static const int CTMN_SPECTATE
= -3; ///< Become spectator
208 static const int CTMN_SPECTATOR
= -4; ///< Show a company window as spectator
211 * Pop up a generic company list menu.
212 * @param w The toolbar window.
213 * @param widget The button widget id.
214 * @param grey A bitbask of which items to mark as disabled.
215 * @param include_spectator If true, a spectator option is included in the list.
217 static void PopupMainCompanyToolbMenu(Window
*w
, int widget
, int grey
= 0, bool include_spectator
= false)
219 DropDownList
*list
= new DropDownList();
221 #ifdef ENABLE_NETWORK
223 if (widget
== WID_TN_COMPANIES
) {
224 /* Add the client list button for the companies menu */
225 *list
->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST
, CTMN_CLIENT_LIST
, false);
228 if (include_spectator
) {
229 if (widget
== WID_TN_COMPANIES
) {
230 if (_local_company
== COMPANY_SPECTATOR
) {
231 *list
->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY
, CTMN_NEW_COMPANY
, NetworkMaxCompaniesReached());
233 *list
->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE
, CTMN_SPECTATE
, NetworkMaxSpectatorsReached());
236 *list
->Append() = new DropDownListStringItem(STR_NETWORK_TOOLBAR_LIST_SPECTATOR
, CTMN_SPECTATOR
, false);
240 #endif /* ENABLE_NETWORK */
242 for (CompanyID c
= COMPANY_FIRST
; c
< MAX_COMPANIES
; c
++) {
243 if (!Company::IsValidID(c
)) continue;
244 *list
->Append() = new DropDownListCompanyItem(c
, false, HasBit(grey
, c
));
247 PopupMainToolbMenu(w
, widget
, list
, _local_company
== COMPANY_SPECTATOR
? CTMN_CLIENT_LIST
: (int)_local_company
);
251 static ToolbarMode _toolbar_mode
;
253 static CallBackFunction
SelectSignTool()
255 if (_last_started_action
== CBF_PLACE_SIGN
) {
256 ResetObjectToPlace();
259 SetObjectToPlace(SPR_CURSOR_SIGN
, PAL_NONE
, HT_RECT
, WC_MAIN_TOOLBAR
, 0);
260 return CBF_PLACE_SIGN
;
264 /* --- Pausing --- */
266 static CallBackFunction
ToolbarPauseClick(Window
*w
)
268 if (_networking
&& !_network_server
) return CBF_NONE
; // only server can pause the game
270 if (DoCommandP(0, PM_PAUSED_NORMAL
, _pause_mode
== PM_UNPAUSED
, CMD_PAUSE
)) {
271 if (_settings_client
.sound
.confirm
) SndPlayFx(SND_15_BEEP
);
277 * Toggle fast forward mode.
282 static CallBackFunction
ToolbarFastForwardClick(Window
*w
)
284 _fast_forward
^= true;
285 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
290 * Game Option button menu entries.
292 enum OptionMenuEntries
{
300 OME_SHOW_STATIONNAMES
,
301 OME_SHOW_WAYPOINTNAMES
,
303 OME_SHOW_COMPETITOR_SIGNS
,
307 OME_TRANSPARENTBUILDINGS
,
308 OME_SHOW_STATIONSIGNS
,
312 * Handle click on Options button in toolbar.
314 * @param w parent window the shown Drop down list is attached to.
317 static CallBackFunction
ToolbarOptionsClick(Window
*w
)
319 DropDownList
*list
= new DropDownList();
320 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS
, OME_GAMEOPTIONS
, false);
321 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE
, OME_SETTINGS
, false);
322 /* Changes to the per-AI settings don't get send from the server to the clients. Clients get
323 * the settings once they join but never update it. As such don't show the window at all
324 * to network clients. */
325 if (!_networking
|| _network_server
) *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS
, OME_SCRIPT_SETTINGS
, false);
326 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS
, OME_NEWGRFSETTINGS
, false);
327 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_ZONING
, OME_ZONING
, false);
328 *list
->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS
, OME_TRANSPARENCIES
, false);
329 *list
->Append() = new DropDownListItem(-1, false);
330 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED
, OME_SHOW_TOWNNAMES
, false, HasBit(_display_opt
, DO_SHOW_TOWN_NAMES
));
331 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED
, OME_SHOW_STATIONNAMES
, false, HasBit(_display_opt
, DO_SHOW_STATION_NAMES
));
332 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED
, OME_SHOW_WAYPOINTNAMES
, false, HasBit(_display_opt
, DO_SHOW_WAYPOINT_NAMES
));
333 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED
, OME_SHOW_SIGNS
, false, HasBit(_display_opt
, DO_SHOW_SIGNS
));
334 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS
, OME_SHOW_COMPETITOR_SIGNS
, false, HasBit(_display_opt
, DO_SHOW_COMPETITOR_SIGNS
));
335 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION
, OME_FULL_ANIMATION
, false, HasBit(_display_opt
, DO_FULL_ANIMATION
));
336 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_RAIL_FENCES
, OME_RAIL_FENCES
, false, HasBit(_display_opt
, DO_RAIL_FENCES
));
337 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL
, OME_FULL_DETAILS
, false, HasBit(_display_opt
, DO_FULL_DETAIL
));
338 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS
, OME_TRANSPARENTBUILDINGS
, false, IsTransparencySet(TO_HOUSES
));
339 *list
->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS
, OME_SHOW_STATIONSIGNS
, false, IsTransparencySet(TO_SIGNS
));
341 ShowDropDownList(w
, list
, 0, WID_TN_SETTINGS
, 140, true, true);
342 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
347 * Handle click on one of the entries in the Options button menu.
349 * @param index Index being clicked.
352 static CallBackFunction
MenuClickSettings(int index
)
355 case OME_GAMEOPTIONS
: ShowGameOptions(); return CBF_NONE
;
356 case OME_SETTINGS
: ShowGameSettings(); return CBF_NONE
;
357 case OME_SCRIPT_SETTINGS
: ShowAIConfigWindow(); return CBF_NONE
;
358 case OME_NEWGRFSETTINGS
: ShowNewGRFSettings(!_networking
&& _settings_client
.gui
.UserIsAllowedToChangeNewGRFs(), true, true, &_grfconfig
); return CBF_NONE
;
359 case OME_ZONING
: ShowZoningToolbar(); break;
360 case OME_TRANSPARENCIES
: ShowTransparencyToolbar(); break;
362 case OME_SHOW_TOWNNAMES
: ToggleBit(_display_opt
, DO_SHOW_TOWN_NAMES
); break;
363 case OME_SHOW_STATIONNAMES
: ToggleBit(_display_opt
, DO_SHOW_STATION_NAMES
); break;
364 case OME_SHOW_WAYPOINTNAMES
: ToggleBit(_display_opt
, DO_SHOW_WAYPOINT_NAMES
); break;
365 case OME_SHOW_SIGNS
: ToggleBit(_display_opt
, DO_SHOW_SIGNS
); break;
366 case OME_SHOW_COMPETITOR_SIGNS
:
367 ToggleBit(_display_opt
, DO_SHOW_COMPETITOR_SIGNS
);
368 InvalidateWindowClassesData(WC_SIGN_LIST
, -1);
370 case OME_FULL_ANIMATION
: ToggleBit(_display_opt
, DO_FULL_ANIMATION
); CheckBlitter(); break;
371 case OME_RAIL_FENCES
: ToggleBit(_display_opt
, DO_RAIL_FENCES
); break;
372 case OME_FULL_DETAILS
: ToggleBit(_display_opt
, DO_FULL_DETAIL
); break;
373 case OME_TRANSPARENTBUILDINGS
: ToggleTransparency(TO_HOUSES
); break;
374 case OME_SHOW_STATIONSIGNS
: ToggleTransparency(TO_SIGNS
); break;
376 MarkWholeScreenDirty();
381 * SaveLoad entries in scenario editor mode.
383 enum SaveLoadEditorMenuEntries
{
384 SLEME_SAVE_SCENARIO
= 0,
386 SLEME_SAVE_HEIGHTMAP
,
387 SLEME_LOAD_HEIGHTMAP
,
394 * SaveLoad entries in normal game mode.
396 enum SaveLoadNormalMenuEntries
{
405 * Handle click on Save button in toolbar in normal game mode.
407 * @param w parent window the shown save dialogue is attached to.
410 static CallBackFunction
ToolbarSaveClick(Window
*w
)
412 PopupMainToolbMenu(w
, WID_TN_SAVE
, STR_FILE_MENU_SAVE_GAME
, SLNME_MENUCOUNT
);
417 * Handle click on SaveLoad button in toolbar in the scenario editor.
419 * @param w parent window the shown save dialogue is attached to.
422 static CallBackFunction
ToolbarScenSaveOrLoad(Window
*w
)
424 PopupMainToolbMenu(w
, WID_TE_SAVE
, STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO
, SLEME_MENUCOUNT
);
429 * Handle click on one of the entries in the SaveLoad menu.
431 * @param index Index being clicked.
434 static CallBackFunction
MenuClickSaveLoad(int index
= 0)
436 if (_game_mode
== GM_EDITOR
) {
438 case SLEME_SAVE_SCENARIO
: ShowSaveLoadDialog(FT_SCENARIO
, SLO_SAVE
); break;
439 case SLEME_LOAD_SCENARIO
: ShowSaveLoadDialog(FT_SCENARIO
, SLO_LOAD
); break;
440 case SLEME_SAVE_HEIGHTMAP
: ShowSaveLoadDialog(FT_HEIGHTMAP
,SLO_SAVE
); break;
441 case SLEME_LOAD_HEIGHTMAP
: ShowSaveLoadDialog(FT_HEIGHTMAP
,SLO_LOAD
); break;
442 case SLEME_EXIT_TOINTRO
: AskExitToGameMenu(); break;
443 case SLEME_EXIT_GAME
: HandleExitGameRequest(); break;
447 case SLNME_SAVE_GAME
: ShowSaveLoadDialog(FT_SAVEGAME
, SLO_SAVE
); break;
448 case SLNME_LOAD_GAME
: ShowSaveLoadDialog(FT_SAVEGAME
, SLO_LOAD
); break;
449 case SLNME_EXIT_TOINTRO
: AskExitToGameMenu(); break;
450 case SLNME_EXIT_GAME
: HandleExitGameRequest(); break;
456 /* --- Map button menu --- */
458 enum MapMenuEntries
{
459 MME_SHOW_SMALLMAP
= 0,
460 MME_SHOW_EXTRAVIEWPORTS
,
463 MME_SHOW_TOWNDIRECTORY
,
464 MME_SHOW_INDUSTRYDIRECTORY
,
468 static CallBackFunction
ToolbarMapClick(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_LINGRAPH_LEGEND
, MME_SHOW_LINKGRAPH
, false);
474 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST
, MME_SHOW_SIGNLISTS
, false);
475 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_PLAN_LIST
, MME_SHOW_PLANS
, false);
476 PopupMainToolbMenu(w
, WID_TN_SMALL_MAP
, list
, 0);
480 static CallBackFunction
ToolbarScenMapTownDir(Window
*w
)
482 DropDownList
*list
= new DropDownList();
483 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD
, MME_SHOW_SMALLMAP
, false);
484 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT
, MME_SHOW_EXTRAVIEWPORTS
, false);
485 *list
->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST
, MME_SHOW_SIGNLISTS
, false);
486 *list
->Append() = new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY
, MME_SHOW_TOWNDIRECTORY
, false);
487 *list
->Append() = new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY
, MME_SHOW_INDUSTRYDIRECTORY
, false);
488 PopupMainToolbMenu(w
, WID_TE_SMALL_MAP
, list
, 0);
493 * Handle click on one of the entries in the Map menu.
495 * @param index Index being clicked.
498 static CallBackFunction
MenuClickMap(int index
)
501 case MME_SHOW_SMALLMAP
: ShowSmallMap(); break;
502 case MME_SHOW_EXTRAVIEWPORTS
: ShowExtraViewPortWindow(); break;
503 case MME_SHOW_LINKGRAPH
: ShowLinkGraphLegend(); break;
504 case MME_SHOW_SIGNLISTS
: ShowSignList(); break;
505 case MME_SHOW_TOWNDIRECTORY
: ShowTownDirectory(); break;
506 case MME_SHOW_INDUSTRYDIRECTORY
: ShowIndustryDirectory(); break;
507 case MME_SHOW_PLANS
: ShowPlansWindow(); break;
512 /* --- Town button menu --- */
514 static CallBackFunction
ToolbarTownClick(Window
*w
)
516 PopupMainToolbMenu(w
, WID_TN_TOWNS
, STR_TOWN_MENU_TOWN_DIRECTORY
, (_settings_game
.economy
.found_town
== TF_FORBIDDEN
) ? 1 : 2);
521 * Handle click on one of the entries in the Town menu.
523 * @param index Index being clicked.
526 static CallBackFunction
MenuClickTown(int index
)
529 case 0: ShowTownDirectory(); break;
530 case 1: // setting could be changed when the dropdown was open
531 if (_settings_game
.economy
.found_town
!= TF_FORBIDDEN
) ShowFoundTownWindow();
537 /* --- Subidies button menu --- */
539 static CallBackFunction
ToolbarSubsidiesClick(Window
*w
)
541 PopupMainToolbMenu(w
, WID_TN_SUBSIDIES
, STR_SUBSIDIES_MENU_SUBSIDIES
, 1);
546 * Handle click on the entry in the Subsidies menu.
548 * @param index Unused.
551 static CallBackFunction
MenuClickSubsidies(int index
)
554 case 0: ShowSubsidiesList(); break;
559 /* --- Stations button menu --- */
561 static CallBackFunction
ToolbarStationsClick(Window
*w
)
563 PopupMainCompanyToolbMenu(w
, WID_TN_STATIONS
);
568 * Handle click on the entry in the Stations menu
570 * @param index CompanyID to show station list for
573 static CallBackFunction
MenuClickStations(int index
)
575 ShowCompanyStations((CompanyID
)index
);
579 /* --- Finances button menu --- */
581 static CallBackFunction
ToolbarFinancesClick(Window
*w
)
583 PopupMainCompanyToolbMenu(w
, WID_TN_FINANCES
);
588 * Handle click on the entry in the finances overview menu.
590 * @param index CompanyID to show finances for.
593 static CallBackFunction
MenuClickFinances(int index
)
595 ShowCompanyFinances((CompanyID
)index
);
599 /* --- Company's button menu --- */
601 static CallBackFunction
ToolbarCompaniesClick(Window
*w
)
603 PopupMainCompanyToolbMenu(w
, WID_TN_COMPANIES
, 0, true);
608 * Handle click on the entry in the Company menu.
610 * @param index Menu entry to handle.
613 static CallBackFunction
MenuClickCompany(int index
)
615 #ifdef ENABLE_NETWORK
618 case CTMN_CLIENT_LIST
:
622 case CTMN_NEW_COMPANY
:
623 if (_network_server
) {
624 DoCommandP(0, 0, _network_own_client_id
, CMD_COMPANY_CTRL
);
626 NetworkSendCommand(0, 0, 0, CMD_COMPANY_CTRL
, nullptr, nullptr, _local_company
, 0);
631 if (_network_server
) {
632 NetworkServerDoMove(CLIENT_ID_SERVER
, COMPANY_SPECTATOR
);
633 MarkWholeScreenDirty();
635 NetworkClientRequestMove(COMPANY_SPECTATOR
);
640 #endif /* ENABLE_NETWORK */
641 ShowCompany((CompanyID
)index
);
645 /* --- Story button menu --- */
647 static CallBackFunction
ToolbarStoryClick(Window
*w
)
649 PopupMainCompanyToolbMenu(w
, WID_TN_STORY
, 0, true);
654 * Handle click on the entry in the Story menu
656 * @param index CompanyID to show story book for
659 static CallBackFunction
MenuClickStory(int index
)
661 ShowStoryBook(index
== CTMN_SPECTATOR
? INVALID_COMPANY
: (CompanyID
)index
);
665 /* --- Goal button menu --- */
667 static CallBackFunction
ToolbarGoalClick(Window
*w
)
669 PopupMainCompanyToolbMenu(w
, WID_TN_GOAL
, 0, true);
674 * Handle click on the entry in the Goal menu
676 * @param index CompanyID to show story book for
679 static CallBackFunction
MenuClickGoal(int index
)
681 ShowGoalsList(index
== CTMN_SPECTATOR
? INVALID_COMPANY
: (CompanyID
)index
);
685 /* --- Graphs button menu --- */
687 static CallBackFunction
ToolbarGraphsClick(Window
*w
)
689 PopupMainToolbMenu(w
, WID_TN_GRAPHS
, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH
, (_toolbar_mode
== TB_NORMAL
) ? 6 : 8);
694 * Handle click on the entry in the Graphs menu.
696 * @param index Graph to show.
699 static CallBackFunction
MenuClickGraphs(int index
)
702 case 0: ShowOperatingProfitGraph(); break;
703 case 1: ShowIncomeGraph(); break;
704 case 2: ShowDeliveredCargoGraph(); break;
705 case 3: ShowPerformanceHistoryGraph(); break;
706 case 4: ShowCompanyValueGraph(); break;
707 case 5: ShowCargoPaymentRates(); break;
708 /* functions for combined graphs/league button */
709 case 6: ShowCompanyLeagueTable(); break;
710 case 7: ShowPerformanceRatingDetail(); break;
715 /* --- League button menu --- */
717 static CallBackFunction
ToolbarLeagueClick(Window
*w
)
719 PopupMainToolbMenu(w
, WID_TN_LEAGUE
, STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE
, _networking
? 2 : 3);
724 * Handle click on the entry in the CompanyLeague menu.
726 * @param index Menu entry number.
729 static CallBackFunction
MenuClickLeague(int index
)
732 case 0: ShowCompanyLeagueTable(); break;
733 case 1: ShowPerformanceRatingDetail(); break;
734 case 2: ShowHighscoreTable(); break;
739 /* --- Industries button menu --- */
741 static CallBackFunction
ToolbarIndustryClick(Window
*w
)
743 /* Disable build-industry menu if we are a spectator */
744 PopupMainToolbMenu(w
, WID_TN_INDUSTRIES
, STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY
, (_local_company
== COMPANY_SPECTATOR
) ? 2 : 3);
749 * Handle click on the entry in the Industry menu.
751 * @param index Menu entry number.
754 static CallBackFunction
MenuClickIndustry(int index
)
757 case 0: ShowIndustryDirectory(); break;
758 case 1: ShowIndustryCargoesWindow(); break;
759 case 2: ShowBuildIndustryWindow(); break;
764 /* --- Trains button menu + 1 helper function for all vehicles. --- */
766 static void ToolbarVehicleClick(Window
*w
, VehicleType veh
)
771 FOR_ALL_VEHICLES(v
) {
772 if (v
->type
== veh
&& v
->IsPrimaryVehicle()) ClrBit(dis
, v
->owner
);
774 PopupMainCompanyToolbMenu(w
, WID_TN_VEHICLE_START
+ veh
, dis
);
778 static CallBackFunction
ToolbarTrainClick(Window
*w
)
780 ToolbarVehicleClick(w
, VEH_TRAIN
);
785 * Handle click on the entry in the Train menu.
787 * @param index CompanyID to show train list for.
790 static CallBackFunction
MenuClickShowTrains(int index
)
792 ShowVehicleListWindow((CompanyID
)index
, VEH_TRAIN
);
796 /* --- Road vehicle button menu --- */
798 static CallBackFunction
ToolbarRoadClick(Window
*w
)
800 ToolbarVehicleClick(w
, VEH_ROAD
);
805 * Handle click on the entry in the Road Vehicles menu.
807 * @param index CompanyID to show road vehicles list for.
810 static CallBackFunction
MenuClickShowRoad(int index
)
812 ShowVehicleListWindow((CompanyID
)index
, VEH_ROAD
);
816 /* --- Ship button menu --- */
818 static CallBackFunction
ToolbarShipClick(Window
*w
)
820 ToolbarVehicleClick(w
, VEH_SHIP
);
825 * Handle click on the entry in the Ships menu.
827 * @param index CompanyID to show ship list for.
830 static CallBackFunction
MenuClickShowShips(int index
)
832 ShowVehicleListWindow((CompanyID
)index
, VEH_SHIP
);
836 /* --- Aircraft button menu --- */
838 static CallBackFunction
ToolbarAirClick(Window
*w
)
840 ToolbarVehicleClick(w
, VEH_AIRCRAFT
);
845 * Handle click on the entry in the Aircraft menu.
847 * @param index CompanyID to show aircraft list for.
850 static CallBackFunction
MenuClickShowAir(int index
)
852 ShowVehicleListWindow((CompanyID
)index
, VEH_AIRCRAFT
);
856 /* --- Zoom in button --- */
858 static CallBackFunction
ToolbarZoomInClick(Window
*w
)
860 if (DoZoomInOutWindow(ZOOM_IN
, FindWindowById(WC_MAIN_WINDOW
, 0))) {
861 w
->HandleButtonClick((_game_mode
== GM_EDITOR
) ? (byte
)WID_TE_ZOOM_IN
: (byte
)WID_TN_ZOOM_IN
);
862 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
867 /* --- Zoom out button --- */
869 static CallBackFunction
ToolbarZoomOutClick(Window
*w
)
871 if (DoZoomInOutWindow(ZOOM_OUT
, FindWindowById(WC_MAIN_WINDOW
, 0))) {
872 w
->HandleButtonClick((_game_mode
== GM_EDITOR
) ? (byte
)WID_TE_ZOOM_OUT
: (byte
)WID_TN_ZOOM_OUT
);
873 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
878 /* --- Rail button menu --- */
880 static CallBackFunction
ToolbarBuildRailClick(Window
*w
)
882 ShowDropDownList(w
, GetRailTypeDropDownList(), _last_built_railtype
, WID_TN_RAILS
, 140, true, true);
883 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
888 * Handle click on the entry in the Build Rail menu.
890 * @param index RailType to show the build toolbar for.
893 static CallBackFunction
MenuClickBuildRail(int index
)
895 _last_built_railtype
= (RailType
)index
;
896 ShowBuildRailToolbar(_last_built_railtype
);
900 /* --- Road button menu --- */
902 static CallBackFunction
ToolbarBuildRoadClick(Window
*w
)
904 const Company
*c
= Company::Get(_local_company
);
905 DropDownList
*list
= new DropDownList();
907 /* Road is always visible and available. */
908 *list
->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION
, ROADTYPE_ROAD
, false);
910 /* Tram is only visible when there will be a tram, and available when that has been introduced. */
912 FOR_ALL_ENGINES_OF_TYPE(e
, VEH_ROAD
) {
913 if (!HasBit(e
->info
.climates
, _settings_game
.game_creation
.landscape
)) continue;
914 if (!HasBit(e
->info
.misc_flags
, EF_ROAD_TRAM
)) continue;
916 *list
->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION
, ROADTYPE_TRAM
, !HasBit(c
->avail_roadtypes
, ROADTYPE_TRAM
));
919 ShowDropDownList(w
, list
, _last_built_roadtype
, WID_TN_ROADS
, 140, true, true);
920 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
925 * Handle click on the entry in the Build Road menu.
927 * @param index RoadType to show the build toolbar for.
930 static CallBackFunction
MenuClickBuildRoad(int index
)
932 _last_built_roadtype
= (RoadType
)index
;
933 ShowBuildRoadToolbar(_last_built_roadtype
);
937 /* --- Water button menu --- */
939 static CallBackFunction
ToolbarBuildWaterClick(Window
*w
)
941 PopupMainToolbMenu(w
, WID_TN_WATER
, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION
, 1);
946 * Handle click on the entry in the Build Waterways menu.
948 * @param index Unused.
951 static CallBackFunction
MenuClickBuildWater(int index
)
953 ShowBuildDocksToolbar();
957 /* --- Airport button menu --- */
959 static CallBackFunction
ToolbarBuildAirClick(Window
*w
)
961 PopupMainToolbMenu(w
, WID_TN_AIR
, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION
, 1);
966 * Handle click on the entry in the Build Air menu.
968 * @param index Unused.
971 static CallBackFunction
MenuClickBuildAir(int index
)
973 ShowBuildAirToolbar();
977 /* --- Forest button menu --- */
979 static CallBackFunction
ToolbarForestClick(Window
*w
)
981 PopupMainToolbMenu(w
, WID_TN_LANDSCAPE
, STR_LANDSCAPING_MENU_LANDSCAPING
, 3);
986 * Handle click on the entry in the landscaping menu.
988 * @param index Menu entry clicked.
991 static CallBackFunction
MenuClickForest(int index
)
994 case 0: ShowTerraformToolbar(); break;
995 case 1: ShowBuildTreesToolbar(); break;
996 case 2: return SelectSignTool();
1001 /* --- Music button menu --- */
1003 static CallBackFunction
ToolbarMusicClick(Window
*w
)
1005 PopupMainToolbMenu(w
, WID_TN_MUSIC_SOUND
, STR_TOOLBAR_SOUND_MUSIC
, 1);
1010 * Handle click on the entry in the Music menu.
1012 * @param index Unused.
1015 static CallBackFunction
MenuClickMusicWindow(int index
)
1021 /* --- Newspaper button menu --- */
1023 static CallBackFunction
ToolbarNewspaperClick(Window
*w
)
1025 PopupMainToolbMenu(w
, WID_TN_MESSAGES
, STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT
, 2);
1030 * Handle click on the entry in the Newspaper menu.
1032 * @param index Menu entry clicked.
1035 static CallBackFunction
MenuClickNewspaper(int index
)
1038 case 0: ShowLastNewsMessage(); break;
1039 case 1: ShowMessageHistory(); break;
1044 /* --- Help button menu --- */
1046 static CallBackFunction
PlaceLandBlockInfo()
1048 if (_last_started_action
== CBF_PLACE_LANDINFO
) {
1049 ResetObjectToPlace();
1052 SetObjectToPlace(SPR_CURSOR_QUERY
, PAL_NONE
, HT_RECT
, WC_MAIN_TOOLBAR
, 0);
1053 return CBF_PLACE_LANDINFO
;
1057 static CallBackFunction
ToolbarHelpClick(Window
*w
)
1059 PopupMainToolbMenu(w
, WID_TN_HELP
, STR_ABOUT_MENU_LAND_BLOCK_INFO
, _settings_client
.gui
.newgrf_developer_tools
? 16 : 13);
1063 static void MenuClickSmallScreenshot()
1065 MakeScreenshot(SC_VIEWPORT
, nullptr);
1068 static void MenuClickFlatMinimapScreenshot(ScreenshotType type
)
1070 MakeScreenshot(type
, nullptr);
1074 * Callback on the confirmation window for huge screenshots.
1075 * @param w Window with viewport
1076 * @param confirmed true on confirmation
1078 static void ScreenshotConfirmCallback(Window
*w
, bool confirmed
)
1080 if (confirmed
) MakeScreenshot(_confirmed_screenshot_type
, nullptr);
1084 * Make a screenshot of the world.
1085 * Ask for confirmation if the screenshot will be huge.
1086 * @param t Screenshot type: World or viewport screenshot
1088 static void MenuClickLargeWorldScreenshot(ScreenshotType t
)
1091 SetupScreenshotViewport(t
, &vp
);
1092 if ((uint64
)vp
.width
* (uint64
)vp
.height
> 8192 * 8192) {
1093 /* Ask for confirmation */
1094 SetDParam(0, vp
.width
);
1095 SetDParam(1, vp
.height
);
1096 _confirmed_screenshot_type
= t
;
1097 ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION
, STR_WARNING_SCREENSHOT_SIZE_MESSAGE
, nullptr, ScreenshotConfirmCallback
);
1099 /* Less than 64M pixels, just do it */
1100 MakeScreenshot(t
, nullptr);
1105 * Toggle drawing of sprites' bounding boxes.
1106 * @note has only an effect when newgrf_developer_tools are active.
1108 * Function is found here and not in viewport.cpp in order to avoid
1109 * importing the settings structs to there.
1111 void ToggleBoundingBoxes()
1113 extern bool _draw_bounding_boxes
;
1114 /* Always allow to toggle them off */
1115 if (_settings_client
.gui
.newgrf_developer_tools
|| _draw_bounding_boxes
) {
1116 _draw_bounding_boxes
= !_draw_bounding_boxes
;
1117 MarkWholeScreenDirty();
1122 * Toggle drawing of the dirty blocks.
1123 * @note has only an effect when newgrf_developer_tools are active.
1125 * Function is found here and not in viewport.cpp in order to avoid
1126 * importing the settings structs to there.
1128 void ToggleDirtyBlocks()
1130 extern bool _draw_dirty_blocks
;
1131 /* Always allow to toggle them off */
1132 if (_settings_client
.gui
.newgrf_developer_tools
|| _draw_dirty_blocks
) {
1133 _draw_dirty_blocks
= !_draw_dirty_blocks
;
1134 MarkWholeScreenDirty();
1139 * Set the starting year for a scenario.
1140 * @param year New starting year.
1142 void SetStartingYear(Year year
)
1144 _settings_game
.game_creation
.starting_year
= Clamp(year
, MIN_YEAR
, MAX_YEAR
);
1145 Date new_date
= ConvertYMDToDate(_settings_game
.game_creation
.starting_year
, 0, 1);
1146 /* If you open a savegame as scenario there may already be link graphs.*/
1147 LinkGraphSchedule::instance
.ShiftDates(new_date
- _date
);
1148 SetDate(new_date
, 0);
1152 * Choose the proper callback function for the main toolbar's help menu.
1153 * @param index The menu index which was selected.
1156 static CallBackFunction
MenuClickHelp(int index
)
1159 case 0: return PlaceLandBlockInfo();
1160 case 2: IConsoleSwitch(); break;
1161 case 3: ShowAIDebugWindow(); break;
1162 case 4: MenuClickSmallScreenshot(); break;
1163 case 5: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN
); break;
1164 case 6: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM
); break;
1165 case 7: MenuClickLargeWorldScreenshot(SC_WORLD
); break;
1166 case 8: MenuClickFlatMinimapScreenshot(SC_MINIMAP
); break;
1167 case 9: MenuClickFlatMinimapScreenshot(SC_MINI_HEIGHTMAP
); break;
1168 case 10: MenuClickFlatMinimapScreenshot(SC_MINI_INDUSTRYMAP
); break;
1169 case 11: MenuClickFlatMinimapScreenshot(SC_MINI_OWNERMAP
); break;
1170 case 12: ShowAboutWindow(); break;
1171 case 13: ShowSpriteAlignerWindow(); break;
1172 case 14: ToggleBoundingBoxes(); break;
1173 case 15: ToggleDirtyBlocks(); break;
1178 /* --- Switch toolbar button --- */
1180 static CallBackFunction
ToolbarSwitchClick(Window
*w
)
1182 if (_toolbar_mode
!= TB_LOWER
) {
1183 _toolbar_mode
= TB_LOWER
;
1185 _toolbar_mode
= TB_UPPER
;
1189 w
->SetWidgetLoweredState(WID_TN_SWITCH_BAR
, _toolbar_mode
== TB_LOWER
);
1190 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1194 /* --- Scenario editor specific handlers. */
1197 * Called when clicking at the date panel of the scenario editor toolbar.
1199 static CallBackFunction
ToolbarScenDatePanel(Window
*w
)
1201 SetDParam(0, _settings_game
.game_creation
.starting_year
);
1202 ShowQueryString(STR_JUST_INT
, STR_MAPGEN_START_DATE_QUERY_CAPT
, 8, w
, CS_NUMERAL
, QSF_ENABLE_DEFAULT
);
1203 _left_button_clicked
= false;
1207 static CallBackFunction
ToolbarScenDateBackward(Window
*w
)
1209 /* don't allow too fast scrolling */
1210 if (!(w
->flags
& WF_TIMEOUT
) || w
->timeout_timer
<= 1) {
1211 w
->HandleButtonClick(WID_TE_DATE_BACKWARD
);
1214 SetStartingYear(_settings_game
.game_creation
.starting_year
- 1);
1216 _left_button_clicked
= false;
1220 static CallBackFunction
ToolbarScenDateForward(Window
*w
)
1222 /* don't allow too fast scrolling */
1223 if (!(w
->flags
& WF_TIMEOUT
) || w
->timeout_timer
<= 1) {
1224 w
->HandleButtonClick(WID_TE_DATE_FORWARD
);
1227 SetStartingYear(_settings_game
.game_creation
.starting_year
+ 1);
1229 _left_button_clicked
= false;
1233 static CallBackFunction
ToolbarScenGenLand(Window
*w
)
1235 w
->HandleButtonClick(WID_TE_LAND_GENERATE
);
1236 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1238 ShowEditorTerraformToolbar();
1243 static CallBackFunction
ToolbarScenGenTown(Window
*w
)
1245 w
->HandleButtonClick(WID_TE_TOWN_GENERATE
);
1246 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1247 ShowFoundTownWindow();
1251 static CallBackFunction
ToolbarScenGenIndustry(Window
*w
)
1253 w
->HandleButtonClick(WID_TE_INDUSTRY
);
1254 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1255 ShowBuildIndustryWindow();
1259 static CallBackFunction
ToolbarScenBuildRoad(Window
*w
)
1261 w
->HandleButtonClick(WID_TE_ROADS
);
1262 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1263 ShowBuildRoadScenToolbar();
1267 static CallBackFunction
ToolbarScenBuildDocks(Window
*w
)
1269 w
->HandleButtonClick(WID_TE_WATER
);
1270 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1271 ShowBuildDocksScenToolbar();
1275 static CallBackFunction
ToolbarScenPlantTrees(Window
*w
)
1277 w
->HandleButtonClick(WID_TE_TREES
);
1278 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1279 ShowBuildTreesToolbar();
1283 static CallBackFunction
ToolbarScenPlaceSign(Window
*w
)
1285 w
->HandleButtonClick(WID_TE_SIGNS
);
1286 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
1287 return SelectSignTool();
1290 static CallBackFunction
ToolbarBtn_NULL(Window
*w
)
1295 typedef CallBackFunction
MenuClickedProc(int index
);
1297 static MenuClickedProc
* const _menu_clicked_procs
[] = {
1300 MenuClickSettings
, // 2
1301 MenuClickSaveLoad
, // 3
1304 MenuClickSubsidies
, // 6
1305 MenuClickStations
, // 7
1306 MenuClickFinances
, // 8
1307 MenuClickCompany
, // 9
1308 MenuClickStory
, // 10
1309 MenuClickGoal
, // 11
1310 MenuClickGraphs
, // 12
1311 MenuClickLeague
, // 13
1312 MenuClickIndustry
, // 14
1313 MenuClickShowTrains
, // 15
1314 MenuClickShowRoad
, // 16
1315 MenuClickShowShips
, // 17
1316 MenuClickShowAir
, // 18
1319 MenuClickBuildRail
, // 21
1320 MenuClickBuildRoad
, // 22
1321 MenuClickBuildWater
, // 23
1322 MenuClickBuildAir
, // 24
1323 MenuClickForest
, // 25
1324 MenuClickMusicWindow
, // 26
1325 MenuClickNewspaper
, // 27
1326 MenuClickHelp
, // 28
1329 /** Full blown container to make it behave exactly as we want :) */
1330 class NWidgetToolbarContainer
: public NWidgetContainer
{
1331 bool visible
[WID_TN_END
]; ///< The visible headers
1333 uint spacers
; ///< Number of spacer widgets in this toolbar
1336 NWidgetToolbarContainer() : NWidgetContainer(NWID_HORIZONTAL
)
1341 * Check whether the given widget type is a button for us.
1342 * @param type the widget type to check.
1343 * @return true if it is a button for us.
1345 bool IsButton(WidgetType type
) const
1347 return type
== WWT_IMGBTN
|| type
== WWT_IMGBTN_2
|| type
== WWT_PUSHIMGBTN
;
1350 void SetupSmallestSize(Window
*w
, bool init_array
)
1352 this->smallest_x
= 0; // Biggest child
1353 this->smallest_y
= 0; // Biggest child
1356 this->resize_x
= 1; // We only resize in this direction
1357 this->resize_y
= 0; // We never resize in this direction
1361 /* First initialise some variables... */
1362 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= nullptr; child_wid
= child_wid
->next
) {
1363 child_wid
->SetupSmallestSize(w
, init_array
);
1364 this->smallest_y
= max(this->smallest_y
, child_wid
->smallest_y
+ child_wid
->padding_top
+ child_wid
->padding_bottom
);
1365 if (this->IsButton(child_wid
->type
)) {
1367 this->smallest_x
= max(this->smallest_x
, child_wid
->smallest_x
+ child_wid
->padding_left
+ child_wid
->padding_right
);
1368 } else if (child_wid
->type
== NWID_SPACER
) {
1373 /* ... then in a second pass make sure the 'current' heights are set. Won't change ever. */
1374 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= nullptr; child_wid
= child_wid
->next
) {
1375 child_wid
->current_y
= this->smallest_y
;
1376 if (!this->IsButton(child_wid
->type
)) {
1377 child_wid
->current_x
= child_wid
->smallest_x
;
1380 _toolbar_width
= nbuttons
* this->smallest_x
;
1383 void AssignSizePosition(SizingType sizing
, uint x
, uint y
, uint given_width
, uint given_height
, bool rtl
)
1385 assert(given_width
>= this->smallest_x
&& given_height
>= this->smallest_y
);
1389 this->current_x
= given_width
;
1390 this->current_y
= given_height
;
1392 /* Figure out what are the visible buttons */
1393 memset(this->visible
, 0, sizeof(this->visible
));
1394 uint arrangable_count
, button_count
, spacer_count
;
1395 const byte
*arrangement
= GetButtonArrangement(given_width
, arrangable_count
, button_count
, spacer_count
);
1396 for (uint i
= 0; i
< arrangable_count
; i
++) {
1397 this->visible
[arrangement
[i
]] = true;
1400 /* Create us ourselves a quick lookup table */
1401 NWidgetBase
*widgets
[WID_TN_END
];
1402 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= nullptr; child_wid
= child_wid
->next
) {
1403 if (child_wid
->type
== NWID_SPACER
) continue;
1404 widgets
[((NWidgetCore
*)child_wid
)->index
] = child_wid
;
1407 /* Now assign the widgets to their rightful place */
1408 uint position
= 0; // Place to put next child relative to origin of the container.
1409 uint spacer_space
= max(0, (int)given_width
- (int)(button_count
* this->smallest_x
)); // Remaining spacing for 'spacer' widgets
1410 uint button_space
= given_width
- spacer_space
; // Remaining spacing for the buttons
1414 /* Index into the arrangement indices. The macro lastof cannot be used here! */
1415 const byte
*cur_wid
= rtl
? &arrangement
[arrangable_count
- 1] : arrangement
;
1416 for (uint i
= 0; i
< arrangable_count
; i
++) {
1417 NWidgetBase
*child_wid
= widgets
[*cur_wid
];
1418 /* If we have to give space to the spacers, do that */
1419 if (spacer_space
!= 0) {
1420 NWidgetBase
*possible_spacer
= rtl
? child_wid
->next
: child_wid
->prev
;
1421 if (possible_spacer
!= nullptr && possible_spacer
->type
== NWID_SPACER
) {
1422 uint add
= spacer_space
/ (spacer_count
- spacer_i
);
1424 spacer_space
-= add
;
1429 /* Buttons can be scaled, the others not. */
1430 if (this->IsButton(child_wid
->type
)) {
1431 child_wid
->current_x
= button_space
/ (button_count
- button_i
);
1432 button_space
-= child_wid
->current_x
;
1435 child_wid
->AssignSizePosition(sizing
, x
+ position
, y
, child_wid
->current_x
, this->current_y
, rtl
);
1436 position
+= child_wid
->current_x
;
1446 /* virtual */ void Draw(const Window
*w
)
1448 /* Draw brown-red toolbar bg. */
1449 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
);
1450 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
);
1452 bool rtl
= _current_text_dir
== TD_RTL
;
1453 for (NWidgetBase
*child_wid
= rtl
? this->tail
: this->head
; child_wid
!= nullptr; child_wid
= rtl
? child_wid
->prev
: child_wid
->next
) {
1454 if (child_wid
->type
== NWID_SPACER
) continue;
1455 if (!this->visible
[((NWidgetCore
*)child_wid
)->index
]) continue;
1461 /* virtual */ NWidgetCore
*GetWidgetFromPos(int x
, int y
)
1463 if (!IsInsideBS(x
, this->pos_x
, this->current_x
) || !IsInsideBS(y
, this->pos_y
, this->current_y
)) return nullptr;
1465 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= nullptr; child_wid
= child_wid
->next
) {
1466 if (child_wid
->type
== NWID_SPACER
) continue;
1467 if (!this->visible
[((NWidgetCore
*)child_wid
)->index
]) continue;
1469 NWidgetCore
*nwid
= child_wid
->GetWidgetFromPos(x
, y
);
1470 if (nwid
!= nullptr) return nwid
;
1476 * Get the arrangement of the buttons for the toolbar.
1477 * @param width the new width of the toolbar.
1478 * @param arrangable_count output of the number of visible items.
1479 * @param button_count output of the number of visible buttons.
1480 * @param spacer_count output of the number of spacers.
1481 * @return the button configuration.
1483 virtual const byte
*GetButtonArrangement(uint
&width
, uint
&arrangable_count
, uint
&button_count
, uint
&spacer_count
) const = 0;
1486 /** Container for the 'normal' main toolbar */
1487 class NWidgetMainToolbarContainer
: public NWidgetToolbarContainer
{
1488 /* virtual */ const byte
*GetButtonArrangement(uint
&width
, uint
&arrangable_count
, uint
&button_count
, uint
&spacer_count
) const
1490 static const uint SMALLEST_ARRANGEMENT
= 14;
1491 static const uint BIGGEST_ARRANGEMENT
= 20;
1493 /* The number of buttons of each row of the toolbar should match the number of items which we want to be visible.
1494 * The total number of buttons should be equal to arrangable_count * 2.
1495 * No bad things happen, but we could see strange behaviours if we have buttons < (arrangable_count * 2) like a
1496 * pause button appearing on the right of the lower toolbar and weird resizing of the widgets even if there is
1499 static const byte arrange14
[] = {
1501 WID_TN_FAST_FORWARD
,
1530 static const byte arrange15
[] = {
1532 WID_TN_FAST_FORWARD
,
1563 static const byte arrange16
[] = {
1565 WID_TN_FAST_FORWARD
,
1582 WID_TN_FAST_FORWARD
,
1598 static const byte arrange17
[] = {
1600 WID_TN_FAST_FORWARD
,
1618 WID_TN_FAST_FORWARD
,
1635 static const byte arrange18
[] = {
1637 WID_TN_FAST_FORWARD
,
1656 WID_TN_FAST_FORWARD
,
1674 static const byte arrange19
[] = {
1676 WID_TN_FAST_FORWARD
,
1696 WID_TN_FAST_FORWARD
,
1715 static const byte arrange20
[] = {
1717 WID_TN_FAST_FORWARD
,
1738 WID_TN_FAST_FORWARD
,
1758 static const byte arrange_all
[] = {
1760 WID_TN_FAST_FORWARD
,
1790 /* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
1791 uint full_buttons
= max(CeilDiv(width
, this->smallest_x
), SMALLEST_ARRANGEMENT
);
1792 if (full_buttons
> BIGGEST_ARRANGEMENT
) {
1793 button_count
= arrangable_count
= lengthof(arrange_all
);
1794 spacer_count
= this->spacers
;
1798 /* Introduce the split toolbar */
1799 static const byte
* const arrangements
[] = { arrange14
, arrange15
, arrange16
, arrange17
, arrange18
, arrange19
, arrange20
};
1801 button_count
= arrangable_count
= full_buttons
;
1802 spacer_count
= this->spacers
;
1803 return arrangements
[full_buttons
- SMALLEST_ARRANGEMENT
] + ((_toolbar_mode
== TB_LOWER
) ? full_buttons
: 0);
1807 /** Container for the scenario editor's toolbar */
1808 class NWidgetScenarioToolbarContainer
: public NWidgetToolbarContainer
{
1809 uint panel_widths
[2]; ///< The width of the two panels (the text panel and date panel)
1811 void SetupSmallestSize(Window
*w
, bool init_array
)
1813 this->NWidgetToolbarContainer::SetupSmallestSize(w
, init_array
);
1815 /* Find the size of panel_widths */
1817 for (NWidgetBase
*child_wid
= this->head
; child_wid
!= nullptr; child_wid
= child_wid
->next
) {
1818 if (child_wid
->type
== NWID_SPACER
|| this->IsButton(child_wid
->type
)) continue;
1820 assert(i
< lengthof(this->panel_widths
));
1821 this->panel_widths
[i
++] = child_wid
->current_x
;
1822 _toolbar_width
+= child_wid
->current_x
;
1826 /* virtual */ const byte
*GetButtonArrangement(uint
&width
, uint
&arrangable_count
, uint
&button_count
, uint
&spacer_count
) const
1828 static const byte arrange_all
[] = {
1830 WID_TE_FAST_FORWARD
,
1838 WID_TE_LAND_GENERATE
,
1839 WID_TE_TOWN_GENERATE
,
1848 static const byte arrange_nopanel
[] = {
1850 WID_TE_FAST_FORWARD
,
1857 WID_TE_LAND_GENERATE
,
1858 WID_TE_TOWN_GENERATE
,
1867 static const byte arrange_switch
[] = {
1870 WID_TE_LAND_GENERATE
,
1871 WID_TE_TOWN_GENERATE
,
1880 WID_TE_FAST_FORWARD
,
1887 WID_TE_HELP
, WID_TE_SWITCH_BAR
,
1890 /* If we can place all buttons *and* the panels, show them. */
1891 uint min_full_width
= (lengthof(arrange_all
) - lengthof(this->panel_widths
)) * this->smallest_x
+ this->panel_widths
[0] + this->panel_widths
[1];
1892 if (width
>= min_full_width
) {
1893 width
-= this->panel_widths
[0] + this->panel_widths
[1];
1894 arrangable_count
= lengthof(arrange_all
);
1895 button_count
= arrangable_count
- 2;
1896 spacer_count
= this->spacers
;
1900 /* 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 */
1901 uint min_small_width
= (lengthof(arrange_switch
) - lengthof(this->panel_widths
)) * this->smallest_x
/ 2 + this->panel_widths
[1];
1902 if (width
> min_small_width
) {
1903 width
-= this->panel_widths
[1];
1904 arrangable_count
= lengthof(arrange_nopanel
);
1905 button_count
= arrangable_count
- 1;
1906 spacer_count
= this->spacers
- 1;
1907 return arrange_nopanel
;
1911 width
-= this->panel_widths
[1];
1912 arrangable_count
= lengthof(arrange_switch
) / 2;
1913 button_count
= arrangable_count
- 1;
1915 return arrange_switch
+ ((_toolbar_mode
== TB_LOWER
) ? arrangable_count
: 0);
1919 /* --- Toolbar handling for the 'normal' case */
1921 typedef CallBackFunction
ToolbarButtonProc(Window
*w
);
1923 static ToolbarButtonProc
* const _toolbar_button_procs
[] = {
1925 ToolbarFastForwardClick
,
1926 ToolbarOptionsClick
,
1930 ToolbarSubsidiesClick
,
1931 ToolbarStationsClick
,
1932 ToolbarFinancesClick
,
1933 ToolbarCompaniesClick
,
1938 ToolbarIndustryClick
,
1944 ToolbarZoomOutClick
,
1945 ToolbarBuildRailClick
,
1946 ToolbarBuildRoadClick
,
1947 ToolbarBuildWaterClick
,
1948 ToolbarBuildAirClick
,
1951 ToolbarNewspaperClick
,
1956 enum MainToolbarHotkeys
{
1986 MTHK_SMALL_SCREENSHOT
,
1987 MTHK_ZOOMEDIN_SCREENSHOT
,
1988 MTHK_DEFAULTZOOM_SCREENSHOT
,
1989 MTHK_GIANT_SCREENSHOT
,
1992 MTHK_EXTRA_VIEWPORT
,
1998 /** Main toolbar. */
1999 struct MainToolbarWindow
: Window
{
2000 MainToolbarWindow(WindowDesc
*desc
) : Window(desc
)
2002 this->InitNested(0);
2004 _last_started_action
= CBF_NONE
;
2005 CLRBITS(this->flags
, WF_WHITE_BORDER
);
2006 this->SetWidgetDisabledState(WID_TN_PAUSE
, _networking
&& !_network_server
); // if not server, disable pause button
2007 this->SetWidgetDisabledState(WID_TN_FAST_FORWARD
, _networking
); // if networking, disable fast-forward button
2008 PositionMainToolbar(this);
2009 DoZoomInOutWindow(ZOOM_NONE
, this);
2012 virtual void FindWindowPlacementAndResize(int def_width
, int def_height
)
2014 Window::FindWindowPlacementAndResize(_toolbar_width
, def_height
);
2017 virtual void OnPaint()
2019 /* If spectator, disable all construction buttons
2020 * ie : Build road, rail, ships, airports and landscaping
2021 * Since enabled state is the default, just disable when needed */
2022 this->SetWidgetsDisabledState(_local_company
== COMPANY_SPECTATOR
, WID_TN_RAILS
, WID_TN_ROADS
, WID_TN_WATER
, WID_TN_AIR
, WID_TN_LANDSCAPE
, WIDGET_LIST_END
);
2023 /* disable company list drop downs, if there are no companies */
2024 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
);
2026 this->SetWidgetDisabledState(WID_TN_GOAL
, Goal::GetNumItems() == 0);
2027 this->SetWidgetDisabledState(WID_TN_STORY
, StoryPage::GetNumItems() == 0);
2029 this->SetWidgetDisabledState(WID_TN_RAILS
, !CanBuildVehicleInfrastructure(VEH_TRAIN
));
2030 this->SetWidgetDisabledState(WID_TN_AIR
, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT
));
2032 this->DrawWidgets();
2035 virtual void OnClick(Point pt
, int widget
, int click_count
)
2037 if (_game_mode
!= GM_MENU
&& !this->IsWidgetDisabled(widget
)) _toolbar_button_procs
[widget
](this);
2040 virtual void OnDropdownSelect(int widget
, int index
)
2042 CallBackFunction cbf
= _menu_clicked_procs
[widget
](index
);
2043 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
2046 virtual EventState
OnHotkey(int hotkey
)
2049 case MTHK_PAUSE
: ToolbarPauseClick(this); break;
2050 case MTHK_FASTFORWARD
: ToolbarFastForwardClick(this); break;
2051 case MTHK_SETTINGS
: ShowGameOptions(); break;
2052 case MTHK_SAVEGAME
: MenuClickSaveLoad(); break;
2053 case MTHK_LOADGAME
: ShowSaveLoadDialog(FT_SAVEGAME
, SLO_LOAD
); break;
2054 case MTHK_SMALLMAP
: ShowSmallMap(); break;
2055 case MTHK_TOWNDIRECTORY
: ShowTownDirectory(); break;
2056 case MTHK_SUBSIDIES
: ShowSubsidiesList(); break;
2057 case MTHK_STATIONS
: ShowCompanyStations(_local_company
); break;
2058 case MTHK_FINANCES
: ShowCompanyFinances(_local_company
); break;
2059 case MTHK_COMPANIES
: ShowCompany(_local_company
); break;
2060 case MTHK_STORY
: ShowStoryBook(_local_company
); break;
2061 case MTHK_GOAL
: ShowGoalsList(_local_company
); break;
2062 case MTHK_GRAPHS
: ShowOperatingProfitGraph(); break;
2063 case MTHK_LEAGUE
: ShowCompanyLeagueTable(); break;
2064 case MTHK_INDUSTRIES
: ShowBuildIndustryWindow(); break;
2065 case MTHK_TRAIN_LIST
: ShowVehicleListWindow(_local_company
, VEH_TRAIN
); break;
2066 case MTHK_ROADVEH_LIST
: ShowVehicleListWindow(_local_company
, VEH_ROAD
); break;
2067 case MTHK_SHIP_LIST
: ShowVehicleListWindow(_local_company
, VEH_SHIP
); break;
2068 case MTHK_AIRCRAFT_LIST
: ShowVehicleListWindow(_local_company
, VEH_AIRCRAFT
); break;
2069 case MTHK_ZOOM_IN
: ToolbarZoomInClick(this); break;
2070 case MTHK_ZOOM_OUT
: ToolbarZoomOutClick(this); break;
2071 case MTHK_BUILD_RAIL
: if (CanBuildVehicleInfrastructure(VEH_TRAIN
)) ShowBuildRailToolbar(_last_built_railtype
); break;
2072 case MTHK_BUILD_ROAD
: ShowBuildRoadToolbar(_last_built_roadtype
); break;
2073 case MTHK_BUILD_DOCKS
: ShowBuildDocksToolbar(); break;
2074 case MTHK_BUILD_AIRPORT
: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT
)) ShowBuildAirToolbar(); break;
2075 case MTHK_BUILD_TREES
: ShowBuildTreesToolbar(); break;
2076 case MTHK_MUSIC
: ShowMusicWindow(); break;
2077 case MTHK_AI_DEBUG
: ShowAIDebugWindow(); break;
2078 case MTHK_SMALL_SCREENSHOT
: MenuClickSmallScreenshot(); break;
2079 case MTHK_ZOOMEDIN_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN
); break;
2080 case MTHK_DEFAULTZOOM_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM
); break;
2081 case MTHK_GIANT_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_WORLD
); break;
2082 case MTHK_CHEATS
: if (!_networking
) ShowCheatWindow(); break;
2083 case MTHK_TERRAFORM
: ShowTerraformToolbar(); break;
2084 case MTHK_EXTRA_VIEWPORT
: ShowExtraViewPortWindowForTileUnderCursor(); break;
2085 #ifdef ENABLE_NETWORK
2086 case MTHK_CLIENT_LIST
: if (_networking
) ShowClientList(); break;
2088 case MTHK_SIGN_LIST
: ShowSignList(); break;
2089 case MTHK_PLAN_LIST
: ShowPlansWindow(); break;
2090 default: return ES_NOT_HANDLED
;
2095 virtual void OnPlaceObject(Point pt
, TileIndex tile
)
2097 switch (_last_started_action
) {
2098 case CBF_PLACE_SIGN
:
2099 PlaceProc_Sign(tile
);
2102 case CBF_PLACE_LANDINFO
:
2106 default: NOT_REACHED();
2110 virtual void OnPlaceObjectAbort()
2112 _last_started_action
= CBF_NONE
;
2115 virtual void OnTick()
2117 if (this->IsWidgetLowered(WID_TN_PAUSE
) != !!_pause_mode
) {
2118 this->ToggleWidgetLoweredState(WID_TN_PAUSE
);
2119 this->SetWidgetDirty(WID_TN_PAUSE
);
2122 if (this->IsWidgetLowered(WID_TN_FAST_FORWARD
) != !!_fast_forward
) {
2123 this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD
);
2124 this->SetWidgetDirty(WID_TN_FAST_FORWARD
);
2128 virtual void OnTimeout()
2130 /* We do not want to automatically raise the pause, fast forward and
2131 * switchbar buttons; they have to stay down when pressed etc. */
2132 for (uint i
= WID_TN_SETTINGS
; i
< WID_TN_SWITCH_BAR
; i
++) {
2133 if (this->IsWidgetLowered(i
)) {
2134 this->RaiseWidget(i
);
2135 this->SetWidgetDirty(i
);
2141 * Some data on this window has become invalid.
2142 * @param data Information about the changed data.
2143 * @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.
2145 virtual void OnInvalidateData(int data
= 0, bool gui_scope
= true)
2147 if (!gui_scope
) return;
2148 if (FindWindowById(WC_MAIN_WINDOW
, 0) != nullptr) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW
, 0)->viewport
, WID_TN_ZOOM_IN
, WID_TN_ZOOM_OUT
);
2151 static HotkeyList hotkeys
;
2154 const uint16 _maintoolbar_pause_keys
[] = {WKC_F1
, WKC_PAUSE
, 0};
2155 const uint16 _maintoolbar_zoomin_keys
[] = {WKC_NUM_PLUS
, WKC_EQUALS
, WKC_SHIFT
| WKC_EQUALS
, WKC_SHIFT
| WKC_F5
, 0};
2156 const uint16 _maintoolbar_zoomout_keys
[] = {WKC_NUM_MINUS
, WKC_MINUS
, WKC_SHIFT
| WKC_MINUS
, WKC_SHIFT
| WKC_F6
, 0};
2157 const uint16 _maintoolbar_smallmap_keys
[] = {WKC_F4
, 'M', 0};
2159 static Hotkey maintoolbar_hotkeys
[] = {
2160 Hotkey(_maintoolbar_pause_keys
, "pause", MTHK_PAUSE
),
2161 Hotkey((uint16
)0, "fastforward", MTHK_FASTFORWARD
),
2162 Hotkey(WKC_F2
, "settings", MTHK_SETTINGS
),
2163 Hotkey(WKC_F3
, "saveload", MTHK_SAVEGAME
),
2164 Hotkey((uint16
)0, "load_game", MTHK_LOADGAME
),
2165 Hotkey(_maintoolbar_smallmap_keys
, "smallmap", MTHK_SMALLMAP
),
2166 Hotkey(WKC_F5
, "town_list", MTHK_TOWNDIRECTORY
),
2167 Hotkey(WKC_F6
, "subsidies", MTHK_SUBSIDIES
),
2168 Hotkey(WKC_F7
, "station_list", MTHK_STATIONS
),
2169 Hotkey(WKC_F8
, "finances", MTHK_FINANCES
),
2170 Hotkey(WKC_F9
, "companies", MTHK_COMPANIES
),
2171 Hotkey((uint16
)0, "story_book", MTHK_STORY
),
2172 Hotkey((uint16
)0, "goal_list", MTHK_GOAL
),
2173 Hotkey(WKC_F10
, "graphs", MTHK_GRAPHS
),
2174 Hotkey(WKC_F11
, "league", MTHK_LEAGUE
),
2175 Hotkey(WKC_F12
, "industry_list", MTHK_INDUSTRIES
),
2176 Hotkey(WKC_SHIFT
| WKC_F1
, "train_list", MTHK_TRAIN_LIST
),
2177 Hotkey(WKC_SHIFT
| WKC_F2
, "roadveh_list", MTHK_ROADVEH_LIST
),
2178 Hotkey(WKC_SHIFT
| WKC_F3
, "ship_list", MTHK_SHIP_LIST
),
2179 Hotkey(WKC_SHIFT
| WKC_F4
, "aircraft_list", MTHK_AIRCRAFT_LIST
),
2180 Hotkey(_maintoolbar_zoomin_keys
, "zoomin", MTHK_ZOOM_IN
),
2181 Hotkey(_maintoolbar_zoomout_keys
, "zoomout", MTHK_ZOOM_OUT
),
2182 Hotkey(WKC_SHIFT
| WKC_F7
, "build_rail", MTHK_BUILD_RAIL
),
2183 Hotkey(WKC_SHIFT
| WKC_F8
, "build_road", MTHK_BUILD_ROAD
),
2184 Hotkey(WKC_SHIFT
| WKC_F9
, "build_docks", MTHK_BUILD_DOCKS
),
2185 Hotkey(WKC_SHIFT
| WKC_F10
, "build_airport", MTHK_BUILD_AIRPORT
),
2186 Hotkey(WKC_SHIFT
| WKC_F11
, "build_trees", MTHK_BUILD_TREES
),
2187 Hotkey(WKC_SHIFT
| WKC_F12
, "music", MTHK_MUSIC
),
2188 Hotkey((uint16
)0, "ai_debug", MTHK_AI_DEBUG
),
2189 Hotkey(WKC_CTRL
| 'S', "small_screenshot", MTHK_SMALL_SCREENSHOT
),
2190 Hotkey(WKC_CTRL
| 'P', "zoomedin_screenshot", MTHK_ZOOMEDIN_SCREENSHOT
),
2191 Hotkey(WKC_CTRL
| 'D', "defaultzoom_screenshot", MTHK_DEFAULTZOOM_SCREENSHOT
),
2192 Hotkey((uint16
)0, "giant_screenshot", MTHK_GIANT_SCREENSHOT
),
2193 Hotkey(WKC_CTRL
| WKC_ALT
| 'C', "cheats", MTHK_CHEATS
),
2194 Hotkey('L', "terraform", MTHK_TERRAFORM
),
2195 Hotkey('V', "extra_viewport", MTHK_EXTRA_VIEWPORT
),
2196 #ifdef ENABLE_NETWORK
2197 Hotkey((uint16
)0, "client_list", MTHK_CLIENT_LIST
),
2199 Hotkey((uint16
)0, "sign_list", MTHK_SIGN_LIST
),
2200 Hotkey('P', "plan_list", MTHK_PLAN_LIST
),
2203 HotkeyList
MainToolbarWindow::hotkeys("maintoolbar", maintoolbar_hotkeys
);
2205 static NWidgetBase
*MakeMainToolbar(int *biggest_index
)
2207 /** Sprites to use for the different toolbar buttons */
2208 static const SpriteID toolbar_button_sprites
[] = {
2209 SPR_IMG_PAUSE
, // WID_TN_PAUSE
2210 SPR_IMG_FASTFORWARD
, // WID_TN_FAST_FORWARD
2211 SPR_IMG_SETTINGS
, // WID_TN_SETTINGS
2212 SPR_IMG_SAVE
, // WID_TN_SAVE
2213 SPR_IMG_SMALLMAP
, // WID_TN_SMALL_MAP
2214 SPR_IMG_TOWN
, // WID_TN_TOWNS
2215 SPR_IMG_SUBSIDIES
, // WID_TN_SUBSIDIES
2216 SPR_IMG_COMPANY_LIST
, // WID_TN_STATIONS
2217 SPR_IMG_COMPANY_FINANCE
, // WID_TN_FINANCES
2218 SPR_IMG_COMPANY_GENERAL
, // WID_TN_COMPANIES
2219 SPR_IMG_STORY_BOOK
, // WID_TN_STORY
2220 SPR_IMG_GOAL
, // WID_TN_GOAL
2221 SPR_IMG_GRAPHS
, // WID_TN_GRAPHS
2222 SPR_IMG_COMPANY_LEAGUE
, // WID_TN_LEAGUE
2223 SPR_IMG_INDUSTRY
, // WID_TN_INDUSTRIES
2224 SPR_IMG_TRAINLIST
, // WID_TN_TRAINS
2225 SPR_IMG_TRUCKLIST
, // WID_TN_ROADVEHS
2226 SPR_IMG_SHIPLIST
, // WID_TN_SHIPS
2227 SPR_IMG_AIRPLANESLIST
, // WID_TN_AIRCRAFT
2228 SPR_IMG_ZOOMIN
, // WID_TN_ZOOMIN
2229 SPR_IMG_ZOOMOUT
, // WID_TN_ZOOMOUT
2230 SPR_IMG_BUILDRAIL
, // WID_TN_RAILS
2231 SPR_IMG_BUILDROAD
, // WID_TN_ROADS
2232 SPR_IMG_BUILDWATER
, // WID_TN_WATER
2233 SPR_IMG_BUILDAIR
, // WID_TN_AIR
2234 SPR_IMG_LANDSCAPING
, // WID_TN_LANDSCAPE
2235 SPR_IMG_MUSIC
, // WID_TN_MUSIC_SOUND
2236 SPR_IMG_MESSAGES
, // WID_TN_MESSAGES
2237 SPR_IMG_QUERY
, // WID_TN_HELP
2238 SPR_IMG_SWITCH_TOOLBAR
, // WID_TN_SWITCH_BAR
2241 NWidgetMainToolbarContainer
*hor
= new NWidgetMainToolbarContainer();
2242 for (uint i
= 0; i
< WID_TN_END
; i
++) {
2244 case WID_TN_SMALL_MAP
:
2245 case WID_TN_FINANCES
:
2246 case WID_TN_VEHICLE_START
:
2247 case WID_TN_ZOOM_IN
:
2248 case WID_TN_BUILDING_TOOLS_START
:
2249 case WID_TN_MUSIC_SOUND
:
2250 hor
->Add(new NWidgetSpacer(0, 0));
2253 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
));
2256 *biggest_index
= max
<int>(*biggest_index
, WID_TN_SWITCH_BAR
);
2260 static const NWidgetPart _nested_toolbar_normal_widgets
[] = {
2261 NWidgetFunction(MakeMainToolbar
),
2264 static WindowDesc
_toolb_normal_desc(
2265 WDP_MANUAL
, nullptr, 0, 0,
2266 WC_MAIN_TOOLBAR
, WC_NONE
,
2268 _nested_toolbar_normal_widgets
, lengthof(_nested_toolbar_normal_widgets
),
2269 &MainToolbarWindow::hotkeys
2273 /* --- Toolbar handling for the scenario editor */
2275 static ToolbarButtonProc
* const _scen_toolbar_button_procs
[] = {
2277 ToolbarFastForwardClick
,
2278 ToolbarOptionsClick
,
2279 ToolbarScenSaveOrLoad
,
2281 ToolbarScenDatePanel
,
2282 ToolbarScenDateBackward
,
2283 ToolbarScenDateForward
,
2284 ToolbarScenMapTownDir
,
2286 ToolbarZoomOutClick
,
2289 ToolbarScenGenIndustry
,
2290 ToolbarScenBuildRoad
,
2291 ToolbarScenBuildDocks
,
2292 ToolbarScenPlantTrees
,
2293 ToolbarScenPlaceSign
,
2308 enum MainToolbarEditorHotkeys
{
2322 MTEHK_SMALL_SCREENSHOT
,
2323 MTEHK_ZOOMEDIN_SCREENSHOT
,
2324 MTEHK_DEFAULTZOOM_SCREENSHOT
,
2325 MTEHK_GIANT_SCREENSHOT
,
2330 MTEHK_EXTRA_VIEWPORT
,
2333 struct ScenarioEditorToolbarWindow
: Window
{
2334 ScenarioEditorToolbarWindow(WindowDesc
*desc
) : Window(desc
)
2336 this->InitNested(0);
2338 _last_started_action
= CBF_NONE
;
2339 CLRBITS(this->flags
, WF_WHITE_BORDER
);
2340 PositionMainToolbar(this);
2341 DoZoomInOutWindow(ZOOM_NONE
, this);
2344 virtual void FindWindowPlacementAndResize(int def_width
, int def_height
)
2346 Window::FindWindowPlacementAndResize(_toolbar_width
, def_height
);
2349 virtual void OnPaint()
2351 this->SetWidgetDisabledState(WID_TE_DATE_BACKWARD
, _settings_game
.game_creation
.starting_year
<= MIN_YEAR
);
2352 this->SetWidgetDisabledState(WID_TE_DATE_FORWARD
, _settings_game
.game_creation
.starting_year
>= MAX_YEAR
);
2354 this->DrawWidgets();
2357 virtual void DrawWidget(const Rect
&r
, int widget
) const
2361 SetDParam(0, ConvertYMDToDate(_settings_game
.game_creation
.starting_year
, 0, 1));
2362 DrawString(r
.left
, r
.right
, (this->height
- FONT_HEIGHT_NORMAL
) / 2, STR_WHITE_DATE_LONG
, TC_FROMSTRING
, SA_HOR_CENTER
);
2365 case WID_TE_SPACER
: {
2366 int height
= r
.bottom
- r
.top
;
2367 if (height
> 2 * FONT_HEIGHT_NORMAL
) {
2368 DrawString(r
.left
, r
.right
, (height
+ 1) / 2 - FONT_HEIGHT_NORMAL
, STR_SCENEDIT_TOOLBAR_OPENTTD
, TC_FROMSTRING
, SA_HOR_CENTER
);
2369 DrawString(r
.left
, r
.right
, (height
+ 1) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
, TC_FROMSTRING
, SA_HOR_CENTER
);
2371 DrawString(r
.left
, r
.right
, (height
- FONT_HEIGHT_NORMAL
) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
, TC_FROMSTRING
, SA_HOR_CENTER
);
2378 virtual void UpdateWidgetSize(int widget
, Dimension
*size
, const Dimension
&padding
, Dimension
*fill
, Dimension
*resize
)
2382 size
->width
= max(GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_OPENTTD
).width
, GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR
).width
) + WD_FRAMERECT_LEFT
+ WD_FRAMERECT_RIGHT
;
2386 SetDParam(0, ConvertYMDToDate(MAX_YEAR
, 0, 1));
2387 *size
= GetStringBoundingBox(STR_WHITE_DATE_LONG
);
2388 size
->height
= max(size
->height
, GetSpriteSize(SPR_IMG_SAVE
).height
+ WD_IMGBTN_TOP
+ WD_IMGBTN_BOTTOM
);
2393 virtual void OnClick(Point pt
, int widget
, int click_count
)
2395 if (_game_mode
== GM_MENU
) return;
2396 CallBackFunction cbf
= _scen_toolbar_button_procs
[widget
](this);
2397 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
2400 virtual void OnDropdownSelect(int widget
, int index
)
2402 /* The map button is in a different location on the scenario
2403 * editor toolbar, so we need to adjust for it. */
2404 if (widget
== WID_TE_SMALL_MAP
) widget
= WID_TN_SMALL_MAP
;
2405 CallBackFunction cbf
= _menu_clicked_procs
[widget
](index
);
2406 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
2407 if (_settings_client
.sound
.click_beep
) SndPlayFx(SND_15_BEEP
);
2410 virtual EventState
OnHotkey(int hotkey
)
2412 CallBackFunction cbf
= CBF_NONE
;
2414 case MTEHK_PAUSE
: ToolbarPauseClick(this); break;
2415 case MTEHK_FASTFORWARD
: ToolbarFastForwardClick(this); break;
2416 case MTEHK_SETTINGS
: ShowGameOptions(); break;
2417 case MTEHK_SAVEGAME
: MenuClickSaveLoad(); break;
2418 case MTEHK_GENLAND
: ToolbarScenGenLand(this); break;
2419 case MTEHK_GENTOWN
: ToolbarScenGenTown(this); break;
2420 case MTEHK_GENINDUSTRY
: ToolbarScenGenIndustry(this); break;
2421 case MTEHK_BUILD_ROAD
: ToolbarScenBuildRoad(this); break;
2422 case MTEHK_BUILD_DOCKS
: ToolbarScenBuildDocks(this); break;
2423 case MTEHK_BUILD_TREES
: ToolbarScenPlantTrees(this); break;
2424 case MTEHK_SIGN
: cbf
= ToolbarScenPlaceSign(this); break;
2425 case MTEHK_MUSIC
: ShowMusicWindow(); break;
2426 case MTEHK_LANDINFO
: cbf
= PlaceLandBlockInfo(); break;
2427 case MTEHK_SMALL_SCREENSHOT
: MenuClickSmallScreenshot(); break;
2428 case MTEHK_ZOOMEDIN_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN
); break;
2429 case MTEHK_DEFAULTZOOM_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM
); break;
2430 case MTEHK_GIANT_SCREENSHOT
: MenuClickLargeWorldScreenshot(SC_WORLD
); break;
2431 case MTEHK_ZOOM_IN
: ToolbarZoomInClick(this); break;
2432 case MTEHK_ZOOM_OUT
: ToolbarZoomOutClick(this); break;
2433 case MTEHK_TERRAFORM
: ShowEditorTerraformToolbar(); break;
2434 case MTEHK_SMALLMAP
: ShowSmallMap(); break;
2435 case MTEHK_EXTRA_VIEWPORT
: ShowExtraViewPortWindowForTileUnderCursor(); break;
2436 default: return ES_NOT_HANDLED
;
2438 if (cbf
!= CBF_NONE
) _last_started_action
= cbf
;
2442 virtual void OnPlaceObject(Point pt
, TileIndex tile
)
2444 switch (_last_started_action
) {
2445 case CBF_PLACE_SIGN
:
2446 PlaceProc_Sign(tile
);
2449 case CBF_PLACE_LANDINFO
:
2453 default: NOT_REACHED();
2457 virtual void OnPlaceObjectAbort()
2459 _last_started_action
= CBF_NONE
;
2462 virtual void OnTimeout()
2464 this->SetWidgetsLoweredState(false, WID_TE_DATE_BACKWARD
, WID_TE_DATE_FORWARD
, WIDGET_LIST_END
);
2465 this->SetWidgetDirty(WID_TE_DATE_BACKWARD
);
2466 this->SetWidgetDirty(WID_TE_DATE_FORWARD
);
2469 virtual void OnTick()
2471 if (this->IsWidgetLowered(WID_TE_PAUSE
) != !!_pause_mode
) {
2472 this->ToggleWidgetLoweredState(WID_TE_PAUSE
);
2476 if (this->IsWidgetLowered(WID_TE_FAST_FORWARD
) != !!_fast_forward
) {
2477 this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD
);
2483 * Some data on this window has become invalid.
2484 * @param data Information about the changed data.
2485 * @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.
2487 virtual void OnInvalidateData(int data
= 0, bool gui_scope
= true)
2489 if (!gui_scope
) return;
2490 if (FindWindowById(WC_MAIN_WINDOW
, 0) != nullptr) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW
, 0)->viewport
, WID_TE_ZOOM_IN
, WID_TE_ZOOM_OUT
);
2493 virtual void OnQueryTextFinished(char *str
)
2495 /* Was 'cancel' pressed? */
2496 if (str
== nullptr) return;
2499 if (!StrEmpty(str
)) {
2502 /* An empty string means revert to the default */
2503 value
= DEF_START_YEAR
;
2505 SetStartingYear(value
);
2510 static HotkeyList hotkeys
;
2513 static Hotkey scenedit_maintoolbar_hotkeys
[] = {
2514 Hotkey(_maintoolbar_pause_keys
, "pause", MTEHK_PAUSE
),
2515 Hotkey((uint16
)0, "fastforward", MTEHK_FASTFORWARD
),
2516 Hotkey(WKC_F2
, "settings", MTEHK_SETTINGS
),
2517 Hotkey(WKC_F3
, "saveload", MTEHK_SAVEGAME
),
2518 Hotkey(WKC_F4
, "gen_land", MTEHK_GENLAND
),
2519 Hotkey(WKC_F5
, "gen_town", MTEHK_GENTOWN
),
2520 Hotkey(WKC_F6
, "gen_industry", MTEHK_GENINDUSTRY
),
2521 Hotkey(WKC_F7
, "build_road", MTEHK_BUILD_ROAD
),
2522 Hotkey(WKC_F8
, "build_docks", MTEHK_BUILD_DOCKS
),
2523 Hotkey(WKC_F9
, "build_trees", MTEHK_BUILD_TREES
),
2524 Hotkey(WKC_F10
, "build_sign", MTEHK_SIGN
),
2525 Hotkey(WKC_F11
, "music", MTEHK_MUSIC
),
2526 Hotkey(WKC_F12
, "land_info", MTEHK_LANDINFO
),
2527 Hotkey(WKC_CTRL
| 'S', "small_screenshot", MTEHK_SMALL_SCREENSHOT
),
2528 Hotkey(WKC_CTRL
| 'P', "zoomedin_screenshot", MTEHK_ZOOMEDIN_SCREENSHOT
),
2529 Hotkey(WKC_CTRL
| 'D', "defaultzoom_screenshot", MTEHK_DEFAULTZOOM_SCREENSHOT
),
2530 Hotkey((uint16
)0, "giant_screenshot", MTEHK_GIANT_SCREENSHOT
),
2531 Hotkey(_maintoolbar_zoomin_keys
, "zoomin", MTEHK_ZOOM_IN
),
2532 Hotkey(_maintoolbar_zoomout_keys
, "zoomout", MTEHK_ZOOM_OUT
),
2533 Hotkey('L', "terraform", MTEHK_TERRAFORM
),
2534 Hotkey('M', "smallmap", MTEHK_SMALLMAP
),
2535 Hotkey('V', "extra_viewport", MTEHK_EXTRA_VIEWPORT
),
2538 HotkeyList
ScenarioEditorToolbarWindow::hotkeys("scenedit_maintoolbar", scenedit_maintoolbar_hotkeys
);
2540 static const NWidgetPart _nested_toolb_scen_inner_widgets
[] = {
2541 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_PAUSE
), SetDataTip(SPR_IMG_PAUSE
, STR_TOOLBAR_TOOLTIP_PAUSE_GAME
),
2542 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_FAST_FORWARD
), SetDataTip(SPR_IMG_FASTFORWARD
, STR_TOOLBAR_TOOLTIP_FORWARD
),
2543 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_SETTINGS
), SetDataTip(SPR_IMG_SETTINGS
, STR_TOOLBAR_TOOLTIP_OPTIONS
),
2544 NWidget(WWT_IMGBTN_2
, COLOUR_GREY
, WID_TE_SAVE
), SetDataTip(SPR_IMG_SAVE
, STR_SCENEDIT_TOOLBAR_TOOLTIP_SAVE_SCENARIO_LOAD_SCENARIO
),
2545 NWidget(NWID_SPACER
),
2546 NWidget(WWT_PANEL
, COLOUR_GREY
, WID_TE_SPACER
), EndContainer(),
2547 NWidget(NWID_SPACER
),
2548 NWidget(WWT_PANEL
, COLOUR_GREY
, WID_TE_DATE_PANEL
),
2549 NWidget(NWID_HORIZONTAL
), SetPIP(3, 2, 3),
2550 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_DATE_BACKWARD
), SetDataTip(SPR_ARROW_DOWN
, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD
),
2551 NWidget(WWT_EMPTY
, COLOUR_GREY
, WID_TE_DATE
), SetDataTip(STR_NULL
, STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE
),
2552 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_DATE_FORWARD
), SetDataTip(SPR_ARROW_UP
, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD
),
2555 NWidget(NWID_SPACER
),
2556 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_SMALL_MAP
), SetDataTip(SPR_IMG_SMALLMAP
, STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY
),
2557 NWidget(NWID_SPACER
),
2558 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_ZOOM_IN
), SetDataTip(SPR_IMG_ZOOMIN
, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN
),
2559 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_ZOOM_OUT
), SetDataTip(SPR_IMG_ZOOMOUT
, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT
),
2560 NWidget(NWID_SPACER
),
2561 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_LAND_GENERATE
), SetDataTip(SPR_IMG_LANDSCAPING
, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION
),
2562 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_TOWN_GENERATE
), SetDataTip(SPR_IMG_TOWN
, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION
),
2563 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_INDUSTRY
), SetDataTip(SPR_IMG_INDUSTRY
, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION
),
2564 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_ROADS
), SetDataTip(SPR_IMG_BUILDROAD
, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION
),
2565 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_WATER
), SetDataTip(SPR_IMG_BUILDWATER
, STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS
),
2566 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_TREES
), SetDataTip(SPR_IMG_PLANTTREES
, STR_SCENEDIT_TOOLBAR_PLANT_TREES
),
2567 NWidget(WWT_PUSHIMGBTN
, COLOUR_GREY
, WID_TE_SIGNS
), SetDataTip(SPR_IMG_SIGN
, STR_SCENEDIT_TOOLBAR_PLACE_SIGN
),
2568 NWidget(NWID_SPACER
),
2569 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_MUSIC_SOUND
), SetDataTip(SPR_IMG_MUSIC
, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW
),
2570 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_HELP
), SetDataTip(SPR_IMG_QUERY
, STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION
),
2571 NWidget(WWT_IMGBTN
, COLOUR_GREY
, WID_TE_SWITCH_BAR
), SetDataTip(SPR_IMG_SWITCH_TOOLBAR
, STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR
),
2574 static NWidgetBase
*MakeScenarioToolbar(int *biggest_index
)
2576 return MakeNWidgets(_nested_toolb_scen_inner_widgets
, lengthof(_nested_toolb_scen_inner_widgets
), biggest_index
, new NWidgetScenarioToolbarContainer());
2579 static const NWidgetPart _nested_toolb_scen_widgets
[] = {
2580 NWidgetFunction(MakeScenarioToolbar
),
2583 static WindowDesc
_toolb_scen_desc(
2584 WDP_MANUAL
, nullptr, 0, 0,
2585 WC_MAIN_TOOLBAR
, WC_NONE
,
2587 _nested_toolb_scen_widgets
, lengthof(_nested_toolb_scen_widgets
),
2588 &ScenarioEditorToolbarWindow::hotkeys
2591 /** Allocate the toolbar. */
2592 void AllocateToolbar()
2594 /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
2595 _last_built_roadtype
= ROADTYPE_ROAD
;
2597 if (_game_mode
== GM_EDITOR
) {
2598 new ScenarioEditorToolbarWindow(&_toolb_scen_desc
);
2600 new MainToolbarWindow(&_toolb_normal_desc
);