Skip to content

Make the scrolling container reach the last row of a multi-column grid - #236

Open
rubensworks wants to merge 1 commit into
master-1.21-ltsfrom
claude/scrolling-grid-rows
Open

Make the scrolling container reach the last row of a multi-column grid#236
rubensworks wants to merge 1 commit into
master-1.21-ltsfrom
claude/scrolling-grid-rows

Conversation

@rubensworks

@rubensworks rubensworks commented Sep 1, 2026

Copy link
Copy Markdown
Member

ScrollingInventoryContainer supports multiple columns — onScroll walks i * getColumns() + j and getScrollStepSize() defaults to getColumns() — but two places still assume there is only one.

The last row is unreachable

ContainerScreenScrolling computes the scrollbar's total rows as filteredItemCount / getColumns(), in both init and updateSearch. That truncates, so WidgetScrollBar#getScrollStep (totalRows - visibleRows) comes out one short and the last, partially filled row can never be scrolled to.

Measured live in a dev client, on a 9-column grid of 985 elements with 6 visible rows, by setting the scrollbar to each value and scrolling fully to the bottom:

totalRows last row at full scroll highest reachable element
985 / 9 = 109 (today) 9 cells — a full row index 980
ceil(985 / 9) = 110 (this PR) 4 cells past index 984

The final element is index 984, so 981–984 are unreachable: the scrollbar is already at the bottom and they never appear.

Rounded up now, in one getTotalRows() both call sites share, so a subclass that wants different behaviour has a single place to override.

isElementVisible returns false past the first row

public boolean isElementVisible(int row) {
    return row < getPageSize() && getVisibleElement(row) != null;
}

getPageSize() is the number of rows, while the parameter indexes into the visible elements, which number rows × columns. So for a grid this returns false for everything after the first row, even though getVisibleElement returns those elements and onScroll fills them in. It now guards against getPageSize() * getColumns(); for a single-column container the two are identical, so nothing changes for existing users.

A cosmetic third one

The constructor null-filled only the first getPageSize() entries of a list that is rows × columns long. Harmless, since Arrays.asList(new Object[n]) is already all-null, but it read as if the rest were left uninitialized.

How this came up

Building a 9 × 6 recipe grid on ScrollingInventoryContainer in IntegratedCrafting (CyclopsMC/IntegratedCrafting#221). Both were worked around locally there; that workaround can go once a release carries this.

Testing

./gradlew :loader-neoforge:compileJava passes. Behaviour verified in a dev client through the IntegratedCrafting grid, as measured above: with the fix, scrolling fully down lands on a last row holding exactly the 4 remaining elements (985 % 9 = 4), and every cell renders across the whole scroll range.

🤖 Generated with Claude Code

https://claude.ai/code/session_01T9xTc8kXNRDppvXktL24aR

ScrollingInventoryContainer supports multiple columns, but two places assume
there is only one.

ContainerScreenScrolling computes the scrollbar's total rows as
`filteredItemCount / getColumns()`, which truncates. With one column that is
exact, but with nine columns and 985 elements it gives 109 rows instead of 110,
so the four elements of the last row can never be scrolled to. The division is
rounded up now, in one place both call sites share.

isElementVisible guards against getPageSize(), which is the number of rows, and
so returns false for every element past the first row of a grid, even though
getVisibleElement returns them and onScroll fills them in. It now guards against
the size of the visible elements, which is rows times columns; for a
single-column container the two are the same.

The constructor also only null-filled the first getPageSize() entries of a list
that is rows times columns long. That was harmless, as the array it wraps is
already all-null, but it read as if the rest were left uninitialized.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T9xTc8kXNRDppvXktL24aR
@sonarqubecloud

sonarqubecloud Bot commented Sep 1, 2026

Copy link
Copy Markdown

@coveralls

coveralls commented Sep 1, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 26.641% (-0.002%) from 26.643% — claude/scrolling-grid-rows into master-1.21-lts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants