bjogui/examples/counter.bjo
Linus Björnstam 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

35 lines
1.2 KiB
Text

;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;; bjogui/examples/counter.bjo — a counter and a greeting in a window.
;;
;; bjo run examples/counter.bjo
(import (std prelude))
(import (bjogui view))
(import (bjogui app))
(type (: Msg (Union Inc Dec (: Typed string))))
(type (: Model (Record (: count int) (: name string))))
(: gui-update (-> Msg Model (Tuple Model (List (Event Msg)))))
(defun (gui-update msg m)
(next
(match msg
(Inc (record-set m (count (+ (.count m) 1))))
(Dec (record-set m (count (- (.count m) 1))))
((Typed s) (record-set m (name s))))))
(: view (-> Model (View Msg)))
(defun (view m)
(column #:spacing 8.0 #:margin 16.0
(text-input (.name m) Typed #:placeholder "Your name")
(text #"Hello, ${(if (string-empty? (.name m)) "stranger" (.name m))}!" #:size 18.0)
(row #:spacing 8.0
(button "-" Dec #:width 40.0)
(text #"${(.count m)}" #:size 18.0 #:margin 4.0)
(button "+" Inc #:width 40.0))))
(defun (main)
(run-app (Model (count 0) (name "")) gui-update view #:title "Counter" #:width 320.0 #:height 200.0))