1
0
Fork 0

(svn r12672) -Codechange: Add support for variably-sized drop down list items.

release/0.7
peter1138 2008-04-12 20:32:18 +00:00
parent f44aa5e088
commit 711909fa0c
2 changed files with 52 additions and 23 deletions

View File

@ -20,6 +20,11 @@ StringID DropDownListItem::String() const
return STR_NULL; return STR_NULL;
} }
uint DropDownListItem::Height(uint width) const
{
return 10;
}
StringID DropDownListStringItem::String() const StringID DropDownListStringItem::String() const
{ {
return this->string; return this->string;
@ -66,20 +71,25 @@ static int GetDropDownItem(const Window *w)
{ {
if (GetWidgetFromPos(w, _cursor.pos.x - w->left, _cursor.pos.y - w->top) < 0) return -1; 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; int y = _cursor.pos.y - w->top - 2;
if (y < 0) return -1; int width = w->widget[0].right - 3;
int pos = w->vscroll.pos;
uint selected_row = y / 10;
const DropDownList *list = WP(w, dropdown_d).list; 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) {
/* Skip items that are scrolled up */
if (--pos >= 0) continue;
for (DropDownList::const_iterator it = list->begin(); it != list->end(); ++it, selected_row--) { const DropDownListItem *item = *it;
if (selected_row == 0) { int item_height = item->Height(width);
const DropDownListItem *item = *it;
if (y < item_height) {
if (item->masked || item->String() == STR_NULL) return -1; if (item->masked || item->String() == STR_NULL) return -1;
return item->result; return item->result;
} }
y -= item_height;
} }
return -1; return -1;
@ -92,24 +102,30 @@ static void DropDownMenuWndProc(Window *w, WindowEvent *e)
DrawWindowWidgets(w); DrawWindowWidgets(w);
int x = 1; int x = 1;
int y = 2 - w->vscroll.pos * 10; int y = 2;
int sel = WP(w, dropdown_d).selected_index; int sel = WP(w, dropdown_d).selected_index;
int width = w->widget[0].right - 3; int width = w->widget[0].right - 3;
int height = w->widget[0].bottom - 3; int height = w->widget[0].bottom;
int pos = w->vscroll.pos;
DropDownList *list = WP(w, dropdown_d).list; DropDownList *list = WP(w, dropdown_d).list;
for (DropDownList::const_iterator it = list->begin(); it != list->end(); ++it) { for (DropDownList::const_iterator it = list->begin(); it != list->end(); ++it) {
if (y >= 0 && y <= height) { const DropDownListItem *item = *it;
const DropDownListItem *item = *it; int item_height = item->Height(width);
/* Skip items that are scrolled up */
if (--pos >= 0) continue;
if (y + item_height < height) {
if (item->String() != STR_NULL) { if (item->String() != STR_NULL) {
if (sel == item->result) GfxFillRect(x + 1, y, x + width, y + 9, 0); if (sel == item->result) GfxFillRect(x + 1, y, x + width, y + item_height - 1, 0);
DrawStringTruncated(x + 2, y, item->String(), sel == item->result ? TC_WHITE : TC_BLACK, x + width); DrawStringTruncated(x + 2, y, item->String(), sel == item->result ? TC_WHITE : TC_BLACK, x + width);
if (item->masked) { if (item->masked) {
GfxFillRect(x, y, x + width, y + 9, GfxFillRect(x, y, x + width, y + item_height - 1,
(1 << PALETTE_MODIFIER_GREYOUT) | _colour_gradient[w->widget[0].color][5] (1 << PALETTE_MODIFIER_GREYOUT) | _colour_gradient[w->widget[0].color][5]
); );
} }
@ -121,7 +137,7 @@ static void DropDownMenuWndProc(Window *w, WindowEvent *e)
GfxFillRect(x + 1, y + 4, x + w->width - 5, y + 4, c2); GfxFillRect(x + 1, y + 4, x + w->width - 5, y + 4, c2);
} }
} }
y += 10; y += item_height;
} }
} break; } break;
@ -221,7 +237,17 @@ void ShowDropDownList(Window *w, DropDownList *list, int selected, int button, u
/* The preferred position is just below the dropdown calling widget */ /* The preferred position is just below the dropdown calling widget */
int top = w->top + wi->bottom + 1; int top = w->top + wi->bottom + 1;
int height = list->size() * 10 + 4;
/* Total length of list */
int list_height = 0;
for (DropDownList::const_iterator it = list->begin(); it != list->end(); ++it) {
DropDownListItem *item = *it;
list_height += item->Height(width);
}
/* Height of window visible */
int height = list_height;
/* Check if the status bar is visible, as we don't want to draw over it */ /* Check if the status bar is visible, as we don't want to draw over it */
Window *w3 = FindWindowById(WC_STATUS_BAR, 0); Window *w3 = FindWindowById(WC_STATUS_BAR, 0);
@ -230,18 +256,19 @@ void ShowDropDownList(Window *w, DropDownList *list, int selected, int button, u
bool scroll = false; bool scroll = false;
/* Check if the dropdown will fully fit below the widget */ /* Check if the dropdown will fully fit below the widget */
if (top + height >= screen_bottom) { if (top + height + 4 >= screen_bottom) {
w3 = FindWindowById(WC_MAIN_TOOLBAR, 0); w3 = FindWindowById(WC_MAIN_TOOLBAR, 0);
int screen_top = w3 == NULL ? 0 : w3->top + w3->height; int screen_top = w3 == NULL ? 0 : w3->top + w3->height;
/* If not, check if it will fit above the widget */ /* If not, check if it will fit above the widget */
if (w->top + wi->top - height > screen_top) { if (w->top + wi->top - height > screen_top) {
top = w->top + wi->top - height; top = w->top + wi->top - height - 4;
} else { } else {
/* ... and lastly if it won't, enable the scroll bar and fit the /* ... and lastly if it won't, enable the scroll bar and fit the
* list in below the widget */ * list in below the widget */
int rows = (screen_bottom - 4 - top) / 10; int avg_height = list_height / list->size();
height = rows * 10 + 4; int rows = (screen_bottom - 4 - top) / avg_height;
height = rows * avg_height;
scroll = true; scroll = true;
} }
} }
@ -252,14 +279,14 @@ void ShowDropDownList(Window *w, DropDownList *list, int selected, int button, u
w->left + wi->left, w->left + wi->left,
top, top,
width, width,
height, height + 4,
DropDownMenuWndProc, DropDownMenuWndProc,
WC_DROPDOWN_MENU, WC_DROPDOWN_MENU,
_dropdown_menu_widgets); _dropdown_menu_widgets);
dw->widget[0].color = wi->color; dw->widget[0].color = wi->color;
dw->widget[0].right = width - 1; dw->widget[0].right = width - 1;
dw->widget[0].bottom = height - 1; dw->widget[0].bottom = height + 3;
dw->SetWidgetHiddenState(1, !scroll); dw->SetWidgetHiddenState(1, !scroll);
@ -269,10 +296,11 @@ void ShowDropDownList(Window *w, DropDownList *list, int selected, int button, u
dw->widget[1].color = wi->color; dw->widget[1].color = wi->color;
dw->widget[1].right = dw->widget[0].right; dw->widget[1].right = dw->widget[0].right;
dw->widget[1].left = dw->widget[1].right - 11; dw->widget[1].left = dw->widget[1].right - 11;
dw->widget[1].bottom = height - 1; dw->widget[1].bottom = dw->widget[0].bottom;
dw->widget[0].right -= 12; dw->widget[0].right -= 12;
dw->vscroll.cap = (height - 4) / 10; /* Capacity is the average number of items visible */
dw->vscroll.cap = height * list->size() / list_height;
dw->vscroll.count = list->size(); dw->vscroll.count = list->size();
} }

View File

@ -18,6 +18,7 @@ public:
DropDownListItem(int result, bool masked) : result(result), masked(masked) {} DropDownListItem(int result, bool masked) : result(result), masked(masked) {}
virtual ~DropDownListItem() {} virtual ~DropDownListItem() {}
virtual StringID String() const; virtual StringID String() const;
virtual uint Height(uint width) const;
}; };
/** /**