forked from cljfx/cljfx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathe22_button_with_confirmation_dialog.clj
82 lines (69 loc) · 3.43 KB
/
e22_button_with_confirmation_dialog.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
(ns e22-button-with-confirmation-dialog
(:require [cljfx.api :as fx]
[clojure.core.cache :as cache])
(:import [javafx.scene.control DialogEvent Dialog ButtonBar$ButtonData ButtonType]))
;; Example of generic component that is a button with confirmation dialog
;; Its local state is kept in `:internal` map of global app state. This component is
;; parameterized with state identifier which is a key in that map where such component can
;; put it's state, so having different independent instances of such component requires to
;; provide different state identifiers for such instances
(def *context
(atom (fx/create-context
{:showing true
:internal {}}
cache/lru-cache-factory)))
;; Events of `button-with-confirmation-dialog` component
(defmulti handle-event :event/type)
(defmethod handle-event ::show-confirmation
[{:keys [fx/context state-id]}]
{:context (fx/swap-context context assoc-in [:internal state-id :showing] true)})
(defmethod handle-event ::on-confirmation-dialog-hidden
[{:keys [fx/context ^DialogEvent fx/event state-id on-confirmed]}]
(condp = (.getButtonData ^ButtonType (.getResult ^Dialog (.getSource event)))
ButtonBar$ButtonData/CANCEL_CLOSE
{:context (fx/swap-context context assoc-in [:internal state-id :showing] false)}
ButtonBar$ButtonData/OK_DONE
{:context (fx/swap-context context assoc-in [:internal state-id :showing] false)
:dispatch on-confirmed}))
;; Independent event that is used as an example `:on-confirm` action
(defmethod handle-event ::quit
[{:keys [fx/context]}]
{:context (fx/swap-context context assoc :showing false)})
;; Component itself:
;; - `:state-id` for local state
;; - `:on-confirmed` is a callback event for action that requires confirmation
;; - `:button` and `:dialog-pane` are prop maps that are used to configure views
(defn button-with-confirmation-dialog [{:keys [fx/context
state-id
on-confirmed
button
dialog-pane]}]
{:fx/type fx/ext-let-refs
:refs {::dialog {:fx/type :dialog
:showing (fx/sub-val context get-in [:internal state-id :showing] false)
:on-hidden {:event/type ::on-confirmation-dialog-hidden
:state-id state-id
:on-confirmed on-confirmed}
:dialog-pane (merge {:fx/type :dialog-pane
:button-types [:cancel :ok]}
dialog-pane)}}
:desc (merge {:fx/type :button
:on-action {:event/type ::show-confirmation
:state-id state-id}}
button)})
(defn root-view [{:keys [fx/context]}]
{:fx/type :stage
:showing (fx/sub-val context :showing)
:scene {:fx/type :scene
:root {:fx/type :v-box
:padding 50
:children [{:fx/type button-with-confirmation-dialog
:state-id ::main-quit-button
:button {:text "Quit"}
:dialog-pane {:content-text "Are you sure?"}
:on-confirmed {:event/type ::quit}}]}}})
(def app
(fx/create-app *context
:event-handler handle-event
:desc-fn (fn [_]
{:fx/type root-view})))