diff --git a/src/openrct2-ui/scripting/CustomListView.cpp b/src/openrct2-ui/scripting/CustomListView.cpp index c2efda6450..8343a14253 100644 --- a/src/openrct2-ui/scripting/CustomListView.cpp +++ b/src/openrct2-ui/scripting/CustomListView.cpp @@ -24,6 +24,8 @@ using namespace OpenRCT2::Ui::Windows; namespace OpenRCT2::Scripting { + constexpr size_t COLUMN_HEADER_HEIGHT = LIST_ROW_HEIGHT + 1; + template<> ColumnSortOrder FromDuk(const DukValue& d) { if (d.type() == DukValue::Type::STRING) @@ -212,27 +214,19 @@ void CustomListView::SetScrollbars(ScrollbarType value, bool initialising) if (!initialising) { - size_t scrollIndex = 0; - for (auto widget = ParentWindow->widgets; widget->type != WWT_LAST; widget++) + auto widget = GetWidget(); + if (widget != nullptr) { - if (widget->type == WWT_SCROLL) - { - 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++; - } + 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; } - window_init_scroll_widgets(ParentWindow); - Invalidate(); + RefreshScroll(); } } @@ -249,8 +243,7 @@ void CustomListView::SetColumns(const std::vector& columns, bool SortItems(0, ColumnSortOrder::None); if (!initialising) { - window_init_scroll_widgets(ParentWindow); - Invalidate(); + RefreshScroll(); } } @@ -277,8 +270,7 @@ void CustomListView::SetItems(std::vector&& items, bool initialisi SortItems(0, ColumnSortOrder::None); if (!initialising) { - window_init_scroll_widgets(ParentWindow); - Invalidate(); + RefreshScroll(); } } @@ -388,9 +380,6 @@ void CustomListView::Resize(const ScreenSize& size) } widthRemaining = std::max(0, widthRemaining - column.Width); } - - window_init_scroll_widgets(ParentWindow); - Invalidate(); } ScreenSize CustomListView::GetSize() @@ -413,6 +402,37 @@ ScreenSize CustomListView::GetSize() if (Scrollbars == ScrollbarType::Vertical || Scrollbars == ScrollbarType::Both) { result.height = static_cast(Items.size() * LIST_ROW_HEIGHT); + if (ShowColumnHeaders) + { + result.height += COLUMN_HEADER_HEIGHT; + } + } + + // If the list is getting bigger than the contents, pan towards top left scroll + auto widget = GetWidget(); + if (widget != nullptr) + { + auto& scroll = ParentWindow->scrolls[ScrollIndex]; + + // Horizontal + auto left = result.width - widget->right + widget->left + 21; + if (left < 0) + left = 0; + if (left < scroll.h_left) + { + scroll.h_left = left; + Invalidate(); + } + + // Vertical + auto top = result.height - widget->bottom + widget->top + 21; + if (top < 0) + top = 0; + if (top < scroll.v_top) + { + scroll.v_top = top; + Invalidate(); + } } return result; } @@ -517,7 +537,7 @@ void CustomListView::Paint(rct_window* w, rct_drawpixelinfo* dpi, const rct_scro auto paletteIndex = ColourMapA[w->colours[1]].mid_light; gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width, dpi->y + dpi->height, paletteIndex); - int32_t y = ShowColumnHeaders ? LIST_ROW_HEIGHT + 1 : 0; + int32_t y = ShowColumnHeaders ? COLUMN_HEADER_HEIGHT : 0; for (size_t i = 0; i < Items.size(); i++) { if (y > dpi->y + dpi->height) @@ -665,7 +685,7 @@ std::optional CustomListView::GetItemIndexAt(const ScreenCoordsXY& po else { // Check what row we pressed - int32_t firstY = ShowColumnHeaders ? LIST_ROW_HEIGHT + 1 : 0; + int32_t firstY = ShowColumnHeaders ? COLUMN_HEADER_HEIGHT : 0; int32_t row = (pos.y - firstY) / LIST_ROW_HEIGHT; if (row >= 0 && row < static_cast(Items.size())) { @@ -703,6 +723,29 @@ std::optional CustomListView::GetItemIndexAt(const ScreenCoordsXY& po return result; } +void CustomListView::RefreshScroll() +{ + window_init_scroll_widgets(ParentWindow); + Invalidate(); +} + +rct_widget* CustomListView::GetWidget() const +{ + size_t scrollIndex = 0; + for (auto widget = ParentWindow->widgets; widget->type != WWT_LAST; widget++) + { + if (widget->type == WWT_SCROLL) + { + if (scrollIndex == ScrollIndex) + { + return widget; + } + scrollIndex++; + } + } + return nullptr; +} + void CustomListView::Invalidate() { ParentWindow->Invalidate(); diff --git a/src/openrct2-ui/scripting/CustomListView.h b/src/openrct2-ui/scripting/CustomListView.h index e51fe0df98..d6f2c83ba5 100644 --- a/src/openrct2-ui/scripting/CustomListView.h +++ b/src/openrct2-ui/scripting/CustomListView.h @@ -145,6 +145,8 @@ namespace OpenRCT2::Ui::Windows rct_drawpixelinfo* dpi, const ScreenCoordsXY& pos, const ScreenSize& size, const char* text, bool isHighlighted) const; std::optional GetItemIndexAt(const ScreenCoordsXY& pos); + void RefreshScroll(); + rct_widget* GetWidget() const; void Invalidate(); }; } // namespace OpenRCT2::Ui::Windows diff --git a/src/openrct2-ui/scripting/CustomWindow.cpp b/src/openrct2-ui/scripting/CustomWindow.cpp index 84feda7735..4a1c2b66fb 100644 --- a/src/openrct2-ui/scripting/CustomWindow.cpp +++ b/src/openrct2-ui/scripting/CustomWindow.cpp @@ -581,6 +581,18 @@ namespace OpenRCT2::Ui::Windows } InvokeEventHandler(info.Owner, info.Desc.OnUpdate); } + + // Since the plugin may alter widget positions and sizes during an update event, + // we need to force an update for all list view scrollbars + rct_widgetindex widgetIndex = 0; + for (auto widget = w->widgets; widget->type != WWT_EMPTY; widget++) + { + if (widget->type == WWT_SCROLL) + { + widget_scroll_update_thumbs(w, widgetIndex); + } + widgetIndex++; + } } static void window_custom_scrollgetsize(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height)