Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (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))
Add Comment
Please, Sign In to add comment