toolbar_gui.cpp

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