/** * 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 which is passed to Window::OnDropdownSelect and OnDropdownClose. * Unless you override those functions, this should be then widget index of the dropdown button. * @param wi_rect Coord of the parent drop down button, used to position the dropdown menu. * @param auto_width The width is determined by the widest item in the list, * in this case only one of \a left or \a right is used (depending on text direction). * @param instant_close Set to true if releasing mouse button should close the * list regardless of where the cursor is. */ void ShowDropDownListAt(Window *w, DropDownList *list, int selected, int button, Rect wi_rect, Colours wi_colour, bool auto_width, bool instant_close) { DeleteWindowById(WC_DROPDOWN_MENU, 0); /* The preferred position is just below the dropdown calling widget */ int top = w->top + wi_rect.bottom + 1; /* The preferred width equals the calling widget */ uint width = wi_rect.right - wi_rect.left + 1; uint max_item_width = 0; if (auto_width) { /* Find the longest item in the list */ for (DropDownList::const_iterator it = list->begin(); it != list->end(); ++it) { const DropDownListItem *item = *it; max_item_width = max(max_item_width, item->Width() + 5); } } /* 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 */ int screen_bottom = GetMainViewBottom(); bool scroll = false; /* Check if the dropdown will fully fit below the widget */ if (top + height + 4 >= screen_bottom) { /* If not, check if it will fit above the widget */ if (w->top + wi_rect.top - height > GetMainViewTop()) { top = w->top + wi_rect.top - height - 4; } else { /* ... and lastly if it won't, enable the scroll bar and fit the * list in below the widget */ int avg_height = list_height / (int)list->size(); int rows = (screen_bottom - 4 - top) / avg_height; height = rows * avg_height; scroll = true; /* Add space for the scroll bar if we automatically determined * the width of the list. */ max_item_width += NWidgetScrollbar::GetVerticalDimension().width; } } if (auto_width) width = max(width, max_item_width); Point dw_pos = { w->left + (_current_text_dir == TD_RTL ? wi_rect.right + 1 - width : wi_rect.left), top}; Dimension dw_size = {width, height}; new DropdownWindow(w, list, selected, button, instant_close, dw_pos, dw_size, wi_colour, scroll); }
/** * Create a dropdown menu. * @param parent Parent window. * @param list Dropdown item list. * @param selected Index of the selected item in the list. * @param button Widget of the parent window doing the dropdown. * @param instant_close Close the window when the mouse button is raised. * @param position Topleft position of the dropdown menu window. * @param size Size of the dropdown menu window. * @param wi_colour Colour of the parent widget. * @param scroll Dropdown menu has a scrollbar. * @param widget Widgets of the dropdown menu window. */ DropdownWindow(Window *parent, DropDownList *list, int selected, int button, bool instant_close, const Point &position, const Dimension &size, Colours wi_colour, bool scroll) : Window() { this->position = position; this->CreateNestedTree(&_dropdown_desc); this->vscroll = this->GetScrollbar(DDM_SCROLL); uint items_width = size.width - (scroll ? WD_VSCROLLBAR_WIDTH : 0); NWidgetCore *nwi = this->GetWidget<NWidgetCore>(DDM_ITEMS); nwi->SetMinimalSize(items_width, size.height + 4); nwi->colour = wi_colour; nwi = this->GetWidget<NWidgetCore>(DDM_SCROLL); nwi->colour = wi_colour; this->GetWidget<NWidgetStacked>(DDM_SHOW_SCROLL)->SetDisplayedPlane(scroll ? 0 : SZSP_NONE); this->FinishInitNested(&_dropdown_desc, 0); this->flags4 &= ~WF_WHITE_BORDER_MASK; /* 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(items_width); } /* Capacity is the average number of items visible */ this->vscroll->SetCapacity(size.height * (uint16)list->size() / list_height); this->vscroll->SetCount((uint16)list->size()); this->parent_wnd_class = parent->window_class; this->parent_wnd_num = parent->window_number; this->parent_button = button; this->list = list; this->selected_index = selected; this->click_delay = 0; this->drag_mode = true; this->instant_close = instant_close; }
void ShowDropDownList(Window *w, DropDownList *list, int selected, int button, uint width, bool auto_width, bool instant_close) { DeleteWindowById(WC_DROPDOWN_MENU, 0); /* Our parent's button widget is used to determine where to place the drop * down list window. */ Rect wi_rect; Colours wi_colour; NWidgetCore *nwi = w->GetWidget<NWidgetCore>(button); wi_rect.left = nwi->pos_x; wi_rect.right = nwi->pos_x + nwi->current_x - 1; wi_rect.top = nwi->pos_y; wi_rect.bottom = nwi->pos_y + nwi->current_y - 1; wi_colour = nwi->colour; if (nwi->type == NWID_BUTTON_DROPDOWN) { nwi->disp_flags |= ND_DROPDOWN_ACTIVE; } else { w->LowerWidget(button); } w->SetWidgetDirty(button); /* The preferred position is just below the dropdown calling widget */ int top = w->top + wi_rect.bottom + 1; if (width == 0) width = wi_rect.right - wi_rect.left + 1; uint max_item_width = 0; if (auto_width) { /* Find the longest item in the list */ for (DropDownList::const_iterator it = list->begin(); it != list->end(); ++it) { const DropDownListItem *item = *it; max_item_width = max(max_item_width, item->Width() + 5); } } /* 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 */ int screen_bottom = GetMainViewBottom(); bool scroll = false; /* Check if the dropdown will fully fit below the widget */ if (top + height + 4 >= screen_bottom) { /* If not, check if it will fit above the widget */ if (w->top + wi_rect.top - height > GetMainViewTop()) { top = w->top + wi_rect.top - height - 4; } else { /* ... and lastly if it won't, enable the scroll bar and fit the * list in below the widget */ int avg_height = list_height / (int)list->size(); int rows = (screen_bottom - 4 - top) / avg_height; height = rows * avg_height; scroll = true; /* Add space for the scroll bar if we automatically determined * the width of the list. */ max_item_width += WD_VSCROLLBAR_WIDTH; } } if (auto_width) width = max(width, max_item_width); Point dw_pos = { w->left + (_current_text_dir == TD_RTL ? wi_rect.right + 1 - width : wi_rect.left), top}; Dimension dw_size = {width, height}; new DropdownWindow(w, list, selected, button, instant_close, dw_pos, dw_size, wi_colour, scroll); }