# toolbar_gui.cpp

Go to the documentation of this file.

    00001 /* $Id: toolbar_gui.cpp 26314 2014-02-06 22:24:02Z frosch $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "gui.h"
    00014 #include "window_gui.h"
    00015 #include "window_func.h"
    00016 #include "viewport_func.h"
    00017 #include "command_func.h"
    00018 #include "vehicle_gui.h"
    00019 #include "rail_gui.h"
    00020 #include "road_gui.h"
    00021 #include "date_func.h"
    00022 #include "vehicle_func.h"
    00023 #include "sound_func.h"
    00024 #include "terraform_gui.h"
    00025 #include "strings_func.h"
    00026 #include "company_func.h"
    00027 #include "company_gui.h"
    00028 #include "vehicle_base.h"
    00029 #include "cheat_func.h"
    00030 #include "transparency_gui.h"
    00031 #include "screenshot.h"
    00032 #include "signs_func.h"
    00033 #include "fios.h"
    00034 #include "console_gui.h"
    00035 #include "news_gui.h"
    00036 #include "ai/ai_gui.hpp"
    00037 #include "tilehighlight_func.h"
    00038 #include "smallmap_gui.h"
    00039 #include "graph_gui.h"
    00040 #include "textbuf_gui.h"
    00041 #include "linkgraph/linkgraph_gui.h"
    00042 #include "newgrf_debug.h"
    00043 #include "hotkeys.h"
    00044 #include "engine_base.h"
    00045 #include "highscore.h"
    00046 #include "game/game.hpp"
    00047 #include "goal_base.h"
    00048 #include "story_base.h"
    00049
    00050 #include "widgets/toolbar_widget.h"
    00051
    00052 #include "network/network.h"
    00053 #include "network/network_gui.h"
    00054 #include "network/network_func.h"
    00055
    00056
    00057 RailType _last_built_railtype;
    00058 RoadType _last_built_roadtype;
    00059
    00060 static ScreenshotType _confirmed_screenshot_type;
    00061
    00063 enum ToolbarMode {
    00064   TB_NORMAL,
    00065   TB_UPPER,
    00066   TB_LOWER
    00067 };
    00068
    00070 enum CallBackFunction {
    00071   CBF_NONE,
    00072   CBF_PLACE_SIGN,
    00073   CBF_PLACE_LANDINFO,
    00074 };
    00075
    00079 class DropDownListCheckedItem : public DropDownListStringItem {
    00080   uint checkmark_width;
    00081 public:
    00082   bool checked;
    00083
    00084   DropDownListCheckedItem(StringID string, int result, bool masked, bool checked) : DropDownListStringItem(string, result, masked), checked(checked)
    00085   {
    00086     this->checkmark_width = GetStringBoundingBox(STR_JUST_CHECKMARK).width + 3;
    00087   }
    00088
    00089   virtual ~DropDownListCheckedItem() {}
    00090
    00091   uint Width() const
    00092   {
    00093     return DropDownListStringItem::Width() + this->checkmark_width;
    00094   }
    00095
    00096   void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
    00097   {
    00098     bool rtl = _current_text_dir == TD_RTL;
    00099     if (this->checked) {
    00100       DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, STR_JUST_CHECKMARK, sel ? TC_WHITE : TC_BLACK);
    00101     }
    00102     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);
    00103   }
    00104 };
    00105
    00109 class DropDownListCompanyItem : public DropDownListItem {
    00110   Dimension icon_size;
    00111 public:
    00112   bool greyed;
    00113
    00114   DropDownListCompanyItem(int result, bool masked, bool greyed) : DropDownListItem(result, masked), greyed(greyed)
    00115   {
    00116     this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
    00117   }
    00118
    00119   virtual ~DropDownListCompanyItem() {}
    00120
    00121   bool Selectable() const
    00122   {
    00123     return true;
    00124   }
    00125
    00126   uint Width() const
    00127   {
    00128     CompanyID company = (CompanyID)this->result;
    00129     SetDParam(0, company);
    00130     SetDParam(1, company);
    00131     return GetStringBoundingBox(STR_COMPANY_NAME_COMPANY_NUM).width + this->icon_size.width + 3;
    00132   }
    00133
    00134   uint Height(uint width) const
    00135   {
    00136     return max(this->icon_size.height + 2U, (uint)FONT_HEIGHT_NORMAL);
    00137   }
    00138
    00139   void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
    00140   {
    00141     CompanyID company = (CompanyID)this->result;
    00142     bool rtl = _current_text_dir == TD_RTL;
    00143
    00144     /* It's possible the company is deleted while the dropdown is open */
    00145     if (!Company::IsValidID(company)) return;
    00146
    00147     int icon_offset = (bottom - top - icon_size.height) / 2;
    00148     int text_offset = (bottom - top - FONT_HEIGHT_NORMAL) / 2;
    00149
    00150     DrawCompanyIcon(company, rtl ? right - this->icon_size.width - WD_FRAMERECT_RIGHT : left + WD_FRAMERECT_LEFT, top + icon_offset);
    00151
    00152     SetDParam(0, company);
    00153     SetDParam(1, company);
    00154     TextColour col;
    00155     if (this->greyed) {
    00156       col = (sel ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
    00157     } else {
    00158       col = sel ? TC_WHITE : TC_BLACK;
    00159     }
    00160     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);
    00161   }
    00162 };
    00163
    00171 static void PopupMainToolbMenu(Window *w, int widget, DropDownList *list, int def)
    00172 {
    00173   ShowDropDownList(w, list, def, widget, 0, true, true);
    00174   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    00175 }
    00176
    00184 static void PopupMainToolbMenu(Window *w, int widget, StringID string, int count)
    00185 {
    00186   DropDownList *list = new DropDownList();
    00187   for (int i = 0; i < count; i++) {
    00188     *list->Append() = new DropDownListStringItem(string + i, i, false);
    00189   }
    00190   PopupMainToolbMenu(w, widget, list, 0);
    00191 }
    00192
    00194 static const int CTMN_CLIENT_LIST = -1;
    00195 static const int CTMN_NEW_COMPANY = -2;
    00196 static const int CTMN_SPECTATE    = -3;
    00197 static const int CTMN_SPECTATOR   = -4;
    00198
    00206 static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0, bool include_spectator = false)
    00207 {
    00208   DropDownList *list = new DropDownList();
    00209
    00210 #ifdef ENABLE_NETWORK
    00211   if (_networking) {
    00212     if (widget == WID_TN_COMPANIES) {
    00213       /* Add the client list button for the companies menu */
    00214       *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false);
    00215     }
    00216
    00217     if (include_spectator) {
    00218       if (widget == WID_TN_COMPANIES) {
    00219         if (_local_company == COMPANY_SPECTATOR) {
    00220           *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached());
    00221         } else {
    00222           *list->Append() = new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, NetworkMaxSpectatorsReached());
    00223         }
    00224       } else {
    00225         *list->Append() = new DropDownListStringItem(STR_NETWORK_TOOLBAR_LIST_SPECTATOR, CTMN_SPECTATOR, false);
    00226       }
    00227     }
    00228   }
    00229 #endif /* ENABLE_NETWORK */
    00230
    00231   for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
    00232     if (!Company::IsValidID(c)) continue;
    00233     *list->Append() = new DropDownListCompanyItem(c, false, HasBit(grey, c));
    00234   }
    00235
    00236   PopupMainToolbMenu(w, widget, list, _local_company == COMPANY_SPECTATOR ? CTMN_CLIENT_LIST : (int)_local_company);
    00237 }
    00238
    00239
    00240 static ToolbarMode _toolbar_mode;
    00241
    00242 static CallBackFunction SelectSignTool()
    00243 {
    00244   if (_cursor.sprite == SPR_CURSOR_SIGN) {
    00245     ResetObjectToPlace();
    00246     return CBF_NONE;
    00247   } else {
    00248     SetObjectToPlace(SPR_CURSOR_SIGN, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0);
    00249     return CBF_PLACE_SIGN;
    00250   }
    00251 }
    00252
    00253 /* --- Pausing --- */
    00254
    00255 static CallBackFunction ToolbarPauseClick(Window *w)
    00256 {
    00257   if (_networking && !_network_server) return CBF_NONE; // only server can pause the game
    00258
    00259   if (DoCommandP(0, PM_PAUSED_NORMAL, _pause_mode == PM_UNPAUSED, CMD_PAUSE)) {
    00260     if (_settings_client.sound.confirm) SndPlayFx(SND_15_BEEP);
    00261   }
    00262   return CBF_NONE;
    00263 }
    00264
    00271 static CallBackFunction ToolbarFastForwardClick(Window *w)
    00272 {
    00273   _fast_forward ^= true;
    00274   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    00275   return CBF_NONE;
    00276 }
    00277
    00281 enum OptionMenuEntries {
    00282   OME_GAMEOPTIONS,
    00283   OME_SETTINGS,
    00284   OME_SCRIPT_SETTINGS,
    00285   OME_NEWGRFSETTINGS,
    00286   OME_TRANSPARENCIES,
    00287   OME_SHOW_TOWNNAMES,
    00288   OME_SHOW_STATIONNAMES,
    00289   OME_SHOW_WAYPOINTNAMES,
    00290   OME_SHOW_SIGNS,
    00291   OME_SHOW_COMPETITOR_SIGNS,
    00292   OME_FULL_ANIMATION,
    00293   OME_FULL_DETAILS,
    00294   OME_TRANSPARENTBUILDINGS,
    00295   OME_SHOW_STATIONSIGNS,
    00296 };
    00297
    00304 static CallBackFunction ToolbarOptionsClick(Window *w)
    00305 {
    00306   DropDownList *list = new DropDownList();
    00307   *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS,             OME_GAMEOPTIONS, false);
    00308   *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS,          OME_SETTINGS, false);
    00309   /* Changes to the per-AI settings don't get send from the server to the clients. Clients get
    00310    * the settings once they join but never update it. As such don't show the window at all
    00311    * to network clients. */
    00312   if (!_networking || _network_server) *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_SCRIPT_SETTINGS, OME_SCRIPT_SETTINGS, false);
    00313   *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS,          OME_NEWGRFSETTINGS, false);
    00314   *list->Append() = new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS,     OME_TRANSPARENCIES, false);
    00315   *list->Append() = new DropDownListItem(-1, false);
    00316   *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED,    OME_SHOW_TOWNNAMES, false, HasBit(_display_opt, DO_SHOW_TOWN_NAMES));
    00317   *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED, OME_SHOW_STATIONNAMES, false, HasBit(_display_opt, DO_SHOW_STATION_NAMES));
    00318   *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED,     OME_SHOW_WAYPOINTNAMES, false, HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES));
    00319   *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED,         OME_SHOW_SIGNS, false, HasBit(_display_opt, DO_SHOW_SIGNS));
    00320   *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS,   OME_SHOW_COMPETITOR_SIGNS, false, HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS));
    00321   *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION,          OME_FULL_ANIMATION, false, HasBit(_display_opt, DO_FULL_ANIMATION));
    00322   *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL,             OME_FULL_DETAILS, false, HasBit(_display_opt, DO_FULL_DETAIL));
    00323   *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS,   OME_TRANSPARENTBUILDINGS, false, IsTransparencySet(TO_HOUSES));
    00324   *list->Append() = new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS,       OME_SHOW_STATIONSIGNS, false, IsTransparencySet(TO_SIGNS));
    00325
    00326   ShowDropDownList(w, list, 0, WID_TN_SETTINGS, 140, true, true);
    00327   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    00328   return CBF_NONE;
    00329 }
    00330
    00337 static CallBackFunction MenuClickSettings(int index)
    00338 {
    00339   switch (index) {
    00340     case OME_GAMEOPTIONS:          ShowGameOptions();                               return CBF_NONE;
    00341     case OME_SETTINGS:             ShowGameSettings();                              return CBF_NONE;
    00342     case OME_SCRIPT_SETTINGS:      ShowAIConfigWindow();                            return CBF_NONE;
    00343     case OME_NEWGRFSETTINGS:       ShowNewGRFSettings(!_networking && _settings_client.gui.UserIsAllowedToChangeNewGRFs(), true, true, &_grfconfig); return CBF_NONE;
    00344     case OME_TRANSPARENCIES:       ShowTransparencyToolbar();                       break;
    00345
    00346     case OME_SHOW_TOWNNAMES:       ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES);     break;
    00347     case OME_SHOW_STATIONNAMES:    ToggleBit(_display_opt, DO_SHOW_STATION_NAMES);  break;
    00348     case OME_SHOW_WAYPOINTNAMES:   ToggleBit(_display_opt, DO_SHOW_WAYPOINT_NAMES); break;
    00349     case OME_SHOW_SIGNS:           ToggleBit(_display_opt, DO_SHOW_SIGNS);          break;
    00350     case OME_SHOW_COMPETITOR_SIGNS:
    00351       ToggleBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS);
    00352       InvalidateWindowClassesData(WC_SIGN_LIST, -1);
    00353       break;
    00354     case OME_FULL_ANIMATION:       ToggleBit(_display_opt, DO_FULL_ANIMATION); CheckBlitter(); break;
    00355     case OME_FULL_DETAILS:         ToggleBit(_display_opt, DO_FULL_DETAIL);         break;
    00356     case OME_TRANSPARENTBUILDINGS: ToggleTransparency(TO_HOUSES);                   break;
    00357     case OME_SHOW_STATIONSIGNS:    ToggleTransparency(TO_SIGNS);                    break;
    00358   }
    00359   MarkWholeScreenDirty();
    00360   return CBF_NONE;
    00361 }
    00362
    00366 enum SaveLoadEditorMenuEntries {
    00367   SLEME_SAVE_SCENARIO   = 0,
    00368   SLEME_LOAD_SCENARIO,
    00369   SLEME_SAVE_HEIGHTMAP,
    00370   SLEME_LOAD_HEIGHTMAP,
    00371   SLEME_EXIT_TOINTRO,
    00372   SLEME_EXIT_GAME       = 6,
    00373   SLEME_MENUCOUNT,
    00374 };
    00375
    00379 enum SaveLoadNormalMenuEntries {
    00380   SLNME_SAVE_GAME   = 0,
    00381   SLNME_LOAD_GAME,
    00382   SLNME_EXIT_TOINTRO,
    00383   SLNME_EXIT_GAME = 4,
    00384   SLNME_MENUCOUNT,
    00385 };
    00386
    00393 static CallBackFunction ToolbarSaveClick(Window *w)
    00394 {
    00395   PopupMainToolbMenu(w, WID_TN_SAVE, STR_FILE_MENU_SAVE_GAME, SLNME_MENUCOUNT);
    00396   return CBF_NONE;
    00397 }
    00398
    00405 static CallBackFunction ToolbarScenSaveOrLoad(Window *w)
    00406 {
    00407   PopupMainToolbMenu(w, WID_TE_SAVE, STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO, SLEME_MENUCOUNT);
    00408   return CBF_NONE;
    00409 }
    00410
    00417 static CallBackFunction MenuClickSaveLoad(int index = 0)
    00418 {
    00419   if (_game_mode == GM_EDITOR) {
    00420     switch (index) {
    00421       case SLEME_SAVE_SCENARIO:  ShowSaveLoadDialog(SLD_SAVE_SCENARIO);  break;
    00422       case SLEME_LOAD_SCENARIO:  ShowSaveLoadDialog(SLD_LOAD_SCENARIO);  break;
    00423       case SLEME_SAVE_HEIGHTMAP: ShowSaveLoadDialog(SLD_SAVE_HEIGHTMAP); break;
    00424       case SLEME_LOAD_HEIGHTMAP: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break;
    00425       case SLEME_EXIT_TOINTRO:   AskExitToGameMenu();                    break;
    00426       case SLEME_EXIT_GAME:      HandleExitGameRequest();                break;
    00427     }
    00428   } else {
    00429     switch (index) {
    00430       case SLNME_SAVE_GAME:      ShowSaveLoadDialog(SLD_SAVE_GAME); break;
    00431       case SLNME_LOAD_GAME:      ShowSaveLoadDialog(SLD_LOAD_GAME); break;
    00432       case SLNME_EXIT_TOINTRO:   AskExitToGameMenu();               break;
    00433       case SLNME_EXIT_GAME:      HandleExitGameRequest();           break;
    00434     }
    00435   }
    00436   return CBF_NONE;
    00437 }
    00438
    00439 /* --- Map button menu --- */
    00440
    00441 enum MapMenuEntries {
    00442   MME_SHOW_SMALLMAP        = 0,
    00443   MME_SHOW_EXTRAVIEWPORTS,
    00444   MME_SHOW_LINKGRAPH,
    00445   MME_SHOW_SIGNLISTS,
    00446   MME_SHOW_TOWNDIRECTORY,
    00447   MME_SHOW_INDUSTRYDIRECTORY,
    00448 };
    00449
    00450 static CallBackFunction ToolbarMapClick(Window *w)
    00451 {
    00452   DropDownList *list = new DropDownList();
    00453   *list->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD,            MME_SHOW_SMALLMAP,          false);
    00454   *list->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT,         MME_SHOW_EXTRAVIEWPORTS,    false);
    00455   *list->Append() = new DropDownListStringItem(STR_MAP_MENU_LINGRAPH_LEGEND,         MME_SHOW_LINKGRAPH,         false);
    00456   *list->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST,               MME_SHOW_SIGNLISTS,         false);
    00457   PopupMainToolbMenu(w, WID_TN_SMALL_MAP, list, 0);
    00458   return CBF_NONE;
    00459 }
    00460
    00461 static CallBackFunction ToolbarScenMapTownDir(Window *w)
    00462 {
    00463   DropDownList *list = new DropDownList();
    00464   *list->Append() = new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD,            MME_SHOW_SMALLMAP,          false);
    00465   *list->Append() = new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEW_PORT,         MME_SHOW_EXTRAVIEWPORTS,    false);
    00466   *list->Append() = new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST,               MME_SHOW_SIGNLISTS,         false);
    00467   *list->Append() = new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY,         MME_SHOW_TOWNDIRECTORY,     false);
    00468   *list->Append() = new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, MME_SHOW_INDUSTRYDIRECTORY, false);
    00469   PopupMainToolbMenu(w, WID_TE_SMALL_MAP, list, 0);
    00470   return CBF_NONE;
    00471 }
    00472
    00479 static CallBackFunction MenuClickMap(int index)
    00480 {
    00481   switch (index) {
    00482     case MME_SHOW_SMALLMAP:       ShowSmallMap();            break;
    00483     case MME_SHOW_EXTRAVIEWPORTS: ShowExtraViewPortWindow(); break;
    00484     case MME_SHOW_LINKGRAPH:      ShowLinkGraphLegend();     break;
    00485     case MME_SHOW_SIGNLISTS:      ShowSignList();            break;
    00486     case MME_SHOW_TOWNDIRECTORY:  ShowTownDirectory();       break;
    00487     case MME_SHOW_INDUSTRYDIRECTORY: ShowIndustryDirectory(); break;
    00488   }
    00489   return CBF_NONE;
    00490 }
    00491
    00492 /* --- Town button menu --- */
    00493
    00494 static CallBackFunction ToolbarTownClick(Window *w)
    00495 {
    00496   PopupMainToolbMenu(w, WID_TN_TOWNS, STR_TOWN_MENU_TOWN_DIRECTORY, (_settings_game.economy.found_town == TF_FORBIDDEN) ? 1 : 2);
    00497   return CBF_NONE;
    00498 }
    00499
    00506 static CallBackFunction MenuClickTown(int index)
    00507 {
    00508   switch (index) {
    00509     case 0: ShowTownDirectory(); break;
    00510     case 1: // setting could be changed when the dropdown was open
    00511       if (_settings_game.economy.found_town != TF_FORBIDDEN) ShowFoundTownWindow();
    00512       break;
    00513   }
    00514   return CBF_NONE;
    00515 }
    00516
    00517 /* --- Subidies button menu --- */
    00518
    00519 static CallBackFunction ToolbarSubsidiesClick(Window *w)
    00520 {
    00521   PopupMainToolbMenu(w, WID_TN_SUBSIDIES, STR_SUBSIDIES_MENU_SUBSIDIES, 1);
    00522   return CBF_NONE;
    00523 }
    00524
    00531 static CallBackFunction MenuClickSubsidies(int index)
    00532 {
    00533   switch (index) {
    00534     case 0: ShowSubsidiesList(); break;
    00535   }
    00536   return CBF_NONE;
    00537 }
    00538
    00539 /* --- Stations button menu --- */
    00540
    00541 static CallBackFunction ToolbarStationsClick(Window *w)
    00542 {
    00543   PopupMainCompanyToolbMenu(w, WID_TN_STATIONS);
    00544   return CBF_NONE;
    00545 }
    00546
    00553 static CallBackFunction MenuClickStations(int index)
    00554 {
    00555   ShowCompanyStations((CompanyID)index);
    00556   return CBF_NONE;
    00557 }
    00558
    00559 /* --- Finances button menu --- */
    00560
    00561 static CallBackFunction ToolbarFinancesClick(Window *w)
    00562 {
    00563   PopupMainCompanyToolbMenu(w, WID_TN_FINANCES);
    00564   return CBF_NONE;
    00565 }
    00566
    00573 static CallBackFunction MenuClickFinances(int index)
    00574 {
    00575   ShowCompanyFinances((CompanyID)index);
    00576   return CBF_NONE;
    00577 }
    00578
    00579 /* --- Company's button menu --- */
    00580
    00581 static CallBackFunction ToolbarCompaniesClick(Window *w)
    00582 {
    00583   PopupMainCompanyToolbMenu(w, WID_TN_COMPANIES, 0, true);
    00584   return CBF_NONE;
    00585 }
    00586
    00593 static CallBackFunction MenuClickCompany(int index)
    00594 {
    00595 #ifdef ENABLE_NETWORK
    00596   if (_networking) {
    00597     switch (index) {
    00598       case CTMN_CLIENT_LIST:
    00599         ShowClientList();
    00600         return CBF_NONE;
    00601
    00602       case CTMN_NEW_COMPANY:
    00603         if (_network_server) {
    00604           DoCommandP(0, 0, _network_own_client_id, CMD_COMPANY_CTRL);
    00605         } else {
    00606           NetworkSendCommand(0, 0, 0, CMD_COMPANY_CTRL, NULL, NULL, _local_company);
    00607         }
    00608         return CBF_NONE;
    00609
    00610       case CTMN_SPECTATE:
    00611         if (_network_server) {
    00612           NetworkServerDoMove(CLIENT_ID_SERVER, COMPANY_SPECTATOR);
    00613           MarkWholeScreenDirty();
    00614         } else {
    00615           NetworkClientRequestMove(COMPANY_SPECTATOR);
    00616         }
    00617         return CBF_NONE;
    00618     }
    00619   }
    00620 #endif /* ENABLE_NETWORK */
    00621   ShowCompany((CompanyID)index);
    00622   return CBF_NONE;
    00623 }
    00624
    00625 /* --- Story button menu --- */
    00626
    00627 static CallBackFunction ToolbarStoryClick(Window *w)
    00628 {
    00629   PopupMainCompanyToolbMenu(w, WID_TN_STORY, 0, true);
    00630   return CBF_NONE;
    00631 }
    00632
    00639 static CallBackFunction MenuClickStory(int index)
    00640 {
    00641   ShowStoryBook(index == CTMN_SPECTATOR ? INVALID_COMPANY : (CompanyID)index);
    00642   return CBF_NONE;
    00643 }
    00644
    00645 /* --- Goal button menu --- */
    00646
    00647 static CallBackFunction ToolbarGoalClick(Window *w)
    00648 {
    00649   PopupMainCompanyToolbMenu(w, WID_TN_GOAL, 0, true);
    00650   return CBF_NONE;
    00651 }
    00652
    00659 static CallBackFunction MenuClickGoal(int index)
    00660 {
    00661   ShowGoalsList(index == CTMN_SPECTATOR ? INVALID_COMPANY : (CompanyID)index);
    00662   return CBF_NONE;
    00663 }
    00664
    00665 /* --- Graphs button menu --- */
    00666
    00667 static CallBackFunction ToolbarGraphsClick(Window *w)
    00668 {
    00669   PopupMainToolbMenu(w, WID_TN_GRAPHS, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, (_toolbar_mode == TB_NORMAL) ? 6 : 8);
    00670   return CBF_NONE;
    00671 }
    00672
    00679 static CallBackFunction MenuClickGraphs(int index)
    00680 {
    00681   switch (index) {
    00682     case 0: ShowOperatingProfitGraph();    break;
    00683     case 1: ShowIncomeGraph();             break;
    00684     case 2: ShowDeliveredCargoGraph();     break;
    00685     case 3: ShowPerformanceHistoryGraph(); break;
    00686     case 4: ShowCompanyValueGraph();       break;
    00687     case 5: ShowCargoPaymentRates();       break;
    00688     /* functions for combined graphs/league button */
    00689     case 6: ShowCompanyLeagueTable();      break;
    00690     case 7: ShowPerformanceRatingDetail(); break;
    00691   }
    00692   return CBF_NONE;
    00693 }
    00694
    00695 /* --- League button menu --- */
    00696
    00697 static CallBackFunction ToolbarLeagueClick(Window *w)
    00698 {
    00699   PopupMainToolbMenu(w, WID_TN_LEAGUE, STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE, _networking ? 2 : 3);
    00700   return CBF_NONE;
    00701 }
    00702
    00709 static CallBackFunction MenuClickLeague(int index)
    00710 {
    00711   switch (index) {
    00712     case 0: ShowCompanyLeagueTable();      break;
    00713     case 1: ShowPerformanceRatingDetail(); break;
    00714     case 2: ShowHighscoreTable();          break;
    00715   }
    00716   return CBF_NONE;
    00717 }
    00718
    00719 /* --- Industries button menu --- */
    00720
    00721 static CallBackFunction ToolbarIndustryClick(Window *w)
    00722 {
    00723   /* Disable build-industry menu if we are a spectator */
    00724   PopupMainToolbMenu(w, WID_TN_INDUSTRIES, STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, (_local_company == COMPANY_SPECTATOR) ? 2 : 3);
    00725   return CBF_NONE;
    00726 }
    00727
    00734 static CallBackFunction MenuClickIndustry(int index)
    00735 {
    00736   switch (index) {
    00737     case 0: ShowIndustryDirectory();     break;
    00738     case 1: ShowIndustryCargoesWindow(); break;
    00739     case 2: ShowBuildIndustryWindow();   break;
    00740   }
    00741   return CBF_NONE;
    00742 }
    00743
    00744 /* --- Trains button menu + 1 helper function for all vehicles. --- */
    00745
    00746 static void ToolbarVehicleClick(Window *w, VehicleType veh)
    00747 {
    00748   const Vehicle *v;
    00749   int dis = ~0;
    00750
    00751   FOR_ALL_VEHICLES(v) {
    00752     if (v->type == veh && v->IsPrimaryVehicle()) ClrBit(dis, v->owner);
    00753   }
    00754   PopupMainCompanyToolbMenu(w, WID_TN_VEHICLE_START + veh, dis);
    00755 }
    00756
    00757
    00758 static CallBackFunction ToolbarTrainClick(Window *w)
    00759 {
    00760   ToolbarVehicleClick(w, VEH_TRAIN);
    00761   return CBF_NONE;
    00762 }
    00763
    00770 static CallBackFunction MenuClickShowTrains(int index)
    00771 {
    00772   ShowVehicleListWindow((CompanyID)index, VEH_TRAIN);
    00773   return CBF_NONE;
    00774 }
    00775
    00776 /* --- Road vehicle button menu --- */
    00777
    00778 static CallBackFunction ToolbarRoadClick(Window *w)
    00779 {
    00780   ToolbarVehicleClick(w, VEH_ROAD);
    00781   return CBF_NONE;
    00782 }
    00783
    00790 static CallBackFunction MenuClickShowRoad(int index)
    00791 {
    00792   ShowVehicleListWindow((CompanyID)index, VEH_ROAD);
    00793   return CBF_NONE;
    00794 }
    00795
    00796 /* --- Ship button menu --- */
    00797
    00798 static CallBackFunction ToolbarShipClick(Window *w)
    00799 {
    00800   ToolbarVehicleClick(w, VEH_SHIP);
    00801   return CBF_NONE;
    00802 }
    00803
    00810 static CallBackFunction MenuClickShowShips(int index)
    00811 {
    00812   ShowVehicleListWindow((CompanyID)index, VEH_SHIP);
    00813   return CBF_NONE;
    00814 }
    00815
    00816 /* --- Aircraft button menu --- */
    00817
    00818 static CallBackFunction ToolbarAirClick(Window *w)
    00819 {
    00820   ToolbarVehicleClick(w, VEH_AIRCRAFT);
    00821   return CBF_NONE;
    00822 }
    00823
    00830 static CallBackFunction MenuClickShowAir(int index)
    00831 {
    00832   ShowVehicleListWindow((CompanyID)index, VEH_AIRCRAFT);
    00833   return CBF_NONE;
    00834 }
    00835
    00836 /* --- Zoom in button --- */
    00837
    00838 static CallBackFunction ToolbarZoomInClick(Window *w)
    00839 {
    00840   if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
    00841     w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)WID_TE_ZOOM_IN : (byte)WID_TN_ZOOM_IN);
    00842     if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    00843   }
    00844   return CBF_NONE;
    00845 }
    00846
    00847 /* --- Zoom out button --- */
    00848
    00849 static CallBackFunction ToolbarZoomOutClick(Window *w)
    00850 {
    00851   if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) {
    00852     w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)WID_TE_ZOOM_OUT : (byte)WID_TN_ZOOM_OUT);
    00853     if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    00854   }
    00855   return CBF_NONE;
    00856 }
    00857
    00858 /* --- Rail button menu --- */
    00859
    00860 static CallBackFunction ToolbarBuildRailClick(Window *w)
    00861 {
    00862   ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, WID_TN_RAILS, 140, true, true);
    00863   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    00864   return CBF_NONE;
    00865 }
    00866
    00873 static CallBackFunction MenuClickBuildRail(int index)
    00874 {
    00875   _last_built_railtype = (RailType)index;
    00876   ShowBuildRailToolbar(_last_built_railtype);
    00877   return CBF_NONE;
    00878 }
    00879
    00880 /* --- Road button menu --- */
    00881
    00882 static CallBackFunction ToolbarBuildRoadClick(Window *w)
    00883 {
    00884   const Company *c = Company::Get(_local_company);
    00885   DropDownList *list = new DropDownList();
    00886
    00887   /* Road is always visible and available. */
    00888   *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION, ROADTYPE_ROAD, false);
    00889
    00890   /* Tram is only visible when there will be a tram, and available when that has been introduced. */
    00891   Engine *e;
    00892   FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
    00893     if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
    00894     if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
    00895
    00896     *list->Append() = new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION, ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM));
    00897     break;
    00898   }
    00899   ShowDropDownList(w, list, _last_built_roadtype, WID_TN_ROADS, 140, true, true);
    00900   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    00901   return CBF_NONE;
    00902 }
    00903
    00910 static CallBackFunction MenuClickBuildRoad(int index)
    00911 {
    00912   _last_built_roadtype = (RoadType)index;
    00913   ShowBuildRoadToolbar(_last_built_roadtype);
    00914   return CBF_NONE;
    00915 }
    00916
    00917 /* --- Water button menu --- */
    00918
    00919 static CallBackFunction ToolbarBuildWaterClick(Window *w)
    00920 {
    00921   PopupMainToolbMenu(w, WID_TN_WATER, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION, 1);
    00922   return CBF_NONE;
    00923 }
    00924
    00931 static CallBackFunction MenuClickBuildWater(int index)
    00932 {
    00933   ShowBuildDocksToolbar();
    00934   return CBF_NONE;
    00935 }
    00936
    00937 /* --- Airport button menu --- */
    00938
    00939 static CallBackFunction ToolbarBuildAirClick(Window *w)
    00940 {
    00941   PopupMainToolbMenu(w, WID_TN_AIR, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION, 1);
    00942   return CBF_NONE;
    00943 }
    00944
    00951 static CallBackFunction MenuClickBuildAir(int index)
    00952 {
    00953   ShowBuildAirToolbar();
    00954   return CBF_NONE;
    00955 }
    00956
    00957 /* --- Forest button menu --- */
    00958
    00959 static CallBackFunction ToolbarForestClick(Window *w)
    00960 {
    00961   PopupMainToolbMenu(w, WID_TN_LANDSCAPE, STR_LANDSCAPING_MENU_LANDSCAPING, 3);
    00962   return CBF_NONE;
    00963 }
    00964
    00971 static CallBackFunction MenuClickForest(int index)
    00972 {
    00973   switch (index) {
    00974     case 0: ShowTerraformToolbar();  break;
    00975     case 1: ShowBuildTreesToolbar(); break;
    00976     case 2: return SelectSignTool();
    00977   }
    00978   return CBF_NONE;
    00979 }
    00980
    00981 /* --- Music button menu --- */
    00982
    00983 static CallBackFunction ToolbarMusicClick(Window *w)
    00984 {
    00985   PopupMainToolbMenu(w, WID_TN_MUSIC_SOUND, STR_TOOLBAR_SOUND_MUSIC, 1);
    00986   return CBF_NONE;
    00987 }
    00988
    00995 static CallBackFunction MenuClickMusicWindow(int index)
    00996 {
    00997   ShowMusicWindow();
    00998   return CBF_NONE;
    00999 }
    01000
    01001 /* --- Newspaper button menu --- */
    01002
    01003 static CallBackFunction ToolbarNewspaperClick(Window *w)
    01004 {
    01005   PopupMainToolbMenu(w, WID_TN_MESSAGES, STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT, 2);
    01006   return CBF_NONE;
    01007 }
    01008
    01015 static CallBackFunction MenuClickNewspaper(int index)
    01016 {
    01017   switch (index) {
    01018     case 0: ShowLastNewsMessage(); break;
    01019     case 1: ShowMessageHistory();  break;
    01020   }
    01021   return CBF_NONE;
    01022 }
    01023
    01024 /* --- Help button menu --- */
    01025
    01026 static CallBackFunction PlaceLandBlockInfo()
    01027 {
    01028   if (_cursor.sprite == SPR_CURSOR_QUERY) {
    01029     ResetObjectToPlace();
    01030     return CBF_NONE;
    01031   } else {
    01032     SetObjectToPlace(SPR_CURSOR_QUERY, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0);
    01033     return CBF_PLACE_LANDINFO;
    01034   }
    01035 }
    01036
    01037 static CallBackFunction ToolbarHelpClick(Window *w)
    01038 {
    01039   PopupMainToolbMenu(w, WID_TN_HELP, STR_ABOUT_MENU_LAND_BLOCK_INFO, _settings_client.gui.newgrf_developer_tools ? 12 : 9);
    01040   return CBF_NONE;
    01041 }
    01042
    01043 static void MenuClickSmallScreenshot()
    01044 {
    01045   MakeScreenshot(SC_VIEWPORT, NULL);
    01046 }
    01047
    01053 static void ScreenshotConfirmCallback(Window *w, bool confirmed)
    01054 {
    01055   if (confirmed) MakeScreenshot(_confirmed_screenshot_type, NULL);
    01056 }
    01057
    01063 static void MenuClickLargeWorldScreenshot(ScreenshotType t)
    01064 {
    01065   ViewPort vp;
    01066   SetupScreenshotViewport(t, &vp);
    01067   if ((uint64)vp.width * (uint64)vp.height > 8192 * 8192) {
    01068     /* Ask for confirmation */
    01069     SetDParam(0, vp.width);
    01070     SetDParam(1, vp.height);
    01071     _confirmed_screenshot_type = t;
    01072     ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, NULL, ScreenshotConfirmCallback);
    01073   } else {
    01074     /* Less than 64M pixels, just do it */
    01075     MakeScreenshot(t, NULL);
    01076   }
    01077 }
    01078
    01086 void ToggleBoundingBoxes()
    01087 {
    01088   extern bool _draw_bounding_boxes;
    01089   /* Always allow to toggle them off */
    01090   if (_settings_client.gui.newgrf_developer_tools || _draw_bounding_boxes) {
    01091     _draw_bounding_boxes = !_draw_bounding_boxes;
    01092     MarkWholeScreenDirty();
    01093   }
    01094 }
    01095
    01103 void ToggleDirtyBlocks()
    01104 {
    01105   extern bool _draw_dirty_blocks;
    01106   /* Always allow to toggle them off */
    01107   if (_settings_client.gui.newgrf_developer_tools || _draw_dirty_blocks) {
    01108     _draw_dirty_blocks = !_draw_dirty_blocks;
    01109     MarkWholeScreenDirty();
    01110   }
    01111 }
    01112
    01117 void SetStartingYear(Year year)
    01118 {
    01119   _settings_game.game_creation.starting_year = Clamp(year, MIN_YEAR, MAX_YEAR);
    01120   Date new_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
    01121   /* If you open a savegame as scenario there may already be link graphs.*/
    01122   LinkGraphSchedule::Instance()->ShiftDates(new_date - _date);
    01123   SetDate(new_date, 0);
    01124 }
    01125
    01131 static CallBackFunction MenuClickHelp(int index)
    01132 {
    01133   switch (index) {
    01134     case  0: return PlaceLandBlockInfo();
    01135     case  2: IConsoleSwitch();                 break;
    01136     case  3: ShowAIDebugWindow();              break;
    01137     case  4: MenuClickSmallScreenshot();       break;
    01138     case  5: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN);    break;
    01139     case  6: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
    01140     case  7: MenuClickLargeWorldScreenshot(SC_WORLD);       break;
    01141     case  8: ShowAboutWindow();                break;
    01142     case  9: ShowSpriteAlignerWindow();        break;
    01143     case 10: ToggleBoundingBoxes();            break;
    01144     case 11: ToggleDirtyBlocks();              break;
    01145   }
    01146   return CBF_NONE;
    01147 }
    01148
    01149 /* --- Switch toolbar button --- */
    01150
    01151 static CallBackFunction ToolbarSwitchClick(Window *w)
    01152 {
    01153   if (_toolbar_mode != TB_LOWER) {
    01154     _toolbar_mode = TB_LOWER;
    01155   } else {
    01156     _toolbar_mode = TB_UPPER;
    01157   }
    01158
    01159   w->ReInit();
    01160   w->SetWidgetLoweredState(WID_TN_SWITCH_BAR, _toolbar_mode == TB_LOWER);
    01161   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    01162   return CBF_NONE;
    01163 }
    01164
    01165 /* --- Scenario editor specific handlers. */
    01166
    01170 static CallBackFunction ToolbarScenDatePanel(Window *w)
    01171 {
    01172   SetDParam(0, _settings_game.game_creation.starting_year);
    01173   ShowQueryString(STR_JUST_INT, STR_MAPGEN_START_DATE_QUERY_CAPT, 8, w, CS_NUMERAL, QSF_ENABLE_DEFAULT);
    01174   _left_button_clicked = false;
    01175   return CBF_NONE;
    01176 }
    01177
    01178 static CallBackFunction ToolbarScenDateBackward(Window *w)
    01179 {
    01180   /* don't allow too fast scrolling */
    01181   if (!(w->flags & WF_TIMEOUT) || w->timeout_timer <= 1) {
    01182     w->HandleButtonClick(WID_TE_DATE_BACKWARD);
    01183     w->SetDirty();
    01184
    01185     SetStartingYear(_settings_game.game_creation.starting_year - 1);
    01186   }
    01187   _left_button_clicked = false;
    01188   return CBF_NONE;
    01189 }
    01190
    01191 static CallBackFunction ToolbarScenDateForward(Window *w)
    01192 {
    01193   /* don't allow too fast scrolling */
    01194   if (!(w->flags & WF_TIMEOUT) || w->timeout_timer <= 1) {
    01195     w->HandleButtonClick(WID_TE_DATE_FORWARD);
    01196     w->SetDirty();
    01197
    01198     SetStartingYear(_settings_game.game_creation.starting_year + 1);
    01199   }
    01200   _left_button_clicked = false;
    01201   return CBF_NONE;
    01202 }
    01203
    01204 static CallBackFunction ToolbarScenGenLand(Window *w)
    01205 {
    01206   w->HandleButtonClick(WID_TE_LAND_GENERATE);
    01207   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    01208
    01209   ShowEditorTerraformToolbar();
    01210   return CBF_NONE;
    01211 }
    01212
    01213
    01214 static CallBackFunction ToolbarScenGenTown(Window *w)
    01215 {
    01216   w->HandleButtonClick(WID_TE_TOWN_GENERATE);
    01217   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    01218   ShowFoundTownWindow();
    01219   return CBF_NONE;
    01220 }
    01221
    01222 static CallBackFunction ToolbarScenGenIndustry(Window *w)
    01223 {
    01224   w->HandleButtonClick(WID_TE_INDUSTRY);
    01225   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    01226   ShowBuildIndustryWindow();
    01227   return CBF_NONE;
    01228 }
    01229
    01230 static CallBackFunction ToolbarScenBuildRoad(Window *w)
    01231 {
    01232   w->HandleButtonClick(WID_TE_ROADS);
    01233   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    01234   ShowBuildRoadScenToolbar();
    01235   return CBF_NONE;
    01236 }
    01237
    01238 static CallBackFunction ToolbarScenBuildDocks(Window *w)
    01239 {
    01240   w->HandleButtonClick(WID_TE_WATER);
    01241   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    01242   ShowBuildDocksScenToolbar();
    01243   return CBF_NONE;
    01244 }
    01245
    01246 static CallBackFunction ToolbarScenPlantTrees(Window *w)
    01247 {
    01248   w->HandleButtonClick(WID_TE_TREES);
    01249   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    01250   ShowBuildTreesToolbar();
    01251   return CBF_NONE;
    01252 }
    01253
    01254 static CallBackFunction ToolbarScenPlaceSign(Window *w)
    01255 {
    01256   w->HandleButtonClick(WID_TE_SIGNS);
    01257   if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    01258   return SelectSignTool();
    01259 }
    01260
    01261 static CallBackFunction ToolbarBtn_NULL(Window *w)
    01262 {
    01263   return CBF_NONE;
    01264 }
    01265
    01266 typedef CallBackFunction MenuClickedProc(int index);
    01267
    01268 static MenuClickedProc * const _menu_clicked_procs[] = {
    01269   NULL,                 // 0
    01270   NULL,                 // 1
    01271   MenuClickSettings,    // 2
    01272   MenuClickSaveLoad,    // 3
    01273   MenuClickMap,         // 4
    01274   MenuClickTown,        // 5
    01275   MenuClickSubsidies,   // 6
    01276   MenuClickStations,    // 7
    01277   MenuClickFinances,    // 8
    01278   MenuClickCompany,     // 9
    01279   MenuClickStory,       // 10
    01280   MenuClickGoal,        // 11
    01281   MenuClickGraphs,      // 12
    01282   MenuClickLeague,      // 13
    01283   MenuClickIndustry,    // 14
    01284   MenuClickShowTrains,  // 15
    01285   MenuClickShowRoad,    // 16
    01286   MenuClickShowShips,   // 17
    01287   MenuClickShowAir,     // 18
    01288   MenuClickMap,         // 19
    01289   NULL,                 // 20
    01290   MenuClickBuildRail,   // 21
    01291   MenuClickBuildRoad,   // 22
    01292   MenuClickBuildWater,  // 23
    01293   MenuClickBuildAir,    // 24
    01294   MenuClickForest,      // 25
    01295   MenuClickMusicWindow, // 26
    01296   MenuClickNewspaper,   // 27
    01297   MenuClickHelp,        // 28
    01298 };
    01299
    01301 class NWidgetToolbarContainer : public NWidgetContainer {
    01302   bool visible[WID_TN_END];
    01303 protected:
    01304   uint spacers;
    01305
    01306 public:
    01307   NWidgetToolbarContainer() : NWidgetContainer(NWID_HORIZONTAL)
    01308   {
    01309   }
    01310
    01316   bool IsButton(WidgetType type) const
    01317   {
    01318     return type == WWT_IMGBTN || type == WWT_IMGBTN_2 || type == WWT_PUSHIMGBTN;
    01319   }
    01320
    01321   void SetupSmallestSize(Window *w, bool init_array)
    01322   {
    01323     this->smallest_x = 0; // Biggest child
    01324     this->smallest_y = 0; // Biggest child
    01325     this->fill_x = 1;
    01326     this->fill_y = 0;
    01327     this->resize_x = 1; // We only resize in this direction
    01328     this->resize_y = 0; // We never resize in this direction
    01329     this->spacers = 0;
    01330
    01331     uint nbuttons = 0;
    01332     /* First initialise some variables... */
    01333     for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
    01334       child_wid->SetupSmallestSize(w, init_array);
    01335       this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
    01336       if (this->IsButton(child_wid->type)) {
    01337         nbuttons++;
    01338         this->smallest_x = max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
    01339       } else if (child_wid->type == NWID_SPACER) {
    01340         this->spacers++;
    01341       }
    01342     }
    01343
    01344     /* ... then in a second pass make sure the 'current' heights are set. Won't change ever. */
    01345     for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
    01346       child_wid->current_y = this->smallest_y;
    01347       if (!this->IsButton(child_wid->type)) {
    01348         child_wid->current_x = child_wid->smallest_x;
    01349       }
    01350     }
    01351     w->window_desc->default_width = nbuttons * this->smallest_x;
    01352   }
    01353
    01354   void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
    01355   {
    01356     assert(given_width >= this->smallest_x && given_height >= this->smallest_y);
    01357
    01358     this->pos_x = x;
    01359     this->pos_y = y;
    01360     this->current_x = given_width;
    01361     this->current_y = given_height;
    01362
    01363     /* Figure out what are the visible buttons */
    01364     memset(this->visible, 0, sizeof(this->visible));
    01365     uint arrangable_count, button_count, spacer_count;
    01366     const byte *arrangement = GetButtonArrangement(given_width, arrangable_count, button_count, spacer_count);
    01367     for (uint i = 0; i < arrangable_count; i++) {
    01368       this->visible[arrangement[i]] = true;
    01369     }
    01370
    01371     /* Create us ourselves a quick lookup table */
    01372     NWidgetBase *widgets[WID_TN_END];
    01373     for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
    01374       if (child_wid->type == NWID_SPACER) continue;
    01375       widgets[((NWidgetCore*)child_wid)->index] = child_wid;
    01376     }
    01377
    01378     /* Now assign the widgets to their rightful place */
    01379     uint position = 0; // Place to put next child relative to origin of the container.
    01380     uint spacer_space = max(0, (int)given_width - (int)(button_count * this->smallest_x)); // Remaining spacing for 'spacer' widgets
    01381     uint button_space = given_width - spacer_space; // Remaining spacing for the buttons
    01382     uint spacer_i = 0;
    01383     uint button_i = 0;
    01384
    01385     /* Index into the arrangement indices. The macro lastof cannot be used here! */
    01386     const byte *cur_wid = rtl ? &arrangement[arrangable_count - 1] : arrangement;
    01387     for (uint i = 0; i < arrangable_count; i++) {
    01388       NWidgetBase *child_wid = widgets[*cur_wid];
    01389       /* If we have to give space to the spacers, do that */
    01390       if (spacer_space != 0) {
    01391         NWidgetBase *possible_spacer = rtl ? child_wid->next : child_wid->prev;
    01392         if (possible_spacer != NULL && possible_spacer->type == NWID_SPACER) {
    01393           uint add = spacer_space / (spacer_count - spacer_i);
    01394           position += add;
    01395           spacer_space -= add;
    01396           spacer_i++;
    01397         }
    01398       }
    01399
    01400       /* Buttons can be scaled, the others not. */
    01401       if (this->IsButton(child_wid->type)) {
    01402         child_wid->current_x = button_space / (button_count - button_i);
    01403         button_space -= child_wid->current_x;
    01404         button_i++;
    01405       }
    01406       child_wid->AssignSizePosition(sizing, x + position, y, child_wid->current_x, this->current_y, rtl);
    01407       position += child_wid->current_x;
    01408
    01409       if (rtl) {
    01410         cur_wid--;
    01411       } else {
    01412         cur_wid++;
    01413       }
    01414     }
    01415   }
    01416
    01417   /* virtual */ void Draw(const Window *w)
    01418   {
    01419     /* Draw brown-red toolbar bg. */
    01420     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);
    01421     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);
    01422
    01423     bool rtl = _current_text_dir == TD_RTL;
    01424     for (NWidgetBase *child_wid = rtl ? this->tail : this->head; child_wid != NULL; child_wid = rtl ? child_wid->prev : child_wid->next) {
    01425       if (child_wid->type == NWID_SPACER) continue;
    01426       if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
    01427
    01428       child_wid->Draw(w);
    01429     }
    01430   }
    01431
    01432   /* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y)
    01433   {
    01434     if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
    01435
    01436     for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
    01437       if (child_wid->type == NWID_SPACER) continue;
    01438       if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
    01439
    01440       NWidgetCore *nwid = child_wid->GetWidgetFromPos(x, y);
    01441       if (nwid != NULL) return nwid;
    01442     }
    01443     return NULL;
    01444   }
    01445
    01454   virtual const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const = 0;
    01455 };
    01456
    01458 class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
    01459   /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
    01460   {
    01461     static const uint SMALLEST_ARRANGEMENT = 14;
    01462     static const uint BIGGEST_ARRANGEMENT  = 20;
    01463     static const byte arrange14[] = {
    01464       0,  1, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 29,
    01465       2,  3,  4,  5,  6,  7,  8,  9, 12, 14, 26, 27, 28, 29,
    01466     };
    01467     static const byte arrange15[] = {
    01468       0,  1,  4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
    01469       0,  2,  4,  3,  5,  6,  7,  8,  9, 12, 14, 26, 27, 28, 29,
    01470     };
    01471     static const byte arrange16[] = {
    01472       0,  1,  2,  4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
    01473       0,  1,  3,  5,  6,  7,  8,  9, 12, 14, 26, 27, 28, 19, 20, 29,
    01474     };
    01475     static const byte arrange17[] = {
    01476       0,  1,  2,  4,  6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
    01477       0,  1,  3,  4,  6,  5,  7,  8,  9, 12, 14, 26, 27, 28, 19, 20, 29,
    01478     };
    01479     static const byte arrange18[] = {
    01480       0,  1,  2,  4,  5,  6,  7,  8,  9, 14, 21, 22, 23, 24, 25, 19, 20, 29,
    01481       0,  1,  3,  4,  5,  6,  7, 12, 15, 16, 17, 18, 26, 27, 28, 19, 20, 29,
    01482     };
    01483     static const byte arrange19[] = {
    01484       0,  1,  2,  4,  5,  6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 19, 20, 29,
    01485       0,  1,  3,  4,  7,  8,  9, 12, 14, 27, 21, 22, 23, 24, 25, 28, 19, 20, 29,
    01486     };
    01487     static const byte arrange20[] = {
    01488       0,  1,  2,  4,  5,  6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 11, 19, 20, 29,
    01489       0,  1,  3,  4,  7,  8,  9, 12, 14, 27, 21, 22, 23, 24, 25, 10, 28, 19, 20, 29,
    01490     };
    01491     static const byte arrange_all[] = {
    01492       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
    01493     };
    01494
    01495     /* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
    01496     uint full_buttons = max(CeilDiv(width, this->smallest_x), SMALLEST_ARRANGEMENT);
    01497     if (full_buttons > BIGGEST_ARRANGEMENT) {
    01498       button_count = arrangable_count = lengthof(arrange_all);
    01499       spacer_count = this->spacers;
    01500       return arrange_all;
    01501     }
    01502
    01503     /* Introduce the split toolbar */
    01504     static const byte * const arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19, arrange20 };
    01505
    01506     button_count = arrangable_count = full_buttons;
    01507     spacer_count = this->spacers;
    01508     return arrangements[full_buttons - SMALLEST_ARRANGEMENT] + ((_toolbar_mode == TB_LOWER) ? full_buttons : 0);
    01509   }
    01510 };
    01511
    01513 class NWidgetScenarioToolbarContainer : public NWidgetToolbarContainer {
    01514   uint panel_widths[2];
    01515
    01516   void SetupSmallestSize(Window *w, bool init_array)
    01517   {
    01518     this->NWidgetToolbarContainer::SetupSmallestSize(w, init_array);
    01519
    01520     /* Find the size of panel_widths */
    01521     uint i = 0;
    01522     for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
    01523       if (child_wid->type == NWID_SPACER || this->IsButton(child_wid->type)) continue;
    01524
    01525       assert(i < lengthof(this->panel_widths));
    01526       this->panel_widths[i++] = child_wid->current_x;
    01527       w->window_desc->default_width += child_wid->current_x;
    01528     }
    01529   }
    01530
    01531   /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
    01532   {
    01533     static const byte arrange_all[] = {
    01534       0, 1, 2, 3, 4, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 26, 28,
    01535     };
    01536     static const byte arrange_nopanel[] = {
    01537       0, 1, 2, 3, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 26, 28,
    01538     };
    01539     static const byte arrange_switch[] = {
    01540       18,  8, 11, 12, 13, 14, 15, 16, 17, 29,
    01541        0,  1,  2,  3, 18,  9, 10, 26, 28, 29,
    01542     };
    01543
    01544     /* If we can place all buttons *and* the panels, show them. */
    01545     uint min_full_width = (lengthof(arrange_all) - lengthof(this->panel_widths)) * this->smallest_x + this->panel_widths[0] + this->panel_widths[1];
    01546     if (width >= min_full_width) {
    01547       width -= this->panel_widths[0] + this->panel_widths[1];
    01548       arrangable_count = lengthof(arrange_all);
    01549       button_count = arrangable_count - 2;
    01550       spacer_count = this->spacers;
    01551       return arrange_all;
    01552     }
    01553
    01554     /* 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 */
    01555     uint min_small_width = (lengthof(arrange_switch) - lengthof(this->panel_widths)) * this->smallest_x / 2 + this->panel_widths[1];
    01556     if (width > min_small_width) {
    01557       width -= this->panel_widths[1];
    01558       arrangable_count = lengthof(arrange_nopanel);
    01559       button_count = arrangable_count - 1;
    01560       spacer_count = this->spacers - 1;
    01561       return arrange_nopanel;
    01562     }
    01563
    01564     /* Split toolbar */
    01565     width -= this->panel_widths[1];
    01566     arrangable_count = lengthof(arrange_switch) / 2;
    01567     button_count = arrangable_count - 1;
    01568     spacer_count = 0;
    01569     return arrange_switch + ((_toolbar_mode == TB_LOWER) ? arrangable_count : 0);
    01570   }
    01571 };
    01572
    01573 /* --- Toolbar handling for the 'normal' case */
    01574
    01575 typedef CallBackFunction ToolbarButtonProc(Window *w);
    01576
    01577 static ToolbarButtonProc * const _toolbar_button_procs[] = {
    01578   ToolbarPauseClick,
    01579   ToolbarFastForwardClick,
    01580   ToolbarOptionsClick,
    01581   ToolbarSaveClick,
    01582   ToolbarMapClick,
    01583   ToolbarTownClick,
    01584   ToolbarSubsidiesClick,
    01585   ToolbarStationsClick,
    01586   ToolbarFinancesClick,
    01587   ToolbarCompaniesClick,
    01588   ToolbarStoryClick,
    01589   ToolbarGoalClick,
    01590   ToolbarGraphsClick,
    01591   ToolbarLeagueClick,
    01592   ToolbarIndustryClick,
    01593   ToolbarTrainClick,
    01594   ToolbarRoadClick,
    01595   ToolbarShipClick,
    01596   ToolbarAirClick,
    01597   ToolbarZoomInClick,
    01598   ToolbarZoomOutClick,
    01599   ToolbarBuildRailClick,
    01600   ToolbarBuildRoadClick,
    01601   ToolbarBuildWaterClick,
    01602   ToolbarBuildAirClick,
    01603   ToolbarForestClick,
    01604   ToolbarMusicClick,
    01605   ToolbarNewspaperClick,
    01606   ToolbarHelpClick,
    01607   ToolbarSwitchClick,
    01608 };
    01609
    01610 enum MainToolbarHotkeys {
    01611   MTHK_PAUSE,
    01612   MTHK_FASTFORWARD,
    01613   MTHK_SETTINGS,
    01614   MTHK_SAVEGAME,
    01615   MTHK_LOADGAME,
    01616   MTHK_SMALLMAP,
    01617   MTHK_TOWNDIRECTORY,
    01618   MTHK_SUBSIDIES,
    01619   MTHK_STATIONS,
    01620   MTHK_FINANCES,
    01621   MTHK_COMPANIES,
    01622   MTHK_STORY,
    01623   MTHK_GOAL,
    01624   MTHK_GRAPHS,
    01625   MTHK_LEAGUE,
    01626   MTHK_INDUSTRIES,
    01627   MTHK_TRAIN_LIST,
    01628   MTHK_ROADVEH_LIST,
    01629   MTHK_SHIP_LIST,
    01630   MTHK_AIRCRAFT_LIST,
    01631   MTHK_ZOOM_IN,
    01632   MTHK_ZOOM_OUT,
    01633   MTHK_BUILD_RAIL,
    01634   MTHK_BUILD_ROAD,
    01635   MTHK_BUILD_DOCKS,
    01636   MTHK_BUILD_AIRPORT,
    01637   MTHK_BUILD_TREES,
    01638   MTHK_MUSIC,
    01639   MTHK_AI_DEBUG,
    01640   MTHK_SMALL_SCREENSHOT,
    01641   MTHK_ZOOMEDIN_SCREENSHOT,
    01642   MTHK_DEFAULTZOOM_SCREENSHOT,
    01643   MTHK_GIANT_SCREENSHOT,
    01644   MTHK_CHEATS,
    01645   MTHK_TERRAFORM,
    01646   MTHK_EXTRA_VIEWPORT,
    01647   MTHK_CLIENT_LIST,
    01648   MTHK_SIGN_LIST,
    01649 };
    01650
    01652 struct MainToolbarWindow : Window {
    01653   CallBackFunction last_started_action;
    01654
    01655   MainToolbarWindow(WindowDesc *desc) : Window(desc)
    01656   {
    01657     this->InitNested(0);
    01658
    01659     this->last_started_action = CBF_NONE;
    01660     CLRBITS(this->flags, WF_WHITE_BORDER);
    01661     this->SetWidgetDisabledState(WID_TN_PAUSE, _networking && !_network_server); // if not server, disable pause button
    01662     this->SetWidgetDisabledState(WID_TN_FAST_FORWARD, _networking); // if networking, disable fast-forward button
    01663     PositionMainToolbar(this);
    01664     DoZoomInOutWindow(ZOOM_NONE, this);
    01665   }
    01666
    01667   virtual void OnPaint()
    01668   {
    01669     /* If spectator, disable all construction buttons
    01670      * ie : Build road, rail, ships, airports and landscaping
    01671      * Since enabled state is the default, just disable when needed */
    01672     this->SetWidgetsDisabledState(_local_company == COMPANY_SPECTATOR, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, WID_TN_AIR, WID_TN_LANDSCAPE, WIDGET_LIST_END);
    01673     /* disable company list drop downs, if there are no companies */
    01674     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);
    01675
    01676     this->SetWidgetDisabledState(WID_TN_GOAL, Goal::GetNumItems() == 0);
    01677     this->SetWidgetDisabledState(WID_TN_STORY, StoryPage::GetNumItems() == 0);
    01678
    01679     this->SetWidgetDisabledState(WID_TN_RAILS, !CanBuildVehicleInfrastructure(VEH_TRAIN));
    01680     this->SetWidgetDisabledState(WID_TN_AIR, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT));
    01681
    01682     this->DrawWidgets();
    01683   }
    01684
    01685   virtual void OnClick(Point pt, int widget, int click_count)
    01686   {
    01687     if (_game_mode != GM_MENU && !this->IsWidgetDisabled(widget)) _toolbar_button_procs[widget](this);
    01688   }
    01689
    01690   virtual void OnDropdownSelect(int widget, int index)
    01691   {
    01692     CallBackFunction cbf = _menu_clicked_procs[widget](index);
    01693     if (cbf != CBF_NONE) this->last_started_action = cbf;
    01694   }
    01695
    01696   virtual EventState OnHotkey(int hotkey)
    01697   {
    01698     switch (hotkey) {
    01699       case MTHK_PAUSE: ToolbarPauseClick(this); break;
    01700       case MTHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
    01701       case MTHK_SETTINGS: ShowGameOptions(); break;
    01702       case MTHK_SAVEGAME: MenuClickSaveLoad(); break;
    01703       case MTHK_LOADGAME: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
    01704       case MTHK_SMALLMAP: ShowSmallMap(); break;
    01705       case MTHK_TOWNDIRECTORY: ShowTownDirectory(); break;
    01706       case MTHK_SUBSIDIES: ShowSubsidiesList(); break;
    01707       case MTHK_STATIONS: ShowCompanyStations(_local_company); break;
    01708       case MTHK_FINANCES: ShowCompanyFinances(_local_company); break;
    01709       case MTHK_COMPANIES: ShowCompany(_local_company); break;
    01710       case MTHK_STORY: ShowStoryBook(_local_company); break;
    01711       case MTHK_GOAL: ShowGoalsList(_local_company); break;
    01712       case MTHK_GRAPHS: ShowOperatingProfitGraph(); break;
    01713       case MTHK_LEAGUE: ShowCompanyLeagueTable(); break;
    01714       case MTHK_INDUSTRIES: ShowBuildIndustryWindow(); break;
    01715       case MTHK_TRAIN_LIST: ShowVehicleListWindow(_local_company, VEH_TRAIN); break;
    01716       case MTHK_ROADVEH_LIST: ShowVehicleListWindow(_local_company, VEH_ROAD); break;
    01717       case MTHK_SHIP_LIST: ShowVehicleListWindow(_local_company, VEH_SHIP); break;
    01718       case MTHK_AIRCRAFT_LIST: ShowVehicleListWindow(_local_company, VEH_AIRCRAFT); break;
    01719       case MTHK_ZOOM_IN: ToolbarZoomInClick(this); break;
    01720       case MTHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
    01721       case MTHK_BUILD_RAIL: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype); break;
    01722       case MTHK_BUILD_ROAD: ShowBuildRoadToolbar(_last_built_roadtype); break;
    01723       case MTHK_BUILD_DOCKS: ShowBuildDocksToolbar(); break;
    01724       case MTHK_BUILD_AIRPORT: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break;
    01725       case MTHK_BUILD_TREES: ShowBuildTreesToolbar(); break;
    01726       case MTHK_MUSIC: ShowMusicWindow(); break;
    01727       case MTHK_AI_DEBUG: ShowAIDebugWindow(); break;
    01728       case MTHK_SMALL_SCREENSHOT: MenuClickSmallScreenshot(); break;
    01729       case MTHK_ZOOMEDIN_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
    01730       case MTHK_DEFAULTZOOM_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
    01731       case MTHK_GIANT_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_WORLD); break;
    01732       case MTHK_CHEATS: if (!_networking) ShowCheatWindow(); break;
    01733       case MTHK_TERRAFORM: ShowTerraformToolbar(); break;
    01734       case MTHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
    01735 #ifdef ENABLE_NETWORK
    01736       case MTHK_CLIENT_LIST: if (_networking) ShowClientList(); break;
    01737 #endif
    01738       case MTHK_SIGN_LIST: ShowSignList(); break;
    01739       default: return ES_NOT_HANDLED;
    01740     }
    01741     return ES_HANDLED;
    01742   }
    01743
    01744   virtual void OnPlaceObject(Point pt, TileIndex tile)
    01745   {
    01746     switch (this->last_started_action) {
    01747       case CBF_PLACE_SIGN:
    01748         PlaceProc_Sign(tile);
    01749         break;
    01750
    01751       case CBF_PLACE_LANDINFO:
    01752         ShowLandInfo(tile);
    01753         break;
    01754
    01755       default: NOT_REACHED();
    01756     }
    01757   }
    01758
    01759   virtual void OnTick()
    01760   {
    01761     if (this->IsWidgetLowered(WID_TN_PAUSE) != !!_pause_mode) {
    01762       this->ToggleWidgetLoweredState(WID_TN_PAUSE);
    01763       this->SetWidgetDirty(WID_TN_PAUSE);
    01764     }
    01765
    01766     if (this->IsWidgetLowered(WID_TN_FAST_FORWARD) != !!_fast_forward) {
    01767       this->ToggleWidgetLoweredState(WID_TN_FAST_FORWARD);
    01768       this->SetWidgetDirty(WID_TN_FAST_FORWARD);
    01769     }
    01770   }
    01771
    01772   virtual void OnTimeout()
    01773   {
    01774     /* We do not want to automatically raise the pause, fast forward and
    01775      * switchbar buttons; they have to stay down when pressed etc. */
    01776     for (uint i = WID_TN_SETTINGS; i < WID_TN_SWITCH_BAR; i++) {
    01777       if (this->IsWidgetLowered(i)) {
    01778         this->RaiseWidget(i);
    01779         this->SetWidgetDirty(i);
    01780       }
    01781     }
    01782   }
    01783
    01789   virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
    01790   {
    01791     if (!gui_scope) return;
    01792     if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, WID_TN_ZOOM_IN, WID_TN_ZOOM_OUT);
    01793   }
    01794
    01795   static HotkeyList hotkeys;
    01796 };
    01797
    01798 const uint16 _maintoolbar_pause_keys[] = {WKC_F1, WKC_PAUSE, 0};
    01799 const uint16 _maintoolbar_zoomin_keys[] = {WKC_NUM_PLUS, WKC_EQUALS, WKC_SHIFT | WKC_EQUALS, WKC_SHIFT | WKC_F5, 0};
    01800 const uint16 _maintoolbar_zoomout_keys[] = {WKC_NUM_MINUS, WKC_MINUS, WKC_SHIFT | WKC_MINUS, WKC_SHIFT | WKC_F6, 0};
    01801 const uint16 _maintoolbar_smallmap_keys[] = {WKC_F4, 'M', 0};
    01802
    01803 static Hotkey maintoolbar_hotkeys[] = {
    01804   Hotkey(_maintoolbar_pause_keys, "pause", MTHK_PAUSE),
    01805   Hotkey((uint16)0, "fastforward", MTHK_FASTFORWARD),
    01806   Hotkey(WKC_F2, "settings", MTHK_SETTINGS),
    01807   Hotkey(WKC_F3, "saveload", MTHK_SAVEGAME),
    01808   Hotkey((uint16)0, "load_game", MTHK_LOADGAME),
    01809   Hotkey(_maintoolbar_smallmap_keys, "smallmap", MTHK_SMALLMAP),
    01810   Hotkey(WKC_F5, "town_list", MTHK_TOWNDIRECTORY),
    01811   Hotkey(WKC_F6, "subsidies", MTHK_SUBSIDIES),
    01812   Hotkey(WKC_F7, "station_list", MTHK_STATIONS),
    01813   Hotkey(WKC_F8, "finances", MTHK_FINANCES),
    01814   Hotkey(WKC_F9, "companies", MTHK_COMPANIES),
    01815   Hotkey((uint16)0, "story_book", MTHK_STORY),
    01816   Hotkey((uint16)0, "goal_list", MTHK_GOAL),
    01817   Hotkey(WKC_F10, "graphs", MTHK_GRAPHS),
    01818   Hotkey(WKC_F11, "league", MTHK_LEAGUE),
    01819   Hotkey(WKC_F12, "industry_list", MTHK_INDUSTRIES),
    01820   Hotkey(WKC_SHIFT | WKC_F1, "train_list", MTHK_TRAIN_LIST),
    01821   Hotkey(WKC_SHIFT | WKC_F2, "roadveh_list", MTHK_ROADVEH_LIST),
    01822   Hotkey(WKC_SHIFT | WKC_F3, "ship_list", MTHK_SHIP_LIST),
    01823   Hotkey(WKC_SHIFT | WKC_F4, "aircraft_list", MTHK_AIRCRAFT_LIST),
    01824   Hotkey(_maintoolbar_zoomin_keys, "zoomin", MTHK_ZOOM_IN),
    01825   Hotkey(_maintoolbar_zoomout_keys, "zoomout", MTHK_ZOOM_OUT),
    01826   Hotkey(WKC_SHIFT | WKC_F7, "build_rail", MTHK_BUILD_RAIL),
    01827   Hotkey(WKC_SHIFT | WKC_F8, "build_road", MTHK_BUILD_ROAD),
    01828   Hotkey(WKC_SHIFT | WKC_F9, "build_docks", MTHK_BUILD_DOCKS),
    01829   Hotkey(WKC_SHIFT | WKC_F10, "build_airport", MTHK_BUILD_AIRPORT),
    01830   Hotkey(WKC_SHIFT | WKC_F11, "build_trees", MTHK_BUILD_TREES),
    01831   Hotkey(WKC_SHIFT | WKC_F12, "music", MTHK_MUSIC),
    01832   Hotkey((uint16)0, "ai_debug", MTHK_AI_DEBUG),
    01833   Hotkey(WKC_CTRL  | 'S', "small_screenshot", MTHK_SMALL_SCREENSHOT),
    01834   Hotkey(WKC_CTRL  | 'P', "zoomedin_screenshot", MTHK_ZOOMEDIN_SCREENSHOT),
    01835   Hotkey(WKC_CTRL  | 'D', "defaultzoom_screenshot", MTHK_DEFAULTZOOM_SCREENSHOT),
    01836   Hotkey((uint16)0, "giant_screenshot", MTHK_GIANT_SCREENSHOT),
    01837   Hotkey(WKC_CTRL | WKC_ALT | 'C', "cheats", MTHK_CHEATS),
    01838   Hotkey('L', "terraform", MTHK_TERRAFORM),
    01839   Hotkey('V', "extra_viewport", MTHK_EXTRA_VIEWPORT),
    01840 #ifdef ENABLE_NETWORK
    01841   Hotkey((uint16)0, "client_list", MTHK_CLIENT_LIST),
    01842 #endif
    01843   Hotkey((uint16)0, "sign_list", MTHK_SIGN_LIST),
    01844   HOTKEY_LIST_END
    01845 };
    01846 HotkeyList MainToolbarWindow::hotkeys("maintoolbar", maintoolbar_hotkeys);
    01847
    01848 static NWidgetBase *MakeMainToolbar(int *biggest_index)
    01849 {
    01851   static const SpriteID toolbar_button_sprites[] = {
    01852     SPR_IMG_PAUSE,           // WID_TN_PAUSE
    01853     SPR_IMG_FASTFORWARD,     // WID_TN_FAST_FORWARD
    01854     SPR_IMG_SETTINGS,        // WID_TN_SETTINGS
    01855     SPR_IMG_SAVE,            // WID_TN_SAVE
    01856     SPR_IMG_SMALLMAP,        // WID_TN_SMALL_MAP
    01857     SPR_IMG_TOWN,            // WID_TN_TOWNS
    01858     SPR_IMG_SUBSIDIES,       // WID_TN_SUBSIDIES
    01859     SPR_IMG_COMPANY_LIST,    // WID_TN_STATIONS
    01860     SPR_IMG_COMPANY_FINANCE, // WID_TN_FINANCES
    01861     SPR_IMG_COMPANY_GENERAL, // WID_TN_COMPANIES
    01862     SPR_IMG_STORY_BOOK,      // WID_TN_STORY
    01863     SPR_IMG_GOAL,            // WID_TN_GOAL
    01864     SPR_IMG_GRAPHS,          // WID_TN_GRAPHS
    01865     SPR_IMG_COMPANY_LEAGUE,  // WID_TN_LEAGUE
    01866     SPR_IMG_INDUSTRY,        // WID_TN_INDUSTRIES
    01867     SPR_IMG_TRAINLIST,       // WID_TN_TRAINS
    01868     SPR_IMG_TRUCKLIST,       // WID_TN_ROADVEHS
    01869     SPR_IMG_SHIPLIST,        // WID_TN_SHIPS
    01870     SPR_IMG_AIRPLANESLIST,   // WID_TN_AIRCRAFT
    01871     SPR_IMG_ZOOMIN,          // WID_TN_ZOOMIN
    01872     SPR_IMG_ZOOMOUT,         // WID_TN_ZOOMOUT
    01873     SPR_IMG_BUILDRAIL,       // WID_TN_RAILS
    01874     SPR_IMG_BUILDROAD,       // WID_TN_ROADS
    01875     SPR_IMG_BUILDWATER,      // WID_TN_WATER
    01876     SPR_IMG_BUILDAIR,        // WID_TN_AIR
    01877     SPR_IMG_LANDSCAPING,     // WID_TN_LANDSCAPE
    01878     SPR_IMG_MUSIC,           // WID_TN_MUSIC_SOUND
    01879     SPR_IMG_MESSAGES,        // WID_TN_MESSAGES
    01880     SPR_IMG_QUERY,           // WID_TN_HELP
    01881     SPR_IMG_SWITCH_TOOLBAR,  // WID_TN_SWITCH_BAR
    01882   };
    01883
    01884   NWidgetMainToolbarContainer *hor = new NWidgetMainToolbarContainer();
    01885   for (uint i = 0; i < WID_TN_END; i++) {
    01886     switch (i) {
    01887       case 4: case 8: case 15: case 19: case 21: case 26: hor->Add(new NWidgetSpacer(0, 0)); break;
    01888     }
    01889     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));
    01890   }
    01891
    01892   *biggest_index = max<int>(*biggest_index, WID_TN_SWITCH_BAR);
    01893   return hor;
    01894 }
    01895
    01896 static const NWidgetPart _nested_toolbar_normal_widgets[] = {
    01897   NWidgetFunction(MakeMainToolbar),
    01898 };
    01899
    01900 static WindowDesc _toolb_normal_desc(
    01901   WDP_MANUAL, NULL, 640, 22,
    01902   WC_MAIN_TOOLBAR, WC_NONE,
    01903   WDF_NO_FOCUS,
    01904   _nested_toolbar_normal_widgets, lengthof(_nested_toolbar_normal_widgets),
    01905   &MainToolbarWindow::hotkeys
    01906 );
    01907
    01908
    01909 /* --- Toolbar handling for the scenario editor */
    01910
    01911 static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
    01912   ToolbarPauseClick,
    01913   ToolbarFastForwardClick,
    01914   ToolbarOptionsClick,
    01915   ToolbarScenSaveOrLoad,
    01916   ToolbarBtn_NULL,
    01917   ToolbarScenDatePanel,
    01918   ToolbarScenDateBackward,
    01919   ToolbarScenDateForward,
    01920   ToolbarScenMapTownDir,
    01921   ToolbarZoomInClick,
    01922   ToolbarZoomOutClick,
    01923   ToolbarScenGenLand,
    01924   ToolbarScenGenTown,
    01925   ToolbarScenGenIndustry,
    01926   ToolbarScenBuildRoad,
    01927   ToolbarScenBuildDocks,
    01928   ToolbarScenPlantTrees,
    01929   ToolbarScenPlaceSign,
    01930   ToolbarBtn_NULL,
    01931   NULL,
    01932   NULL,
    01933   NULL,
    01934   NULL,
    01935   NULL,
    01936   NULL,
    01937   NULL,
    01938   ToolbarMusicClick,
    01939   NULL,
    01940   ToolbarHelpClick,
    01941   ToolbarSwitchClick,
    01942 };
    01943
    01944 enum MainToolbarEditorHotkeys {
    01945   MTEHK_PAUSE,
    01946   MTEHK_FASTFORWARD,
    01947   MTEHK_SETTINGS,
    01948   MTEHK_SAVEGAME,
    01949   MTEHK_GENLAND,
    01950   MTEHK_GENTOWN,
    01951   MTEHK_GENINDUSTRY,
    01952   MTEHK_BUILD_ROAD,
    01953   MTEHK_BUILD_DOCKS,
    01954   MTEHK_BUILD_TREES,
    01955   MTEHK_SIGN,
    01956   MTEHK_MUSIC,
    01957   MTEHK_LANDINFO,
    01958   MTEHK_SMALL_SCREENSHOT,
    01959   MTEHK_ZOOMEDIN_SCREENSHOT,
    01960   MTEHK_DEFAULTZOOM_SCREENSHOT,
    01961   MTEHK_GIANT_SCREENSHOT,
    01962   MTEHK_ZOOM_IN,
    01963   MTEHK_ZOOM_OUT,
    01964   MTEHK_TERRAFORM,
    01965   MTEHK_SMALLMAP,
    01966   MTEHK_EXTRA_VIEWPORT,
    01967 };
    01968
    01969 struct ScenarioEditorToolbarWindow : Window {
    01970   CallBackFunction last_started_action;
    01971
    01972   ScenarioEditorToolbarWindow(WindowDesc *desc) : Window(desc)
    01973   {
    01974     this->InitNested(0);
    01975
    01976     this->last_started_action = CBF_NONE;
    01977     CLRBITS(this->flags, WF_WHITE_BORDER);
    01978     PositionMainToolbar(this);
    01979     DoZoomInOutWindow(ZOOM_NONE, this);
    01980   }
    01981
    01982   virtual void OnPaint()
    01983   {
    01984     this->SetWidgetDisabledState(WID_TE_DATE_BACKWARD, _settings_game.game_creation.starting_year <= MIN_YEAR);
    01985     this->SetWidgetDisabledState(WID_TE_DATE_FORWARD, _settings_game.game_creation.starting_year >= MAX_YEAR);
    01986
    01987     this->DrawWidgets();
    01988   }
    01989
    01990   virtual void DrawWidget(const Rect &r, int widget) const
    01991   {
    01992     switch (widget) {
    01993       case WID_TE_DATE:
    01994         SetDParam(0, ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
    01995         DrawString(r.left, r.right, (this->height - FONT_HEIGHT_NORMAL) / 2, STR_WHITE_DATE_LONG, TC_FROMSTRING, SA_HOR_CENTER);
    01996         break;
    01997
    01998       case WID_TE_SPACER: {
    01999         int height = r.bottom - r.top;
    02000         if (height > 2 * FONT_HEIGHT_NORMAL) {
    02001           DrawString(r.left, r.right, (height + 1) / 2 - FONT_HEIGHT_NORMAL, STR_SCENEDIT_TOOLBAR_OPENTTD, TC_FROMSTRING, SA_HOR_CENTER);
    02002           DrawString(r.left, r.right, (height + 1) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
    02003         } else {
    02004           DrawString(r.left, r.right, (height - FONT_HEIGHT_NORMAL) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
    02005         }
    02006         break;
    02007       }
    02008     }
    02009   }
    02010
    02011   virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
    02012   {
    02013     switch (widget) {
    02014       case WID_TE_SPACER:
    02015         size->width = max(GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_OPENTTD).width, GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR).width) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
    02016         break;
    02017
    02018       case WID_TE_DATE:
    02019         SetDParam(0, ConvertYMDToDate(MAX_YEAR, 0, 1));
    02020         *size = GetStringBoundingBox(STR_WHITE_DATE_LONG);
    02021         size->height = max(size->height, GetSpriteSize(SPR_IMG_SAVE).height + WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM);
    02022         break;
    02023     }
    02024   }
    02025
    02026   virtual void OnClick(Point pt, int widget, int click_count)
    02027   {
    02028     if (_game_mode == GM_MENU) return;
    02029     CallBackFunction cbf = _scen_toolbar_button_procs[widget](this);
    02030     if (cbf != CBF_NONE) this->last_started_action = cbf;
    02031   }
    02032
    02033   virtual void OnDropdownSelect(int widget, int index)
    02034   {
    02035     /* The map button is in a different location on the scenario
    02036      * editor toolbar, so we need to adjust for it. */
    02037     if (widget == WID_TE_SMALL_MAP) widget = WID_TN_SMALL_MAP;
    02038     CallBackFunction cbf = _menu_clicked_procs[widget](index);
    02039     if (cbf != CBF_NONE) this->last_started_action = cbf;
    02040     if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
    02041   }
    02042
    02043   virtual EventState OnHotkey(int hotkey)
    02044   {
    02045     CallBackFunction cbf = CBF_NONE;
    02046     switch (hotkey) {
    02047       case MTEHK_PAUSE:                  ToolbarPauseClick(this); break;
    02048       case MTEHK_FASTFORWARD:            ToolbarFastForwardClick(this); break;
    02049       case MTEHK_SETTINGS:               ShowGameOptions(); break;
    02050       case MTEHK_SAVEGAME:               MenuClickSaveLoad(); break;
    02051       case MTEHK_GENLAND:                ToolbarScenGenLand(this); break;
    02052       case MTEHK_GENTOWN:                ToolbarScenGenTown(this); break;
    02053       case MTEHK_GENINDUSTRY:            ToolbarScenGenIndustry(this); break;
    02054       case MTEHK_BUILD_ROAD:             ToolbarScenBuildRoad(this); break;
    02055       case MTEHK_BUILD_DOCKS:            ToolbarScenBuildDocks(this); break;
    02056       case MTEHK_BUILD_TREES:            ToolbarScenPlantTrees(this); break;
    02057       case MTEHK_SIGN:                   cbf = ToolbarScenPlaceSign(this); break;
    02058       case MTEHK_MUSIC:                  ShowMusicWindow(); break;
    02059       case MTEHK_LANDINFO:               cbf = PlaceLandBlockInfo(); break;
    02060       case MTEHK_SMALL_SCREENSHOT:       MenuClickSmallScreenshot(); break;
    02061       case MTEHK_ZOOMEDIN_SCREENSHOT:    MenuClickLargeWorldScreenshot(SC_ZOOMEDIN); break;
    02062       case MTEHK_DEFAULTZOOM_SCREENSHOT: MenuClickLargeWorldScreenshot(SC_DEFAULTZOOM); break;
    02063       case MTEHK_GIANT_SCREENSHOT:       MenuClickLargeWorldScreenshot(SC_WORLD); break;
    02064       case MTEHK_ZOOM_IN:                ToolbarZoomInClick(this); break;
    02065       case MTEHK_ZOOM_OUT:               ToolbarZoomOutClick(this); break;
    02066       case MTEHK_TERRAFORM:              ShowEditorTerraformToolbar(); break;
    02067       case MTEHK_SMALLMAP:               ShowSmallMap(); break;
    02068       case MTEHK_EXTRA_VIEWPORT:         ShowExtraViewPortWindowForTileUnderCursor(); break;
    02069       default: return ES_NOT_HANDLED;
    02070     }
    02071     if (cbf != CBF_NONE) this->last_started_action = cbf;
    02072     return ES_HANDLED;
    02073   }
    02074
    02075   virtual void OnPlaceObject(Point pt, TileIndex tile)
    02076   {
    02077     switch (this->last_started_action) {
    02078       case CBF_PLACE_SIGN:
    02079         PlaceProc_Sign(tile);
    02080         break;
    02081
    02082       case CBF_PLACE_LANDINFO:
    02083         ShowLandInfo(tile);
    02084         break;
    02085
    02086       default: NOT_REACHED();
    02087     }
    02088   }
    02089
    02090   virtual void OnTimeout()
    02091   {
    02092     this->SetWidgetsLoweredState(false, WID_TE_DATE_BACKWARD, WID_TE_DATE_FORWARD, WIDGET_LIST_END);
    02093     this->SetWidgetDirty(WID_TE_DATE_BACKWARD);
    02094     this->SetWidgetDirty(WID_TE_DATE_FORWARD);
    02095   }
    02096
    02097   virtual void OnTick()
    02098   {
    02099     if (this->IsWidgetLowered(WID_TE_PAUSE) != !!_pause_mode) {
    02100       this->ToggleWidgetLoweredState(WID_TE_PAUSE);
    02101       this->SetDirty();
    02102     }
    02103
    02104     if (this->IsWidgetLowered(WID_TE_FAST_FORWARD) != !!_fast_forward) {
    02105       this->ToggleWidgetLoweredState(WID_TE_FAST_FORWARD);
    02106       this->SetDirty();
    02107     }
    02108   }
    02109
    02115   virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
    02116   {
    02117     if (!gui_scope) return;
    02118     if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, WID_TE_ZOOM_IN, WID_TE_ZOOM_OUT);
    02119   }
    02120
    02121   virtual void OnQueryTextFinished(char *str)
    02122   {
    02123     /* Was 'cancel' pressed? */
    02124     if (str == NULL) return;
    02125
    02126     int32 value;
    02127     if (!StrEmpty(str)) {
    02128       value = atoi(str);
    02129     } else {
    02130       /* An empty string means revert to the default */
    02131       value = DEF_START_YEAR;
    02132     }
    02133     SetStartingYear(value);
    02134
    02135     this->SetDirty();
    02136   }
    02137
    02138   static HotkeyList hotkeys;
    02139 };
    02140
    02141 static Hotkey scenedit_maintoolbar_hotkeys[] = {
    02142   Hotkey(_maintoolbar_pause_keys, "pause", MTEHK_PAUSE),
    02143   Hotkey((uint16)0, "fastforward", MTEHK_FASTFORWARD),
    02144   Hotkey(WKC_F2, "settings", MTEHK_SETTINGS),
    02145   Hotkey(WKC_F3, "saveload", MTEHK_SAVEGAME),
    02146   Hotkey(WKC_F4, "gen_land", MTEHK_GENLAND),
    02147   Hotkey(WKC_F5, "gen_town", MTEHK_GENTOWN),
    02148   Hotkey(WKC_F6, "gen_industry", MTEHK_GENINDUSTRY),
    02149   Hotkey(WKC_F7, "build_road", MTEHK_BUILD_ROAD),
    02150   Hotkey(WKC_F8, "build_docks", MTEHK_BUILD_DOCKS),
    02151   Hotkey(WKC_F9, "build_trees", MTEHK_BUILD_TREES),
    02152   Hotkey(WKC_F10, "build_sign", MTEHK_SIGN),
    02153   Hotkey(WKC_F11, "music", MTEHK_MUSIC),
    02154   Hotkey(WKC_F12, "land_info", MTEHK_LANDINFO),
    02155   Hotkey(WKC_CTRL  | 'S', "small_screenshot", MTEHK_SMALL_SCREENSHOT),
    02156   Hotkey(WKC_CTRL  | 'P', "zoomedin_screenshot", MTEHK_ZOOMEDIN_SCREENSHOT),
    02157   Hotkey(WKC_CTRL  | 'D', "defaultzoom_screenshot", MTEHK_DEFAULTZOOM_SCREENSHOT),
    02158   Hotkey((uint16)0, "giant_screenshot", MTEHK_GIANT_SCREENSHOT),
    02159   Hotkey(_maintoolbar_zoomin_keys, "zoomin", MTEHK_ZOOM_IN),
    02160   Hotkey(_maintoolbar_zoomout_keys, "zoomout", MTEHK_ZOOM_OUT),
    02161   Hotkey('L', "terraform", MTEHK_TERRAFORM),
    02162   Hotkey('M', "smallmap", MTEHK_SMALLMAP),
    02163   Hotkey('V', "extra_viewport", MTEHK_EXTRA_VIEWPORT),
    02164   HOTKEY_LIST_END
    02165 };
    02166 HotkeyList ScenarioEditorToolbarWindow::hotkeys("scenedit_maintoolbar", scenedit_maintoolbar_hotkeys);
    02167
    02168 static const NWidgetPart _nested_toolb_scen_inner_widgets[] = {
    02169   NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_PAUSE), SetDataTip(SPR_IMG_PAUSE, STR_TOOLBAR_TOOLTIP_PAUSE_GAME),
    02170   NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_FAST_FORWARD), SetDataTip(SPR_IMG_FASTFORWARD, STR_TOOLBAR_TOOLTIP_FORWARD),
    02171   NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SETTINGS), SetDataTip(SPR_IMG_SETTINGS, STR_TOOLBAR_TOOLTIP_OPTIONS),
    02172   NWidget(WWT_IMGBTN_2, COLOUR_GREY, WID_TE_SAVE), SetDataTip(SPR_IMG_SAVE, STR_SCENEDIT_TOOLBAR_TOOLTIP_SAVE_SCENARIO_LOAD_SCENARIO),
    02173   NWidget(NWID_SPACER),
    02174   NWidget(WWT_PANEL, COLOUR_GREY, WID_TE_SPACER), EndContainer(),
    02175   NWidget(NWID_SPACER),
    02176   NWidget(WWT_PANEL, COLOUR_GREY, WID_TE_DATE_PANEL),
    02177     NWidget(NWID_HORIZONTAL), SetPIP(3, 2, 3),
    02178       NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_DATE_BACKWARD), SetDataTip(SPR_ARROW_DOWN, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD),
    02179       NWidget(WWT_EMPTY, COLOUR_GREY, WID_TE_DATE), SetDataTip(STR_NULL, STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE),
    02180       NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_DATE_FORWARD), SetDataTip(SPR_ARROW_UP, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD),
    02181     EndContainer(),
    02182   EndContainer(),
    02183   NWidget(NWID_SPACER),
    02184   NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SMALL_MAP), SetDataTip(SPR_IMG_SMALLMAP, STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY),
    02185   NWidget(NWID_SPACER),
    02186   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_IN), SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN),
    02187   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_OUT), SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT),
    02188   NWidget(NWID_SPACER),
    02189   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_LAND_GENERATE), SetDataTip(SPR_IMG_LANDSCAPING, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION),
    02190   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TOWN_GENERATE), SetDataTip(SPR_IMG_TOWN, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION),
    02191   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_INDUSTRY), SetDataTip(SPR_IMG_INDUSTRY, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION),
    02192   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ROADS), SetDataTip(SPR_IMG_BUILDROAD, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION),
    02193   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_WATER), SetDataTip(SPR_IMG_BUILDWATER, STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS),
    02194   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TREES), SetDataTip(SPR_IMG_PLANTTREES, STR_SCENEDIT_TOOLBAR_PLANT_TREES),
    02195   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_SIGNS), SetDataTip(SPR_IMG_SIGN, STR_SCENEDIT_TOOLBAR_PLACE_SIGN),
    02196   NWidget(NWID_SPACER),
    02197   NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_MUSIC_SOUND), SetDataTip(SPR_IMG_MUSIC, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW),
    02198   NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_HELP), SetDataTip(SPR_IMG_QUERY, STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION),
    02199   NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SWITCH_BAR), SetDataTip(SPR_IMG_SWITCH_TOOLBAR, STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR),
    02200 };
    02201
    02202 static NWidgetBase *MakeScenarioToolbar(int *biggest_index)
    02203 {
    02204   return MakeNWidgets(_nested_toolb_scen_inner_widgets, lengthof(_nested_toolb_scen_inner_widgets), biggest_index, new NWidgetScenarioToolbarContainer());
    02205 }
    02206
    02207 static const NWidgetPart _nested_toolb_scen_widgets[] = {
    02208   NWidgetFunction(MakeScenarioToolbar),
    02209 };
    02210
    02211 static WindowDesc _toolb_scen_desc(
    02212   WDP_MANUAL, NULL, 640, 22,
    02213   WC_MAIN_TOOLBAR, WC_NONE,
    02214   WDF_NO_FOCUS,
    02215   _nested_toolb_scen_widgets, lengthof(_nested_toolb_scen_widgets),
    02216   &ScenarioEditorToolbarWindow::hotkeys
    02217 );
    02218
    02220 void AllocateToolbar()
    02221 {
    02222   /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
    02223   _last_built_roadtype = ROADTYPE_ROAD;
    02224
    02225   if (_game_mode == GM_EDITOR) {
    02226     new ScenarioEditorToolbarWindow(&_toolb_scen_desc);
    02227   } else {
    02228     new MainToolbarWindow(&_toolb_normal_desc);
    02229   }
    02230 }