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 "transparency.h"
00026 #include "strings_func.h"
00027 #include "company_func.h"
00028 #include "company_gui.h"
00029 #include "vehicle_base.h"
00030 #include "cheat_func.h"
00031 #include "transparency_gui.h"
00032 #include "screenshot.h"
00033 #include "signs_func.h"
00034 #include "fios.h"
00035 #include "functions.h"
00036 #include "console_gui.h"
00037 #include "news_gui.h"
00038 #include "ai/ai_gui.hpp"
00039 #include "tilehighlight_func.h"
00040 #include "smallmap_gui.h"
00041 #include "graph_gui.h"
00042 #include "textbuf_gui.h"
00043 #include "newgrf_debug.h"
00044 #include "hotkeys.h"
00045 #include "engine_base.h"
00046 
00047 #include "network/network.h"
00048 #include "network/network_gui.h"
00049 #include "network/network_func.h"
00050 
00051 #include "table/strings.h"
00052 #include "table/sprites.h"
00053 
00054 RailType _last_built_railtype;
00055 RoadType _last_built_roadtype;
00056 
00057 enum ToolbarMode {
00058   TB_NORMAL,
00059   TB_UPPER,
00060   TB_LOWER
00061 };
00062 
00064 enum CallBackFunction {
00065   CBF_NONE,
00066   CBF_PLACE_SIGN,
00067   CBF_PLACE_LANDINFO,
00068 };
00069 
00070 enum ToolbarNormalWidgets {
00071   TBN_PAUSE         = 0,
00072   TBN_FASTFORWARD,
00073   TBN_SETTINGS,
00074   TBN_SAVEGAME,
00075   TBN_SMALLMAP,
00076   TBN_TOWNDIRECTORY,
00077   TBN_SUBSIDIES,
00078   TBN_STATIONS,
00079   TBN_FINANCES,
00080   TBN_COMPANIES,
00081   TBN_GRAPHICS,
00082   TBN_LEAGUE,
00083   TBN_INDUSTRIES,
00084   TBN_VEHICLESTART,      
00085   TBN_TRAINS        = TBN_VEHICLESTART,
00086   TBN_ROADVEHS,
00087   TBN_SHIPS,
00088   TBN_AIRCRAFTS,
00089   TBN_ZOOMIN,
00090   TBN_ZOOMOUT,
00091   TBN_RAILS,
00092   TBN_ROADS,
00093   TBN_WATER,
00094   TBN_AIR,
00095   TBN_LANDSCAPE,
00096   TBN_MUSICSOUND,
00097   TBN_NEWSREPORT,
00098   TBN_HELP,
00099   TBN_SWITCHBAR,         
00100   TBN_END                
00101 };
00102 
00103 enum ToolbarScenEditorWidgets {
00104   TBSE_PAUSE        = 0,
00105   TBSE_FASTFORWARD,
00106   TBSE_SETTINGS,
00107   TBSE_SAVESCENARIO,
00108   TBSE_SPACERPANEL,
00109   TBSE_DATEPANEL,
00110   TBSE_DATEBACKWARD,
00111   TBSE_DATEFORWARD,
00112   TBSE_SMALLMAP,
00113   TBSE_ZOOMIN,
00114   TBSE_ZOOMOUT,
00115   TBSE_LANDGENERATE,
00116   TBSE_TOWNGENERATE,
00117   TBSE_INDUSTRYGENERATE,
00118   TBSE_BUILDROAD,
00119   TBSE_BUILDDOCKS,
00120   TBSE_PLANTTREES,
00121   TBSE_PLACESIGNS,
00122   TBSE_DATEPANEL_CONTAINER,
00123 };
00124 
00128 class DropDownListCheckedItem : public DropDownListStringItem {
00129   uint checkmark_width;
00130 public:
00131   bool checked;
00132 
00133   DropDownListCheckedItem(StringID string, int result, bool masked, bool checked) : DropDownListStringItem(string, result, masked), checked(checked)
00134   {
00135     this->checkmark_width = GetStringBoundingBox(STR_JUST_CHECKMARK).width + 3;
00136   }
00137 
00138   virtual ~DropDownListCheckedItem() {}
00139 
00140   uint Width() const
00141   {
00142     return DropDownListStringItem::Width() + this->checkmark_width;
00143   }
00144 
00145   void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
00146   {
00147     bool rtl = _current_text_dir == TD_RTL;
00148     if (this->checked) {
00149       DrawString(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, STR_JUST_CHECKMARK, sel ? TC_WHITE : TC_BLACK);
00150     }
00151     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);
00152   }
00153 };
00154 
00158 class DropDownListCompanyItem : public DropDownListItem {
00159   uint icon_width;
00160 public:
00161   bool greyed;
00162 
00163   DropDownListCompanyItem(int result, bool masked, bool greyed) : DropDownListItem(result, masked), greyed(greyed)
00164   {
00165     this->icon_width = GetSpriteSize(SPR_COMPANY_ICON).width;
00166   }
00167 
00168   virtual ~DropDownListCompanyItem() {}
00169 
00170   bool Selectable() const
00171   {
00172     return true;
00173   }
00174 
00175   uint Width() const
00176   {
00177     CompanyID company = (CompanyID)this->result;
00178     SetDParam(0, company);
00179     SetDParam(1, company);
00180     return GetStringBoundingBox(STR_COMPANY_NAME_COMPANY_NUM).width + this->icon_width + 3;
00181   }
00182 
00183   void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
00184   {
00185     CompanyID company = (CompanyID)this->result;
00186     bool rtl = _current_text_dir == TD_RTL;
00187 
00188     /* It's possible the company is deleted while the dropdown is open */
00189     if (!Company::IsValidID(company)) return;
00190 
00191     DrawCompanyIcon(company, rtl ? right - this->icon_width - WD_FRAMERECT_RIGHT : left + WD_FRAMERECT_LEFT, top + 1 + (FONT_HEIGHT_NORMAL - 10) / 2);
00192 
00193     SetDParam(0, company);
00194     SetDParam(1, company);
00195     TextColour col;
00196     if (this->greyed) {
00197       col = TC_GREY;
00198     } else {
00199       col = sel ? TC_WHITE : TC_BLACK;
00200     }
00201     DrawString(left + WD_FRAMERECT_LEFT + (rtl ? 0 : 3 + this->icon_width), right - WD_FRAMERECT_RIGHT - (rtl ? 3 + this->icon_width : 0), top, STR_COMPANY_NAME_COMPANY_NUM, col);
00202   }
00203 };
00204 
00208 static void PopupMainToolbMenu(Window *w, int widget, StringID string, int count)
00209 {
00210   DropDownList *list = new DropDownList();
00211   for (int i = 0; i < count; i++) {
00212     list->push_back(new DropDownListStringItem(string + i, i, false));
00213   }
00214   ShowDropDownList(w, list, 0, widget, 140, true, true);
00215   SndPlayFx(SND_15_BEEP);
00216 }
00217 
00219 static const int CTMN_CLIENT_LIST = -1; 
00220 static const int CTMN_NEW_COMPANY = -2; 
00221 static const int CTMN_SPECTATE    = -3; 
00222 
00226 static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0)
00227 {
00228   DropDownList *list = new DropDownList();
00229 
00230 #ifdef ENABLE_NETWORK
00231   if (widget == TBN_COMPANIES && _networking) {
00232     /* Add the client list button for the companies menu */
00233     list->push_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false));
00234 
00235     if (_local_company == COMPANY_SPECTATOR) {
00236       list->push_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached()));
00237     } else {
00238       list->push_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, NetworkMaxSpectatorsReached()));
00239     }
00240   }
00241 #endif /* ENABLE_NETWORK */
00242 
00243   for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00244     if (!Company::IsValidID(c)) continue;
00245     list->push_back(new DropDownListCompanyItem(c, false, HasBit(grey, c)));
00246   }
00247 
00248   ShowDropDownList(w, list, _local_company == COMPANY_SPECTATOR ? CTMN_CLIENT_LIST : (int)_local_company, widget, 240, true, true);
00249   SndPlayFx(SND_15_BEEP);
00250 }
00251 
00252 
00253 static ToolbarMode _toolbar_mode;
00254 
00255 static CallBackFunction SelectSignTool()
00256 {
00257   if (_cursor.sprite == SPR_CURSOR_SIGN) {
00258     ResetObjectToPlace();
00259     return CBF_NONE;
00260   } else {
00261     SetObjectToPlace(SPR_CURSOR_SIGN, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0);
00262     return CBF_PLACE_SIGN;
00263   }
00264 }
00265 
00266 /* --- Pausing --- */
00267 
00268 static CallBackFunction ToolbarPauseClick(Window *w)
00269 {
00270   if (_networking && !_network_server) return CBF_NONE; // only server can pause the game
00271 
00272   if (DoCommandP(0, PM_PAUSED_NORMAL, _pause_mode == PM_UNPAUSED, CMD_PAUSE)) SndPlayFx(SND_15_BEEP);
00273   return CBF_NONE;
00274 }
00275 
00276 /* --- Fast forwarding --- */
00277 
00278 static CallBackFunction ToolbarFastForwardClick(Window *w)
00279 {
00280   _fast_forward ^= true;
00281   SndPlayFx(SND_15_BEEP);
00282   return CBF_NONE;
00283 }
00284 
00285 /* --- Options button menu --- */
00286 
00287 enum OptionMenuEntries {
00288   OME_GAMEOPTIONS,
00289   OME_DIFFICULTIES,
00290   OME_SETTINGS,
00291   OME_AI_SETTINGS,
00292   OME_NEWGRFSETTINGS,
00293   OME_TRANSPARENCIES,
00294   OME_SHOW_TOWNNAMES,
00295   OME_SHOW_STATIONNAMES,
00296   OME_SHOW_WAYPOINTNAMES,
00297   OME_SHOW_SIGNS,
00298   OME_FULL_ANIMATION,
00299   OME_FULL_DETAILS,
00300   OME_TRANSPARENTBUILDINGS,
00301   OME_SHOW_STATIONSIGNS,
00302 };
00303 
00304 static CallBackFunction ToolbarOptionsClick(Window *w)
00305 {
00306   DropDownList *list = new DropDownList();
00307   list->push_back(new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS,             OME_GAMEOPTIONS, false));
00308   list->push_back(new DropDownListStringItem(STR_SETTINGS_MENU_DIFFICULTY_SETTINGS,      OME_DIFFICULTIES, false));
00309   list->push_back(new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS,          OME_SETTINGS, false));
00310   /* Changes to the per-AI settings don't get send from the server to the clients. Clients get
00311    * the settings once they join but never update it. As such don't show the window at all
00312    * to network clients. */
00313   if (!_networking || _network_server) list->push_back(new DropDownListStringItem(STR_SETTINGS_MENU_AI_SETTINGS, OME_AI_SETTINGS, false));
00314   list->push_back(new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS,          OME_NEWGRFSETTINGS, false));
00315   list->push_back(new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS,     OME_TRANSPARENCIES, false));
00316   list->push_back(new DropDownListItem(-1, false));
00317   list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED,    OME_SHOW_TOWNNAMES, false, HasBit(_display_opt, DO_SHOW_TOWN_NAMES)));
00318   list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED, OME_SHOW_STATIONNAMES, false, HasBit(_display_opt, DO_SHOW_STATION_NAMES)));
00319   list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED,     OME_SHOW_WAYPOINTNAMES, false, HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES)));
00320   list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED,         OME_SHOW_SIGNS, false, HasBit(_display_opt, DO_SHOW_SIGNS)));
00321   list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION,          OME_FULL_ANIMATION, false, HasBit(_display_opt, DO_FULL_ANIMATION)));
00322   list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL,             OME_FULL_DETAILS, false, HasBit(_display_opt, DO_FULL_DETAIL)));
00323   list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS,   OME_TRANSPARENTBUILDINGS, false, IsTransparencySet(TO_HOUSES)));
00324   list->push_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS,       OME_SHOW_STATIONSIGNS, false, IsTransparencySet(TO_SIGNS)));
00325 
00326   ShowDropDownList(w, list, 0, TBN_SETTINGS, 140, true, true);
00327   SndPlayFx(SND_15_BEEP);
00328   return CBF_NONE;
00329 }
00330 
00331 static CallBackFunction MenuClickSettings(int index)
00332 {
00333   switch (index) {
00334     case OME_GAMEOPTIONS:          ShowGameOptions();                               return CBF_NONE;
00335     case OME_DIFFICULTIES:         ShowGameDifficulty();                            return CBF_NONE;
00336     case OME_SETTINGS:             ShowGameSettings();                              return CBF_NONE;
00337     case OME_AI_SETTINGS:          ShowAIConfigWindow();                            return CBF_NONE;
00338     case OME_NEWGRFSETTINGS:       ShowNewGRFSettings(!_networking && _settings_client.gui.UserIsAllowedToChangeNewGRFs(), true, true, &_grfconfig); return CBF_NONE;
00339     case OME_TRANSPARENCIES:       ShowTransparencyToolbar();                       break;
00340 
00341     case OME_SHOW_TOWNNAMES:       ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES);     break;
00342     case OME_SHOW_STATIONNAMES:    ToggleBit(_display_opt, DO_SHOW_STATION_NAMES);  break;
00343     case OME_SHOW_WAYPOINTNAMES:   ToggleBit(_display_opt, DO_SHOW_WAYPOINT_NAMES); break;
00344     case OME_SHOW_SIGNS:           ToggleBit(_display_opt, DO_SHOW_SIGNS);          break;
00345     case OME_FULL_ANIMATION:       ToggleBit(_display_opt, DO_FULL_ANIMATION);      break;
00346     case OME_FULL_DETAILS:         ToggleBit(_display_opt, DO_FULL_DETAIL);         break;
00347     case OME_TRANSPARENTBUILDINGS: ToggleTransparency(TO_HOUSES);                   break;
00348     case OME_SHOW_STATIONSIGNS:    ToggleTransparency(TO_SIGNS);                    break;
00349   }
00350   MarkWholeScreenDirty();
00351   return CBF_NONE;
00352 }
00353 
00354 /* --- Saving/loading button menu --- */
00355 
00356 enum SaveLoadEditorMenuEntries {
00357   SLEME_SAVE_SCENARIO   = 0,
00358   SLEME_LOAD_SCENARIO,
00359   SLEME_LOAD_HEIGHTMAP,
00360   SLEME_EXIT_TOINTRO,
00361   SLEME_EXIT_GAME       = 5,
00362   SLEME_MENUCOUNT,
00363 };
00364 
00365 enum SaveLoadNormalMenuEntries {
00366   SLNME_SAVE_GAME   = 0,
00367   SLNME_LOAD_GAME,
00368   SLNME_EXIT_TOINTRO,
00369   SLNME_EXIT_GAME,
00370   SLNME_MENUCOUNT,
00371 };
00372 
00373 static CallBackFunction ToolbarSaveClick(Window *w)
00374 {
00375   PopupMainToolbMenu(w, TBN_SAVEGAME, STR_FILE_MENU_SAVE_GAME, SLNME_MENUCOUNT);
00376   return CBF_NONE;
00377 }
00378 
00379 static CallBackFunction ToolbarScenSaveOrLoad(Window *w)
00380 {
00381   PopupMainToolbMenu(w, TBSE_SAVESCENARIO, STR_SCENEDIT_FILE_MENU_SAVE_SCENARIO, SLEME_MENUCOUNT);
00382   return CBF_NONE;
00383 }
00384 
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_LOAD_HEIGHTMAP: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break;
00392       case SLEME_EXIT_TOINTRO:   AskExitToGameMenu();                    break;
00393       case SLEME_EXIT_GAME:      HandleExitGameRequest();                break;
00394     }
00395   } else {
00396     switch (index) {
00397       case SLNME_SAVE_GAME:      ShowSaveLoadDialog(SLD_SAVE_GAME); break;
00398       case SLNME_LOAD_GAME:      ShowSaveLoadDialog(SLD_LOAD_GAME); break;
00399       case SLNME_EXIT_TOINTRO:   AskExitToGameMenu();               break;
00400       case SLNME_EXIT_GAME:      HandleExitGameRequest();           break;
00401     }
00402   }
00403   return CBF_NONE;
00404 }
00405 
00406 /* --- Map button menu --- */
00407 
00408 enum MapMenuEntries {
00409   MME_SHOW_SMALLMAP        = 0,
00410   MME_SHOW_EXTRAVIEWPORTS,
00411   MME_SHOW_SIGNLISTS,
00412   MME_SHOW_TOWNDIRECTORY,    
00413   MME_MENUCOUNT_NORMAL     = 3,
00414   MME_MENUCOUNT_EDITOR     = 4,
00415 };
00416 
00417 static CallBackFunction ToolbarMapClick(Window *w)
00418 {
00419   PopupMainToolbMenu(w, TBN_SMALLMAP, STR_MAP_MENU_MAP_OF_WORLD, MME_MENUCOUNT_NORMAL);
00420   return CBF_NONE;
00421 }
00422 
00423 static CallBackFunction ToolbarScenMapTownDir(Window *w)
00424 {
00425   PopupMainToolbMenu(w, TBSE_SMALLMAP, STR_MAP_MENU_MAP_OF_WORLD, MME_MENUCOUNT_EDITOR);
00426   return CBF_NONE;
00427 }
00428 
00429 static CallBackFunction MenuClickMap(int index)
00430 {
00431   switch (index) {
00432     case MME_SHOW_SMALLMAP:       ShowSmallMap();            break;
00433     case MME_SHOW_EXTRAVIEWPORTS: ShowExtraViewPortWindow(); break;
00434     case MME_SHOW_SIGNLISTS:      ShowSignList();            break;
00435     case MME_SHOW_TOWNDIRECTORY:  if (_game_mode == GM_EDITOR) ShowTownDirectory(); break;
00436   }
00437   return CBF_NONE;
00438 }
00439 
00440 /* --- Town button menu --- */
00441 
00442 static CallBackFunction ToolbarTownClick(Window *w)
00443 {
00444   PopupMainToolbMenu(w, TBN_TOWNDIRECTORY, STR_TOWN_MENU_TOWN_DIRECTORY, (_settings_game.economy.found_town == TF_FORBIDDEN) ? 1 : 2);
00445   return CBF_NONE;
00446 }
00447 
00448 static CallBackFunction MenuClickTown(int index)
00449 {
00450   switch (index) {
00451     case 0: ShowTownDirectory(); break;
00452     case 1: // setting could be changed when the dropdown was open
00453       if (_settings_game.economy.found_town != TF_FORBIDDEN) ShowFoundTownWindow();
00454       break;
00455   }
00456   return CBF_NONE;
00457 }
00458 
00459 /* --- Subidies button menu --- */
00460 
00461 static CallBackFunction ToolbarSubsidiesClick(Window *w)
00462 {
00463   PopupMainToolbMenu(w, TBN_SUBSIDIES, STR_SUBSIDIES_MENU_SUBSIDIES, 1);
00464   return CBF_NONE;
00465 }
00466 
00467 static CallBackFunction MenuClickSubsidies(int index)
00468 {
00469   ShowSubsidiesList();
00470   return CBF_NONE;
00471 }
00472 
00473 /* --- Stations button menu --- */
00474 
00475 static CallBackFunction ToolbarStationsClick(Window *w)
00476 {
00477   PopupMainCompanyToolbMenu(w, TBN_STATIONS);
00478   return CBF_NONE;
00479 }
00480 
00481 static CallBackFunction MenuClickStations(int index)
00482 {
00483   ShowCompanyStations((CompanyID)index);
00484   return CBF_NONE;
00485 }
00486 
00487 /* --- Finances button menu --- */
00488 
00489 static CallBackFunction ToolbarFinancesClick(Window *w)
00490 {
00491   PopupMainCompanyToolbMenu(w, TBN_FINANCES);
00492   return CBF_NONE;
00493 }
00494 
00495 static CallBackFunction MenuClickFinances(int index)
00496 {
00497   ShowCompanyFinances((CompanyID)index);
00498   return CBF_NONE;
00499 }
00500 
00501 /* --- Company's button menu --- */
00502 
00503 static CallBackFunction ToolbarCompaniesClick(Window *w)
00504 {
00505   PopupMainCompanyToolbMenu(w, TBN_COMPANIES);
00506   return CBF_NONE;
00507 }
00508 
00509 static CallBackFunction MenuClickCompany(int index)
00510 {
00511 #ifdef ENABLE_NETWORK
00512   if (_networking) {
00513     switch (index) {
00514       case CTMN_CLIENT_LIST:
00515         ShowClientList();
00516         return CBF_NONE;
00517 
00518       case CTMN_NEW_COMPANY:
00519         if (_network_server) {
00520           DoCommandP(0, 0, _network_own_client_id, CMD_COMPANY_CTRL);
00521         } else {
00522           NetworkSendCommand(0, 0, 0, CMD_COMPANY_CTRL, NULL, NULL, _local_company);
00523         }
00524         return CBF_NONE;
00525 
00526       case CTMN_SPECTATE:
00527         if (_network_server) {
00528           NetworkServerDoMove(CLIENT_ID_SERVER, COMPANY_SPECTATOR);
00529           MarkWholeScreenDirty();
00530         } else {
00531           NetworkClientRequestMove(COMPANY_SPECTATOR);
00532         }
00533         return CBF_NONE;
00534     }
00535   }
00536 #endif /* ENABLE_NETWORK */
00537   ShowCompany((CompanyID)index);
00538   return CBF_NONE;
00539 }
00540 
00541 /* --- Graphs button menu --- */
00542 
00543 static CallBackFunction ToolbarGraphsClick(Window *w)
00544 {
00545   PopupMainToolbMenu(w, TBN_GRAPHICS, STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, (_toolbar_mode == TB_NORMAL) ? 6 : 8);
00546   return CBF_NONE;
00547 }
00548 
00549 static CallBackFunction MenuClickGraphs(int index)
00550 {
00551   switch (index) {
00552     case 0: ShowOperatingProfitGraph();    break;
00553     case 1: ShowIncomeGraph();             break;
00554     case 2: ShowDeliveredCargoGraph();     break;
00555     case 3: ShowPerformanceHistoryGraph(); break;
00556     case 4: ShowCompanyValueGraph();       break;
00557     case 5: ShowCargoPaymentRates();       break;
00558     /* functions for combined graphs/league button */
00559     case 6: ShowCompanyLeagueTable();      break;
00560     case 7: ShowPerformanceRatingDetail(); break;
00561   }
00562   return CBF_NONE;
00563 }
00564 
00565 /* --- League button menu --- */
00566 
00567 static CallBackFunction ToolbarLeagueClick(Window *w)
00568 {
00569   PopupMainToolbMenu(w, TBN_LEAGUE, STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE, 2);
00570   return CBF_NONE;
00571 }
00572 
00573 static CallBackFunction MenuClickLeague(int index)
00574 {
00575   switch (index) {
00576     case 0: ShowCompanyLeagueTable();      break;
00577     case 1: ShowPerformanceRatingDetail(); break;
00578   }
00579   return CBF_NONE;
00580 }
00581 
00582 /* --- Industries button menu --- */
00583 
00584 static CallBackFunction ToolbarIndustryClick(Window *w)
00585 {
00586   /* Disable build-industry menu if we are a spectator */
00587   PopupMainToolbMenu(w, TBN_INDUSTRIES, STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, (_local_company == COMPANY_SPECTATOR) ? 1 : 2);
00588   return CBF_NONE;
00589 }
00590 
00591 static CallBackFunction MenuClickIndustry(int index)
00592 {
00593   switch (index) {
00594     case 0: ShowIndustryDirectory();   break;
00595     case 1: ShowBuildIndustryWindow(); break;
00596   }
00597   return CBF_NONE;
00598 }
00599 
00600 /* --- Trains button menu + 1 helper function for all vehicles. --- */
00601 
00602 static void ToolbarVehicleClick(Window *w, VehicleType veh)
00603 {
00604   const Vehicle *v;
00605   int dis = ~0;
00606 
00607   FOR_ALL_VEHICLES(v) {
00608     if (v->type == veh && v->IsPrimaryVehicle()) ClrBit(dis, v->owner);
00609   }
00610   PopupMainCompanyToolbMenu(w, TBN_VEHICLESTART + veh, dis);
00611 }
00612 
00613 
00614 static CallBackFunction ToolbarTrainClick(Window *w)
00615 {
00616   ToolbarVehicleClick(w, VEH_TRAIN);
00617   return CBF_NONE;
00618 }
00619 
00620 static CallBackFunction MenuClickShowTrains(int index)
00621 {
00622   ShowVehicleListWindow((CompanyID)index, VEH_TRAIN);
00623   return CBF_NONE;
00624 }
00625 
00626 /* --- Road vehicle button menu --- */
00627 
00628 static CallBackFunction ToolbarRoadClick(Window *w)
00629 {
00630   ToolbarVehicleClick(w, VEH_ROAD);
00631   return CBF_NONE;
00632 }
00633 
00634 static CallBackFunction MenuClickShowRoad(int index)
00635 {
00636   ShowVehicleListWindow((CompanyID)index, VEH_ROAD);
00637   return CBF_NONE;
00638 }
00639 
00640 /* --- Ship button menu --- */
00641 
00642 static CallBackFunction ToolbarShipClick(Window *w)
00643 {
00644   ToolbarVehicleClick(w, VEH_SHIP);
00645   return CBF_NONE;
00646 }
00647 
00648 static CallBackFunction MenuClickShowShips(int index)
00649 {
00650   ShowVehicleListWindow((CompanyID)index, VEH_SHIP);
00651   return CBF_NONE;
00652 }
00653 
00654 /* --- Aircraft button menu --- */
00655 
00656 static CallBackFunction ToolbarAirClick(Window *w)
00657 {
00658   ToolbarVehicleClick(w, VEH_AIRCRAFT);
00659   return CBF_NONE;
00660 }
00661 
00662 static CallBackFunction MenuClickShowAir(int index)
00663 {
00664   ShowVehicleListWindow((CompanyID)index, VEH_AIRCRAFT);
00665   return CBF_NONE;
00666 }
00667 
00668 /* --- Zoom in button --- */
00669 
00670 static CallBackFunction ToolbarZoomInClick(Window *w)
00671 {
00672   if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) {
00673     w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)TBSE_ZOOMIN : (byte)TBN_ZOOMIN);
00674     SndPlayFx(SND_15_BEEP);
00675   }
00676   return CBF_NONE;
00677 }
00678 
00679 /* --- Zoom out button --- */
00680 
00681 static CallBackFunction ToolbarZoomOutClick(Window *w)
00682 {
00683   if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) {
00684     w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)TBSE_ZOOMOUT : (byte)TBN_ZOOMOUT);
00685     SndPlayFx(SND_15_BEEP);
00686   }
00687   return CBF_NONE;
00688 }
00689 
00690 /* --- Rail button menu --- */
00691 
00692 static CallBackFunction ToolbarBuildRailClick(Window *w)
00693 {
00694   ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, TBN_RAILS, 140, true, true);
00695   SndPlayFx(SND_15_BEEP);
00696   return CBF_NONE;
00697 }
00698 
00699 static CallBackFunction MenuClickBuildRail(int index)
00700 {
00701   _last_built_railtype = (RailType)index;
00702   ShowBuildRailToolbar(_last_built_railtype);
00703   return CBF_NONE;
00704 }
00705 
00706 /* --- Road button menu --- */
00707 
00708 static CallBackFunction ToolbarBuildRoadClick(Window *w)
00709 {
00710   const Company *c = Company::Get(_local_company);
00711   DropDownList *list = new DropDownList();
00712 
00713   /* Road is always visible and available. */
00714   list->push_back(new DropDownListStringItem(STR_ROAD_MENU_ROAD_CONSTRUCTION, ROADTYPE_ROAD, false));
00715 
00716   /* Tram is only visible when there will be a tram, and available when that has been introduced. */
00717   Engine *e;
00718   FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
00719     if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
00720     if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
00721 
00722     list->push_back(new DropDownListStringItem(STR_ROAD_MENU_TRAM_CONSTRUCTION, ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM)));
00723     break;
00724   }
00725   ShowDropDownList(w, list, _last_built_roadtype, TBN_ROADS, 140, true, true);
00726   SndPlayFx(SND_15_BEEP);
00727   return CBF_NONE;
00728 }
00729 
00730 static CallBackFunction MenuClickBuildRoad(int index)
00731 {
00732   _last_built_roadtype = (RoadType)index;
00733   ShowBuildRoadToolbar(_last_built_roadtype);
00734   return CBF_NONE;
00735 }
00736 
00737 /* --- Water button menu --- */
00738 
00739 static CallBackFunction ToolbarBuildWaterClick(Window *w)
00740 {
00741   PopupMainToolbMenu(w, TBN_WATER, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION, 1);
00742   return CBF_NONE;
00743 }
00744 
00745 static CallBackFunction MenuClickBuildWater(int index)
00746 {
00747   ShowBuildDocksToolbar();
00748   return CBF_NONE;
00749 }
00750 
00751 /* --- Airport button menu --- */
00752 
00753 static CallBackFunction ToolbarBuildAirClick(Window *w)
00754 {
00755   PopupMainToolbMenu(w, TBN_AIR, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION, 1);
00756   return CBF_NONE;
00757 }
00758 
00759 static CallBackFunction MenuClickBuildAir(int index)
00760 {
00761   ShowBuildAirToolbar();
00762   return CBF_NONE;
00763 }
00764 
00765 /* --- Forest button menu --- */
00766 
00767 static CallBackFunction ToolbarForestClick(Window *w)
00768 {
00769   PopupMainToolbMenu(w, TBN_LANDSCAPE, STR_LANDSCAPING_MENU_LANDSCAPING, 3);
00770   return CBF_NONE;
00771 }
00772 
00773 static CallBackFunction MenuClickForest(int index)
00774 {
00775   switch (index) {
00776     case 0: ShowTerraformToolbar();  break;
00777     case 1: ShowBuildTreesToolbar(); break;
00778     case 2: return SelectSignTool();
00779   }
00780   return CBF_NONE;
00781 }
00782 
00783 /* --- Music button menu --- */
00784 
00785 static CallBackFunction ToolbarMusicClick(Window *w)
00786 {
00787   PopupMainToolbMenu(w, TBN_MUSICSOUND, STR_TOOLBAR_SOUND_MUSIC, 1);
00788   return CBF_NONE;
00789 }
00790 
00791 static CallBackFunction MenuClickMusicWindow(int index)
00792 {
00793   ShowMusicWindow();
00794   return CBF_NONE;
00795 }
00796 
00797 /* --- Newspaper button menu --- */
00798 
00799 static CallBackFunction ToolbarNewspaperClick(Window *w)
00800 {
00801   PopupMainToolbMenu(w, TBN_NEWSREPORT, STR_NEWS_MENU_LAST_MESSAGE_NEWS_REPORT, 3);
00802   return CBF_NONE;
00803 }
00804 
00805 static CallBackFunction MenuClickNewspaper(int index)
00806 {
00807   switch (index) {
00808     case 0: ShowLastNewsMessage(); break;
00809     case 1: ShowMessageOptions();  break;
00810     case 2: ShowMessageHistory();  break;
00811   }
00812   return CBF_NONE;
00813 }
00814 
00815 /* --- Help button menu --- */
00816 
00817 static CallBackFunction PlaceLandBlockInfo()
00818 {
00819   if (_cursor.sprite == SPR_CURSOR_QUERY) {
00820     ResetObjectToPlace();
00821     return CBF_NONE;
00822   } else {
00823     SetObjectToPlace(SPR_CURSOR_QUERY, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0);
00824     return CBF_PLACE_LANDINFO;
00825   }
00826 }
00827 
00828 static CallBackFunction ToolbarHelpClick(Window *w)
00829 {
00830   PopupMainToolbMenu(w, TBN_HELP, STR_ABOUT_MENU_LAND_BLOCK_INFO, _settings_client.gui.newgrf_developer_tools ? 9 : 8);
00831   return CBF_NONE;
00832 }
00833 
00834 static void MenuClickSmallScreenshot()
00835 {
00836   MakeScreenshot(SC_VIEWPORT, NULL);
00837 }
00838 
00839 static void MenuClickZoomedInScreenshot()
00840 {
00841   MakeScreenshot(SC_ZOOMEDIN, NULL);
00842 }
00843 
00844 static void MenuClickWorldScreenshot()
00845 {
00846   MakeScreenshot(SC_WORLD, NULL);
00847 }
00848 
00849 static CallBackFunction MenuClickHelp(int index)
00850 {
00851   switch (index) {
00852     case 0: return PlaceLandBlockInfo();
00853     case 2: IConsoleSwitch();              break;
00854     case 3: ShowAIDebugWindow();           break;
00855     case 4: MenuClickSmallScreenshot();    break;
00856     case 5: MenuClickZoomedInScreenshot(); break;
00857     case 6: MenuClickWorldScreenshot();    break;
00858     case 7: ShowAboutWindow();             break;
00859     case 8: ShowSpriteAlignerWindow();     break;
00860   }
00861   return CBF_NONE;
00862 }
00863 
00864 /* --- Switch toolbar button --- */
00865 
00866 static CallBackFunction ToolbarSwitchClick(Window *w)
00867 {
00868   if (_toolbar_mode != TB_LOWER) {
00869     _toolbar_mode = TB_LOWER;
00870   } else {
00871     _toolbar_mode = TB_UPPER;
00872   }
00873 
00874   w->ReInit();
00875   w->SetWidgetLoweredState(TBN_SWITCHBAR, _toolbar_mode == TB_LOWER);
00876   SndPlayFx(SND_15_BEEP);
00877   return CBF_NONE;
00878 }
00879 
00880 /* --- Scenario editor specific handlers. */
00881 
00885 static CallBackFunction ToolbarScenDatePanel(Window *w)
00886 {
00887   SetDParam(0, _settings_game.game_creation.starting_year);
00888   ShowQueryString(STR_JUST_INT, STR_MAPGEN_START_DATE_QUERY_CAPT, 8, 100, w, CS_NUMERAL, QSF_ENABLE_DEFAULT);
00889   _left_button_clicked = false;
00890   return CBF_NONE;
00891 }
00892 
00893 static CallBackFunction ToolbarScenDateBackward(Window *w)
00894 {
00895   /* don't allow too fast scrolling */
00896   if ((w->flags4 & WF_TIMEOUT_MASK) <= WF_TIMEOUT_TRIGGER) {
00897     w->HandleButtonClick(TBSE_DATEBACKWARD);
00898     w->SetDirty();
00899 
00900     _settings_game.game_creation.starting_year = Clamp(_settings_game.game_creation.starting_year - 1, MIN_YEAR, MAX_YEAR);
00901     SetDate(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1), 0);
00902   }
00903   _left_button_clicked = false;
00904   return CBF_NONE;
00905 }
00906 
00907 static CallBackFunction ToolbarScenDateForward(Window *w)
00908 {
00909   /* don't allow too fast scrolling */
00910   if ((w->flags4 & WF_TIMEOUT_MASK) <= WF_TIMEOUT_TRIGGER) {
00911     w->HandleButtonClick(TBSE_DATEFORWARD);
00912     w->SetDirty();
00913 
00914     _settings_game.game_creation.starting_year = Clamp(_settings_game.game_creation.starting_year + 1, MIN_YEAR, MAX_YEAR);
00915     SetDate(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1), 0);
00916   }
00917   _left_button_clicked = false;
00918   return CBF_NONE;
00919 }
00920 
00921 static CallBackFunction ToolbarScenGenLand(Window *w)
00922 {
00923   w->HandleButtonClick(TBSE_LANDGENERATE);
00924   SndPlayFx(SND_15_BEEP);
00925 
00926   ShowEditorTerraformToolbar();
00927   return CBF_NONE;
00928 }
00929 
00930 
00931 static CallBackFunction ToolbarScenGenTown(Window *w)
00932 {
00933   w->HandleButtonClick(TBSE_TOWNGENERATE);
00934   SndPlayFx(SND_15_BEEP);
00935   ShowFoundTownWindow();
00936   return CBF_NONE;
00937 }
00938 
00939 static CallBackFunction ToolbarScenGenIndustry(Window *w)
00940 {
00941   w->HandleButtonClick(TBSE_INDUSTRYGENERATE);
00942   SndPlayFx(SND_15_BEEP);
00943   ShowBuildIndustryWindow();
00944   return CBF_NONE;
00945 }
00946 
00947 static CallBackFunction ToolbarScenBuildRoad(Window *w)
00948 {
00949   w->HandleButtonClick(TBSE_BUILDROAD);
00950   SndPlayFx(SND_15_BEEP);
00951   ShowBuildRoadScenToolbar();
00952   return CBF_NONE;
00953 }
00954 
00955 static CallBackFunction ToolbarScenBuildDocks(Window *w)
00956 {
00957   w->HandleButtonClick(TBSE_BUILDDOCKS);
00958   SndPlayFx(SND_15_BEEP);
00959   ShowBuildDocksScenToolbar();
00960   return CBF_NONE;
00961 }
00962 
00963 static CallBackFunction ToolbarScenPlantTrees(Window *w)
00964 {
00965   w->HandleButtonClick(TBSE_PLANTTREES);
00966   SndPlayFx(SND_15_BEEP);
00967   ShowBuildTreesToolbar();
00968   return CBF_NONE;
00969 }
00970 
00971 static CallBackFunction ToolbarScenPlaceSign(Window *w)
00972 {
00973   w->HandleButtonClick(TBSE_PLACESIGNS);
00974   SndPlayFx(SND_15_BEEP);
00975   return SelectSignTool();
00976 }
00977 
00978 static CallBackFunction ToolbarBtn_NULL(Window *w)
00979 {
00980   return CBF_NONE;
00981 }
00982 
00983 typedef CallBackFunction MenuClickedProc(int index);
00984 
00985 static MenuClickedProc * const _menu_clicked_procs[] = {
00986   NULL,                 // 0
00987   NULL,                 // 1
00988   MenuClickSettings,    // 2
00989   MenuClickSaveLoad,    // 3
00990   MenuClickMap,         // 4
00991   MenuClickTown,        // 5
00992   MenuClickSubsidies,   // 6
00993   MenuClickStations,    // 7
00994   MenuClickFinances,    // 8
00995   MenuClickCompany,     // 9
00996   MenuClickGraphs,      // 10
00997   MenuClickLeague,      // 11
00998   MenuClickIndustry,    // 12
00999   MenuClickShowTrains,  // 13
01000   MenuClickShowRoad,    // 14
01001   MenuClickShowShips,   // 15
01002   MenuClickShowAir,     // 16
01003   MenuClickMap,         // 17
01004   NULL,                 // 18
01005   MenuClickBuildRail,   // 19
01006   MenuClickBuildRoad,   // 20
01007   MenuClickBuildWater,  // 21
01008   MenuClickBuildAir,    // 22
01009   MenuClickForest,      // 23
01010   MenuClickMusicWindow, // 24
01011   MenuClickNewspaper,   // 25
01012   MenuClickHelp,        // 26
01013 };
01014 
01015 int16 *_preferred_toolbar_size = NULL; 
01016 
01018 class NWidgetToolbarContainer : public NWidgetContainer {
01019   bool visible[TBN_END]; 
01020 protected:
01021   uint spacers;          
01022 
01023 public:
01024   NWidgetToolbarContainer() : NWidgetContainer(NWID_HORIZONTAL)
01025   {
01026   }
01027 
01033   bool IsButton(WidgetType type) const
01034   {
01035     return type == WWT_IMGBTN || type == WWT_IMGBTN_2 || type == WWT_PUSHIMGBTN;
01036   }
01037 
01038   void SetupSmallestSize(Window *w, bool init_array)
01039   {
01040     this->smallest_x = 0; // Biggest child
01041     this->smallest_y = 0; // Biggest child
01042     this->fill_x = 1;
01043     this->fill_y = 0;
01044     this->resize_x = 1; // We only resize in this direction
01045     this->resize_y = 0; // We never resize in this direction
01046     this->spacers = 0;
01047 
01048     uint nbuttons = 0;
01049     /* First initialise some variables... */
01050     for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
01051       child_wid->SetupSmallestSize(w, init_array);
01052       this->smallest_y = max(this->smallest_y, child_wid->smallest_y + child_wid->padding_top + child_wid->padding_bottom);
01053       if (this->IsButton(child_wid->type)) {
01054         nbuttons++;
01055         this->smallest_x = max(this->smallest_x, child_wid->smallest_x + child_wid->padding_left + child_wid->padding_right);
01056       } else if (child_wid->type == NWID_SPACER) {
01057         this->spacers++;
01058       }
01059     }
01060 
01061     /* ... then in a second pass make sure the 'current' heights are set. Won't change ever. */
01062     for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
01063       child_wid->current_y = this->smallest_y;
01064       if (!this->IsButton(child_wid->type)) {
01065         child_wid->current_x = child_wid->smallest_x;
01066       }
01067     }
01068     *_preferred_toolbar_size = nbuttons * this->smallest_x;
01069   }
01070 
01071   void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl)
01072   {
01073     assert(given_width >= this->smallest_x && given_height >= this->smallest_y);
01074 
01075     this->pos_x = x;
01076     this->pos_y = y;
01077     this->current_x = given_width;
01078     this->current_y = given_height;
01079 
01080     /* Figure out what are the visible buttons */
01081     memset(this->visible, 0, sizeof(this->visible));
01082     uint arrangable_count, button_count, spacer_count;
01083     const byte *arrangement = GetButtonArrangement(given_width, arrangable_count, button_count, spacer_count);
01084     for (uint i = 0; i < arrangable_count; i++) {
01085       this->visible[arrangement[i]] = true;
01086     }
01087 
01088     /* Create us ourselves a quick lookup table */
01089     NWidgetBase *widgets[TBN_END];
01090     for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
01091       if (child_wid->type == NWID_SPACER) continue;
01092       widgets[((NWidgetCore*)child_wid)->index] = child_wid;
01093     }
01094 
01095     /* Now assign the widgets to their rightful place */
01096     uint position = 0; // Place to put next child relative to origin of the container.
01097     uint spacer_space = max(0, (int)given_width - (int)(button_count * this->smallest_x)); // Remaining spacing for 'spacer' widgets
01098     uint button_space = given_width - spacer_space; // Remaining spacing for the buttons
01099     uint spacer_i = 0;
01100     uint button_i = 0;
01101 
01102     /* Index into the arrangement indices. The macro lastof cannot be used here! */
01103     const byte *cur_wid = rtl ? &arrangement[arrangable_count - 1] : arrangement;
01104     for (uint i = 0; i < arrangable_count; i++) {
01105       NWidgetBase *child_wid = widgets[*cur_wid];
01106       /* If we have to give space to the spacers, do that */
01107       if (spacer_space != 0) {
01108         NWidgetBase *possible_spacer = rtl ? child_wid->next : child_wid->prev;
01109         if (possible_spacer != NULL && possible_spacer->type == NWID_SPACER) {
01110           uint add = spacer_space / (spacer_count - spacer_i);
01111           position += add;
01112           spacer_space -= add;
01113           spacer_i++;
01114         }
01115       }
01116 
01117       /* Buttons can be scaled, the others not. */
01118       if (this->IsButton(child_wid->type)) {
01119         child_wid->current_x = button_space / (button_count - button_i);
01120         button_space -= child_wid->current_x;
01121         button_i++;
01122       }
01123       child_wid->AssignSizePosition(sizing, x + position, y, child_wid->current_x, this->current_y, rtl);
01124       position += child_wid->current_x;
01125 
01126       if (rtl) {
01127         cur_wid--;
01128       } else {
01129         cur_wid++;
01130       }
01131     }
01132   }
01133 
01134   /* virtual */ void Draw(const Window *w)
01135   {
01136     /* Draw brown-red toolbar bg. */
01137     GfxFillRect(this->pos_x, this->pos_y, this->pos_x + this->current_x - 1, this->pos_y + this->current_y - 1, 0xB2);
01138     GfxFillRect(this->pos_x, this->pos_y, this->pos_x + this->current_x - 1, this->pos_y + this->current_y - 1, 0xB4, FILLRECT_CHECKER);
01139 
01140     bool rtl = _current_text_dir == TD_RTL;
01141     for (NWidgetBase *child_wid = rtl ? this->tail : this->head; child_wid != NULL; child_wid = rtl ? child_wid->prev : child_wid->next) {
01142       if (child_wid->type == NWID_SPACER) continue;
01143       if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
01144 
01145       child_wid->Draw(w);
01146     }
01147   }
01148 
01149   /* virtual */ NWidgetCore *GetWidgetFromPos(int x, int y)
01150   {
01151     if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return NULL;
01152 
01153     for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
01154       if (child_wid->type == NWID_SPACER) continue;
01155       if (!this->visible[((NWidgetCore*)child_wid)->index]) continue;
01156 
01157       NWidgetCore *nwid = child_wid->GetWidgetFromPos(x, y);
01158       if (nwid != NULL) return nwid;
01159     }
01160     return NULL;
01161   }
01162 
01171   virtual const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const = 0;
01172 };
01173 
01175 class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
01176   /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
01177   {
01178     static const uint SMALLEST_ARRANGEMENT = 14;
01179     static const uint BIGGEST_ARRANGEMENT  = 19;
01180     static const byte arrange14[] = {
01181       0,  1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 27,
01182       2,  3,  4,  5,  6,  7,  8,  9, 10, 12, 24, 25, 26, 27,
01183     };
01184     static const byte arrange15[] = {
01185       0,  1,  4, 13, 14, 15, 16, 19, 20, 21, 22, 23, 17, 18, 27,
01186       0,  2,  4,  3,  5,  6,  7,  8,  9, 10, 12, 24, 25, 26, 27,
01187     };
01188     static const byte arrange16[] = {
01189       0,  1,  2,  4, 13, 14, 15, 16, 19, 20, 21, 22, 23, 17, 18, 27,
01190       0,  1,  3,  5,  6,  7,  8,  9, 10, 12, 24, 25, 26, 17, 18, 27,
01191     };
01192     static const byte arrange17[] = {
01193       0,  1,  2,  4,  6, 13, 14, 15, 16, 19, 20, 21, 22, 23, 17, 18, 27,
01194       0,  1,  3,  4,  6,  5,  7,  8,  9, 10, 12, 24, 25, 26, 17, 18, 27,
01195     };
01196     static const byte arrange18[] = {
01197       0,  1,  2,  4,  5,  6,  7,  8,  9, 12, 19, 20, 21, 22, 23, 17, 18, 27,
01198       0,  1,  3,  4,  5,  6,  7, 10, 13, 14, 15, 16, 24, 25, 26, 17, 18, 27,
01199     };
01200     static const byte arrange19[] = {
01201       0,  1,  2,  4,  5,  6, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 17, 18, 27,
01202       0,  1,  3,  4,  7,  8,  9, 10, 12, 25, 19, 20, 21, 22, 23, 26, 17, 18, 27,
01203     };
01204     static const byte arrange_all[] = {
01205       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,
01206     };
01207 
01208     /* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
01209     uint full_buttons = max(CeilDiv(width, this->smallest_x), SMALLEST_ARRANGEMENT);
01210     if (full_buttons > BIGGEST_ARRANGEMENT) {
01211       button_count = arrangable_count = lengthof(arrange_all);
01212       spacer_count = this->spacers;
01213       return arrange_all;
01214     }
01215 
01216     /* Introduce the split toolbar */
01217     static const byte * const arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19 };
01218 
01219     button_count = arrangable_count = full_buttons;
01220     spacer_count = this->spacers;
01221     return arrangements[full_buttons - SMALLEST_ARRANGEMENT] + ((_toolbar_mode == TB_LOWER) ? full_buttons : 0);
01222   }
01223 };
01224 
01226 class NWidgetScenarioToolbarContainer : public NWidgetToolbarContainer {
01227   uint panel_widths[2]; 
01228 
01229   void SetupSmallestSize(Window *w, bool init_array)
01230   {
01231     this->NWidgetToolbarContainer::SetupSmallestSize(w, init_array);
01232 
01233     /* Find the size of panel_widths */
01234     uint i = 0;
01235     for (NWidgetBase *child_wid = this->head; child_wid != NULL; child_wid = child_wid->next) {
01236       if (child_wid->type == NWID_SPACER || this->IsButton(child_wid->type)) continue;
01237 
01238       assert(i < lengthof(this->panel_widths));
01239       this->panel_widths[i++] = child_wid->current_x;
01240       *_preferred_toolbar_size += child_wid->current_x;
01241     }
01242   }
01243 
01244   /* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
01245   {
01246     static const byte arrange_all[] = {
01247       0, 1, 2, 3, 4, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 24, 26,
01248     };
01249     static const byte arrange_nopanel[] = {
01250       0, 1, 2, 3, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 24, 26,
01251     };
01252     static const byte arrange_switch[] = {
01253       18,  8, 11, 12, 13, 14, 15, 16, 17, 27,
01254        0,  1,  2,  3, 18,  9, 10, 24, 26, 27,
01255     };
01256 
01257     /* If we can place all buttons *and* the panels, show them. */
01258     uint min_full_width = (lengthof(arrange_all) - lengthof(this->panel_widths)) * this->smallest_x + this->panel_widths[0] + this->panel_widths[1];
01259     if (width >= min_full_width) {
01260       width -= this->panel_widths[0] + this->panel_widths[1];
01261       arrangable_count = lengthof(arrange_all);
01262       button_count = arrangable_count - 2;
01263       spacer_count = this->spacers;
01264       return arrange_all;
01265     }
01266 
01267     /* 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 */
01268     uint min_small_width = (lengthof(arrange_switch) - lengthof(this->panel_widths)) * this->smallest_x / 2 + this->panel_widths[1];
01269     if (width > min_small_width) {
01270       width -= this->panel_widths[1];
01271       arrangable_count = lengthof(arrange_nopanel);
01272       button_count = arrangable_count - 1;
01273       spacer_count = this->spacers - 1;
01274       return arrange_nopanel;
01275     }
01276 
01277     /* Split toolbar */
01278     width -= this->panel_widths[1];
01279     arrangable_count = lengthof(arrange_switch) / 2;
01280     button_count = arrangable_count - 1;
01281     spacer_count = 0;
01282     return arrange_switch + ((_toolbar_mode == TB_LOWER) ? arrangable_count : 0);
01283   }
01284 };
01285 
01286 /* --- Toolbar handling for the 'normal' case */
01287 
01288 typedef CallBackFunction ToolbarButtonProc(Window *w);
01289 
01290 static ToolbarButtonProc * const _toolbar_button_procs[] = {
01291   ToolbarPauseClick,
01292   ToolbarFastForwardClick,
01293   ToolbarOptionsClick,
01294   ToolbarSaveClick,
01295   ToolbarMapClick,
01296   ToolbarTownClick,
01297   ToolbarSubsidiesClick,
01298   ToolbarStationsClick,
01299   ToolbarFinancesClick,
01300   ToolbarCompaniesClick,
01301   ToolbarGraphsClick,
01302   ToolbarLeagueClick,
01303   ToolbarIndustryClick,
01304   ToolbarTrainClick,
01305   ToolbarRoadClick,
01306   ToolbarShipClick,
01307   ToolbarAirClick,
01308   ToolbarZoomInClick,
01309   ToolbarZoomOutClick,
01310   ToolbarBuildRailClick,
01311   ToolbarBuildRoadClick,
01312   ToolbarBuildWaterClick,
01313   ToolbarBuildAirClick,
01314   ToolbarForestClick,
01315   ToolbarMusicClick,
01316   ToolbarNewspaperClick,
01317   ToolbarHelpClick,
01318   ToolbarSwitchClick,
01319 };
01320 
01321 enum MainToolbarHotkeys {
01322   MTHK_PAUSE,
01323   MTHK_FASTFORWARD,
01324   MTHK_SETTINGS,
01325   MTHK_SAVEGAME,
01326   MTHK_LOADGAME,
01327   MTHK_SMALLMAP,
01328   MTHK_TOWNDIRECTORY,
01329   MTHK_SUBSIDIES,
01330   MTHK_STATIONS,
01331   MTHK_FINANCES,
01332   MTHK_COMPANIES,
01333   MTHK_GRAPHS,
01334   MTHK_LEAGUE,
01335   MTHK_INDUSTRIES,
01336   MTHK_TRAIN_LIST,
01337   MTHK_ROADVEH_LIST,
01338   MTHK_SHIP_LIST,
01339   MTHK_AIRCRAFT_LIST,
01340   MTHK_ZOOM_IN,
01341   MTHK_ZOOM_OUT,
01342   MTHK_BUILD_RAIL,
01343   MTHK_BUILD_ROAD,
01344   MTHK_BUILD_DOCKS,
01345   MTHK_BUILD_AIRPORT,
01346   MTHK_BUILD_TREES,
01347   MTHK_MUSIC,
01348   MTHK_AI_DEBUG,
01349   MTHK_SMALL_SCREENSHOT,
01350   MTHK_ZOOMEDIN_SCREENSHOT,
01351   MTHK_GIANT_SCREENSHOT,
01352   MTHK_CHEATS,
01353   MTHK_TERRAFORM,
01354   MTHK_EXTRA_VIEWPORT,
01355   MTHK_CLIENT_LIST,
01356   MTHK_SIGN_LIST,
01357 };
01358 
01360 struct MainToolbarWindow : Window {
01361   CallBackFunction last_started_action; 
01362 
01363   MainToolbarWindow(const WindowDesc *desc) : Window()
01364   {
01365     this->InitNested(desc, 0);
01366 
01367     this->last_started_action = CBF_NONE;
01368     CLRBITS(this->flags4, WF_WHITE_BORDER_MASK);
01369     this->SetWidgetDisabledState(TBN_PAUSE, _networking && !_network_server); // if not server, disable pause button
01370     this->SetWidgetDisabledState(TBN_FASTFORWARD, _networking); // if networking, disable fast-forward button
01371     PositionMainToolbar(this);
01372     DoZoomInOutWindow(ZOOM_NONE, this);
01373   }
01374 
01375   virtual void OnPaint()
01376   {
01377     /* If spectator, disable all construction buttons
01378      * ie : Build road, rail, ships, airports and landscaping
01379      * Since enabled state is the default, just disable when needed */
01380     this->SetWidgetsDisabledState(_local_company == COMPANY_SPECTATOR, TBN_RAILS, TBN_ROADS, TBN_WATER, TBN_AIR, TBN_LANDSCAPE, WIDGET_LIST_END);
01381     /* disable company list drop downs, if there are no companies */
01382     this->SetWidgetsDisabledState(Company::GetNumItems() == 0, TBN_STATIONS, TBN_FINANCES, TBN_TRAINS, TBN_ROADVEHS, TBN_SHIPS, TBN_AIRCRAFTS, WIDGET_LIST_END);
01383 
01384     this->SetWidgetDisabledState(TBN_RAILS, !CanBuildVehicleInfrastructure(VEH_TRAIN));
01385     this->SetWidgetDisabledState(TBN_AIR, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT));
01386 
01387     this->DrawWidgets();
01388   }
01389 
01390   virtual void OnClick(Point pt, int widget, int click_count)
01391   {
01392     if (_game_mode != GM_MENU && !this->IsWidgetDisabled(widget)) _toolbar_button_procs[widget](this);
01393   }
01394 
01395   virtual void OnDropdownSelect(int widget, int index)
01396   {
01397     CallBackFunction cbf = _menu_clicked_procs[widget](index);
01398     if (cbf != CBF_NONE) this->last_started_action = cbf;
01399   }
01400 
01401   virtual EventState OnKeyPress(uint16 key, uint16 keycode)
01402   {
01403     switch (CheckHotkeyMatch(maintoolbar_hotkeys, keycode, this)) {
01404       case MTHK_PAUSE: ToolbarPauseClick(this); break;
01405       case MTHK_FASTFORWARD: ToolbarFastForwardClick(this); break;
01406       case MTHK_SETTINGS: ShowGameOptions(); break;
01407       case MTHK_SAVEGAME: MenuClickSaveLoad(); break;
01408       case MTHK_LOADGAME: ShowSaveLoadDialog(SLD_LOAD_GAME); break;
01409       case MTHK_SMALLMAP: ShowSmallMap(); break;
01410       case MTHK_TOWNDIRECTORY: ShowTownDirectory(); break;
01411       case MTHK_SUBSIDIES: ShowSubsidiesList(); break;
01412       case MTHK_STATIONS: ShowCompanyStations(_local_company); break;
01413       case MTHK_FINANCES: ShowCompanyFinances(_local_company); break;
01414       case MTHK_COMPANIES: ShowCompany(_local_company); break;
01415       case MTHK_GRAPHS: ShowOperatingProfitGraph(); break;
01416       case MTHK_LEAGUE: ShowCompanyLeagueTable(); break;
01417       case MTHK_INDUSTRIES: ShowBuildIndustryWindow(); break;
01418       case MTHK_TRAIN_LIST: ShowVehicleListWindow(_local_company, VEH_TRAIN); break;
01419       case MTHK_ROADVEH_LIST: ShowVehicleListWindow(_local_company, VEH_ROAD); break;
01420       case MTHK_SHIP_LIST: ShowVehicleListWindow(_local_company, VEH_SHIP); break;
01421       case MTHK_AIRCRAFT_LIST: ShowVehicleListWindow(_local_company, VEH_AIRCRAFT); break;
01422       case MTHK_ZOOM_IN: ToolbarZoomInClick(this); break;
01423       case MTHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
01424       case MTHK_BUILD_RAIL: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype); break;
01425       case MTHK_BUILD_ROAD: ShowBuildRoadToolbar(_last_built_roadtype); break;
01426       case MTHK_BUILD_DOCKS: ShowBuildDocksToolbar(); break;
01427       case MTHK_BUILD_AIRPORT: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break;
01428       case MTHK_BUILD_TREES: ShowBuildTreesToolbar(); break;
01429       case MTHK_MUSIC: ShowMusicWindow(); break;
01430       case MTHK_AI_DEBUG: ShowAIDebugWindow(); break;
01431       case MTHK_SMALL_SCREENSHOT: MenuClickSmallScreenshot(); break;
01432       case MTHK_ZOOMEDIN_SCREENSHOT: MenuClickZoomedInScreenshot(); break;
01433       case MTHK_GIANT_SCREENSHOT: MenuClickWorldScreenshot(); break;
01434       case MTHK_CHEATS: if (!_networking) ShowCheatWindow(); break;
01435       case MTHK_TERRAFORM: ShowTerraformToolbar(); break;
01436       case MTHK_EXTRA_VIEWPORT: ShowExtraViewPortWindowForTileUnderCursor(); break;
01437 #ifdef ENABLE_NETWORK
01438       case MTHK_CLIENT_LIST: if (_networking) ShowClientList(); break;
01439 #endif
01440       case MTHK_SIGN_LIST: ShowSignList(); break;
01441       default: return ES_NOT_HANDLED;
01442     }
01443     return ES_HANDLED;
01444   }
01445 
01446   virtual void OnPlaceObject(Point pt, TileIndex tile)
01447   {
01448     switch (this->last_started_action) {
01449       case CBF_PLACE_SIGN:
01450         PlaceProc_Sign(tile);
01451         break;
01452 
01453       case CBF_PLACE_LANDINFO:
01454         ShowLandInfo(tile);
01455         break;
01456 
01457       default: NOT_REACHED();
01458     }
01459   }
01460 
01461   virtual void OnTick()
01462   {
01463     if (this->IsWidgetLowered(TBN_PAUSE) != !!_pause_mode) {
01464       this->ToggleWidgetLoweredState(TBN_PAUSE);
01465       this->SetWidgetDirty(TBN_PAUSE);
01466     }
01467 
01468     if (this->IsWidgetLowered(TBN_FASTFORWARD) != !!_fast_forward) {
01469       this->ToggleWidgetLoweredState(TBN_FASTFORWARD);
01470       this->SetWidgetDirty(TBN_FASTFORWARD);
01471     }
01472   }
01473 
01474   virtual void OnTimeout()
01475   {
01476     /* We do not want to automatically raise the pause, fast forward and
01477      * switchbar buttons; they have to stay down when pressed etc. */
01478     for (uint i = TBN_SETTINGS; i < TBN_SWITCHBAR; i++) {
01479       if (this->IsWidgetLowered(i)) {
01480         this->RaiseWidget(i);
01481         this->SetWidgetDirty(i);
01482       }
01483     }
01484   }
01485 
01486   virtual void OnInvalidateData(int data)
01487   {
01488     if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, TBN_ZOOMIN, TBN_ZOOMOUT);
01489   }
01490 
01491   static Hotkey<MainToolbarWindow> maintoolbar_hotkeys[];
01492 };
01493 
01494 const uint16 _maintoolbar_pause_keys[] = {WKC_F1, WKC_PAUSE, 0};
01495 const uint16 _maintoolbar_zoomin_keys[] = {WKC_NUM_PLUS, WKC_EQUALS, WKC_SHIFT | WKC_EQUALS, WKC_SHIFT | WKC_F5, 0};
01496 const uint16 _maintoolbar_zoomout_keys[] = {WKC_NUM_MINUS, WKC_MINUS, WKC_SHIFT | WKC_MINUS, WKC_SHIFT | WKC_F6, 0};
01497 const uint16 _maintoolbar_smallmap_keys[] = {WKC_F4, 'M', 0};
01498 
01499 Hotkey<MainToolbarWindow> MainToolbarWindow::maintoolbar_hotkeys[] = {
01500   Hotkey<MainToolbarWindow>(_maintoolbar_pause_keys, "pause", MTHK_PAUSE),
01501   Hotkey<MainToolbarWindow>((uint16)0, "fastforward", MTHK_FASTFORWARD),
01502   Hotkey<MainToolbarWindow>(WKC_F2, "settings", MTHK_SETTINGS),
01503   Hotkey<MainToolbarWindow>(WKC_F3, "saveload", MTHK_SAVEGAME),
01504   Hotkey<MainToolbarWindow>((uint16)0, "load_game", MTHK_LOADGAME),
01505   Hotkey<MainToolbarWindow>(_maintoolbar_smallmap_keys, "smallmap", MTHK_SMALLMAP),
01506   Hotkey<MainToolbarWindow>(WKC_F5, "town_list", MTHK_TOWNDIRECTORY),
01507   Hotkey<MainToolbarWindow>(WKC_F6, "subsidies", MTHK_SUBSIDIES),
01508   Hotkey<MainToolbarWindow>(WKC_F7, "station_list", MTHK_STATIONS),
01509   Hotkey<MainToolbarWindow>(WKC_F8, "finances", MTHK_FINANCES),
01510   Hotkey<MainToolbarWindow>(WKC_F9, "companies", MTHK_COMPANIES),
01511   Hotkey<MainToolbarWindow>(WKC_F10, "graphs", MTHK_GRAPHS),
01512   Hotkey<MainToolbarWindow>(WKC_F11, "league", MTHK_LEAGUE),
01513   Hotkey<MainToolbarWindow>(WKC_F12, "industry_list", MTHK_INDUSTRIES),
01514   Hotkey<MainToolbarWindow>(WKC_SHIFT | WKC_F1, "train_list", MTHK_TRAIN_LIST),
01515   Hotkey<MainToolbarWindow>(WKC_SHIFT | WKC_F2, "roadveh_list", MTHK_ROADVEH_LIST),
01516   Hotkey<MainToolbarWindow>(WKC_SHIFT | WKC_F3, "ship_list", MTHK_SHIP_LIST),
01517   Hotkey<MainToolbarWindow>(WKC_SHIFT | WKC_F4, "aircraft_list", MTHK_AIRCRAFT_LIST),
01518   Hotkey<MainToolbarWindow>(_maintoolbar_zoomin_keys, "zoomin", MTHK_ZOOM_IN),
01519   Hotkey<MainToolbarWindow>(_maintoolbar_zoomout_keys, "zoomout", MTHK_ZOOM_OUT),
01520   Hotkey<MainToolbarWindow>(WKC_SHIFT | WKC_F7, "build_rail", MTHK_BUILD_RAIL),
01521   Hotkey<MainToolbarWindow>(WKC_SHIFT | WKC_F8, "build_road", MTHK_BUILD_ROAD),
01522   Hotkey<MainToolbarWindow>(WKC_SHIFT | WKC_F9, "build_docks", MTHK_BUILD_DOCKS),
01523   Hotkey<MainToolbarWindow>(WKC_SHIFT | WKC_F10, "build_airport", MTHK_BUILD_AIRPORT),
01524   Hotkey<MainToolbarWindow>(WKC_SHIFT | WKC_F11, "build_trees", MTHK_BUILD_TREES),
01525   Hotkey<MainToolbarWindow>(WKC_SHIFT | WKC_F12, "music", MTHK_MUSIC),
01526   Hotkey<MainToolbarWindow>((uint16)0, "ai_debug", MTHK_AI_DEBUG),
01527   Hotkey<MainToolbarWindow>(WKC_CTRL  | 'S', "small_screenshot", MTHK_SMALL_SCREENSHOT),
01528   Hotkey<MainToolbarWindow>(WKC_CTRL  | 'P', "zoomedin_screenshot", MTHK_ZOOMEDIN_SCREENSHOT),
01529   Hotkey<MainToolbarWindow>((uint16)0, "giant_screenshot", MTHK_GIANT_SCREENSHOT),
01530   Hotkey<MainToolbarWindow>(WKC_CTRL | WKC_ALT | 'C', "cheats", MTHK_CHEATS),
01531   Hotkey<MainToolbarWindow>('L', "terraform", MTHK_TERRAFORM),
01532   Hotkey<MainToolbarWindow>('V', "extra_viewport", MTHK_EXTRA_VIEWPORT),
01533 #ifdef ENABLE_NETWORK
01534   Hotkey<MainToolbarWindow>((uint16)0, "client_list", MTHK_CLIENT_LIST),
01535 #endif
01536   Hotkey<MainToolbarWindow>((uint16)0, "sign_list", MTHK_SIGN_LIST),
01537   HOTKEY_LIST_END(MainToolbarWindow)
01538 };
01539 Hotkey<MainToolbarWindow> *_maintoolbar_hotkeys = MainToolbarWindow::maintoolbar_hotkeys;
01540 
01541 static NWidgetBase *MakeMainToolbar(int *biggest_index)
01542 {
01544   static const SpriteID toolbar_button_sprites[] = {
01545     SPR_IMG_PAUSE,           // TBN_PAUSE
01546     SPR_IMG_FASTFORWARD,     // TBN_FASTFORWARD
01547     SPR_IMG_SETTINGS,        // TBN_SETTINGS
01548     SPR_IMG_SAVE,            // TBN_SAVEGAME
01549     SPR_IMG_SMALLMAP,        // TBN_SMALLMAP
01550     SPR_IMG_TOWN,            // TBN_TOWNDIRECTORY
01551     SPR_IMG_SUBSIDIES,       // TBN_SUBSIDIES
01552     SPR_IMG_COMPANY_LIST,    // TBN_STATIONS
01553     SPR_IMG_COMPANY_FINANCE, // TBN_FINANCES
01554     SPR_IMG_COMPANY_GENERAL, // TBN_COMPANIES
01555     SPR_IMG_GRAPHS,          // TBN_GRAPHICS
01556     SPR_IMG_COMPANY_LEAGUE,  // TBN_LEAGUE
01557     SPR_IMG_INDUSTRY,        // TBN_INDUSTRIES
01558     SPR_IMG_TRAINLIST,       // TBN_TRAINS
01559     SPR_IMG_TRUCKLIST,       // TBN_ROADVEHS
01560     SPR_IMG_SHIPLIST,        // TBN_SHIPS
01561     SPR_IMG_AIRPLANESLIST,   // TBN_AIRCRAFTS
01562     SPR_IMG_ZOOMIN,          // TBN_ZOOMIN
01563     SPR_IMG_ZOOMOUT,         // TBN_ZOOMOUT
01564     SPR_IMG_BUILDRAIL,       // TBN_RAILS
01565     SPR_IMG_BUILDROAD,       // TBN_ROADS
01566     SPR_IMG_BUILDWATER,      // TBN_WATER
01567     SPR_IMG_BUILDAIR,        // TBN_AIR
01568     SPR_IMG_LANDSCAPING,     // TBN_LANDSCAPE
01569     SPR_IMG_MUSIC,           // TBN_MUSICSOUND
01570     SPR_IMG_MESSAGES,        // TBN_NEWSREPORT
01571     SPR_IMG_QUERY,           // TBN_HELP
01572     SPR_IMG_SWITCH_TOOLBAR,  // TBN_SWITCHBAR
01573   };
01574 
01575   NWidgetMainToolbarContainer *hor = new NWidgetMainToolbarContainer();
01576   for (uint i = 0; i < TBN_END; i++) {
01577     switch (i) {
01578       case 4: case 8: case 13: case 17: case 19: case 24: hor->Add(new NWidgetSpacer(0, 0)); break;
01579     }
01580     hor->Add(new NWidgetLeaf(i == TBN_SAVEGAME ? WWT_IMGBTN_2 : WWT_IMGBTN, COLOUR_GREY, i, toolbar_button_sprites[i], STR_TOOLBAR_TOOLTIP_PAUSE_GAME + i));
01581   }
01582 
01583   *biggest_index = max<int>(*biggest_index, TBN_SWITCHBAR);
01584   return hor;
01585 }
01586 
01587 static const NWidgetPart _nested_toolbar_normal_widgets[] = {
01588   NWidgetFunction(MakeMainToolbar),
01589 };
01590 
01591 static WindowDesc _toolb_normal_desc(
01592   WDP_MANUAL, 640, 22,
01593   WC_MAIN_TOOLBAR, WC_NONE,
01594   WDF_NO_FOCUS,
01595   _nested_toolbar_normal_widgets, lengthof(_nested_toolbar_normal_widgets)
01596 );
01597 
01598 
01599 /* --- Toolbar handling for the scenario editor */
01600 
01601 static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
01602   ToolbarPauseClick,
01603   ToolbarFastForwardClick,
01604   ToolbarOptionsClick,
01605   ToolbarScenSaveOrLoad,
01606   ToolbarBtn_NULL,
01607   ToolbarScenDatePanel,
01608   ToolbarScenDateBackward,
01609   ToolbarScenDateForward,
01610   ToolbarScenMapTownDir,
01611   ToolbarZoomInClick,
01612   ToolbarZoomOutClick,
01613   ToolbarScenGenLand,
01614   ToolbarScenGenTown,
01615   ToolbarScenGenIndustry,
01616   ToolbarScenBuildRoad,
01617   ToolbarScenBuildDocks,
01618   ToolbarScenPlantTrees,
01619   ToolbarScenPlaceSign,
01620   ToolbarBtn_NULL,
01621   NULL,
01622   NULL,
01623   NULL,
01624   NULL,
01625   NULL,
01626   ToolbarMusicClick,
01627   NULL,
01628   ToolbarHelpClick,
01629   ToolbarSwitchClick,
01630 };
01631 
01632 enum MainToolbarEditorHotkeys {
01633   MTEHK_PAUSE,
01634   MTEHK_FASTFORWARD,
01635   MTEHK_SETTINGS,
01636   MTEHK_SAVEGAME,
01637   MTEHK_GENLAND,
01638   MTEHK_GENTOWN,
01639   MTEHK_GENINDUSTRY,
01640   MTEHK_BUILD_ROAD,
01641   MTEHK_BUILD_DOCKS,
01642   MTEHK_BUILD_TREES,
01643   MTEHK_SIGN,
01644   MTEHK_MUSIC,
01645   MTEHK_LANDINFO,
01646   MTEHK_SMALL_SCREENSHOT,
01647   MTEHK_ZOOMEDIN_SCREENSHOT,
01648   MTEHK_GIANT_SCREENSHOT,
01649   MTEHK_ZOOM_IN,
01650   MTEHK_ZOOM_OUT,
01651   MTEHK_TERRAFORM,
01652   MTEHK_SMALLMAP,
01653   MTEHK_EXTRA_VIEWPORT,
01654 };
01655 
01656 struct ScenarioEditorToolbarWindow : Window {
01657   CallBackFunction last_started_action; 
01658 
01659   ScenarioEditorToolbarWindow(const WindowDesc *desc) : Window()
01660   {
01661     this->InitNested(desc, 0);
01662 
01663     this->last_started_action = CBF_NONE;
01664     CLRBITS(this->flags4, WF_WHITE_BORDER_MASK);
01665     PositionMainToolbar(this);
01666     DoZoomInOutWindow(ZOOM_NONE, this);
01667   }
01668 
01669   virtual void OnPaint()
01670   {
01671     this->SetWidgetDisabledState(TBSE_DATEBACKWARD, _settings_game.game_creation.starting_year <= MIN_YEAR);
01672     this->SetWidgetDisabledState(TBSE_DATEFORWARD, _settings_game.game_creation.starting_year >= MAX_YEAR);
01673 
01674     this->DrawWidgets();
01675   }
01676 
01677   virtual void DrawWidget(const Rect &r, int widget) const
01678   {
01679     switch (widget) {
01680       case TBSE_DATEPANEL:
01681         SetDParam(0, ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
01682         DrawString(r.left, r.right, (this->height - FONT_HEIGHT_NORMAL) / 2, STR_WHITE_DATE_LONG, TC_FROMSTRING, SA_HOR_CENTER);
01683         break;
01684 
01685       case TBSE_SPACERPANEL: {
01686         int height = r.bottom - r.top;
01687         if (height > 2 * FONT_HEIGHT_NORMAL) {
01688           DrawString(r.left, r.right, (height + 1) / 2 - FONT_HEIGHT_NORMAL, STR_SCENEDIT_TOOLBAR_OPENTTD, TC_FROMSTRING, SA_HOR_CENTER);
01689           DrawString(r.left, r.right, (height + 1) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
01690         } else {
01691           DrawString(r.left, r.right, (height - FONT_HEIGHT_NORMAL) / 2, STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR, TC_FROMSTRING, SA_HOR_CENTER);
01692         }
01693         break;
01694       }
01695     }
01696   }
01697 
01698   virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
01699   {
01700     switch (widget) {
01701       case TBSE_SPACERPANEL:
01702         size->width = max(GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_OPENTTD).width, GetStringBoundingBox(STR_SCENEDIT_TOOLBAR_SCENARIO_EDITOR).width) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
01703         break;
01704 
01705       case TBSE_DATEPANEL:
01706         SetDParam(0, ConvertYMDToDate(MAX_YEAR, 0, 1));
01707         *size = GetStringBoundingBox(STR_WHITE_DATE_LONG);
01708         size->height = max(size->height, GetSpriteSize(SPR_IMG_SAVE).height + WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM);
01709         break;
01710     }
01711   }
01712 
01713   virtual void OnClick(Point pt, int widget, int click_count)
01714   {
01715     if (_game_mode == GM_MENU) return;
01716     CallBackFunction cbf = _scen_toolbar_button_procs[widget](this);
01717     if (cbf != CBF_NONE) this->last_started_action = cbf;
01718   }
01719 
01720   virtual void OnDropdownSelect(int widget, int index)
01721   {
01722     /* The map button is in a different location on the scenario
01723      * editor toolbar, so we need to adjust for it. */
01724     if (widget == TBSE_SMALLMAP) widget = TBN_SMALLMAP;
01725     CallBackFunction cbf = _menu_clicked_procs[widget](index);
01726     if (cbf != CBF_NONE) this->last_started_action = cbf;
01727     SndPlayFx(SND_15_BEEP);
01728   }
01729 
01730   virtual EventState OnKeyPress(uint16 key, uint16 keycode)
01731   {
01732     CallBackFunction cbf = CBF_NONE;
01733     switch (CheckHotkeyMatch(scenedit_maintoolbar_hotkeys, keycode, this)) {
01734       case MTEHK_PAUSE:               ToolbarPauseClick(this); break;
01735       case MTEHK_FASTFORWARD:         ToolbarFastForwardClick(this); break;
01736       case MTEHK_SETTINGS:            ShowGameOptions(); break;
01737       case MTEHK_SAVEGAME:            MenuClickSaveLoad(); break;
01738       case MTEHK_GENLAND:             ToolbarScenGenLand(this); break;
01739       case MTEHK_GENTOWN:             ToolbarScenGenTown(this); break;
01740       case MTEHK_GENINDUSTRY:         ToolbarScenGenIndustry(this); break;
01741       case MTEHK_BUILD_ROAD:          ToolbarScenBuildRoad(this); break;
01742       case MTEHK_BUILD_DOCKS:         ToolbarScenBuildDocks(this); break;
01743       case MTEHK_BUILD_TREES:         ToolbarScenPlantTrees(this); break;
01744       case MTEHK_SIGN:                cbf = ToolbarScenPlaceSign(this); break;
01745       case MTEHK_MUSIC:               ShowMusicWindow(); break;
01746       case MTEHK_LANDINFO:            cbf = PlaceLandBlockInfo(); break;
01747       case MTEHK_SMALL_SCREENSHOT:    MenuClickSmallScreenshot(); break;
01748       case MTEHK_ZOOMEDIN_SCREENSHOT: MenuClickZoomedInScreenshot(); break;
01749       case MTEHK_GIANT_SCREENSHOT:    MenuClickWorldScreenshot(); break;
01750       case MTEHK_ZOOM_IN:             ToolbarZoomInClick(this); break;
01751       case MTEHK_ZOOM_OUT:            ToolbarZoomOutClick(this); break;
01752       case MTEHK_TERRAFORM:           ShowEditorTerraformToolbar(); break;
01753       case MTEHK_SMALLMAP:            ShowSmallMap(); break;
01754       case MTEHK_EXTRA_VIEWPORT:      ShowExtraViewPortWindowForTileUnderCursor(); break;
01755       default: return ES_NOT_HANDLED;
01756     }
01757     if (cbf != CBF_NONE) this->last_started_action = cbf;
01758     return ES_HANDLED;
01759   }
01760 
01761   virtual void OnPlaceObject(Point pt, TileIndex tile)
01762   {
01763     switch (this->last_started_action) {
01764       case CBF_PLACE_SIGN:
01765         PlaceProc_Sign(tile);
01766         break;
01767 
01768       case CBF_PLACE_LANDINFO:
01769         ShowLandInfo(tile);
01770         break;
01771 
01772       default: NOT_REACHED();
01773     }
01774   }
01775 
01776   virtual void OnTimeout()
01777   {
01778     this->SetWidgetsLoweredState(false, TBSE_DATEBACKWARD, TBSE_DATEFORWARD, WIDGET_LIST_END);
01779     this->SetWidgetDirty(TBSE_DATEBACKWARD);
01780     this->SetWidgetDirty(TBSE_DATEFORWARD);
01781   }
01782 
01783   virtual void OnTick()
01784   {
01785     if (this->IsWidgetLowered(TBSE_PAUSE) != !!_pause_mode) {
01786       this->ToggleWidgetLoweredState(TBSE_PAUSE);
01787       this->SetDirty();
01788     }
01789 
01790     if (this->IsWidgetLowered(TBSE_FASTFORWARD) != !!_fast_forward) {
01791       this->ToggleWidgetLoweredState(TBSE_FASTFORWARD);
01792       this->SetDirty();
01793     }
01794   }
01795 
01796   virtual void OnInvalidateData(int data)
01797   {
01798     if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, TBSE_ZOOMIN, TBSE_ZOOMOUT);
01799   }
01800 
01801   virtual void OnQueryTextFinished(char *str)
01802   {
01803     /* Was 'cancel' pressed? */
01804     if (str == NULL) return;
01805 
01806     int32 value;
01807     if (!StrEmpty(str)) {
01808       value = atoi(str);
01809     } else {
01810       /* An empty string means revert to the default */
01811       value = DEF_START_YEAR;
01812     }
01813     _settings_game.game_creation.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR);
01814     SetDate(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1), 0);
01815 
01816     this->SetDirty();
01817   }
01818 
01819   static Hotkey<ScenarioEditorToolbarWindow> scenedit_maintoolbar_hotkeys[];
01820 };
01821 
01822 Hotkey<ScenarioEditorToolbarWindow> ScenarioEditorToolbarWindow::scenedit_maintoolbar_hotkeys[] = {
01823   Hotkey<ScenarioEditorToolbarWindow>(_maintoolbar_pause_keys, "pause", MTEHK_PAUSE),
01824   Hotkey<ScenarioEditorToolbarWindow>((uint16)0, "fastforward", MTEHK_FASTFORWARD),
01825   Hotkey<ScenarioEditorToolbarWindow>(WKC_F2, "settings", MTEHK_SETTINGS),
01826   Hotkey<ScenarioEditorToolbarWindow>(WKC_F3, "saveload", MTEHK_SAVEGAME),
01827   Hotkey<ScenarioEditorToolbarWindow>(WKC_F4, "town_list", MTEHK_GENLAND),
01828   Hotkey<ScenarioEditorToolbarWindow>(WKC_F5, "subsidies", MTEHK_GENTOWN),
01829   Hotkey<ScenarioEditorToolbarWindow>(WKC_F6, "station_list", MTEHK_GENINDUSTRY),
01830   Hotkey<ScenarioEditorToolbarWindow>(WKC_F7, "finances", MTEHK_BUILD_ROAD),
01831   Hotkey<ScenarioEditorToolbarWindow>(WKC_F8, "companies", MTEHK_BUILD_DOCKS),
01832   Hotkey<ScenarioEditorToolbarWindow>(WKC_F9, "graphs", MTEHK_BUILD_TREES),
01833   Hotkey<ScenarioEditorToolbarWindow>(WKC_F10, "league", MTEHK_SIGN),
01834   Hotkey<ScenarioEditorToolbarWindow>(WKC_F11, "industry_list", MTEHK_MUSIC),
01835   Hotkey<ScenarioEditorToolbarWindow>(WKC_F12, "train_list", MTEHK_LANDINFO),
01836   Hotkey<ScenarioEditorToolbarWindow>(WKC_CTRL  | 'S', "small_screenshot", MTEHK_SMALL_SCREENSHOT),
01837   Hotkey<ScenarioEditorToolbarWindow>(WKC_CTRL  | 'P', "zoomedin_screenshot", MTEHK_ZOOMEDIN_SCREENSHOT),
01838   Hotkey<ScenarioEditorToolbarWindow>((uint16)0, "giant_screenshot", MTEHK_GIANT_SCREENSHOT),
01839   Hotkey<ScenarioEditorToolbarWindow>(_maintoolbar_zoomin_keys, "zoomin", MTEHK_ZOOM_IN),
01840   Hotkey<ScenarioEditorToolbarWindow>(_maintoolbar_zoomout_keys, "zoomout", MTEHK_ZOOM_OUT),
01841   Hotkey<ScenarioEditorToolbarWindow>('L', "terraform", MTEHK_TERRAFORM),
01842   Hotkey<ScenarioEditorToolbarWindow>('M', "smallmap", MTEHK_SMALLMAP),
01843   Hotkey<ScenarioEditorToolbarWindow>('V', "extra_viewport", MTEHK_EXTRA_VIEWPORT),
01844   HOTKEY_LIST_END(ScenarioEditorToolbarWindow)
01845 };
01846 Hotkey<ScenarioEditorToolbarWindow> *_scenedit_maintoolbar_hotkeys = ScenarioEditorToolbarWindow::scenedit_maintoolbar_hotkeys;
01847 
01848 static const NWidgetPart _nested_toolb_scen_inner_widgets[] = {
01849   NWidget(WWT_IMGBTN, COLOUR_GREY, TBSE_PAUSE), SetDataTip(SPR_IMG_PAUSE, STR_TOOLBAR_TOOLTIP_PAUSE_GAME),
01850   NWidget(WWT_IMGBTN, COLOUR_GREY, TBSE_FASTFORWARD), SetDataTip(SPR_IMG_FASTFORWARD, STR_TOOLBAR_TOOLTIP_FORWARD),
01851   NWidget(WWT_IMGBTN, COLOUR_GREY, TBSE_SETTINGS), SetDataTip(SPR_IMG_SETTINGS, STR_TOOLBAR_TOOLTIP_OPTIONS),
01852   NWidget(WWT_IMGBTN_2, COLOUR_GREY, TBSE_SAVESCENARIO), SetDataTip(SPR_IMG_SAVE, STR_SCENEDIT_TOOLBAR_TOOLTIP_SAVE_SCENARIO_LOAD_SCENARIO),
01853   NWidget(NWID_SPACER),
01854   NWidget(WWT_PANEL, COLOUR_GREY, TBSE_SPACERPANEL), EndContainer(),
01855   NWidget(NWID_SPACER),
01856   NWidget(WWT_PANEL, COLOUR_GREY, TBSE_DATEPANEL_CONTAINER),
01857     NWidget(NWID_HORIZONTAL), SetPIP(3, 2, 3),
01858       NWidget(WWT_IMGBTN, COLOUR_GREY, TBSE_DATEBACKWARD), SetDataTip(SPR_ARROW_DOWN, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_BACKWARD),
01859       NWidget(WWT_EMPTY, COLOUR_GREY, TBSE_DATEPANEL), SetDataTip(STR_NULL, STR_SCENEDIT_TOOLBAR_TOOLTIP_SET_DATE),
01860       NWidget(WWT_IMGBTN, COLOUR_GREY, TBSE_DATEFORWARD), SetDataTip(SPR_ARROW_UP, STR_SCENEDIT_TOOLBAR_TOOLTIP_MOVE_THE_STARTING_DATE_FORWARD),
01861     EndContainer(),
01862   EndContainer(),
01863   NWidget(NWID_SPACER),
01864   NWidget(WWT_IMGBTN, COLOUR_GREY, TBSE_SMALLMAP), SetDataTip(SPR_IMG_SMALLMAP, STR_SCENEDIT_TOOLBAR_TOOLTIP_DISPLAY_MAP_TOWN_DIRECTORY),
01865   NWidget(NWID_SPACER),
01866   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TBSE_ZOOMIN), SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN),
01867   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TBSE_ZOOMOUT), SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT),
01868   NWidget(NWID_SPACER),
01869   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TBSE_LANDGENERATE), SetDataTip(SPR_IMG_LANDSCAPING, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION),
01870   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TBSE_TOWNGENERATE), SetDataTip(SPR_IMG_TOWN, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION),
01871   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TBSE_INDUSTRYGENERATE), SetDataTip(SPR_IMG_INDUSTRY, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION),
01872   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TBSE_BUILDROAD), SetDataTip(SPR_IMG_BUILDROAD, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION),
01873   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TBSE_BUILDDOCKS), SetDataTip(SPR_IMG_BUILDWATER, STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS),
01874   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TBSE_PLANTTREES), SetDataTip(SPR_IMG_PLANTTREES, STR_SCENEDIT_TOOLBAR_PLANT_TREES),
01875   NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TBSE_PLACESIGNS), SetDataTip(SPR_IMG_SIGN, STR_SCENEDIT_TOOLBAR_PLACE_SIGN),
01876   NWidget(NWID_SPACER),
01877   NWidget(WWT_IMGBTN, COLOUR_GREY, TBN_MUSICSOUND), SetDataTip(SPR_IMG_MUSIC, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW),
01878   NWidget(WWT_IMGBTN, COLOUR_GREY, TBN_HELP), SetDataTip(SPR_IMG_QUERY, STR_TOOLBAR_TOOLTIP_LAND_BLOCK_INFORMATION),
01879   NWidget(WWT_IMGBTN, COLOUR_GREY, TBN_SWITCHBAR), SetDataTip(SPR_IMG_SWITCH_TOOLBAR, STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR),
01880 };
01881 
01882 static NWidgetBase *MakeScenarioToolbar(int *biggest_index)
01883 {
01884   return MakeNWidgets(_nested_toolb_scen_inner_widgets, lengthof(_nested_toolb_scen_inner_widgets), biggest_index, new NWidgetScenarioToolbarContainer());
01885 }
01886 
01887 static const NWidgetPart _nested_toolb_scen_widgets[] = {
01888   NWidgetFunction(MakeScenarioToolbar),
01889 };
01890 
01891 static WindowDesc _toolb_scen_desc(
01892   WDP_MANUAL, 640, 22,
01893   WC_MAIN_TOOLBAR, WC_NONE,
01894   WDF_UNCLICK_BUTTONS | WDF_NO_FOCUS,
01895   _nested_toolb_scen_widgets, lengthof(_nested_toolb_scen_widgets)
01896 );
01897 
01898 /* --- Allocating the toolbar --- */
01899 
01900 void AllocateToolbar()
01901 {
01902   /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
01903   _last_built_roadtype = ROADTYPE_ROAD;
01904 
01905   if (_game_mode == GM_EDITOR) {
01906     _preferred_toolbar_size = &_toolb_scen_desc.default_width;
01907     new ScenarioEditorToolbarWindow(&_toolb_scen_desc);
01908   } else {
01909     _preferred_toolbar_size = &_toolb_normal_desc.default_width;
01910     new MainToolbarWindow(&_toolb_normal_desc);
01911   }
01912 }

Generated on Sun Jan 23 01:49:11 2011 for OpenTTD by  doxygen 1.6.1