Commands for focus, scrolling and the clipboard, and pictures from bytes

focus, scroll-to-end, scroll-to-start and scroll-into-view find their
control by the key of its view, and run once the update's controls are
laid out. copy-text puts text on the clipboard, and paste-text sends what
it holds. A command that sends no message ends its fiber when its work is
done, so none is left waiting until the app stops.

image-data shows a picture from the bytes of a file, read again only when
it is given another array.

start-headless! now adds the Fluent theme, as run-app does, so controls
are templated and laid out as in a window.

🤖 Generated with [ECA](https://eca.dev) (anthropic/claude-opus-4-8)

Co-Authored-By: eca-agent <git@eca.dev>
This commit is contained in:
Linus Björnstam 2026-10-25 21:15:12 +01:00
parent 52ebd0ace8
commit 708256d0b3
4 changed files with 342 additions and 11 deletions

View file

@ -62,6 +62,7 @@ being changed, and they are dropped, so only the user's events are messages.
| ~(progress-bar value)~ | ~ProgressBar~ | nothing |
| ~(dropdown options selected on-select)~ | ~ComboBox~ | ~(on-select index)~ |
| ~(image path)~ | ~Image~ | nothing |
| ~(image-data bytes)~, the bytes of a picture file | ~Image~ | nothing |
| ~(list-box views selected on-select)~ | ~ListBox~ | ~(on-select index)~ |
| ~(tabs selected on-select (tab header view) ...)~ | ~TabControl~ | ~(on-select index)~ |
| ~(column child ...)~, ~(row child ...)~ | ~StackPanel~ | nothing |
@ -101,7 +102,8 @@ number is pixels. ~(at row column view)~ puts a view in a cell, counting from
#:height 200.0)
#+END_SRC
An image that cannot be read shows nothing.
An image that cannot be read shows nothing. ~image-data~ reads its bytes
again only when it is given another array, so keep the array in the model.
A list box's items are views, so an item can be anything: a text, a row with
a checkbox, a dropdown. Give them keys if the list can change order. Each
@ -379,6 +381,30 @@ The fibers belong to the app. They post their messages to the UI thread, so
~gui-update~ and ~view~ always run there. When the window is closed they are
cancelled, and the program ends.
** Commands that act on the controls and the clipboard
Some commands do work of their own and send no message. Each finds its
control by the key of its view, given with ~keyed~, and runs once the
controls of the update are laid out, so a view the same update made is
there.
| Command | Does |
|-------------------------------+---------------------------------------------------------|
| ~(focus key)~ | gives the keyboard to the control |
| ~(scroll-to-end key)~ | scrolls a ~scroll~ view to its end, as a log wants |
| ~(scroll-to-start key)~ | scrolls a ~scroll~ view to its start |
| ~(scroll-into-view key)~ | scrolls the views around the control until it is seen |
| ~(copy-text text)~ | puts ~text~ on the clipboard |
| ~(paste-text on-text)~ | sends ~(on-text (Some text))~, or ~(on-text None)~ |
#+BEGIN_SRC scheme
(Add (next (record-set m (items (vec-add (.items m) (.draft m))) (draft ""))
(focus "draft")
(scroll-to-end "items")))
(keyed "draft" (text-input (.draft m) Draft))
#+END_SRC
* Dialogs: (bjogui dialogs)
A dialog is a command, and its answer comes back as a message.
@ -458,6 +484,7 @@ bjo run tests/tree.bjo # prints "bjogui tree ok"
bjo run tests/canvas.bjo # prints "bjogui canvas ok"
bjo run tests/components.bjo # prints "bjogui components ok"
bjo run tests/native.bjo # prints "bjogui native ok"
bjo run tests/commands.bjo # prints "bjogui commands ok"
bjo run examples/counter.bjo
bjo run examples/stopwatch.bjo
bjo run examples/todo.bjo