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