forked from mirror/OpenTTD
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.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user