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