· 4 years ago · Oct 11, 2021, 03:56 PM
1-----------------
2--Graphical API--
3-----------------
4
5ACTIVE_BUTTON_FADEOUT_DELAY_SECONDS = 0.5
6
7function writeButtonText(button_window, text, width, height)
8 button_window.setCursorPos(1, height / 2 + 1)
9 button_window.write(text)
10end
11
12function createButton(text, x_topleft, y_topleft, width, height, toggle, text_color, color, color_active, on_click, parent_window, custom_on_click_data)
13 -- Create button window and initialize default values
14 local button_window = window.create(parent_window, x_topleft, y_topleft, width, height)
15 assert(color ~= nil)
16 color_active = (color_active == nil and color or color_active)
17 button_window.setBackgroundColor(color)
18 button_window.setTextColor(text_color)
19 button_window.clear()
20
21 -- Write text in the Center
22 writeButtonText(button_window, text, width, height)
23 button_window.setCursorBlink(false)
24
25 return
26 {
27 window=button_window,
28 toggle=toggle,
29 color=color,
30 color_active=color_active,
31 on_click=on_click,
32 text=text,
33 custom=custom_on_click_data,
34 available=true
35 }
36end
37
38
39local buttons = {}
40
41function registerButton(button)
42 table.insert(buttons, button)
43end
44
45function createDirectionButtons(x_topleft, y_topleft, cell_size_x, cell_size_y, color, color_active, event_name, parent_window)
46 local data = {
47 selected="NONE",
48 status_window=window.create(parent_window, x_topleft + cell_size_x + 1, y_topleft + cell_size_y * 3 + 3, cell_size_x * 3, cell_size_y)
49 }
50
51 data["status_window"].setBackgroundColor(parent_window.getBackgroundColor())
52 data["status_window"].clear()
53
54 local function printStatus(window, selected)
55 window.setCursorPos(1, 1)
56 window.clearLine()
57 window.write(selected)
58 end
59
60 printStatus(data["status_window"], data["selected"]:upper())
61
62 local function action(window, payload)
63 local data = payload["data"]
64 local previous_tag = data["selected"]
65 local selected = data[previous_tag]
66
67 if (selected ~= nil) then
68 selected["window"].setBackgroundColor(color)
69 selected["window"].clear()
70 end
71
72 if previous_tag == payload["side"] then
73 data["selected"] = "NONE"
74 printStatus(data["status_window"], "NONE")
75 else
76 data["selected"] = payload["side"]
77 printStatus(data["status_window"], data["selected"]:upper())
78 end
79
80 os.queueEvent(event_name, previous_tag, data["selected"]:upper(), selected)
81 end
82
83 for y_cell = 1, 3, 1 do
84 for x_cell = 1, 3, 1 do
85 if (x_cell == 2 and y_cell == 1) then
86 data["top"] = createButton("", x_topleft + cell_size_x + 1, y_topleft, cell_size_x, cell_size_y, true, color, color, color_active, action, parent_window, {data=data, side="top"})
87 else if (x_cell == 1 and y_cell == 2) then
88 data["left"] = createButton("", x_topleft, y_topleft + cell_size_y + 1, cell_size_x, cell_size_y, true, color, color, color_active, action, parent_window, {data=data, side="left"})
89 else if (x_cell == 2 and y_cell == 2) then
90 data["front"] = createButton("", x_topleft + cell_size_x + 1, y_topleft + cell_size_y + 1, cell_size_x, cell_size_y, true, color, color, color_active, action, parent_window, {data=data, side="front"})
91 else if (x_cell == 3 and y_cell == 2) then
92 data["right"] = createButton("", x_topleft + cell_size_x * 2 + 2, y_topleft + cell_size_y + 1, cell_size_x, cell_size_y, true, color, color, color_active, action, parent_window, {data=data, side="right"})
93 else if (x_cell == 1 and y_cell == 3) then
94 data["back"] = createButton("", x_topleft, y_topleft + cell_size_y * 2 + 2, cell_size_x, cell_size_y, true, color, color, color_active, action, parent_window, {data=data, side="back"})
95 else if (x_cell == 2 and y_cell == 3) then
96 data["bottom"] = createButton("", x_topleft + cell_size_x + 1, y_topleft + cell_size_y * 2 + 2, cell_size_x, cell_size_y, true, color, color, color_active, action, parent_window, {data=data, side="bottom"})
97 end
98 end
99 end
100 end
101 end
102 end
103 end
104 end
105
106 for key, value in pairs(data) do
107 if (key ~= "selected" and key ~= "status_window") then
108 registerButton(value)
109 end
110 end
111
112 return data;
113end
114
115-- Event handlers
116
117local active_button_timer_ids = {}
118
119function buttonClickEventHandler(x, y)
120 -- Executing button on click function if there was a click on it
121 for _, button in ipairs(buttons) do
122 if button["available"] then
123 local window = button["window"]
124 x_tl, y_tl = window.getPosition()
125 x_tl = x_tl
126 y_tl = y_tl
127
128 x_br, y_br = window.getSize()
129 x_br = x_br + x_tl
130 y_br = y_br + y_tl
131
132 if (x >= x_tl and x <= x_br and y >= y_tl and y <= y_br) then
133 -- Change Background color of a button
134 if button["toggle"] then
135 if window.getBackgroundColor() == button["color"] then
136 window.setBackgroundColor(button["color_active"])
137 else
138 window.setBackgroundColor(button["color"])
139 end
140 else
141 window.setBackgroundColor(button["color_active"])
142 local timer_id = os.startTimer(ACTIVE_BUTTON_FADEOUT_DELAY_SECONDS)
143 local data =
144 {
145 window=window,
146 color=button["color"],
147 text=button["text"]
148 }
149 table.insert(active_button_timer_ids, timer_id, data)
150 end
151
152 button["on_click"](button["window"], button["custom"])
153 window.clear()
154 writeButtonText(window, button["text"], window.getSize())
155 break
156 end
157 end
158 end
159end
160
161function mouseClickEventHandler(raw_event)
162 local event, mouse_button, x, y = raw_event[1], raw_event[2], raw_event[3], raw_event[4]
163
164 if (mouse_button == 1) then
165 buttonClickEventHandler(x, y)
166 end
167end
168
169function keyEventHandler(raw_event)
170 local event, key, is_help = raw_event[1], raw_event[2], raw_event[3]
171
172 if (key == keys.slash) then
173 exit()
174 end
175end
176
177function timerEventHandler(raw_event)
178 local event, id = raw_event[1], raw_event[2]
179
180 if (active_button_timer_ids[id] ~= nil) then
181 local data = active_button_timer_ids[id]
182 data["window"].setBackgroundColor(data["color"])
183 data["window"].clear()
184 writeButtonText(data["window"], data["text"], data["window"].getSize())
185 end
186end
187
188function eventHandlerPipeline(externalEventHandler)
189 while true do
190 local eventData = {os.pullEvent()}
191 local event = eventData[1]
192
193 if event == "mouse_click" then
194 mouseClickEventHandler(eventData)
195 else if event == "key" then
196 keyEventHandler(eventData)
197 else if event == "timer" then
198 timerEventHandler(eventData)
199 externalEventHandler(event, eventData)
200 else
201 externalEventHandler(event, eventData)
202 end
203 end
204 end
205 end
206end
207
208-----------
209--CLASSES--
210-----------
211
212MutableTextArea = {}
213
214function MutableTextArea:new(parent_window, x_topleft, y_topleft, width, height, background_color, text_color, shadow, shadow_color, text)
215 local private = {}
216 if (shadow) then
217 private.shadow_window = window.create(parent_window, x_topleft - 1, y_topleft - 1, width, height)
218 private.shadow_window.setBackgroundColor(shadow_color)
219 private.shadow_window.clear()
220 end
221
222 private.window = window.create(parent_window, x_topleft, y_topleft, width, height)
223 private.window.setBackgroundColor(background_color)
224 private.window.setTextColor(text_color)
225 private.window.clear()
226
227 function private:updateWindow()
228 private.window.setTextColor(private.text_color)
229 private.window.setBackgroundColor(private.background_color)
230 private.window.clear()
231 term.redirect(private.window)
232 print(text)
233 term.redirect(parent_window)
234 end
235
236 function private:updateShadow()
237 private.shadow_window.setBackgroundColor(private.background_color)
238 private.shadow_window.clear()
239 end
240
241 local public = {}
242 public.background_color = background_color or colors.black
243 public.text_color = text_color or colors.white
244 public.shadow = shadow or false
245 public.shadow_color = shadow_color
246 public.text = text or ""
247
248 function public:refresh()
249 if (private.shadow_window ~= nil) then
250 private:updateShadow()
251 end
252
253 private:updateWindow()
254 end
255
256 setmetatable(public, self)
257 self.__index = self; return public
258end
259
260
261return {
262 writeButtonText = writeButtonText,
263 createButton = createButton,
264 registerButton = registerButton,
265 createDirectionButtons = createDirectionButtons,
266 eventHandlerPipeline = eventHandlerPipeline,
267 MutableTextArea = MutableTextArea
268}
269