UXScrollView
UXScrollView is the generic vertical scroller: a clipped viewport over
a taller document view, with an optional pinned header strip and a
scrollbar (track, arrow boxes, a draggable thumb).
UXTableView and
UXOutlineView are built on it. Put a tall
view in the document and set its height, and the wheel, arrows, paging and
thumb-drag all work.
The document is moved, not re-laid-out. Scrolling sets the document view’s y
to -scrollOffset and the clip cuts it to the viewport. Your content keeps fixed
coordinates, and the ordinary hit test finds it where it is drawn.
On backends that scroll natively (Win32, AppKit) a native container overlays this whole subtree and the custom bar never draws. On GEM (and headless) this bar is the scrollbar.
#use <UXKit>Overview
Section titled “Overview”UXScrollView* sv = new UXScrollView();content.addSubview(sv, UXGeom.make(8, 8, 300, 200));
BigCanvas* big = new BigCanvas();sv.document().addSubview(big, UXGeom.make(0, 0, 300, 900));sv.setDocumentHeight(900);sv.setLineHeight(18); // the arrow/wheel stepTopics
Section titled “Topics”The document · document · setDocumentHeight · setHeaderView · setLineHeight Motion · scrollTo · scrollByLines Geometry · contentPx · viewportPx · scrollPx · maxScroll · needsBar
document
Section titled “document”UXView* document(void)The view your content goes in. Add subviews at their natural, fixed coordinates. Scrolling moves the document, not them.
setDocumentHeight
Section titled “setDocumentHeight”void setDocumentHeight(i32 h)The height of the content. All the scroll geometry derives from this number. Update it whenever the content grows.
setHeaderView
Section titled “setHeaderView”void setHeaderView(UXView* hv, i16 h)A strip pinned above the viewport, such as a table’s column header. It does not scroll with the document.
setLineHeight
Section titled “setLineHeight”void setLineHeight(i16 h)The arrow-click and wheel-notch step. A table sets its row height here so an arrow click moves one row.
scrollTo
Section titled “scrollTo”void scrollTo(i16 off)Scrolls to an absolute offset, clamped to [0, maxScroll]. This is the only
place a scroll is announced; every other motion goes through it.
scrollByLines
Section titled “scrollByLines”void scrollByLines(i32 lines)Relative motion in line-height steps, used by arrows, wheel notches and the keyboard.
contentPx
Section titled “contentPx”i32 contentPx(void)The document height, as set.
viewportPx
Section titled “viewportPx”i32 viewportPx(void)The visible height (the clip’s, minus any header).
scrollPx
Section titled “scrollPx”i32 scrollPx(void)The current scroll offset. On a native backend the container holds the real value, because the user can drag its scroller without the toolkit being told. This method asks the driver rather than reporting the last value the toolkit set.
maxScroll
Section titled “maxScroll”i32 maxScroll(void)The largest valid offset (zero when the document fits).
needsBar
Section titled “needsBar”bool needsBar(void)Whether the content overflows the viewport. The bar hides when it does not.
Platform appearance
Section titled “Platform appearance”
The toolkit’s scrollbar: track, arrows, and the proportional thumb over the clipped document.

The toolkit’s scrollbar. This driver does not yet use the native scroll container with the platform’s scrolling physics and indicators.

The toolkit’s scrollbar. This driver does not yet use the native scroll container with the platform’s scrolling physics and indicators.

A native scroll container owns the clipping; the platform’s overlay scrollers appear on interaction.

A native scroll child window with system scrollbars.

The toolkit’s scrollbar. This driver does not yet use the native scroll container with the platform’s scrolling physics and indicators.

The toolkit’s scrollbar: track, arrows, and the proportional thumb over the clipped document.
Example
Section titled “Example”Reveal a row from code. This works because scrollTo is the single path for
every scroll:
void revealRow(i32 row) { i32 y = row * rowH; if (y < sv.scrollPx()) { sv.scrollTo((i16)y); } else if (y + rowH > sv.scrollPx() + sv.viewportPx()) { sv.scrollTo((i16)(y + rowH - sv.viewportPx())); }}