diff options
author | rubidium <rubidium@openttd.org> | 2008-04-18 15:11:39 +0000 |
---|---|---|
committer | rubidium <rubidium@openttd.org> | 2008-04-18 15:11:39 +0000 |
commit | dc16b4f2b4cf13f7c55f0bb7efeaf74ec4b56752 (patch) | |
tree | ec23710227cd626467cce813171cef4a6e232ac1 /src/toolbar_gui.cpp | |
parent | 31411d4755fd6f77ea8435dd0fb36f5c07d4e2de (diff) | |
download | openttd-dc16b4f2b4cf13f7c55f0bb7efeaf74ec4b56752.tar.xz |
(svn r12767) -Codechange: merge all main toolbar related functions into a single file instead of scattering the functionality over several files.
Diffstat (limited to 'src/toolbar_gui.cpp')
-rw-r--r-- | src/toolbar_gui.cpp | 743 |
1 files changed, 689 insertions, 54 deletions
diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 088e80f8e..371ebbfcc 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -29,22 +29,42 @@ #include "vehicle_base.h" #include "gfx_func.h" #include "cheat_func.h" +#include "transparency_gui.h" +#include "screenshot.h" +#include "newgrf_config.h" +#include "signs_func.h" +#include "fios.h" +#include "functions.h" +#include "console.h" #include "network/network.h" +#include "network/network_gui.h" #include "table/strings.h" #include "table/sprites.h" -extern void SelectSignTool(); -extern RailType _last_built_railtype; -extern RoadType _last_built_roadtype; +static Window *PopupMainToolbMenu(Window *w, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask); +static Window *PopupMainPlayerToolbMenu(Window *w, int main_button, int gray); -/* Returns the position where the toolbar wants the menu to appear. +RailType _last_built_railtype; +RoadType _last_built_roadtype; + +static void SelectSignTool() +{ + if (_cursor.sprite == SPR_CURSOR_SIGN) { + ResetObjectToPlace(); + } else { + SetObjectToPlace(SPR_CURSOR_SIGN, PAL_NONE, VHM_RECT, WC_MAIN_TOOLBAR, 0); + _place_proc = PlaceProc_Sign; + } +} + +/** Returns the position where the toolbar wants the menu to appear. * Make sure the dropdown is fully visible within the window. * x + w->left because x is supposed to be the offset of the toolbar-button * we clicked on and w->left the toolbar window itself. So meaning that * the default position is aligned with the left side of the clicked button */ -Point GetToolbarDropdownPos(uint16 parent_button, int width, int height) +static Point GetToolbarDropdownPos(uint16 parent_button, int width, int height) { const Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0); Point pos; @@ -55,6 +75,7 @@ Point GetToolbarDropdownPos(uint16 parent_button, int width, int height) return pos; } +/* --- Pausing --- */ static void ToolbarPauseClick(Window *w) { @@ -63,107 +84,291 @@ static void ToolbarPauseClick(Window *w) if (DoCommandP(0, _pause_game ? 0 : 1, 0, NULL, CMD_PAUSE)) SndPlayFx(SND_15_BEEP); } +/* --- Fast forwarding --- */ + static void ToolbarFastForwardClick(Window *w) { _fast_forward ^= true; SndPlayFx(SND_15_BEEP); } +/* --- Options button menu --- */ + +static void ToolbarOptionsClick(Window *w) +{ + uint16 x = 0; + + w = PopupMainToolbMenu(w, 2, STR_02C4_GAME_OPTIONS, 14, 0); + + if (HasBit(_display_opt, DO_SHOW_TOWN_NAMES)) SetBit(x, 6); + if (HasBit(_display_opt, DO_SHOW_STATION_NAMES)) SetBit(x, 7); + if (HasBit(_display_opt, DO_SHOW_SIGNS)) SetBit(x, 8); + if (HasBit(_display_opt, DO_WAYPOINTS)) SetBit(x, 9); + if (HasBit(_display_opt, DO_FULL_ANIMATION)) SetBit(x, 10); + if (HasBit(_display_opt, DO_FULL_DETAIL)) SetBit(x, 11); + if (IsTransparencySet(TO_HOUSES)) SetBit(x, 12); + if (IsTransparencySet(TO_SIGNS)) SetBit(x, 13); + WP(w, menu_d).checked_items = x; +} + +static void MenuClickSettings(int index) +{ + switch (index) { + case 0: ShowGameOptions(); return; + case 1: ShowGameDifficulty(); return; + case 2: ShowPatchesSelection(); return; + case 3: ShowNewGRFSettings(!_networking, true, true, &_grfconfig); return; + case 4: ShowTransparencyToolbar(); break; + + case 6: ToggleBit(_display_opt, DO_SHOW_TOWN_NAMES); break; + case 7: ToggleBit(_display_opt, DO_SHOW_STATION_NAMES); break; + case 8: ToggleBit(_display_opt, DO_SHOW_SIGNS); break; + case 9: ToggleBit(_display_opt, DO_WAYPOINTS); break; + case 10: ToggleBit(_display_opt, DO_FULL_ANIMATION); break; + case 11: ToggleBit(_display_opt, DO_FULL_DETAIL); break; + case 12: ToggleTransparency(TO_HOUSES); break; + case 13: ToggleTransparency(TO_SIGNS); break; + } + MarkWholeScreenDirty(); +} + +/* --- Saving/loading button menu --- */ + static void ToolbarSaveClick(Window *w) { PopupMainToolbMenu(w, 3, STR_015C_SAVE_GAME, 4, 0); } +static void ToolbarScenSaveOrLoad(Window *w) +{ + PopupMainToolbMenu(w, 3, STR_0292_SAVE_SCENARIO, 6, 0); +} + +static void MenuClickSaveLoad(int index) +{ + if (_game_mode == GM_EDITOR) { + switch (index) { + case 0: ShowSaveLoadDialog(SLD_SAVE_SCENARIO); break; + case 1: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break; + case 2: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break; + case 3: AskExitToGameMenu(); break; + case 5: HandleExitGameRequest(); break; + } + } else { + switch (index) { + case 0: ShowSaveLoadDialog(SLD_SAVE_GAME); break; + case 1: ShowSaveLoadDialog(SLD_LOAD_GAME); break; + case 2: AskExitToGameMenu(); break; + case 3: HandleExitGameRequest(); break; + } + } +} + +/* --- Map button menu --- */ + static void ToolbarMapClick(Window *w) { PopupMainToolbMenu(w, 4, STR_02DE_MAP_OF_WORLD, 3, 0); } +static void MenuClickMap(int index) +{ + switch (index) { + case 0: ShowSmallMap(); break; + case 1: ShowExtraViewPortWindow(); break; + case 2: ShowSignList(); break; + } +} + +static void MenuClickScenMap(int index) +{ + switch (index) { + case 0: ShowSmallMap(); break; + case 1: ShowExtraViewPortWindow(); break; + case 2: ShowSignList(); break; + case 3: ShowTownDirectory(); break; + } +} + +/* --- Town button menu --- */ + static void ToolbarTownClick(Window *w) { PopupMainToolbMenu(w, 5, STR_02BB_TOWN_DIRECTORY, 1, 0); } +static void MenuClickTown(int index) +{ + ShowTownDirectory(); +} + +/* --- Subidies button menu --- */ + static void ToolbarSubsidiesClick(Window *w) { PopupMainToolbMenu(w, 6, STR_02DD_SUBSIDIES, 1, 0); } +static void MenuClickSubsidies(int index) +{ + ShowSubsidiesList(); +} + +/* --- Stations button menu --- */ + static void ToolbarStationsClick(Window *w) { PopupMainPlayerToolbMenu(w, 7, 0); } -static void ToolbarMoneyClick(Window *w) +static void MenuClickStations(int index) +{ + ShowPlayerStations((PlayerID)index); +} + +/* --- Finances button menu --- */ + +static void ToolbarFinancesClick(Window *w) { PopupMainPlayerToolbMenu(w, 8, 0); } +static void MenuClickFinances(int index) +{ + ShowPlayerFinances((PlayerID)index); +} + +/* --- Company's button menu --- */ + static void ToolbarPlayersClick(Window *w) { PopupMainPlayerToolbMenu(w, 9, 0); } +static void MenuClickCompany(int index) +{ + if (_networking && index == 0) { + ShowClientList(); + } else { + if (_networking) index--; + ShowPlayerCompany((PlayerID)index); + } +} + +/* --- Graphs button menu --- */ + static void ToolbarGraphsClick(Window *w) { PopupMainToolbMenu(w, 10, STR_0154_OPERATING_PROFIT_GRAPH, 6, 0); } +static void MenuClickGraphs(int index) +{ + switch (index) { + case 0: ShowOperatingProfitGraph(); break; + case 1: ShowIncomeGraph(); break; + case 2: ShowDeliveredCargoGraph(); break; + case 3: ShowPerformanceHistoryGraph(); break; + case 4: ShowCompanyValueGraph(); break; + case 5: ShowCargoPaymentRates(); break; + } +} + +/* --- League button menu --- */ + static void ToolbarLeagueClick(Window *w) { PopupMainToolbMenu(w, 11, STR_015A_COMPANY_LEAGUE_TABLE, 2, 0); } +static void MenuClickLeague(int index) +{ + switch (index) { + case 0: ShowCompanyLeagueTable(); break; + case 1: ShowPerformanceRatingDetail(); break; + } +} + +/* --- Industries button menu --- */ + static void ToolbarIndustryClick(Window *w) { /* Disable build-industry menu if we are a spectator */ PopupMainToolbMenu(w, 12, STR_INDUSTRY_DIR, 2, (_current_player == PLAYER_SPECTATOR) ? (1 << 1) : 0); } -static void ToolbarTrainClick(Window *w) +static void MenuClickIndustry(int index) +{ + switch (index) { + case 0: ShowIndustryDirectory(); break; + case 1: ShowBuildIndustryWindow(); break; + } +} + +/* --- Trains button menu + 1 helper function for all vehicles. --- */ + +static void ToolbarVehicleClick(Window *w, VehicleType veh) { const Vehicle *v; - int dis = -1; + int dis = ~0; FOR_ALL_VEHICLES(v) { - if (v->type == VEH_TRAIN && IsFrontEngine(v)) ClrBit(dis, v->owner); + if (v->type == veh && v->IsPrimaryVehicle()) { + ClrBit(dis, v->owner); + break; + } } - PopupMainPlayerToolbMenu(w, 13, dis); + PopupMainPlayerToolbMenu(w, 13 + veh, dis); } + +static void ToolbarTrainClick(Window *w) +{ + ToolbarVehicleClick(w, VEH_TRAIN); +} + +static void MenuClickShowTrains(int index) +{ + ShowVehicleListWindow((PlayerID)index, VEH_TRAIN); +} + +/* --- Road vehicle button menu --- */ + static void ToolbarRoadClick(Window *w) { - const Vehicle *v; - int dis = -1; + ToolbarVehicleClick(w, VEH_ROAD); +} - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_ROAD && IsRoadVehFront(v)) ClrBit(dis, v->owner); - } - PopupMainPlayerToolbMenu(w, 14, dis); +static void MenuClickShowRoad(int index) +{ + ShowVehicleListWindow((PlayerID)index, VEH_ROAD); } +/* --- Ship button menu --- */ + static void ToolbarShipClick(Window *w) { - const Vehicle *v; - int dis = -1; + ToolbarVehicleClick(w, VEH_SHIP); +} - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_SHIP) ClrBit(dis, v->owner); - } - PopupMainPlayerToolbMenu(w, 15, dis); +static void MenuClickShowShips(int index) +{ + ShowVehicleListWindow((PlayerID)index, VEH_SHIP); } +/* --- Aircraft button menu --- */ + static void ToolbarAirClick(Window *w) { - const Vehicle *v; - int dis = -1; + ToolbarVehicleClick(w, VEH_AIRCRAFT); +} - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_AIRCRAFT) ClrBit(dis, v->owner); - } - PopupMainPlayerToolbMenu(w, 16, dis); +static void MenuClickShowAir(int index) +{ + ShowVehicleListWindow((PlayerID)index, VEH_AIRCRAFT); } +/* --- Zoom in button --- */ static void ToolbarZoomInClick(Window *w) { @@ -173,6 +378,8 @@ static void ToolbarZoomInClick(Window *w) } } +/* --- Zoom out button --- */ + static void ToolbarZoomOutClick(Window *w) { if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) { @@ -181,6 +388,8 @@ static void ToolbarZoomOutClick(Window *w) } } +/* --- Rail button menu --- */ + static void ToolbarBuildRailClick(Window *w) { const Player *p = GetPlayer(_local_player); @@ -188,6 +397,14 @@ static void ToolbarBuildRailClick(Window *w) WP(w2, menu_d).sel_index = _last_built_railtype; } +static void MenuClickBuildRail(int index) +{ + _last_built_railtype = (RailType)index; + ShowBuildRailToolbar(_last_built_railtype, -1); +} + +/* --- Road button menu --- */ + static void ToolbarBuildRoadClick(Window *w) { const Player *p = GetPlayer(_local_player); @@ -196,59 +413,110 @@ static void ToolbarBuildRoadClick(Window *w) WP(w2, menu_d).sel_index = _last_built_roadtype; } +static void MenuClickBuildRoad(int index) +{ + _last_built_roadtype = (RoadType)index; + ShowBuildRoadToolbar(_last_built_roadtype); +} + +/* --- Water button menu --- */ + static void ToolbarBuildWaterClick(Window *w) { PopupMainToolbMenu(w, 21, STR_9800_DOCK_CONSTRUCTION, 1, 0); } +static void MenuClickBuildWater(int index) +{ + ShowBuildDocksToolbar(); +} + +/* --- Airport button menu --- */ + static void ToolbarBuildAirClick(Window *w) { PopupMainToolbMenu(w, 22, STR_A01D_AIRPORT_CONSTRUCTION, 1, 0); } +static void MenuClickBuildAir(int index) +{ + ShowBuildAirToolbar(); +} + +/* --- Forest button menu --- */ + static void ToolbarForestClick(Window *w) { PopupMainToolbMenu(w, 23, STR_LANDSCAPING, 3, 0); } +static void MenuClickForest(int index) +{ + switch (index) { + case 0: ShowTerraformToolbar(); break; + case 1: ShowBuildTreesToolbar(); break; + case 2: SelectSignTool(); break; + } +} + +/* --- Music button menu --- */ + static void ToolbarMusicClick(Window *w) { PopupMainToolbMenu(w, 24, STR_01D3_SOUND_MUSIC, 1, 0); } +static void MenuClickMusicWindow(int index) +{ + ShowMusicWindow(); +} + +/* --- Newspaper button menu --- */ + static void ToolbarNewspaperClick(Window *w) { PopupMainToolbMenu(w, 25, STR_0200_LAST_MESSAGE_NEWS_REPORT, 3, 0); } +static void MenuClickNewspaper(int index) +{ + switch (index) { + case 0: ShowLastNewsMessage(); break; + case 1: ShowMessageOptions(); break; + case 2: ShowMessageHistory(); break; + } +} + +/* --- Help button menu --- */ + static void ToolbarHelpClick(Window *w) { PopupMainToolbMenu(w, 26, STR_02D5_LAND_BLOCK_INFO, 6, 0); } -static void ToolbarOptionsClick(Window *w) +static void MenuClickSmallScreenshot() { - uint16 x = 0; - - w = PopupMainToolbMenu(w, 2, STR_02C4_GAME_OPTIONS, 14, 0); - - if (HasBit(_display_opt, DO_SHOW_TOWN_NAMES)) SetBit(x, 6); - if (HasBit(_display_opt, DO_SHOW_STATION_NAMES)) SetBit(x, 7); - if (HasBit(_display_opt, DO_SHOW_SIGNS)) SetBit(x, 8); - if (HasBit(_display_opt, DO_WAYPOINTS)) SetBit(x, 9); - if (HasBit(_display_opt, DO_FULL_ANIMATION)) SetBit(x, 10); - if (HasBit(_display_opt, DO_FULL_DETAIL)) SetBit(x, 11); - if (IsTransparencySet(TO_HOUSES)) SetBit(x, 12); - if (IsTransparencySet(TO_SIGNS)) SetBit(x, 13); - WP(w, menu_d).checked_items = x; + SetScreenshotType(SC_VIEWPORT); } +static void MenuClickWorldScreenshot() +{ + SetScreenshotType(SC_WORLD); +} -static void ToolbarScenSaveOrLoad(Window *w) +static void MenuClickHelp(int index) { - PopupMainToolbMenu(w, 3, STR_0292_SAVE_SCENARIO, 6, 0); + switch (index) { + case 0: PlaceLandBlockInfo(); break; + case 2: IConsoleSwitch(); break; + case 3: MenuClickSmallScreenshot(); break; + case 4: MenuClickWorldScreenshot(); break; + case 5: ShowAboutWindow(); break; + } } +/* --- Scenario editor specific handlers. */ + static void ToolbarScenDateBackward(Window *w) { /* don't allow too fast scrolling */ @@ -346,6 +614,8 @@ static void ToolbarBtn_NULL(Window *w) } +/* --- Toolbar handling for the 'normal' case */ + typedef void ToolbarButtonProc(Window *w); static ToolbarButtonProc * const _toolbar_button_procs[] = { @@ -357,7 +627,7 @@ static ToolbarButtonProc * const _toolbar_button_procs[] = { ToolbarTownClick, ToolbarSubsidiesClick, ToolbarStationsClick, - ToolbarMoneyClick, + ToolbarFinancesClick, ToolbarPlayersClick, ToolbarGraphsClick, ToolbarLeagueClick, @@ -378,11 +648,7 @@ static ToolbarButtonProc * const _toolbar_button_procs[] = { ToolbarHelpClick, }; -extern void MenuClickSmallScreenshot(); -extern void MenuClickWorldScreenshot(); -extern void MenuClickSaveLoad(int index); - -void MainToolbarWndProc(Window *w, WindowEvent *e) +static void MainToolbarWndProc(Window *w, WindowEvent *e) { switch (e->event) { case WE_PAINT: @@ -404,8 +670,7 @@ void MainToolbarWndProc(Window *w, WindowEvent *e) break; case WE_CLICK: - if (_game_mode != GM_MENU && !w->IsWidgetDisabled(e->we.click.widget)) - _toolbar_button_procs[e->we.click.widget](w); + if (_game_mode != GM_MENU && !w->IsWidgetDisabled(e->we.click.widget)) _toolbar_button_procs[e->we.click.widget](w); break; case WE_KEYPRESS: @@ -561,6 +826,8 @@ static const WindowDesc _toolb_normal_desc = { }; +/* --- Toolbar handling for the scenario editor */ + static ToolbarButtonProc * const _scen_toolbar_button_procs[] = { ToolbarPauseClick, ToolbarFastForwardClick, @@ -591,7 +858,7 @@ static ToolbarButtonProc * const _scen_toolbar_button_procs[] = { ToolbarHelpClick, }; -void ScenEditToolbarWndProc(Window *w, WindowEvent *e) +static void ScenEditToolbarWndProc(Window *w, WindowEvent *e) { switch (e->event) { case WE_PAINT: @@ -794,7 +1061,375 @@ static const WindowDesc _toolb_scen_desc = { ScenEditToolbarWndProc }; +/* --- Rendering/handling the drop down menus --- */ + +typedef void MenuClickedProc(int index); + +static MenuClickedProc * const _menu_clicked_procs[] = { + NULL, /* 0 */ + NULL, /* 1 */ + MenuClickSettings, /* 2 */ + MenuClickSaveLoad, /* 3 */ + MenuClickMap, /* 4 */ + MenuClickTown, /* 5 */ + MenuClickSubsidies, /* 6 */ + MenuClickStations, /* 7 */ + MenuClickFinances, /* 8 */ + MenuClickCompany, /* 9 */ + MenuClickGraphs, /* 10 */ + MenuClickLeague, /* 11 */ + MenuClickIndustry, /* 12 */ + MenuClickShowTrains, /* 13 */ + MenuClickShowRoad, /* 14 */ + MenuClickShowShips, /* 15 */ + MenuClickShowAir, /* 16 */ + MenuClickScenMap, /* 17 */ + NULL, /* 18 */ + MenuClickBuildRail, /* 19 */ + MenuClickBuildRoad, /* 20 */ + MenuClickBuildWater, /* 21 */ + MenuClickBuildAir, /* 22 */ + MenuClickForest, /* 23 */ + MenuClickMusicWindow, /* 24 */ + MenuClickNewspaper, /* 25 */ + MenuClickHelp, /* 26 */ +}; + +static void MenuWndProc(Window *w, WindowEvent *e) +{ + switch (e->event) { + case WE_CREATE: + w->widget[0].right = w->width - 1; + break; + + case WE_PAINT: { + byte count = WP(w, menu_d).item_count; + byte sel = WP(w, menu_d).sel_index; + uint16 chk = WP(w, menu_d).checked_items; + StringID string = WP(w, menu_d).string_id; + byte dis = WP(w, menu_d).disabled_items; + + DrawWindowWidgets(w); + + int x = 1; + int y = 1; + + for (; count != 0; count--, string++, sel--) { + TextColour color = HasBit(dis, 0) ? TC_GREY : (sel == 0) ? TC_WHITE : TC_BLACK; + if (sel == 0) GfxFillRect(x, y, x + w->width - 3, y + 9, 0); + + if (HasBit(chk, 0)) DrawString(x + 2, y, STR_CHECKMARK, color); + DrawString(x + 2, y, string, color); + + y += 10; + chk >>= 1; + dis >>= 1; + } + } break; + + case WE_DESTROY: { + Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0); + v->RaiseWidget(WP(w, menu_d).main_button); + SetWindowDirty(v); + return; + } + + case WE_POPUPMENU_SELECT: { + int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y); + + if (index < 0) { + Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0); + if (GetWidgetFromPos(w2, e->we.popupmenu.pt.x - w2->left, e->we.popupmenu.pt.y - w2->top) == WP(w, menu_d).main_button) + index = WP(w, menu_d).sel_index; + } + + int action_id = WP(w, menu_d).action_id; + DeleteWindow(w); + + if (index >= 0) { + assert((uint)index <= lengthof(_menu_clicked_procs)); + _menu_clicked_procs[action_id](index); + } + + } break; + + case WE_POPUPMENU_OVER: { + int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y); + + if (index == -1 || index == WP(w, menu_d).sel_index) return; + + WP(w, menu_d).sel_index = index; + SetWindowDirty(w); + return; + } + } +} + +/* Dynamic widget length determined by toolbar-string length. + * See PopupMainToolbMenu en MenuWndProc */ +static const Widget _menu_widgets[] = { +{ WWT_PANEL, RESIZE_NONE, 14, 0, 0, 0, 0, 0x0, STR_NULL}, +{ WIDGETS_END}, +}; + + +/** + * Get the maximum length of a given string in a string-list. This is an + * implicit string-list where the ID's are consecutive + * @param base_string StringID of the first string in the list + * @param count amount of StringID's in the list + * @return the length of the longest string + */ +static int GetStringListMaxWidth(StringID base_string, byte count) +{ + char buffer[512]; + int width, max_width = 0; + + for (byte i = 0; i != count; i++) { + GetString(buffer, base_string + i, lastof(buffer)); + width = GetStringBoundingBox(buffer).width; + if (width > max_width) max_width = width; + } + + return max_width; +} + +/** + * Show a general dropdown menu. The positioning of the dropdown menu + * defaults to the left side of the parent_button, eg the button that caused + * this window to appear. The only exceptions are when the right side of this + * dropdown would fall outside the main toolbar window, in that case it is + * aligned with the toolbar's right side. + * Since the disable-mask is only 8 bits right now, these dropdowns are + * restricted to 8 items max if any bits of disabled_mask are active. + * @param w Pointer to a window this dropdown menu belongs to. Has no effect + * whatsoever, only graphically for positioning. + * @param parent_button The widget identifier of the button that was clicked for + * this dropdown. The created dropdown then knows what button to raise (button) on + * action and whose function to execute (action). + * It is possible to appoint another button for an action event by setting the + * upper 8 bits of this parameter. If non is set, action is presumed to be the same + * as button. So<br> + * button bits 0 - 7 - widget clicked to get dropdown + * action bits 8 - 15 - function of widget to execute on select (defaults to bits 0 - 7) + * @param base_string The first StringID shown in the dropdown list. All others are + * consecutive indeces from the language file. XXX - fix? Use ingame-string tables? + * @param item_count Number of strings in the list, see previous parameter + * @param disabled_mask Bitmask of disabled strings in the list + * @return Return a pointer to the newly created dropdown window */ +static Window *PopupMainToolbMenu(Window *w, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask) +{ + assert(disabled_mask == 0 || item_count <= 8); + w->LowerWidget(parent_button); + w->InvalidateWidget(parent_button); + + DeleteWindowById(WC_TOOLBAR_MENU, 0); + + /* Extend the dropdown toolbar to the longest string in the list */ + int width = max(GetStringListMaxWidth(base_string, item_count) + 6, 140); + int height = item_count * 10 + 2; + + Point pos = GetToolbarDropdownPos(parent_button, width, height); + + w = AllocateWindow(pos.x, pos.y, width, height, MenuWndProc, WC_TOOLBAR_MENU, _menu_widgets); + w->widget[0].bottom = item_count * 10 + 1; + w->flags4 &= ~WF_WHITE_BORDER_MASK; + + WP(w, menu_d).item_count = item_count; + WP(w, menu_d).sel_index = 0; + WP(w, menu_d).main_button = GB(parent_button, 0, 8); + WP(w, menu_d).action_id = (GB(parent_button, 8, 8) != 0) ? GB(parent_button, 8, 8) : parent_button; + WP(w, menu_d).string_id = base_string; + WP(w, menu_d).checked_items = 0; + WP(w, menu_d).disabled_items = disabled_mask; + + _popup_menu_active = true; + + SndPlayFx(SND_15_BEEP); + return w; +} + +/* --- Rendering/drawing the player menu --- */ +static int GetPlayerIndexFromMenu(int index) +{ + if (index >= 0) { + const Player *p; + + FOR_ALL_PLAYERS(p) { + if (p->is_active && --index < 0) return p->index; + } + } + return -1; +} + +static void UpdatePlayerMenuHeight(Window *w) +{ + byte num = ActivePlayerCount(); + + /* Increase one to fit in PlayerList in the menu when in network */ + if (_networking && WP(w, menu_d).main_button == 9) num++; + + if (WP(w, menu_d).item_count != num) { + WP(w, menu_d).item_count = num; + SetWindowDirty(w); + num = num * 10 + 2; + w->height = num; + w->widget[0].bottom = w->widget[0].top + num - 1; + w->top = GetToolbarDropdownPos(0, w->width, w->height).y; + SetWindowDirty(w); + } +} + +static void PlayerMenuWndProc(Window *w, WindowEvent *e) +{ + switch (e->event) { + case WE_PAINT: { + UpdatePlayerMenuHeight(w); + DrawWindowWidgets(w); + + int x = 1; + int y = 1; + int sel = WP(w, menu_d).sel_index; + int chk = WP(w, menu_d).checked_items; // let this mean gray items. + + /* 9 = playerlist */ + if (_networking && WP(w, menu_d).main_button == 9) { + if (sel == 0) { + GfxFillRect(x, y, x + 238, y + 9, 0); + } + DrawString(x + 19, y, STR_NETWORK_CLIENT_LIST, TC_FROMSTRING); + y += 10; + sel--; + } + + const Player *p; + FOR_ALL_PLAYERS(p) { + if (p->is_active) { + if (p->index == sel) { + GfxFillRect(x, y, x + 238, y + 9, 0); + } + + DrawPlayerIcon(p->index, x + 2, y + 1); + + SetDParam(0, p->index); + SetDParam(1, p->index); + + TextColour color = (p->index == sel) ? TC_WHITE : TC_BLACK; + if (chk & 1) color = TC_GREY; + DrawString(x + 19, y, STR_7021, color); + + y += 10; + } + chk >>= 1; + } + } break; + + case WE_DESTROY: { + Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0); + v->RaiseWidget(WP(w, menu_d).main_button); + SetWindowDirty(v); + return; + } + + case WE_POPUPMENU_SELECT: { + int index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y); + int action_id = WP(w, menu_d).action_id; + + /* We have a new entry at the top of the list of menu 9 when networking + * so keep that in count */ + if (_networking && WP(w, menu_d).main_button == 9) { + if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1; + } else { + index = GetPlayerIndexFromMenu(index); + } + + if (index < 0) { + Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0); + if (GetWidgetFromPos(w2, e->we.popupmenu.pt.x - w2->left, e->we.popupmenu.pt.y - w2->top) == WP(w, menu_d).main_button) + index = WP(w, menu_d).sel_index; + } + + DeleteWindow(w); + + if (index >= 0) { + assert(index >= 0 && index < 30); + _menu_clicked_procs[action_id](index); + } + } break; + + case WE_POPUPMENU_OVER: { + int index; + UpdatePlayerMenuHeight(w); + index = GetMenuItemIndex(w, e->we.popupmenu.pt.x, e->we.popupmenu.pt.y); + + /* We have a new entry at the top of the list of menu 9 when networking + * so keep that in count */ + if (_networking && WP(w, menu_d).main_button == 9) { + if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1; + } else { + index = GetPlayerIndexFromMenu(index); + } + + if (index == -1 || index == WP(w, menu_d).sel_index) return; + + WP(w, menu_d).sel_index = index; + SetWindowDirty(w); + return; + } + } +} + +static const Widget _player_menu_widgets[] = { +{ WWT_PANEL, RESIZE_NONE, 14, 0, 240, 0, 81, 0x0, STR_NULL}, +{ WIDGETS_END}, +}; + +static Window *PopupMainPlayerToolbMenu(Window *w, int main_button, int gray) +{ + w->LowerWidget(main_button); + w->InvalidateWidget(main_button); + + DeleteWindowById(WC_TOOLBAR_MENU, 0); + Point pos = GetToolbarDropdownPos(main_button, 241, 82); + w = AllocateWindow(pos.x, pos.y, 241, 82, PlayerMenuWndProc, WC_TOOLBAR_MENU, _player_menu_widgets); + w->flags4 &= ~WF_WHITE_BORDER_MASK; + WP(w, menu_d).item_count = 0; + WP(w, menu_d).sel_index = (_local_player != PLAYER_SPECTATOR) ? _local_player : GetPlayerIndexFromMenu(0); + if (_networking && main_button == 9) { + if (_local_player != PLAYER_SPECTATOR) { + WP(w, menu_d).sel_index++; + } else { + /* Select client list by default for spectators */ + WP(w, menu_d).sel_index = 0; + } + } + WP(w, menu_d).action_id = main_button; + WP(w, menu_d).main_button = main_button; + WP(w, menu_d).checked_items = gray; + WP(w, menu_d).disabled_items = 0; + _popup_menu_active = true; + SndPlayFx(SND_15_BEEP); + return w; +} + +/* --- Allocating the toolbar --- */ + Window *AllocateToolbar() { - return AllocateWindowDesc((_game_mode != GM_EDITOR) ? &_toolb_normal_desc : &_toolb_scen_desc); + /* Clean old GUI values */ + _last_built_railtype = RAILTYPE_RAIL; + _last_built_roadtype = ROADTYPE_ROAD; + + Window *w = AllocateWindowDesc((_game_mode != GM_EDITOR) ? &_toolb_normal_desc : &_toolb_scen_desc); + if (w == NULL) return NULL; + + CLRBITS(w->flags4, WF_WHITE_BORDER_MASK); + + w->SetWidgetDisabledState(0, _networking && !_network_server); // if not server, disable pause button + w->SetWidgetDisabledState(1, _networking); // if networking, disable fast-forward button + + /* 'w' is for sure a WC_MAIN_TOOLBAR */ + PositionMainToolbar(w); + + return w; } |