toolbar_gui.cpp

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

Generated on Fri Dec 31 17:15:40 2010 for OpenTTD by  doxygen 1.6.1