Changeset - r8284:d769847bf11d
[Not reviewed]
master
0 14 3
peter1138 - 17 years ago 2008-01-14 16:10:58
peter1138@openttd.org
(svn r11848) -Codechange: New class-based drop down list functionality. Lists are now dynamically generated, and can include parameters, or be extended however needed.
17 files changed with 379 insertions and 252 deletions:
0 comments (0 inline, 0 general)
source.list
Show inline comments
 
@@ -93,6 +93,7 @@ vehicle.cpp
 
viewport.cpp
 
waypoint.cpp
 
widget.cpp
 
widgets/dropdown.cpp
 
#if WIN32
 
	win32.cpp
 
#end
 
@@ -210,6 +211,7 @@ music/win32_m.h
 
sound/win32_s.h
 
video/win32_v.h
 
window.h
 
widgets/dropdown.h
 
zoom.hpp
 

	
 
# GUI Source Code
src/autoreplace_gui.cpp
Show inline comments
 
@@ -18,6 +18,7 @@
 
#include "autoreplace_func.h"
 
#include "gfx_func.h"
 
#include "player_func.h"
 
#include "widgets/dropdown_func.h"
 

	
 
#include "table/sprites.h"
 
#include "table/strings.h"
src/build_vehicle_gui.cpp
Show inline comments
 
@@ -29,6 +29,7 @@
 
#include "vehicle_func.h"
 
#include "settings_type.h"
 
#include "gfx_func.h"
 
#include "widgets/dropdown_func.h"
 

	
 
#include "table/sprites.h"
 
#include "table/strings.h"
src/genworld_gui.cpp
Show inline comments
 
@@ -25,6 +25,7 @@
 
#include "string_func.h"
 
#include "gfx_func.h"
 
#include "settings_type.h"
 
#include "widgets/dropdown_func.h"
 

	
 
#include "table/strings.h"
 
#include "table/sprites.h"
src/group_gui.cpp
Show inline comments
 
@@ -23,6 +23,7 @@
 
#include "viewport_func.h"
 
#include "gfx_func.h"
 
#include "player_func.h"
 
#include "widgets/dropdown_func.h"
 

	
 
#include "table/strings.h"
 
#include "table/sprites.h"
 
@@ -328,14 +329,7 @@ static void GroupWndProc(Window *w, Wind
 
			/* The drop down menu is out, *but* it may not be used, retract it. */
 
			if (gv->l.list_length == 0 && w->IsWidgetLowered(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN)) {
 
				w->RaiseWidget(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN);
 
				Window **w2;
 
				FOR_ALL_WINDOWS(w2) {
 
					if (w->window_class  == WP(*w2, dropdown_d).parent_wnd_class &&
 
							w->window_number == WP(*w2, dropdown_d).parent_wnd_num) {
 
						DeleteWindow(*w2);
 
						break;
 
					}
 
				}
 
				HideDropDownMenu(w);
 
			}
 

	
 
			/* Disable all lists management button when the list is empty */
src/network/network_gui.cpp
Show inline comments
 
@@ -26,6 +26,7 @@
 
#include "../gfx_func.h"
 
#include "../player_func.h"
 
#include "../settings_type.h"
 
#include "../widgets/dropdown_func.h"
 

	
 
#include "table/strings.h"
 
#include "../table/sprites.h"
src/news_gui.cpp
Show inline comments
 
@@ -15,6 +15,7 @@
 
#include "vehicle_base.h"
 
#include "sound_func.h"
 
#include "string_func.h"
 
#include "widgets/dropdown_func.h"
 

	
 
#include "table/sprites.h"
 
#include "table/strings.h"
src/player_gui.cpp
Show inline comments
 
@@ -28,6 +28,7 @@
 
#include "date_func.h"
 
#include "string_func.h"
 
#include "settings_type.h"
 
#include "widgets/dropdown_func.h"
 

	
 
#include "table/sprites.h"
 
#include "table/strings.h"
src/rail_gui.cpp
Show inline comments
 
@@ -27,6 +27,7 @@
 
#include "sound_func.h"
 
#include "player_func.h"
 
#include "settings_type.h"
 
#include "widgets/dropdown_func.h"
 

	
 
#include "bridge_map.h"
 
#include "rail_map.h"
src/settings_gui.cpp
Show inline comments
 
@@ -24,6 +24,7 @@
 
#include "core/alloc_func.hpp"
 
#include "string_func.h"
 
#include "gfx_func.h"
 
#include "widgets/dropdown_func.h"
 

	
 
#include "table/sprites.h"
 
#include "table/strings.h"
src/station_gui.cpp
Show inline comments
 
@@ -23,6 +23,7 @@
 
#include "window_func.h"
 
#include "viewport_func.h"
 
#include "gfx_func.h"
 
#include "widgets/dropdown_func.h"
 

	
 
#include "table/strings.h"
 
#include "table/sprites.h"
src/vehicle_gui.cpp
Show inline comments
 
@@ -35,6 +35,7 @@
 
#include "core/alloc_func.hpp"
 
#include "string_func.h"
 
#include "settings_type.h"
 
#include "widgets/dropdown_func.h"
 

	
 
#include "table/sprites.h"
 
#include "table/strings.h"
src/widget.cpp
Show inline comments
 
@@ -9,6 +9,7 @@
 
#include "gfx_func.h"
 
#include "window_gui.h"
 
#include "window_func.h"
 
#include "widgets/dropdown_func.h"
 

	
 
#include "table/sprites.h"
 
#include "table/strings.h"
 
@@ -484,235 +485,6 @@ draw_default:;
 

	
 
}
 

	
 
static const Widget _dropdown_menu_widgets[] = {
 
{      WWT_PANEL,   RESIZE_NONE,     0,     0, 0,     0, 0, 0x0, STR_NULL},
 
{  WWT_SCROLLBAR,   RESIZE_NONE,     0,     0, 0,     0, 0, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
 
{   WIDGETS_END},
 
};
 

	
 
static int GetDropdownItem(const Window *w)
 
{
 
	byte item, counter;
 
	int y;
 

	
 
	if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) < 0)
 
		return -1;
 

	
 
	y = _cursor.pos.y - w->top - 2 + w->vscroll.pos * 10;
 

	
 
	if (y < 0)
 
		return - 1;
 

	
 
	item = y / 10;
 
	if (item >= WP(w, dropdown_d).num_items || (HasBit(WP(w,dropdown_d).disabled_state, item) && !HasBit(WP(w,dropdown_d).hidden_state, item)) || WP(w,dropdown_d).items[item] == 0)
 
		return - 1;
 

	
 
	/* Skip hidden items -- +1 for each hidden item before the clicked item. */
 
	for (counter = 0; item >= counter; ++counter)
 
		if (HasBit(WP(w, dropdown_d).hidden_state, counter)) item++;
 

	
 
	return item;
 
}
 

	
 
static void DropdownMenuWndProc(Window *w, WindowEvent *e)
 
{
 
	int item;
 

	
 
	switch (e->event) {
 
		case WE_PAINT: {
 
			int x,y,i,sel;
 
			int width, height;
 

	
 
			DrawWindowWidgets(w);
 

	
 
			x = 1;
 
			y = 2 - w->vscroll.pos * 10;
 

	
 
			sel    = WP(w, dropdown_d).selected_index;
 
			width  = w->widget[0].right - 3;
 
			height = w->widget[0].bottom - 3;
 

	
 
			for (i = 0; WP(w, dropdown_d).items[i] != INVALID_STRING_ID; i++, sel--) {
 
				if (HasBit(WP(w, dropdown_d).hidden_state, i)) continue;
 

	
 
				if (y >= 0 && y <= height) {
 
					if (WP(w, dropdown_d).items[i] != STR_NULL) {
 
						if (sel == 0) GfxFillRect(x + 1, y, x + width, y + 9, 0);
 
						DrawStringTruncated(x + 2, y, WP(w, dropdown_d).items[i], sel == 0 ? TC_WHITE : TC_BLACK, x + width);
 

	
 
						if (HasBit(WP(w, dropdown_d).disabled_state, i)) {
 
							GfxFillRect(x, y, x + width, y + 9,
 
								(1 << PALETTE_MODIFIER_GREYOUT) | _colour_gradient[_dropdown_menu_widgets[0].color][5]
 
							);
 
						}
 
					} else {
 
						int c1 = _colour_gradient[_dropdown_menu_widgets[0].color][3];
 
						int c2 = _colour_gradient[_dropdown_menu_widgets[0].color][7];
 

	
 
						GfxFillRect(x + 1, y + 3, x + w->width - 5, y + 3, c1);
 
						GfxFillRect(x + 1, y + 4, x + w->width - 5, y + 4, c2);
 
					}
 
				}
 
				y += 10;
 
			}
 
		} break;
 

	
 
		case WE_CLICK: {
 
			if (e->we.click.widget != 0) break;
 
			item = GetDropdownItem(w);
 
			if (item >= 0) {
 
				WP(w, dropdown_d).click_delay = 4;
 
				WP(w, dropdown_d).selected_index = item;
 
				SetWindowDirty(w);
 
			}
 
		} break;
 

	
 
		case WE_MOUSELOOP: {
 
			Window *w2 = FindWindowById(WP(w, dropdown_d).parent_wnd_class, WP(w,dropdown_d).parent_wnd_num);
 
			if (w2 == NULL) {
 
				DeleteWindow(w);
 
				return;
 
			}
 

	
 
			if (WP(w, dropdown_d).click_delay != 0 && --WP(w,dropdown_d).click_delay == 0) {
 
				WindowEvent e;
 
				e.event = WE_DROPDOWN_SELECT;
 
				e.we.dropdown.button = WP(w, dropdown_d).parent_button;
 
				e.we.dropdown.index  = WP(w, dropdown_d).selected_index;
 
				w2->wndproc(w2, &e);
 
				DeleteWindow(w);
 
				return;
 
			}
 

	
 
			if (WP(w, dropdown_d).drag_mode) {
 
				item = GetDropdownItem(w);
 

	
 
				if (!_left_button_clicked) {
 
					WP(w, dropdown_d).drag_mode = false;
 
					if (item < 0) return;
 
					WP(w, dropdown_d).click_delay = 2;
 
				} else {
 
					if (item < 0) return;
 
				}
 

	
 
				WP(w, dropdown_d).selected_index = item;
 
				SetWindowDirty(w);
 
			}
 
		} break;
 

	
 
		case WE_DESTROY: {
 
			Window *w2 = FindWindowById(WP(w, dropdown_d).parent_wnd_class, WP(w,dropdown_d).parent_wnd_num);
 
			if (w2 != NULL) {
 
				w2->RaiseWidget(WP(w, dropdown_d).parent_button);
 
				w2->InvalidateWidget(WP(w, dropdown_d).parent_button);
 
			}
 
		} break;
 
	}
 
}
 

	
 
void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, uint32 hidden_mask)
 
{
 
	int i;
 
	const Widget *wi;
 
	Window *w2;
 
	const Window *w3;
 
	bool is_dropdown_menu_shown = w->IsWidgetLowered(button);
 
	int top, height;
 
	int screen_top, screen_bottom;
 
	bool scroll = false;
 

	
 
	DeleteWindowById(WC_DROPDOWN_MENU, 0);
 

	
 
	if (is_dropdown_menu_shown) return;
 

	
 
	w->LowerWidget(button);
 

	
 
	w->InvalidateWidget(button);
 

	
 
	for (i = 0; strings[i] != INVALID_STRING_ID; i++) {}
 
	if (i == 0) return;
 

	
 
	wi = &w->widget[button];
 

	
 
	if (hidden_mask != 0) {
 
		uint j;
 

	
 
		for (j = 0; strings[j] != INVALID_STRING_ID; j++) {
 
			if (HasBit(hidden_mask, j)) i--;
 
		}
 
	}
 

	
 
	/* The preferred position is just below the dropdown calling widget */
 
	top = w->top + wi->bottom + 2;
 
	height = i * 10 + 4;
 

	
 
	w3 = FindWindowById(WC_STATUS_BAR, 0);
 
	screen_bottom = w3 == NULL ? _screen.height : w3->top;
 

	
 
	/* Check if the dropdown will fully fit below the widget */
 
	if (top + height >= screen_bottom) {
 
		w3 = FindWindowById(WC_MAIN_TOOLBAR, 0);
 
		screen_top = w3 == NULL ? 0 : w3->top + w3->height;
 

	
 
		/* If not, check if it will fit above the widget */
 
		if (w->top + wi->top - height - 1 > screen_top) {
 
			top = w->top + wi->top - height - 1;
 
		} else {
 
			/* ... and lastly if it won't, enable the scroll bar and fit the
 
			 * list in below the widget */
 
			int rows = (screen_bottom - 4 - top) / 10;
 
			height = rows * 10 + 4;
 
			scroll = true;
 
		}
 
	}
 

	
 
	w2 = AllocateWindow(
 
		w->left + wi[-1].left + 1,
 
		top,
 
		wi->right - wi[-1].left + 1,
 
		height,
 
		DropdownMenuWndProc,
 
		WC_DROPDOWN_MENU,
 
		_dropdown_menu_widgets);
 

	
 
	w2->widget[0].color = wi->color;
 
	w2->widget[0].right = wi->right - wi[-1].left;
 
	w2->widget[0].bottom = height - 1;
 

	
 
	w2->SetWidgetHiddenState(1, !scroll);
 

	
 
	if (scroll) {
 
		/* We're scrolling, so enable the scroll bar and shrink the list by
 
		 * the scrollbar's width */
 
		w2->widget[1].color  = wi->color;
 
		w2->widget[1].right  = w2->widget[0].right;
 
		w2->widget[1].left   = w2->widget[1].right - 11;
 
		w2->widget[1].bottom = height - 1;
 
		w2->widget[0].right -= 12;
 

	
 
		w2->vscroll.cap   = (height - 4) / 10;
 
		w2->vscroll.count = i;
 
	}
 

	
 
	w2->desc_flags = WDF_DEF_WIDGET;
 
	w2->flags4 &= ~WF_WHITE_BORDER_MASK;
 

	
 
	WP(w2, dropdown_d).disabled_state = disabled_mask;
 
	WP(w2, dropdown_d).hidden_state = hidden_mask;
 

	
 
	WP(w2, dropdown_d).parent_wnd_class = w->window_class;
 
	WP(w2, dropdown_d).parent_wnd_num = w->window_number;
 
	WP(w2, dropdown_d).parent_button = button;
 

	
 
	WP(w2, dropdown_d).num_items = i;
 
	WP(w2, dropdown_d).selected_index = selected;
 
	WP(w2, dropdown_d).items = strings;
 

	
 
	WP(w2, dropdown_d).click_delay = 0;
 
	WP(w2, dropdown_d).drag_mode = true;
 
}
 

	
 

	
 
static void ResizeWidgets(Window *w, byte a, byte b)
 
{
 
	int16 offset = w->widget[a].left;
src/widgets/dropdown.cpp
Show inline comments
 
new file 100644
 
/* $Id$ */
 

	
 
#include "../stdafx.h"
 
#include "../openttd.h"
 
#include "../strings_type.h"
 
#include "../window_gui.h"
 
#include "../strings_func.h"
 
#include "../strings_type.h"
 
#include "../gfx_func.h"
 
#include "../window_func.h"
 
#include "dropdown_type.h"
 
#include "dropdown_func.h"
 

	
 
#include "../table/sprites.h"
 
#include "table/strings.h"
 

	
 
StringID DropDownListItem::String() const
 
{
 
	return STR_NULL;
 
}
 

	
 
StringID DropDownListStringItem::String() const
 
{
 
	return this->string;
 
}
 

	
 
StringID DropDownListParamStringItem::String() const
 
{
 
	for (uint i = 0; i < lengthof(this->decode_params); i++) SetDParam(i, this->decode_params[i]);
 
	return this->string;
 
}
 

	
 
struct dropdown_d {
 
	WindowClass parent_wnd_class;
 
	WindowNumber parent_wnd_num;
 
	byte parent_button;
 
	DropDownList *list;
 
	byte selected_index;
 
	byte click_delay;
 
	bool drag_mode;
 
};
 
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(dropdown_d));
 

	
 
static const Widget _dropdown_menu_widgets[] = {
 
{      WWT_PANEL,   RESIZE_NONE,     0,     0, 0,     0, 0, 0x0, STR_NULL},
 
{  WWT_SCROLLBAR,   RESIZE_NONE,     0,     0, 0,     0, 0, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
 
{   WIDGETS_END},
 
};
 

	
 
static int GetDropDownItem(const Window *w)
 
{
 
	if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) < 0) return -1;
 

	
 
	int y = _cursor.pos.y - w->top - 2 + w->vscroll.pos * 10;
 
	if (y < 0) return -1;
 

	
 
	uint selected_row = y / 10;
 
	const DropDownList *list = WP(w, dropdown_d).list;
 

	
 
	if (selected_row >= list->size()) return -1;
 

	
 
	for (DropDownList::const_iterator it = list->begin(); it != list->end(); ++it, selected_row--) {
 
		if (selected_row == 0) {
 
			const DropDownListItem *item = *it;
 
			if (item->masked || item->String() == STR_NULL) return -1;
 
			return item->result;
 
		}
 
	}
 

	
 
	return -1;
 
}
 

	
 
static void DropDownMenuWndProc(Window *w, WindowEvent *e)
 
{
 
	switch (e->event) {
 
		case WE_PAINT: {
 
			DrawWindowWidgets(w);
 

	
 
			int x = 1;
 
			int y = 2 - w->vscroll.pos * 10;
 

	
 
			int sel    = WP(w, dropdown_d).selected_index;
 
			int width  = w->widget[0].right - 3;
 
			int height = w->widget[0].bottom - 3;
 

	
 
			DropDownList *list = WP(w, dropdown_d).list;
 

	
 
			for (DropDownList::const_iterator it = list->begin(); it != list->end(); ++it) {
 
				if (y >= 0 && y <= height) {
 
					const DropDownListItem *item = *it;
 
					if (item->String() != STR_NULL) {
 
						if (sel == item->result) GfxFillRect(x + 1, y, x + width, y + 9, 0);
 

	
 
						DrawStringTruncated(x + 2, y, item->String(), sel == item->result ? TC_WHITE : TC_BLACK, x + width);
 

	
 
						if (item->masked) {
 
							GfxFillRect(x, y, x + width, y + 9,
 
								(1 << PALETTE_MODIFIER_GREYOUT) | _colour_gradient[_dropdown_menu_widgets[0].color][5]
 
							);
 
						}
 
					} else {
 
						int c1 = _colour_gradient[_dropdown_menu_widgets[0].color][3];
 
						int c2 = _colour_gradient[_dropdown_menu_widgets[0].color][7];
 

	
 
						GfxFillRect(x + 1, y + 3, x + w->width - 5, y + 3, c1);
 
						GfxFillRect(x + 1, y + 4, x + w->width - 5, y + 4, c2);
 
					}
 
				}
 
				y += 10;
 
			}
 
		} break;
 

	
 
		case WE_CLICK: {
 
			if (e->we.click.widget != 0) break;
 
			int item = GetDropDownItem(w);
 
			if (item >= 0) {
 
				WP(w, dropdown_d).click_delay = 4;
 
				WP(w, dropdown_d).selected_index = item;
 
				SetWindowDirty(w);
 
			}
 
		} break;
 

	
 
		case WE_MOUSELOOP: {
 
			Window *w2 = FindWindowById(WP(w, dropdown_d).parent_wnd_class, WP(w,dropdown_d).parent_wnd_num);
 
			if (w2 == NULL) {
 
				DeleteWindow(w);
 
				return;
 
			}
 

	
 
			if (WP(w, dropdown_d).click_delay != 0 && --WP(w,dropdown_d).click_delay == 0) {
 
				WindowEvent e;
 
				e.event = WE_DROPDOWN_SELECT;
 
				e.we.dropdown.button = WP(w, dropdown_d).parent_button;
 
				e.we.dropdown.index  = WP(w, dropdown_d).selected_index;
 
				w2->wndproc(w2, &e);
 
				DeleteWindow(w);
 
				return;
 
			}
 

	
 
			if (WP(w, dropdown_d).drag_mode) {
 
				int item = GetDropDownItem(w);
 

	
 
				if (!_left_button_clicked) {
 
					WP(w, dropdown_d).drag_mode = false;
 
					if (item < 0) return;
 
					WP(w, dropdown_d).click_delay = 2;
 
				} else {
 
					if (item < 0) return;
 
				}
 

	
 
				WP(w, dropdown_d).selected_index = item;
 
				SetWindowDirty(w);
 
			}
 
		} break;
 

	
 
		case WE_DESTROY: {
 
			Window *w2 = FindWindowById(WP(w, dropdown_d).parent_wnd_class, WP(w,dropdown_d).parent_wnd_num);
 
			if (w2 != NULL) {
 
				w2->RaiseWidget(WP(w, dropdown_d).parent_button);
 
				w2->InvalidateWidget(WP(w, dropdown_d).parent_button);
 
			}
 

	
 
			delete WP(w, dropdown_d).list;
 
		} break;
 
	}
 
}
 

	
 
void ShowDropDownList(Window *w, DropDownList *list, int selected, int button)
 
{
 
	bool is_dropdown_menu_shown = w->IsWidgetLowered(button);
 

	
 
	DeleteWindowById(WC_DROPDOWN_MENU, 0);
 

	
 
	if (is_dropdown_menu_shown) {
 
		delete list;
 
		return;
 
	}
 

	
 
	w->LowerWidget(button);
 
	w->InvalidateWidget(button);
 

	
 
	/* Our parent's button widget is used to determine where to place the drop
 
	 * down list window. */
 
	const Widget *wi = &w->widget[button];
 

	
 
	/* The preferred position is just below the dropdown calling widget */
 
	int top = w->top + wi->bottom + 2;
 
	int height = list->size() * 10 + 4;
 

	
 
	/* Check if the status bar is visible, as we don't want to draw over it */
 
	Window *w3 = FindWindowById(WC_STATUS_BAR, 0);
 
	int screen_bottom = w3 == NULL ? _screen.height : w3->top;
 

	
 
	bool scroll = false;
 

	
 
	/* Check if the dropdown will fully fit below the widget */
 
	if (top + height >= screen_bottom) {
 
		w3 = FindWindowById(WC_MAIN_TOOLBAR, 0);
 
		int screen_top = w3 == NULL ? 0 : w3->top + w3->height;
 

	
 
		/* If not, check if it will fit above the widget */
 
		if (w->top + wi->top - height - 1 > screen_top) {
 
			top = w->top + wi->top - height - 1;
 
		} else {
 
			/* ... and lastly if it won't, enable the scroll bar and fit the
 
			 * list in below the widget */
 
			int rows = (screen_bottom - 4 - top) / 10;
 
			height = rows * 10 + 4;
 
			scroll = true;
 
		}
 
	}
 

	
 
	Window *dw = AllocateWindow(
 
		w->left + wi[-1].left + 1,
 
		top,
 
		wi->right - wi[-1].left + 1,
 
		height,
 
		DropDownMenuWndProc,
 
		WC_DROPDOWN_MENU,
 
		_dropdown_menu_widgets);
 

	
 
	dw->widget[0].color = wi->color;
 
	dw->widget[0].right = wi->right - wi[-1].left;
 
	dw->widget[0].bottom = height - 1;
 

	
 
	dw->SetWidgetHiddenState(1, !scroll);
 

	
 
	if (scroll) {
 
		/* We're scrolling, so enable the scroll bar and shrink the list by
 
		 * the scrollbar's width */
 
		dw->widget[1].color  = wi->color;
 
		dw->widget[1].right  = dw->widget[0].right;
 
		dw->widget[1].left   = dw->widget[1].right - 11;
 
		dw->widget[1].bottom = height - 1;
 
		dw->widget[0].right -= 12;
 

	
 
		dw->vscroll.cap   = (height - 4) / 10;
 
		dw->vscroll.count = list->size();
 
	}
 

	
 
	dw->desc_flags = WDF_DEF_WIDGET;
 
	dw->flags4 &= ~WF_WHITE_BORDER_MASK;
 

	
 
	WP(dw, dropdown_d).parent_wnd_class = w->window_class;
 
	WP(dw, dropdown_d).parent_wnd_num   = w->window_number;
 
	WP(dw, dropdown_d).parent_button    = button;
 
	WP(dw, dropdown_d).list             = list;
 
	WP(dw, dropdown_d).selected_index   = selected;
 
	WP(dw, dropdown_d).click_delay      = 0;
 
	WP(dw, dropdown_d).drag_mode        = true;
 
}
 

	
 
void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, uint32 hidden_mask)
 
{
 
	uint result = 0;
 
	DropDownList *list = new DropDownList();
 

	
 
	for (uint i = 0; strings[i] != INVALID_STRING_ID; i++) {
 
		if (!HasBit(hidden_mask, i)) {
 
			list->push_back(new DropDownListStringItem(strings[i], result, HasBit(disabled_mask, i)));
 
		}
 
		result++;
 
	}
 

	
 
	/* No entries in the list? */
 
	if (list->size() == 0) {
 
		delete list;
 
		return;
 
	}
 

	
 
	ShowDropDownList(w, list, selected, button);
 
}
 

	
 
void HideDropDownMenu(Window *pw)
 
{
 
	Window **wz;
 
	FOR_ALL_WINDOWS(wz) {
 
		if ((*wz)->window_class != WC_DROPDOWN_MENU) continue;
 

	
 
		if (pw->window_class == WP(*wz, dropdown_d).parent_wnd_class &&
 
				pw->window_number == WP(*wz, dropdown_d).parent_wnd_num) {
 
			DeleteWindow(*wz);
 
			break;
 
		}
 
	}
 
}
 

	
src/widgets/dropdown_func.h
Show inline comments
 
new file 100644
 
/* $Id$ */
 

	
 
#ifndef WIDGETS_DROPDOWN_FUNC_H
 
#define WIDGETS_DROPDOWN_FUNC_H
 

	
 
/* Show drop down menu containing a fixed list of strings */
 
void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, uint32 hidden_mask);
 

	
 
/* Hide drop down menu of a parent window */
 
void HideDropDownMenu(Window *pw);
 

	
 
#endif /* WIDGETS_DROPDOWN_FUNC_H */
src/widgets/dropdown_type.h
Show inline comments
 
new file 100644
 
/* $Id$ */
 

	
 
#ifndef WIDGETS_DROPDOWN_TYPE_H
 
#define WIDGETS_DROPDOWN_TYPE_H
 

	
 
#include "../window_type.h"
 
#include <list>
 

	
 
/**
 
 * Base list item class from which others are derived. If placed in a list it
 
 * will appear as a horizontal line in the menu.
 
 */
 
class DropDownListItem {
 
public:
 
	int result;  ///< Result code to return to window on selection
 
	bool masked; ///< Masked and unselectable item
 

	
 
	virtual StringID String() const;
 
};
 

	
 
/**
 
 * Common string list item.
 
 */
 
class DropDownListStringItem : public DropDownListItem {
 
public:
 
	StringID string; ///< String ID of item
 

	
 
	DropDownListStringItem(StringID string, uint result, bool masked)
 
	{
 
		this->string = string;
 
		this->result = result;
 
		this->masked = masked;
 
	}
 

	
 
	StringID String() const;
 
};
 

	
 
/**
 
 * String list item with parameters.
 
 */
 
class DropDownListParamStringItem : public DropDownListStringItem {
 
public:
 
	uint64 decode_params[10]; ///< Parameters of the string
 

	
 
	StringID String() const;
 
	void SetParam(uint index, uint64 value) { decode_params[index] = value; }
 
};
 

	
 
/**
 
 * A drop down list is a collection of drop down list items.
 
 */
 
typedef std::list<DropDownListItem *> DropDownList;
 

	
 
/**
 
 * Show a drop down list.
 
 * @param w        Parent window for the list.
 
 * @param list     Prepopulated DropDownList. Will be deleted when the list is
 
 *                 closed.
 
 * @param selected The initially selected list item.
 
 * @param button   The widget within the parent window that is used to determine
 
 *                 the list's location.
 
 */
 
void ShowDropDownList(Window *w, DropDownList *list, int selected, int button);
 

	
 
#endif /* WIDGETS_DROPDOWN_TYPE_H */
src/window_gui.h
Show inline comments
 
@@ -439,20 +439,6 @@ struct message_d {
 
};
 
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(message_d));
 

	
 
struct dropdown_d {
 
	uint32 disabled_state;
 
	uint32 hidden_state;
 
	WindowClass parent_wnd_class;
 
	WindowNumber parent_wnd_num;
 
	byte parent_button;
 
	byte num_items;
 
	byte selected_index;
 
	const StringID *items;
 
	byte click_delay;
 
	bool drag_mode;
 
};
 
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(dropdown_d));
 

	
 
struct vehiclelist_d {
 
	const Vehicle** sort_list;  // List of vehicles (sorted)
 
	Listing *_sorting;          // pointer to the appropiate subcategory of _sorting
 
@@ -592,7 +578,6 @@ static inline void GuiShowTooltips(Strin
 
/* widget.cpp */
 
int GetWidgetFromPos(const Window *w, int x, int y);
 
void DrawWindowWidgets(const Window *w);
 
void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, uint32 hidden_mask);
 

	
 

	
 
Window *GetCallbackWnd();
0 comments (0 inline, 0 general)