rubidium@9826: /* $Id$ */ rubidium@9826: rubidium@9826: /** @file toolbar_gui.cpp Code related to the (main) toolbar. */ rubidium@9826: rubidium@9826: #include "stdafx.h" rubidium@9826: #include "openttd.h" rubidium@9826: #include "gui.h" rubidium@9826: #include "window_gui.h" rubidium@9826: #include "window_func.h" rubidium@9826: #include "viewport_func.h" rubidium@9826: #include "command_func.h" rubidium@9826: #include "variables.h" rubidium@9826: #include "train.h" rubidium@9826: #include "roadveh.h" rubidium@9826: #include "vehicle_gui.h" rubidium@9826: #include "rail_gui.h" rubidium@9826: #include "road_gui.h" rubidium@9826: #include "date_func.h" rubidium@9826: #include "vehicle_func.h" rubidium@9826: #include "sound_func.h" rubidium@9826: #include "terraform_gui.h" rubidium@9826: #include "transparency.h" rubidium@9826: #include "strings_func.h" rubidium@9826: #include "player_base.h" rubidium@9826: #include "player_func.h" rubidium@9826: #include "player_gui.h" rubidium@9826: #include "settings_type.h" rubidium@9826: #include "toolbar_gui.h" rubidium@9826: #include "vehicle_base.h" rubidium@9826: #include "gfx_func.h" rubidium@10249: #include "cheat_func.h" rubidium@10249: #include "transparency_gui.h" rubidium@10249: #include "screenshot.h" rubidium@10249: #include "newgrf_config.h" rubidium@10249: #include "signs_func.h" rubidium@10249: #include "fios.h" rubidium@10249: #include "functions.h" rubidium@10715: #include "console_gui.h" rubidium@10249: #include "news_gui.h" rubidium@10249: #include "ai/ai_gui.hpp" rubidium@10455: #include "tilehighlight_func.h" rubidium@9826: rubidium@9826: #include "network/network.h" rubidium@10249: #include "network/network_gui.h" rubidium@9826: rubidium@9826: #include "table/strings.h" rubidium@9826: #include "table/sprites.h" rubidium@9826: glx@10645: static void PopupMainToolbMenu(Window *parent, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask = 0, int sel_index = 0, int checked_items = 0); rubidium@11044: static void PopupMainPlayerToolbMenu(Window *parent, int main_button, int gray = 0); glx@10829: static void SplitToolbar(Window *w); rubidium@9826: rubidium@10249: RailType _last_built_railtype; rubidium@10249: RoadType _last_built_roadtype; rubidium@10249: rubidium@11126: /** This enum gathers properties of both toolbars */ rubidium@11126: enum ToolBarProperties { rubidium@11126: TBP_BUTTONWIDTH = 22, ///< width of a button rubidium@11126: TBP_BUTTONHEIGHT = 22, ///< height of a button as well as the toolbars rubidium@11126: TBP_DATEPANELWIDTH = 130, ///< used in scenario editor to calculate width of the toolbar. rubidium@11126: rubidium@11126: TBP_TOOLBAR_MINBUTTON = 14, ///< references both toolbars rubidium@11126: TBP_NORMAL_MAXBUTTON = 19, ///< normal toolbar has this many buttons rubidium@11126: TBP_SCENARIO_MAXBUTTON = 16, ///< while the scenario has these rubidium@11126: }; rubidium@11126: glx@10829: enum ToolbarMode { glx@10829: TB_NORMAL, glx@10829: TB_UPPER, glx@10829: TB_LOWER glx@10829: }; glx@10829: rubidium@11044: enum ToolbarNormalWidgets { rubidium@11044: TBN_PAUSE = 0, rubidium@11044: TBN_FASTFORWARD, rubidium@11044: TBN_SETTINGS, rubidium@11044: TBN_SAVEGAME, rubidium@11044: TBN_SMALLMAP, rubidium@11044: TBN_TOWNDIRECTORY, rubidium@11044: TBN_SUBSIDIES, rubidium@11044: TBN_STATIONS, rubidium@11044: TBN_FINANCES, rubidium@11044: TBN_PLAYERS, rubidium@11044: TBN_GRAPHICS, rubidium@11044: TBN_LEAGUE, rubidium@11044: TBN_INDUSTRIES, rubidium@11044: TBN_VEHICLESTART, ///< trains, actually. So following are trucks, boats and planes rubidium@11044: TBN_TRAINS = TBN_VEHICLESTART, rubidium@11044: TBN_ROADVEHS, rubidium@11044: TBN_SHIPS, rubidium@11044: TBN_AIRCRAFTS, rubidium@11044: TBN_ZOOMIN, rubidium@11044: TBN_ZOOMOUT, rubidium@11044: TBN_RAILS, rubidium@11044: TBN_ROADS, rubidium@11044: TBN_WATER, rubidium@11044: TBN_AIR, rubidium@11044: TBN_LANDSCAPE, rubidium@11044: TBN_MUSICSOUND, rubidium@11044: TBN_NEWSREPORT, rubidium@11044: TBN_HELP, rubidium@11044: TBN_SWITCHBAR, ///< only available when toolbar has been split rubidium@11044: }; rubidium@11044: rubidium@11044: enum ToolbarScenEditorWidgets { rubidium@11044: TBSE_PAUSE = 0, rubidium@11044: TBSE_FASTFORWARD, rubidium@11044: TBSE_SAVESCENARIO = 3, rubidium@11044: TBSE_SPACERPANEL, rubidium@11126: TBSE_DATEPANEL, rubidium@11044: TBSE_DATEBACKWARD, rubidium@11044: TBSE_DATEFORWARD, rubidium@11044: TBSE_SMALLMAP, rubidium@11044: TBSE_ZOOMIN, rubidium@11044: TBSE_ZOOMOUT, rubidium@11044: TBSE_LANDGENERATE, rubidium@11044: TBSE_TOWNGENERATE, rubidium@11044: TBSE_INDUSTRYGENERATE, rubidium@11044: TBSE_BUILDROAD, rubidium@11126: TBSE_BUILDDOCKS, rubidium@11044: TBSE_PLANTTREES, rubidium@11044: TBSE_PLACESIGNS, rubidium@11044: }; rubidium@11044: rubidium@11044: /** The idea of this enum is to allow a separation between widget position rubidium@11044: * and _menu_clicked_procs's entry. By shifting, the "action" id is extracted and rubidium@11126: * kept safe for usage when required. rubidium@11044: * @see ToolbarMenuWindow::OnMouseLoop */ rubidium@11044: enum ScenarioEditorMenuActions { rubidium@11044: SEMA_MAP_CLICK = 17 << 8, rubidium@11044: }; rubidium@11044: glx@10829: static ToolbarMode _toolbar_mode; glx@10829: rubidium@10249: static void SelectSignTool() rubidium@10249: { rubidium@10249: if (_cursor.sprite == SPR_CURSOR_SIGN) { rubidium@10249: ResetObjectToPlace(); rubidium@10249: } else { rubidium@10249: SetObjectToPlace(SPR_CURSOR_SIGN, PAL_NONE, VHM_RECT, WC_MAIN_TOOLBAR, 0); rubidium@10249: _place_proc = PlaceProc_Sign; rubidium@10249: } rubidium@10249: } rubidium@10249: rubidium@10249: /** Returns the position where the toolbar wants the menu to appear. rubidium@9826: * Make sure the dropdown is fully visible within the window. rubidium@9826: * x + w->left because x is supposed to be the offset of the toolbar-button rubidium@9826: * we clicked on and w->left the toolbar window itself. So meaning that rubidium@9826: * the default position is aligned with the left side of the clicked button */ rubidium@10249: static Point GetToolbarDropdownPos(uint16 parent_button, int width, int height) rubidium@9826: { rubidium@10249: const Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0); rubidium@9826: Point pos; rubidium@9826: pos.x = w->widget[GB(parent_button, 0, 8)].left; rubidium@9826: pos.x = w->left + Clamp(pos.x, 0, w->width - width); rubidium@9826: pos.y = w->height; rubidium@9826: rubidium@9826: return pos; rubidium@9826: } rubidium@9826: rubidium@10513: /** glx@10645: * Retrieve the menu item number from a position rubidium@10513: * @param w Window holding the menu items rubidium@10513: * @param x X coordinate of the position rubidium@10513: * @param y Y coordinate of the position rubidium@10513: * @return Index number of the menu item, or \c -1 if no valid selection under position rubidium@10513: */ glx@10645: static int GetMenuItemIndex(const Window *w, int item_count, int disabled_items) rubidium@10513: { rubidium@10513: int x = _cursor.pos.x; rubidium@10513: int y = _cursor.pos.y; rubidium@10513: rubidium@10513: if ((x -= w->left) >= 0 && x < w->width && (y -= w->top + 1) >= 0) { rubidium@10513: y /= 10; rubidium@10513: glx@10645: if (y < item_count && glx@10645: !HasBit(disabled_items, y)) { rubidium@10513: return y; rubidium@10513: } rubidium@10513: } rubidium@10513: return -1; rubidium@10513: } rubidium@10513: rubidium@10249: /* --- Pausing --- */ rubidium@9826: rubidium@9826: static void ToolbarPauseClick(Window *w) rubidium@9826: { rubidium@9826: if (_networking && !_network_server) return; // only server can pause the game rubidium@9826: rubidium@9826: if (DoCommandP(0, _pause_game ? 0 : 1, 0, NULL, CMD_PAUSE)) SndPlayFx(SND_15_BEEP); rubidium@9826: } rubidium@9826: rubidium@10249: /* --- Fast forwarding --- */ rubidium@10249: rubidium@9826: static void ToolbarFastForwardClick(Window *w) rubidium@9826: { rubidium@9826: _fast_forward ^= true; rubidium@9826: SndPlayFx(SND_15_BEEP); rubidium@9826: } rubidium@9826: rubidium@10249: /* --- Options button menu --- */ rubidium@9826: rubidium@11044: enum OptionMenuEntries { rubidium@11044: OME_GAMEOPTIONS = 0, rubidium@11044: OME_DIFFICULTIES, rubidium@11044: OME_PATCHES, rubidium@11044: OME_NEWGRFSETTINGS, rubidium@11044: OME_TRANSPARENCIES, rubidium@11044: OME_SHOW_TOWNNAMES = 6, rubidium@11044: OME_SHOW_STATIONNAMES, rubidium@11044: OME_SHOW_SIGNS, rubidium@11044: OME_SHOW_WAYPOINTNAMES, rubidium@11044: OME_FULL_ANIMATION, rubidium@11044: OME_FULL_DETAILS, rubidium@11044: OME_TRANSPARENTBUILDINGS, rubidium@11044: OME_SHOW_STATIONSIGNS, rubidium@11044: OME_MENUCOUNT, rubidium@11044: }; rubidium@11044: rubidium@9826: static void ToolbarOptionsClick(Window *w) rubidium@9826: { rubidium@9826: uint16 x = 0; rubidium@11044: if (HasBit(_display_opt, DO_SHOW_TOWN_NAMES)) SetBit(x, OME_SHOW_TOWNNAMES); rubidium@11044: if (HasBit(_display_opt, DO_SHOW_STATION_NAMES)) SetBit(x, OME_SHOW_STATIONNAMES); rubidium@11044: if (HasBit(_display_opt, DO_SHOW_SIGNS)) SetBit(x, OME_SHOW_SIGNS); rubidium@11044: if (HasBit(_display_opt, DO_WAYPOINTS)) SetBit(x, OME_SHOW_WAYPOINTNAMES); rubidium@11044: if (HasBit(_display_opt, DO_FULL_ANIMATION)) SetBit(x, OME_FULL_ANIMATION); rubidium@11044: if (HasBit(_display_opt, DO_FULL_DETAIL)) SetBit(x, OME_FULL_DETAILS); rubidium@11044: if (IsTransparencySet(TO_HOUSES)) SetBit(x, OME_TRANSPARENTBUILDINGS); rubidium@11044: if (IsTransparencySet(TO_SIGNS)) SetBit(x, OME_SHOW_STATIONSIGNS); glx@10645: rubidium@11044: PopupMainToolbMenu(w, TBN_SETTINGS, STR_02C4_GAME_OPTIONS, OME_MENUCOUNT, 0, 0, x); rubidium@9826: } rubidium@9826: rubidium@10249: static void MenuClickSettings(int index) rubidium@10249: { rubidium@10249: switch (index) { rubidium@11044: case OME_GAMEOPTIONS: ShowGameOptions(); return; rubidium@11044: case OME_DIFFICULTIES: ShowGameDifficulty(); return; rubidium@11044: case OME_PATCHES: ShowPatchesSelection(); return; rubidium@11044: case OME_NEWGRFSETTINGS: ShowNewGRFSettings(!_networking, true, true, &_grfconfig); return; rubidium@11044: case OME_TRANSPARENCIES: ShowTransparencyToolbar(); break; rubidium@10249: rubidium@11044: case OME_SHOW_TOWNNAMES: ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES); break; rubidium@11044: case OME_SHOW_STATIONNAMES: ToggleBit(_display_opt, DO_SHOW_STATION_NAMES); break; rubidium@11044: case OME_SHOW_SIGNS: ToggleBit(_display_opt, DO_SHOW_SIGNS); break; rubidium@11044: case OME_SHOW_WAYPOINTNAMES: ToggleBit(_display_opt, DO_WAYPOINTS); break; rubidium@11044: case OME_FULL_ANIMATION: ToggleBit(_display_opt, DO_FULL_ANIMATION); break; rubidium@11044: case OME_FULL_DETAILS: ToggleBit(_display_opt, DO_FULL_DETAIL); break; rubidium@11044: case OME_TRANSPARENTBUILDINGS: ToggleTransparency(TO_HOUSES); break; rubidium@11044: case OME_SHOW_STATIONSIGNS: ToggleTransparency(TO_SIGNS); break; rubidium@10249: } rubidium@10249: MarkWholeScreenDirty(); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Saving/loading button menu --- */ rubidium@10249: rubidium@11044: enum SaveLoadEditorMenuEntries { rubidium@11044: SLEME_SAVE_SCENARIO = 0, rubidium@11044: SLEME_LOAD_SCENARIO, rubidium@11044: SLEME_LOAD_HEIGHTMAP, rubidium@11044: SLEME_EXIT_TOINTRO, rubidium@11044: SLEME_EXIT_GAME = 5, rubidium@11044: SLEME_MENUCOUNT, rubidium@11044: }; rubidium@11044: rubidium@11044: enum SaveLoadNormalMenuEntries { rubidium@11044: SLNME_SAVE_GAME = 0, rubidium@11044: SLNME_LOAD_GAME, rubidium@11044: SLNME_EXIT_TOINTRO, rubidium@11044: SLNME_EXIT_GAME, rubidium@11044: SLNME_MENUCOUNT, rubidium@11044: }; rubidium@11044: rubidium@10249: static void ToolbarSaveClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainToolbMenu(w, TBN_SAVEGAME, STR_015C_SAVE_GAME, SLNME_MENUCOUNT); rubidium@10249: } rubidium@9826: rubidium@9826: static void ToolbarScenSaveOrLoad(Window *w) rubidium@9826: { rubidium@11044: PopupMainToolbMenu(w, TBSE_SAVESCENARIO, STR_0292_SAVE_SCENARIO, SLEME_MENUCOUNT); rubidium@9826: } rubidium@9826: rubidium@11126: static void MenuClickSaveLoad(int index = 0) rubidium@10249: { rubidium@10249: if (_game_mode == GM_EDITOR) { rubidium@10249: switch (index) { rubidium@11044: case SLEME_SAVE_SCENARIO: ShowSaveLoadDialog(SLD_SAVE_SCENARIO); break; rubidium@11044: case SLEME_LOAD_SCENARIO: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break; rubidium@11044: case SLEME_LOAD_HEIGHTMAP: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break; rubidium@11044: case SLEME_EXIT_TOINTRO: AskExitToGameMenu(); break; rubidium@11044: case SLEME_EXIT_GAME: HandleExitGameRequest(); break; rubidium@10249: } rubidium@10249: } else { rubidium@10249: switch (index) { rubidium@11044: case SLNME_SAVE_GAME: ShowSaveLoadDialog(SLD_SAVE_GAME); break; rubidium@11044: case SLNME_LOAD_GAME: ShowSaveLoadDialog(SLD_LOAD_GAME); break; rubidium@11044: case SLNME_EXIT_TOINTRO: AskExitToGameMenu(); break; rubidium@11044: case SLNME_EXIT_GAME: HandleExitGameRequest(); break; rubidium@10249: } rubidium@10249: } rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Map button menu --- */ rubidium@10249: rubidium@11044: enum MapMenuEntries { rubidium@11044: MME_SHOW_SMALLMAP = 0, rubidium@11044: MME_SHOW_EXTRAVIEWPORTS, rubidium@11044: MME_SHOW_SIGNLISTS, rubidium@11044: MME_SHOW_TOWNDIRECTORY, ///< This entry is only used in Editor mode rubidium@11126: MME_MENUCOUNT_NORMAL = 3, rubidium@11126: MME_MENUCOUNT_EDITOR = 4, rubidium@11044: }; rubidium@11044: rubidium@10249: static void ToolbarMapClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainToolbMenu(w, TBN_SMALLMAP, STR_02DE_MAP_OF_WORLD, MME_MENUCOUNT_NORMAL); rubidium@11044: } rubidium@11044: rubidium@11044: static void ToolbarScenMapTownDir(Window *w) rubidium@11044: { rubidium@11044: /* Scenario editor button, Use different button to activate. rubidium@11044: * This scheme will allow to have an action (SEMA_MAP_CLICK, which is in fact rubidium@11044: * an entry in _menu_clicked_procs) while at the same time having a start button rubidium@11044: * who is not at the same index as its action rubidium@11044: * @see ToolbarMenuWindow::OnMouseLoop */ rubidium@11044: PopupMainToolbMenu(w, TBSE_SMALLMAP | SEMA_MAP_CLICK, STR_02DE_MAP_OF_WORLD, MME_MENUCOUNT_EDITOR); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickMap(int index) rubidium@10249: { rubidium@10249: switch (index) { rubidium@11044: case MME_SHOW_SMALLMAP: ShowSmallMap(); break; rubidium@11044: case MME_SHOW_EXTRAVIEWPORTS: ShowExtraViewPortWindow(); break; rubidium@11044: case MME_SHOW_SIGNLISTS: ShowSignList(); break; rubidium@11044: case MME_SHOW_TOWNDIRECTORY: if (_game_mode == GM_EDITOR) ShowTownDirectory(); break; rubidium@10249: } rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Town button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarTownClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainToolbMenu(w, TBN_TOWNDIRECTORY, STR_02BB_TOWN_DIRECTORY, 1); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickTown(int index) rubidium@10249: { rubidium@10249: ShowTownDirectory(); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Subidies button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarSubsidiesClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainToolbMenu(w, TBN_SUBSIDIES, STR_02DD_SUBSIDIES, 1); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickSubsidies(int index) rubidium@10249: { rubidium@10249: ShowSubsidiesList(); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Stations button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarStationsClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainPlayerToolbMenu(w, TBN_STATIONS); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickStations(int index) rubidium@10249: { rubidium@10249: ShowPlayerStations((PlayerID)index); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Finances button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarFinancesClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainPlayerToolbMenu(w, TBN_FINANCES); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickFinances(int index) rubidium@10249: { rubidium@10249: ShowPlayerFinances((PlayerID)index); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Company's button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarPlayersClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainPlayerToolbMenu(w, TBN_PLAYERS); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickCompany(int index) rubidium@10249: { rubidium@10249: if (_networking && index == 0) { rubidium@10249: ShowClientList(); rubidium@10249: } else { rubidium@10249: if (_networking) index--; rubidium@10249: ShowPlayerCompany((PlayerID)index); rubidium@10249: } rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Graphs button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarGraphsClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainToolbMenu(w, TBN_GRAPHICS, STR_0154_OPERATING_PROFIT_GRAPH, (_toolbar_mode == TB_NORMAL) ? 6 : 8); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickGraphs(int index) rubidium@10249: { rubidium@10249: switch (index) { rubidium@10249: case 0: ShowOperatingProfitGraph(); break; rubidium@10249: case 1: ShowIncomeGraph(); break; rubidium@10249: case 2: ShowDeliveredCargoGraph(); break; rubidium@10249: case 3: ShowPerformanceHistoryGraph(); break; rubidium@10249: case 4: ShowCompanyValueGraph(); break; rubidium@10249: case 5: ShowCargoPaymentRates(); break; glx@10829: /* functions for combined graphs/league button */ glx@10829: case 6: ShowCompanyLeagueTable(); break; glx@10829: case 7: ShowPerformanceRatingDetail(); break; rubidium@10249: } rubidium@10249: } rubidium@10249: rubidium@10249: /* --- League button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarLeagueClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainToolbMenu(w, TBN_LEAGUE, STR_015A_COMPANY_LEAGUE_TABLE, 2); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickLeague(int index) rubidium@10249: { rubidium@10249: switch (index) { rubidium@10249: case 0: ShowCompanyLeagueTable(); break; rubidium@10249: case 1: ShowPerformanceRatingDetail(); break; rubidium@10249: } rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Industries button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarIndustryClick(Window *w) rubidium@10249: { rubidium@10249: /* Disable build-industry menu if we are a spectator */ rubidium@11044: PopupMainToolbMenu(w, TBN_INDUSTRIES, STR_INDUSTRY_DIR, 2, (_current_player == PLAYER_SPECTATOR) ? 2 : 0); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickIndustry(int index) rubidium@10249: { rubidium@10249: switch (index) { rubidium@10249: case 0: ShowIndustryDirectory(); break; rubidium@10249: case 1: ShowBuildIndustryWindow(); break; rubidium@10249: } rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Trains button menu + 1 helper function for all vehicles. --- */ rubidium@10249: rubidium@10249: static void ToolbarVehicleClick(Window *w, VehicleType veh) rubidium@10249: { rubidium@10249: const Vehicle *v; rubidium@10249: int dis = ~0; rubidium@10249: rubidium@10249: FOR_ALL_VEHICLES(v) { rubidium@10355: if (v->type == veh && v->IsPrimaryVehicle()) ClrBit(dis, v->owner); rubidium@10249: } rubidium@11044: PopupMainPlayerToolbMenu(w, TBN_VEHICLESTART + veh, dis); rubidium@10249: } rubidium@10249: rubidium@10249: rubidium@10249: static void ToolbarTrainClick(Window *w) rubidium@10249: { rubidium@10249: ToolbarVehicleClick(w, VEH_TRAIN); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickShowTrains(int index) rubidium@10249: { rubidium@10249: ShowVehicleListWindow((PlayerID)index, VEH_TRAIN); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Road vehicle button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarRoadClick(Window *w) rubidium@10249: { rubidium@10249: ToolbarVehicleClick(w, VEH_ROAD); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickShowRoad(int index) rubidium@10249: { rubidium@10249: ShowVehicleListWindow((PlayerID)index, VEH_ROAD); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Ship button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarShipClick(Window *w) rubidium@10249: { rubidium@10249: ToolbarVehicleClick(w, VEH_SHIP); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickShowShips(int index) rubidium@10249: { rubidium@10249: ShowVehicleListWindow((PlayerID)index, VEH_SHIP); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Aircraft button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarAirClick(Window *w) rubidium@10249: { rubidium@10249: ToolbarVehicleClick(w, VEH_AIRCRAFT); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickShowAir(int index) rubidium@10249: { rubidium@10249: ShowVehicleListWindow((PlayerID)index, VEH_AIRCRAFT); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Zoom in button --- */ rubidium@10249: rubidium@10249: static void ToolbarZoomInClick(Window *w) rubidium@10249: { rubidium@10249: if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) { rubidium@11126: w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)TBSE_ZOOMIN : (byte)TBN_ZOOMIN); rubidium@10249: SndPlayFx(SND_15_BEEP); rubidium@10249: } rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Zoom out button --- */ rubidium@10249: rubidium@10249: static void ToolbarZoomOutClick(Window *w) rubidium@10249: { rubidium@10249: if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) { rubidium@11126: w->HandleButtonClick((_game_mode == GM_EDITOR) ? (byte)TBSE_ZOOMOUT : (byte)TBN_ZOOMOUT); rubidium@10249: SndPlayFx(SND_15_BEEP); rubidium@10249: } rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Rail button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarBuildRailClick(Window *w) rubidium@10249: { rubidium@10249: const Player *p = GetPlayer(_local_player); rubidium@11044: PopupMainToolbMenu(w, TBN_RAILS, STR_1015_RAILROAD_CONSTRUCTION, RAILTYPE_END, ~p->avail_railtypes, _last_built_railtype); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickBuildRail(int index) rubidium@10249: { rubidium@10249: _last_built_railtype = (RailType)index; rubidium@10249: ShowBuildRailToolbar(_last_built_railtype, -1); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Road button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarBuildRoadClick(Window *w) rubidium@10249: { rubidium@10249: const Player *p = GetPlayer(_local_player); rubidium@10249: /* The standard road button is *always* available */ rubidium@11044: PopupMainToolbMenu(w, TBN_ROADS, STR_180A_ROAD_CONSTRUCTION, 2, ~(p->avail_roadtypes | ROADTYPES_ROAD), _last_built_roadtype); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickBuildRoad(int index) rubidium@10249: { rubidium@10249: _last_built_roadtype = (RoadType)index; rubidium@10249: ShowBuildRoadToolbar(_last_built_roadtype); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Water button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarBuildWaterClick(Window *w) rubidium@10249: { rubidium@11126: PopupMainToolbMenu(w, TBN_WATER, STR_9800_WATERWAYS_CONSTRUCTION, 1); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickBuildWater(int index) rubidium@10249: { rubidium@10249: ShowBuildDocksToolbar(); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Airport button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarBuildAirClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainToolbMenu(w, TBN_AIR, STR_A01D_AIRPORT_CONSTRUCTION, 1); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickBuildAir(int index) rubidium@10249: { rubidium@10249: ShowBuildAirToolbar(); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Forest button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarForestClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainToolbMenu(w, TBN_LANDSCAPE, STR_LANDSCAPING, 3); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickForest(int index) rubidium@10249: { rubidium@10249: switch (index) { rubidium@10249: case 0: ShowTerraformToolbar(); break; rubidium@10249: case 1: ShowBuildTreesToolbar(); break; rubidium@10249: case 2: SelectSignTool(); break; rubidium@10249: } rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Music button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarMusicClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainToolbMenu(w, TBN_MUSICSOUND, STR_01D3_SOUND_MUSIC, 1); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickMusicWindow(int index) rubidium@10249: { rubidium@10249: ShowMusicWindow(); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Newspaper button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarNewspaperClick(Window *w) rubidium@10249: { rubidium@11044: PopupMainToolbMenu(w, TBN_NEWSREPORT, STR_0200_LAST_MESSAGE_NEWS_REPORT, 3); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickNewspaper(int index) rubidium@10249: { rubidium@10249: switch (index) { rubidium@10249: case 0: ShowLastNewsMessage(); break; rubidium@10249: case 1: ShowMessageOptions(); break; rubidium@10249: case 2: ShowMessageHistory(); break; rubidium@10249: } rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Help button menu --- */ rubidium@10249: rubidium@10249: static void ToolbarHelpClick(Window *w) rubidium@10249: { truebrain@11068: PopupMainToolbMenu(w, TBN_HELP, STR_02D5_LAND_BLOCK_INFO, 7); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickSmallScreenshot() rubidium@10249: { rubidium@10249: SetScreenshotType(SC_VIEWPORT); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickWorldScreenshot() rubidium@10249: { rubidium@10249: SetScreenshotType(SC_WORLD); rubidium@10249: } rubidium@10249: rubidium@10249: static void MenuClickHelp(int index) rubidium@10249: { rubidium@10249: switch (index) { rubidium@10249: case 0: PlaceLandBlockInfo(); break; rubidium@10249: case 2: IConsoleSwitch(); break; rubidium@10249: case 3: ShowAIDebugWindow(); break; rubidium@10249: case 4: MenuClickSmallScreenshot(); break; rubidium@10249: case 5: MenuClickWorldScreenshot(); break; rubidium@10249: case 6: ShowAboutWindow(); break; rubidium@10249: } rubidium@10249: } rubidium@10249: glx@10829: /* --- Switch toolbar button --- */ glx@10829: glx@10829: static void ToolbarSwitchClick(Window *w) glx@10829: { glx@10829: if (_toolbar_mode != TB_LOWER) { glx@10829: _toolbar_mode = TB_LOWER; glx@10829: } else { glx@10829: _toolbar_mode = TB_UPPER; glx@10829: } glx@10829: glx@10829: SplitToolbar(w); rubidium@11044: w->HandleButtonClick(TBN_SWITCHBAR); glx@10829: SetWindowDirty(w); glx@10829: SndPlayFx(SND_15_BEEP); glx@10829: } glx@10829: rubidium@10249: /* --- Scenario editor specific handlers. */ rubidium@10249: rubidium@9826: static void ToolbarScenDateBackward(Window *w) rubidium@9826: { rubidium@9826: /* don't allow too fast scrolling */ rubidium@9826: if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) { rubidium@11044: w->HandleButtonClick(TBSE_DATEBACKWARD); rubidium@10455: w->SetDirty(); rubidium@9826: rubidium@10715: _settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year - 1, MIN_YEAR, MAX_YEAR); rubidium@10715: SetDate(ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); rubidium@9826: } rubidium@9826: _left_button_clicked = false; rubidium@9826: } rubidium@9826: rubidium@9826: static void ToolbarScenDateForward(Window *w) rubidium@9826: { rubidium@9826: /* don't allow too fast scrolling */ rubidium@9826: if ((w->flags4 & WF_TIMEOUT_MASK) <= 2 << WF_TIMEOUT_SHL) { rubidium@11044: w->HandleButtonClick(TBSE_DATEFORWARD); rubidium@10455: w->SetDirty(); rubidium@9826: rubidium@10715: _settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year + 1, MIN_YEAR, MAX_YEAR); rubidium@10715: SetDate(ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); rubidium@9826: } rubidium@9826: _left_button_clicked = false; rubidium@9826: } rubidium@9826: rubidium@9826: static void ToolbarScenGenLand(Window *w) rubidium@9826: { rubidium@11044: w->HandleButtonClick(TBSE_LANDGENERATE); rubidium@9826: SndPlayFx(SND_15_BEEP); rubidium@9826: rubidium@9826: ShowEditorTerraformToolbar(); rubidium@9826: } rubidium@9826: rubidium@9826: rubidium@9826: static void ToolbarScenGenTown(Window *w) rubidium@9826: { rubidium@11044: w->HandleButtonClick(TBSE_TOWNGENERATE); rubidium@9826: SndPlayFx(SND_15_BEEP); rubidium@9826: ShowBuildTownWindow(); rubidium@9826: } rubidium@9826: rubidium@9826: static void ToolbarScenGenIndustry(Window *w) rubidium@9826: { rubidium@11044: w->HandleButtonClick(TBSE_INDUSTRYGENERATE); rubidium@9826: SndPlayFx(SND_15_BEEP); rubidium@9826: ShowBuildIndustryWindow(); rubidium@9826: } rubidium@9826: rubidium@9826: static void ToolbarScenBuildRoad(Window *w) rubidium@9826: { rubidium@11044: w->HandleButtonClick(TBSE_BUILDROAD); rubidium@9826: SndPlayFx(SND_15_BEEP); rubidium@9826: ShowBuildRoadScenToolbar(); rubidium@9826: } rubidium@9826: rubidium@11126: static void ToolbarScenBuildDocks(Window *w) rubidium@11126: { rubidium@11126: w->HandleButtonClick(TBSE_BUILDDOCKS); rubidium@11126: SndPlayFx(SND_15_BEEP); rubidium@11126: ShowBuildDocksScenToolbar(); rubidium@11126: } rubidium@11126: rubidium@9826: static void ToolbarScenPlantTrees(Window *w) rubidium@9826: { rubidium@11044: w->HandleButtonClick(TBSE_PLANTTREES); rubidium@9826: SndPlayFx(SND_15_BEEP); glx@10645: ShowBuildTreesToolbar(); rubidium@9826: } rubidium@9826: rubidium@9826: static void ToolbarScenPlaceSign(Window *w) rubidium@9826: { rubidium@11044: w->HandleButtonClick(TBSE_PLACESIGNS); rubidium@9826: SndPlayFx(SND_15_BEEP); rubidium@9826: SelectSignTool(); rubidium@9826: } rubidium@9826: rubidium@9826: static void ToolbarBtn_NULL(Window *w) rubidium@9826: { rubidium@9826: } rubidium@9826: glx@10829: /* --- Resizing the toolbar */ glx@10829: glx@10829: static void ResizeToolbar(Window *w) glx@10829: { glx@10829: /* There are 27 buttons plus some spacings if the space allows it */ glx@10829: uint button_width; glx@10829: uint spacing; rubidium@11044: uint widgetcount = w->widget_count - 1; rubidium@11044: rubidium@11126: if (w->width >= (int)widgetcount * TBP_BUTTONWIDTH) { rubidium@11126: button_width = TBP_BUTTONWIDTH; rubidium@11044: spacing = w->width - (widgetcount * button_width); glx@10829: } else { rubidium@11044: button_width = w->width / widgetcount; glx@10829: spacing = 0; glx@10829: } rubidium@11044: rubidium@11126: static const uint extra_spacing_at[] = { 4, 8, 13, 17, 19, 24, 0 }; rubidium@11044: uint i = 0; rubidium@11044: for (uint x = 0, j = 0; i < widgetcount; i++) { glx@10829: if (extra_spacing_at[j] == i) { glx@10829: j++; glx@10829: uint add = spacing / (lengthof(extra_spacing_at) - j); glx@10829: spacing -= add; glx@10829: x += add; glx@10829: } glx@10829: glx@10829: w->widget[i].type = WWT_IMGBTN; glx@10829: w->widget[i].left = x; rubidium@11044: x += (spacing != 0) ? button_width : (w->width - x) / (widgetcount - i); glx@10829: w->widget[i].right = x - 1; glx@10829: } glx@10829: rubidium@11044: w->widget[i].type = WWT_EMPTY; // i now points to the last item glx@10829: _toolbar_mode = TB_NORMAL; glx@10829: } glx@10829: glx@10829: /* --- Split the toolbar */ glx@10829: glx@10829: static void SplitToolbar(Window *w) glx@10829: { glx@10829: static const byte arrange14[] = { glx@10829: 0, 1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 27, glx@10829: 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 24, 25, 26, 27, glx@10829: }; glx@10829: static const byte arrange15[] = { glx@10829: 0, 1, 4, 13, 14, 15, 16, 19, 20, 21, 22, 23, 17, 18, 27, glx@10829: 0, 2, 4, 3, 5, 6, 7, 8, 9, 10, 12, 24, 25, 26, 27, glx@10829: }; glx@10829: static const byte arrange16[] = { glx@10829: 0, 1, 2, 4, 13, 14, 15, 16, 19, 20, 21, 22, 23, 17, 18, 27, glx@10829: 0, 1, 3, 5, 6, 7, 8, 9, 10, 12, 24, 25, 26, 17, 18, 27, glx@10829: }; glx@10829: static const byte arrange17[] = { glx@10829: 0, 1, 2, 4, 6, 13, 14, 15, 16, 19, 20, 21, 22, 23, 17, 18, 27, glx@10829: 0, 1, 3, 4, 6, 5, 7, 8, 9, 10, 12, 24, 25, 26, 17, 18, 27, glx@10829: }; glx@10829: static const byte arrange18[] = { glx@10829: 0, 1, 2, 4, 5, 6, 7, 8, 9, 12, 19, 20, 21, 22, 23, 17, 18, 27, glx@10829: 0, 1, 3, 4, 5, 6, 7, 10, 13, 14, 15, 16, 24, 25, 26, 17, 18, 27, glx@10829: }; glx@10829: static const byte arrange19[] = { glx@10829: 0, 1, 2, 4, 5, 6, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 17, 18, 27, glx@10829: 0, 1, 3, 4, 7, 8, 9, 10, 12, 25, 19, 20, 21, 22, 23, 26, 17, 18, 27, glx@10829: }; glx@10829: glx@10829: static const byte *arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19 }; glx@10829: rubidium@11126: uint max_icons = max(TBP_TOOLBAR_MINBUTTON, (ToolBarProperties)((w->width + TBP_BUTTONWIDTH / 2) / TBP_BUTTONWIDTH)); glx@10829: rubidium@11126: assert(max_icons >= TBP_TOOLBAR_MINBUTTON && max_icons <= TBP_NORMAL_MAXBUTTON); glx@10829: glx@10829: /* first hide all icons */ rubidium@11044: for (uint i = 0; i < w->widget_count - 1; i++) { glx@10829: w->widget[i].type = WWT_EMPTY; glx@10829: } glx@10829: glx@10829: /* now activate them all on their proper positions */ rubidium@11126: for (uint i = 0, x = 0, n = max_icons - TBP_TOOLBAR_MINBUTTON; i < max_icons; i++) { glx@10829: uint icon = arrangements[n][i + ((_toolbar_mode == TB_LOWER) ? max_icons : 0)]; glx@10829: w->widget[icon].type = WWT_IMGBTN; glx@10829: w->widget[icon].left = x; glx@10829: x += (w->width - x) / (max_icons - i); glx@10829: w->widget[icon].right = x - 1; glx@10829: } glx@10829: } rubidium@9826: rubidium@10249: /* --- Toolbar handling for the 'normal' case */ rubidium@10249: rubidium@9826: typedef void ToolbarButtonProc(Window *w); rubidium@9826: rubidium@9826: static ToolbarButtonProc * const _toolbar_button_procs[] = { rubidium@9826: ToolbarPauseClick, rubidium@9826: ToolbarFastForwardClick, rubidium@9826: ToolbarOptionsClick, rubidium@9826: ToolbarSaveClick, rubidium@9826: ToolbarMapClick, rubidium@9826: ToolbarTownClick, rubidium@9826: ToolbarSubsidiesClick, rubidium@9826: ToolbarStationsClick, rubidium@10249: ToolbarFinancesClick, rubidium@9826: ToolbarPlayersClick, rubidium@9826: ToolbarGraphsClick, rubidium@9826: ToolbarLeagueClick, rubidium@9826: ToolbarIndustryClick, rubidium@9826: ToolbarTrainClick, rubidium@9826: ToolbarRoadClick, rubidium@9826: ToolbarShipClick, rubidium@9826: ToolbarAirClick, rubidium@9826: ToolbarZoomInClick, rubidium@9826: ToolbarZoomOutClick, rubidium@9826: ToolbarBuildRailClick, rubidium@9826: ToolbarBuildRoadClick, rubidium@9826: ToolbarBuildWaterClick, rubidium@9826: ToolbarBuildAirClick, rubidium@9826: ToolbarForestClick, rubidium@9826: ToolbarMusicClick, rubidium@9826: ToolbarNewspaperClick, rubidium@9826: ToolbarHelpClick, glx@10829: ToolbarSwitchClick, rubidium@9826: }; rubidium@9826: glx@10645: struct MainToolbarWindow : Window { glx@10645: MainToolbarWindow(const WindowDesc *desc) : Window(desc) glx@10645: { rubidium@11044: this->SetWidgetDisabledState(TBN_PAUSE, _networking && !_network_server); // if not server, disable pause button rubidium@11044: this->SetWidgetDisabledState(TBN_FASTFORWARD, _networking); // if networking, disable fast-forward button rubidium@9826: glx@10645: CLRBITS(this->flags4, WF_WHITE_BORDER_MASK); rubidium@9826: glx@10645: this->FindWindowPlacementAndResize(desc); glx@10645: PositionMainToolbar(this); glx@10645: DoZoomInOutWindow(ZOOM_NONE, this); glx@10645: } rubidium@9826: glx@10645: virtual void OnPaint() glx@10645: { glx@10645: /* Draw brown-red toolbar bg. */ glx@10645: GfxFillRect(0, 0, this->width - 1, this->height - 1, 0xB2); rubidium@11126: GfxFillRect(0, 0, this->width - 1, this->height - 1, 0xB4, FILLRECT_CHECKER); rubidium@9826: glx@10645: /* If spectator, disable all construction buttons glx@10645: * ie : Build road, rail, ships, airports and landscaping glx@10645: * Since enabled state is the default, just disable when needed */ rubidium@11044: this->SetWidgetsDisabledState(_current_player == PLAYER_SPECTATOR, TBN_RAILS, TBN_ROADS, TBN_WATER, TBN_AIR, TBN_LANDSCAPE, WIDGET_LIST_END); glx@10645: /* disable company list drop downs, if there are no companies */ rubidium@11044: this->SetWidgetsDisabledState(ActivePlayerCount() == TBN_PAUSE, TBN_STATIONS, TBN_FINANCES, TBN_TRAINS, TBN_ROADVEHS, TBN_SHIPS, TBN_AIRCRAFTS, WIDGET_LIST_END); glx@10645: rubidium@11044: this->SetWidgetDisabledState(TBN_RAILS, !CanBuildVehicleInfrastructure(VEH_TRAIN)); rubidium@11044: this->SetWidgetDisabledState(TBN_AIR, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT)); glx@10645: glx@10645: this->DrawWidgets(); glx@10645: } glx@10645: glx@10645: virtual void OnClick(Point pt, int widget) glx@10645: { glx@10645: if (_game_mode != GM_MENU && !this->IsWidgetDisabled(widget)) _toolbar_button_procs[widget](this); glx@10645: } glx@10645: glx@10645: virtual EventState OnKeyPress(uint16 key, uint16 keycode) glx@10645: { glx@10645: switch (keycode) { glx@10645: case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(this); break; glx@10645: case WKC_F2: ShowGameOptions(); break; rubidium@11126: case WKC_F3: MenuClickSaveLoad(); break; glx@10645: case WKC_F4: ShowSmallMap(); break; glx@10645: case WKC_F5: ShowTownDirectory(); break; glx@10645: case WKC_F6: ShowSubsidiesList(); break; glx@10645: case WKC_F7: ShowPlayerStations(_local_player); break; glx@10645: case WKC_F8: ShowPlayerFinances(_local_player); break; glx@10645: case WKC_F9: ShowPlayerCompany(_local_player); break; glx@10645: case WKC_F10: ShowOperatingProfitGraph(); break; glx@10645: case WKC_F11: ShowCompanyLeagueTable(); break; glx@10645: case WKC_F12: ShowBuildIndustryWindow(); break; glx@10645: case WKC_SHIFT | WKC_F1: ShowVehicleListWindow(_local_player, VEH_TRAIN); break; glx@10645: case WKC_SHIFT | WKC_F2: ShowVehicleListWindow(_local_player, VEH_ROAD); break; glx@10645: case WKC_SHIFT | WKC_F3: ShowVehicleListWindow(_local_player, VEH_SHIP); break; glx@10645: case WKC_SHIFT | WKC_F4: ShowVehicleListWindow(_local_player, VEH_AIRCRAFT); break; glx@10645: case WKC_NUM_PLUS: // Fall through glx@10645: case WKC_EQUALS: // Fall through glx@10645: case WKC_SHIFT | WKC_EQUALS: // Fall through glx@10645: case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(this); break; glx@10645: case WKC_NUM_MINUS: // Fall through glx@10645: case WKC_MINUS: // Fall through glx@10645: case WKC_SHIFT | WKC_MINUS: // Fall through glx@10645: case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(this); break; glx@10645: case WKC_SHIFT | WKC_F7: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, -1); break; glx@10645: case WKC_SHIFT | WKC_F8: ShowBuildRoadToolbar(_last_built_roadtype); break; glx@10645: case WKC_SHIFT | WKC_F9: ShowBuildDocksToolbar(); break; glx@10645: case WKC_SHIFT | WKC_F10: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break; glx@10645: case WKC_SHIFT | WKC_F11: ShowBuildTreesToolbar(); break; glx@10645: case WKC_SHIFT | WKC_F12: ShowMusicWindow(); break; glx@10645: case WKC_CTRL | 'S': MenuClickSmallScreenshot(); break; glx@10645: case WKC_CTRL | 'G': MenuClickWorldScreenshot(); break; glx@10645: case WKC_CTRL | WKC_ALT | 'C': if (!_networking) ShowCheatWindow(); break; glx@10645: case 'A': if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, 4); break; // Invoke Autorail glx@10645: case 'L': ShowTerraformToolbar(); break; glx@10645: case 'M': ShowSmallMap(); break; glx@10645: case 'V': ShowExtraViewPortWindow(); break; glx@10645: default: return ES_NOT_HANDLED; glx@10645: } glx@10645: return ES_HANDLED; glx@10645: } glx@10645: glx@10645: virtual void OnPlaceObject(Point pt, TileIndex tile) glx@10645: { glx@10645: _place_proc(tile); glx@10645: } glx@10645: glx@10645: virtual void OnTick() glx@10645: { rubidium@11044: if (this->IsWidgetLowered(TBN_PAUSE) != !!_pause_game) { rubidium@11044: this->ToggleWidgetLoweredState(TBN_PAUSE); rubidium@11044: this->InvalidateWidget(TBN_PAUSE); glx@10645: } glx@10645: rubidium@11044: if (this->IsWidgetLowered(TBN_FASTFORWARD) != !!_fast_forward) { rubidium@11044: this->ToggleWidgetLoweredState(TBN_FASTFORWARD); rubidium@11044: this->InvalidateWidget(TBN_FASTFORWARD); glx@10645: } glx@10645: } glx@10645: glx@10645: virtual void OnResize(Point new_size, Point delta) glx@10645: { rubidium@11126: if (this->width <= TBP_NORMAL_MAXBUTTON * TBP_BUTTONWIDTH) { glx@10829: SplitToolbar(this); glx@10645: } else { glx@10829: ResizeToolbar(this); glx@10645: } glx@10645: } rubidium@9826: glx@10645: virtual void OnTimeout() glx@10645: { rubidium@11044: for (uint i = TBN_SETTINGS; i < this->widget_count - 1; i++) { glx@10645: if (this->IsWidgetLowered(i)) { glx@10645: this->RaiseWidget(i); glx@10645: this->InvalidateWidget(i); rubidium@9826: } glx@10645: } glx@10645: } rubidium@9826: glx@10645: virtual void OnInvalidateData(int data) glx@10645: { rubidium@11044: if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, TBN_ZOOMIN, TBN_ZOOMOUT); rubidium@9826: } glx@10645: }; rubidium@9826: rubidium@9826: static const Widget _toolb_normal_widgets[] = { rubidium@11126: { WWT_IMGBTN, RESIZE_LEFT, 14, 0, 0, 0, 21, SPR_IMG_PAUSE, STR_0171_PAUSE_GAME}, // TBN_PAUSE rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_FASTFORWARD, STR_FAST_FORWARD}, // TBN_FASTFORWARD rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SETTINGS, STR_0187_OPTIONS}, // TBN_SETTINGS rubidium@11126: { WWT_IMGBTN_2, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SAVE, STR_0172_SAVE_GAME_ABANDON_GAME}, // TBN_SAVEGAME rubidium@9826: rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SMALLMAP, STR_0174_DISPLAY_MAP}, // TBN_SMALLMAP rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_TOWN, STR_0176_DISPLAY_TOWN_DIRECTORY}, // TBN_TOWNDIRECTORY rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SUBSIDIES, STR_02DC_DISPLAY_SUBSIDIES}, // TBN_SUBSIDIES rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_COMPANY_LIST, STR_0173_DISPLAY_LIST_OF_COMPANY}, // TBN_STATIONS rubidium@9826: rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_COMPANY_FINANCE, STR_0177_DISPLAY_COMPANY_FINANCES}, // TBN_FINANCES rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_COMPANY_GENERAL, STR_0178_DISPLAY_COMPANY_GENERAL}, // TBN_PLAYERS rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_GRAPHS, STR_0179_DISPLAY_GRAPHS}, // TBN_GRAPHICS rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_COMPANY_LEAGUE, STR_017A_DISPLAY_COMPANY_LEAGUE}, // TBN_LEAGUE rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_INDUSTRY, STR_0312_FUND_CONSTRUCTION_OF_NEW}, // TBN_INDUSTRIES rubidium@9826: rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_TRAINLIST, STR_017B_DISPLAY_LIST_OF_COMPANY}, // TBN_TRAINS rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_TRUCKLIST, STR_017C_DISPLAY_LIST_OF_COMPANY}, // TBN_ROADVEHS rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SHIPLIST, STR_017D_DISPLAY_LIST_OF_COMPANY}, // TBN_SHIPS rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_AIRPLANESLIST, STR_017E_DISPLAY_LIST_OF_COMPANY}, // TBN_AIRCRAFTS rubidium@11126: rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_ZOOMIN, STR_017F_ZOOM_THE_VIEW_IN}, // TBN_ZOOMIN rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_ZOOMOUT, STR_0180_ZOOM_THE_VIEW_OUT}, // TBN_ZOOMOUT rubidium@11126: rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_BUILDRAIL, STR_0181_BUILD_RAILROAD_TRACK}, // TBN_RAILS rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_BUILDROAD, STR_0182_BUILD_ROADS}, // TBN_ROADS rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_BUILDWATER, STR_0183_BUILD_SHIP_DOCKS}, // TBN_WATER rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_BUILDAIR, STR_0184_BUILD_AIRPORTS}, // TBN_AIR rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP}, // TBN_LANDSCAPE tree icon is SPR_IMG_PLANTTREES rubidium@11126: rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_MUSIC, STR_01D4_SHOW_SOUND_MUSIC_WINDOW}, // TBN_MUSICSOUND rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_MESSAGES, STR_0203_SHOW_LAST_MESSAGE_NEWS}, // TBN_NEWSREPORT rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_QUERY, STR_0186_LAND_BLOCK_INFORMATION}, // TBN_HELP rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_SWITCH_TOOLBAR, STR_EMPTY}, // TBN_SWITCHBAR rubidium@9826: { WIDGETS_END}, rubidium@9826: }; rubidium@9826: rubidium@9826: static const WindowDesc _toolb_normal_desc = { rubidium@11126: 0, 0, 0, TBP_BUTTONHEIGHT, 640, TBP_BUTTONHEIGHT, rubidium@9826: WC_MAIN_TOOLBAR, WC_NONE, rubidium@9826: WDF_STD_TOOLTIPS | WDF_DEF_WIDGET, rubidium@9826: _toolb_normal_widgets, rubidium@9826: }; rubidium@9826: rubidium@9826: rubidium@10249: /* --- Toolbar handling for the scenario editor */ rubidium@10249: rubidium@9826: static ToolbarButtonProc * const _scen_toolbar_button_procs[] = { rubidium@9826: ToolbarPauseClick, rubidium@9826: ToolbarFastForwardClick, rubidium@9826: ToolbarOptionsClick, rubidium@9826: ToolbarScenSaveOrLoad, rubidium@9826: ToolbarBtn_NULL, rubidium@9826: ToolbarBtn_NULL, rubidium@9826: ToolbarScenDateBackward, rubidium@9826: ToolbarScenDateForward, rubidium@9826: ToolbarScenMapTownDir, rubidium@11126: ToolbarZoomInClick, rubidium@11126: ToolbarZoomOutClick, rubidium@9826: ToolbarScenGenLand, rubidium@9826: ToolbarScenGenTown, rubidium@9826: ToolbarScenGenIndustry, rubidium@9826: ToolbarScenBuildRoad, rubidium@11126: ToolbarScenBuildDocks, rubidium@9826: ToolbarScenPlantTrees, rubidium@9826: ToolbarScenPlaceSign, rubidium@9826: NULL, rubidium@9826: NULL, rubidium@9826: NULL, rubidium@9826: NULL, rubidium@9826: NULL, rubidium@9826: NULL, rubidium@9826: ToolbarMusicClick, rubidium@9826: NULL, rubidium@9826: ToolbarHelpClick, rubidium@9826: }; rubidium@9826: glx@10645: struct ScenarioEditorToolbarWindow : Window { glx@10955: public: glx@10645: ScenarioEditorToolbarWindow(const WindowDesc *desc) : Window(desc) glx@10645: { glx@10645: CLRBITS(this->flags4, WF_WHITE_BORDER_MASK); rubidium@9826: glx@10645: this->FindWindowPlacementAndResize(desc); glx@10645: PositionMainToolbar(this); glx@10645: DoZoomInOutWindow(ZOOM_NONE, this); glx@10645: } rubidium@9826: glx@10645: virtual void OnPaint() glx@10645: { glx@10955: this->SetWidgetDisabledState(TBSE_DATEBACKWARD, _settings_newgame.game_creation.starting_year <= MIN_YEAR); glx@10955: this->SetWidgetDisabledState(TBSE_DATEFORWARD, _settings_newgame.game_creation.starting_year >= MAX_YEAR); rubidium@9826: glx@10645: /* Draw brown-red toolbar bg. */ glx@10645: GfxFillRect(0, 0, this->width - 1, this->height - 1, 0xB2); rubidium@11126: GfxFillRect(0, 0, this->width - 1, this->height - 1, 0xB4, FILLRECT_CHECKER); glx@10645: glx@10645: this->DrawWidgets(); glx@10645: rubidium@10715: SetDParam(0, ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); glx@10955: DrawStringCenteredTruncated(this->widget[TBSE_DATEBACKWARD].right, this->widget[TBSE_DATEFORWARD].left, 6, STR_00AF, TC_FROMSTRING); glx@10645: glx@10645: /* We hide this panel when the toolbar space gets too small */ glx@10955: const Widget *panel = &this->widget[TBSE_SPACERPANEL]; glx@10955: if (panel->left != panel->right) { glx@10955: DrawStringCenteredTruncated(panel->left + 1, panel->right - 1, 1, STR_0221_OPENTTD, TC_FROMSTRING); glx@10955: DrawStringCenteredTruncated(panel->left + 1, panel->right - 1, 11, STR_0222_SCENARIO_EDITOR, TC_FROMSTRING); glx@10645: } glx@10645: } glx@10645: glx@10645: virtual void OnClick(Point pt, int widget) glx@10645: { glx@10645: if (_game_mode == GM_MENU) return; glx@10645: _scen_toolbar_button_procs[widget](this); glx@10645: } glx@10645: glx@10645: virtual EventState OnKeyPress(uint16 key, uint16 keycode) glx@10645: { glx@10645: switch (keycode) { glx@10645: case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(this); break; glx@10645: case WKC_F2: ShowGameOptions(); break; rubidium@11126: case WKC_F3: MenuClickSaveLoad(); break; glx@10645: case WKC_F4: ToolbarScenGenLand(this); break; glx@10645: case WKC_F5: ToolbarScenGenTown(this); break; glx@10645: case WKC_F6: ToolbarScenGenIndustry(this); break; glx@10645: case WKC_F7: ToolbarScenBuildRoad(this); break; rubidium@11126: case WKC_F8: ToolbarScenBuildDocks(this); break; rubidium@11126: case WKC_F9: ToolbarScenPlantTrees(this); break; rubidium@11126: case WKC_F10: ToolbarScenPlaceSign(this); break; rubidium@11126: case WKC_F11: ShowMusicWindow(); break; rubidium@11126: case WKC_F12: PlaceLandBlockInfo(); break; glx@10645: case WKC_CTRL | 'S': MenuClickSmallScreenshot(); break; glx@10645: case WKC_CTRL | 'G': MenuClickWorldScreenshot(); break; glx@10645: glx@10645: /* those following are all fall through */ glx@10645: case WKC_NUM_PLUS: glx@10645: case WKC_EQUALS: glx@10645: case WKC_SHIFT | WKC_EQUALS: rubidium@11126: case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(this); break; glx@10645: glx@10645: /* those following are all fall through */ glx@10645: case WKC_NUM_MINUS: glx@10645: case WKC_MINUS: glx@10645: case WKC_SHIFT | WKC_MINUS: rubidium@11126: case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(this); break; glx@10645: glx@10645: case 'L': ShowEditorTerraformToolbar(); break; glx@10645: case 'M': ShowSmallMap(); break; glx@10645: case 'V': ShowExtraViewPortWindow(); break; glx@10645: default: return ES_NOT_HANDLED; glx@10645: } glx@10645: return ES_HANDLED; glx@10645: } glx@10645: glx@10645: virtual void OnPlaceObject(Point pt, TileIndex tile) glx@10645: { glx@10645: _place_proc(tile); glx@10645: } glx@10645: glx@10645: virtual void OnResize(Point new_size, Point delta) glx@10645: { rubidium@11126: /* There are 16 buttons plus some spacings if the space allows it. glx@10645: * Furthermore there are two panels of which one is non - essential rubidium@11126: * and that one can be removed if the space is too small. */ glx@10645: uint buttons_width; glx@10645: uint spacing; glx@10645: rubidium@11126: static const int normal_min_width = (TBP_SCENARIO_MAXBUTTON * TBP_BUTTONWIDTH) + (2 * TBP_DATEPANELWIDTH); rubidium@11126: static const int one_less_panel_min_width = (TBP_SCENARIO_MAXBUTTON * TBP_BUTTONWIDTH) + TBP_DATEPANELWIDTH; glx@10645: glx@10645: if (this->width >= one_less_panel_min_width) { rubidium@11126: buttons_width = TBP_SCENARIO_MAXBUTTON * TBP_BUTTONWIDTH; glx@10645: spacing = this->width - ((this->width >= normal_min_width) ? normal_min_width : one_less_panel_min_width); glx@10645: } else { rubidium@11126: buttons_width = this->width - TBP_DATEPANELWIDTH; glx@10645: spacing = 0; glx@10645: } rubidium@11126: static const uint extra_spacing_at[] = { 3, 4, 7, 8, 10, 17, 0 }; glx@10645: rubidium@11044: for (uint i = 0, x = 0, j = 0, b = 0; i < this->widget_count; i++) { glx@10645: switch (i) { rubidium@11044: case TBSE_SPACERPANEL: glx@10645: this->widget[i].left = x; glx@10645: if (this->width < normal_min_width) { glx@10645: this->widget[i].right = x; glx@10645: j++; glx@10645: continue; glx@10645: } glx@10645: rubidium@11126: x += TBP_DATEPANELWIDTH; glx@10645: this->widget[i].right = x - 1; glx@10645: break; glx@10645: rubidium@11126: case TBSE_DATEPANEL: { glx@10645: int offset = x - this->widget[i].left; glx@10645: this->widget[i + 1].left += offset; glx@10645: this->widget[i + 1].right += offset; glx@10645: this->widget[i + 2].left += offset; glx@10645: this->widget[i + 2].right += offset; glx@10645: this->widget[i].left = x; rubidium@11126: x += TBP_DATEPANELWIDTH; glx@10645: this->widget[i].right = x - 1; glx@10645: i += 2; glx@10645: } break; glx@10645: glx@10645: default: glx@10645: if (this->widget[i].bottom == 0) continue; glx@10645: glx@10645: this->widget[i].left = x; rubidium@11126: x += buttons_width / (TBP_SCENARIO_MAXBUTTON - b); glx@10645: this->widget[i].right = x - 1; rubidium@11126: buttons_width -= buttons_width / (TBP_SCENARIO_MAXBUTTON - b); glx@10645: b++; glx@10645: break; rubidium@9826: } rubidium@9826: glx@10645: if (extra_spacing_at[j] == i) { glx@10645: j++; glx@10645: uint add = spacing / (lengthof(extra_spacing_at) - j); glx@10645: spacing -= add; glx@10645: x += add; rubidium@9826: } glx@10645: } glx@10645: } rubidium@9826: glx@10645: virtual void OnTick() glx@10645: { glx@10955: if (this->IsWidgetLowered(TBSE_PAUSE) != !!_pause_game) { glx@10955: this->ToggleWidgetLoweredState(TBSE_PAUSE); glx@10645: this->SetDirty(); glx@10645: } rubidium@9826: glx@10955: if (this->IsWidgetLowered(TBSE_FASTFORWARD) != !!_fast_forward) { glx@10955: this->ToggleWidgetLoweredState(TBSE_FASTFORWARD); glx@10645: this->SetDirty(); glx@10645: } glx@10645: } rubidium@9826: glx@10645: virtual void OnInvalidateData(int data) glx@10645: { glx@10955: if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, TBSE_ZOOMIN, TBSE_ZOOMOUT); rubidium@9826: } glx@10645: }; rubidium@9826: rubidium@9826: static const Widget _toolb_scen_widgets[] = { rubidium@11126: { WWT_IMGBTN, RESIZE_LEFT, 14, 0, 0, 0, 21, SPR_IMG_PAUSE, STR_0171_PAUSE_GAME}, // TBSE_PAUSE rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_FASTFORWARD, STR_FAST_FORWARD}, // TBSE_FASTFORWARD rubidium@9826: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SETTINGS, STR_0187_OPTIONS}, rubidium@11126: {WWT_IMGBTN_2, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SAVE, STR_0297_SAVE_SCENARIO_LOAD_SCENARIO}, // TBSE_SAVESCENARIO rubidium@9826: rubidium@11126: { WWT_PANEL, RESIZE_NONE, 14, 0, 0, 0, 21, 0x0, STR_NULL}, // TBSE_SPACERPANEL rubidium@9826: rubidium@11126: { WWT_PANEL, RESIZE_NONE, 14, 0, 129, 0, 21, 0x0, STR_NULL}, // TBSE_DATEPANEL rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 3, 14, 5, 16, SPR_ARROW_DOWN, STR_029E_MOVE_THE_STARTING_DATE}, // TBSE_DATEBACKWARD rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 113, 125, 5, 16, SPR_ARROW_UP, STR_029F_MOVE_THE_STARTING_DATE}, // TBSE_DATEFORWARD rubidium@9826: rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SMALLMAP, STR_0175_DISPLAY_MAP_TOWN_DIRECTORY}, // TBSE_SMALLMAP rubidium@11126: rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_ZOOMIN, STR_017F_ZOOM_THE_VIEW_IN}, // TBSE_ZOOMIN rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_ZOOMOUT, STR_0180_ZOOM_THE_VIEW_OUT}, // TBSE_ZOOMOUT rubidium@11126: rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_LANDSCAPING, STR_022E_LANDSCAPE_GENERATION}, // TBSE_LANDGENERATE rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_TOWN, STR_022F_TOWN_GENERATION}, // TBSE_TOWNGENERATE rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_INDUSTRY, STR_0230_INDUSTRY_GENERATION}, // TBSE_INDUSTRYGENERATE rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_BUILDROAD, STR_0231_ROAD_CONSTRUCTION}, // TBSE_BUILDROAD rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_BUILDWATER, STR_0183_BUILD_SHIP_DOCKS}, // TBSE_BUILDDOCKS rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_PLANTTREES, STR_0288_PLANT_TREES}, // TBSE_PLANTTREES rubidium@11126: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_SIGN, STR_0289_PLACE_SIGN}, // TBSE_PLACESIGNS rubidium@11126: rubidium@9826: { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL}, rubidium@9826: { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL}, rubidium@9826: { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL}, rubidium@9826: { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL}, rubidium@9826: { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL}, rubidium@9826: { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL}, rubidium@9826: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_MUSIC, STR_01D4_SHOW_SOUND_MUSIC_WINDOW}, rubidium@9826: { WWT_EMPTY, RESIZE_NONE, 0, 0, 0, 0, 0, 0x0, STR_NULL}, rubidium@9826: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 0, 0, 21, SPR_IMG_QUERY, STR_0186_LAND_BLOCK_INFORMATION}, rubidium@9826: {WIDGETS_END}, rubidium@9826: }; rubidium@9826: rubidium@9826: static const WindowDesc _toolb_scen_desc = { rubidium@11126: 0, 0, 130, TBP_BUTTONHEIGHT, 640, TBP_BUTTONHEIGHT, rubidium@9826: WC_MAIN_TOOLBAR, WC_NONE, rubidium@9826: WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, rubidium@9826: _toolb_scen_widgets, rubidium@9826: }; rubidium@9826: rubidium@10249: /* --- Rendering/handling the drop down menus --- */ rubidium@10249: rubidium@10249: typedef void MenuClickedProc(int index); rubidium@10249: rubidium@10249: static MenuClickedProc * const _menu_clicked_procs[] = { rubidium@10249: NULL, /* 0 */ rubidium@10249: NULL, /* 1 */ rubidium@10249: MenuClickSettings, /* 2 */ rubidium@10249: MenuClickSaveLoad, /* 3 */ rubidium@10249: MenuClickMap, /* 4 */ rubidium@10249: MenuClickTown, /* 5 */ rubidium@10249: MenuClickSubsidies, /* 6 */ rubidium@10249: MenuClickStations, /* 7 */ rubidium@10249: MenuClickFinances, /* 8 */ rubidium@10249: MenuClickCompany, /* 9 */ rubidium@10249: MenuClickGraphs, /* 10 */ rubidium@10249: MenuClickLeague, /* 11 */ rubidium@10249: MenuClickIndustry, /* 12 */ rubidium@10249: MenuClickShowTrains, /* 13 */ rubidium@10249: MenuClickShowRoad, /* 14 */ rubidium@10249: MenuClickShowShips, /* 15 */ rubidium@10249: MenuClickShowAir, /* 16 */ rubidium@11044: MenuClickMap, /* 17 */ rubidium@10249: NULL, /* 18 */ rubidium@10249: MenuClickBuildRail, /* 19 */ rubidium@10249: MenuClickBuildRoad, /* 20 */ rubidium@10249: MenuClickBuildWater, /* 21 */ rubidium@10249: MenuClickBuildAir, /* 22 */ rubidium@10249: MenuClickForest, /* 23 */ rubidium@10249: MenuClickMusicWindow, /* 24 */ rubidium@10249: MenuClickNewspaper, /* 25 */ rubidium@10249: MenuClickHelp, /* 26 */ rubidium@10249: }; rubidium@10249: glx@10645: struct ToolbarMenuWindow : Window { glx@10645: int item_count; glx@10645: int sel_index; glx@10645: int main_button; glx@10645: int action_id; glx@10645: int checked_items; glx@10645: int disabled_items; glx@10645: StringID base_string; rubidium@10249: glx@10645: ToolbarMenuWindow(int x, int y, int width, int height, const Widget *widgets, int item_count, glx@10645: int sel_index, int parent_button, StringID base_string, int checked_items, rubidium@10715: int disabled_items) : glx@10645: Window(x, y, width, height, WC_TOOLBAR_MENU, widgets), glx@10645: item_count(item_count), sel_index(sel_index), main_button(GB(parent_button, 0, 8)), glx@10645: action_id((GB(parent_button, 8, 8) != 0) ? GB(parent_button, 8, 8) : parent_button), glx@10645: checked_items(checked_items), disabled_items(disabled_items), base_string(base_string) glx@10645: { glx@10645: this->widget[0].bottom = item_count * 10 + 1; glx@10645: this->widget[0].right = this->width - 1; glx@10645: this->flags4 &= ~WF_WHITE_BORDER_MASK; rubidium@10249: glx@10645: this->FindWindowPlacementAndResize(width, height); glx@10645: } rubidium@10249: glx@10645: ~ToolbarMenuWindow() glx@10645: { glx@10645: Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0); glx@10645: w->RaiseWidget(this->main_button); glx@10645: w->SetDirty(); glx@10645: } glx@10645: glx@10645: virtual void OnPaint() glx@10645: { glx@10645: this->DrawWidgets(); glx@10645: glx@10645: for (int i = 0, x = 1, y = 1; i != this->item_count; i++, y += 10) { glx@10645: TextColour color = HasBit(this->disabled_items, i) ? TC_GREY : (this->sel_index == i) ? TC_WHITE : TC_BLACK; glx@10645: if (this->sel_index == i) GfxFillRect(x, y, x + this->width - 3, y + 9, 0); glx@10645: glx@10645: if (HasBit(this->checked_items, i)) DrawString(x + 2, y, STR_CHECKMARK, color); glx@10645: DrawString(x + 2, y, this->base_string + i, color); glx@10645: } glx@10645: } glx@10645: glx@10645: virtual void OnMouseLoop() glx@10645: { glx@10645: int index = GetMenuItemIndex(this, this->item_count, this->disabled_items); glx@10645: glx@10645: if (_left_button_down) { glx@10645: if (index == -1 || index == this->sel_index) return; glx@10645: glx@10645: this->sel_index = index; glx@10645: this->SetDirty(); glx@10645: } else { glx@10645: if (index < 0) { glx@10645: Window *w = FindWindowById(WC_MAIN_TOOLBAR,0); glx@10645: if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) == this->main_button) { glx@10645: index = this->sel_index; glx@10645: } rubidium@10249: } rubidium@10249: glx@10645: int action_id = this->action_id; glx@10645: delete this; rubidium@10249: glx@10645: if (index >= 0) { glx@10645: assert((uint)index <= lengthof(_menu_clicked_procs)); glx@10645: _menu_clicked_procs[action_id](index); rubidium@10513: } glx@10645: } rubidium@10249: } glx@10645: }; rubidium@10249: rubidium@10249: /* Dynamic widget length determined by toolbar-string length. rubidium@10249: * See PopupMainToolbMenu en MenuWndProc */ rubidium@10249: static const Widget _menu_widgets[] = { rubidium@10249: { WWT_PANEL, RESIZE_NONE, 14, 0, 0, 0, 0, 0x0, STR_NULL}, rubidium@10249: { WIDGETS_END}, rubidium@10249: }; rubidium@10249: rubidium@10249: rubidium@10249: /** rubidium@10249: * Get the maximum length of a given string in a string-list. This is an rubidium@10249: * implicit string-list where the ID's are consecutive rubidium@10249: * @param base_string StringID of the first string in the list rubidium@10249: * @param count amount of StringID's in the list rubidium@10249: * @return the length of the longest string rubidium@10249: */ rubidium@10249: static int GetStringListMaxWidth(StringID base_string, byte count) rubidium@10249: { rubidium@10249: char buffer[512]; rubidium@10249: int width, max_width = 0; rubidium@10249: rubidium@10249: for (byte i = 0; i != count; i++) { rubidium@10249: GetString(buffer, base_string + i, lastof(buffer)); rubidium@10249: width = GetStringBoundingBox(buffer).width; rubidium@10249: if (width > max_width) max_width = width; rubidium@10249: } rubidium@10249: rubidium@10249: return max_width; rubidium@10249: } rubidium@10249: rubidium@10249: /** rubidium@10249: * Show a general dropdown menu. The positioning of the dropdown menu rubidium@10249: * defaults to the left side of the parent_button, eg the button that caused rubidium@10249: * this window to appear. The only exceptions are when the right side of this rubidium@10249: * dropdown would fall outside the main toolbar window, in that case it is rubidium@10249: * aligned with the toolbar's right side. rubidium@10249: * Since the disable-mask is only 8 bits right now, these dropdowns are rubidium@10249: * restricted to 8 items max if any bits of disabled_mask are active. glx@10645: * @param parent Pointer to a window this dropdown menu belongs to. Has no effect rubidium@10249: * whatsoever, only graphically for positioning. rubidium@10249: * @param parent_button The widget identifier of the button that was clicked for rubidium@10249: * this dropdown. The created dropdown then knows what button to raise (button) on rubidium@10249: * action and whose function to execute (action). rubidium@10249: * It is possible to appoint another button for an action event by setting the rubidium@10249: * upper 8 bits of this parameter. If non is set, action is presumed to be the same rubidium@10249: * as button. So
rubidium@10249: * button bits 0 - 7 - widget clicked to get dropdown rubidium@10249: * action bits 8 - 15 - function of widget to execute on select (defaults to bits 0 - 7) rubidium@10249: * @param base_string The first StringID shown in the dropdown list. All others are rubidium@10249: * consecutive indeces from the language file. XXX - fix? Use ingame-string tables? rubidium@10249: * @param item_count Number of strings in the list, see previous parameter rubidium@10249: * @param disabled_mask Bitmask of disabled strings in the list glx@10645: * @param sel_index The selected toolbar item glx@10645: * @param check_items The items to have a checked mark in front of them. glx@10645: * @return Return a pointer to the newly created dropdown window glx@10645: */ glx@10645: static void PopupMainToolbMenu(Window *parent, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask, int sel_index, int checked_items) rubidium@10249: { rubidium@10249: assert(disabled_mask == 0 || item_count <= 8); glx@10645: parent->LowerWidget(parent_button); glx@10645: parent->InvalidateWidget(parent_button); rubidium@10249: rubidium@10249: DeleteWindowById(WC_TOOLBAR_MENU, 0); rubidium@10249: rubidium@10249: /* Extend the dropdown toolbar to the longest string in the list */ rubidium@10249: int width = max(GetStringListMaxWidth(base_string, item_count) + 6, 140); rubidium@10249: int height = item_count * 10 + 2; rubidium@10249: rubidium@10249: Point pos = GetToolbarDropdownPos(parent_button, width, height); rubidium@10249: glx@10645: new ToolbarMenuWindow(pos.x, pos.y, width, height, _menu_widgets, item_count, sel_index, parent_button, base_string, checked_items, disabled_mask); rubidium@10249: rubidium@10249: SndPlayFx(SND_15_BEEP); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Rendering/drawing the player menu --- */ rubidium@10249: static int GetPlayerIndexFromMenu(int index) rubidium@10249: { rubidium@10249: if (index >= 0) { rubidium@10249: const Player *p; rubidium@10249: rubidium@10249: FOR_ALL_PLAYERS(p) { rubidium@10249: if (p->is_active && --index < 0) return p->index; rubidium@10249: } rubidium@10249: } rubidium@10249: return -1; rubidium@10249: } rubidium@10249: glx@10645: struct ToolbarPlayerMenuWindow : Window { glx@10645: int item_count; glx@10645: int sel_index; glx@10645: int main_button; glx@10645: int action_id; glx@10645: int gray_items; rubidium@10249: glx@10645: ToolbarPlayerMenuWindow(int x, int y, int width, int height, const Widget *widgets, int main_button, int gray) : glx@10645: Window(x, y, width, height, WC_TOOLBAR_MENU, widgets), glx@10645: item_count(0), main_button(main_button), action_id(main_button), gray_items(gray) glx@10645: { glx@10645: this->flags4 &= ~WF_WHITE_BORDER_MASK; glx@10645: this->sel_index = (_local_player != PLAYER_SPECTATOR) ? _local_player : GetPlayerIndexFromMenu(0); rubidium@11044: if (_networking && main_button == TBN_PLAYERS) { glx@10645: if (_local_player != PLAYER_SPECTATOR) { glx@10645: this->sel_index++; glx@10645: } else { glx@10645: /* Select client list by default for spectators */ glx@10645: this->sel_index = 0; glx@10645: } glx@10645: } rubidium@10715: rubidium@10715: this->FindWindowPlacementAndResize(width, height); glx@10645: } glx@10645: glx@10645: ~ToolbarPlayerMenuWindow() glx@10645: { glx@10645: Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0); glx@10645: w->RaiseWidget(this->main_button); rubidium@10455: w->SetDirty(); rubidium@10249: } rubidium@10249: glx@10645: void UpdatePlayerMenuHeight() glx@10645: { glx@10645: byte num = ActivePlayerCount(); rubidium@10249: glx@10645: /* Increase one to fit in PlayerList in the menu when in network */ rubidium@11044: if (_networking && this->main_button == TBN_PLAYERS) num++; rubidium@10249: glx@10645: if (this->item_count != num) { glx@10645: this->item_count = num; glx@10645: this->SetDirty(); glx@10645: num = num * 10 + 2; glx@10645: this->height = num; glx@10645: this->widget[0].bottom = this->widget[0].top + num - 1; glx@10645: this->top = GetToolbarDropdownPos(0, this->width, this->height).y; glx@10645: this->SetDirty(); glx@10645: } glx@10645: } glx@10645: glx@10645: virtual void OnPaint() glx@10645: { glx@10645: this->UpdatePlayerMenuHeight(); glx@10645: this->DrawWidgets(); glx@10645: glx@10645: int x = 1; glx@10645: int y = 1; glx@10645: int sel = this->sel_index; glx@10645: int gray = this->gray_items; glx@10645: glx@10645: /* 9 = playerlist */ rubidium@11044: if (_networking && this->main_button == TBN_PLAYERS) { glx@10645: if (sel == 0) { glx@10645: GfxFillRect(x, y, x + 238, y + 9, 0); glx@10645: } glx@10645: DrawString(x + 19, y, STR_NETWORK_CLIENT_LIST, TC_FROMSTRING); glx@10645: y += 10; glx@10645: sel--; glx@10645: } glx@10645: glx@10645: const Player *p; glx@10645: FOR_ALL_PLAYERS(p) { glx@10645: if (p->is_active) { glx@10645: if (p->index == sel) { rubidium@10249: GfxFillRect(x, y, x + 238, y + 9, 0); rubidium@10249: } glx@10645: glx@10645: DrawPlayerIcon(p->index, x + 2, y + 1); glx@10645: glx@10645: SetDParam(0, p->index); glx@10645: SetDParam(1, p->index); glx@10645: glx@10645: TextColour color = (p->index == sel) ? TC_WHITE : TC_BLACK; glx@10645: if (gray & 1) color = TC_GREY; glx@10645: DrawString(x + 19, y, STR_7021, color); glx@10645: rubidium@10249: y += 10; glx@10645: } glx@10645: gray >>= 1; glx@10645: } glx@10645: } glx@10645: glx@10645: virtual void OnMouseLoop() glx@10645: { glx@10645: int index = GetMenuItemIndex(this, this->item_count, 0); glx@10645: glx@10645: if (_left_button_down) { glx@10645: this->UpdatePlayerMenuHeight(); glx@10645: /* We have a new entry at the top of the list of menu 9 when networking glx@10645: * so keep that in count */ rubidium@11044: if (_networking && this->main_button == TBN_PLAYERS) { glx@10645: if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1; glx@10645: } else { glx@10645: index = GetPlayerIndexFromMenu(index); rubidium@10249: } rubidium@10249: glx@10645: if (index == -1 || index == this->sel_index) return; rubidium@10249: glx@10645: this->sel_index = index; glx@10645: this->SetDirty(); glx@10645: } else { glx@10645: int action_id = this->action_id; rubidium@10249: glx@10645: /* We have a new entry at the top of the list of menu 9 when networking glx@10645: * so keep that in count */ rubidium@11044: if (_networking && this->main_button == TBN_PLAYERS) { glx@10645: if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1; glx@10645: } else { glx@10645: index = GetPlayerIndexFromMenu(index); glx@10645: } rubidium@10249: glx@10645: if (index < 0) { glx@10645: Window *w = FindWindowById(WC_MAIN_TOOLBAR,0); glx@10645: if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) == this->main_button) { glx@10645: index = this->sel_index; rubidium@10513: } rubidium@10249: } glx@10645: glx@10645: delete this; glx@10645: glx@10645: if (index >= 0) { glx@10645: assert(index >= 0 && index < 30); glx@10645: _menu_clicked_procs[action_id](index); glx@10645: } glx@10645: } rubidium@10249: } glx@10645: }; rubidium@10249: rubidium@10249: static const Widget _player_menu_widgets[] = { rubidium@10249: { WWT_PANEL, RESIZE_NONE, 14, 0, 240, 0, 81, 0x0, STR_NULL}, rubidium@10249: { WIDGETS_END}, rubidium@10249: }; rubidium@10249: rubidium@11044: /** Shows the list of players appearing under the buttons that are linked to options for rubidium@11044: * multiple players. rubidium@11044: * @param parent Window who triggered that action. It's the toolbar, in fact rubidium@11044: * @param main_button widget which has been used rubidium@11044: * @param gray bit-mapping of the items that will need to be grayed out once displayed */ glx@10645: static void PopupMainPlayerToolbMenu(Window *parent, int main_button, int gray) rubidium@10249: { glx@10645: parent->LowerWidget(main_button); glx@10645: parent->InvalidateWidget(main_button); rubidium@10249: rubidium@10249: DeleteWindowById(WC_TOOLBAR_MENU, 0); rubidium@10249: Point pos = GetToolbarDropdownPos(main_button, 241, 82); glx@10645: new ToolbarPlayerMenuWindow(pos.x, pos.y, 241, 82, _player_menu_widgets, main_button, gray); rubidium@10513: rubidium@10249: SndPlayFx(SND_15_BEEP); rubidium@10249: } rubidium@10249: rubidium@10249: /* --- Allocating the toolbar --- */ rubidium@10249: glx@10645: void AllocateToolbar() rubidium@9826: { glx@10294: /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */ rubidium@10249: _last_built_roadtype = ROADTYPE_ROAD; rubidium@10249: glx@10645: if (_game_mode == GM_EDITOR) { glx@10645: new ScenarioEditorToolbarWindow(&_toolb_scen_desc);; glx@10645: } else { glx@10645: new MainToolbarWindow(&_toolb_normal_desc); glx@10645: } rubidium@9826: }