bjogui/examples/stopwatch.bjo

56 lines
2.2 KiB
Text
Raw Permalink Normal View History

;; 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/stopwatch.bjo — a subscription and a command.
;;
;; bjo run examples/stopwatch.bjo
;;
;; The stopwatch ticks while it runs: `subscriptions` asks for a tick only
;; then, so stopping it stops the fiber. "Lap" saves the time after a pause,
;; to show a command: the pause runs in a fiber, and the window does not wait
;; for it.
(import (std prelude))
(import (bjogui view))
(import (bjogui app))
(type (: Msg (Union Toggle Tick Reset Lap (: Saved int))))
(type (: Model (Record (: tenths int) (: running bool) (: saving bool) (: laps (List int)))))
(: gui-update (-> Msg Model (Tuple Model (List (Event Msg)))))
(defun (gui-update msg m)
(match msg
(Toggle (next (record-set m (running (not (.running m))))))
(Tick (next (record-set m (tenths (+ (.tenths m) 1)))))
(Reset (next (record-set m (tenths 0) (laps '()))))
;; The time is taken now, and saved half a second later.
(Lap (next (record-set m (saving #t))
(wrap (timeout (milliseconds 500)) (fun (_) (Saved (.tenths m))))))
((Saved t) (next (record-set m (saving #f) (laps (cons t (.laps m))))))))
(: subscriptions (-> Model (List (Sub Msg))))
(defun (subscriptions m)
(if (.running m) (list (every (milliseconds 100) Tick)) '()))
(: (-> int string))
(defun (show tenths)
#"${(/ tenths 10)}.${(% tenths 10)} s")
(: view (-> Model (View Msg)))
(defun (view m)
(column #:spacing 8.0 #:margin 16.0
(text (show (.tenths m)) #:size 32.0)
(row #:spacing 8.0
(button (if (.running m) "Stop" "Start") Toggle #:width 80.0)
(button "Lap" Lap #:enabled (not (.saving m)) #:width 80.0)
(button "Reset" Reset #:width 80.0))
(apply column (vec->array (vec-map (fun (t) (text #"lap: ${(show t)}"))
(list->vec (.laps m)))))))
(defun (main)
(run-app (Model (tenths 0) (running #f) (saving #f) (laps '()))
gui-update view
#:subscriptions subscriptions
#:title "Stopwatch" #:width 320.0 #:height 300.0))