run-app's #:theme gives "light", "dark" or the system's for a model, and is set again when it changes. classed puts a view in classes, and #:styles are rules of style: a kind and a class, and colours, a font size, a padding and a radius. A button's rule may also give the colours while the pointer is over it and while it is pressed; those are set on the presenter in its template, as the Fluent theme sets its own. Avalonia's Selectors.Class adds a class to a type-and-class selector it is given rather than making a new one, so each style's selector is made anew. 🤖 Generated with [ECA](https://eca.dev) (anthropic/claude-opus-4-8) Co-Authored-By: eca-agent <git@eca.dev>
144 lines
7.9 KiB
Text
144 lines
7.9 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/tests/inputs.bjo — switches, radios, numbers, dates, completion,
|
|
;; expanders, tooltips, flows and docks.
|
|
;;
|
|
;; bjo run tests/inputs.bjo
|
|
;;
|
|
;; No window is opened. A control is changed as a user's input would change
|
|
;; it, through its Avalonia property, and the message is checked.
|
|
|
|
(import (std prelude))
|
|
(import (std simpletest))
|
|
(import (bjogui view))
|
|
(import (bjogui app))
|
|
|
|
(import/class
|
|
(Object (: System.Object))
|
|
(ClrString (: System.String))
|
|
(Disposable (: System.IDisposable))
|
|
(AvaloniaObject (: Avalonia.AvaloniaObject))
|
|
(AvaloniaProperty (: Avalonia.AvaloniaProperty))
|
|
(Priority (: Avalonia.Data.BindingPriority))
|
|
(Control (: Avalonia.Controls.Control))
|
|
(Controls (: Avalonia.Controls.Controls))
|
|
(Panel (: Avalonia.Controls.Panel))
|
|
(ToggleButton (: Avalonia.Controls.Primitives.ToggleButton))
|
|
(NumericUpDown (: Avalonia.Controls.NumericUpDown))
|
|
(DatePicker (: Avalonia.Controls.DatePicker))
|
|
(DateTimeOffset (: System.DateTimeOffset))
|
|
(AutoCompleteBox (: Avalonia.Controls.AutoCompleteBox))
|
|
(Expander (: Avalonia.Controls.Expander))
|
|
(DockEdge (: Avalonia.Controls.Dock))
|
|
(StyledElement (: Avalonia.StyledElement))
|
|
(Classes (: Avalonia.Controls.Classes))
|
|
((Nullable %a) (: System.Nullable)))
|
|
|
|
(import/extern
|
|
(set-value (: Avalonia.AvaloniaObject.SetValue
|
|
(-> AvaloniaObject AvaloniaProperty Object Priority Disposable)))
|
|
(checked-property (: Avalonia.Controls.Primitives.ToggleButton.IsCheckedProperty #:get))
|
|
(number-property (: Avalonia.Controls.NumericUpDown.ValueProperty #:get))
|
|
(date-property (: Avalonia.Controls.DatePicker.SelectedDateProperty #:get))
|
|
(auto-property (: Avalonia.Controls.AutoCompleteBox.TextProperty #:get))
|
|
(expanded-property (: Avalonia.Controls.Expander.IsExpandedProperty #:get))
|
|
(is-checked (: Avalonia.Controls.Primitives.ToggleButton.IsChecked
|
|
(-> ToggleButton (Nullable bool)) #:get))
|
|
(number-value (: Avalonia.Controls.NumericUpDown.Value (-> NumericUpDown (Nullable decimal)) #:get))
|
|
(selected-date (: Avalonia.Controls.DatePicker.SelectedDate (-> DatePicker (Nullable DateTimeOffset)) #:get))
|
|
(parse-date (: System.DateTimeOffset.Parse (-> string DateTimeOffset)))
|
|
(expanded? (: Avalonia.Controls.Expander.IsExpanded (-> Expander bool) #:get))
|
|
(tip-of (: Avalonia.Controls.ToolTip.GetTip (-> Control Object)))
|
|
(dock-of (: Avalonia.Controls.DockPanel.GetDock (-> Control DockEdge)))
|
|
(children (: Avalonia.Controls.Panel.Children (-> Panel Controls) #:get))
|
|
(count (: Avalonia.Controls.Controls.Count (-> Controls int) #:get))
|
|
(classes-of (: Avalonia.StyledElement.Classes (-> StyledElement Classes) #:get))
|
|
(clr-string (: System.Convert.ToString (-> string ClrString))))
|
|
|
|
(type (: Msg (Union (: Switched bool) (: Picked string) (: Amount double) (: Dated string)
|
|
(: Typed string) (: Opened bool))))
|
|
(type (: Model (Record (: on bool) (: pick string) (: amount double) (: date string)
|
|
(: typed string) (: open bool))))
|
|
|
|
(: (-> Msg Model (Tuple Model (List (Event Msg)))))
|
|
(defun (gui-update msg m)
|
|
(next (match msg
|
|
((Switched b) (record-set m (on b)))
|
|
((Picked s) (record-set m (pick s)))
|
|
((Amount d) (record-set m (amount d)))
|
|
((Dated s) (record-set m (date s)))
|
|
((Typed s) (record-set m (typed s)))
|
|
((Opened b) (record-set m (open b))))))
|
|
|
|
(: (-> Model (View Msg)))
|
|
(defun (view m)
|
|
(column
|
|
(toggle-switch "Wi-Fi" (.on m) Switched) ; 0
|
|
(row (radio "tea" (= (.pick m) "tea") (Picked "tea")) ; 1 0
|
|
(radio "coffee" (= (.pick m) "coffee") (Picked "coffee"))) ; 1 1
|
|
(number-input (.amount m) Amount #:minimum 0.0 #:maximum 10.0 #:step 0.5) ; 2
|
|
(date-picker (.date m) Dated) ; 3
|
|
(auto-complete (.typed m) ["apple" "apricot" "banana"] Typed) ; 4
|
|
(expander "More" (.open m) Opened (text "inside")) ; 5
|
|
(tooltip (text "hover me") "a tip") ; 6
|
|
(flow #:spacing 4.0 (text "a") (text "b") (text "c")) ; 7
|
|
(dock (at-top (text "top")) (text "fill")) ; 8
|
|
(if (.open m) (classed (text "c") "wide") (classed (text "c") "big" "red")))) ; 9
|
|
|
|
(defun (main)
|
|
(def app (start-app (Model (on #f) (pick "tea") (amount 2.0) (date "2026-10-25")
|
|
(typed "") (open #f))
|
|
gui-update view (fun (c) unit)))
|
|
(defun (ctl path) (app-control-at app path))
|
|
(defun (put! path property value)
|
|
(ignore (set-value (cast AvaloniaObject (ctl path)) property value Priority.LocalValue)))
|
|
(defun (model) (app-model app))
|
|
|
|
;; --- switch and radios --------------------------------------------------------
|
|
(put! '(0) (cast AvaloniaProperty checked-property) (cast Object #t))
|
|
(expect "a switch sends its state" (.on (model)) #t)
|
|
(expect "a radio shows the model's choice"
|
|
(.GetValueOrDefault (is-checked (cast ToggleButton (ctl '(1 0))))) #t)
|
|
(put! '(1 1) (cast AvaloniaProperty checked-property) (cast Object #t))
|
|
(expect "choosing a radio sends its message" (.pick (model)) "coffee")
|
|
(expect "the other one is not chosen any more"
|
|
(.GetValueOrDefault (is-checked (cast ToggleButton (ctl '(1 0))))) #f)
|
|
|
|
;; --- number ---------------------------------------------------------------------
|
|
(expect "a number input's value" (cast System.Double (.GetValueOrDefault (number-value (cast NumericUpDown (ctl '(2)))))) 2.0)
|
|
(put! '(2) (cast AvaloniaProperty number-property) (cast Object (cast System.Decimal 3.5)))
|
|
(expect "a number sends its value" (.amount (model)) 3.5)
|
|
|
|
;; --- date -----------------------------------------------------------------------
|
|
(expect "a date picker's date" (.ToString (.-Value (selected-date (cast DatePicker (ctl '(3))))) "yyyy-MM-dd")
|
|
"2026-10-25")
|
|
(put! '(3) (cast AvaloniaProperty date-property) (cast Object (parse-date "2026-12-24")))
|
|
(expect "a date picked is sent" (.date (model)) "2026-12-24")
|
|
|
|
;; --- completion -------------------------------------------------------------------
|
|
(put! '(4) (cast AvaloniaProperty auto-property) (cast Object (clr-string "ap")))
|
|
(expect "completion sends what is typed" (.typed (model)) "ap")
|
|
|
|
;; --- expander ---------------------------------------------------------------------
|
|
(expect "an expander starts closed" (expanded? (cast Expander (ctl '(5)))) #f)
|
|
(put! '(5) (cast AvaloniaProperty expanded-property) (cast Object #t))
|
|
(expect "opening it sends a message" (.open (model)) #t)
|
|
|
|
;; --- tooltip, flow, dock ---------------------------------------------------------
|
|
(expect "a tooltip" (.ToString (tip-of (ctl '(6)))) "a tip")
|
|
(expect "a flow's children" (count (children (cast Panel (ctl '(7))))) 3)
|
|
(expect "a docked child" (written (dock-of (ctl '(8 0)))) "Top")
|
|
|
|
;; --- classes ---------------------------------------------------------------------
|
|
;; The expander was opened above, so the view has "wide" and not the others.
|
|
(def cls (classes-of (cast StyledElement (ctl '(9)))))
|
|
(defun (has-class? (: c Classes) (: name string)) (.Contains c name))
|
|
(expect "a class" (has-class? cls "wide") #t)
|
|
(expect "the classes of the last view are gone" (has-class? cls "big") #f)
|
|
(put! '(5) (cast AvaloniaProperty expanded-property) (cast Object #f))
|
|
(expect "and change with the model" (list (has-class? cls "big") (has-class? cls "red") (has-class? cls "wide"))
|
|
'(#t #t #f))
|
|
|
|
(println "bjogui inputs ok"))
|