Commit graph

8 commits

Author SHA256 Message Date
cfcb1851b7 Dialogs, file pickers, and closing by the program's leave
(bjogui dialogs) has alert, confirm and prompt, the open, save and folder
pickers, and quit, each a command whose answer comes back as a message. A
dialog is a window, which only the UI thread may make, so the command posts
it there and awaits its Task in a fiber. Avalonia's dialogs take no
CancellationToken, so they cannot be task->event; the Task is awaited
through the non-generic Task.WhenAll, and its result read by reflection,
because Bjolang reads no Task's Result.

With no window, as under start-app, each answers as if cancelled.

run-app's #:on-close turns the close button into a message, and quit
closes the windows by program, which is not asked again.

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

Co-Authored-By: eca-agent <git@eca.dev>
2026-10-25 18:01:27 +01:00
be288ac03e Menus, context menus and keyboard shortcuts
A menu bar, submenus and menu items are views. A menu item's items are an
ItemsControl's, so they are patched as a list's. A context menu wraps a
view: the view and its menu are two places of the wrapper.

Keys are matched in the window's KeyDown, after the focused control had its
chance: an enabled menu item in the view whose shortcut it is, or else the
app's #:keys. Avalonia's own key bindings take an ICommand, which a Bjolang
program cannot make. app-press! presses keys for a test.

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

Co-Authored-By: eca-agent <git@eca.dev>
2026-10-25 17:55:19 +01:00
1e46202eef Show the todo picture in the Readme, and say how it was taken
🤖 Generated with [ECA](https://eca.dev) (anthropic/claude-opus-4-8)

Co-Authored-By: eca-agent <git@eca.dev>
2026-10-25 17:24:45 +01:00
5a80685397 A todo example, and its picture in the Readme
run-app takes #:screenshot, a path: the window saves a PNG of itself there
once it is shown and laid out, at twice its size, and closes. It defaults to
the environment variable BJOGUI_SCREENSHOT, so any program can be pictured
with no change. docs/todo.png is examples/todo.bjo, taken that way.

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

Co-Authored-By: eca-agent <git@eca.dev>
2026-10-25 17:24:32 +01:00
e773bc424e List boxes, tabs, colours and borders
A list box's items and a tab control's tabs are views, patched by key as a
column's children are: Panel.Children and ItemsControl.Items are both an
IList, so one patch serves both. A list can choose an item only once its
items are there, so the choice is set after the children.

A routed event bubbles, so each handler now takes only its own control's
events. Before, a dropdown in a list item would have been heard as the
list's choice too.

paint gives any view a text and a background colour, and border a frame. A
colour that cannot be read leaves the theme's.

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

Co-Authored-By: eca-agent <git@eca.dev>
2026-10-25 17:21:40 +01:00
95b6707cc1 Keyed children, and eight more controls
A child is now known by its key, or by its place among the children with no
key. One whose identity was there before keeps its control, and the
controls are put in the new order by moving only those out of place. So a
list that is sorted, or has an item put in front, keeps its controls.

Text areas, sliders, progress bars, dropdowns, images, grids with cells and
spans, and scroll views. A grid's sizes are .NET properties and not
Avalonia's, so they are set by a setter of their own. A text is centred in
its height, so a label lines up with the control beside it.

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

Co-Authored-By: eca-agent <git@eca.dev>
2026-10-25 17:13:35 +01:00
4f48282314 Commands and subscriptions, and gui-update
gui-update is a plain function, so it cannot wait. It returns the work to do
as values. A command is an (Event %m), synced in a fiber of its own, whose
answer is the next message. A subscription is a source of messages that the
model asks for: after each update the app starts the new ones and cancels the
ones that are gone, by key. every sends a message on a timer, and
subscription takes a source of one's own.

The fibers belong to the app's scope and post their messages to the UI
thread, so gui-update and view only run there. Closing the window cancels
them. The prelude's path macros already use the name update, hence
gui-update.

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

Co-Authored-By: eca-agent <git@eca.dev>
2026-10-25 17:02:02 +01:00
2f4c99ba62 Views, events as messages, and a patch, over plain Avalonia
A program is a model, an update and a view. A view is a Bjolang value; an
event finds its message in the view its control was last given, and the next
view is compared with the last so only what differs is changed. Controls are
made with plain constructors and changed with SetValue, so nothing is
subclassed, and a program never names an Avalonia type.

Text, button, text input, checkbox, column and row. tests/app.bjo drives an
app through its real controls with no window.

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

Co-Authored-By: eca-agent <git@eca.dev>
2026-10-25 16:18:09 +01:00