Mercurial > hg > openttd
changeset 8975:b053ca278abe draft
(svn r12767) -Codechange: merge all main toolbar related functions into a single file instead of scattering the functionality over several files.
author | rubidium <rubidium@openttd.org> |
---|---|
date | Fri, 18 Apr 2008 15:11:39 +0000 |
parents | 6b1769a870ad |
children | cbf8b2b89c08 |
files | src/gui.h src/main_gui.cpp src/misc.cpp src/toolbar_gui.cpp src/toolbar_gui.h |
diffstat | 5 files changed, 807 insertions(+), 787 deletions(-) [+] |
line wrap: on
line diff
--- a/src/gui.h +++ b/src/gui.h @@ -17,8 +17,6 @@ void CcBuildCanal(bool success, TileIndex tile, uint32 p1, uint32 p2); void HandleOnEditText(const char *str); void InitializeGUI(); -Window *PopupMainPlayerToolbMenu(Window *w, int main_button, int gray); -Window *PopupMainToolbMenu(Window *w, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask); /* settings_gui.cpp */ void ShowGameOptions();
--- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -4,7 +4,6 @@ #include "stdafx.h" #include "openttd.h" -#include "heightmap.h" #include "currency.h" #include "spritecache.h" #include "gui.h" @@ -14,28 +13,13 @@ #include "viewport_func.h" #include "command_func.h" #include "news_func.h" -#include "town.h" #include "console.h" -#include "signs_func.h" #include "waypoint.h" -#include "variables.h" -#include "train.h" -#include "roadveh.h" -#include "bridge_map.h" -#include "screenshot.h" #include "genworld.h" -#include "vehicle_gui.h" #include "transparency_gui.h" -#include "newgrf_config.h" -#include "rail_gui.h" -#include "road_gui.h" #include "date_func.h" #include "functions.h" -#include "vehicle_func.h" #include "sound_func.h" -#include "fios.h" -#include "terraform_gui.h" -#include "industry.h" #include "transparency.h" #include "strings_func.h" #include "zoom_func.h" @@ -45,6 +29,7 @@ #include "player_gui.h" #include "settings_type.h" #include "toolbar_gui.h" +#include "variables.h" #include "network/network.h" #include "network/network_data.h" @@ -58,8 +43,6 @@ static int _rename_id = 1; static int _rename_what = -1; -RailType _last_built_railtype; -RoadType _last_built_roadtype; bool _draw_bounding_boxes = false; @@ -142,167 +125,6 @@ if (success) SndPlayTileFx(SND_12_EXPLOSION, tile); } - -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(); -} - -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; - } - } -} - -static void MenuClickMap(int index) -{ - switch (index) { - case 0: ShowSmallMap(); break; - case 1: ShowExtraViewPortWindow(); break; - case 2: ShowSignList(); break; - } -} - -static void MenuClickTown(int index) -{ - ShowTownDirectory(); -} - -static void MenuClickScenMap(int index) -{ - switch (index) { - case 0: ShowSmallMap(); break; - case 1: ShowExtraViewPortWindow(); break; - case 2: ShowSignList(); break; - case 3: ShowTownDirectory(); break; - } -} - -static void MenuClickSubsidies(int index) -{ - ShowSubsidiesList(); -} - -static void MenuClickStations(int index) -{ - ShowPlayerStations((PlayerID)index); -} - -static void MenuClickFinances(int index) -{ - ShowPlayerFinances((PlayerID)index); -} - -static void MenuClickCompany(int index) -{ - if (_networking && index == 0) { - ShowClientList(); - } else { - if (_networking) index--; - ShowPlayerCompany((PlayerID)index); - } -} - -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; - } -} - -static void MenuClickLeague(int index) -{ - switch (index) { - case 0: ShowCompanyLeagueTable(); break; - case 1: ShowPerformanceRatingDetail(); break; - } -} - -static void MenuClickIndustry(int index) -{ - switch (index) { - case 0: ShowIndustryDirectory(); break; - case 1: ShowBuildIndustryWindow(); break; - } -} - -static void MenuClickShowTrains(int index) -{ - ShowVehicleListWindow((PlayerID)index, VEH_TRAIN); -} - -static void MenuClickShowRoad(int index) -{ - ShowVehicleListWindow((PlayerID)index, VEH_ROAD); -} - -static void MenuClickShowShips(int index) -{ - ShowVehicleListWindow((PlayerID)index, VEH_SHIP); -} - -static void MenuClickShowAir(int index) -{ - ShowVehicleListWindow((PlayerID)index, VEH_AIRCRAFT); -} - -static void MenuClickBuildRail(int index) -{ - _last_built_railtype = (RailType)index; - ShowBuildRailToolbar(_last_built_railtype, -1); -} - -static void MenuClickBuildRoad(int index) -{ - _last_built_roadtype = (RoadType)index; - ShowBuildRoadToolbar(_last_built_roadtype); -} - -static void MenuClickBuildWater(int index) -{ - ShowBuildDocksToolbar(); -} - -static void MenuClickBuildAir(int index) -{ - ShowBuildAirToolbar(); -} - #ifdef ENABLE_NETWORK void ShowNetworkGiveMoneyWindow(PlayerID player) { @@ -329,418 +151,6 @@ ShowQueryString(STR_WAYPOINT_RAW, STR_EDIT_WAYPOINT_NAME, 30, 180, NULL, CS_ALPHANUMERAL); } -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; - } -} - -static void MenuClickForest(int index) -{ - switch (index) { - case 0: ShowTerraformToolbar(); break; - case 1: ShowBuildTreesToolbar(); break; - case 2: SelectSignTool(); break; - } -} - -static void MenuClickMusicWindow(int index) -{ - ShowMusicWindow(); -} - -static void MenuClickNewspaper(int index) -{ - switch (index) { - case 0: ShowLastNewsMessage(); break; - case 1: ShowMessageOptions(); break; - case 2: ShowMessageHistory(); break; - } -} - -void MenuClickSmallScreenshot() -{ - SetScreenshotType(SC_VIEWPORT); -} - -void MenuClickWorldScreenshot() -{ - SetScreenshotType(SC_WORLD); -} - -static void MenuClickHelp(int index) -{ - switch (index) { - case 0: PlaceLandBlockInfo(); break; - case 2: IConsoleSwitch(); break; - case 3: MenuClickSmallScreenshot(); break; - case 4: MenuClickWorldScreenshot(); break; - case 5: ShowAboutWindow(); break; - } -} - - -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: { - int x, y; - - 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); - - x = 1; - 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); - int action_id; - - - 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; - } - - 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}, -}; - - -static const Widget _player_menu_widgets[] = { -{ WWT_PANEL, RESIZE_NONE, 14, 0, 240, 0, 81, 0x0, STR_NULL}, -{ WIDGETS_END}, -}; - - -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: { - int x,y; - byte sel; - TextColour color; - Player *p; - uint16 chk; - - UpdatePlayerMenuHeight(w); - DrawWindowWidgets(w); - - x = 1; - y = 1; - sel = WP(w, menu_d).sel_index; - 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--; - } - - 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); - - 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; - } - } -} - -/** 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; - byte i; - - max_width = 0; - for (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 */ - 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; -} - -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; -} /* Zooms a viewport in a window in or out */ /* No button handling or what so ever */ @@ -1196,14 +606,6 @@ Window *w = AllocateToolbar(); DoZoomInOutWindow(ZOOM_NONE, w); - 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); - /* Status bad only for normal games */ if (_game_mode == GM_EDITOR) return; @@ -1226,15 +628,3 @@ ScreenSizeChanged(); MarkWholeScreenDirty(); } - -void InitializeMainGui() -{ - /* Clean old GUI values */ - _last_built_railtype = RAILTYPE_RAIL; - _last_built_roadtype = ROADTYPE_ROAD; -} - - - - -
--- a/src/misc.cpp +++ b/src/misc.cpp @@ -44,7 +44,6 @@ void InitializeAirportGui(); void InitializeDockGui(); void InitializeIndustries(); -void InitializeMainGui(); void InitializeTowns(); void InitializeTrees(); void InitializeSigns(); @@ -93,7 +92,6 @@ InitializeCargoPackets(); InitializeIndustries(); InitializeBuildingCounts(); - InitializeMainGui(); InitializeNameMgr(); InitializeVehiclesGuiList();
--- 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); + +RailType _last_built_railtype; +RoadType _last_built_roadtype; -/* Returns the position where the toolbar wants the menu to appear. +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 @@ return pos; } +/* --- Pausing --- */ static void ToolbarPauseClick(Window *w) { @@ -63,168 +84,15 @@ 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); } -static void ToolbarSaveClick(Window *w) -{ - PopupMainToolbMenu(w, 3, STR_015C_SAVE_GAME, 4, 0); -} - -static void ToolbarMapClick(Window *w) -{ - PopupMainToolbMenu(w, 4, STR_02DE_MAP_OF_WORLD, 3, 0); -} - -static void ToolbarTownClick(Window *w) -{ - PopupMainToolbMenu(w, 5, STR_02BB_TOWN_DIRECTORY, 1, 0); -} - -static void ToolbarSubsidiesClick(Window *w) -{ - PopupMainToolbMenu(w, 6, STR_02DD_SUBSIDIES, 1, 0); -} - -static void ToolbarStationsClick(Window *w) -{ - PopupMainPlayerToolbMenu(w, 7, 0); -} - -static void ToolbarMoneyClick(Window *w) -{ - PopupMainPlayerToolbMenu(w, 8, 0); -} - -static void ToolbarPlayersClick(Window *w) -{ - PopupMainPlayerToolbMenu(w, 9, 0); -} - -static void ToolbarGraphsClick(Window *w) -{ - PopupMainToolbMenu(w, 10, STR_0154_OPERATING_PROFIT_GRAPH, 6, 0); -} - -static void ToolbarLeagueClick(Window *w) -{ - PopupMainToolbMenu(w, 11, STR_015A_COMPANY_LEAGUE_TABLE, 2, 0); -} - -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) -{ - const Vehicle *v; - int dis = -1; - - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_TRAIN && IsFrontEngine(v)) ClrBit(dis, v->owner); - } - PopupMainPlayerToolbMenu(w, 13, dis); -} - -static void ToolbarRoadClick(Window *w) -{ - const Vehicle *v; - int dis = -1; - - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_ROAD && IsRoadVehFront(v)) ClrBit(dis, v->owner); - } - PopupMainPlayerToolbMenu(w, 14, dis); -} - -static void ToolbarShipClick(Window *w) -{ - const Vehicle *v; - int dis = -1; - - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_SHIP) ClrBit(dis, v->owner); - } - PopupMainPlayerToolbMenu(w, 15, dis); -} - -static void ToolbarAirClick(Window *w) -{ - const Vehicle *v; - int dis = -1; - - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_AIRCRAFT) ClrBit(dis, v->owner); - } - PopupMainPlayerToolbMenu(w, 16, dis); -} - - -static void ToolbarZoomInClick(Window *w) -{ - if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) { - w->HandleButtonClick(17); - SndPlayFx(SND_15_BEEP); - } -} - -static void ToolbarZoomOutClick(Window *w) -{ - if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) { - w->HandleButtonClick(18); - SndPlayFx(SND_15_BEEP); - } -} - -static void ToolbarBuildRailClick(Window *w) -{ - const Player *p = GetPlayer(_local_player); - Window *w2 = PopupMainToolbMenu(w, 19, STR_1015_RAILROAD_CONSTRUCTION, RAILTYPE_END, ~p->avail_railtypes); - WP(w2, menu_d).sel_index = _last_built_railtype; -} - -static void ToolbarBuildRoadClick(Window *w) -{ - const Player *p = GetPlayer(_local_player); - /* The standard road button is *always* available */ - Window *w2 = PopupMainToolbMenu(w, 20, STR_180A_ROAD_CONSTRUCTION, 2, ~(p->avail_roadtypes | ROADTYPES_ROAD)); - WP(w2, menu_d).sel_index = _last_built_roadtype; -} - -static void ToolbarBuildWaterClick(Window *w) -{ - PopupMainToolbMenu(w, 21, STR_9800_DOCK_CONSTRUCTION, 1, 0); -} - -static void ToolbarBuildAirClick(Window *w) -{ - PopupMainToolbMenu(w, 22, STR_A01D_AIRPORT_CONSTRUCTION, 1, 0); -} - -static void ToolbarForestClick(Window *w) -{ - PopupMainToolbMenu(w, 23, STR_LANDSCAPING, 3, 0); -} - -static void ToolbarMusicClick(Window *w) -{ - PopupMainToolbMenu(w, 24, STR_01D3_SOUND_MUSIC, 1, 0); -} - -static void ToolbarNewspaperClick(Window *w) -{ - PopupMainToolbMenu(w, 25, STR_0200_LAST_MESSAGE_NEWS_REPORT, 3, 0); -} - -static void ToolbarHelpClick(Window *w) -{ - PopupMainToolbMenu(w, 26, STR_02D5_LAND_BLOCK_INFO, 6, 0); -} +/* --- Options button menu --- */ static void ToolbarOptionsClick(Window *w) { @@ -243,12 +111,412 @@ 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 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 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 = ~0; + + FOR_ALL_VEHICLES(v) { + if (v->type == veh && v->IsPrimaryVehicle()) { + ClrBit(dis, v->owner); + break; + } + } + 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) +{ + ToolbarVehicleClick(w, VEH_ROAD); +} + +static void MenuClickShowRoad(int index) +{ + ShowVehicleListWindow((PlayerID)index, VEH_ROAD); +} + +/* --- Ship button menu --- */ + +static void ToolbarShipClick(Window *w) +{ + ToolbarVehicleClick(w, VEH_SHIP); +} + +static void MenuClickShowShips(int index) +{ + ShowVehicleListWindow((PlayerID)index, VEH_SHIP); +} + +/* --- Aircraft button menu --- */ + +static void ToolbarAirClick(Window *w) +{ + ToolbarVehicleClick(w, VEH_AIRCRAFT); +} + +static void MenuClickShowAir(int index) +{ + ShowVehicleListWindow((PlayerID)index, VEH_AIRCRAFT); +} + +/* --- Zoom in button --- */ + +static void ToolbarZoomInClick(Window *w) +{ + if (DoZoomInOutWindow(ZOOM_IN, FindWindowById(WC_MAIN_WINDOW, 0))) { + w->HandleButtonClick(17); + SndPlayFx(SND_15_BEEP); + } +} + +/* --- Zoom out button --- */ + +static void ToolbarZoomOutClick(Window *w) +{ + if (DoZoomInOutWindow(ZOOM_OUT, FindWindowById(WC_MAIN_WINDOW, 0))) { + w->HandleButtonClick(18); + SndPlayFx(SND_15_BEEP); + } +} + +/* --- Rail button menu --- */ + +static void ToolbarBuildRailClick(Window *w) +{ + const Player *p = GetPlayer(_local_player); + Window *w2 = PopupMainToolbMenu(w, 19, STR_1015_RAILROAD_CONSTRUCTION, RAILTYPE_END, ~p->avail_railtypes); + 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); + /* The standard road button is *always* available */ + Window *w2 = PopupMainToolbMenu(w, 20, STR_180A_ROAD_CONSTRUCTION, 2, ~(p->avail_roadtypes | ROADTYPES_ROAD)); + 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 MenuClickSmallScreenshot() +{ + SetScreenshotType(SC_VIEWPORT); +} + +static void MenuClickWorldScreenshot() +{ + SetScreenshotType(SC_WORLD); +} + +static void MenuClickHelp(int index) +{ + 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 @@ } +/* --- Toolbar handling for the 'normal' case */ + typedef void ToolbarButtonProc(Window *w); static ToolbarButtonProc * const _toolbar_button_procs[] = { @@ -357,7 +627,7 @@ ToolbarTownClick, ToolbarSubsidiesClick, ToolbarStationsClick, - ToolbarMoneyClick, + ToolbarFinancesClick, ToolbarPlayersClick, ToolbarGraphsClick, ToolbarLeagueClick, @@ -378,11 +648,7 @@ 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 @@ 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 @@ }; +/* --- Toolbar handling for the scenario editor */ + static ToolbarButtonProc * const _scen_toolbar_button_procs[] = { ToolbarPauseClick, ToolbarFastForwardClick, @@ -591,7 +858,7 @@ ToolbarHelpClick, }; -void ScenEditToolbarWndProc(Window *w, WindowEvent *e) +static void ScenEditToolbarWndProc(Window *w, WindowEvent *e) { switch (e->event) { case WE_PAINT: @@ -794,7 +1061,375 @@ 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; }