Changeset - r13433:235ceb319b3c
[Not reviewed]
master
0 1 0
rubidium - 15 years ago 2009-11-02 15:37:54
rubidium@openttd.org
(svn r17952) -Codechange: make the network client list popup nested
1 file changed with 50 insertions and 38 deletions:
0 comments (0 inline, 0 general)
src/network/network_gui.cpp
Show inline comments
 
@@ -1748,32 +1748,34 @@ NetworkCompanyInfo *GetLobbyCompanyInfo(
 
	return (lobby != NULL && company < MAX_COMPANIES) ? &lobby->company_info[company] : NULL;
 
}
 

	
 
/* The window below gives information about the connected clients
 
 *  and also makes able to give money to them, kick them (if server)
 
 *  and stuff like that. */
 

	
 
extern void DrawCompanyIcon(CompanyID cid, int x, int y);
 

	
 
/* Every action must be of this form */
 
typedef void ClientList_Action_Proc(byte client_no);
 

	
 
static const Widget _client_list_popup_widgets[] = {
 
{      WWT_PANEL,   RESIZE_NONE,  COLOUR_GREY,     0,   99,     0,     0,     0, STR_NULL},
 
{   WIDGETS_END},
 
static const NWidgetPart _nested_client_list_popup_widgets[] = {
 
	NWidget(WWT_PANEL, COLOUR_GREY, 0), EndContainer(),
 
};
 

	
 
static const NWidgetPart _nested_client_list_popup_widgets[] = {
 
	NWidget(WWT_PANEL, COLOUR_GREY, 0), SetMinimalSize(100, 1), EndContainer(),
 
};
 
static const WindowDesc _client_list_popup_desc(
 
	WDP_AUTO, WDP_AUTO, 150, 1, 150, 1,
 
	WC_TOOLBAR_MENU, WC_CLIENT_LIST,
 
	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET,
 
	NULL, _nested_client_list_popup_widgets, lengthof(_nested_client_list_popup_widgets)
 
);
 

	
 
/* Finds the Xth client-info that is active */
 
static NetworkClientInfo *NetworkFindClientInfo(byte client_no)
 
{
 
	NetworkClientInfo *ci;
 

	
 
	FOR_ALL_CLIENT_INFOS(ci) {
 
		if (client_no == 0) return ci;
 
		client_no--;
 
	}
 

	
 
	return NULL;
 
@@ -1825,96 +1827,113 @@ static void ClientList_SpeakToAll(byte c
 
}
 

	
 
/** Popup selection window to chose an action to perform */
 
struct NetworkClientListPopupWindow : Window {
 
	/** Container for actions that can be executed. */
 
	struct ClientListAction {
 
		StringID name;                ///< Name of the action to execute
 
		ClientList_Action_Proc *proc; ///< Action to execute
 
	};
 

	
 
	uint sel_index;
 
	int client_no;
 
	Point desired_location;
 
	SmallVector<ClientListAction, 2> actions; ///< Actions to execute
 

	
 
	/**
 
	 * Add an action to the list of actions to execute.
 
	 * @param name the name of the action
 
	 * @param proc the procedure to execute for the action
 
	 */
 
	inline void AddAction(StringID name, ClientList_Action_Proc *proc)
 
	{
 
		ClientListAction *action = this->actions.Append();
 
		action->name = name;
 
		action->proc = proc;
 
	}
 

	
 
	NetworkClientListPopupWindow(int x, int y, const Widget *widgets, int client_no) :
 
			Window(x, y, 150, 100, WC_TOOLBAR_MENU, widgets),
 
	NetworkClientListPopupWindow(const WindowDesc *desc, int x, int y, int client_no) :
 
			Window(),
 
			sel_index(0), client_no(client_no)
 
	{
 
		this->desired_location.x = x;
 
		this->desired_location.y = y;
 

	
 
		const NetworkClientInfo *ci = NetworkFindClientInfo(client_no);
 

	
 
		if (_network_own_client_id != ci->client_id) {
 
			this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, &ClientList_SpeakToClient);
 
		}
 

	
 
		if (Company::IsValidID(ci->client_playas) || ci->client_playas == COMPANY_SPECTATOR) {
 
			this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, &ClientList_SpeakToCompany);
 
		}
 
		this->AddAction(STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, &ClientList_SpeakToAll);
 

	
 
		if (_network_own_client_id != ci->client_id) {
 
			/* We are no spectator and the company we want to give money to is no spectator and money gifts are allowed */
 
			if (Company::IsValidID(_local_company) && Company::IsValidID(ci->client_playas) && _settings_game.economy.give_money) {
 
				this->AddAction(STR_NETWORK_CLIENTLIST_GIVE_MONEY, &ClientList_GiveMoney);
 
			}
 
		}
 

	
 
		/* A server can kick clients (but not himself) */
 
		if (_network_server && _network_own_client_id != ci->client_id) {
 
			this->AddAction(STR_NETWORK_CLIENTLIST_KICK, &ClientList_Kick);
 
			this->AddAction(STR_NETWORK_CLIENTLIST_BAN, &ClientList_Ban);
 
		}
 

	
 
		/* Calculate the height */
 
		int h = this->actions.Length() * FONT_HEIGHT_NORMAL + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
 
		this->flags4 &= ~WF_WHITE_BORDER_MASK;
 
		this->InitNested(desc, 0);
 
	}
 

	
 
	virtual Point OnInitialPosition(const WindowDesc *desc, int16 sm_width, int16 sm_height, int window_number)
 
	{
 
		return this->desired_location;
 
	}
 

	
 
	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *resize)
 
	{
 
		Dimension d = *size;
 
		for (const ClientListAction *action = this->actions.Begin(); action != this->actions.End(); action++) {
 
			d = maxdim(GetStringBoundingBox(action->name), d);
 
		}
 

	
 
		/* Allocate the popup */
 
		this->widget[0].bottom = this->widget[0].top + h;
 
		this->widget[0].right = this->widget[0].left + 150;
 
		d.height *= this->actions.Length();
 
		d.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
 
		d.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
 
		*size = d;
 
	}
 

	
 
		this->flags4 &= ~WF_WHITE_BORDER_MASK;
 
	virtual void DrawWidget(const Rect &r, int widget) const
 
	{
 
		/* Draw the actions */
 
		int sel = this->sel_index;
 
		int y = r.top + WD_FRAMERECT_TOP;
 
		for (const ClientListAction *action = this->actions.Begin(); action != this->actions.End(); action++, y += FONT_HEIGHT_NORMAL) {
 
			TextColour colour;
 
			if (sel-- == 0) { // Selected item, highlight it
 
				GfxFillRect(r.left + 1, y, r.right - 1, y + FONT_HEIGHT_NORMAL - 1, 0);
 
				colour = TC_WHITE;
 
			} else {
 
				colour = TC_BLACK;
 
			}
 

	
 
		this->FindWindowPlacementAndResize(150, h + 1);
 
			DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, action->name, colour);
 
		}
 
	}
 

	
 
	virtual void OnPaint()
 
	{
 
		this->DrawWidgets();
 

	
 
		/* Draw the actions */
 
		int sel = this->sel_index;
 
		int y = WD_FRAMERECT_TOP;
 
		for (const ClientListAction *action = this->actions.Begin(); action != this->actions.End(); action++, y += FONT_HEIGHT_NORMAL) {
 
			TextColour colour;
 
			if (sel-- == 0) { // Selected item, highlight it
 
				GfxFillRect(1, y, 150 - 2, y + FONT_HEIGHT_NORMAL - 1, 0);
 
				colour = TC_WHITE;
 
			} else {
 
				colour = TC_BLACK;
 
			}
 

	
 
			DrawString(4, this->width - 4, y, action->name, colour);
 
		}
 
	}
 

	
 
	virtual void OnMouseLoop()
 
	{
 
		/* We selected an action */
 
		uint index = (_cursor.pos.y - this->top - WD_FRAMERECT_TOP) / FONT_HEIGHT_NORMAL;
 

	
 
		if (_left_button_down) {
 
			if (index == this->sel_index || index >= this->actions.Length()) return;
 

	
 
			this->sel_index = index;
 
			this->SetDirty();
 
@@ -1924,36 +1943,29 @@ struct NetworkClientListPopupWindow : Wi
 
			}
 

	
 
			DeleteWindowById(WC_TOOLBAR_MENU, 0);
 
		}
 
	}
 
};
 

	
 
/**
 
 * Show the popup (action list)
 
 */
 
static void PopupClientList(int client_no, int x, int y)
 
{
 
	static Widget *generated_client_list_popup_widgets = NULL;
 

	
 
	DeleteWindowById(WC_TOOLBAR_MENU, 0);
 

	
 
	if (NetworkFindClientInfo(client_no) == NULL) return;
 

	
 
	const Widget *wid = InitializeWidgetArrayFromNestedWidgets(
 
		_nested_client_list_popup_widgets, lengthof(_nested_client_list_popup_widgets),
 
		_client_list_popup_widgets, &generated_client_list_popup_widgets
 
	);
 

	
 
	new NetworkClientListPopupWindow(x, y, wid, client_no);
 
	new NetworkClientListPopupWindow(&_client_list_popup_desc, x, y, client_no);
 
}
 

	
 

	
 
/** Widget numbers of the client list window. */
 
enum ClientListWidgets {
 
	CLW_CLOSE,
 
	CLW_CAPTION,
 
	CLW_STICKY,
 
	CLW_PANEL,
 
};
 

	
 
static const Widget _client_list_widgets[] = {
0 comments (0 inline, 0 general)