diff --git a/src/openrct2-ui/scripting/CustomListView.cpp b/src/openrct2-ui/scripting/CustomListView.cpp index 35d38a6d1e..bda9302dea 100644 --- a/src/openrct2-ui/scripting/CustomListView.cpp +++ b/src/openrct2-ui/scripting/CustomListView.cpp @@ -35,6 +35,19 @@ namespace OpenRCT2::Scripting return ColumnSortOrder::None; } + template<> DukValue ToDuk(duk_context* ctx, const ColumnSortOrder& value) + { + switch (value) + { + case ColumnSortOrder::Ascending: + return ToDuk(ctx, "ascending"); + case ColumnSortOrder::Descending: + return ToDuk(ctx, "descending"); + default: + return ToDuk(ctx, "none"); + } + } + template<> std::optional FromDuk(const DukValue& d) { if (d.type() == DukValue::Type::NUMBER) @@ -67,6 +80,20 @@ namespace OpenRCT2::Scripting return result; } + template<> DukValue ToDuk(duk_context* ctx, const ListViewColumn& value) + { + DukObject obj(ctx); + obj.Set("canSort", value.CanSort); + obj.Set("sortOrder", ToDuk(ctx, value.SortOrder)); + obj.Set("header", value.Header); + obj.Set("headerTooltip", value.HeaderTooltip); + obj.Set("minWidth", value.MinWidth); + obj.Set("maxWidth", value.MaxWidth); + obj.Set("ratioWidth", value.RatioWidth); + obj.Set("width", value.Width); + return obj.Take(); + } + template<> ListViewItem FromDuk(const DukValue& d) { ListViewItem result; @@ -86,6 +113,34 @@ namespace OpenRCT2::Scripting return result; } + template<> std::vector FromDuk(const DukValue& d) + { + std::vector result; + if (d.is_array()) + { + auto dukColumns = d.as_array(); + for (const auto& dukColumn : dukColumns) + { + result.push_back(FromDuk(dukColumn)); + } + } + return result; + } + + template<> std::vector FromDuk(const DukValue& d) + { + std::vector result; + if (d.is_array()) + { + auto dukItems = d.as_array(); + for (const auto& dukItem : dukItems) + { + result.push_back(FromDuk(dukItem)); + } + } + return result; + } + template<> std::optional FromDuk(const DukValue& d) { if (d.type() == DukValue::Type::OBJECT) @@ -109,8 +164,27 @@ namespace OpenRCT2::Scripting } } // namespace OpenRCT2::Scripting +const std::vector& CustomListView::GetColumns() const +{ + return Columns; +} + +void CustomListView::SetColumns(const std::vector& columns) +{ + SelectedCell = std::nullopt; + Columns = columns; + LastKnownSize = {}; + SortItems(0, ColumnSortOrder::None); +} + +const std::vector& CustomListView::CustomListView::GetItems() const +{ + return Items; +} + void CustomListView::SetItems(const std::vector& items) { + SelectedCell = std::nullopt; Items = items; SortItems(0, ColumnSortOrder::None); } diff --git a/src/openrct2-ui/scripting/CustomListView.h b/src/openrct2-ui/scripting/CustomListView.h index 343dd7b88c..c4e9f69395 100644 --- a/src/openrct2-ui/scripting/CustomListView.h +++ b/src/openrct2-ui/scripting/CustomListView.h @@ -92,11 +92,11 @@ namespace OpenRCT2::Ui::Windows { private: static constexpr int32_t HEADER_ROW = -1; + std::vector Columns; std::vector Items; public: std::shared_ptr Owner; - std::vector Columns; std::vector SortedItems; std::optional HighlightedCell; std::optional LastHighlightedCell; @@ -116,6 +116,9 @@ namespace OpenRCT2::Ui::Windows DukValue OnClick; DukValue OnHighlight; + const std::vector& GetColumns() const; + void SetColumns(const std::vector& columns); + const std::vector& GetItems() const; void SetItems(const std::vector& items); void SetItems(std::vector&& items); bool SortItem(size_t indexA, size_t indexB, int32_t column); @@ -149,8 +152,11 @@ namespace OpenRCT2::Scripting template<> std::optional FromDuk(const DukValue& d); template<> ListViewColumn FromDuk(const DukValue& d); template<> ListViewItem FromDuk(const DukValue& d); + template<> std::vector FromDuk(const DukValue& d); + template<> std::vector FromDuk(const DukValue& d); template<> std::optional FromDuk(const DukValue& d); template<> DukValue ToDuk(duk_context* ctx, const RowColumn& value); + template<> DukValue ToDuk(duk_context* ctx, const ListViewColumn& value); } // namespace OpenRCT2::Scripting #endif diff --git a/src/openrct2-ui/scripting/CustomWindow.cpp b/src/openrct2-ui/scripting/CustomWindow.cpp index 4dab81905f..a94e51bf1c 100644 --- a/src/openrct2-ui/scripting/CustomWindow.cpp +++ b/src/openrct2-ui/scripting/CustomWindow.cpp @@ -171,22 +171,8 @@ namespace OpenRCT2::Ui::Windows } else if (result.Type == "listview") { - if (desc["columns"].is_array()) - { - auto dukColumns = desc["columns"].as_array(); - for (const auto& dukColumn : dukColumns) - { - result.ListViewColumns.push_back(FromDuk(dukColumn)); - } - } - if (desc["items"].is_array()) - { - auto dukItems = desc["items"].as_array(); - for (const auto& dukItem : dukItems) - { - result.ListViewItems.push_back(FromDuk(dukItem)); - } - } + result.ListViewColumns = FromDuk>(desc["columns"]); + result.ListViewItems = FromDuk>(desc["items"]); result.ShowColumnHeaders = AsOrDefault(desc["showColumnHeaders"], false); result.IsStriped = AsOrDefault(desc["isStriped"], false); result.OnClick = desc["onClick"]; @@ -986,7 +972,7 @@ namespace OpenRCT2::Ui::Windows if (widgetDesc.Type == "listview") { CustomListView listView; - listView.Columns = widgetDesc.ListViewColumns; + listView.SetColumns(widgetDesc.ListViewColumns); listView.SetItems(widgetDesc.ListViewItems); listView.ShowColumnHeaders = widgetDesc.ShowColumnHeaders; listView.IsStriped = widgetDesc.IsStriped; diff --git a/src/openrct2-ui/scripting/ScWidget.hpp b/src/openrct2-ui/scripting/ScWidget.hpp index 55537a455f..6677bc1796 100644 --- a/src/openrct2-ui/scripting/ScWidget.hpp +++ b/src/openrct2-ui/scripting/ScWidget.hpp @@ -373,6 +373,8 @@ namespace OpenRCT2::Scripting dukglue_register_property(ctx, &ScListViewWidget::highlightedCell_get, nullptr, "highlightedCell"); dukglue_register_property( ctx, &ScListViewWidget::selectedCell_get, &ScListViewWidget::selectedCell_set, "selectedCell"); + dukglue_register_property(ctx, &ScListViewWidget::columns_get, &ScListViewWidget::columns_set, "columns"); + dukglue_register_property(ctx, &ScListViewWidget::items_get, &ScListViewWidget::items_set, "items"); } private: @@ -464,6 +466,53 @@ namespace OpenRCT2::Scripting } } + std::vector> items_get() + { + std::vector> result; + auto listView = GetListView(); + if (listView != nullptr) + { + for (const auto& item : listView->GetItems()) + { + result.push_back(item.Cells); + } + } + return result; + } + + void items_set(const DukValue& value) + { + auto listView = GetListView(); + if (listView != nullptr) + { + listView->SetItems(FromDuk>(value)); + } + } + + std::vector columns_get() + { + std::vector result; + auto listView = GetListView(); + if (listView != nullptr) + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + for (const auto& column : listView->GetColumns()) + { + result.push_back(ToDuk(ctx, column)); + } + } + return result; + } + + void columns_set(const DukValue& value) + { + auto listView = GetListView(); + if (listView != nullptr) + { + listView->SetColumns(FromDuk>(value)); + } + } + CustomListView* GetListView() const { auto w = GetWindow(); diff --git a/src/openrct2/scripting/Duktape.hpp b/src/openrct2/scripting/Duktape.hpp index c36849ac4d..1a9eb0962d 100644 --- a/src/openrct2/scripting/Duktape.hpp +++ b/src/openrct2/scripting/Duktape.hpp @@ -113,6 +113,20 @@ namespace OpenRCT2::Scripting duk_put_prop_string(_ctx, _idx, name); } + template void Set(const char* name, const std::optional& value) + { + if (value) + { + EnsureObjectPushed(); + duk_push_null(_ctx); + duk_put_prop_string(_ctx, _idx, name); + } + else + { + Set(name, *value); + } + } + DukValue Take() { EnsureObjectPushed(); @@ -199,6 +213,16 @@ namespace OpenRCT2::Scripting duk_push_null(ctx); return DukValue::take_from_stack(ctx); } + template<> inline DukValue ToDuk(duk_context* ctx, const std::string_view& value) + { + duk_push_lstring(ctx, value.data(), value.size()); + return DukValue::take_from_stack(ctx); + } + template inline DukValue ToDuk(duk_context* ctx, const char (&value)[TLen]) + { + duk_push_string(ctx, value); + return DukValue::take_from_stack(ctx); + } template DukValue ToDuk(duk_context* ctx, const std::optional& value) { return value ? ToDuk(ctx, *value) : ToDuk(ctx, nullptr);