A tree node is a TreeViewItem: a header and items, patched by key as a
list's items are. The chosen node is chosen by its key, once the nodes are
there, and a click sends the key. SelectedItem is a direct property, which
a clear does not reset, so no choice is set as null.
The Readme now covers menus and keys, dialogs, styles and themes, and the
new controls. docs/styles.png is examples/styles.bjo.
🤖 Generated with [ECA](https://eca.dev) (anthropic/claude-opus-4-8)
Co-Authored-By: eca-agent <git@eca.dev>
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>
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>
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>
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>