145 lines
5.6 KiB
Text
145 lines
5.6 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/src/view.bjo — the module (bjogui view).
|
||
|
|
;;
|
||
|
|
;; A view is a value: what the window shows for one model. `view` functions
|
||
|
|
;; build it with the constructors here, and (bjogui app) makes the controls
|
||
|
|
;; for it and changes them when the next view differs. Nothing here knows
|
||
|
|
;; about Avalonia, so a view can be built and compared in a test with no
|
||
|
|
;; window.
|
||
|
|
;;
|
||
|
|
;; An event is a message, or a function that makes one from what the control
|
||
|
|
;; holds. The app gives the message to `update`.
|
||
|
|
|
||
|
|
(export
|
||
|
|
;; Types.
|
||
|
|
View Kind Prop On
|
||
|
|
|
||
|
|
;; Constructors.
|
||
|
|
text button text-input checkbox column row
|
||
|
|
|
||
|
|
;; Reading one.
|
||
|
|
view-kind view-props view-events view-children)
|
||
|
|
|
||
|
|
(import (std prelude))
|
||
|
|
|
||
|
|
;; ---------------------------------------------------------------------------
|
||
|
|
;; The types
|
||
|
|
;; ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
;; What control a view is.
|
||
|
|
(type (: Kind (Union TextKind ButtonKind TextInputKind CheckBoxKind ColumnKind RowKind)))
|
||
|
|
|
||
|
|
;; A property of a control. A kind takes only some of them; the app ignores
|
||
|
|
;; the others.
|
||
|
|
(type (: Prop (Union (: Label string) ; the text of a text, a button or a checkbox
|
||
|
|
(: Value string) ; the text in a text input
|
||
|
|
(: Placeholder string) ; shown in an empty text input
|
||
|
|
(: Checked bool)
|
||
|
|
(: Enabled bool)
|
||
|
|
(: FontSize double)
|
||
|
|
(: Width double)
|
||
|
|
(: Height double)
|
||
|
|
(: Margin double)
|
||
|
|
(: Padding double)
|
||
|
|
(: Spacing double))))
|
||
|
|
|
||
|
|
;; An event, and the message it sends.
|
||
|
|
(type (: (On %m) (Union (: Click %m)
|
||
|
|
(: Input (-> string %m))
|
||
|
|
(: Toggle (-> bool %m)))))
|
||
|
|
|
||
|
|
;; One control and what is in it.
|
||
|
|
(type (: (View %m) (Record (: kind Kind)
|
||
|
|
(: props (Vec Prop))
|
||
|
|
(: events (Vec (On %m)))
|
||
|
|
(: children (Vec (View %m))))))
|
||
|
|
|
||
|
|
(: view-kind (-> (View %m) Kind))
|
||
|
|
(defun (view-kind v) (.kind v))
|
||
|
|
|
||
|
|
(: view-props (-> (View %m) (Vec Prop)))
|
||
|
|
(defun (view-props v) (.props v))
|
||
|
|
|
||
|
|
(: view-events (-> (View %m) (Vec (On %m))))
|
||
|
|
(defun (view-events v) (.events v))
|
||
|
|
|
||
|
|
(: view-children (-> (View %m) (Vec (View %m))))
|
||
|
|
(defun (view-children v) (.children v))
|
||
|
|
|
||
|
|
;; ---------------------------------------------------------------------------
|
||
|
|
;; Constructors
|
||
|
|
;; ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
;; A size of zero or less means: the size the control asks for. The
|
||
|
|
;; constructors leave such a size out of the props, so the control keeps its
|
||
|
|
;; own.
|
||
|
|
(: (-> (Vec Prop) (-> double Prop) double (Vec Prop)))
|
||
|
|
(defun (with-size props make size)
|
||
|
|
(if (> size 0.0) (vec-add props (make size)) props))
|
||
|
|
|
||
|
|
(: (-> (Vec Prop) double double double double (Vec Prop)))
|
||
|
|
(defun (with-layout props width height margin padding)
|
||
|
|
(with-size (with-size (with-size (with-size props Width width) Height height)
|
||
|
|
Margin margin)
|
||
|
|
Padding padding))
|
||
|
|
|
||
|
|
(: (-> Kind (Vec Prop) (Vec (On %m)) (View %m)))
|
||
|
|
(defun (leaf kind props events)
|
||
|
|
(View (kind kind) (props props) (events events) (children [])))
|
||
|
|
|
||
|
|
;; A text.
|
||
|
|
(: (-> string (#:size double) (#:width double) (#:height double) (#:margin double)
|
||
|
|
(View %m)))
|
||
|
|
(defun (text s #:size 0.0 #:width 0.0 #:height 0.0 #:margin 0.0)
|
||
|
|
(leaf TextKind
|
||
|
|
(with-layout (with-size [(Label s)] FontSize size) width height margin 0.0)
|
||
|
|
[]))
|
||
|
|
|
||
|
|
;; A button that sends `msg` when it is clicked.
|
||
|
|
(: (-> string %m (#:enabled bool) (#:width double) (#:height double)
|
||
|
|
(#:margin double) (#:padding double)
|
||
|
|
(View %m)))
|
||
|
|
(defun (button label msg #:enabled #t #:width 0.0 #:height 0.0 #:margin 0.0 #:padding 0.0)
|
||
|
|
(leaf ButtonKind
|
||
|
|
(with-layout [(Label label) (Enabled enabled)] width height margin padding)
|
||
|
|
[(Click msg)]))
|
||
|
|
|
||
|
|
;; A one-line text input that holds `value`. Each change sends `(on-input
|
||
|
|
;; text)`, with the whole text.
|
||
|
|
(: (-> string (-> string %m) (#:placeholder string) (#:enabled bool)
|
||
|
|
(#:width double) (#:margin double)
|
||
|
|
(View %m)))
|
||
|
|
(defun (text-input value on-input #:placeholder "" #:enabled #t #:width 0.0 #:margin 0.0)
|
||
|
|
(leaf TextInputKind
|
||
|
|
(with-layout [(Value value) (Placeholder placeholder) (Enabled enabled)]
|
||
|
|
width 0.0 margin 0.0)
|
||
|
|
[(Input on-input)]))
|
||
|
|
|
||
|
|
;; A checkbox that is `checked?`. A click sends `(on-toggle checked)`, with
|
||
|
|
;; the new state.
|
||
|
|
(: (-> string bool (-> bool %m) (#:enabled bool) (#:margin double) (View %m)))
|
||
|
|
(defun (checkbox label checked? on-toggle #:enabled #t #:margin 0.0)
|
||
|
|
(leaf CheckBoxKind
|
||
|
|
(with-layout [(Label label) (Checked checked?) (Enabled enabled)] 0.0 0.0 margin 0.0)
|
||
|
|
[(Toggle on-toggle)]))
|
||
|
|
|
||
|
|
(: (-> Kind double double (Array (View %m)) (View %m)))
|
||
|
|
(defun (stack kind spacing margin children)
|
||
|
|
(View (kind kind)
|
||
|
|
(props (with-layout (with-size [] Spacing spacing) 0.0 0.0 margin 0.0))
|
||
|
|
(events [])
|
||
|
|
(children (array->vec children))))
|
||
|
|
|
||
|
|
;; Views one above the other.
|
||
|
|
(: (-> (#:spacing double) (#:margin double) #:rest (View %m) (View %m)))
|
||
|
|
(defun (column #:spacing 0.0 #:margin 0.0 #:rest children)
|
||
|
|
(stack ColumnKind spacing margin children))
|
||
|
|
|
||
|
|
;; Views side by side.
|
||
|
|
(: (-> (#:spacing double) (#:margin double) #:rest (View %m) (View %m)))
|
||
|
|
(defun (row #:spacing 0.0 #:margin 0.0 #:rest children)
|
||
|
|
(stack RowKind spacing margin children))
|