diff --git a/src/widget.cpp b/src/widget.cpp --- a/src/widget.cpp +++ b/src/widget.cpp @@ -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;