;; 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/todo.bjo — a todo list. ;; ;; bjo run examples/todo.bjo ;; ;; The picture in the Readme is this program, taken with ;; ;; BJOGUI_SCREENSHOT=docs/todo.png bjo run examples/todo.bjo (import (std prelude)) (import (bjogui view)) (import (bjogui app)) (type (: Todo (Record (: id int) (: title string) (: done bool)))) (type (: Msg (Union (: Typed string) Add (: Toggle int bool) (: Chose int) ClearDone (: Tab int) (: Size double)))) (type (: Model (Record (: todos (List Todo)) (: draft string) (: next-id int) (: chosen int) (: tab int) (: size double)))) (: gui-update (-> Msg Model (Tuple Model (List (Event Msg))))) (defun (gui-update msg m) (next (match msg ((Typed s) (record-set m (draft s))) (Add (if (string-empty? (.draft m)) m (record-set m (todos (list-append (.todos m) (list (Todo (id (.next-id m)) (title (.draft m)) (done #f))))) (draft "") (next-id (+ (.next-id m) 1))))) ((Toggle id done) (record-set m (todos (list-map (fun (t) (if (= (.id t) id) (record-set t (done done)) t)) (.todos m))))) ((Chose i) (record-set m (chosen i))) (ClearDone (record-set m (todos (list-filter (fun (t) (not (.done t))) (.todos m))) (chosen -1))) ((Tab i) (record-set m (tab i))) ((Size d) (record-set m (size d)))))) (: (-> Model int)) (defun (done-count m) (length (list-filter (fun (t) (.done t)) (.todos m)))) (: (-> Model double Todo (View Msg))) (defun (todo-row m size t) (keyed (int->string (.id t)) (row #:spacing 8.0 (checkbox "" (.done t) (fun (b) (Toggle (.id t) b))) (if (.done t) (paint (text (.title t) #:size size) #:colour "#7f8c8d") (text (.title t) #:size size))))) (: (-> Model (View Msg))) (defun (todo-tab m) (def total (length (.todos m))) (column #:spacing 10.0 #:margin 12.0 (grid #:columns "*,Auto" #:spacing 8.0 (at 0 0 (text-input (.draft m) Typed #:placeholder "What needs doing?")) (at 0 1 (paint (button "Add" Add #:enabled (not (string-empty? (.draft m)))) #:background "#27ae60" #:colour "white"))) (list-box (vec-map (fun (t) (todo-row m (.size m) t)) (list->vec (.todos m))) (.chosen m) Chose #:height 218.0) (grid #:columns "*,Auto" #:spacing 8.0 (at 0 0 (column #:spacing 4.0 (text #"${(done-count m)} of ${total} done") (progress-bar (if (= total 0) 0.0 (/ (cast System.Double (done-count m)) (cast System.Double total)))))) (at 0 1 (button "Clear done" ClearDone #:enabled (> (done-count m) 0)))))) (: (-> Model (View Msg))) (defun (settings-tab m) (column #:spacing 10.0 #:margin 12.0 (text "Text size") (slider (.size m) 10.0 24.0 Size) (border (text "Written in Bjolang, drawn by Avalonia." #:wrap #t) #:colour "#2980b9" #:radius 6.0 #:background "#ecf0f1" #:padding 10.0))) (: (-> Model (View Msg))) (defun (view m) (column #:margin 8.0 (paint (text "Things to do" #:size 22.0 #:margin 6.0) #:colour "#2c3e50") (tabs (.tab m) Tab (tab "List" (todo-tab m)) (tab "Settings" (settings-tab m))))) (: (-> string bool int Todo)) (defun (todo title done id) (Todo (id id) (title title) (done done))) (defun (main) (run-app (Model (todos (list (todo "Buy milk" #t 1) (todo "Write the bjogui Readme" #t 2) (todo "Add menus and dialogs" #f 3) (todo "Walk the dog" #f 4))) (draft "Water the plants") (next-id 5) (chosen 2) (tab 0) (size 14.0)) gui-update view #:title "bjogui todo" #:width 420.0 #:height 450.0))