OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

toolbar_gui.cpp
Go to the documentation of this file.
1 /* $Id: toolbar_gui.cpp 27653 2016-09-04 16:06:50Z alberth $ */
2
3 /*
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/>.
8 */
9
12 #include "stdafx.h"
13 #include "gui.h"
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"
19 #include "rail_gui.h"
20 #include "road_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"
33 #include "fios.h"
34 #include "console_gui.h"
35 #include "news_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"
43 #include "hotkeys.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
51 #include "widgets/toolbar_widget.h"
52
53 #include "network/network.h"
54 #include "network/network_gui.h"
55 #include "network/network_func.h"
56
57 #include "safeguards.h"
58
59
61 uint _toolbar_width = 0;
62
63 RailType _last_built_railtype;
64 RoadType _last_built_roadtype;
65
66 static ScreenshotType _confirmed_screenshot_type;
67
69 enum ToolbarMode {
70 TB_NORMAL,
71 TB_UPPER,
72 TB_LOWER
73 };
74
76 enum CallBackFunction {
77 CBF_NONE,
78 CBF_PLACE_SIGN,
79 CBF_PLACE_LANDINFO,
80 };
81
82 static CallBackFunction _last_started_action = CBF_NONE;
83
84
88 class DropDownListCheckedItem : public DropDownListStringItem {
89 uint checkmark_width;
90 public:
91 bool checked;
92
93 DropDownListCheckedItem(StringID string, int result, bool masked, bool checked) : DropDownListStringItem(string, result, masked), checked(checked)
94 {
95 this->checkmark_width = GetStringBoundingBox(STR_JUST_CHECKMARK).width + 3;
96 }
97
98 virtual ~DropDownListCheckedItem() {}
99
100 uint Width() const
101 {
102 return DropDownListStringItem::Width() + this->checkmark_width;
103 }
104
105 void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
106 {
107 bool rtl = _current_text_dir == TD_RTL;
108 if (this->checked) {
109 DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, STR_JUST_CHECKMARK, sel ? TC_WHITE : TC_BLACK);
110 }
111 DrawString(left + WD_FRAMERECT_LEFT + (rtl ? 0 : this->checkmark_width), right - WD_FRAMERECT_RIGHT - (rtl ? this->checkmark_width : 0), top, this->String(), sel ? TC_WHITE : TC_BLACK);
112 }
113 };
114
118 class DropDownListCompanyItem : public DropDownListItem {
119 Dimension icon_size;
120 public:
121 bool greyed;
122
123 DropDownListCompanyItem(int result, bool masked, bool greyed) : DropDownListItem(result, masked), greyed(greyed)
124 {
125 this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
126 }
127
128 virtual ~DropDownListCompanyItem() {}
129
130 bool Selectable() const
131 {
132 return true;
133 }
134
135 uint Width() const
136 {
137 CompanyID company = (CompanyID)this->result;
138 SetDParam(0, company);
139 SetDParam(1, company);
140 return GetStringBoundingBox(STR_COMPANY_NAME_COMPANY_NUM).width + this->icon_size.width + 3;
141 }
142
143 uint Height(uint width) const
144 {
145 return max(this->icon_size.height + 2U, (uint)FONT_HEIGHT_NORMAL);
146 }
147
148 void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
149 {
150 CompanyID company = (CompanyID)this->result;
151 bool rtl = _current_text_dir == TD_RTL;
152
153 /* It's possible the company is deleted while the dropdown is open */
154 if (!Company::IsValidID(company)) return;
155
156 int icon_offset = (bottom - top - icon_size.height) / 2;
157 int text_offset = (bottom - top - FONT_HEIGHT_NORMAL) / 2;
158
159 DrawCompanyIcon(company, rtl ? right - this->icon_size.width - WD_FRAMERECT_RIGHT : left + WD_FRAMERECT_LEFT, top + icon_offset);
160
161 SetDParam(0, company);
162 SetDParam(1, company);
163 TextColour col;
164 if (this->greyed) {
165 col = (sel ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
166 } else {
167 col = sel ? TC_WHITE : TC_BLACK;
168 }
169 DrawString(left + WD_FRAMERECT_LEFT + (rtl ? 0 : 3 + this->icon_size.width), right - WD_FRAMERECT_RIGHT - (rtl ? 3 + this->icon_size.width : 0), top + text_offset, STR_COMPANY_NAME_COMPANY_NUM, col);
170 }
171 };
172
180 static void PopupMainToolbMenu(Window *w, int widget, DropDownList *list, int def)
181 {
182 ShowDropDownList(w, list, def, widget, 0, true, true);
183 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
184 }
185
193 static void PopupMainToolbMenu(Window *w, int widget, StringID string, int count)
194 {
195 DropDownList *list = new DropDownList();
196 for (int i = 0; i < count; i++) {
197 *list->Append() = new DropDownListStringItem(string + i, i, false);
198 }
199 PopupMainToolbMenu(w, widget, list, 0);
200 }
201
203 static const int CTMN_CLIENT_LIST = -1;
204 static const int CTMN_NEW_COMPANY = -2;
205 static const int CTMN_SPECTATE = -3;
206 static const int CTMN_SPECTATOR = -4;
207
215 static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0, bool include_spectator = false)
216 {
217 DropDownList *list = new DropDownList();
218
219 #ifdef ENABLE_NETWORK
220 if (_networking) {
221 if (widget == WID_TN_COMPANIES) {
222 /* Add the client list button for the companies menu */
223 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false);
224 }
225
226 if (include_spectator) {
227 if (widget == WID_TN_COMPANIES) {
228 if (_local_company == COMPANY_SPECTATOR) {
229 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached());
230 } else {
231 *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, NetworkMaxSpectatorsReached());
232 }
233 } else {
234 *list->Append() = new DropDownListStringItem(STR_NETWORK_TOOLBAR_LIST_SPECTATOR, CTMN_SPECTATOR, false);
235 }
236 }
237 }
238 #endif /* ENABLE_NETWORK */
239
240 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
241 if (!Company::IsValidID(c)) continue;
242 *list->Append() = new DropDownListCompanyItem(c, false, HasBit(grey, c));
243 }
244
245 PopupMainToolbMenu(w, widget, list, _local_company == COMPANY_SPECTATOR ? CTMN_CLIENT_LIST : (int)_local_company);
246 }
247
248
249 static ToolbarMode _toolbar_mode;
250
251 static CallBackFunction SelectSignTool()
252 {
253 if (_last_started_action == CBF_PLACE_SIGN) {
254 ResetObjectToPlace();
255 return CBF_NONE;
256 } else {
257 SetObjectToPlace(SPR_CURSOR_SIGN, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0);
258 return CBF_PLACE_SIGN;
259 }
260 }
261
262 /* --- Pausing --- */
263
264 static CallBackFunction ToolbarPauseClick(Window *w)
265 {
266 if (_networking && !_network_server) return CBF_NONE; // only server can pause the game
267
268 if (DoCommandP(0, PM_PAUSED_NORMAL, _pause_mode == PM_UNPAUSED, CMD_PAUSE)) {
269 if (_settings_client.sound.confirm) SndPlayFx(SND_15_BEEP);
270 }
271 return CBF_NONE;
272 }
273
280 static CallBackFunction ToolbarFastForwardClick(Window *w)
281 {
282 _fast_forward ^= true;
283 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
284 return CBF_NONE;
285 }
286
290 enum OptionMenuEntries {
291 OME_GAMEOPTIONS,
292 OME_SETTINGS,
293 OME_SCRIPT_SETTINGS,
294 OME_NEWGRFSETTINGS,
295 OME_TRANSPARENCIES,
296 OME_SHOW_TOWNNAMES,
297 OME_SHOW_STATIONNAMES,
298 OME_SHOW_WAYPOINTNAMES,
299 OME_SHOW_SIGNS,
300 OME_SHOW_COMPETITOR_SIGNS,
301 OME_FULL_ANIMATION,
302 OME_FULL_DETAILS,
303 OME_TRANSPARENTBUILDINGS,
304 OME_SHOW_STATIONSIGNS,
305 };
306
313 static CallBackFunction ToolbarOptionsClick(Window *w)
314 {
315 DropDownList *list = new DropDownList();
316 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS, OME_GAMEOPTIONS, false);
317 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE, OME_SETTINGS, false);
318 /* Changes to the per-AI settings don't get send from the server to the clients. Clients get
319 * the settings once they join but never update it. As such don't show the window at all
320 * to network clients. */
321 if (!_networking || _network_server) *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS, OME_SCRIPT_SETTINGS, false);
322 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS, OME_NEWGRFSETTINGS, false);
323 *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS, OME_TRANSPARENCIES, false);
324 *list->Append() = new DropDownListItem(-1, false);
325 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED, OME_SHOW_TOWNNAMES, false, HasBit(_display_opt, DO_SHOW_TOWN_NAMES));
326 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED, OME_SHOW_STATIONNAMES, false, HasBit(_display_opt, DO_SHOW_STATION_NAMES));
327 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED, OME_SHOW_WAYPOINTNAMES, false, HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES));
328 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED, OME_SHOW_SIGNS, false, HasBit(_display_opt, DO_SHOW_SIGNS));
329 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS, OME_SHOW_COMPETITOR_SIGNS, false, HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS));
330 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION, OME_FULL_ANIMATION, false, HasBit(_display_opt, DO_FULL_ANIMATION));
331 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL, OME_FULL_DETAILS, false, HasBit(_display_opt, DO_FULL_DETAIL));
332 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS, OME_TRANSPARENTBUILDINGS, false, IsTransparencySet(TO_HOUSES));
333 *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS, OME_SHOW_STATIONSIGNS, false, IsTransparencySet(TO_SIGNS));
334
335 ShowDropDownList(w, list, 0, WID_TN_SETTINGS, 140, true, true);
336 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
337 return CBF_NONE;
338 }
339
346 static CallBackFunction MenuClickSettings(int index)
347 {
348 switch (index) {
349 case OME_GAMEOPTIONS: ShowGameOptions(); return CBF_NONE;
350 case OME_SETTINGS: ShowGameSettings(); return CBF_NONE;
351 case OME_SCRIPT_SETTINGS: ShowAIConfigWindow(); return CBF_NONE;
352 case OME_NEWGRFSETTINGS: ShowNewGRFSettings(!_networking && _settings_client.gui.UserIsAllowedToChangeNewGRFs(), true, true, &_grfconfig); return CBF_NONE;
353 case OME_TRANSPARENCIES: ShowTransparencyToolbar(); break;
354
355 case OME_SHOW_TOWNNAMES: ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES); break;
356 case OME_SHOW_STATIONNAMES: ToggleBit(_display_opt, DO_SHOW_STATION_NAMES); break;
357 case OME_SHOW_WAYPOINTNAMES: ToggleBit(_display_opt, DO_SHOW_WAYPOINT_NAMES); break;
358 case OME_SHOW_SIGNS: ToggleBit(_display_opt, DO_SHOW_SIGNS); break;
359 case OME_SHOW_COMPETITOR_SIGNS:
360 ToggleBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS);
361 InvalidateWindowClassesData(WC_SIGN_LIST, -1);
362 break;
363 case OME_FULL_ANIMATION: ToggleBit(_display_opt, DO_FULL_ANIMATION); CheckBlitter(); break;
364 case OME_FULL_DETAILS: ToggleBit(_display_opt, DO_FULL_DETAIL); break;
365 case OME_TRANSPARENTBUILDINGS: ToggleTransparency(TO_HOUSES); break;
366 case OME_SHOW_STATIONSIGNS: ToggleTransparency(TO_SIGNS); break;
367 }
368 MarkWholeScreenDirty();
369 return CBF_NONE;
370 }
371
375 enum SaveLoadEditorMenuEntries {
376 SLEME_SAVE_SCENARIO = 0,
377 SLEME_LOAD_SCENARIO,
378 SLEME_SAVE_HEIGHTMAP,
379 SLEME_LOAD_HEIGHTMAP,
380 SLEME_EXIT_TOINTRO,
381 SLEME_EXIT_GAME = 6,
382 SLEME_MENUCOUNT,
383 };
384
388 enum SaveLoadNormalMenuEntries {
389 SLNME_SAVE_GAME = 0,
390 SLNME_LOAD_GAME,
391 SLNME_EXIT_TOINTRO,
392 SLNME_EXIT_GAME = 4,
393 SLNME_MENUCOUNT,
394 };
395
402 static CallBackFunction ToolbarSaveClick(Window *w)
403 {
404 PopupMainToolbMenu(w, WID_TN_SAVE, STR_FILE_MENU_SAVE_GAME, SLNME_MENUCOUNT);
405 return CBF_NONE;
406 }
407
414 static CallBackFunction ToolbarScenSaveOrLoad(Window *w)
415 {
416 PopupMainToolbMenu(w, WID_TE_SAVE, STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO, SLEME_MENUCOUNT);
417 return CBF_NONE;
418 }
419
426 static CallBackFunction MenuClickSaveLoad(int index = 0)
427 {
428 if (_game_mode == GM_EDITOR) {
429 switch (index) {
430 case SLEME_SAVE_SCENARIO: ShowSaveLoadDialog(FT_SCENARIO, SLO_SAVE); break;
431 case SLEME_LOAD_SCENARIO: ShowSaveLoadDialog(FT_SCENARIO, SLO_LOAD); break;
432 case SLEME_SAVE_HEIGHTMAP: ShowSaveLoadDialog(FT_HEIGHTMAP,SLO_SAVE); break;
433 case SLEME_LOAD_HEIGHTMAP: ShowSaveLoadDialog(FT_HEIGHTMAP,SLO_LOAD); break;
434 case SLEME_EXIT_TOINTRO: AskExitToGameMenu(); break;
435 case SLEME_EXIT_GAME: HandleExitGameRequest(); break;
436 }
437 } else {
438 switch (index) {
439 case SLNME_SAVE_GAME: ShowSaveLoadDialog(FT_SAVEGAME, SLO_SAVE); break;
440 case SLNME_LOAD_GAME: ShowSaveLoadDialog(FT_SAVEGAME, SLO_LOAD); break;
441 case SLNME_EXIT_TOINTRO: AskExitToGameMenu(); break;
442 case SLNME_EXIT_GAME: HandleExitGameRequest(); break;
443 }
444 }
445 return CBF_NONE;
446 }
447
448 /* --- Map button menu --- */
449
450 enum MapMenuEntries {
451 MME_SHOW_SMALLMAP = 0,
452 MME_SHOW_EXTRAVIEWPORTS,
453 MME_SHOW_LINKGRAPH,
454 MME_SHOW_SIGNLISTS,
455 MME_SHOW_TOWNDIRECTORY,
456 MME_SHOW_INDUSTRYDIRECTORY,
457 };
458
459 static CallBackFunction ToolbarMapClick(Window *w)
460 {
461 DropDownList *list = new DropDownList();
462 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false);
463 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false);
464 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_LINGRAPH_LEGEND, MME_SHOW_LINKGRAPH, false);
465 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false);
466 PopupMainToolbMenu(w, WID_TN_SMALL_MAP, list, 0);
467 return CBF_NONE;
468 }
469
470 static CallBackFunction ToolbarScenMapTownDir(Window *w)
471 {
472 DropDownList *list = new DropDownList();
473 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false);
474 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT, MME_SHOW_EXTRAVIEWPORTS, false);
475 *list->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false);
476 *list->Append() = new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY, MME_SHOW_TOWNDIRECTORY, false);
477 *list->Append() = new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, MME_SHOW_INDUSTRYDIRECTORY, false);
478 PopupMainToolbMenu(w, WID_TE_SMALL_MAP, list, 0);
479 return CBF_NONE;
480 }
481
488 static CallBackFunction MenuClickMap(int index)
489 {
490 switch (index) {
491 case MME_SHOW_SMALLMAP: ShowSmallMap(); break;
492 case MME_SHOW_EXTRAVIEWPORTS: ShowExtraViewPortWindow(); break;
493 case MME_SHOW_LINKGRAPH: ShowLinkGraphLegend(); break;
494 case MME_SHOW_SIGNLISTS: ShowSignList(); break;
495 case MME_SHOW_TOWNDIRECTORY: ShowTownDirectory(); break;
496 case MME_SHOW_INDUSTRYDIRECTORY: ShowIndustryDirectory(); break;
497 }
498 return CBF_NONE;
499 }
500
501 /* --- Town button menu --- */
502
503 static CallBackFunction ToolbarTownClick(Window *w)
504 {
505 PopupMainToolbMenu(w, WID_TN_TOWNS, STR_TOWN_MENU_TOWN_DIRECTORY, (_settings_game.economy.found_town == TF_FORBIDDEN) ? 1 : 2);
506 return CBF_NONE;
507 }
508
515 static CallBackFunction MenuClickTown(int index)
516 {
517 switch (index) {
518 case 0: ShowTownDirectory(); break;
519 case 1: // setting could be changed when the dropdown was open
520 if (_settings_game.economy.found_town != TF_FORBIDDEN) ShowFoundTownWindow();
521 break;
522 }
523 return CBF_NONE;
524 }
525
526 /* --- Subidies button menu --- */
527
528 static CallBackFunction ToolbarSubsidiesClick(Window *w)
529 {
530 PopupMainToolbMenu(w, WID_TN_SUBSIDIES, STR_SUBSIDIES_MENU_SUBSIDIES, 1);
531 return CBF_NONE;
532 }
533
540 static CallBackFunction MenuClickSubsidies(int index)
541 {
542 switch (index) {
543 case 0: ShowSubsidiesList(); break;
544 }
545 return CBF_NONE;
546 }
547
548 /* --- Stations button menu --- */
549
550 static CallBackFunction ToolbarStationsClick(Window *w)
551 {
552 PopupMainCompanyToolbMenu(w, WID_TN_STATIONS);
553 return CBF_NONE;
554 }
555
562 static CallBackFunction MenuClickStations(int index)
563 {
564 ShowCompanyStations((CompanyID)index);
565 return CBF_NONE;
566 }
567
568 /* --- Finances button menu --- */
569
570 static CallBackFunction ToolbarFinancesClick(Window *w)
571 {
572 PopupMainCompanyToolbMenu(w, WID_TN_FINANCES);
573 return CBF_NONE;
574 }
575
582 static CallBackFunction MenuClickFinances(int index)
583 {
584 ShowCompanyFinances((CompanyID)index);
585 return CBF_NONE;
586 }
587
588 /* --- Company's button menu --- */
589
590 static CallBackFunction ToolbarCompaniesClick(Window *w)
591 {
592 PopupMainCompanyToolbMenu(w, WID_TN_COMPANIES, 0, true);
593 return CBF_NONE;
594 }
595
602 static CallBackFunction MenuClickCompany(int index)
603 {
604 #ifdef ENABLE_NETWORK
605 if (_networking) {
606 switch (index) {
607 case CTMN_CLIENT_LIST:
608 ShowClientList();
609 return CBF_NONE;
610
611 case CTMN_NEW_COMPANY:
612 if (_network_server) {
613 DoCommandP(0, 0, _network_own_client_id, CMD_COMPANY_CTRL);
614 } else {
615 NetworkSendCommand(0, 0, 0, CMD_COMPANY_CTRL, NULL, NULL, _local_company);
616 }
617 return CBF_NONE;
618
619 case CTMN_SPECTATE:
620 if (_network_server) {
621 NetworkServerDoMove(CLIENT_ID_SERVER, COMPANY_SPECTATOR);
622 MarkWholeScreenDirty();
623 } else {
624 NetworkClientRequestMove(COMPANY_SPECTATOR);
625 }
626 return CBF_NONE;
627 }
628 }
629 #endif /* ENABLE_NETWORK */
630 ShowCompany((CompanyID)index);
631 return CBF_NONE;
632 }
633
634 /* --- Story button menu --- */
635
636 static CallBackFunction ToolbarStoryClick(Window *w)
637 {
638 PopupMainCompanyToolbMenu(w, WID_TN_STORY, 0, true);
639 return CBF_NONE;
640 }
641
648 static CallBackFunction MenuClickStory(int index)
649 {
650 ShowStoryBook(index == CTMN_SPECTATOR ? INVALID_COMPANY : (CompanyID)index);
651 return CBF_NONE;
652 }
653
654 /* --- Goal button menu --- */
655
656 static CallBackFunction ToolbarGoalClick(Window *w)
657 {
658 PopupMainCompanyToolbMenu(w, WID_TN_GOAL, 0, true);
659 return CBF_NONE;
660 }
661
668 static CallBackFunction MenuClickGoal(int index)
669 {
670 ShowGoalsList(index == CTMN_SPECTATOR ? INVALID_COMPANY : (CompanyID)index);
671 return CBF_NONE;
672 }
673
674 /* --- Graphs button menu --- */
675
676 static CallBackFunction ToolbarGraphsClick(Window *w)
677 {
678 PopupMainToolbMenu(w, WID_TN_GRAPHS, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, (_toolbar_mode == TB_NORMAL) ? 6 : 8);
679 return CBF_NONE;
680 }
681
688 static CallBackFunction MenuClickGraphs(int index)
689 {
690 switch (index) {
691 case 0: ShowOperatingProfitGraph(); break;
692 case 1: ShowIncomeGraph(); break;
693 case 2: ShowDeliveredCargoGraph(); break;
694 case 3: ShowPerformanceHistoryGraph(); break;
695 case 4: ShowCompanyValueGraph(); break;
696 case 5: ShowCargoPaymentRates(); break;
697 /* functions for combined graphs/league button */
698 case 6: ShowCompanyLeagueTable(); break;
699 case 7: ShowPerformanceRatingDetail(); break;
700 }
701 return CBF_NONE;
702 }
703
704 /* --- League button menu --- */
705
706 static CallBackFunction ToolbarLeagueClick(Window *w)
707 {
708 PopupMainToolbMenu(w, WID_TN_LEAGUE, STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE, _networking ? 2 : 3);
709 return CBF_NONE;
710 }
711
718 static CallBackFunction MenuClickLeague(int index)
719 {
720 switch (index) {
721 case 0: ShowCompanyLeagueTable(); break;
722 case 1: ShowPerformanceRatingDetail(); break;
723 case 2: ShowHighscoreTable(); break;
724 }
725 return CBF_NONE;
726 }
727
728 /* --- Industries button menu --- */
729
730 static CallBackFunction ToolbarIndustryClick(Window *w)
731 {
732 /* Disable build-industry menu if we are a spectator */
733 PopupMainToolbMenu(w, WID_TN_INDUSTRIES, STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, (_local_company == COMPANY_SPECTATOR) ? 2 : 3);
734 return CBF_NONE;
735 }
736
743 static CallBackFunction MenuClickIndustry(int index)
744 {
745 switch (index) {
746 case 0: ShowIndustryDirectory(); break;
747 case 1: ShowIndustryCargoesWindow(); break;
748 case 2: ShowBuildIndustryWindow(); break;
749 }
750 return CBF_NONE;
751 }
752
753 /* --- Trains button menu + 1 helper function for all vehicles. --- */
754
755 static void ToolbarVehicleClick(Window *w, VehicleType veh)
756 {
757 const Vehicle *v;
758 int dis = ~0;
759
760 FOR_ALL_VEHICLES(v) {
761 if (v->type == veh && v->IsPrimaryVehicle()) ClrBit(dis, v->owner);
762 }
763 PopupMainCompanyToolbMenu(w, WID_TN_VEHICLE_START + veh, dis);
764 }
765
766
767 static CallBackFunction ToolbarTrainClick(Window *w)
768 {
769 ToolbarVehicleClick(w, VEH_TRAIN);
770 return CBF_NONE;
771 }
772
779 static CallBackFunction MenuClickShowTrains(int index)
780 {
781 ShowVehicleListWindow((CompanyID)index, VEH_TRAIN);
782 return CBF_NONE;
783 }
784
785 /* --- Road vehicle button menu --- */
786
787 static CallBackFunction ToolbarRoadClick(Window *w)
788 {
789 ToolbarVehicleClick(w, VEH_ROAD);
790 return CBF_NONE;
791 }
792
799 static CallBackFunction MenuClickShowRoad(int index)
800 {
801 ShowVehicleListWindow((CompanyID)index, VEH_ROAD);
802 return CBF_NONE;
803 }
804
805 /* --- Ship button menu --- */
806
807 static CallBackFunction ToolbarShipClick(Window *w)
808 {
809 ToolbarVehicleClick(w, VEH_SHIP);
810 return CBF_NONE;
811 }
812
819 static CallBackFunction MenuClickShowShips(int index)
820 {
821 ShowVehicleListWindow((CompanyID)index, VEH_SHIP);
822 return CBF_NONE;
823 }
824
825 /* --- Aircraft button menu --- */
826
827 static CallBackFunction ToolbarAirClick(Window *w)
828 {
829 ToolbarVehicleClick(w, VEH_AIRCRAFT);
830 return CBF_NONE;
831 }
832
839 static CallBackFunction MenuClickShowAir(int index)
840 {
841 ShowVehicleListWindow((CompanyID)index, VEH_AIRCRAFT);
842 return CBF_NONE;
843 }
844
845 /* --- Zoom in button --- */
846
847 static CallBackFunction ToolbarZoomInClick(Window *w)
848 {
849 if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
850 w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)WID_TE_ZOOM_IN : (byte)WID_TN_ZOOM_IN);
851 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
852 }
853 return CBF_NONE;
854 }
855
856 /* --- Zoom out button --- */
857
858 static CallBackFunction ToolbarZoomOutClick(Window *w)
859 {
860 if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) {
861 w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)WID_TE_ZOOM_OUT : (byte)WID_TN_ZOOM_OUT);
862 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
863 }
864 return CBF_NONE;
865 }
866
867 /* --- Rail button menu --- */
868
869 static CallBackFunction ToolbarBuildRailClick(Window *w)
870 {
871 ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, WID_TN_RAILS, 140, true, true);
872 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
873 return CBF_NONE;
874 }
875
882 static CallBackFunction MenuClickBuildRail(int index)
883 {
884 _last_built_railtype = (RailType)index;
885 ShowBuildRailToolbar(_last_built_railtype);
886 return CBF_NONE;
887 }
888
889 /* --- Road button menu --- */
890
891 static CallBackFunction ToolbarBuildRoadClick(Window *w)
892 {
893 const Company *c = Company::Get(_local_company);
894 DropDownList *list = new DropDownList();
895
896 /* Road is always visible and available. */
897 *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION, ROADTYPE_ROAD, false);
898
899 /* Tram is only visible when there will be a tram, and available when that has been introduced. */
900 Engine *e;
901 FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
902 if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
903 if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
904
905 *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION, ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM));
906 break;
907 }
908 ShowDropDownList(w, list, _last_built_roadtype, WID_TN_ROADS, 140, true, true);
909 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
910 return CBF_NONE;
911 }
912
919 static CallBackFunction MenuClickBuildRoad(int index)
920 {
921 _last_built_roadtype = (RoadType)index;
922 ShowBuildRoadToolbar(_last_built_roadtype);
923 return CBF_NONE;
924 }
925
926 /* --- Water button menu --- */
927
928 static CallBackFunction ToolbarBuildWaterClick(Window *w)
929 {
930 PopupMainToolbMenu(w, WID_TN_WATER, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION, 1);
931 return CBF_NONE;
932 }
933
940 static CallBackFunction MenuClickBuildWater(int index)
941 {
942 ShowBuildDocksToolbar();
943 return CBF_NONE;
944 }
945
946 /* --- Airport button menu --- */
947
948 static CallBackFunction ToolbarBuildAirClick(Window *w)
949 {
950 PopupMainToolbMenu(w, WID_TN_AIR, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION, 1);
951 return CBF_NONE;
952 }
953
960 static CallBackFunction MenuClickBuildAir(int index)
961 {
962 ShowBuildAirToolbar();
963 return CBF_NONE;
964 }
965
966 /* --- Forest button menu --- */
967
968 static CallBackFunction ToolbarForestClick(Window *w)
969 {
970 PopupMainToolbMenu(w, WID_TN_LANDSCAPE, STR_LANDSCAPING_MENU_LANDSCAPING, 3);
971 return CBF_NONE;
972 }
973
980 static CallBackFunction MenuClickForest(int index)
981 {
982 switch (index) {
983 case 0: ShowTerraformToolbar(); break;
984 case 1: ShowBuildTreesToolbar(); break;
985 case 2: return SelectSignTool();
986 }
987 return CBF_NONE;
988 }
989
990 /* --- Music button menu --- */
991
992 static CallBackFunction ToolbarMusicClick(Window *w)
993 {
994 PopupMainToolbMenu(w, WID_TN_MUSIC_SOUND, STR_TOOLBAR_SOUND_MUSIC, 1);
995 return CBF_NONE;
996 }
997
1004 static CallBackFunction MenuClickMusicWindow(int index)
1005 {
1006 ShowMusicWindow();
1007 return CBF_NONE;
1008 }
1009
1010 /* --- Newspaper button menu --- */
1011
1012 static CallBackFunction ToolbarNewspaperClick(Window *w)
1013 {
1014 PopupMainToolbMenu(w, WID_TN_MESSAGES, STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT, 2);
1015 return CBF_NONE;
1016 }
1017
1024 static CallBackFunction MenuClickNewspaper(int index)
1025 {
1026 switch (index) {
1027 case 0: ShowLastNewsMessage(); break;
1028 case 1: ShowMessageHistory(); break;
1029 }
1030 return CBF_NONE;
1031 }
1032
1033 /* --- Help button menu --- */
1034
1035 static CallBackFunction PlaceLandBlockInfo()
1036 {
1037 if (_last_started_action == CBF_PLACE_LANDINFO) {
1038 ResetObjectToPlace();
1039 return CBF_NONE;
1040 } else {
1041 SetObjectToPlace(SPR_CURSOR_QUERY, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0);
1042 return CBF_PLACE_LANDINFO;
1043 }
1044 }
1045
1046 static CallBackFunction ToolbarHelpClick(Window *w)
1047 {
1048 PopupMainToolbMenu(w, WID_TN_HELP, STR_ABOUT_MENU_LAND_BLOCK_INFO, _settings_client.gui.newgrf_developer_tools ? 12 : 9);
1049 return CBF_NONE;
1050 }
1051
1052 static void MenuClickSmallScreenshot()
1053 {
1054 MakeScreenshot(SC_VIEWPORT, NULL);
1055 }
1056
1062 static void ScreenshotConfirmCallback(Window *w, bool confirmed)
1063 {
1064 if (confirmed) MakeScreenshot(_confirmed_screenshot_type, NULL);
1065 }
1066
1072 static void MenuClickLargeWorldScreenshot(ScreenshotType t)
1073 {
1074 ViewPort vp;
1075 SetupScreenshotViewport(t, &vp);
1076 if ((uint64)vp.width * (uint64)vp.height > 8192 * 8192) {
1077 /* Ask for confirmation */
1078 SetDParam(0, vp.width);
1079 SetDParam(1, vp.height);
1080 _confirmed_screenshot_type = t;
1081 ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, NULL, ScreenshotConfirmCallback);
1082 } else {
1083 /* Less than 64M pixels, just do it */
1084 MakeScreenshot(t, NULL);
1085 }
1086 }
1087
1095 void ToggleBoundingBoxes()
1096 {
1097 extern bool _draw_bounding_boxes;
1098 /* Always allow to toggle them off */
1099 if (_settings_client.gui.newgrf_developer_tools || _draw_bounding_boxes) {
1100 _draw_bounding_boxes = !_draw_bounding_boxes;
1101 MarkWholeScreenDirty();
1102 }
1103 }
1104
1112 void ToggleDirtyBlocks()
1113 {
1114 extern bool _draw_dirty_blocks;
1115 /* Always allow to toggle them off */
1116 if (_settings_client.gui.newgrf_developer_tools || _draw_dirty_blocks) {
1117 _draw_dirty_blocks = !_draw_dirty_blocks;
1118 MarkWholeScreenDirty();
1119 }
1120 }
1121
1126 void SetStartingYear(Year year)
1127 {
1128 _settings_game.game_creation.starting_year = Clamp(year, MIN_YEAR, MAX_YEAR);
1129 Date new_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
1130 /* If you open a savegame as scenario there may already be link graphs.*/
1131 LinkGraphSchedule::instance.ShiftDates(new_date - _date);
1132 SetDate(new_date, 0);
1133 }
1134
1140 static CallBackFunction MenuClickHelp(int index)
1141 {
1142 switch (index) {
1143 case 0: return PlaceLandBlockInfo();
1144 case 2: IConsoleSwitch(); break;
1145 case 3: ShowAIDebugWindow(); break;
1146 case 4: MenuClickSmallScreenshot(); break;
1147 case 5: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
1148 case 6: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
1149 case 7: MenuClickLargeWorldScreenshot(SC_WORLD); break;
1150 case 8: ShowAboutWindow(); break;
1151 case 9: ShowSpriteAlignerWindow(); break;
1152 case 10: ToggleBoundingBoxes(); break;
1153 case 11: ToggleDirtyBlocks(); break;
1154 }
1155 return CBF_NONE;
1156 }
1157
1158 /* --- Switch toolbar button --- */
1159
1160 static CallBackFunction ToolbarSwitchClick(Window *w)
1161 {
1162 if (_toolbar_mode != TB_LOWER) {
1163 _toolbar_mode = TB_LOWER;
1164 } else {
1165 _toolbar_mode = TB_UPPER;
1166 }
1167
1168 w->ReInit();
1169 w->SetWidgetLoweredState(WID_TN_SWITCH_BAR, _toolbar_mode == TB_LOWER);
1170 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1171 return CBF_NONE;
1172 }
1173
1174 /* --- Scenario editor specific handlers. */
1175
1179 static CallBackFunction ToolbarScenDatePanel(Window *w)
1180 {
1181 SetDParam(0, _settings_game.game_creation.starting_year);
1182 ShowQueryString(STR_JUST_INT, STR_MAPGEN_START_DATE_QUERY_CAPT, 8, w, CS_NUMERAL, QSF_ENABLE_DEFAULT);
1183 _left_button_clicked = false;
1184 return CBF_NONE;
1185 }
1186
1187 static CallBackFunction ToolbarScenDateBackward(Window *w)
1188 {
1189 /* don't allow too fast scrolling */
1190 if (!(w->flags & WF_TIMEOUT) || w->timeout_timer <= 1) {
1191 w->HandleButtonClick(WID_TE_DATE_BACKWARD);
1192 w->SetDirty();
1193
1194 SetStartingYear(_settings_game.game_creation.starting_year - 1);
1195 }
1196 _left_button_clicked = false;
1197 return CBF_NONE;
1198 }
1199
1200 static CallBackFunction ToolbarScenDateForward(Window *w)
1201 {
1202 /* don't allow too fast scrolling */
1203 if (!(w->flags & WF_TIMEOUT) || w->timeout_timer <= 1) {
1204 w->HandleButtonClick(WID_TE_DATE_FORWARD);
1205 w->SetDirty();
1206
1207 SetStartingYear(_settings_game.game_creation.starting_year + 1);
1208 }
1209 _left_button_clicked = false;
1210 return CBF_NONE;
1211 }
1212
1213 static CallBackFunction ToolbarScenGenLand(Window *w)
1214 {
1215 w->HandleButtonClick(WID_TE_LAND_GENERATE);
1216 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1217
1218 ShowEditorTerraformToolbar();
1219 return CBF_NONE;
1220 }
1221
1222
1223 static CallBackFunction ToolbarScenGenTown(Window *w)
1224 {
1225 w->HandleButtonClick(WID_TE_TOWN_GENERATE);
1226 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1227 ShowFoundTownWindow();
1228 return CBF_NONE;
1229 }
1230
1231 static CallBackFunction ToolbarScenGenIndustry(Window *w)
1232 {
1233 w->HandleButtonClick(WID_TE_INDUSTRY);
1234 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1235 ShowBuildIndustryWindow();
1236 return CBF_NONE;
1237 }
1238
1239 static CallBackFunction ToolbarScenBuildRoad(Window *w)
1240 {
1241 w->HandleButtonClick(WID_TE_ROADS);
1242 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1243 ShowBuildRoadScenToolbar();
1244 return CBF_NONE;
1245 }
1246
1247 static CallBackFunction ToolbarScenBuildDocks(Window *w)
1248 {
1249 w->HandleButtonClick(WID_TE_WATER);
1250 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1251 ShowBuildDocksScenToolbar();
1252 return CBF_NONE;
1253 }
1254
1255 static CallBackFunction ToolbarScenPlantTrees(Window *w)
1256 {
1257 w->HandleButtonClick(WID_TE_TREES);
1258 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1259 ShowBuildTreesToolbar();
1260 return CBF_NONE;
1261 }
1262
1263 static CallBackFunction ToolbarScenPlaceSign(Window *w)
1264 {
1265 w->HandleButtonClick(WID_TE_SIGNS);
1266 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
1267 return SelectSignTool();
1268 }
1269
1270 static CallBackFunction ToolbarBtn_NULL(Window *w)
1271 {
1272 return CBF_NONE;
1273 }
1274
1275 typedef CallBackFunction MenuClickedProc(int index);
1276
1277 static MenuClickedProc * const _menu_clicked_procs[] = {
1278 NULL, // 0
1279 NULL, // 1
1280 MenuClickSettings, // 2
1281 MenuClickSaveLoad, // 3
1282 MenuClickMap, // 4
1283 MenuClickTown, // 5
1284 MenuClickSubsidies, // 6
1285 MenuClickStations, // 7
1286 MenuClickFinances, // 8
1287 MenuClickCompany, // 9
1288 MenuClickStory, // 10
1289 MenuClickGoal, // 11
1290 MenuClickGraphs, // 12
1291 MenuClickLeague, // 13
1292 MenuClickIndustry, // 14
1293 MenuClickShowTrains, // 15
1294 MenuClickShowRoad, // 16
1295 MenuClickShowShips, // 17
1296 MenuClickShowAir, // 18
1297 MenuClickMap, // 19
1298 NULL, // 20
1299 MenuClickBuildRail, // 21
1300 MenuClickBuildRoad, // 22
1301 MenuClickBuildWater, // 23
1302 MenuClickBuildAir, // 24
1303 MenuClickForest, // 25
1304 MenuClickMusicWindow, // 26
1305 MenuClickNewspaper, // 27
1306 MenuClickHelp, // 28
1307 };
1308
1310 class NWidgetToolbarContainer : public NWidgetContainer {
1311 bool visible[WID_TN_END];
1312 protected:
1313 uint spacers;
1314
1315 public:
1316 NWidgetToolbarContainer() : NWidgetContainer(NWID_HORIZONTAL)
1317 {
1318 }
1319
1325 bool IsButton(WidgetType type) const
1326 {
1327 return type == WWT_IMGBTN || type == WWT_IMGBTN_2 || type == WWT_PUSHIMGBTN;
1328 }
1329
1330 void SetupSmallestSize(Window *w, bool init_array)
1331 {
1332 this->smallest_x = 0; // Biggest child
1333 this->smallest_y = 0; // Biggest child
1334 this->fill_x = 1;
1335 this->fill_y = 0;
1336 this->resize_x = 1; // We only resize in this direction
1337 this->resize_y = 0; // We never resize in this direction
1338 this->spacers = 0;
1339
1340 uint nbuttons = 0;
1341 /* First initialise some variables... */
1342 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1343 child_wid->SetupSmallestSize(w, init_array);
1344 this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
1345 if (this->IsButton(child_wid->type)) {
1346 nbuttons++;
1347 this->smallest_x = max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
1348 } else if (child_wid->type == NWID_SPACER) {
1349 this->spacers++;
1350 }
1351 }
1352
1353 /* ... then in a second pass make sure the 'current' heights are set. Won't change ever. */
1354 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1355 child_wid->current_y = this->smallest_y;
1356 if (!this->IsButton(child_wid->type)) {
1357 child_wid->current_x = child_wid->smallest_x;
1358 }
1359 }
1360 _toolbar_width = nbuttons * this->smallest_x;
1361 }
1362
1363 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
1364 {
1365 assert(given_width >= this->smallest_x && given_height >= this->smallest_y);
1366
1367 this->pos_x = x;
1368 this->pos_y = y;
1369 this->current_x = given_width;
1370 this->current_y = given_height;
1371
1372 /* Figure out what are the visible buttons */
1373 memset(this->visible, 0, sizeof(this->visible));
1374 uint arrangable_count, button_count, spacer_count;
1375 const byte *arrangement = GetButtonArrangement(given_width, arrangable_count, button_count, spacer_count);
1376 for (uint i = 0; i < arrangable_count; i++) {
1377 this->visible[arrangement[i]] = true;
1378 }
1379
1380 /* Create us ourselves a quick lookup table */
1381 NWidgetBase *widgets[WID_TN_END];
1382 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1383 if (child_wid->type == NWID_SPACER) continue;
1384 widgets[((NWidgetCore*)child_wid)->index] = child_wid;
1385 }
1386
1387 /* Now assign the widgets to their rightful place */
1388 uint position = 0; // Place to put next child relative to origin of the container.
1389 uint spacer_space = max(0, (int)given_width - (int)(button_count * this->smallest_x)); // Remaining spacing for 'spacer' widgets
1390 uint button_space = given_width - spacer_space; // Remaining spacing for the buttons
1391 uint spacer_i = 0;
1392 uint button_i = 0;
1393
1394 /* Index into the arrangement indices. The macro lastof cannot be used here! */
1395 const byte *cur_wid = rtl ? &arrangement[arrangable_count - 1] : arrangement;
1396 for (uint i = 0; i < arrangable_count; i++) {
1397 NWidgetBase *child_wid = widgets[*cur_wid];
1398 /* If we have to give space to the spacers, do that */
1399 if (spacer_space != 0) {
1400 NWidgetBase *possible_spacer = rtl ? child_wid->next : child_wid->prev;
1401 if (possible_spacer != NULL && possible_spacer->type == NWID_SPACER) {
1402 uint add = spacer_space / (spacer_count - spacer_i);
1403 position += add;
1404 spacer_space -= add;
1405 spacer_i++;
1406 }
1407 }
1408
1409 /* Buttons can be scaled, the others not. */
1410 if (this->IsButton(child_wid->type)) {
1411 child_wid->current_x = button_space / (button_count - button_i);
1412 button_space -= child_wid->current_x;
1413 button_i++;
1414 }
1415 child_wid->AssignSizePosition(sizing, x + position, y, child_wid->current_x, this->current_y, rtl);
1416 position += child_wid->current_x;
1417
1418 if (rtl) {
1419 cur_wid--;
1420 } else {
1421 cur_wid++;
1422 }
1423 }
1424 }
1425
1426 /* virtual */ void Draw(const Window *w)
1427 {
1428 /* Draw brown-red toolbar bg. */
1429 GfxFillRect(this->pos_x, this->pos_y, this->pos_x + this->current_x - 1, this->pos_y + this->current_y - 1, PC_VERY_DARK_RED);
1430 GfxFillRect(this->pos_x, this->pos_y, this->pos_x + this->current_x - 1, this->pos_y + this->current_y - 1, PC_DARK_RED, FILLRECT_CHECKER);
1431
1432 bool rtl = _current_text_dir == TD_RTL;
1433 for (NWidgetBase *child_wid = rtl ? this->tail : this->head; child_wid != NULL; child_wid = rtl ? child_wid->prev : child_wid->next) {
1434 if (child_wid->type == NWID_SPACER) continue;
1435 if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
1436
1437 child_wid->Draw(w);
1438 }
1439 }
1440
1441 /* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y)
1442 {
1443 if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
1444
1445 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1446 if (child_wid->type == NWID_SPACER) continue;
1447 if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
1448
1449 NWidgetCore *nwid = child_wid->GetWidgetFromPos(x, y);
1450 if (nwid != NULL) return nwid;
1451 }
1452 return NULL;
1453 }
1454
1463 virtual const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const = 0;
1464 };
1465
1467 class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
1468 /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
1469 {
1470 static const uint SMALLEST_ARRANGEMENT = 14;
1471 static const uint BIGGEST_ARRANGEMENT = 20;
1472 static const byte arrange14[] = {
1473 0, 1, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 29,
1474 2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 29,
1475 };
1476 static const byte arrange15[] = {
1477 0, 1, 4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
1478 0, 2, 4, 3, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 29,
1479 };
1480 static const byte arrange16[] = {
1481 0, 1, 2, 4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
1482 0, 1, 3, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 19, 20, 29,
1483 };
1484 static const byte arrange17[] = {
1485 0, 1, 2, 4, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
1486 0, 1, 3, 4, 6, 5, 7, 8, 9, 12, 14, 26, 27, 28, 19, 20, 29,
1487 };
1488 static const byte arrange18[] = {
1489 0, 1, 2, 4, 5, 6, 7, 8, 9, 14, 21, 22, 23, 24, 25, 19, 20, 29,
1490 0, 1, 3, 4, 5, 6, 7, 12, 15, 16, 17, 18, 26, 27, 28, 19, 20, 29,
1491 };
1492 static const byte arrange19[] = {
1493 0, 1, 2, 4, 5, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 19, 20, 29,
1494 0, 1, 3, 4, 7, 8, 9, 12, 14, 27, 21, 22, 23, 24, 25, 28, 19, 20, 29,
1495 };
1496 static const byte arrange20[] = {
1497 0, 1, 2, 4, 5, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 11, 19, 20, 29,
1498 0, 1, 3, 4, 7, 8, 9, 12, 14, 27, 21, 22, 23, 24, 25, 10, 28, 19, 20, 29,
1499 };
1500 static const byte arrange_all[] = {
1501 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28
1502 };
1503
1504 /* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
1505 uint full_buttons = max(CeilDiv(width, this->smallest_x), SMALLEST_ARRANGEMENT);
1506 if (full_buttons > BIGGEST_ARRANGEMENT) {
1507 button_count = arrangable_count = lengthof(arrange_all);
1508 spacer_count = this->spacers;
1509 return arrange_all;
1510 }
1511
1512 /* Introduce the split toolbar */
1513 static const byte * const arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19, arrange20 };
1514
1515 button_count = arrangable_count = full_buttons;
1516 spacer_count = this->spacers;
1517 return arrangements[full_buttons - SMALLEST_ARRANGEMENT] + ((_toolbar_mode == TB_LOWER) ? full_buttons : 0);
1518 }
1519 };
1520
1522 class NWidgetScenarioToolbarContainer : public NWidgetToolbarContainer {
1523 uint panel_widths[2];
1524
1525 void SetupSmallestSize(Window *w, bool init_array)
1526 {
1527 this->NWidgetToolbarContainer::SetupSmallestSize(w, init_array);
1528
1529 /* Find the size of panel_widths */
1530 uint i = 0;
1531 for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
1532 if (child_wid->type == NWID_SPACER || this->IsButton(child_wid->type)) continue;
1533
1534 assert(i < lengthof(this->panel_widths));
1535 this->panel_widths[i++] = child_wid->current_x;
1536 _toolbar_width += child_wid->current_x;
1537 }
1538 }
1539
1540 /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
1541 {
1542 static const byte arrange_all[] = {
1543 0, 1, 2, 3, 4, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 26, 28,
1544 };
1545 static const byte arrange_nopanel[] = {
1546 0, 1, 2, 3, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 26, 28,
1547 };
1548 static const byte arrange_switch[] = {
1549 18, 8, 11, 12, 13, 14, 15, 16, 17, 29,
1550 0, 1, 2, 3, 18, 9, 10, 26, 28, 29,
1551 };
1552
1553 /* If we can place all buttons *and* the panels, show them. */
1554 uint min_full_width = (lengthof(arrange_all) - lengthof(this->panel_widths)) * this->smallest_x + this->panel_widths[0] + this->panel_widths[1];
1555 if (width >= min_full_width) {
1556 width -= this->panel_widths[0] + this->panel_widths[1];
1557 arrangable_count = lengthof(arrange_all);
1558 button_count = arrangable_count - 2;
1559 spacer_count = this->spacers;
1560 return arrange_all;
1561 }
1562
1563 /* 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 */
1564 uint min_small_width = (lengthof(arrange_switch) - lengthof(this->panel_widths)) * this->smallest_x / 2 + this->panel_widths[1];
1565 if (width > min_small_width) {
1566 width -= this->panel_widths[1];
1567 arrangable_count = lengthof(arrange_nopanel);
1568 button_count = arrangable_count - 1;
1569 spacer_count = this->spacers - 1;
1570 return arrange_nopanel;
1571 }
1572
1573 /* Split toolbar */
1574 width -= this->panel_widths[1];
1575 arrangable_count = lengthof(arrange_switch) / 2;
1576 button_count = arrangable_count - 1;
1577 spacer_count = 0;
1578 return arrange_switch + ((_toolbar_mode == TB_LOWER) ? arrangable_count : 0);
1579 }
1580 };
1581
1582 /* --- Toolbar handling for the 'normal' case */
1583
1584 typedef CallBackFunction ToolbarButtonProc(Window *w);
1585
1586 static ToolbarButtonProc * const _toolbar_button_procs[] = {
1587 ToolbarPauseClick,
1588 ToolbarFastForwardClick,
1589 ToolbarOptionsClick,
1590 ToolbarSaveClick,
1591 ToolbarMapClick,
1592 ToolbarTownClick,
1593 ToolbarSubsidiesClick,
1594 ToolbarStationsClick,
1595 ToolbarFinancesClick,
1596 ToolbarCompaniesClick,
1597 ToolbarStoryClick,
1598 ToolbarGoalClick,
1599 ToolbarGraphsClick,
1600 ToolbarLeagueClick,
1601 ToolbarIndustryClick,
1602 ToolbarTrainClick,
1603 ToolbarRoadClick,
1604 ToolbarShipClick,
1605 ToolbarAirClick,
1606 ToolbarZoomInClick,
1607 ToolbarZoomOutClick,
1608 ToolbarBuildRailClick,
1609 ToolbarBuildRoadClick,
1610 ToolbarBuildWaterClick,
1611 ToolbarBuildAirClick,
1612 ToolbarForestClick,
1613 ToolbarMusicClick,
1614 ToolbarNewspaperClick,
1615 ToolbarHelpClick,
1616 ToolbarSwitchClick,
1617 };
1618
1619 enum MainToolbarHotkeys {
1620 MTHK_PAUSE,
1621 MTHK_FASTFORWARD,
1622 MTHK_SETTINGS,
1623 MTHK_SAVEGAME,
1624 MTHK_LOADGAME,
1625 MTHK_SMALLMAP,
1626 MTHK_TOWNDIRECTORY,
1627 MTHK_SUBSIDIES,
1628 MTHK_STATIONS,
1629 MTHK_FINANCES,
1630 MTHK_COMPANIES,
1631 MTHK_STORY,
1632 MTHK_GOAL,
1633 MTHK_GRAPHS,
1634 MTHK_LEAGUE,
1635 MTHK_INDUSTRIES,
1636 MTHK_TRAIN_LIST,
1637 MTHK_ROADVEH_LIST,
1638 MTHK_SHIP_LIST,
1639 MTHK_AIRCRAFT_LIST,
1640 MTHK_ZOOM_IN,
1641 MTHK_ZOOM_OUT,
1642 MTHK_BUILD_RAIL,
1643 MTHK_BUILD_ROAD,
1644 MTHK_BUILD_DOCKS,
1645 MTHK_BUILD_AIRPORT,
1646 MTHK_BUILD_TREES,
1647 MTHK_MUSIC,
1648 MTHK_AI_DEBUG,
1649 MTHK_SMALL_SCREENSHOT,
1650 MTHK_ZOOMEDIN_SCREENSHOT,
1651 MTHK_DEFAULTZOOM_SCREENSHOT,
1652 MTHK_GIANT_SCREENSHOT,
1653 MTHK_CHEATS,
1654 MTHK_TERRAFORM,
1655 MTHK_EXTRA_VIEWPORT,
1656 MTHK_CLIENT_LIST,
1657 MTHK_SIGN_LIST,
1658 };
1659
1661 struct MainToolbarWindow : Window {
1662 MainToolbarWindow(WindowDesc *desc) : Window(desc)
1663 {
1664 this->InitNested(0);
1665
1666 _last_started_action = CBF_NONE;
1667 CLRBITS(this->flags, WF_WHITE_BORDER);
1668 this->SetWidgetDisabledState(WID_TN_PAUSE, _networking && !_network_server); // if not server, disable pause button
1669 this->SetWidgetDisabledState(WID_TN_FAST_FORWARD, _networking); // if networking, disable fast-forward button
1670 PositionMainToolbar(this);
1671 DoZoomInOutWindow(ZOOM_NONE, this);
1672 }
1673
1674 virtual void FindWindowPlacementAndResize(int def_width, int def_height)
1675 {
1676 Window::FindWindowPlacementAndResize(_toolbar_width, def_height);
1677 }
1678
1679 virtual void OnPaint()
1680 {
1681 /* If spectator, disable all construction buttons
1682 * ie : Build road, rail, ships, airports and landscaping
1683 * Since enabled state is the default, just disable when needed */
1684 this->SetWidgetsDisabledState(_local_company == COMPANY_SPECTATOR, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, WID_TN_AIR, WID_TN_LANDSCAPE, WIDGET_LIST_END);
1685 /* disable company list drop downs, if there are no companies */
1686 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);
1687
1688 this->SetWidgetDisabledState(WID_TN_GOAL, Goal::GetNumItems() == 0);
1689 this->SetWidgetDisabledState(WID_TN_STORY, StoryPage::GetNumItems() == 0);
1690
1691 this->SetWidgetDisabledState(WID_TN_RAILS, !CanBuildVehicleInfrastructure(VEH_TRAIN));
1692 this->SetWidgetDisabledState(WID_TN_AIR, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT));
1693
1694 this->DrawWidgets();
1695 }
1696
1697 virtual void OnClick(Point pt, int widget, int click_count)
1698 {
1699 if (_game_mode != GM_MENU && !this->IsWidgetDisabled(widget)) _toolbar_button_procs[widget](this);
1700 }
1701
1702 virtual void OnDropdownSelect(int widget, int index)
1703 {
1704 CallBackFunction cbf = _menu_clicked_procs[widget](index);
1705 if (cbf != CBF_NONE) _last_started_action = cbf;
1706 }
1707
1708 virtual EventState OnHotkey(int hotkey)
1709 {
1710 switch (hotkey) {
1711 case MTHK_PAUSE: ToolbarPauseClick(this); break;
1712 case MTHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
1713 case MTHK_SETTINGS: ShowGameOptions(); break;
1714 case MTHK_SAVEGAME: MenuClickSaveLoad(); break;
1715 case MTHK_LOADGAME: ShowSaveLoadDialog(FT_SAVEGAME, SLO_LOAD); break;
1716 case MTHK_SMALLMAP: ShowSmallMap(); break;
1717 case MTHK_TOWNDIRECTORY: ShowTownDirectory(); break;
1718 case MTHK_SUBSIDIES: ShowSubsidiesList(); break;
1719 case MTHK_STATIONS: ShowCompanyStations(_local_company); break;
1720 case MTHK_FINANCES: ShowCompanyFinances(_local_company); break;
1721 case MTHK_COMPANIES: ShowCompany(_local_company); break;
1722 case MTHK_STORY: ShowStoryBook(_local_company); break;
1723 case MTHK_GOAL: ShowGoalsList(_local_company); break;
1724 case MTHK_GRAPHS: ShowOperatingProfitGraph(); break;
1725 case MTHK_LEAGUE: ShowCompanyLeagueTable(); break;
1726 case MTHK_INDUSTRIES: ShowBuildIndustryWindow(); break;
1727 case MTHK_TRAIN_LIST: ShowVehicleListWindow(_local_company, VEH_TRAIN); break;
1728 case MTHK_ROADVEH_LIST: ShowVehicleListWindow(_local_company, VEH_ROAD); break;
1729 case MTHK_SHIP_LIST: ShowVehicleListWindow(_local_company, VEH_SHIP); break;
1730 case MTHK_AIRCRAFT_LIST: ShowVehicleListWindow(_local_company, VEH_AIRCRAFT); break;
1731 case MTHK_ZOOM_IN: ToolbarZoomInClick(this); break;
1732 case MTHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
1733 case MTHK_BUILD_RAIL: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype); break;
1734 case MTHK_BUILD_ROAD: ShowBuildRoadToolbar(_last_built_roadtype); break;
1735 case MTHK_BUILD_DOCKS: ShowBuildDocksToolbar(); break;
1736 case MTHK_BUILD_AIRPORT: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break;
1737 case MTHK_BUILD_TREES: ShowBuildTreesToolbar(); break;
1738 case MTHK_MUSIC: ShowMusicWindow(); break;
1739 case MTHK_AI_DEBUG: ShowAIDebugWindow(); break;
1740 case MTHK_SMALL_SCREENSHOT: MenuClickSmallScreenshot(); break;
1741 case MTHK_ZOOMEDIN_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
1742 case MTHK_DEFAULTZOOM_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
1743 case MTHK_GIANT_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_WORLD); break;
1744 case MTHK_CHEATS: if (!_networking) ShowCheatWindow(); break;
1745 case MTHK_TERRAFORM: ShowTerraformToolbar(); break;
1746 case MTHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
1747 #ifdef ENABLE_NETWORK
1748 case MTHK_CLIENT_LIST: if (_networking) ShowClientList(); break;
1749 #endif
1750 case MTHK_SIGN_LIST: ShowSignList(); break;
1751 default: return ES_NOT_HANDLED;
1752 }
1753 return ES_HANDLED;
1754 }
1755
1756 virtual void OnPlaceObject(Point pt, TileIndex tile)
1757 {
1758 switch (_last_started_action) {
1759 case CBF_PLACE_SIGN:
1760 PlaceProc_Sign(tile);
1761 break;
1762
1763 case CBF_PLACE_LANDINFO:
1764 ShowLandInfo(tile);
1765 break;
1766
1767 default: NOT_REACHED();
1768 }
1769 }
1770
1771 virtual void OnPlaceObjectAbort()
1772 {
1773 _last_started_action = CBF_NONE;
1774 }
1775
1776 virtual void OnTick()
1777 {
1778 if (this->IsWidgetLowered(WID_TN_PAUSE) != !!_pause_mode) {
1779 this->ToggleWidgetLoweredState(WID_TN_PAUSE);
1780 this->SetWidgetDirty(WID_TN_PAUSE);
1781 }
1782
1783 if (this->IsWidgetLowered(WID_TN_FAST_FORWARD) != !!_fast_forward) {
1784 this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD);
1785 this->SetWidgetDirty(WID_TN_FAST_FORWARD);
1786 }
1787 }
1788
1789 virtual void OnTimeout()
1790 {
1791 /* We do not want to automatically raise the pause, fast forward and
1792 * switchbar buttons; they have to stay down when pressed etc. */
1793 for (uint i = WID_TN_SETTINGS; i < WID_TN_SWITCH_BAR; i++) {
1794 if (this->IsWidgetLowered(i)) {
1795 this->RaiseWidget(i);
1796 this->SetWidgetDirty(i);
1797 }
1798 }
1799 }
1800
1806 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
1807 {
1808 if (!gui_scope) return;
1809 if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT);
1810 }
1811
1812 static HotkeyList hotkeys;
1813 };
1814
1815 const uint16 _maintoolbar_pause_keys[] = {WKC_F1, WKC_PAUSE, 0};
1816 const uint16 _maintoolbar_zoomin_keys[] = {WKC_NUM_PLUS, WKC_EQUALS, WKC_SHIFT | WKC_EQUALS, WKC_SHIFT | WKC_F5, 0};
1817 const uint16 _maintoolbar_zoomout_keys[] = {WKC_NUM_MINUS, WKC_MINUS, WKC_SHIFT | WKC_MINUS, WKC_SHIFT | WKC_F6, 0};
1818 const uint16 _maintoolbar_smallmap_keys[] = {WKC_F4, 'M', 0};
1819
1820 static Hotkey maintoolbar_hotkeys[] = {
1821 Hotkey(_maintoolbar_pause_keys, "pause", MTHK_PAUSE),
1822 Hotkey((uint16)0, "fastforward", MTHK_FASTFORWARD),
1823 Hotkey(WKC_F2, "settings", MTHK_SETTINGS),
1824 Hotkey(WKC_F3, "saveload", MTHK_SAVEGAME),
1825 Hotkey((uint16)0, "load_game", MTHK_LOADGAME),
1826 Hotkey(_maintoolbar_smallmap_keys, "smallmap", MTHK_SMALLMAP),
1827 Hotkey(WKC_F5, "town_list", MTHK_TOWNDIRECTORY),
1828 Hotkey(WKC_F6, "subsidies", MTHK_SUBSIDIES),
1829 Hotkey(WKC_F7, "station_list", MTHK_STATIONS),
1830 Hotkey(WKC_F8, "finances", MTHK_FINANCES),
1831 Hotkey(WKC_F9, "companies", MTHK_COMPANIES),
1832 Hotkey((uint16)0, "story_book", MTHK_STORY),
1833 Hotkey((uint16)0, "goal_list", MTHK_GOAL),
1834 Hotkey(WKC_F10, "graphs", MTHK_GRAPHS),
1835 Hotkey(WKC_F11, "league", MTHK_LEAGUE),
1836 Hotkey(WKC_F12, "industry_list", MTHK_INDUSTRIES),
1837 Hotkey(WKC_SHIFT | WKC_F1, "train_list", MTHK_TRAIN_LIST),
1838 Hotkey(WKC_SHIFT | WKC_F2, "roadveh_list", MTHK_ROADVEH_LIST),
1839 Hotkey(WKC_SHIFT | WKC_F3, "ship_list", MTHK_SHIP_LIST),
1840 Hotkey(WKC_SHIFT | WKC_F4, "aircraft_list", MTHK_AIRCRAFT_LIST),
1841 Hotkey(_maintoolbar_zoomin_keys, "zoomin", MTHK_ZOOM_IN),
1842 Hotkey(_maintoolbar_zoomout_keys, "zoomout", MTHK_ZOOM_OUT),
1843 Hotkey(WKC_SHIFT | WKC_F7, "build_rail", MTHK_BUILD_RAIL),
1844 Hotkey(WKC_SHIFT | WKC_F8, "build_road", MTHK_BUILD_ROAD),
1845 Hotkey(WKC_SHIFT | WKC_F9, "build_docks", MTHK_BUILD_DOCKS),
1846 Hotkey(WKC_SHIFT | WKC_F10, "build_airport", MTHK_BUILD_AIRPORT),
1847 Hotkey(WKC_SHIFT | WKC_F11, "build_trees", MTHK_BUILD_TREES),
1848 Hotkey(WKC_SHIFT | WKC_F12, "music", MTHK_MUSIC),
1849 Hotkey((uint16)0, "ai_debug", MTHK_AI_DEBUG),
1850 Hotkey(WKC_CTRL | 'S', "small_screenshot", MTHK_SMALL_SCREENSHOT),
1851 Hotkey(WKC_CTRL | 'P', "zoomedin_screenshot", MTHK_ZOOMEDIN_SCREENSHOT),
1852 Hotkey(WKC_CTRL | 'D', "defaultzoom_screenshot", MTHK_DEFAULTZOOM_SCREENSHOT),
1853 Hotkey((uint16)0, "giant_screenshot", MTHK_GIANT_SCREENSHOT),
1854 Hotkey(WKC_CTRL | WKC_ALT | 'C', "cheats", MTHK_CHEATS),
1855 Hotkey('L', "terraform", MTHK_TERRAFORM),
1856 Hotkey('V', "extra_viewport", MTHK_EXTRA_VIEWPORT),
1857 #ifdef ENABLE_NETWORK
1858 Hotkey((uint16)0, "client_list", MTHK_CLIENT_LIST),
1859 #endif
1860 Hotkey((uint16)0, "sign_list", MTHK_SIGN_LIST),
1861 HOTKEY_LIST_END
1862 };
1863 HotkeyList MainToolbarWindow::hotkeys("maintoolbar", maintoolbar_hotkeys);
1864
1865 static NWidgetBase *MakeMainToolbar(int *biggest_index)
1866 {
1868 static const SpriteID toolbar_button_sprites[] = {
1869 SPR_IMG_PAUSE, // WID_TN_PAUSE
1870 SPR_IMG_FASTFORWARD, // WID_TN_FAST_FORWARD
1871 SPR_IMG_SETTINGS, // WID_TN_SETTINGS
1872 SPR_IMG_SAVE, // WID_TN_SAVE
1873 SPR_IMG_SMALLMAP, // WID_TN_SMALL_MAP
1874 SPR_IMG_TOWN, // WID_TN_TOWNS
1875 SPR_IMG_SUBSIDIES, // WID_TN_SUBSIDIES
1876 SPR_IMG_COMPANY_LIST, // WID_TN_STATIONS
1877 SPR_IMG_COMPANY_FINANCE, // WID_TN_FINANCES
1878 SPR_IMG_COMPANY_GENERAL, // WID_TN_COMPANIES
1879 SPR_IMG_STORY_BOOK, // WID_TN_STORY
1880 SPR_IMG_GOAL, // WID_TN_GOAL
1881 SPR_IMG_GRAPHS, // WID_TN_GRAPHS
1882 SPR_IMG_COMPANY_LEAGUE, // WID_TN_LEAGUE
1883 SPR_IMG_INDUSTRY, // WID_TN_INDUSTRIES
1884 SPR_IMG_TRAINLIST, // WID_TN_TRAINS
1885 SPR_IMG_TRUCKLIST, // WID_TN_ROADVEHS
1886 SPR_IMG_SHIPLIST, // WID_TN_SHIPS
1887 SPR_IMG_AIRPLANESLIST, // WID_TN_AIRCRAFT
1888 SPR_IMG_ZOOMIN, // WID_TN_ZOOMIN
1889 SPR_IMG_ZOOMOUT, // WID_TN_ZOOMOUT
1890 SPR_IMG_BUILDRAIL, // WID_TN_RAILS
1891 SPR_IMG_BUILDROAD, // WID_TN_ROADS
1892 SPR_IMG_BUILDWATER, // WID_TN_WATER
1893 SPR_IMG_BUILDAIR, // WID_TN_AIR
1894 SPR_IMG_LANDSCAPING, // WID_TN_LANDSCAPE
1895 SPR_IMG_MUSIC, // WID_TN_MUSIC_SOUND
1896 SPR_IMG_MESSAGES, // WID_TN_MESSAGES
1897 SPR_IMG_QUERY, // WID_TN_HELP
1898 SPR_IMG_SWITCH_TOOLBAR, // WID_TN_SWITCH_BAR
1899 };
1900
1901 NWidgetMainToolbarContainer *hor = new NWidgetMainToolbarContainer();
1902 for (uint i = 0; i < WID_TN_END; i++) {
1903 switch (i) {
1904 case 4: case 8: case 15: case 19: case 21: case 26: hor->Add(new NWidgetSpacer(0, 0)); break;
1905 }
1906 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));
1907 }
1908
1909 *biggest_index = max<int>(*biggest_index, WID_TN_SWITCH_BAR);
1910 return hor;
1911 }
1912
1913 static const NWidgetPart _nested_toolbar_normal_widgets[] = {
1914 NWidgetFunction(MakeMainToolbar),
1915 };
1916
1917 static WindowDesc _toolb_normal_desc(
1918 WDP_MANUAL, NULL, 0, 0,
1919 WC_MAIN_TOOLBAR, WC_NONE,
1920 WDF_NO_FOCUS,
1921 _nested_toolbar_normal_widgets, lengthof(_nested_toolbar_normal_widgets),
1922 &MainToolbarWindow::hotkeys
1923 );
1924
1925
1926 /* --- Toolbar handling for the scenario editor */
1927
1928 static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
1929 ToolbarPauseClick,
1930 ToolbarFastForwardClick,
1931 ToolbarOptionsClick,
1932 ToolbarScenSaveOrLoad,
1933 ToolbarBtn_NULL,
1934 ToolbarScenDatePanel,
1935 ToolbarScenDateBackward,
1936 ToolbarScenDateForward,
1937 ToolbarScenMapTownDir,
1938 ToolbarZoomInClick,
1939 ToolbarZoomOutClick,
1940 ToolbarScenGenLand,
1941 ToolbarScenGenTown,
1942 ToolbarScenGenIndustry,
1943 ToolbarScenBuildRoad,
1944 ToolbarScenBuildDocks,
1945 ToolbarScenPlantTrees,
1946 ToolbarScenPlaceSign,
1947 ToolbarBtn_NULL,
1948 NULL,
1949 NULL,
1950 NULL,
1951 NULL,
1952 NULL,
1953 NULL,
1954 NULL,
1955 ToolbarMusicClick,
1956 NULL,
1957 ToolbarHelpClick,
1958 ToolbarSwitchClick,
1959 };
1960
1961 enum MainToolbarEditorHotkeys {
1962 MTEHK_PAUSE,
1963 MTEHK_FASTFORWARD,
1964 MTEHK_SETTINGS,
1965 MTEHK_SAVEGAME,
1966 MTEHK_GENLAND,
1967 MTEHK_GENTOWN,
1968 MTEHK_GENINDUSTRY,
1969 MTEHK_BUILD_ROAD,
1970 MTEHK_BUILD_DOCKS,
1971 MTEHK_BUILD_TREES,
1972 MTEHK_SIGN,
1973 MTEHK_MUSIC,
1974 MTEHK_LANDINFO,
1975 MTEHK_SMALL_SCREENSHOT,
1976 MTEHK_ZOOMEDIN_SCREENSHOT,
1977 MTEHK_DEFAULTZOOM_SCREENSHOT,
1978 MTEHK_GIANT_SCREENSHOT,
1979 MTEHK_ZOOM_IN,
1980 MTEHK_ZOOM_OUT,
1981 MTEHK_TERRAFORM,
1982 MTEHK_SMALLMAP,
1983 MTEHK_EXTRA_VIEWPORT,
1984 };
1985
1986 struct ScenarioEditorToolbarWindow : Window {
1987 ScenarioEditorToolbarWindow(WindowDesc *desc) : Window(desc)
1988 {
1989 this->InitNested(0);
1990
1991 _last_started_action = CBF_NONE;
1992 CLRBITS(this->flags, WF_WHITE_BORDER);
1993 PositionMainToolbar(this);
1994 DoZoomInOutWindow(ZOOM_NONE, this);
1995 }
1996
1997 virtual void FindWindowPlacementAndResize(int def_width, int def_height)
1998 {
1999 Window::FindWindowPlacementAndResize(_toolbar_width, def_height);
2000 }
2001
2002 virtual void OnPaint()
2003 {
2004 this->SetWidgetDisabledState(WID_TE_DATE_BACKWARD, _settings_game.game_creation.starting_year <= MIN_YEAR);
2005 this->SetWidgetDisabledState(WID_TE_DATE_FORWARD, _settings_game.game_creation.starting_year >= MAX_YEAR);
2006
2007 this->DrawWidgets();
2008 }
2009
2010 virtual void DrawWidget(const Rect &r, int widget) const
2011 {
2012 switch (widget) {
2013 case WID_TE_DATE:
2014 SetDParam(0, ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
2015 DrawString(r.left, r.right, (this->height - FONT_HEIGHT_NORMAL) / 2, STR_WHITE_DATE_LONG, TC_FROMSTRING, SA_HOR_CENTER);
2016 break;
2017
2018 case WID_TE_SPACER: {
2019 int height = r.bottom - r.top;
2020 if (height > 2 * FONT_HEIGHT_NORMAL) {
2021 DrawString(r.left, r.right, (height + 1) / 2 - FONT_HEIGHT_NORMAL, STR_SCENEDIT_TOOLBAR_OPENTTD, TC_FROMSTRING, SA_HOR_CENTER);
2022 DrawString(r.left, r.right, (height + 1) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
2023 } else {
2024 DrawString(r.left, r.right, (height - FONT_HEIGHT_NORMAL) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
2025 }
2026 break;
2027 }
2028 }
2029 }
2030
2031 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2032 {
2033 switch (widget) {
2034 case WID_TE_SPACER:
2035 size->width = max(GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_OPENTTD).width, GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR).width) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
2036 break;
2037
2038 case WID_TE_DATE:
2039 SetDParam(0, ConvertYMDToDate(MAX_YEAR, 0, 1));
2040 *size = GetStringBoundingBox(STR_WHITE_DATE_LONG);
2041 size->height = max(size->height, GetSpriteSize(SPR_IMG_SAVE).height + WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM);
2042 break;
2043 }
2044 }
2045
2046 virtual void OnClick(Point pt, int widget, int click_count)
2047 {
2048 if (_game_mode == GM_MENU) return;
2049 CallBackFunction cbf = _scen_toolbar_button_procs[widget](this);
2050 if (cbf != CBF_NONE) _last_started_action = cbf;
2051 }
2052
2053 virtual void OnDropdownSelect(int widget, int index)
2054 {
2055 /* The map button is in a different location on the scenario
2056 * editor toolbar, so we need to adjust for it. */
2057 if (widget == WID_TE_SMALL_MAP) widget = WID_TN_SMALL_MAP;
2058 CallBackFunction cbf = _menu_clicked_procs[widget](index);
2059 if (cbf != CBF_NONE) _last_started_action = cbf;
2060 if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
2061 }
2062
2063 virtual EventState OnHotkey(int hotkey)
2064 {
2065 CallBackFunction cbf = CBF_NONE;
2066 switch (hotkey) {
2067 case MTEHK_PAUSE: ToolbarPauseClick(this); break;
2068 case MTEHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
2069 case MTEHK_SETTINGS: ShowGameOptions(); break;
2070 case MTEHK_SAVEGAME: MenuClickSaveLoad(); break;
2071 case MTEHK_GENLAND: ToolbarScenGenLand(this); break;
2072 case MTEHK_GENTOWN: ToolbarScenGenTown(this); break;
2073 case MTEHK_GENINDUSTRY: ToolbarScenGenIndustry(this); break;
2074 case MTEHK_BUILD_ROAD: ToolbarScenBuildRoad(this); break;
2075 case MTEHK_BUILD_DOCKS: ToolbarScenBuildDocks(this); break;
2076 case MTEHK_BUILD_TREES: ToolbarScenPlantTrees(this); break;
2077 case MTEHK_SIGN: cbf = ToolbarScenPlaceSign(this); break;
2078 case MTEHK_MUSIC: ShowMusicWindow(); break;
2079 case MTEHK_LANDINFO: cbf = PlaceLandBlockInfo(); break;
2080 case MTEHK_SMALL_SCREENSHOT: MenuClickSmallScreenshot(); break;
2081 case MTEHK_ZOOMEDIN_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
2082 case MTEHK_DEFAULTZOOM_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
2083 case MTEHK_GIANT_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_WORLD); break;
2084 case MTEHK_ZOOM_IN: ToolbarZoomInClick(this); break;
2085 case MTEHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
2086 case MTEHK_TERRAFORM: ShowEditorTerraformToolbar(); break;
2087 case MTEHK_SMALLMAP: ShowSmallMap(); break;
2088 case MTEHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
2089 default: return ES_NOT_HANDLED;
2090 }
2091 if (cbf != CBF_NONE) _last_started_action = cbf;
2092 return ES_HANDLED;
2093 }
2094
2095 virtual void OnPlaceObject(Point pt, TileIndex tile)
2096 {
2097 switch (_last_started_action) {
2098 case CBF_PLACE_SIGN:
2099 PlaceProc_Sign(tile);
2100 break;
2101
2102 case CBF_PLACE_LANDINFO:
2103 ShowLandInfo(tile);
2104 break;
2105
2106 default: NOT_REACHED();
2107 }
2108 }
2109
2110 virtual void OnPlaceObjectAbort()
2111 {
2112 _last_started_action = CBF_NONE;
2113 }
2114
2115 virtual void OnTimeout()
2116 {
2117 this->SetWidgetsLoweredState(false, WID_TE_DATE_BACKWARD, WID_TE_DATE_FORWARD, WIDGET_LIST_END);
2118 this->SetWidgetDirty(WID_TE_DATE_BACKWARD);
2119 this->SetWidgetDirty(WID_TE_DATE_FORWARD);
2120 }
2121
2122 virtual void OnTick()
2123 {
2124 if (this->IsWidgetLowered(WID_TE_PAUSE) != !!_pause_mode) {
2125 this->ToggleWidgetLoweredState(WID_TE_PAUSE);
2126 this->SetDirty();
2127 }
2128
2129 if (this->IsWidgetLowered(WID_TE_FAST_FORWARD) != !!_fast_forward) {
2130 this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD);
2131 this->SetDirty();
2132 }
2133 }
2134
2140 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2141 {
2142 if (!gui_scope) return;
2143 if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, WID_TE_ZOOM_IN, WID_TE_ZOOM_OUT);
2144 }
2145
2146 virtual void OnQueryTextFinished(char *str)
2147 {
2148 /* Was 'cancel' pressed? */
2149 if (str == NULL) return;
2150
2151 int32 value;
2152 if (!StrEmpty(str)) {
2153 value = atoi(str);
2154 } else {
2155 /* An empty string means revert to the default */
2156 value = DEF_START_YEAR;
2157 }
2158 SetStartingYear(value);
2159
2160 this->SetDirty();
2161 }
2162
2163 static HotkeyList hotkeys;
2164 };
2165
2166 static Hotkey scenedit_maintoolbar_hotkeys[] = {
2167 Hotkey(_maintoolbar_pause_keys, "pause", MTEHK_PAUSE),
2168 Hotkey((uint16)0, "fastforward", MTEHK_FASTFORWARD),
2169 Hotkey(WKC_F2, "settings", MTEHK_SETTINGS),
2170 Hotkey(WKC_F3, "saveload", MTEHK_SAVEGAME),
2171 Hotkey(WKC_F4, "gen_land", MTEHK_GENLAND),
2172 Hotkey(WKC_F5, "gen_town", MTEHK_GENTOWN),
2173 Hotkey(WKC_F6, "gen_industry", MTEHK_GENINDUSTRY),
2174 Hotkey(WKC_F7, "build_road", MTEHK_BUILD_ROAD),
2175 Hotkey(WKC_F8, "build_docks", MTEHK_BUILD_DOCKS),
2176 Hotkey(WKC_F9, "build_trees", MTEHK_BUILD_TREES),
2177 Hotkey(WKC_F10, "build_sign", MTEHK_SIGN),
2178 Hotkey(WKC_F11, "music", MTEHK_MUSIC),
2179 Hotkey(WKC_F12, "land_info", MTEHK_LANDINFO),
2180 Hotkey(WKC_CTRL | 'S', "small_screenshot", MTEHK_SMALL_SCREENSHOT),
2181 Hotkey(WKC_CTRL | 'P', "zoomedin_screenshot", MTEHK_ZOOMEDIN_SCREENSHOT),
2182 Hotkey(WKC_CTRL | 'D', "defaultzoom_screenshot", MTEHK_DEFAULTZOOM_SCREENSHOT),
2183 Hotkey((uint16)0, "giant_screenshot", MTEHK_GIANT_SCREENSHOT),
2184 Hotkey(_maintoolbar_zoomin_keys, "zoomin", MTEHK_ZOOM_IN),
2185 Hotkey(_maintoolbar_zoomout_keys, "zoomout", MTEHK_ZOOM_OUT),
2186 Hotkey('L', "terraform", MTEHK_TERRAFORM),
2187 Hotkey('M', "smallmap", MTEHK_SMALLMAP),
2188 Hotkey('V', "extra_viewport", MTEHK_EXTRA_VIEWPORT),
2189 HOTKEY_LIST_END
2190 };
2191 HotkeyList ScenarioEditorToolbarWindow::hotkeys("scenedit_maintoolbar", scenedit_maintoolbar_hotkeys);
2192
2193 static const NWidgetPart _nested_toolb_scen_inner_widgets[] = {
2194 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_PAUSE), SetDataTip(SPR_IMG_PAUSE, STR_TOOLBAR_TOOLTIP_PAUSE_GAME),
2195 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_FAST_FORWARD), SetDataTip(SPR_IMG_FASTFORWARD, STR_TOOLBAR_TOOLTIP_FORWARD),
2196 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SETTINGS), SetDataTip(SPR_IMG_SETTINGS, STR_TOOLBAR_TOOLTIP_OPTIONS),
2197 NWidget(WWT_IMGBTN_2, COLOUR_GREY, WID_TE_SAVE), SetDataTip(SPR_IMG_SAVE, STR_SCENEDIT_TOOLBAR_TOOLTIP_SAVE_SCENARIO_LOAD_SCENARIO),
2198 NWidget(NWID_SPACER),
2199 NWidget(WWT_PANEL, COLOUR_GREY, WID_TE_SPACER), EndContainer(),
2200 NWidget(NWID_SPACER),
2201 NWidget(WWT_PANEL, COLOUR_GREY, WID_TE_DATE_PANEL),
2202 NWidget(NWID_HORIZONTAL), SetPIP(3, 2, 3),
2203 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_DATE_BACKWARD), SetDataTip(SPR_ARROW_DOWN, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD),
2204 NWidget(WWT_EMPTY, COLOUR_GREY, WID_TE_DATE), SetDataTip(STR_NULL, STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE),
2205 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_DATE_FORWARD), SetDataTip(SPR_ARROW_UP, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD),
2206 EndContainer(),
2207 EndContainer(),
2208 NWidget(NWID_SPACER),
2209 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SMALL_MAP), SetDataTip(SPR_IMG_SMALLMAP, STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY),
2210 NWidget(NWID_SPACER),
2211 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_IN), SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN),
2212 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_OUT), SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT),
2213 NWidget(NWID_SPACER),
2214 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_LAND_GENERATE), SetDataTip(SPR_IMG_LANDSCAPING, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION),
2215 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TOWN_GENERATE), SetDataTip(SPR_IMG_TOWN, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION),
2216 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_INDUSTRY), SetDataTip(SPR_IMG_INDUSTRY, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION),
2217 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ROADS), SetDataTip(SPR_IMG_BUILDROAD, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION),
2218 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_WATER), SetDataTip(SPR_IMG_BUILDWATER, STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS),
2219 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TREES), SetDataTip(SPR_IMG_PLANTTREES, STR_SCENEDIT_TOOLBAR_PLANT_TREES),
2220 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_SIGNS), SetDataTip(SPR_IMG_SIGN, STR_SCENEDIT_TOOLBAR_PLACE_SIGN),
2221 NWidget(NWID_SPACER),
2222 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_MUSIC_SOUND), SetDataTip(SPR_IMG_MUSIC, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW),
2223 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_HELP), SetDataTip(SPR_IMG_QUERY, STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION),
2224 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SWITCH_BAR), SetDataTip(SPR_IMG_SWITCH_TOOLBAR, STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR),
2225 };
2226
2227 static NWidgetBase *MakeScenarioToolbar(int *biggest_index)
2228 {
2229 return MakeNWidgets(_nested_toolb_scen_inner_widgets, lengthof(_nested_toolb_scen_inner_widgets), biggest_index, new NWidgetScenarioToolbarContainer());
2230 }
2231
2232 static const NWidgetPart _nested_toolb_scen_widgets[] = {
2233 NWidgetFunction(MakeScenarioToolbar),
2234 };
2235
2236 static WindowDesc _toolb_scen_desc(
2237 WDP_MANUAL, NULL, 0, 0,
2238 WC_MAIN_TOOLBAR, WC_NONE,
2239 WDF_NO_FOCUS,
2240 _nested_toolb_scen_widgets, lengthof(_nested_toolb_scen_widgets),
2241 &ScenarioEditorToolbarWindow::hotkeys
2242 );
2243
2245 void AllocateToolbar()
2246 {
2247 /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
2248 _last_built_roadtype = ROADTYPE_ROAD;
2249
2250 if (_game_mode == GM_EDITOR) {
2251 new ScenarioEditorToolbarWindow(&_toolb_scen_desc);
2252 } else {
2253 new MainToolbarWindow(&_toolb_normal_desc);
2254 }
2255 }