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