toolbar_gui.cpp

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