Changeset - r9242:7cd026479b6e
[Not reviewed]
master
0 3 0
rubidium - 17 years ago 2008-05-15 20:04:10
rubidium@openttd.org
(svn r13108) -Codechange: make a Window subclass of the main toolbars sub menus.
3 files changed with 411 insertions and 423 deletions:
0 comments (0 inline, 0 general)
src/network/network_gui.cpp
Show inline comments
 
@@ -1214,20 +1214,12 @@ extern void DrawPlayerIcon(PlayerID pid,
 
// Every action must be of this form
 
typedef void ClientList_Action_Proc(byte client_no);
 

	
 
// 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
 
};
 

	
 
static const Widget _client_list_widgets[] = {
 
@@ -1246,13 +1238,13 @@ static const Widget _client_list_popup_w
 

	
 
static WindowDesc _client_list_desc = {
 
	WDP_AUTO, WDP_AUTO, 250, 1, 250, 1,
 
	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
 
static const NetworkClientInfo *NetworkFindClientInfo(byte client_no)
 
{
 
	const NetworkClientInfo *ci;
 
@@ -1318,273 +1310,277 @@ static void ClientList_None(byte client_
 
{
 
	/* No action ;) */
 
}
 

	
 

	
 

	
 
/**
 
 * 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<Window>(&_client_list_desc, 0);
 
	AllocateWindowDescFront<NetworkClientListWindow>(&_client_list_desc, 0);
 
}
 

	
 

	
 
static NetworkPasswordType pw_type;
 

	
 

	
src/toolbar_gui.cpp
Show inline comments
 
@@ -75,28 +75,28 @@ static Point GetToolbarDropdownPos(uint1
 
	pos.y = w->height;
 

	
 
	return pos;
 
}
 

	
 
/**
 
 * 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;
 

	
 
	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;
 
		}
 
	}
 
	return -1;
 
}
 

	
 
@@ -1110,77 +1110,83 @@ static MenuClickedProc * const _menu_cli
 
	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;
 
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 */
 
static const Widget _menu_widgets[] = {
 
{    WWT_PANEL, RESIZE_NONE, 14, 0,  0, 0, 0, 0x0, STR_NULL},
 
{ WIDGETS_END},
 
@@ -1245,23 +1251,13 @@ static void PopupMainToolbMenu(Window *p
 
	/* 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);
 

	
 
	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);
 
}
 

	
 
/* --- Rendering/drawing the player menu --- */
 
static int GetPlayerIndexFromMenu(int index)
 
@@ -1273,125 +1269,147 @@ static int GetPlayerIndexFromMenu(int in
 
			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++;
 
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},
 
{ WIDGETS_END},
 
};
 

	
 
@@ -1399,28 +1417,13 @@ static void PopupMainPlayerToolbMenu(Win
 
{
 
	parent->LowerWidget(main_button);
 
	parent->InvalidateWidget(main_button);
 

	
 
	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);
 
}
 

	
 
/* --- Allocating the toolbar --- */
 

	
src/window_gui.h
Show inline comments
 
@@ -512,23 +512,12 @@ public:
 
	 */
 
	virtual void OnPlacePresize(Point pt, TileIndex tile);
 

	
 
	/*** 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;
 
};
 
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(def_d));
 

	
 
enum SortListFlags {
0 comments (0 inline, 0 general)