diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1217,14 +1217,6 @@ typedef void ClientList_Action_Proc(byte // Max 10 actions per client #define MAX_CLIENTLIST_ACTION 10 -// Some standard bullshit.. defines variables ;) -static void ClientListWndProc(Window *w, WindowEvent *e); -static void ClientListPopupWndProc(Window *w, WindowEvent *e); -static byte _selected_clientlist_item = 255; -static byte _selected_clientlist_y = 0; -static char _clientlist_action[MAX_CLIENTLIST_ACTION][50]; -static ClientList_Action_Proc *_clientlist_proc[MAX_CLIENTLIST_ACTION]; - enum { CLNWND_OFFSET = 16, CLNWND_ROWSIZE = 10 @@ -1249,7 +1241,7 @@ static WindowDesc _client_list_desc = { WC_CLIENT_LIST, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _client_list_widgets, - ClientListWndProc + NULL }; // Finds the Xth client-info that is active @@ -1321,267 +1313,271 @@ static void ClientList_None(byte client_ -/** - * An action is clicked! What do we do? - */ -static void HandleClientListPopupClick(byte index, byte clientno) -{ - /* A click on the Popup of the ClientList.. handle the command */ - if (index < MAX_CLIENTLIST_ACTION && _clientlist_proc[index] != NULL) { - _clientlist_proc[index](clientno); - } -} +struct NetworkClientListPopupWindow : Window { + int sel_index; + int client_no; + char action[MAX_CLIENTLIST_ACTION][50]; + ClientList_Action_Proc *proc[MAX_CLIENTLIST_ACTION]; + + NetworkClientListPopupWindow(int x, int y, const Widget *widgets, int client_no) : + Window(x, y, 150, 100, NULL, WC_TOOLBAR_MENU, widgets), + sel_index(0), client_no(client_no) + { + /* + * Fill the actions this client has. + * Watch is, max 50 chars long! + */ + + const NetworkClientInfo *ci = NetworkFindClientInfo(client_no); + + int i = 0; + if (_network_own_client_index != ci->client_index) { + GetString(this->action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, lastof(this->action[i])); + this->proc[i++] = &ClientList_SpeakToClient; + } + + if (IsValidPlayer(ci->client_playas) || ci->client_playas == PLAYER_SPECTATOR) { + GetString(this->action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, lastof(this->action[i])); + this->proc[i++] = &ClientList_SpeakToCompany; + } + GetString(this->action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, lastof(this->action[i])); + this->proc[i++] = &ClientList_SpeakToAll; -/** - * Finds the amount of clients and set the height correct - */ -static bool CheckClientListHeight(Window *w) -{ - int num = 0; - const NetworkClientInfo *ci; + if (_network_own_client_index != ci->client_index) { + /* We are no spectator and the player we want to give money to is no spectator and money gifts are allowed */ + if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas) && _patches.give_money) { + GetString(this->action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(this->action[i])); + this->proc[i++] = &ClientList_GiveMoney; + } + } + + /* A server can kick clients (but not himself) */ + if (_network_server && _network_own_client_index != ci->client_index) { + GetString(this->action[i], STR_NETWORK_CLIENTLIST_KICK, lastof(this->action[i])); + this->proc[i++] = &ClientList_Kick; - /* Should be replaced with a loop through all clients */ - FOR_ALL_ACTIVE_CLIENT_INFOS(ci) { - num++; + sprintf(this->action[i],"Ban"); // XXX GetString? + this->proc[i++] = &ClientList_Ban; + } + + if (i == 0) { + GetString(this->action[i], STR_NETWORK_CLIENTLIST_NONE, lastof(this->action[i])); + this->proc[i++] = &ClientList_None; + } + + /* Calculate the height */ + int h = ClientListPopupHeight(); + + /* Allocate the popup */ + this->widget[0].bottom = this->widget[0].top + h; + this->widget[0].right = this->widget[0].left + 150; + + this->flags4 &= ~WF_WHITE_BORDER_MASK; + + this->FindWindowPlacementAndResize(150, h + 1); } - num *= CLNWND_ROWSIZE; - - /* If height is changed */ - if (w->height != CLNWND_OFFSET + num + 1) { - // XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1) - w->SetDirty(); - w->widget[3].bottom = w->widget[3].top + num + 2; - w->height = CLNWND_OFFSET + num + 1; - w->SetDirty(); - return false; + /** + * An action is clicked! What do we do? + */ + void HandleClientListPopupClick(byte index) + { + /* A click on the Popup of the ClientList.. handle the command */ + if (index < MAX_CLIENTLIST_ACTION && this->proc[index] != NULL) { + this->proc[index](this->client_no); + } } - return true; -} + + /** + * Finds the amount of actions in the popup and set the height correct + */ + uint ClientListPopupHeight() + { + int num = 0; -/** - * Finds the amount of actions in the popup and set the height correct - */ -static uint ClientListPopupHeight() -{ - int num = 0; + // Find the amount of actions + for (int i = 0; i < MAX_CLIENTLIST_ACTION; i++) { + if (this->action[i][0] == '\0') continue; + if (this->proc[i] == NULL) continue; + num++; + } - // Find the amount of actions - for (int i = 0; i < MAX_CLIENTLIST_ACTION; i++) { - if (_clientlist_action[i][0] == '\0') continue; - if (_clientlist_proc[i] == NULL) continue; - num++; + num *= CLNWND_ROWSIZE; + + return num + 1; } - num *= CLNWND_ROWSIZE; + + virtual void OnPaint() + { + DrawWindowWidgets(this); + + /* Draw the actions */ + int sel = this->sel_index; + int y = 1; + for (int i = 0; i < MAX_CLIENTLIST_ACTION; i++, y += CLNWND_ROWSIZE) { + if (this->action[i][0] == '\0') continue; + if (this->proc[i] == NULL) continue; + + TextColour colour; + if (sel-- == 0) { // Selected item, highlight it + GfxFillRect(1, y, 150 - 2, y + CLNWND_ROWSIZE - 1, 0); + colour = TC_WHITE; + } else { + colour = TC_BLACK; + } - return num + 1; -} + DoDrawString(this->action[i], 4, y, colour); + } + } + + virtual void OnMouseLoop() + { + /* We selected an action */ + int index = (_cursor.pos.y - this->top) / CLNWND_ROWSIZE; + + if (_left_button_down) { + if (index == -1 || index == this->sel_index) return; + + this->sel_index = index; + this->SetDirty(); + } else { + if (index >= 0 && _cursor.pos.y >= this->top) { + HandleClientListPopupClick(index); + } + + DeleteWindowById(WC_TOOLBAR_MENU, 0); + } + } +}; /** * Show the popup (action list) */ -static Window *PopupClientList(Window *w, int client_no, int x, int y) +static void PopupClientList(int client_no, int x, int y) { - int i; - const NetworkClientInfo *ci; DeleteWindowById(WC_TOOLBAR_MENU, 0); - /* Clean the current actions */ - for (i = 0; i < MAX_CLIENTLIST_ACTION; i++) { - _clientlist_action[i][0] = '\0'; - _clientlist_proc[i] = NULL; - } - - /* - * Fill the actions this client has. - * Watch is, max 50 chars long! - */ - - ci = NetworkFindClientInfo(client_no); - if (ci == NULL) return NULL; - - i = 0; - if (_network_own_client_index != ci->client_index) { - GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, lastof(_clientlist_action[i])); - _clientlist_proc[i++] = &ClientList_SpeakToClient; - } - - if (IsValidPlayer(ci->client_playas) || ci->client_playas == PLAYER_SPECTATOR) { - GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, lastof(_clientlist_action[i])); - _clientlist_proc[i++] = &ClientList_SpeakToCompany; - } - GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, lastof(_clientlist_action[i])); - _clientlist_proc[i++] = &ClientList_SpeakToAll; - - if (_network_own_client_index != ci->client_index) { - /* We are no spectator and the player we want to give money to is no spectator and money gifts are allowed */ - if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas) && _patches.give_money) { - GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(_clientlist_action[i])); - _clientlist_proc[i++] = &ClientList_GiveMoney; - } - } - - /* A server can kick clients (but not himself) */ - if (_network_server && _network_own_client_index != ci->client_index) { - GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_KICK, lastof(_clientlist_action[i])); - _clientlist_proc[i++] = &ClientList_Kick; - - sprintf(_clientlist_action[i],"Ban"); // XXX GetString? - _clientlist_proc[i++] = &ClientList_Ban; - } - - if (i == 0) { - GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_NONE, lastof(_clientlist_action[i])); - _clientlist_proc[i++] = &ClientList_None; - } - - /* Calculate the height */ - int h = ClientListPopupHeight(); + if (NetworkFindClientInfo(client_no) == NULL) return; - /* Allocate the popup */ - w = new Window(x, y, 150, h + 1, ClientListPopupWndProc, WC_TOOLBAR_MENU, _client_list_popup_widgets); - w->widget[0].bottom = w->widget[0].top + h; - w->widget[0].right = w->widget[0].left + 150; - - w->flags4 &= ~WF_WHITE_BORDER_MASK; - WP(w, menu_d).item_count = 0; - // Save our client - WP(w, menu_d).main_button = client_no; - WP(w, menu_d).sel_index = 0; - - return w; -} - -/** Main handle for the client popup list - * uses menu_d WP macro */ -static void ClientListPopupWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - DrawWindowWidgets(w); - - /* Draw the actions */ - int sel = WP(w, menu_d).sel_index; - int y = 1; - for (int i = 0; i < MAX_CLIENTLIST_ACTION; i++, y += CLNWND_ROWSIZE) { - if (_clientlist_action[i][0] == '\0') continue; - if (_clientlist_proc[i] == NULL) continue; - - TextColour colour; - if (sel-- == 0) { // Selected item, highlight it - GfxFillRect(1, y, 150 - 2, y + CLNWND_ROWSIZE - 1, 0); - colour = TC_WHITE; - } else { - colour = TC_BLACK; - } - - DoDrawString(_clientlist_action[i], 4, y, colour); - } - } break; - - case WE_MOUSELOOP: { - /* We selected an action */ - int index = (_cursor.pos.y - w->top) / CLNWND_ROWSIZE; - - if (_left_button_down) { - if (index == -1 || index == WP(w, menu_d).sel_index) return; - - WP(w, menu_d).sel_index = index; - w->SetDirty(); - } else { - if (index >= 0 && _cursor.pos.y >= w->top) { - HandleClientListPopupClick(index, WP(w, menu_d).main_button); - } - - DeleteWindowById(WC_TOOLBAR_MENU, 0); - } - } break; - } + new NetworkClientListPopupWindow(x, y, _client_list_popup_widgets, client_no); } /** * Main handle for clientlist */ -static void ClientListWndProc(Window *w, WindowEvent *e) +struct NetworkClientListWindow : Window { - switch (e->event) { - case WE_PAINT: { - NetworkClientInfo *ci; - int i = 0; + byte selected_item; + byte selected_y; - /* Check if we need to reset the height */ - if (!CheckClientListHeight(w)) break; - - DrawWindowWidgets(w); - - int y = CLNWND_OFFSET; + NetworkClientListWindow(const WindowDesc *desc, WindowNumber window_number) : + Window(desc, window_number), + selected_item(0), + selected_y(255) + { + this->FindWindowPlacementAndResize(desc); + } - FOR_ALL_ACTIVE_CLIENT_INFOS(ci) { - TextColour colour; - if (_selected_clientlist_item == i++) { // Selected item, highlight it - GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0); - colour = TC_WHITE; - } else { - colour = TC_BLACK; - } + /** + * Finds the amount of clients and set the height correct + */ + bool CheckClientListHeight() + { + int num = 0; + const NetworkClientInfo *ci; - if (ci->client_index == NETWORK_SERVER_INDEX) { - DrawString(4, y, STR_NETWORK_SERVER, colour); - } else { - DrawString(4, y, STR_NETWORK_CLIENT, colour); - } + /* Should be replaced with a loop through all clients */ + FOR_ALL_ACTIVE_CLIENT_INFOS(ci) { + num++; + } + + num *= CLNWND_ROWSIZE; - /* Filter out spectators */ - if (IsValidPlayer(ci->client_playas)) DrawPlayerIcon(ci->client_playas, 64, y + 1); - - DoDrawString(ci->client_name, 81, y, colour); - - y += CLNWND_ROWSIZE; - } - } break; - - case WE_CLICK: - /* Show the popup with option */ - if (_selected_clientlist_item != 255) { - PopupClientList(w, _selected_clientlist_item, e->we.click.pt.x + w->left, e->we.click.pt.y + w->top); - } - break; + /* If height is changed */ + if (this->height != CLNWND_OFFSET + num + 1) { + // XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1) + this->SetDirty(); + this->widget[3].bottom = this->widget[3].top + num + 2; + this->height = CLNWND_OFFSET + num + 1; + this->SetDirty(); + return false; + } + return true; + } - case WE_MOUSEOVER: - /* -1 means we left the current window */ - if (e->we.mouseover.pt.y == -1) { - _selected_clientlist_y = 0; - _selected_clientlist_item = 255; - w->SetDirty(); - break; - } - /* It did not change.. no update! */ - if (e->we.mouseover.pt.y == _selected_clientlist_y) break; + virtual void OnPaint() + { + NetworkClientInfo *ci; + int i = 0; + + /* Check if we need to reset the height */ + if (!this->CheckClientListHeight()) return; + + DrawWindowWidgets(this); - /* Find the new selected item (if any) */ - _selected_clientlist_y = e->we.mouseover.pt.y; - if (e->we.mouseover.pt.y > CLNWND_OFFSET) { - _selected_clientlist_item = (e->we.mouseover.pt.y - CLNWND_OFFSET) / CLNWND_ROWSIZE; + int y = CLNWND_OFFSET; + + FOR_ALL_ACTIVE_CLIENT_INFOS(ci) { + TextColour colour; + if (this->selected_item == i++) { // Selected item, highlight it + GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0); + colour = TC_WHITE; } else { - _selected_clientlist_item = 255; + colour = TC_BLACK; } - /* Repaint */ - w->SetDirty(); - break; + if (ci->client_index == NETWORK_SERVER_INDEX) { + DrawString(4, y, STR_NETWORK_SERVER, colour); + } else { + DrawString(4, y, STR_NETWORK_CLIENT, colour); + } + + /* Filter out spectators */ + if (IsValidPlayer(ci->client_playas)) DrawPlayerIcon(ci->client_playas, 64, y + 1); + + DoDrawString(ci->client_name, 81, y, colour); + + y += CLNWND_ROWSIZE; + } + } + + virtual void OnClick(Point pt, int widget) + { + /* Show the popup with option */ + if (this->selected_item != 255) { + PopupClientList(this->selected_item, pt.x + this->left, pt.y + this->top); + } + } - case WE_DESTROY: case WE_CREATE: - /* When created or destroyed, data is reset */ - _selected_clientlist_item = 255; - _selected_clientlist_y = 0; - break; + virtual void OnMouseOver(Point pt, int widget) + { + /* -1 means we left the current window */ + if (pt.y == -1) { + this->selected_y = 0; + this->selected_item = 255; + this->SetDirty(); + return; + } + /* It did not change.. no update! */ + if (pt.y == this->selected_y) return; + + /* Find the new selected item (if any) */ + this->selected_y = pt.y; + if (pt.y > CLNWND_OFFSET) { + this->selected_item = (pt.y - CLNWND_OFFSET) / CLNWND_ROWSIZE; + } else { + this->selected_item = 255; + } + + /* Repaint */ + this->SetDirty(); } -} +}; void ShowClientList() { - AllocateWindowDescFront(&_client_list_desc, 0); + AllocateWindowDescFront(&_client_list_desc, 0); } diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -78,13 +78,13 @@ static Point GetToolbarDropdownPos(uint1 } /** - * In a window with menu_d custom extension, retrieve the menu item number from a position + * Retrieve the menu item number from a position * @param w Window holding the menu items * @param x X coordinate of the position * @param y Y coordinate of the position * @return Index number of the menu item, or \c -1 if no valid selection under position */ -static int GetMenuItemIndex(const Window *w) +static int GetMenuItemIndex(const Window *w, int item_count, int disabled_items) { int x = _cursor.pos.x; int y = _cursor.pos.y; @@ -92,8 +92,8 @@ static int GetMenuItemIndex(const Window if ((x -= w->left) >= 0 && x < w->width && (y -= w->top + 1) >= 0) { y /= 10; - if (y < WP(w, const menu_d).item_count && - !HasBit(WP(w, const menu_d).disabled_items, y)) { + if (y < item_count && + !HasBit(disabled_items, y)) { return y; } } @@ -1113,71 +1113,77 @@ static MenuClickedProc * const _menu_cli MenuClickHelp, /* 26 */ }; -static void MenuWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_CREATE: - w->widget[0].right = w->width - 1; - break; +struct ToolbarMenuWindow : Window { + int item_count; + int sel_index; + int main_button; + int action_id; + int checked_items; + int disabled_items; + StringID base_string; - 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; + ToolbarMenuWindow(int x, int y, int width, int height, const Widget *widgets, int item_count, + int sel_index, int parent_button, StringID base_string, int checked_items, + int disabled_mask) : + Window(x, y, width, height, NULL, WC_TOOLBAR_MENU, widgets), + item_count(item_count), sel_index(sel_index), main_button(GB(parent_button, 0, 8)), + action_id((GB(parent_button, 8, 8) != 0) ? GB(parent_button, 8, 8) : parent_button), + checked_items(checked_items), disabled_items(disabled_items), base_string(base_string) + { + this->widget[0].bottom = item_count * 10 + 1; + this->widget[0].right = this->width - 1; + this->flags4 &= ~WF_WHITE_BORDER_MASK; - DrawWindowWidgets(w); - - int x = 1; - int y = 1; + this->FindWindowPlacementAndResize(width, height); + } - 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); + ~ToolbarMenuWindow() + { + Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0); + w->RaiseWidget(this->main_button); + w->SetDirty(); + } - if (HasBit(chk, 0)) DrawString(x + 2, y, STR_CHECKMARK, color); - DrawString(x + 2, y, string, color); + virtual void OnPaint() + { + DrawWindowWidgets(this); + + for (int i = 0, x = 1, y = 1; i != this->item_count; i++, y += 10) { + TextColour color = HasBit(this->disabled_items, i) ? TC_GREY : (this->sel_index == i) ? TC_WHITE : TC_BLACK; + if (this->sel_index == i) GfxFillRect(x, y, x + this->width - 3, y + 9, 0); - y += 10; - chk >>= 1; - dis >>= 1; - } - } break; + if (HasBit(this->checked_items, i)) DrawString(x + 2, y, STR_CHECKMARK, color); + DrawString(x + 2, y, this->base_string + i, color); + } + } + + virtual void OnMouseLoop() + { + int index = GetMenuItemIndex(this, this->item_count, this->disabled_items); - case WE_DESTROY: { - Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0); - v->RaiseWidget(WP(w, menu_d).main_button); - v->SetDirty(); - return; + if (_left_button_down) { + if (index == -1 || index == this->sel_index) return; + + this->sel_index = index; + this->SetDirty(); + } else { + if (index < 0) { + Window *w = FindWindowById(WC_MAIN_TOOLBAR,0); + if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) == this->main_button) { + index = this->sel_index; + } } - case WE_MOUSELOOP: { - int index = GetMenuItemIndex(w); - - if (_left_button_down) { - if (index == -1 || index == WP(w, menu_d).sel_index) return; + int action_id = this->action_id; + delete this; - WP(w, menu_d).sel_index = index; - w->SetDirty(); - } else { - if (index < 0) { - Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0); - if (GetWidgetFromPos(w2, _cursor.pos.x - w2->left, _cursor.pos.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; - delete w; - - if (index >= 0) { - assert((uint)index <= lengthof(_menu_clicked_procs)); - _menu_clicked_procs[action_id](index); - } + if (index >= 0) { + assert((uint)index <= lengthof(_menu_clicked_procs)); + _menu_clicked_procs[action_id](index); } - } break; + } } -} +}; /* Dynamic widget length determined by toolbar-string length. * See PopupMainToolbMenu en MenuWndProc */ @@ -1248,17 +1254,7 @@ static void PopupMainToolbMenu(Window *p Point pos = GetToolbarDropdownPos(parent_button, width, height); - Window *w = new Window(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 = sel_index; - 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 = checked_items; - WP(w, menu_d).disabled_items = disabled_mask; + new ToolbarMenuWindow(pos.x, pos.y, width, height, _menu_widgets, item_count, sel_index, parent_button, base_string, checked_items, disabled_mask); SndPlayFx(SND_15_BEEP); } @@ -1276,119 +1272,141 @@ static int GetPlayerIndexFromMenu(int in 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++; +struct ToolbarPlayerMenuWindow : Window { + int item_count; + int sel_index; + int main_button; + int action_id; + int gray_items; - if (WP(w, menu_d).item_count != num) { - WP(w, menu_d).item_count = num; - w->SetDirty(); - 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; + ToolbarPlayerMenuWindow(int x, int y, int width, int height, const Widget *widgets, int main_button, int gray) : + Window(x, y, width, height, NULL, WC_TOOLBAR_MENU, widgets), + item_count(0), main_button(main_button), action_id(main_button), gray_items(gray) + { + this->flags4 &= ~WF_WHITE_BORDER_MASK; + this->sel_index = (_local_player != PLAYER_SPECTATOR) ? _local_player : GetPlayerIndexFromMenu(0); + if (_networking && main_button == 9) { + if (_local_player != PLAYER_SPECTATOR) { + this->sel_index++; + } else { + /* Select client list by default for spectators */ + this->sel_index = 0; + } + } + } + + ~ToolbarPlayerMenuWindow() + { + Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0); + w->RaiseWidget(this->main_button); w->SetDirty(); } -} + + void UpdatePlayerMenuHeight() + { + byte num = ActivePlayerCount(); + + /* Increase one to fit in PlayerList in the menu when in network */ + if (_networking && this->main_button == 9) num++; -static void PlayerMenuWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - UpdatePlayerMenuHeight(w); - DrawWindowWidgets(w); + if (this->item_count != num) { + this->item_count = num; + this->SetDirty(); + num = num * 10 + 2; + this->height = num; + this->widget[0].bottom = this->widget[0].top + num - 1; + this->top = GetToolbarDropdownPos(0, this->width, this->height).y; + this->SetDirty(); + } + } - 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. + virtual void OnPaint() + { + this->UpdatePlayerMenuHeight(); + DrawWindowWidgets(this); + + int x = 1; + int y = 1; + int sel = this->sel_index; + int gray = this->gray_items; - /* 9 = playerlist */ - if (_networking && WP(w, menu_d).main_button == 9) { - if (sel == 0) { + /* 9 = playerlist */ + if (_networking && this->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); } - DrawString(x + 19, y, STR_NETWORK_CLIENT_LIST, TC_FROMSTRING); + + 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 (gray & 1) color = TC_GREY; + DrawString(x + 19, y, STR_7021, color); + y += 10; - sel--; + } + gray >>= 1; + } + } + + virtual void OnMouseLoop() + { + int index = GetMenuItemIndex(this, this->item_count, 0); + + if (_left_button_down) { + this->UpdatePlayerMenuHeight(); + /* We have a new entry at the top of the list of menu 9 when networking + * so keep that in count */ + if (_networking && this->main_button == 9) { + if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1; + } else { + index = GetPlayerIndexFromMenu(index); } - 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); + if (index == -1 || index == this->sel_index) return; - y += 10; - } - chk >>= 1; - } - } break; - - case WE_DESTROY: { - Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0); - v->RaiseWidget(WP(w, menu_d).main_button); - v->SetDirty(); - return; - } - - case WE_MOUSELOOP: { - int index = GetMenuItemIndex(w); + this->sel_index = index; + this->SetDirty(); + } else { + int action_id = this->action_id; - if (_left_button_down) { - UpdatePlayerMenuHeight(w); - /* 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; - w->SetDirty(); + /* We have a new entry at the top of the list of menu 9 when networking + * so keep that in count */ + if (_networking && this->main_button == 9) { + if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1; } else { - int action_id = WP(w, menu_d).action_id; + index = GetPlayerIndexFromMenu(index); + } - /* 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, _cursor.pos.x - w2->left, _cursor.pos.y - w2->top) == WP(w, menu_d).main_button) - index = WP(w, menu_d).sel_index; - } - - delete w; - - if (index >= 0) { - assert(index >= 0 && index < 30); - _menu_clicked_procs[action_id](index); + if (index < 0) { + Window *w = FindWindowById(WC_MAIN_TOOLBAR,0); + if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) == this->main_button) { + index = this->sel_index; } } - } break; + + delete this; + + if (index >= 0) { + assert(index >= 0 && index < 30); + _menu_clicked_procs[action_id](index); + } + } } -} +}; static const Widget _player_menu_widgets[] = { { WWT_PANEL, RESIZE_NONE, 14, 0, 240, 0, 81, 0x0, STR_NULL}, @@ -1402,22 +1420,7 @@ static void PopupMainPlayerToolbMenu(Win DeleteWindowById(WC_TOOLBAR_MENU, 0); Point pos = GetToolbarDropdownPos(main_button, 241, 82); - Window *w = new Window(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; + new ToolbarPlayerMenuWindow(pos.x, pos.y, 241, 82, _player_menu_widgets, main_button, gray); SndPlayFx(SND_15_BEEP); } diff --git a/src/window_gui.h b/src/window_gui.h --- a/src/window_gui.h +++ b/src/window_gui.h @@ -515,17 +515,6 @@ public: /*** End of the event handling ***/ }; -struct menu_d { - byte item_count; ///< follow_vehicle - byte sel_index; ///< scrollpos_x - byte main_button; ///< scrollpos_y - byte action_id; - StringID string_id; ///< unk30 - uint16 checked_items; ///< unk32 - byte disabled_items; -}; -assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(menu_d)); - struct def_d { int16 data_1, data_2, data_3; };