mirror of https://github.com/OpenTTD/OpenTTD
(svn r13108) -Codechange: make a Window subclass of the main toolbars sub menus.
parent
6a50687bdc
commit
b08d728ac9
|
@ -1217,14 +1217,6 @@ typedef void ClientList_Action_Proc(byte client_no);
|
||||||
// Max 10 actions per client
|
// Max 10 actions per client
|
||||||
#define MAX_CLIENTLIST_ACTION 10
|
#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 {
|
enum {
|
||||||
CLNWND_OFFSET = 16,
|
CLNWND_OFFSET = 16,
|
||||||
CLNWND_ROWSIZE = 10
|
CLNWND_ROWSIZE = 10
|
||||||
|
@ -1249,7 +1241,7 @@ static WindowDesc _client_list_desc = {
|
||||||
WC_CLIENT_LIST, WC_NONE,
|
WC_CLIENT_LIST, WC_NONE,
|
||||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
|
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
|
||||||
_client_list_widgets,
|
_client_list_widgets,
|
||||||
ClientListWndProc
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
// Finds the Xth client-info that is active
|
// Finds the Xth client-info that is active
|
||||||
|
@ -1321,21 +1313,176 @@ static void ClientList_None(byte client_no)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An action is clicked! What do we do?
|
* An action is clicked! What do we do?
|
||||||
*/
|
*/
|
||||||
static void HandleClientListPopupClick(byte index, byte clientno)
|
void HandleClientListPopupClick(byte index)
|
||||||
{
|
{
|
||||||
/* A click on the Popup of the ClientList.. handle the command */
|
/* A click on the Popup of the ClientList.. handle the command */
|
||||||
if (index < MAX_CLIENTLIST_ACTION && _clientlist_proc[index] != NULL) {
|
if (index < MAX_CLIENTLIST_ACTION && this->proc[index] != NULL) {
|
||||||
_clientlist_proc[index](clientno);
|
this->proc[index](this->client_no);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the amount of actions in the popup and set the height correct
|
||||||
|
*/
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
num *= CLNWND_ROWSIZE;
|
||||||
|
|
||||||
|
return num + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 void PopupClientList(int client_no, int x, int y)
|
||||||
|
{
|
||||||
|
DeleteWindowById(WC_TOOLBAR_MENU, 0);
|
||||||
|
|
||||||
|
if (NetworkFindClientInfo(client_no) == NULL) return;
|
||||||
|
|
||||||
|
new NetworkClientListPopupWindow(x, y, _client_list_popup_widgets, client_no);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main handle for clientlist
|
||||||
|
*/
|
||||||
|
struct NetworkClientListWindow : Window
|
||||||
|
{
|
||||||
|
byte selected_item;
|
||||||
|
byte selected_y;
|
||||||
|
|
||||||
|
NetworkClientListWindow(const WindowDesc *desc, WindowNumber window_number) :
|
||||||
|
Window(desc, window_number),
|
||||||
|
selected_item(0),
|
||||||
|
selected_y(255)
|
||||||
|
{
|
||||||
|
this->FindWindowPlacementAndResize(desc);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the amount of clients and set the height correct
|
* Finds the amount of clients and set the height correct
|
||||||
*/
|
*/
|
||||||
static bool CheckClientListHeight(Window *w)
|
bool CheckClientListHeight()
|
||||||
{
|
{
|
||||||
int num = 0;
|
int num = 0;
|
||||||
const NetworkClientInfo *ci;
|
const NetworkClientInfo *ci;
|
||||||
|
@ -1348,178 +1495,32 @@ static bool CheckClientListHeight(Window *w)
|
||||||
num *= CLNWND_ROWSIZE;
|
num *= CLNWND_ROWSIZE;
|
||||||
|
|
||||||
/* If height is changed */
|
/* If height is changed */
|
||||||
if (w->height != CLNWND_OFFSET + num + 1) {
|
if (this->height != CLNWND_OFFSET + num + 1) {
|
||||||
// XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1)
|
// XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1)
|
||||||
w->SetDirty();
|
this->SetDirty();
|
||||||
w->widget[3].bottom = w->widget[3].top + num + 2;
|
this->widget[3].bottom = this->widget[3].top + num + 2;
|
||||||
w->height = CLNWND_OFFSET + num + 1;
|
this->height = CLNWND_OFFSET + num + 1;
|
||||||
w->SetDirty();
|
this->SetDirty();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
virtual void OnPaint()
|
||||||
* 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 (_clientlist_action[i][0] == '\0') continue;
|
|
||||||
if (_clientlist_proc[i] == NULL) continue;
|
|
||||||
num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
num *= CLNWND_ROWSIZE;
|
|
||||||
|
|
||||||
return num + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the popup (action list)
|
|
||||||
*/
|
|
||||||
static Window *PopupClientList(Window *w, 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();
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main handle for clientlist
|
|
||||||
*/
|
|
||||||
static void ClientListWndProc(Window *w, WindowEvent *e)
|
|
||||||
{
|
|
||||||
switch (e->event) {
|
|
||||||
case WE_PAINT: {
|
|
||||||
NetworkClientInfo *ci;
|
NetworkClientInfo *ci;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
/* Check if we need to reset the height */
|
/* Check if we need to reset the height */
|
||||||
if (!CheckClientListHeight(w)) break;
|
if (!this->CheckClientListHeight()) return;
|
||||||
|
|
||||||
DrawWindowWidgets(w);
|
DrawWindowWidgets(this);
|
||||||
|
|
||||||
int y = CLNWND_OFFSET;
|
int y = CLNWND_OFFSET;
|
||||||
|
|
||||||
FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
|
FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
|
||||||
TextColour colour;
|
TextColour colour;
|
||||||
if (_selected_clientlist_item == i++) { // Selected item, highlight it
|
if (this->selected_item == i++) { // Selected item, highlight it
|
||||||
GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0);
|
GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0);
|
||||||
colour = TC_WHITE;
|
colour = TC_WHITE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1539,49 +1540,44 @@ static void ClientListWndProc(Window *w, WindowEvent *e)
|
||||||
|
|
||||||
y += CLNWND_ROWSIZE;
|
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;
|
|
||||||
|
|
||||||
case WE_MOUSEOVER:
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnMouseOver(Point pt, int widget)
|
||||||
|
{
|
||||||
/* -1 means we left the current window */
|
/* -1 means we left the current window */
|
||||||
if (e->we.mouseover.pt.y == -1) {
|
if (pt.y == -1) {
|
||||||
_selected_clientlist_y = 0;
|
this->selected_y = 0;
|
||||||
_selected_clientlist_item = 255;
|
this->selected_item = 255;
|
||||||
w->SetDirty();
|
this->SetDirty();
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
/* It did not change.. no update! */
|
/* It did not change.. no update! */
|
||||||
if (e->we.mouseover.pt.y == _selected_clientlist_y) break;
|
if (pt.y == this->selected_y) return;
|
||||||
|
|
||||||
/* Find the new selected item (if any) */
|
/* Find the new selected item (if any) */
|
||||||
_selected_clientlist_y = e->we.mouseover.pt.y;
|
this->selected_y = pt.y;
|
||||||
if (e->we.mouseover.pt.y > CLNWND_OFFSET) {
|
if (pt.y > CLNWND_OFFSET) {
|
||||||
_selected_clientlist_item = (e->we.mouseover.pt.y - CLNWND_OFFSET) / CLNWND_ROWSIZE;
|
this->selected_item = (pt.y - CLNWND_OFFSET) / CLNWND_ROWSIZE;
|
||||||
} else {
|
} else {
|
||||||
_selected_clientlist_item = 255;
|
this->selected_item = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Repaint */
|
/* Repaint */
|
||||||
w->SetDirty();
|
this->SetDirty();
|
||||||
break;
|
|
||||||
|
|
||||||
case WE_DESTROY: case WE_CREATE:
|
|
||||||
/* When created or destroyed, data is reset */
|
|
||||||
_selected_clientlist_item = 255;
|
|
||||||
_selected_clientlist_y = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void ShowClientList()
|
void ShowClientList()
|
||||||
{
|
{
|
||||||
AllocateWindowDescFront<Window>(&_client_list_desc, 0);
|
AllocateWindowDescFront<NetworkClientListWindow>(&_client_list_desc, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -78,13 +78,13 @@ static Point GetToolbarDropdownPos(uint16 parent_button, int width, int height)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 w Window holding the menu items
|
||||||
* @param x X coordinate of the position
|
* @param x X coordinate of the position
|
||||||
* @param y Y 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
|
* @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 x = _cursor.pos.x;
|
||||||
int y = _cursor.pos.y;
|
int y = _cursor.pos.y;
|
||||||
|
@ -92,8 +92,8 @@ static int GetMenuItemIndex(const Window *w)
|
||||||
if ((x -= w->left) >= 0 && x < w->width && (y -= w->top + 1) >= 0) {
|
if ((x -= w->left) >= 0 && x < w->width && (y -= w->top + 1) >= 0) {
|
||||||
y /= 10;
|
y /= 10;
|
||||||
|
|
||||||
if (y < WP(w, const menu_d).item_count &&
|
if (y < item_count &&
|
||||||
!HasBit(WP(w, const menu_d).disabled_items, y)) {
|
!HasBit(disabled_items, y)) {
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1113,71 +1113,77 @@ static MenuClickedProc * const _menu_clicked_procs[] = {
|
||||||
MenuClickHelp, /* 26 */
|
MenuClickHelp, /* 26 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void MenuWndProc(Window *w, WindowEvent *e)
|
struct ToolbarMenuWindow : Window {
|
||||||
|
int item_count;
|
||||||
|
int sel_index;
|
||||||
|
int main_button;
|
||||||
|
int action_id;
|
||||||
|
int checked_items;
|
||||||
|
int disabled_items;
|
||||||
|
StringID base_string;
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
switch (e->event) {
|
this->widget[0].bottom = item_count * 10 + 1;
|
||||||
case WE_CREATE:
|
this->widget[0].right = this->width - 1;
|
||||||
w->widget[0].right = w->width - 1;
|
this->flags4 &= ~WF_WHITE_BORDER_MASK;
|
||||||
break;
|
|
||||||
|
|
||||||
case WE_PAINT: {
|
this->FindWindowPlacementAndResize(width, height);
|
||||||
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);
|
|
||||||
v->SetDirty();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case WE_MOUSELOOP: {
|
~ToolbarMenuWindow()
|
||||||
int index = GetMenuItemIndex(w);
|
{
|
||||||
|
Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
|
||||||
|
w->RaiseWidget(this->main_button);
|
||||||
|
w->SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
if (_left_button_down) {
|
if (_left_button_down) {
|
||||||
if (index == -1 || index == WP(w, menu_d).sel_index) return;
|
if (index == -1 || index == this->sel_index) return;
|
||||||
|
|
||||||
WP(w, menu_d).sel_index = index;
|
this->sel_index = index;
|
||||||
w->SetDirty();
|
this->SetDirty();
|
||||||
} else {
|
} else {
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0);
|
Window *w = FindWindowById(WC_MAIN_TOOLBAR,0);
|
||||||
if (GetWidgetFromPos(w2, _cursor.pos.x - w2->left, _cursor.pos.y - w2->top) == WP(w, menu_d).main_button)
|
if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) == this->main_button) {
|
||||||
index = WP(w, menu_d).sel_index;
|
index = this->sel_index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int action_id = WP(w, menu_d).action_id;
|
int action_id = this->action_id;
|
||||||
delete w;
|
delete this;
|
||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
assert((uint)index <= lengthof(_menu_clicked_procs));
|
assert((uint)index <= lengthof(_menu_clicked_procs));
|
||||||
_menu_clicked_procs[action_id](index);
|
_menu_clicked_procs[action_id](index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* Dynamic widget length determined by toolbar-string length.
|
/* Dynamic widget length determined by toolbar-string length.
|
||||||
* See PopupMainToolbMenu en MenuWndProc */
|
* See PopupMainToolbMenu en MenuWndProc */
|
||||||
|
@ -1248,17 +1254,7 @@ static void PopupMainToolbMenu(Window *parent, uint16 parent_button, StringID ba
|
||||||
|
|
||||||
Point pos = GetToolbarDropdownPos(parent_button, width, height);
|
Point pos = GetToolbarDropdownPos(parent_button, width, height);
|
||||||
|
|
||||||
Window *w = new Window(pos.x, pos.y, width, height, MenuWndProc, WC_TOOLBAR_MENU, _menu_widgets);
|
new ToolbarMenuWindow(pos.x, pos.y, width, height, _menu_widgets, item_count, sel_index, parent_button, base_string, checked_items, disabled_mask);
|
||||||
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;
|
|
||||||
|
|
||||||
SndPlayFx(SND_15_BEEP);
|
SndPlayFx(SND_15_BEEP);
|
||||||
}
|
}
|
||||||
|
@ -1276,38 +1272,66 @@ static int GetPlayerIndexFromMenu(int index)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UpdatePlayerMenuHeight(Window *w)
|
struct ToolbarPlayerMenuWindow : Window {
|
||||||
|
int item_count;
|
||||||
|
int sel_index;
|
||||||
|
int main_button;
|
||||||
|
int action_id;
|
||||||
|
int gray_items;
|
||||||
|
|
||||||
|
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();
|
byte num = ActivePlayerCount();
|
||||||
|
|
||||||
/* Increase one to fit in PlayerList in the menu when in network */
|
/* Increase one to fit in PlayerList in the menu when in network */
|
||||||
if (_networking && WP(w, menu_d).main_button == 9) num++;
|
if (_networking && this->main_button == 9) num++;
|
||||||
|
|
||||||
if (WP(w, menu_d).item_count != num) {
|
if (this->item_count != num) {
|
||||||
WP(w, menu_d).item_count = num;
|
this->item_count = num;
|
||||||
w->SetDirty();
|
this->SetDirty();
|
||||||
num = num * 10 + 2;
|
num = num * 10 + 2;
|
||||||
w->height = num;
|
this->height = num;
|
||||||
w->widget[0].bottom = w->widget[0].top + num - 1;
|
this->widget[0].bottom = this->widget[0].top + num - 1;
|
||||||
w->top = GetToolbarDropdownPos(0, w->width, w->height).y;
|
this->top = GetToolbarDropdownPos(0, this->width, this->height).y;
|
||||||
w->SetDirty();
|
this->SetDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PlayerMenuWndProc(Window *w, WindowEvent *e)
|
virtual void OnPaint()
|
||||||
{
|
{
|
||||||
switch (e->event) {
|
this->UpdatePlayerMenuHeight();
|
||||||
case WE_PAINT: {
|
DrawWindowWidgets(this);
|
||||||
UpdatePlayerMenuHeight(w);
|
|
||||||
DrawWindowWidgets(w);
|
|
||||||
|
|
||||||
int x = 1;
|
int x = 1;
|
||||||
int y = 1;
|
int y = 1;
|
||||||
int sel = WP(w, menu_d).sel_index;
|
int sel = this->sel_index;
|
||||||
int chk = WP(w, menu_d).checked_items; // let this mean gray items.
|
int gray = this->gray_items;
|
||||||
|
|
||||||
/* 9 = playerlist */
|
/* 9 = playerlist */
|
||||||
if (_networking && WP(w, menu_d).main_button == 9) {
|
if (_networking && this->main_button == 9) {
|
||||||
if (sel == 0) {
|
if (sel == 0) {
|
||||||
GfxFillRect(x, y, x + 238, y + 9, 0);
|
GfxFillRect(x, y, x + 238, y + 9, 0);
|
||||||
}
|
}
|
||||||
|
@ -1329,66 +1353,60 @@ static void PlayerMenuWndProc(Window *w, WindowEvent *e)
|
||||||
SetDParam(1, p->index);
|
SetDParam(1, p->index);
|
||||||
|
|
||||||
TextColour color = (p->index == sel) ? TC_WHITE : TC_BLACK;
|
TextColour color = (p->index == sel) ? TC_WHITE : TC_BLACK;
|
||||||
if (chk & 1) color = TC_GREY;
|
if (gray & 1) color = TC_GREY;
|
||||||
DrawString(x + 19, y, STR_7021, color);
|
DrawString(x + 19, y, STR_7021, color);
|
||||||
|
|
||||||
y += 10;
|
y += 10;
|
||||||
}
|
}
|
||||||
chk >>= 1;
|
gray >>= 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: {
|
virtual void OnMouseLoop()
|
||||||
int index = GetMenuItemIndex(w);
|
{
|
||||||
|
int index = GetMenuItemIndex(this, this->item_count, 0);
|
||||||
|
|
||||||
if (_left_button_down) {
|
if (_left_button_down) {
|
||||||
UpdatePlayerMenuHeight(w);
|
this->UpdatePlayerMenuHeight();
|
||||||
/* We have a new entry at the top of the list of menu 9 when networking
|
/* We have a new entry at the top of the list of menu 9 when networking
|
||||||
* so keep that in count */
|
* so keep that in count */
|
||||||
if (_networking && WP(w, menu_d).main_button == 9) {
|
if (_networking && this->main_button == 9) {
|
||||||
if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
|
if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
|
||||||
} else {
|
} else {
|
||||||
index = GetPlayerIndexFromMenu(index);
|
index = GetPlayerIndexFromMenu(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == -1 || index == WP(w, menu_d).sel_index) return;
|
if (index == -1 || index == this->sel_index) return;
|
||||||
|
|
||||||
WP(w, menu_d).sel_index = index;
|
this->sel_index = index;
|
||||||
w->SetDirty();
|
this->SetDirty();
|
||||||
} else {
|
} else {
|
||||||
int action_id = WP(w, menu_d).action_id;
|
int action_id = this->action_id;
|
||||||
|
|
||||||
/* We have a new entry at the top of the list of menu 9 when networking
|
/* We have a new entry at the top of the list of menu 9 when networking
|
||||||
* so keep that in count */
|
* so keep that in count */
|
||||||
if (_networking && WP(w, menu_d).main_button == 9) {
|
if (_networking && this->main_button == 9) {
|
||||||
if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
|
if (index > 0) index = GetPlayerIndexFromMenu(index - 1) + 1;
|
||||||
} else {
|
} else {
|
||||||
index = GetPlayerIndexFromMenu(index);
|
index = GetPlayerIndexFromMenu(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
Window *w2 = FindWindowById(WC_MAIN_TOOLBAR,0);
|
Window *w = FindWindowById(WC_MAIN_TOOLBAR,0);
|
||||||
if (GetWidgetFromPos(w2, _cursor.pos.x - w2->left, _cursor.pos.y - w2->top) == WP(w, menu_d).main_button)
|
if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) == this->main_button) {
|
||||||
index = WP(w, menu_d).sel_index;
|
index = this->sel_index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete w;
|
delete this;
|
||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
assert(index >= 0 && index < 30);
|
assert(index >= 0 && index < 30);
|
||||||
_menu_clicked_procs[action_id](index);
|
_menu_clicked_procs[action_id](index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static const Widget _player_menu_widgets[] = {
|
static const Widget _player_menu_widgets[] = {
|
||||||
{ WWT_PANEL, RESIZE_NONE, 14, 0, 240, 0, 81, 0x0, STR_NULL},
|
{ WWT_PANEL, RESIZE_NONE, 14, 0, 240, 0, 81, 0x0, STR_NULL},
|
||||||
|
@ -1402,22 +1420,7 @@ static void PopupMainPlayerToolbMenu(Window *parent, int main_button, int gray)
|
||||||
|
|
||||||
DeleteWindowById(WC_TOOLBAR_MENU, 0);
|
DeleteWindowById(WC_TOOLBAR_MENU, 0);
|
||||||
Point pos = GetToolbarDropdownPos(main_button, 241, 82);
|
Point pos = GetToolbarDropdownPos(main_button, 241, 82);
|
||||||
Window *w = new Window(pos.x, pos.y, 241, 82, PlayerMenuWndProc, WC_TOOLBAR_MENU, _player_menu_widgets);
|
new ToolbarPlayerMenuWindow(pos.x, pos.y, 241, 82, _player_menu_widgets, main_button, gray);
|
||||||
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;
|
|
||||||
|
|
||||||
SndPlayFx(SND_15_BEEP);
|
SndPlayFx(SND_15_BEEP);
|
||||||
}
|
}
|
||||||
|
|
|
@ -515,17 +515,6 @@ public:
|
||||||
/*** End of the event handling ***/
|
/*** 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 {
|
struct def_d {
|
||||||
int16 data_1, data_2, data_3;
|
int16 data_1, data_2, data_3;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue