Created
January 8, 2019 19:32
-
-
Save joinr/039e2b182e5cdba308770cadf73ce7cb to your computer and use it in GitHub Desktop.
an extend example of the fn-fx form example, this time with a timer and a label that updates the model (reflected in the UI) programatically.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns getting-started.reactlike | |
(:require [fn-fx.fx-dom :as dom] | |
[fn-fx.diff :refer [component defui render should-update?]] | |
[fn-fx.controls :as ui])) | |
(def firebrick | |
(ui/color :red 0.69 :green 0.13 :blue 0.13)) | |
;; The main login window component, notice the authed? parameter, this defines a function | |
;; we can use to construct these ui components, named "login-form" | |
(defui LoginWindow | |
(render [this {:keys [authed? label]}] | |
(ui/grid-pane | |
:alignment :center | |
:hgap 10 | |
:vgap 10 | |
:padding (ui/insets | |
:bottom 25 | |
:left 25 | |
:right 25 | |
:top 25) | |
:children [(ui/text | |
:text "Welcome" | |
:font (ui/font | |
:family "Tahoma" | |
:weight :normal | |
:size 20) | |
:grid-pane/column-index 0 | |
:grid-pane/row-index 0 | |
:grid-pane/column-span 2 | |
:grid-pane/row-span 1) | |
(ui/label | |
:text "User:" | |
:grid-pane/column-index 0 | |
:grid-pane/row-index 1) | |
(ui/text-field | |
:id :user-name-field | |
:grid-pane/column-index 1 | |
:grid-pane/row-index 1) | |
(ui/label :text "Password:" | |
:grid-pane/column-index 0 | |
:grid-pane/row-index 2) | |
(ui/password-field | |
:id :password-field | |
:grid-pane/column-index 1 | |
:grid-pane/row-index 2) | |
(ui/h-box | |
:spacing 10 | |
:alignment :bottom-right | |
:children [(ui/button :text "Sign in" | |
:on-action {:event :auth | |
:fn-fx/include {:user-name-field #{:text} | |
:password-field #{:text}}})] | |
:grid-pane/column-index 1 | |
:grid-pane/row-index 4) | |
(ui/text | |
:text (if authed? "Sign in was pressed" "") | |
:fill firebrick | |
:grid-pane/column-index 1 | |
:grid-pane/row-index 6) | |
(ui/text | |
:text (or label "No label present!") | |
:fill firebrick | |
:grid-pane/column-index 1 | |
:grid-pane/row-index 7)]))) | |
;; Wrap our login form in a stage/scene, and create a "stage" function | |
(defui Stage | |
(render [this args] | |
(ui/stage | |
:title "JavaFX Welcome" | |
:shown true | |
:scene (ui/scene | |
:root (login-window args))))) | |
(def app-state (atom nil)) | |
(defn reset-state! [] | |
(do (reset! app-state {:authed? false}) | |
app-state)) | |
(defn set-label! [x] | |
(swap! app-state assoc :label x)) | |
(defn -main [] | |
(let [;; Data State holds the business logic of our app | |
;; now it points to the global app-state.... | |
data-state (reset-state!) | |
;; handler-fn handles events from the ui and updates the data state | |
handler-fn (fn [{:keys [event] :as all-data}] | |
(println "UI Event" event all-data) | |
(case event | |
:auth (swap! data-state assoc :authed? true) | |
(println "Unknown UI event" event all-data))) | |
;; ui-state holds the most recent state of the ui | |
ui-state (agent (dom/app (stage @data-state) handler-fn))] | |
;; Every time the data-state changes, queue up an update of the UI | |
;; Transitively, we can push changes to the DOM by munging with | |
;; the global app state now. | |
(add-watch data-state :ui (fn [_ _ _ _] | |
(send ui-state | |
(fn [old-ui] | |
(dom/update-app old-ui (stage @data-state)))))))) | |
(comment | |
(-main) | |
;;Let's see what happens when we change the time.... | |
(def res (future | |
(while true | |
(do (set-label! (str (System/currentTimeMillis) " ms")) | |
(Thread/sleep 16))))) | |
;;we're now propogating changes to our model just modifying the | |
;;atom from another thread. You can do this a number of ways, | |
;;uncluding core.async. I used futures... | |
;;to stop the counter (manually), cancel the future. | |
;;we'd probably use channels or something else for this. | |
#_(future-cancel res)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment