Skip to content

feat(markup): a list column can draw a button in each row - #223

Merged
eriknihlen merged 4 commits into
eriknihlen:mainfrom
davidc-smith:feat/list-button-column-upstream
Oct 19, 2026
Merged

eriknihlen merged 4 commits into
eriknihlen:mainfrom
davidc-smith:feat/list-button-column-upstream

Conversation

@davidc-smith

Copy link
Copy Markdown
Contributor

What this changes

A markup <list> gets a fourth column type, button, for per-row actions:

<column type="button" width="64" items="{Captions}" onclick="{Act}" buttonw="40" buttonh="14" />
  • Each row's caption is drawn on a button with the face and border of a markup <button>
    (the theme's colours on a themed window), lighter while hovered and darker while pressed.
  • onclick is an Action<int> given the row index. It fires when the left button comes up
    over the button it went down on, as a <button> does, so a press dragged off cancels it.
    The click never selects the row.
  • An empty caption draws no button and ignores clicks, so a row can have no action.
  • Optional buttonw / buttonh size the button, centred in its cell and never larger than it.
    Left out, the button fills the cell. Only the button itself takes clicks and hover.
  • items and onclick are required; a missing one, or a negative size, fails the window's
    build with the column and attribute named.

Before this, a row action had to be a text column with onclick, drawn as plain text like
the data beside it, so nothing showed it could be clicked.

docs/plugin-ui-markup.md documents the column; ListButtonColumnTests covers binding,
validation, click/cancel, empty captions, hover/press/disabled state, sizing and drawing.
UiControlState (normal, hovered, pressed, disabled) is a new small enum for the cell's look.

Original behavior

Not applicable: plugin markup only, nothing the client does in the world changes.

Checklist

  • dotnet build AcDream.slnx -c Release is green
  • The portable test filter passes locally (see CONTRIBUTING.md)
  • One topic per PR
  • No code copied from ACEmulator, ACViewer, or holtburger
  • No comments describing the original client's internals

https://claude.ai/code/session_01Lm9T9oP2Hi5FEjwsLmXeyN

davidc-smith and others added 4 commits October 14, 2026 12:02
A `<column type="button" items="{Captions}" onclick="{Act}">` draws each
row's caption on a button with the face and border of a markup `<button>`
(the theme's colours on a themed window), lighter while hovered and darker
while pressed. It fires the column's onclick with the row index when the
left button comes up over the button it went down on, and never selects
the row. An empty caption draws no button. Optional `buttonw`/`buttonh`
size the button, centred in its cell and never larger than it; only the
button itself takes clicks.

Claude-Session: https://claude.ai/code/session_01Lm9T9oP2Hi5FEjwsLmXeyN
The enum sat alone in a file named for something else. Only the list's
button cells and their tests use it, and nothing public returns it, so it
does not need to be part of the App's public surface.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…abled

A button column's onclick gets a row index, so a release could fire for a
different item than the one pressed. The press is now dropped if, before
the release, the list scrolls, its row count changes, or the pressed row's
text, caption or icon changes. The rows are re-read at the release, so a
change with no frame drawn in between still counts. Rows re-read with the
same content (bindings hand over a fresh array each read) still fire.
Disabling the list while pressed drops the press too.

A wheel scroll with no pointer move left the hover on a button that had
scrolled away; the hover is now found again from the last pointer position
after a scroll and on every draw.

A disabled list drew an enabled-looking face; face, border and caption now
fade by the alpha a disabled toggle's caption uses (named for both). A
caption wider than its button is cut at the button's edges instead of
running across the cell.

The docs now say what the button looks like on and off a theme, that its
hover and pressed looks are its own, and when a press is cancelled. New
tests go through UiRoot dispatch (press, release, capture taken away) and
cover each fix; the fix tests fail on the previous commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comparing the whole pressed row cancelled presses in lists with a live
column: a distance that updates every frame changed the row between press
and release, so the button beside it fired only now and then. The press is
now cancelled only when the list scrolls, its row count changes, or the
pressed button's own caption changes or becomes empty. Disabling the list
while the button is held still cancels it.

The docs say so, and note that a plugin which reorders rows without
changing the count should change the caption too. A new test has a
different column change between press and release and still fire; it fails
on the previous commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@eriknihlen
eriknihlen merged commit c92c14b into eriknihlen:main Oct 19, 2026
eriknihlen added a commit that referenced this pull request Oct 19, 2026
@davidc-smith
davidc-smith deleted the feat/list-button-column-upstream branch October 20, 2026 14:50
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.

2 participants