From f492827c8a6787a2999f88ad290df5c53f557c7b Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 9 May 2020 17:09:47 +0100 Subject: [PATCH] Implement horizontal scrollbars and fix resizing --- src/openrct2-ui/scripting/CustomListView.cpp | 76 ++++++++++++++------ src/openrct2-ui/scripting/CustomListView.h | 8 +-- src/openrct2-ui/scripting/CustomWindow.cpp | 10 +-- 3 files changed, 64 insertions(+), 30 deletions(-) diff --git a/src/openrct2-ui/scripting/CustomListView.cpp b/src/openrct2-ui/scripting/CustomListView.cpp index b66e10cc15..3bf74f717b 100644 --- a/src/openrct2-ui/scripting/CustomListView.cpp +++ b/src/openrct2-ui/scripting/CustomListView.cpp @@ -14,6 +14,7 @@ # include "../interface/Widget.h" # include "../interface/Window.h" +# include # include # include # include @@ -205,28 +206,32 @@ ScrollbarType CustomListView::GetScrollbars() const return Scrollbars; } -void CustomListView::SetScrollbars(ScrollbarType value) +void CustomListView::SetScrollbars(ScrollbarType value, bool initialising) { Scrollbars = value; - size_t scrollIndex = 0; - for (auto widget = ParentWindow->widgets; widget->type != WWT_LAST; widget++) + if (!initialising) { - if (widget->type == WWT_SCROLL) + size_t scrollIndex = 0; + for (auto widget = ParentWindow->widgets; widget->type != WWT_LAST; widget++) { - if (scrollIndex == ScrollIndex) + if (widget->type == WWT_SCROLL) { - if (value == ScrollbarType::Horizontal) - widget->content = SCROLL_HORIZONTAL; - else if (value == ScrollbarType::Vertical) - widget->content = SCROLL_VERTICAL; - else if (value == ScrollbarType::Both) - widget->content = SCROLL_BOTH; - else - widget->content = 0; + if (scrollIndex == ScrollIndex) + { + if (value == ScrollbarType::Horizontal) + widget->content = SCROLL_HORIZONTAL; + else if (value == ScrollbarType::Vertical) + widget->content = SCROLL_VERTICAL; + else if (value == ScrollbarType::Both) + widget->content = SCROLL_BOTH; + else + widget->content = 0; + } + scrollIndex++; } - scrollIndex++; } + window_init_scroll_widgets(ParentWindow); } } @@ -235,12 +240,14 @@ const std::vector& CustomListView::GetColumns() const return Columns; } -void CustomListView::SetColumns(const std::vector& columns) +void CustomListView::SetColumns(const std::vector& columns, bool initialising) { SelectedCell = std::nullopt; Columns = columns; LastKnownSize = {}; SortItems(0, ColumnSortOrder::None); + if (!initialising) + window_init_scroll_widgets(ParentWindow); } const std::vector& CustomListView::CustomListView::GetItems() const @@ -248,17 +255,21 @@ const std::vector& CustomListView::CustomListView::GetItems() cons return Items; } -void CustomListView::SetItems(const std::vector& items) +void CustomListView::SetItems(const std::vector& items, bool initialising) { SelectedCell = std::nullopt; Items = items; SortItems(0, ColumnSortOrder::None); + if (!initialising) + window_update_scroll_widgets(ParentWindow); } -void CustomListView::SetItems(std::vector&& items) +void CustomListView::SetItems(std::vector&& items, bool initialising) { Items = items; SortItems(0, ColumnSortOrder::None); + if (!initialising) + window_init_scroll_widgets(ParentWindow); } bool CustomListView::SortItem(size_t indexA, size_t indexB, int32_t column) @@ -328,11 +339,13 @@ void CustomListView::Resize(const ScreenSize& size) } // Calculate column widths + bool hasHorizontalScroll = Scrollbars == ScrollbarType::Horizontal || Scrollbars == ScrollbarType::Both; int32_t widthRemaining = size.width; for (size_t c = 0; c < Columns.size(); c++) { auto& column = Columns[c]; - if (c == Columns.size() - 1) + auto isLastColumn = c == Columns.size() - 1; + if (!hasHorizontalScroll && isLastColumn) { column.Width = widthRemaining; } @@ -341,7 +354,14 @@ void CustomListView::Resize(const ScreenSize& size) column.Width = 0; if (column.RatioWidth && *column.RatioWidth > 0) { - column.Width = (size.width * *column.RatioWidth) / totalRatio; + if (isLastColumn) + { + column.Width = widthRemaining; + } + else + { + column.Width = (size.width * *column.RatioWidth) / totalRatio; + } } if (column.MinWidth) { @@ -352,8 +372,10 @@ void CustomListView::Resize(const ScreenSize& size) column.Width = std::min(column.Width, *column.MaxWidth); } } - widthRemaining -= column.Width; + widthRemaining = std::max(0, widthRemaining - column.Width); } + + window_init_scroll_widgets(ParentWindow); } ScreenSize CustomListView::GetSize() @@ -365,8 +387,18 @@ ScreenSize CustomListView::GetSize() IsMouseDown = false; ScreenSize result; - result.width = 0; - result.height = static_cast(Items.size() * LIST_ROW_HEIGHT); + if (Scrollbars == ScrollbarType::Horizontal || Scrollbars == ScrollbarType::Both) + { + result.width = std::accumulate( + Columns.begin(), Columns.end(), 0, [](int32_t acc, const ListViewColumn& column) { return acc + column.Width; }); + + // Fixes an off-by-one error that causes the scrollbar thumb to not fill when the widget is wide enough + result.width--; + } + if (Scrollbars == ScrollbarType::Vertical || Scrollbars == ScrollbarType::Both) + { + result.height = static_cast(Items.size() * LIST_ROW_HEIGHT); + } return result; } diff --git a/src/openrct2-ui/scripting/CustomListView.h b/src/openrct2-ui/scripting/CustomListView.h index 068690a551..a6cef7d641 100644 --- a/src/openrct2-ui/scripting/CustomListView.h +++ b/src/openrct2-ui/scripting/CustomListView.h @@ -121,12 +121,12 @@ namespace OpenRCT2::Ui::Windows CustomListView(rct_window* parent, size_t scrollIndex); ScrollbarType GetScrollbars() const; - void SetScrollbars(ScrollbarType value); + void SetScrollbars(ScrollbarType value, bool initialising = false); const std::vector& GetColumns() const; - void SetColumns(const std::vector& columns); + void SetColumns(const std::vector& columns, bool initialising = false); const std::vector& GetItems() const; - void SetItems(const std::vector& items); - void SetItems(std::vector&& items); + void SetItems(const std::vector& items, bool initialising = false); + void SetItems(std::vector&& items, bool initialising = false); bool SortItem(size_t indexA, size_t indexB, int32_t column); void SortItems(int32_t column); void SortItems(int32_t column, ColumnSortOrder order); diff --git a/src/openrct2-ui/scripting/CustomWindow.cpp b/src/openrct2-ui/scripting/CustomWindow.cpp index d18491a118..26e9899fc5 100644 --- a/src/openrct2-ui/scripting/CustomWindow.cpp +++ b/src/openrct2-ui/scripting/CustomWindow.cpp @@ -417,8 +417,6 @@ namespace OpenRCT2::Ui::Windows window->max_height = desc.MaxHeight.value_or(std::numeric_limits::max()); } RefreshWidgets(window); - window_init_scroll_widgets(window); - window_custom_update_viewport(window); return window; } @@ -983,8 +981,9 @@ namespace OpenRCT2::Ui::Windows if (widgetDesc.Type == "listview") { CustomListView listView(w, info.ListViews.size()); - listView.SetColumns(widgetDesc.ListViewColumns); - listView.SetItems(widgetDesc.ListViewItems); + listView.SetScrollbars(widgetDesc.Scrollbars, true); + listView.SetColumns(widgetDesc.ListViewColumns, true); + listView.SetItems(widgetDesc.ListViewItems, true); listView.ShowColumnHeaders = widgetDesc.ShowColumnHeaders; listView.IsStriped = widgetDesc.IsStriped; listView.OnClick = widgetDesc.OnClick; @@ -1014,6 +1013,9 @@ namespace OpenRCT2::Ui::Windows widgets.push_back({ WIDGETS_END }); w->widgets = widgets.data(); + + window_init_scroll_widgets(w); + window_custom_update_viewport(w); } static void InvokeEventHandler(const std::shared_ptr& owner, const DukValue& dukHandler)