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 }