Apple renderer: honour Prop.Axis (horizontal Scroll) in both Swift shims #4

Closed
opened 2026-09-28 08:53:46 -07:00 by rleibman · 0 comments
Owner

Prop.Axis(Orientation) is new in modules/renderer-api and is the framework's answer to Row overflow: Row clips, so a row wider than the screen goes inside a horizontal Scroll. GTK and Android now honour it; the Apple renderer ignores it (AppleRenderer.update has an explicit no-op case Prop.Axis(_) with a comment pointing here), so on macOS and iOS such a row still clips.

Why it needs the Mac. The axis is read at create, and create reaches Swift as a single int kind code (sui_create(kindCode)), so the axis has to travel as a new code rather than a later setter. On Android the two directions are genuinely different classes; on AppKit/UIKit one class does both, so the shim change is small.

What to do

  1. scalaui_apple.h / AppleRenderer.kindCode: reserve kind code 9 for a horizontal Scroll. Keep 6 as the vertical one so nothing existing moves.
  2. AppleRenderer.create: pick 9 when props contains Prop.Axis(Orientation.Horizontal), 6 otherwise. Then delete the no-op case Prop.Axis(_) => () comment's "not yet honoured" wording and leave it a documented create-only no-op, exactly as GTK and Android have it (the contract says a renderer may ignore an axis change at update).
  3. Shim+AppKit.swift: for 9, an NSScrollView with hasHorizontalScroller = true, hasVerticalScroller = false, and the document view pinned so it can exceed the clip view's width but not its height.
  4. Shim+UIKit.swift: for 9, a UIScrollView with showsHorizontalScrollIndicator = true, alwaysBounceHorizontal = true, and the content's height constrained to the scroll view's frame height while its width is free.

How to verify. examples/shared TodoApp now puts its five action buttons (Add, Rotate, Drop, About, 10 000 rows) inside Scroll(axis = Orientation.Horizontal). The GTK self-test measures it and should be mirrored: the row's content wants ~429px while the scroller's own natural width is ~46px. On Apple, assert the equivalent — the scroll view's intrinsic/fitting width is far below its content's — and confirm the fifth button is reachable by scrolling rather than clipped. Add the check to the existing 23-check macOS/iOS self-test and record the two numbers in the report.

See docs/11-what-it-looks-like.md ("Two gaps this exposed") and the 2026-09-28 entry in docs/decisions.md.

`Prop.Axis(Orientation)` is new in `modules/renderer-api` and is the framework's answer to `Row` overflow: `Row` clips, so a row wider than the screen goes inside a horizontal `Scroll`. GTK and Android now honour it; the Apple renderer ignores it (`AppleRenderer.update` has an explicit no-op `case Prop.Axis(_)` with a comment pointing here), so on macOS and iOS such a row still clips. **Why it needs the Mac.** The axis is read at `create`, and `create` reaches Swift as a single int kind code (`sui_create(kindCode)`), so the axis has to travel as a new code rather than a later setter. On Android the two directions are genuinely different classes; on AppKit/UIKit one class does both, so the shim change is small. **What to do** 1. `scalaui_apple.h` / `AppleRenderer.kindCode`: reserve kind code **9** for a horizontal `Scroll`. Keep 6 as the vertical one so nothing existing moves. 2. `AppleRenderer.create`: pick 9 when `props` contains `Prop.Axis(Orientation.Horizontal)`, 6 otherwise. Then delete the no-op `case Prop.Axis(_) => ()` comment's "not yet honoured" wording and leave it a documented create-only no-op, exactly as GTK and Android have it (the contract says a renderer may ignore an axis change at `update`). 3. `Shim+AppKit.swift`: for 9, an `NSScrollView` with `hasHorizontalScroller = true`, `hasVerticalScroller = false`, and the document view pinned so it can exceed the clip view's width but not its height. 4. `Shim+UIKit.swift`: for 9, a `UIScrollView` with `showsHorizontalScrollIndicator = true`, `alwaysBounceHorizontal = true`, and the content's height constrained to the scroll view's frame height while its width is free. **How to verify.** `examples/shared` `TodoApp` now puts its five action buttons (`Add`, `Rotate`, `Drop`, `About`, `10 000 rows`) inside `Scroll(axis = Orientation.Horizontal)`. The GTK self-test measures it and should be mirrored: the row's content wants ~429px while the scroller's own natural width is ~46px. On Apple, assert the equivalent — the scroll view's intrinsic/fitting width is far below its content's — and confirm the fifth button is reachable by scrolling rather than clipped. Add the check to the existing 23-check macOS/iOS self-test and record the two numbers in the report. See `docs/11-what-it-looks-like.md` ("Two gaps this exposed") and the 2026-09-28 entry in `docs/decisions.md`.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
rleibman/scala-ui#4
No description provided.