diff options
author | Michael Lutz <michi@icosahedron.de> | 2019-04-02 21:31:24 +0200 |
---|---|---|
committer | Michael Lutz <michi@icosahedron.de> | 2019-04-09 22:45:15 +0200 |
commit | c7b9987d081ae4e0103309b18c93deecc395dec9 (patch) | |
tree | e5b1f9553d6399e2eed9c05a2d91673205f9c912 /src/widgets | |
parent | d3e113eb5f618ce0174fa0dfa2591cb96e999350 (diff) | |
download | openttd-c7b9987d081ae4e0103309b18c93deecc395dec9.tar.xz |
Codechange: Switch DropDownList to directly use std::vector, thus making AutoDeleteSmallVector obsolete.
DropDownListItem are strongly managed using std::unique_ptr to ensure leak-free handling. Appropriate use
of move-semantics make intent a lot clearer than parameter comments and allows the compiler to generate
copy-free code for most situations.
Diffstat (limited to 'src/widgets')
-rw-r--r-- | src/widgets/dropdown.cpp | 56 | ||||
-rw-r--r-- | src/widgets/dropdown_type.h | 8 |
2 files changed, 27 insertions, 37 deletions
diff --git a/src/widgets/dropdown.cpp b/src/widgets/dropdown.cpp index d0ad6bc46..cb1382dd6 100644 --- a/src/widgets/dropdown.cpp +++ b/src/widgets/dropdown.cpp @@ -51,11 +51,11 @@ void DropDownListStringItem::Draw(int left, int right, int top, int bottom, bool * @return true if \a first precedes \a second. * @warning All items in the list need to be derivates of DropDownListStringItem. */ -/* static */ int DropDownListStringItem::NatSortFunc(const DropDownListItem * const *first, const DropDownListItem * const * second) +/* static */ int DropDownListStringItem::NatSortFunc(std::unique_ptr<const DropDownListItem> const &first, std::unique_ptr<const DropDownListItem> const &second) { char buffer1[512], buffer2[512]; - GetString(buffer1, static_cast<const DropDownListStringItem*>(*first)->String(), lastof(buffer1)); - GetString(buffer2, static_cast<const DropDownListStringItem*>(*second)->String(), lastof(buffer2)); + GetString(buffer1, static_cast<const DropDownListStringItem*>(first.get())->String(), lastof(buffer1)); + GetString(buffer2, static_cast<const DropDownListStringItem*>(second.get())->String(), lastof(buffer2)); return strnatcmp(buffer1, buffer2); } @@ -126,7 +126,7 @@ struct DropdownWindow : Window { WindowClass parent_wnd_class; ///< Parent window class. WindowNumber parent_wnd_num; ///< Parent window number. int parent_button; ///< Parent widget number where the window is dropped from. - const DropDownList *list; ///< List with dropdown menu items. + const DropDownList list; ///< List with dropdown menu items. int selected_index; ///< Index of the selected item in the list. byte click_delay; ///< Timer to delay selection. bool drag_mode; @@ -148,10 +148,10 @@ struct DropdownWindow : Window { * @param wi_colour Colour of the parent widget. * @param scroll Dropdown menu has a scrollbar. */ - DropdownWindow(Window *parent, const DropDownList *list, int selected, int button, bool instant_close, const Point &position, const Dimension &size, Colours wi_colour, bool scroll) - : Window(&_dropdown_desc) + DropdownWindow(Window *parent, DropDownList &&list, int selected, int button, bool instant_close, const Point &position, const Dimension &size, Colours wi_colour, bool scroll) + : Window(&_dropdown_desc), list(std::move(list)) { - assert(list->size() > 0); + assert(this->list.size() > 0); this->position = position; @@ -174,18 +174,17 @@ struct DropdownWindow : Window { /* Total length of list */ int list_height = 0; - for (const DropDownListItem *item : *list) { + for (const auto &item : this->list) { 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->vscroll->SetCapacity(size.height * (uint16)this->list.size() / list_height); + this->vscroll->SetCount((uint16)this->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; @@ -207,7 +206,6 @@ struct DropdownWindow : Window { pt.y -= w2->top; w2->OnDropdownClose(pt, this->parent_button, this->selected_index, this->instant_close); } - delete this->list; } virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) @@ -229,7 +227,7 @@ struct DropdownWindow : Window { int width = nwi->current_x - 4; int pos = this->vscroll->GetPosition(); - for (const DropDownListItem *item : *this->list) { + for (const auto &item : this->list) { /* Skip items that are scrolled up */ if (--pos >= 0) continue; @@ -255,7 +253,7 @@ struct DropdownWindow : Window { int y = r.top + 2; int pos = this->vscroll->GetPosition(); - for (const DropDownListItem *item : *this->list) { + for (const auto &item : this->list) { int item_height = item->Height(r.right - r.left + 1); /* Skip items that are scrolled up */ @@ -357,8 +355,7 @@ struct DropdownWindow : Window { /** * 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 list Prepopulated DropDownList. * @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. @@ -368,7 +365,7 @@ struct DropdownWindow : Window { * @param instant_close Set to true if releasing mouse button should close the * list regardless of where the cursor is. */ -void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int button, Rect wi_rect, Colours wi_colour, bool auto_width, bool instant_close) +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); @@ -384,7 +381,7 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b /* Total height of list */ uint height = 0; - for (const DropDownListItem *item : *list) { + for (const auto &item : list) { height += item->Height(width); if (auto_width) max_item_width = max(max_item_width, item->Width() + 5); } @@ -412,7 +409,7 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b /* If the dropdown doesn't fully fit, we need a dropdown. */ if (height > available_height) { scroll = true; - uint avg_height = height / (uint)list->size(); + uint avg_height = height / (uint)list.size(); /* Check at least there is space for one item. */ assert(available_height >= avg_height); @@ -435,7 +432,7 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b Point dw_pos = { w->left + (_current_text_dir == TD_RTL ? wi_rect.right + 1 - (int)width : wi_rect.left), top}; Dimension dw_size = {width, height}; - DropdownWindow *dropdown = new DropdownWindow(w, list, selected, button, instant_close, dw_pos, dw_size, wi_colour, scroll); + DropdownWindow *dropdown = new DropdownWindow(w, std::move(list), selected, button, instant_close, dw_pos, dw_size, wi_colour, scroll); /* The dropdown starts scrolling downwards when opening it towards * the top and holding down the mouse button. It can be fooled by @@ -446,8 +443,7 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b /** * 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 list Prepopulated DropDownList. * @param selected The initially selected list item. * @param button The widget within the parent window that is used to determine * the list's location. @@ -456,7 +452,7 @@ void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int b * @param instant_close Set to true if releasing mouse button should close the * list regardless of where the cursor is. */ -void ShowDropDownList(Window *w, const DropDownList *list, int selected, int button, uint width, bool auto_width, bool instant_close) +void ShowDropDownList(Window *w, DropDownList &&list, int selected, int button, uint width, bool auto_width, bool instant_close) { /* Our parent's button widget is used to determine where to place the drop * down list window. */ @@ -483,7 +479,7 @@ void ShowDropDownList(Window *w, const DropDownList *list, int selected, int but } } - ShowDropDownListAt(w, list, selected, button, wi_rect, wi_colour, auto_width, instant_close); + ShowDropDownListAt(w, std::move(list), selected, button, wi_rect, wi_colour, auto_width, instant_close); } /** @@ -499,21 +495,15 @@ void ShowDropDownList(Window *w, const DropDownList *list, int selected, int but */ void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, uint32 hidden_mask, uint width) { - DropDownList *list = new DropDownList(); + DropDownList list; for (uint i = 0; strings[i] != INVALID_STRING_ID; i++) { if (!HasBit(hidden_mask, i)) { - list->push_back(new DropDownListStringItem(strings[i], i, HasBit(disabled_mask, i))); + list.emplace_back(new DropDownListStringItem(strings[i], i, HasBit(disabled_mask, i))); } } - /* No entries in the list? */ - if (list->size() == 0) { - delete list; - return; - } - - ShowDropDownList(w, list, selected, button, width); + if (!list.empty()) ShowDropDownList(w, std::move(list), selected, button, width); } /** diff --git a/src/widgets/dropdown_type.h b/src/widgets/dropdown_type.h index bf8638a92..26c699f16 100644 --- a/src/widgets/dropdown_type.h +++ b/src/widgets/dropdown_type.h @@ -49,7 +49,7 @@ public: void Draw(int left, int right, int top, int bottom, bool sel, Colours bg_colour) const override; virtual StringID String() const { return this->string; } - static int CDECL NatSortFunc(const DropDownListItem * const *first, const DropDownListItem * const *second); + static int NatSortFunc(std::unique_ptr<const DropDownListItem> const &first, std::unique_ptr<const DropDownListItem> const &second); }; /** @@ -98,10 +98,10 @@ public: /** * A drop down list is a collection of drop down list items. */ -typedef AutoDeleteSmallVector<const DropDownListItem *> DropDownList; +typedef std::vector<std::unique_ptr<const DropDownListItem>> DropDownList; -void ShowDropDownListAt(Window *w, const DropDownList *list, int selected, int button, Rect wi_rect, Colours wi_colour, bool auto_width = false, bool instant_close = false); +void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, int button, Rect wi_rect, Colours wi_colour, bool auto_width = false, bool instant_close = false); -void ShowDropDownList(Window *w, const DropDownList *list, int selected, int button, uint width = 0, bool auto_width = false, bool instant_close = false); +void ShowDropDownList(Window *w, DropDownList &&list, int selected, int button, uint width = 0, bool auto_width = false, bool instant_close = false); #endif /* WIDGETS_DROPDOWN_TYPE_H */ |