From 7124b4eef12155051e824d09bbe8dc74773ef603 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sat, 30 Dec 2023 07:36:22 +0000 Subject: [PATCH] Codechange: Use std::unique_ptr for all NWidgets. --- src/graph_gui.cpp | 18 +-- src/linkgraph/linkgraph_gui.cpp | 30 ++--- src/network/network_gui.cpp | 20 ++-- src/newgrf_gui.cpp | 40 ++++--- src/osk_gui.cpp | 38 +++--- src/script/script_gui.cpp | 2 +- src/smallmap_gui.cpp | 8 +- src/station_gui.cpp | 8 +- src/tests/test_window_desc.cpp | 3 +- src/toolbar_gui.cpp | 14 +-- src/tree_gui.cpp | 12 +- src/widget.cpp | 198 +++++++++++++++----------------- src/widget_type.h | 18 +-- src/window.cpp | 1 - src/window_gui.h | 2 +- 15 files changed, 200 insertions(+), 212 deletions(-) diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index 20186a6080..6952b8ec60 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -109,19 +109,19 @@ struct GraphLegendWindow : Window { * Construct a vertical list of buttons, one for each company. * @return Panel with company buttons. */ -static NWidgetBase *MakeNWidgetCompanyLines() +static std::unique_ptr MakeNWidgetCompanyLines() { - NWidgetVertical *vert = new NWidgetVertical(NC_EQUALSIZE); + auto vert = std::make_unique(NC_EQUALSIZE); vert->SetPadding(2, 2, 2, 2); uint sprite_height = GetSpriteSize(SPR_COMPANY_ICON, nullptr, ZOOM_LVL_OUT_4X).height; for (WidgetID widnum = WID_GL_FIRST_COMPANY; widnum <= WID_GL_LAST_COMPANY; widnum++) { - NWidgetBackground *panel = new NWidgetBackground(WWT_PANEL, COLOUR_BROWN, widnum); + auto panel = std::make_unique(WWT_PANEL, COLOUR_BROWN, widnum); panel->SetMinimalSize(246, sprite_height + WidgetDimensions::unscaled.framerect.Vertical()); panel->SetMinimalTextLines(1, WidgetDimensions::unscaled.framerect.Vertical(), FS_NORMAL); panel->SetFill(1, 1); panel->SetDataTip(0x0, STR_GRAPH_KEY_COMPANY_SELECTION_TOOLTIP); - vert->Add(panel); + vert->Add(std::move(panel)); } return vert; } @@ -1337,7 +1337,7 @@ CompanyID PerformanceRatingDetailWindow::company = INVALID_COMPANY; * Make a vertical list of panels for outputting score details. * @return Panel with performance details. */ -static NWidgetBase *MakePerformanceDetailPanels() +static std::unique_ptr MakePerformanceDetailPanels() { const StringID performance_tips[] = { STR_PERFORMANCE_DETAIL_VEHICLES_TOOLTIP, @@ -1354,18 +1354,18 @@ static NWidgetBase *MakePerformanceDetailPanels() static_assert(lengthof(performance_tips) == SCORE_END - SCORE_BEGIN); - NWidgetVertical *vert = new NWidgetVertical(NC_EQUALSIZE); + auto vert = std::make_unique(NC_EQUALSIZE); for (WidgetID widnum = WID_PRD_SCORE_FIRST; widnum <= WID_PRD_SCORE_LAST; widnum++) { - NWidgetBackground *panel = new NWidgetBackground(WWT_PANEL, COLOUR_BROWN, widnum); + auto panel = std::make_unique(WWT_PANEL, COLOUR_BROWN, widnum); panel->SetFill(1, 1); panel->SetDataTip(0x0, performance_tips[widnum - WID_PRD_SCORE_FIRST]); - vert->Add(panel); + vert->Add(std::move(panel)); } return vert; } /** Make a number of rows with buttons for each company for the performance rating detail window. */ -NWidgetBase *MakeCompanyButtonRowsGraphGUI() +std::unique_ptr MakeCompanyButtonRowsGraphGUI() { return MakeCompanyButtonRows(WID_PRD_COMPANY_FIRST, WID_PRD_COMPANY_LAST, COLOUR_BROWN, 8, STR_PERFORMANCE_DETAIL_SELECT_COMPANY_TOOLTIP); } diff --git a/src/linkgraph/linkgraph_gui.cpp b/src/linkgraph/linkgraph_gui.cpp index ad3661b44e..6f44f5c601 100644 --- a/src/linkgraph/linkgraph_gui.cpp +++ b/src/linkgraph/linkgraph_gui.cpp @@ -454,54 +454,54 @@ void LinkGraphOverlay::SetCompanyMask(CompanyMask company_mask) } /** Make a number of rows with buttons for each company for the linkgraph legend window. */ -NWidgetBase *MakeCompanyButtonRowsLinkGraphGUI() +std::unique_ptr MakeCompanyButtonRowsLinkGraphGUI() { return MakeCompanyButtonRows(WID_LGL_COMPANY_FIRST, WID_LGL_COMPANY_LAST, COLOUR_GREY, 3, STR_NULL); } -NWidgetBase *MakeSaturationLegendLinkGraphGUI() +std::unique_ptr MakeSaturationLegendLinkGraphGUI() { - NWidgetVertical *panel = new NWidgetVertical(NC_EQUALSIZE); + auto panel = std::make_unique(NC_EQUALSIZE); for (uint i = 0; i < lengthof(LinkGraphOverlay::LINK_COLOURS[0]); ++i) { - NWidgetBackground * wid = new NWidgetBackground(WWT_PANEL, COLOUR_DARK_GREEN, i + WID_LGL_SATURATION_FIRST); + auto wid = std::make_unique(WWT_PANEL, COLOUR_DARK_GREEN, i + WID_LGL_SATURATION_FIRST); wid->SetMinimalSize(50, 0); wid->SetMinimalTextLines(1, 0, FS_SMALL); wid->SetFill(1, 1); wid->SetResize(0, 0); - panel->Add(wid); + panel->Add(std::move(wid)); } return panel; } -NWidgetBase *MakeCargoesLegendLinkGraphGUI() +std::unique_ptr MakeCargoesLegendLinkGraphGUI() { uint num_cargo = static_cast(_sorted_cargo_specs.size()); static const uint ENTRIES_PER_COL = 5; - NWidgetHorizontal *panel = new NWidgetHorizontal(NC_EQUALSIZE); - NWidgetVertical *col = nullptr; + auto panel = std::make_unique(NC_EQUALSIZE); + std::unique_ptr col = nullptr; for (uint i = 0; i < num_cargo; ++i) { if (i % ENTRIES_PER_COL == 0) { - if (col != nullptr) panel->Add(col); - col = new NWidgetVertical(NC_EQUALSIZE); + if (col != nullptr) panel->Add(std::move(col)); + col = std::make_unique(NC_EQUALSIZE); } - NWidgetBackground * wid = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, i + WID_LGL_CARGO_FIRST); + auto wid = std::make_unique(WWT_PANEL, COLOUR_GREY, i + WID_LGL_CARGO_FIRST); wid->SetMinimalSize(25, 0); wid->SetMinimalTextLines(1, 0, FS_SMALL); wid->SetFill(1, 1); wid->SetResize(0, 0); - col->Add(wid); + col->Add(std::move(wid)); } /* Fill up last row */ for (uint i = num_cargo; i < Ceil(num_cargo, ENTRIES_PER_COL); ++i) { - NWidgetSpacer *spc = new NWidgetSpacer(25, 0); + auto spc = std::make_unique(25, 0); spc->SetMinimalTextLines(1, 0, FS_SMALL); spc->SetFill(1, 1); spc->SetResize(0, 0); - col->Add(spc); + col->Add(std::move(spc)); } /* If there are no cargo specs defined, then col won't have been created so don't add it. */ - if (col != nullptr) panel->Add(col); + if (col != nullptr) panel->Add(std::move(col)); return panel; } diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 0ce4e55be2..29227844bf 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -89,21 +89,21 @@ class NWidgetServerListHeader : public NWidgetContainer { public: NWidgetServerListHeader() : NWidgetContainer(NWID_HORIZONTAL) { - NWidgetLeaf *leaf = new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_NAME, STR_NETWORK_SERVER_LIST_GAME_NAME, STR_NETWORK_SERVER_LIST_GAME_NAME_TOOLTIP); + auto leaf = std::make_unique(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_NAME, STR_NETWORK_SERVER_LIST_GAME_NAME, STR_NETWORK_SERVER_LIST_GAME_NAME_TOOLTIP); leaf->SetResize(1, 0); leaf->SetFill(1, 0); - this->Add(leaf); + this->Add(std::move(leaf)); - this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_CLIENTS, STR_NETWORK_SERVER_LIST_CLIENTS_CAPTION, STR_NETWORK_SERVER_LIST_CLIENTS_CAPTION_TOOLTIP)); - this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_MAPSIZE, STR_NETWORK_SERVER_LIST_MAP_SIZE_CAPTION, STR_NETWORK_SERVER_LIST_MAP_SIZE_CAPTION_TOOLTIP)); - this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_DATE, STR_NETWORK_SERVER_LIST_DATE_CAPTION, STR_NETWORK_SERVER_LIST_DATE_CAPTION_TOOLTIP)); - this->Add(new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_YEARS, STR_NETWORK_SERVER_LIST_YEARS_CAPTION, STR_NETWORK_SERVER_LIST_YEARS_CAPTION_TOOLTIP)); + this->Add(std::make_unique(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_CLIENTS, STR_NETWORK_SERVER_LIST_CLIENTS_CAPTION, STR_NETWORK_SERVER_LIST_CLIENTS_CAPTION_TOOLTIP)); + this->Add(std::make_unique(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_MAPSIZE, STR_NETWORK_SERVER_LIST_MAP_SIZE_CAPTION, STR_NETWORK_SERVER_LIST_MAP_SIZE_CAPTION_TOOLTIP)); + this->Add(std::make_unique(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_DATE, STR_NETWORK_SERVER_LIST_DATE_CAPTION, STR_NETWORK_SERVER_LIST_DATE_CAPTION_TOOLTIP)); + this->Add(std::make_unique(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_YEARS, STR_NETWORK_SERVER_LIST_YEARS_CAPTION, STR_NETWORK_SERVER_LIST_YEARS_CAPTION_TOOLTIP)); - leaf = new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_INFO, STR_EMPTY, STR_NETWORK_SERVER_LIST_INFO_ICONS_TOOLTIP); + leaf = std::make_unique(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_INFO, STR_EMPTY, STR_NETWORK_SERVER_LIST_INFO_ICONS_TOOLTIP); leaf->SetMinimalSize(14 + GetSpriteSize(SPR_LOCK, nullptr, ZOOM_LVL_OUT_4X).width + GetSpriteSize(SPR_BLOT, nullptr, ZOOM_LVL_OUT_4X).width, 12); leaf->SetFill(0, 1); - this->Add(leaf); + this->Add(std::move(leaf)); } void SetupSmallestSize(Window *w) override @@ -866,9 +866,9 @@ GUIGameServerList::FilterFunction * const NetworkGameWindow::filter_funcs[] = { &NGameSearchFilter }; -static NWidgetBase *MakeResizableHeader() +static std::unique_ptr MakeResizableHeader() { - return new NWidgetServerListHeader(); + return std::make_unique(); } static const NWidgetPart _nested_network_game_widgets[] = { diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index fd9dd69f87..57071d28d3 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -1600,27 +1600,22 @@ NewGRFWindow::GUIGRFConfigList::FilterFunction * const NewGRFWindow::filter_func * - two column mode, put the #acs and the #avs underneath each other and the #inf next to it, or * - three column mode, put the #avs, #acs, and #inf each in its own column. */ -class NWidgetNewGRFDisplay : public NWidgetContainer { +class NWidgetNewGRFDisplay : public NWidgetBase { public: static const uint MAX_EXTRA_INFO_WIDTH; ///< Maximal additional width given to the panel. static const uint MIN_EXTRA_FOR_3_COLUMNS; ///< Minimal additional width needed before switching to 3 columns. - NWidgetBase *avs; ///< Widget with the available grfs list and buttons. - NWidgetBase *acs; ///< Widget with the active grfs list and buttons. - NWidgetBase *inf; ///< Info panel. + std::unique_ptr avs; ///< Widget with the available grfs list and buttons. + std::unique_ptr acs; ///< Widget with the active grfs list and buttons. + std::unique_ptr inf; ///< Info panel. bool editable; ///< Editable status of the parent NewGRF window (if \c false, drop all widgets that make the window editable). - NWidgetNewGRFDisplay(NWidgetBase *avs, NWidgetBase *acs, NWidgetBase *inf) : NWidgetContainer(NWID_HORIZONTAL) + NWidgetNewGRFDisplay(std::unique_ptr &&avs, std::unique_ptr &&acs, std::unique_ptr &&inf) : NWidgetBase(NWID_CUSTOM) + , avs(std::move(avs)) + , acs(std::move(acs)) + , inf(std::move(inf)) + , editable(true) // Temporary setting, 'real' value is set in SetupSmallestSize(). { - this->avs = avs; - this->acs = acs; - this->inf = inf; - - this->Add(this->avs); - this->Add(this->acs); - this->Add(this->inf); - - this->editable = true; // Temporary setting, 'real' value is set in SetupSmallestSize(). } void SetupSmallestSize(Window *w) override @@ -1785,6 +1780,13 @@ public: } } + void FillWidgetLookup(WidgetLookup &widget_lookup) override + { + this->avs->FillWidgetLookup(widget_lookup); + this->acs->FillWidgetLookup(widget_lookup); + this->inf->FillWidgetLookup(widget_lookup); + } + NWidgetCore *GetWidgetFromPos(int x, int y) override { if (!IsInsideBS(x, this->pos_x, this->current_x) || !IsInsideBS(y, this->pos_y, this->current_y)) return nullptr; @@ -1937,13 +1939,13 @@ static const NWidgetPart _nested_newgrf_infopanel_widgets[] = { }; /** Construct nested container widget for managing the lists and the info panel of the NewGRF GUI. */ -NWidgetBase* NewGRFDisplay() +std::unique_ptr NewGRFDisplay() { - NWidgetBase *avs = MakeNWidgets(std::begin(_nested_newgrf_availables_widgets), std::end(_nested_newgrf_availables_widgets), nullptr); - NWidgetBase *acs = MakeNWidgets(std::begin(_nested_newgrf_actives_widgets), std::end(_nested_newgrf_actives_widgets), nullptr); - NWidgetBase *inf = MakeNWidgets(std::begin(_nested_newgrf_infopanel_widgets), std::end(_nested_newgrf_infopanel_widgets), nullptr); + std::unique_ptr avs = MakeNWidgets(std::begin(_nested_newgrf_availables_widgets), std::end(_nested_newgrf_availables_widgets), nullptr); + std::unique_ptr acs = MakeNWidgets(std::begin(_nested_newgrf_actives_widgets), std::end(_nested_newgrf_actives_widgets), nullptr); + std::unique_ptr inf = MakeNWidgets(std::begin(_nested_newgrf_infopanel_widgets), std::end(_nested_newgrf_infopanel_widgets), nullptr); - return new NWidgetNewGRFDisplay(avs, acs, inf); + return std::make_unique(std::move(avs), std::move(acs), std::move(inf)); } /* Widget definition of the manage newgrfs window */ diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp index 627e264138..bdd1e0f0e3 100644 --- a/src/osk_gui.cpp +++ b/src/osk_gui.cpp @@ -222,32 +222,32 @@ static const int KEY_PADDING = 6; // Vertical padding for remaining key rows * @param widdata Data value of the key widget. * @note Key width is measured in 1/2 keys to allow for 1/2 key shifting between rows. */ -static void AddKey(NWidgetHorizontal *hor, int pad_y, int num_half, WidgetType widtype, WidgetID widnum, uint16_t widdata) +static void AddKey(std::unique_ptr &hor, int pad_y, int num_half, WidgetType widtype, WidgetID widnum, uint16_t widdata) { int key_width = HALF_KEY_WIDTH + (INTER_KEY_SPACE + HALF_KEY_WIDTH) * (num_half - 1); if (widtype == NWID_SPACER) { if (!hor->IsEmpty()) key_width += INTER_KEY_SPACE; - NWidgetSpacer *spc = new NWidgetSpacer(key_width, 0); + auto spc = std::make_unique(key_width, 0); spc->SetMinimalTextLines(1, pad_y, FS_NORMAL); - hor->Add(spc); + hor->Add(std::move(spc)); } else { if (!hor->IsEmpty()) { - NWidgetSpacer *spc = new NWidgetSpacer(INTER_KEY_SPACE, 0); + auto spc = std::make_unique(INTER_KEY_SPACE, 0); spc->SetMinimalTextLines(1, pad_y, FS_NORMAL); - hor->Add(spc); + hor->Add(std::move(spc)); } - NWidgetLeaf *leaf = new NWidgetLeaf(widtype, COLOUR_GREY, widnum, widdata, STR_NULL); + auto leaf = std::make_unique(widtype, COLOUR_GREY, widnum, widdata, STR_NULL); leaf->SetMinimalSize(key_width, 0); leaf->SetMinimalTextLines(1, pad_y, FS_NORMAL); - hor->Add(leaf); + hor->Add(std::move(leaf)); } } /** Construct the top row keys (cancel, ok, backspace). */ -static NWidgetBase *MakeTopKeys() +static std::unique_ptr MakeTopKeys() { - NWidgetHorizontal *hor = new NWidgetHorizontal(); + auto hor = std::make_unique(); AddKey(hor, TOP_KEY_PADDING, 6 * 2, WWT_TEXTBTN, WID_OSK_CANCEL, STR_BUTTON_CANCEL); AddKey(hor, TOP_KEY_PADDING, 6 * 2, WWT_TEXTBTN, WID_OSK_OK, STR_BUTTON_OK ); @@ -256,9 +256,9 @@ static NWidgetBase *MakeTopKeys() } /** Construct the row containing the digit keys. */ -static NWidgetBase *MakeNumberKeys() +static std::unique_ptr MakeNumberKeys() { - NWidgetHorizontal *hor = new NWidgetHorizontalLTR(); + std::unique_ptr hor = std::make_unique(); for (WidgetID widnum = WID_OSK_NUMBERS_FIRST; widnum <= WID_OSK_NUMBERS_LAST; widnum++) { AddKey(hor, KEY_PADDING, 2, WWT_PUSHBTN, widnum, 0x0); @@ -267,9 +267,9 @@ static NWidgetBase *MakeNumberKeys() } /** Construct the qwerty row keys. */ -static NWidgetBase *MakeQwertyKeys() +static std::unique_ptr MakeQwertyKeys() { - NWidgetHorizontal *hor = new NWidgetHorizontalLTR(); + std::unique_ptr hor = std::make_unique(); AddKey(hor, KEY_PADDING, 3, WWT_PUSHIMGBTN, WID_OSK_SPECIAL, SPR_OSK_SPECIAL); for (WidgetID widnum = WID_OSK_QWERTY_FIRST; widnum <= WID_OSK_QWERTY_LAST; widnum++) { @@ -280,9 +280,9 @@ static NWidgetBase *MakeQwertyKeys() } /** Construct the asdfg row keys. */ -static NWidgetBase *MakeAsdfgKeys() +static std::unique_ptr MakeAsdfgKeys() { - NWidgetHorizontal *hor = new NWidgetHorizontalLTR(); + std::unique_ptr hor = std::make_unique(); AddKey(hor, KEY_PADDING, 4, WWT_IMGBTN, WID_OSK_CAPS, SPR_OSK_CAPS); for (WidgetID widnum = WID_OSK_ASDFG_FIRST; widnum <= WID_OSK_ASDFG_LAST; widnum++) { @@ -292,9 +292,9 @@ static NWidgetBase *MakeAsdfgKeys() } /** Construct the zxcvb row keys. */ -static NWidgetBase *MakeZxcvbKeys() +static std::unique_ptr MakeZxcvbKeys() { - NWidgetHorizontal *hor = new NWidgetHorizontalLTR(); + std::unique_ptr hor = std::make_unique(); AddKey(hor, KEY_PADDING, 3, WWT_IMGBTN, WID_OSK_SHIFT, SPR_OSK_SHIFT); for (WidgetID widnum = WID_OSK_ZXCVB_FIRST; widnum <= WID_OSK_ZXCVB_LAST; widnum++) { @@ -305,9 +305,9 @@ static NWidgetBase *MakeZxcvbKeys() } /** Construct the spacebar row keys. */ -static NWidgetBase *MakeSpacebarKeys() +static std::unique_ptr MakeSpacebarKeys() { - NWidgetHorizontal *hor = new NWidgetHorizontal(); + auto hor = std::make_unique(); AddKey(hor, KEY_PADDING, 8, NWID_SPACER, 0, 0); AddKey(hor, KEY_PADDING, 13, WWT_PUSHTXTBTN, WID_OSK_SPACE, STR_EMPTY); diff --git a/src/script/script_gui.cpp b/src/script/script_gui.cpp index f89e7f3f59..8a8fa7b2ca 100644 --- a/src/script/script_gui.cpp +++ b/src/script/script_gui.cpp @@ -1229,7 +1229,7 @@ struct ScriptDebugWindow : public Window { }; /** Make a number of rows with buttons for each company for the Script debug window. */ -NWidgetBase *MakeCompanyButtonRowsScriptDebug() +std::unique_ptr MakeCompanyButtonRowsScriptDebug() { return MakeCompanyButtonRows(WID_SCRD_COMPANY_BUTTON_START, WID_SCRD_COMPANY_BUTTON_END, COLOUR_GREY, 8, STR_AI_DEBUG_SELECT_AI_TOOLTIP); } diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index a91760f646..51acb14a26 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -1944,12 +1944,12 @@ static const NWidgetPart _nested_smallmap_bar[] = { EndContainer(), }; -static NWidgetBase *SmallMapDisplay() +static std::unique_ptr SmallMapDisplay() { - NWidgetContainer *map_display = new NWidgetSmallmapDisplay; + std::unique_ptr map_display = std::make_unique(); - MakeNWidgets(std::begin(_nested_smallmap_display), std::end(_nested_smallmap_display), map_display); - MakeNWidgets(std::begin(_nested_smallmap_bar), std::end(_nested_smallmap_bar), map_display); + map_display = MakeNWidgets(std::begin(_nested_smallmap_display), std::end(_nested_smallmap_display), std::move(map_display)); + map_display = MakeNWidgets(std::begin(_nested_smallmap_bar), std::end(_nested_smallmap_bar), std::move(map_display)); return map_display; } diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 036bb665e1..eac09d48bc 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -716,18 +716,18 @@ const StringID CompanyStationsWindow::sorter_names[] = { * Make a horizontal row of cargo buttons, starting at widget #WID_STL_CARGOSTART. * @return Horizontal row. */ -static NWidgetBase *CargoWidgets() +static std::unique_ptr CargoWidgets() { - NWidgetHorizontal *container = new NWidgetHorizontal(); + auto container = std::make_unique(); for (uint i = 0; i < _sorted_standard_cargo_specs.size(); i++) { - NWidgetBackground *panel = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, WID_STL_CARGOSTART + i); + auto panel = std::make_unique(WWT_PANEL, COLOUR_GREY, WID_STL_CARGOSTART + i); panel->SetMinimalSize(14, 0); panel->SetMinimalTextLines(1, 0, FS_NORMAL); panel->SetResize(0, 0); panel->SetFill(0, 1); panel->SetDataTip(0, STR_STATION_LIST_USE_CTRL_TO_SELECT_MORE); - container->Add(panel); + container->Add(std::move(panel)); } return container; } diff --git a/src/tests/test_window_desc.cpp b/src/tests/test_window_desc.cpp index 419c6994ca..3cd8406666 100644 --- a/src/tests/test_window_desc.cpp +++ b/src/tests/test_window_desc.cpp @@ -90,9 +90,8 @@ TEST_CASE_METHOD(WindowDescTestsFixture, "WindowDesc - NWidgetPart validity") INFO(fmt::format("{}:{}", window_desc->file, window_desc->line)); NWidgetStacked *shade_select = nullptr; - NWidgetBase *root = nullptr; + std::unique_ptr root = nullptr; REQUIRE_NOTHROW(root = MakeWindowNWidgetTree(window_desc->nwid_begin, window_desc->nwid_end, &shade_select)); CHECK((root != nullptr)); - delete root; } diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 396932196a..4ca6ad5383 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -2122,7 +2122,7 @@ struct MainToolbarWindow : Window { }}; }; -static NWidgetBase *MakeMainToolbar() +static std::unique_ptr MakeMainToolbar() { /** Sprites to use for the different toolbar buttons */ static const SpriteID toolbar_button_sprites[] = { @@ -2159,7 +2159,7 @@ static NWidgetBase *MakeMainToolbar() SPR_IMG_SWITCH_TOOLBAR, // WID_TN_SWITCH_BAR }; - NWidgetMainToolbarContainer *hor = new NWidgetMainToolbarContainer(); + auto hor = std::make_unique(); for (WidgetID i = 0; i < WID_TN_END; i++) { switch (i) { case WID_TN_SMALL_MAP: @@ -2168,12 +2168,12 @@ static NWidgetBase *MakeMainToolbar() case WID_TN_ZOOM_IN: case WID_TN_BUILDING_TOOLS_START: case WID_TN_MUSIC_SOUND: - hor->Add(new NWidgetSpacer(0, 0)); + hor->Add(std::make_unique(0, 0)); break; } - NWidgetLeaf *leaf = new NWidgetLeaf(i == WID_TN_SAVE ? WWT_IMGBTN_2 : WWT_IMGBTN, COLOUR_GREY, i, toolbar_button_sprites[i], STR_TOOLBAR_TOOLTIP_PAUSE_GAME + i); + auto leaf = std::make_unique(i == WID_TN_SAVE ? WWT_IMGBTN_2 : WWT_IMGBTN, COLOUR_GREY, i, toolbar_button_sprites[i], STR_TOOLBAR_TOOLTIP_PAUSE_GAME + i); leaf->SetMinimalSize(20, 20); - hor->Add(leaf); + hor->Add(std::move(leaf)); } return hor; @@ -2514,9 +2514,9 @@ static const NWidgetPart _nested_toolb_scen_inner_widgets[] = { NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SWITCH_BAR), SetDataTip(SPR_IMG_SWITCH_TOOLBAR, STR_TOOLBAR_TOOLTIP_SWITCH_TOOLBAR), }; -static NWidgetBase *MakeScenarioToolbar() +static std::unique_ptr MakeScenarioToolbar() { - return MakeNWidgets(std::begin(_nested_toolb_scen_inner_widgets), std::end(_nested_toolb_scen_inner_widgets), new NWidgetScenarioToolbarContainer()); + return MakeNWidgets(std::begin(_nested_toolb_scen_inner_widgets), std::end(_nested_toolb_scen_inner_widgets), std::make_unique()); } static const NWidgetPart _nested_toolb_scen_widgets[] = { diff --git a/src/tree_gui.cpp b/src/tree_gui.cpp index 448df9a797..9a08cfef99 100644 --- a/src/tree_gui.cpp +++ b/src/tree_gui.cpp @@ -256,7 +256,7 @@ public: * get producing the correct result than dynamically building the widgets is. * @see NWidgetFunctionType */ -static NWidgetBase *MakeTreeTypeButtons() +static std::unique_ptr MakeTreeTypeButtons() { const byte type_base = _tree_base_by_landscape[_settings_game.game_creation.landscape]; const byte type_count = _tree_count_by_landscape[_settings_game.game_creation.landscape]; @@ -266,20 +266,20 @@ static NWidgetBase *MakeTreeTypeButtons() const int num_rows = CeilDiv(type_count, num_columns); byte cur_type = type_base; - NWidgetVertical *vstack = new NWidgetVertical(NC_EQUALSIZE); + auto vstack = std::make_unique(NC_EQUALSIZE); vstack->SetPIP(0, 1, 0); for (int row = 0; row < num_rows; row++) { - NWidgetHorizontal *hstack = new NWidgetHorizontal(NC_EQUALSIZE); + auto hstack = std::make_unique(NC_EQUALSIZE); hstack->SetPIP(0, 1, 0); - vstack->Add(hstack); for (int col = 0; col < num_columns; col++) { if (cur_type > type_base + type_count) break; - NWidgetBackground *button = new NWidgetBackground(WWT_PANEL, COLOUR_GREY, WID_BT_TYPE_BUTTON_FIRST + cur_type); + auto button = std::make_unique(WWT_PANEL, COLOUR_GREY, WID_BT_TYPE_BUTTON_FIRST + cur_type); button->SetDataTip(0x0, STR_PLANT_TREE_TOOLTIP); - hstack->Add(button); + hstack->Add(std::move(button)); cur_type++; } + vstack->Add(std::move(hstack)); } return vstack; diff --git a/src/widget.cpp b/src/widget.cpp index fa5791dbb4..18a04092bf 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -1297,11 +1297,11 @@ void NWidgetContainer::AdjustPaddingForZoom() * Append widget \a wid to container. * @param wid Widget to append. */ -void NWidgetContainer::Add(NWidgetBase *wid) +void NWidgetContainer::Add(std::unique_ptr &&wid) { assert(wid != nullptr); wid->parent = this; - this->children.emplace_back(wid); + this->children.push_back(std::move(wid)); } void NWidgetContainer::FillWidgetLookup(WidgetLookup &widget_lookup) @@ -2121,19 +2121,14 @@ void NWidgetMatrix::GetScrollOffsets(int &start_x, int &start_y, int &base_offs_ * vertical container will be inserted while adding the first * child widget. */ -NWidgetBackground::NWidgetBackground(WidgetType tp, Colours colour, WidgetID index, NWidgetPIPContainer *child) : NWidgetCore(tp, colour, index, 1, 1, 0x0, STR_NULL) +NWidgetBackground::NWidgetBackground(WidgetType tp, Colours colour, WidgetID index, std::unique_ptr &&child) : NWidgetCore(tp, colour, index, 1, 1, 0x0, STR_NULL) { assert(tp == WWT_PANEL || tp == WWT_INSET || tp == WWT_FRAME); - this->child = child; + this->child = std::move(child); if (this->child != nullptr) this->child->parent = this; this->SetAlignment(SA_TOP | SA_LEFT); } -NWidgetBackground::~NWidgetBackground() -{ - if (this->child != nullptr) delete this->child; -} - /** * Add a child to the parent. * @param nwid Nested widget to add to the background widget. @@ -2141,13 +2136,13 @@ NWidgetBackground::~NWidgetBackground() * Unless a child container has been given in the constructor, a parent behaves as a vertical container. * You can add several children to it, and they are put underneath each other. */ -void NWidgetBackground::Add(NWidgetBase *nwid) +void NWidgetBackground::Add(std::unique_ptr &&nwid) { if (this->child == nullptr) { - this->child = new NWidgetVertical(); + this->child = std::make_unique(); } - nwid->parent = this->child; - this->child->Add(nwid); + nwid->parent = this->child.get(); + this->child->Add(std::move(nwid)); } /** @@ -2163,7 +2158,7 @@ void NWidgetBackground::Add(NWidgetBase *nwid) void NWidgetBackground::SetPIP(uint8_t pip_pre, uint8_t pip_inter, uint8_t pip_post) { if (this->child == nullptr) { - this->child = new NWidgetVertical(); + this->child = std::make_unique(); } this->child->parent = this; this->child->SetPIP(pip_pre, pip_inter, pip_post); @@ -2182,7 +2177,7 @@ void NWidgetBackground::SetPIP(uint8_t pip_pre, uint8_t pip_inter, uint8_t pip_p void NWidgetBackground::SetPIPRatio(uint8_t pip_ratio_pre, uint8_t pip_ratio_inter, uint8_t pip_ratio_post) { if (this->child == nullptr) { - this->child = new NWidgetVertical(); + this->child = std::make_unique(); } this->child->parent = this; this->child->SetPIPRatio(pip_ratio_pre, pip_ratio_inter, pip_ratio_post); @@ -3043,60 +3038,60 @@ bool NWidgetLeaf::ButtonHit(const Point &pt) * @param fill_dest Fill the composed widget with child widgets. * @return Pointer to remaining nested widget parts. */ -static const NWidgetPart *MakeNWidget(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, NWidgetBase **dest, bool *fill_dest) +static const NWidgetPart *MakeNWidget(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, std::unique_ptr &dest, bool *fill_dest) { - *dest = nullptr; + dest = nullptr; *fill_dest = false; while (nwid_begin < nwid_end) { switch (nwid_begin->type) { case NWID_SPACER: - if (*dest != nullptr) return nwid_begin; - *dest = new NWidgetSpacer(0, 0); + if (dest != nullptr) return nwid_begin; + dest = std::make_unique(0, 0); break; case NWID_HORIZONTAL: - if (*dest != nullptr) return nwid_begin; - *dest = new NWidgetHorizontal(nwid_begin->u.cont_flags); + if (dest != nullptr) return nwid_begin; + dest = std::make_unique(nwid_begin->u.cont_flags); *fill_dest = true; break; case NWID_HORIZONTAL_LTR: - if (*dest != nullptr) return nwid_begin; - *dest = new NWidgetHorizontalLTR(nwid_begin->u.cont_flags); + if (dest != nullptr) return nwid_begin; + dest = std::make_unique(nwid_begin->u.cont_flags); *fill_dest = true; break; case WWT_PANEL: case WWT_INSET: case WWT_FRAME: - if (*dest != nullptr) return nwid_begin; - *dest = new NWidgetBackground(nwid_begin->type, nwid_begin->u.widget.colour, nwid_begin->u.widget.index); + if (dest != nullptr) return nwid_begin; + dest = std::make_unique(nwid_begin->type, nwid_begin->u.widget.colour, nwid_begin->u.widget.index); *fill_dest = true; break; case NWID_VERTICAL: - if (*dest != nullptr) return nwid_begin; - *dest = new NWidgetVertical(nwid_begin->u.cont_flags); + if (dest != nullptr) return nwid_begin; + dest = std::make_unique(nwid_begin->u.cont_flags); *fill_dest = true; break; case NWID_MATRIX: { - if (*dest != nullptr) return nwid_begin; - *dest = new NWidgetMatrix(nwid_begin->u.widget.colour, nwid_begin->u.widget.index); + if (dest != nullptr) return nwid_begin; + dest = std::make_unique(nwid_begin->u.widget.colour, nwid_begin->u.widget.index); *fill_dest = true; break; } case WPT_FUNCTION: { - if (*dest != nullptr) return nwid_begin; - *dest = nwid_begin->u.func_ptr(); + if (dest != nullptr) return nwid_begin; + dest = nwid_begin->u.func_ptr(); *fill_dest = false; break; } case WPT_RESIZE: { - NWidgetResizeBase *nwrb = dynamic_cast(*dest); + NWidgetResizeBase *nwrb = dynamic_cast(dest.get()); if (unlikely(nwrb == nullptr)) throw std::runtime_error("WPT_RESIZE requires NWidgetResizeBase"); assert(nwid_begin->u.xy.x >= 0 && nwid_begin->u.xy.y >= 0); nwrb->SetResize(nwid_begin->u.xy.x, nwid_begin->u.xy.y); @@ -3104,7 +3099,7 @@ static const NWidgetPart *MakeNWidget(const NWidgetPart *nwid_begin, const NWidg } case WPT_MINSIZE: { - NWidgetResizeBase *nwrb = dynamic_cast(*dest); + NWidgetResizeBase *nwrb = dynamic_cast(dest.get()); if (unlikely(nwrb == nullptr)) throw std::runtime_error("WPT_MINSIZE requires NWidgetResizeBase"); assert(nwid_begin->u.xy.x >= 0 && nwid_begin->u.xy.y >= 0); nwrb->SetMinimalSize(nwid_begin->u.xy.x, nwid_begin->u.xy.y); @@ -3112,7 +3107,7 @@ static const NWidgetPart *MakeNWidget(const NWidgetPart *nwid_begin, const NWidg } case WPT_MINTEXTLINES: { - NWidgetResizeBase *nwrb = dynamic_cast(*dest); + NWidgetResizeBase *nwrb = dynamic_cast(dest.get()); if (unlikely(nwrb == nullptr)) throw std::runtime_error("WPT_MINTEXTLINES requires NWidgetResizeBase"); assert(nwid_begin->u.text_lines.size >= FS_BEGIN && nwid_begin->u.text_lines.size < FS_END); nwrb->SetMinimalTextLines(nwid_begin->u.text_lines.lines, nwid_begin->u.text_lines.spacing, nwid_begin->u.text_lines.size); @@ -3120,28 +3115,28 @@ static const NWidgetPart *MakeNWidget(const NWidgetPart *nwid_begin, const NWidg } case WPT_TEXTSTYLE: { - NWidgetCore *nwc = dynamic_cast(*dest); + NWidgetCore *nwc = dynamic_cast(dest.get()); if (unlikely(nwc == nullptr)) throw std::runtime_error("WPT_TEXTSTYLE requires NWidgetCore"); nwc->SetTextStyle(nwid_begin->u.text_style.colour, nwid_begin->u.text_style.size); break; } case WPT_ALIGNMENT: { - NWidgetCore *nwc = dynamic_cast(*dest); + NWidgetCore *nwc = dynamic_cast(dest.get()); if (unlikely(nwc == nullptr)) throw std::runtime_error("WPT_ALIGNMENT requires NWidgetCore"); nwc->SetAlignment(nwid_begin->u.align.align); break; } case WPT_FILL: { - NWidgetResizeBase *nwrb = dynamic_cast(*dest); + NWidgetResizeBase *nwrb = dynamic_cast(dest.get()); if (unlikely(nwrb == nullptr)) throw std::runtime_error("WPT_FILL requires NWidgetResizeBase"); nwrb->SetFill(nwid_begin->u.xy.x, nwid_begin->u.xy.y); break; } case WPT_DATATIP: { - NWidgetCore *nwc = dynamic_cast(*dest); + NWidgetCore *nwc = dynamic_cast(dest.get()); if (unlikely(nwc == nullptr)) throw std::runtime_error("WPT_DATATIP requires NWidgetCore"); nwc->widget_data = nwid_begin->u.data_tip.data; nwc->tool_tip = nwid_begin->u.data_tip.tooltip; @@ -3149,15 +3144,15 @@ static const NWidgetPart *MakeNWidget(const NWidgetPart *nwid_begin, const NWidg } case WPT_PADDING: - if (unlikely(*dest == nullptr)) throw std::runtime_error("WPT_PADDING requires NWidgetBase"); - (*dest)->SetPadding(nwid_begin->u.padding); + if (unlikely(dest == nullptr)) throw std::runtime_error("WPT_PADDING requires NWidgetBase"); + dest->SetPadding(nwid_begin->u.padding); break; case WPT_PIPSPACE: { - NWidgetPIPContainer *nwc = dynamic_cast(*dest); + NWidgetPIPContainer *nwc = dynamic_cast(dest.get()); if (nwc != nullptr) nwc->SetPIP(nwid_begin->u.pip.pre, nwid_begin->u.pip.inter, nwid_begin->u.pip.post); - NWidgetBackground *nwb = dynamic_cast(*dest); + NWidgetBackground *nwb = dynamic_cast(dest.get()); if (nwb != nullptr) nwb->SetPIP(nwid_begin->u.pip.pre, nwid_begin->u.pip.inter, nwid_begin->u.pip.post); if (unlikely(nwc == nullptr && nwb == nullptr)) throw std::runtime_error("WPT_PIPSPACE requires NWidgetPIPContainer or NWidgetBackground"); @@ -3165,10 +3160,10 @@ static const NWidgetPart *MakeNWidget(const NWidgetPart *nwid_begin, const NWidg } case WPT_PIPRATIO: { - NWidgetPIPContainer *nwc = dynamic_cast(*dest); + NWidgetPIPContainer *nwc = dynamic_cast(dest.get()); if (nwc != nullptr) nwc->SetPIPRatio(nwid_begin->u.pip.pre, nwid_begin->u.pip.inter, nwid_begin->u.pip.post); - NWidgetBackground *nwb = dynamic_cast(*dest); + NWidgetBackground *nwb = dynamic_cast(dest.get()); if (nwb != nullptr) nwb->SetPIPRatio(nwid_begin->u.pip.pre, nwid_begin->u.pip.inter, nwid_begin->u.pip.post); if (unlikely(nwc == nullptr && nwb == nullptr)) throw std::runtime_error("WPT_PIPRATIO requires NWidgetPIPContainer or NWidgetBackground"); @@ -3176,7 +3171,7 @@ static const NWidgetPart *MakeNWidget(const NWidgetPart *nwid_begin, const NWidg } case WPT_SCROLLBAR: { - NWidgetCore *nwc = dynamic_cast(*dest); + NWidgetCore *nwc = dynamic_cast(dest.get()); if (unlikely(nwc == nullptr)) throw std::runtime_error("WPT_SCROLLBAR requires NWidgetCore"); nwc->scrollbar_index = nwid_begin->u.widget.index; break; @@ -3186,27 +3181,27 @@ static const NWidgetPart *MakeNWidget(const NWidgetPart *nwid_begin, const NWidg return nwid_begin; case NWID_VIEWPORT: - if (*dest != nullptr) return nwid_begin; - *dest = new NWidgetViewport(nwid_begin->u.widget.index); + if (dest != nullptr) return nwid_begin; + dest = std::make_unique(nwid_begin->u.widget.index); break; case NWID_HSCROLLBAR: case NWID_VSCROLLBAR: - if (*dest != nullptr) return nwid_begin; - *dest = new NWidgetScrollbar(nwid_begin->type, nwid_begin->u.widget.colour, nwid_begin->u.widget.index); + if (dest != nullptr) return nwid_begin; + dest = std::make_unique(nwid_begin->type, nwid_begin->u.widget.colour, nwid_begin->u.widget.index); break; case NWID_SELECTION: { - if (*dest != nullptr) return nwid_begin; - *dest = new NWidgetStacked(nwid_begin->u.widget.index); + if (dest != nullptr) return nwid_begin; + dest = std::make_unique(nwid_begin->u.widget.index); *fill_dest = true; break; } default: - if (*dest != nullptr) return nwid_begin; + if (dest != nullptr) return nwid_begin; assert((nwid_begin->type & WWT_MASK) < WWT_LAST || (nwid_begin->type & WWT_MASK) == NWID_BUTTON_DROPDOWN); - *dest = new NWidgetLeaf(nwid_begin->type, nwid_begin->u.widget.colour, nwid_begin->u.widget.index, 0x0, STR_NULL); + dest = std::make_unique(nwid_begin->type, nwid_begin->u.widget.colour, nwid_begin->u.widget.index, 0x0, STR_NULL); break; } nwid_begin++; @@ -3233,33 +3228,32 @@ bool IsContainerWidgetType(WidgetType tp) * @param parent Pointer or container to use for storing the child widgets (*parent == nullptr or *parent == container or background widget). * @return Pointer to remaining nested widget parts. */ -static const NWidgetPart *MakeWidgetTree(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, NWidgetBase **parent) +static const NWidgetPart *MakeWidgetTree(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, std::unique_ptr &parent) { /* If *parent == nullptr, only the first widget is read and returned. Otherwise, *parent must point to either * a #NWidgetContainer or a #NWidgetBackground object, and parts are added as much as possible. */ - NWidgetContainer *nwid_cont = dynamic_cast(*parent); - NWidgetBackground *nwid_parent = dynamic_cast(*parent); - assert(*parent == nullptr || (nwid_cont != nullptr && nwid_parent == nullptr) || (nwid_cont == nullptr && nwid_parent != nullptr)); + NWidgetContainer *nwid_cont = dynamic_cast(parent.get()); + NWidgetBackground *nwid_parent = dynamic_cast(parent.get()); + assert(parent == nullptr || (nwid_cont != nullptr && nwid_parent == nullptr) || (nwid_cont == nullptr && nwid_parent != nullptr)); for (;;) { - NWidgetBase *sub_widget = nullptr; + std::unique_ptr sub_widget = nullptr; bool fill_sub = false; - nwid_begin = MakeNWidget(nwid_begin, nwid_end, &sub_widget, &fill_sub); + nwid_begin = MakeNWidget(nwid_begin, nwid_end, sub_widget, &fill_sub); /* Break out of loop when end reached */ if (sub_widget == nullptr) break; /* If sub-widget is a container, recursively fill that container. */ if (fill_sub && IsContainerWidgetType(sub_widget->type)) { - NWidgetBase *sub_ptr = sub_widget; - nwid_begin = MakeWidgetTree(nwid_begin, nwid_end, &sub_ptr); + nwid_begin = MakeWidgetTree(nwid_begin, nwid_end, sub_widget); } /* Add sub_widget to parent container if available, otherwise return the widget to the caller. */ - if (nwid_cont != nullptr) nwid_cont->Add(sub_widget); - if (nwid_parent != nullptr) nwid_parent->Add(sub_widget); + if (nwid_cont != nullptr) nwid_cont->Add(std::move(sub_widget)); + if (nwid_parent != nullptr) nwid_parent->Add(std::move(sub_widget)); if (nwid_cont == nullptr && nwid_parent == nullptr) { - *parent = sub_widget; + parent = std::move(sub_widget); return nwid_begin; } } @@ -3279,15 +3273,14 @@ static const NWidgetPart *MakeWidgetTree(const NWidgetPart *nwid_begin, const NW * @return Root of the nested widget tree, a vertical container containing the entire GUI. * @ingroup NestedWidgetParts */ -NWidgetContainer *MakeNWidgets(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, NWidgetContainer *container) +std::unique_ptr MakeNWidgets(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, std::unique_ptr &&container) { - if (container == nullptr) container = new NWidgetVertical(); - NWidgetBase *cont_ptr = container; - [[maybe_unused]] const NWidgetPart *nwid_part = MakeWidgetTree(nwid_begin, nwid_end, &cont_ptr); + if (container == nullptr) container = std::make_unique(); + [[maybe_unused]] const NWidgetPart *nwid_part = MakeWidgetTree(nwid_begin, nwid_end, container); #ifdef WITH_ASSERT if (unlikely(nwid_part != nwid_end)) throw std::runtime_error("Did not consume all NWidgetParts"); #endif - return container; + return std::move(container); } /** @@ -3300,38 +3293,33 @@ NWidgetContainer *MakeNWidgets(const NWidgetPart *nwid_begin, const NWidgetPart * @return Root of the nested widget tree, a vertical container containing the entire GUI. * @ingroup NestedWidgetParts */ -NWidgetContainer *MakeWindowNWidgetTree(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, NWidgetStacked **shade_select) +std::unique_ptr MakeWindowNWidgetTree(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, NWidgetStacked **shade_select) { + *shade_select = nullptr; + /* Read the first widget recursively from the array. */ - NWidgetBase *nwid = nullptr; - nwid_begin = MakeWidgetTree(nwid_begin, nwid_end, &nwid); + std::unique_ptr nwid = nullptr; + nwid_begin = MakeWidgetTree(nwid_begin, nwid_end, nwid); assert(nwid != nullptr); - NWidgetContainer *root = new NWidgetVertical; - root->Add(nwid); - if (nwid_begin == nwid_end) { // There is no body at all. - *shade_select = nullptr; + NWidgetHorizontal *hor_cont = dynamic_cast(nwid.get()); + + auto root = std::make_unique(); + root->Add(std::move(nwid)); + if (nwid_begin == nwid_end) return root; // There is no body at all. + + if (hor_cont != nullptr && hor_cont->GetWidgetOfType(WWT_CAPTION) != nullptr && hor_cont->GetWidgetOfType(WWT_SHADEBOX) != nullptr) { + /* If the first widget has a title bar and a shade box, silently add a shade selection widget in the tree. */ + auto shade_stack = std::make_unique(-1); + *shade_select = shade_stack.get(); + /* Load the remaining parts into the shade stack. */ + shade_stack->Add(MakeNWidgets(nwid_begin, nwid_end, std::make_unique())); + root->Add(std::move(shade_stack)); return root; } - /* If the first widget looks like a titlebar, treat it as such. - * If it has a shading box, silently add a shade selection widget in the tree. */ - NWidgetHorizontal *hor_cont = dynamic_cast(nwid); - NWidgetContainer *body; - if (hor_cont != nullptr && hor_cont->GetWidgetOfType(WWT_CAPTION) != nullptr && hor_cont->GetWidgetOfType(WWT_SHADEBOX) != nullptr) { - *shade_select = new NWidgetStacked(-1); - root->Add(*shade_select); - body = new NWidgetVertical; - (*shade_select)->Add(body); - } else { - *shade_select = nullptr; - body = root; - } - - /* Load the remaining parts into 'body'. */ - MakeNWidgets(nwid_begin, nwid_end, body); - - return root; + /* Load the remaining parts into 'root'. */ + return MakeNWidgets(nwid_begin, nwid_end, std::move(root)); } /** @@ -3343,11 +3331,11 @@ NWidgetContainer *MakeWindowNWidgetTree(const NWidgetPart *nwid_begin, const NWi * @param button_tooltip The tooltip-string of every button. * @return Panel with rows of company buttons. */ -NWidgetBase *MakeCompanyButtonRows(WidgetID widget_first, WidgetID widget_last, Colours button_colour, int max_length, StringID button_tooltip) +std::unique_ptr MakeCompanyButtonRows(WidgetID widget_first, WidgetID widget_last, Colours button_colour, int max_length, StringID button_tooltip) { assert(max_length >= 1); - NWidgetVertical *vert = nullptr; // Storage for all rows. - NWidgetHorizontal *hor = nullptr; // Storage for buttons in one row. + std::unique_ptr vert = nullptr; // Storage for all rows. + std::unique_ptr hor = nullptr; // Storage for buttons in one row. int hor_length = 0; Dimension sprite_size = GetSpriteSize(SPR_COMPANY_ICON, nullptr, ZOOM_LVL_OUT_4X); @@ -3357,33 +3345,33 @@ NWidgetBase *MakeCompanyButtonRows(WidgetID widget_first, WidgetID widget_last, for (WidgetID widnum = widget_first; widnum <= widget_last; widnum++) { /* Ensure there is room in 'hor' for another button. */ if (hor_length == max_length) { - if (vert == nullptr) vert = new NWidgetVertical(); - vert->Add(hor); + if (vert == nullptr) vert = std::make_unique(); + vert->Add(std::move(hor)); hor = nullptr; hor_length = 0; } if (hor == nullptr) { - hor = new NWidgetHorizontal(); + hor = std::make_unique(); hor_length = 0; } - NWidgetBackground *panel = new NWidgetBackground(WWT_PANEL, button_colour, widnum); + auto panel = std::make_unique(WWT_PANEL, button_colour, widnum); panel->SetMinimalSize(sprite_size.width, sprite_size.height); panel->SetFill(1, 1); panel->SetResize(1, 0); panel->SetDataTip(0x0, button_tooltip); - hor->Add(panel); + hor->Add(std::move(panel)); hor_length++; } if (vert == nullptr) return hor; // All buttons fit in a single row. if (hor_length > 0 && hor_length < max_length) { /* Last row is partial, add a spacer at the end to force all buttons to the left. */ - NWidgetSpacer *spc = new NWidgetSpacer(sprite_size.width, sprite_size.height); + auto spc = std::make_unique(sprite_size.width, sprite_size.height); spc->SetFill(1, 1); spc->SetResize(1, 0); - hor->Add(spc); + hor->Add(std::move(spc)); } - if (hor != nullptr) vert->Add(hor); + if (hor != nullptr) vert->Add(std::move(hor)); return vert; } diff --git a/src/widget_type.h b/src/widget_type.h index 375ed88291..1f831090e2 100644 --- a/src/widget_type.h +++ b/src/widget_type.h @@ -84,6 +84,7 @@ enum WidgetType { NWID_BUTTON_DROPDOWN, ///< Button with a drop-down. NWID_HSCROLLBAR, ///< Horizontal scrollbar NWID_VSCROLLBAR, ///< Vertical scrollbar + NWID_CUSTOM, ///< General Custom widget. /* Nested widget part types. */ WPT_RESIZE, ///< Widget part for specifying resizing. @@ -446,7 +447,7 @@ public: NWidgetContainer(WidgetType tp) : NWidgetBase(tp) { } void AdjustPaddingForZoom() override; - void Add(NWidgetBase *wid); + void Add(std::unique_ptr &&wid); void FillWidgetLookup(WidgetLookup &widget_lookup) override; void Draw(const Window *w) override; @@ -631,10 +632,9 @@ public: */ class NWidgetBackground : public NWidgetCore { public: - NWidgetBackground(WidgetType tp, Colours colour, WidgetID index, NWidgetPIPContainer *child = nullptr); - ~NWidgetBackground(); + NWidgetBackground(WidgetType tp, Colours colour, WidgetID index, std::unique_ptr &&child = nullptr); - void Add(NWidgetBase *nwid); + void Add(std::unique_ptr &&nwid); void SetPIP(uint8_t pip_pre, uint8_t pip_inter, uint8_t pip_post); void SetPIPRatio(uint8_t pip_ratio_pre, uint8_t pip_ratio_inter, uint8_t pip_ratio_post); @@ -649,7 +649,7 @@ public: NWidgetBase *GetWidgetOfType(WidgetType tp) override; private: - NWidgetPIPContainer *child; ///< Child widget. + std::unique_ptr child; ///< Child widget. }; /** @@ -1029,7 +1029,7 @@ struct NWidgetPartAlignment { * Pointer to function returning a nested widget. * @return Nested widget (tree). */ -typedef NWidgetBase *NWidgetFunctionType(); +typedef std::unique_ptr NWidgetFunctionType(); /** * Partial widget specification to allow NWidgets to be written nested. @@ -1353,10 +1353,10 @@ static inline NWidgetPart NWidgetFunction(NWidgetFunctionType *func_ptr) } bool IsContainerWidgetType(WidgetType tp); -NWidgetContainer *MakeNWidgets(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, NWidgetContainer *container); -NWidgetContainer *MakeWindowNWidgetTree(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, NWidgetStacked **shade_select); +std::unique_ptr MakeNWidgets(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, std::unique_ptr &&container); +std::unique_ptr MakeWindowNWidgetTree(const NWidgetPart *nwid_begin, const NWidgetPart *nwid_end, NWidgetStacked **shade_select); -NWidgetBase *MakeCompanyButtonRows(WidgetID widget_first, WidgetID widget_last, Colours button_colour, int max_length, StringID button_tooltip); +std::unique_ptr MakeCompanyButtonRows(WidgetID widget_first, WidgetID widget_last, Colours button_colour, int max_length, StringID button_tooltip); void SetupWidgetDimensions(); diff --git a/src/window.cpp b/src/window.cpp index ebe91b007b..8f99f252a4 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1088,7 +1088,6 @@ Window::~Window() assert(*this->z_position == nullptr); if (this->viewport != nullptr) DeleteWindowViewport(this); - delete this->nested_root; } /** diff --git a/src/window_gui.h b/src/window_gui.h index 49426c5000..b1bc06306c 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -259,7 +259,7 @@ public: ViewportData *viewport; ///< Pointer to viewport data, if present. const NWidgetCore *nested_focus; ///< Currently focused nested widget, or \c nullptr if no nested widget has focus. std::map querystrings; ///< QueryString associated to WWT_EDITBOX widgets. - NWidgetBase *nested_root; ///< Root of the nested tree. + std::unique_ptr nested_root; ///< Root of the nested tree. WidgetLookup widget_lookup; ///< Indexed access to the nested widget tree. Do not access directly, use #Window::GetWidget() instead. NWidgetStacked *shade_select; ///< Selection widget (#NWID_SELECTION) to use for shading the window. If \c nullptr, window cannot shade. Dimension unshaded_size; ///< Last known unshaded size (only valid while shaded).