Tree views, a styles example, and the Readme for all of it
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>
This commit is contained in:
parent
e3c54c4348
commit
8941425f05
6 changed files with 321 additions and 10 deletions
106
Readme.org
106
Readme.org
|
|
@ -68,6 +68,16 @@ being changed, and they are dropped, so only the user's events are messages.
|
|||
| ~(grid #:columns #:rows child ...)~ | ~Grid~ | nothing |
|
||||
| ~(scroll child)~ | ~ScrollViewer~ | nothing |
|
||||
| ~(border child)~ | ~Border~ | nothing |
|
||||
| ~(toggle-switch label on? on-toggle)~ | ~ToggleSwitch~ | ~(on-toggle on)~ |
|
||||
| ~(radio label chosen? msg)~ | ~RadioButton~ | ~msg~ when it is chosen |
|
||||
| ~(number-input value on-change)~ | ~NumericUpDown~ | ~(on-change value)~ |
|
||||
| ~(date-picker "2026-10-25" on-change)~ | ~DatePicker~ | ~(on-change date)~ |
|
||||
| ~(auto-complete value options on-input)~ | ~AutoCompleteBox~ | ~(on-input text)~ |
|
||||
| ~(expander header expanded? on-toggle child)~ | ~Expander~ | ~(on-toggle expanded)~ |
|
||||
| ~(tree-view chosen on-pick (tree-node key header ...) ...)~ | ~TreeView~ | ~(on-pick key)~ |
|
||||
| ~(flow child ...)~ | ~WrapPanel~ | nothing |
|
||||
| ~(dock child ...)~, with ~at-top~, ~at-left~ … | ~DockPanel~ | nothing |
|
||||
| ~(menu-bar (submenu label (menu-item label msg) ...))~ | ~Menu~ | ~msg~ when an item is chosen |
|
||||
|
||||
They take keywords where they apply: ~#:size~ (the font size of a text),
|
||||
~#:wrap~ (a text breaks its lines at its width), ~#:width~, ~#:height~,
|
||||
|
|
@ -122,6 +132,53 @@ a line around a view, with round corners if ~#:radius~ is more than zero.
|
|||
The Fluent theme gives a button its own colours when the pointer is over it
|
||||
or it is pressed, so a painted button shows the theme's colour then.
|
||||
|
||||
More wrappers: ~(tooltip view "text")~, ~(with-context-menu view item ...)~
|
||||
for a menu on the right button, and ~(classed view "name" ...)~ for styles.
|
||||
|
||||
A tree node is known by its key, which must be its own in the tree. A node
|
||||
is open at first when it says ~#:expanded~; after that the user opens and
|
||||
closes it.
|
||||
|
||||
* Styles and themes
|
||||
|
||||
[[file:docs/styles.png]]
|
||||
|
||||
~run-app~'s ~#:theme~ gives ~"light"~, ~"dark"~, or anything else for the
|
||||
system's, for a model, so a setting can switch it. ~#:styles~ is a list of
|
||||
rules made by ~style~: a kind, by the name of its constructor, a class
|
||||
given with ~classed~, and the look.
|
||||
|
||||
#+BEGIN_SRC scheme
|
||||
(run-app init gui-update view
|
||||
#:theme (fun (m) (if (.dark m) "dark" "light"))
|
||||
#:styles (list (style "text" #:class "title" #:font-size 22.0 #:colour "#f1c40f")
|
||||
(style "button" #:class "primary" #:background "#27ae60" #:colour "white"
|
||||
#:hover-background "#2ecc71" #:pressed-background "#1e8449")))
|
||||
#+END_SRC
|
||||
|
||||
A rule takes ~#:colour~, ~#:background~, ~#:font-size~, ~#:padding~ and
|
||||
~#:radius~. A button's rule also takes ~#:hover-colour~, ~#:hover-background~,
|
||||
~#:pressed-colour~ and ~#:pressed-background~, which are set inside its
|
||||
template, as the Fluent theme sets its own; no other kind has them.
|
||||
[[file:examples/styles.bjo][examples/styles.bjo]] is the picture above.
|
||||
|
||||
* Menus and keys
|
||||
|
||||
#+BEGIN_SRC scheme
|
||||
(menu-bar
|
||||
(submenu "File"
|
||||
(menu-item "New" New #:shortcut "Ctrl+N")
|
||||
(menu-separator)
|
||||
(menu-item "Quit" Quit #:shortcut "Ctrl+Q")))
|
||||
#+END_SRC
|
||||
|
||||
A menu bar is a view, so it goes where the program puts it, usually at the
|
||||
top of a ~dock~. A menu item's ~#:shortcut~ is shown beside it, and the keys
|
||||
send its message while it is in the view and enabled. ~run-app~'s ~#:keys~
|
||||
gives more, for a model: ~(fun (m) (list (key "F5" Refresh)))~. Keys are
|
||||
the window's after the control that has the keyboard had its chance, so a
|
||||
text input keeps ~Ctrl+C~.
|
||||
|
||||
* Work: commands and subscriptions
|
||||
|
||||
~gui-update~ is a plain function, so it cannot wait, and the compiler says so
|
||||
|
|
@ -159,10 +216,42 @@ 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.
|
||||
|
||||
* Dialogs: (bjogui dialogs)
|
||||
|
||||
A dialog is a command, and its answer comes back as a message.
|
||||
|
||||
| Command | Sends |
|
||||
|-------------------------------------------+-----------------------------------------------|
|
||||
| ~(alert text msg)~ | ~msg~ when it is closed |
|
||||
| ~(confirm text on-answer)~ | ~(on-answer #t)~ for OK, ~#f~ otherwise |
|
||||
| ~(prompt text on-answer #:value)~ | ~(on-answer (Some text))~, or ~None~ |
|
||||
| ~(open-file on-answer #:filters)~ | ~(on-answer (Some path))~, or ~None~ |
|
||||
| ~(open-files on-answer)~ | ~(on-answer paths)~ |
|
||||
| ~(save-file on-answer #:name)~ | ~(on-answer (Some path))~, or ~None~ |
|
||||
| ~(open-folder on-answer)~ | ~(on-answer (Some path))~, or ~None~ |
|
||||
| ~(quit)~ | nothing: it closes the windows |
|
||||
|
||||
#+BEGIN_SRC scheme
|
||||
(Delete (next m (confirm "Delete it?" Deleted?)))
|
||||
((Deleted? #t) (next (remove m)))
|
||||
((Deleted? #f) (next m))
|
||||
#+END_SRC
|
||||
|
||||
~#:filters~ are kinds of file, each a name and patterns: ~(list (Tuple "Text"
|
||||
'("*.txt" "*.md")))~. ~run-app~'s ~#:on-close msg~ makes the close button
|
||||
send ~msg~ instead of closing, and the program closes with ~(quit)~ when it
|
||||
is ready, say after asking about unsaved work.
|
||||
|
||||
A dialog belongs to the main window. With none, as under ~start-app~, each
|
||||
answers as if it was cancelled. Avalonia's dialogs cannot be cancelled, so a
|
||||
command that is cancelled stops waiting, and the dialog stays until it is
|
||||
answered.
|
||||
|
||||
* Running: (bjogui app)
|
||||
|
||||
- ~(run-app init gui-update view #:subscriptions #:title #:width #:height)~
|
||||
opens a window and runs until it is closed.
|
||||
- ~(run-app init gui-update view #:subscriptions #:keys #:theme #:styles
|
||||
#:on-close #:title #:width #:height)~ opens a window and runs until it is
|
||||
closed.
|
||||
- ~#:screenshot path~ makes ~run-app~ save a PNG of the window once it is
|
||||
shown, at twice its size, and close it. It is the environment variable
|
||||
~BJOGUI_SCREENSHOT~ unless the program says otherwise, so any program can
|
||||
|
|
@ -176,6 +265,7 @@ cancelled, and the program ends.
|
|||
- ~app-run-pending!~ runs what fibers have posted, where no loop of
|
||||
Avalonia's does.
|
||||
- ~app-stop!~ cancels the subscriptions and drops later messages.
|
||||
- ~app-press!~ presses keys, such as ~"Ctrl+S"~, as the window does.
|
||||
- ~app-model~ reads the model, and ~app-control-at~ finds a control by its
|
||||
path of child indices.
|
||||
|
||||
|
|
@ -196,15 +286,21 @@ bjo run tests/app.bjo # prints "bjogui ok"
|
|||
bjo run tests/effects.bjo # prints "bjogui effects ok"
|
||||
bjo run tests/controls.bjo # prints "bjogui controls ok"
|
||||
bjo run tests/lists.bjo # prints "bjogui lists ok"
|
||||
bjo run tests/inputs.bjo # prints "bjogui inputs ok"
|
||||
bjo run tests/menus.bjo # prints "bjogui menus ok"
|
||||
bjo run tests/dialogs.bjo # prints "bjogui dialogs ok"
|
||||
bjo run tests/tree.bjo # prints "bjogui tree ok"
|
||||
bjo run examples/counter.bjo
|
||||
bjo run examples/stopwatch.bjo
|
||||
bjo run examples/todo.bjo
|
||||
bjo run examples/styles.bjo
|
||||
#+END_SRC
|
||||
|
||||
* Not yet
|
||||
|
||||
- Menus and dialogs.
|
||||
- Styles of one's own, with classes, and colours for the pointer-over and
|
||||
pressed states.
|
||||
- A data grid, and lists that make controls only for the items on screen.
|
||||
- Dialogs of one's own, with a view and a state.
|
||||
- The macOS menu bar.
|
||||
- Pointer-over and pressed colours for kinds other than buttons.
|
||||
- A moved control is taken out of the panel and put back, so it may lose the
|
||||
keyboard focus.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue