-
Notifications
You must be signed in to change notification settings - Fork 0
/
core.clj
189 lines (171 loc) · 6.43 KB
/
core.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
(ns strigui.core
(:require
[clojure.edn :as edn]
[clojure.java.io :as io]
[strigui.button]
[strigui.label]
[strigui.input :as inp]
[strigui.window :as wnd]
[strigui.widget :as wdg])
(:import [strigui.button Button]
[strigui.label Label]
[strigui.input Input]))
(defn find-by-name
"Find and return an widget by its name"
[name]
((:widgets @wdg/state) name))
(defn find-by-group
"Retuns a vector of widgets by group name"
[name]
(let [get-seq (fn [x] (if (string? x) (vector x) x))
filter-crit (fn [x] (some #(= name %) (-> x :args :group get-seq)))]
(filter filter-crit (:widgets @wdg/state))))
(defn remove!
"Remove an widget by its name"
[name]
(when-let [box-to-remove (find-by-name name)]
(wdg/unregister! (-> @wdg/state :context :canvas) box-to-remove)))
(defn remove-group!
"Removes all widgets assigned to the given group"
[name]
(when-let [widgets (find-by-group name)]
(loop [widgets widgets]
(when (seq widgets)
(wdg/unregister! (-> @wdg/state :context :canvas) (first widgets))
(recur (rest widgets))))
widgets))
(defn- update-widget!
[widget key value]
(when (seq widget)
(wdg/unregister! (-> @wdg/state :context :canvas) widget)
(let [keys (if (seqable? key) key (vector key))]
(wdg/register! (-> @wdg/state :context :canvas) (assoc-in widget keys value)))))
(defn update!
"Update any property of a widget via the widget name.
name - name of the widget
key - either single key or vector of keys
value - the new property value"
[name key value]
(when-let [w (find-by-name name)]
(update-widget! w key value)))
(defn update-group!
[name key value]
(when-let [widgets (find-by-group name)]
(loop [widgets widgets]
(when (seq widgets)
(update-widget! (first widgets) key value)
(recur (rest widgets))))
widgets))
(defn window!
"Initializes a new window or reuses an existing one
wind - an already existing windows instance (experimental)
width
height
fps - frames per second
quality - rendering quality :low :mid :high :highest"
([wind]
(swap! wdg/state assoc :context (wnd/init-window wind)))
([width height title]
(swap! wdg/state assoc :context (wnd/init-window width height title)))
([width height title ^Integer fps quality]
{:pre [(> fps 0) (some #(= % quality) [:low :mid :high :highest])]}
(swap! wdg/state assoc :context (wnd/init-window width height title fps quality))))
(defn create!
"Register and show a custom widget.
Registering a component with the same name will replace the existing component with the new one."
[^strigui.widget.Widget widget]
(remove! (:name widget))
(let [canvas (-> @wdg/state :context :canvas)
widget (wdg/adjust-dimensions canvas widget)
widget (wdg/defaults widget)
neighbours (wdg/all-neighbouring-widgets canvas widget (->> @wdg/state :widgets vals) >)
neighbours (sort-by #(-> % :args :z) neighbours)]
(apply wdg/redraw! canvas neighbours)
(wdg/register! canvas widget)))
(defn close-window
"Closes the current active window."
[]
(wnd/close-window (-> @wdg/state :context :window)))
(defn button!
"Create a simple button on screen.
name - name of the element
text - text displayed inside the button
args - map of:
x - x coordinate of top left corner
y - y coordinate of top left corner
color - vector consisting of [background-color font-color]
min-width - the minimum width"
[name text args]
(create! (Button. name text args)))
(defn label!
"Create a simple label on screen.
name - name of the element
text - text displayed inside the button
args - map of:
x - x coordinate of top left corner
y - y coordinate of top left corner
color - vector consisting of [font-color]
font-style - vector consisting of either :bold :italic :italic-bold
font-size - number"
[name text args]
(create! (Label. name text args)))
(defn input!
"Create a simple imput field on screen.
name - name of the element
text - text displayed inside the button
args - map of:
x - x coordinate of top left corner
y - y coordinate of top left corner
color - vector consisting of [background-color font-color]
min-width - the minimum width"
[name text args]
(create! (inp/input (-> @wdg/state :context :canvas) name text args)))
(defn info
[text]
(wnd/display-info (:context @wdg/state) text))
(defn from-map
"Initializes the window and the widgets from a map"
[strigui-map]
(when-let [window-args (:window strigui-map)]
(apply window! window-args))
(let [exprs (for [widget-key (filter #(not= % :window) (keys strigui-map))]
(for [widgets-args (map identity (widget-key strigui-map))]
(str "(strigui.core/create! (apply " (namespace widget-key) "/->" (name widget-key) " " widgets-args "))")))]
(loop [exp (mapcat identity exprs)]
(when (seq exp)
(eval (read-string (first exp)))
(recur (rest exp))))))
(defn from-file
"Initializes the window and the widgets from a edn file"
[file-name]
(when (.exists (io/file file-name))
(->> (slurp file-name)
edn/read-string
from-map)))
(defn to-map
"converts the current state to a map that could be stored in a file"
[]
(let [window (select-keys (-> @wdg/state :context :window) [:w :h :fps :frame])
window-name (-> window :frame .getTitle)
{:keys [w h name fps]} (assoc (select-keys window [:w :h :fps]) :name window-name)
strigui-map {:window [w h name fps]}
widgets-grouped (group-by #(class %) (-> @wdg/state :widgets))
widget-types (keys widgets-grouped)
widget-map (loop [w-types widget-types
w-map {}]
(if (seq w-types)
(recur (rest w-types) (merge w-map {(keyword (clojure.string/replace-first (str (first w-types)) #"class " ""))
(mapv #(vec (vals (select-keys % (filter (fn [k] (not= k :events)) (keys %))))) (get widgets-grouped (first w-types)))}))
w-map))
strigui-map (merge strigui-map widget-map)]
strigui-map))
(defn to-file
"Writes the current state of strigui into a edn file"
[file-name]
(when (.exists (io/file file-name))
(io/delete-file file-name))
(->> (to-map)
str
(#(clojure.string/replace % #"]]," "]]\n"))
(#(clojure.string/replace % #"," ""))
(spit file-name)))