· 6 years ago · Nov 28, 2019, 08:08 PM
1local version = "1.1"
2
3function startup()
4
5 print("ChamAPI> Loading Version: "..version)
6
7 -- Load API "aeslua"
8 if not fs.exists("aeslua") then
9 print("ChamAPI> \"aeslua\" not found! Retrieving via wget!")
10 shell.run("wget","https://git.io/aeslua","aeslua")
11 end
12 os.loadAPI("aeslua")
13 print("ChamAPI> \"aeslua\" successfully loaded!")
14end
15
16-- > Most of these functions below are from the Touchpoint API, mainly in the Term class and the new(), setupLabel() functions below all with modifications with variable names, features, etc.
17-- > https://pastebin.com/pFHeia96
18local function setupLabel(buttonLen, minY, maxY, name)
19 local labelTable = {}
20 if type(name) == "table" then
21 for i = 1, #name do
22 labelTable[i] = name[i]
23 end
24 name = name.label
25 elseif type(name) == "string" then
26 local buttonText = string.sub(name, 1, buttonLen - 2)
27 if #buttonText < #name then
28 buttonText = " "..buttonText.." "
29 else
30 local labelLine = string.rep(" ", math.floor((buttonLen - #buttonText) / 2))..buttonText
31 buttonText = labelLine..string.rep(" ", buttonLen - #labelLine)
32 end
33 for i = 1, maxY - minY + 1 do
34 if maxY == minY or i == math.floor((maxY - minY) / 2) + 1 then
35 labelTable[i] = buttonText
36 else
37 labelTable[i] = string.rep(" ", buttonLen)
38 end
39 end
40 end
41 return labelTable, name
42end
43
44local function verifySpace(row,fixMap)
45 for i = #fixMap - 3, #fixMap do
46 for j = row, row + 3 do
47 if fixMap[i][j] then
48 return false
49 end
50 end
51 end
52 return true
53end
54
55local Term = {
56
57 draw = function(self)
58 term = self.mon
59 term.clear()
60 self:updateTextWrap()
61
62 for id, compoData in pairs(self.compoList) do
63 if not compoData.fixed then
64 term.setCursorPos(compoData.x1,compoData.fixed and compoData.y1 or compoData.y1 - self.scrollY)
65 term.setTextColor(compoData.color)
66 term.setBackgroundColor(compoData.bgColor)
67 if not compoData.hidden then
68 if compoData.label then
69 for i = compoData.y1, compoData.y2 do
70 term.setCursorPos(compoData.x1, compoData.fixed and i or i - self.scrollY)
71 term.write(compoData.label[i - compoData.y1 + 1])
72 end
73 else
74 for i = compoData.y1, #compoData.wrapLines + compoData.y1 do
75 term.setCursorPos(compoData.x1 + (i == compoData.y1 and 0 or compoData.wrapIndent), compoData.fixed and i or i - self.scrollY)
76 term.write(compoData.wrapLines[i - compoData.y1 + 1])
77 end
78 end
79 end
80 end
81 end
82 for id, compoData in pairs(self.compoList) do
83 if compoData.fixed then
84 term.setCursorPos(compoData.x1,compoData.y1)
85 term.setTextColor(compoData.color)
86 term.setBackgroundColor(compoData.bgColor)
87 if not compoData.hidden then
88 if compoData.label then
89 for i = compoData.y1, compoData.y2 do
90 term.setCursorPos(compoData.x1, i)
91 term.write(compoData.label[i - compoData.y1 + 1])
92 end
93 else
94 for i = compoData.y1, #compoData.wrapLines + compoData.y1 do
95 term.setCursorPos(compoData.x1,i or i)
96 term.write(compoData.wrapLines[i - compoData.y1 + 1])
97 end
98 end
99 end
100 end
101 end
102
103 self:updateScrollIndicator()
104
105 term.setBackgroundColor(self.monColor)
106 end,
107
108 addText = function(self, id, text, x, y, color, bgColor, wrapIndent)
109 if not (self or id) then
110 error("Too few arguments", 2)
111 end
112
113 if (self.compoList[2000] and id==2000) or (self.compoList[4000] and id==4000) then
114 error("ID is API-reserved", 2)
115 end
116
117 self.compoList[id] = {
118 wrapLines = {},
119 wrapIndent = wrapIndent or 1,
120 text = text or "",
121 x1 = x,
122 y1 = y,
123 x2 = x,
124 y2 = y,
125 color = color or colors.white,
126 bgColor = bgColor or colors.black,
127 hidden = false,
128 fixed = false
129 }
130
131 self:updateScrollbar()
132 self:updateTextWrap()
133 end,
134
135 addButton = function(self, id, text, func, x1, y1, x2, y2, color, bgColor)
136 if not (self or id or func or x1 or y1 or x2 or y2) then
137 error("Too few arguments", 2)
138 end
139
140 if (self.compoList[2000] and id==2000) or (self.compoList[4000] and id==4000) then
141 error("ID is API-reserved", 2)
142 end
143
144 label, newText = setupLabel(x2 - x1, y1, y2, text or "")
145
146 self.compoList[id] = {
147 label = label,
148 text = newText,
149 func = func,
150 x1 = x1,
151 y1 = y1,
152 x2 = x2,
153 y2 = y2,
154 color = color or colors.white,
155 bgColor = bgColor or colors.black,
156 hidden = false,
157 fixed = false
158 }
159
160 self:updateClickMap()
161 self:updateScrollbar()
162 end,
163
164 hide = function(self,id)
165 self.compoList[id].hidden = true
166 self:updateClickMap()
167 self:updateScrollbar()
168 end,
169
170 hideAll = function(self)
171 for id, compoData in pairs(self.compoList) do
172 compoData.hidden = true
173 end
174 self:updateClickMap()
175 self:updateScrollbar()
176 end,
177
178 show = function(self,id)
179 self.compoList[id].hidden = false
180 self:updateClickMap()
181 self:updateScrollbar()
182 end,
183
184 showAll = function(self)
185 for id, compoData in pairs(self.compoList) do
186 compoData.hidden = false
187 end
188 self:updateClickMap()
189 self:updateScrollbar()
190 end,
191
192 fix = function(self, id)
193 self.compoList[id].fixed = true
194 self:updateClickMap()
195 self:updateScrollbar()
196 end,
197
198 unfix = function(self, id)
199 self.compoList[id].fixed = false
200 self:updateClickMap()
201 self:updateScrollbar()
202 end,
203
204 scroll = function(self,n)
205 local _,h = self.mon.getSize()
206 self.hiddenY = self.maxY - h - self.scrollY
207 if self.scrollY + n < 0 then
208 self.scrollY = 0
209 elseif self.hiddenY - n <= 0 then
210 self.scrollY = self.maxY - h
211 else
212 self.scrollY = self.scrollY + n
213 end
214
215 self:updateScrollButton(2000,true)
216 if self.scrollY == 0 then
217 self:updateScrollButton(2000,false)
218 end
219 self.hiddenY = self.maxY - h - self.scrollY
220 if self.compoList[4000] then
221 self:updateScrollButton(4000,true)
222 if self.hiddenY <= 0 then
223 self:updateScrollButton(4000,false)
224 end
225 end
226
227 self:updateClickMap()
228 end,
229
230 setColor = function(self,id,color)
231 self.compoList[id].color = color
232 end,
233
234 setBGColor = function(self, id, color)
235 self.compoList[id].bgColor = color
236 end,
237
238 setMonColor = function(self, color)
239 self.monColor = color
240 end,
241
242 showScrollbar = function(self, hideValue)
243 if not hideValue then
244 self.compoList[2000].hidden = true
245 if self.compoList[4000]~=nil then
246 self.compoList[4000].hidden = true
247 end
248 self.scrollbarShown = false
249 else
250 self.compoList[2000].hidden = false
251 if self.compoList[4000]~=nil then
252 self.compoList[4000].hidden = false
253 end
254 self.scrollbarShown = true
255 end
256 self:updateTextWrap()
257 end,
258
259 updateClickMap = function(self)
260
261 for i in ipairs(self.clickMap) do
262 self.clickMap[i] = {}
263 self.fixMap[i] = {}
264 end
265
266 for id, compoData in pairs(self.compoList) do
267 if compoData.label and not compoData.fixed and not compoData.hidden then
268 for i=compoData.x1,compoData.x2 do
269 for j = compoData.y1 - self.scrollY, compoData.y2 - self.scrollY do
270 if j>0 and j<=self.width then
271 self.clickMap[i][j] = id
272 end
273 end
274 end
275 end
276 end
277 for id, compoData in pairs(self.compoList) do
278 if compoData.label and compoData.fixed and not compoData.hidden then
279 for i=compoData.x1,compoData.x2 do
280 for j = compoData.y1, compoData.y2 do
281 if j>0 and j<=self.width then
282 self.clickMap[i][j] = id
283 if id~=2000 and id~=4000 then
284 self.fixMap[i][j] = true
285 end
286 end
287 end
288 end
289 end
290 end
291 end,
292
293 updateScrollbar = function(self)
294 local curMaxY = 0
295 for id, compoData in pairs(self.compoList) do
296 if not compoData.fixed and not compoData.hidden then
297 local iMaxY = compoData.y2
298 if curMaxY < iMaxY then
299 curMaxY = iMaxY
300 end
301 end
302 end
303
304 self.hiddenY = curMaxY - self.height - self.scrollY
305
306 self.maxY = curMaxY
307
308 self.compoList[2000].hidden = true
309 self:locateAvailableTop()
310 if self.compoList[4000] then
311 self.compoList[4000].hidden = true
312 self:locateAvailableBottom()
313 end
314
315 if self.hiddenY <= 0 then
316 self:showScrollbar(false)
317 self.scrollY = 0
318 self:updateScrollButton(2000,false)
319 else
320 self:showScrollbar(true)
321 end
322
323 end,
324
325 updateTextWrap = function(self)
326 local term = self.mon
327 for id, compoData in pairs(self.compoList) do
328 if compoData.wrapLines and not compoData.hidden then
329 local maxLength = (self.scrollbarShown and -3 or 0) + self.width
330 compoData.wrapLines = {compoData.text}
331 compoData.y2 = compoData.y1
332 while #compoData.wrapLines[#compoData.wrapLines]>maxLength-compoData.x1+1- (#compoData.wrapLines==1 and 0 or compoData.wrapIndent) do
333 if #compoData.text==1 then
334 break
335 end
336 local i = #compoData.wrapLines[#compoData.wrapLines]
337 while (string.sub(compoData.wrapLines[#compoData.wrapLines],i,i)~=" " or i>maxLength - compoData.x1+1- (#compoData.wrapLines==1 and 0 or compoData.wrapIndent)) and i>1 do
338 i = i - 1
339 end
340 local leftover = string.sub(compoData.wrapLines[#compoData.wrapLines],1,i-1)
341 local toWrap = string.sub(compoData.wrapLines[#compoData.wrapLines],i+1)
342 compoData.wrapLines[#compoData.wrapLines] = leftover
343 compoData.wrapLines[#compoData.wrapLines+1] = toWrap
344 compoData.y2 = compoData.y2 + 1
345 end
346 end
347 end
348 end,
349
350 locateAvailableTop = function(self)
351 local i = 1
352 while not verifySpace(i,self.fixMap) or i==self.height-1 do
353 i = i + 1
354 end
355 self.barTop = i + 4
356 self.compoList[2000].y1 = i
357 self.compoList[2000].y2 = i+3
358 end,
359
360 locateAvailableBottom = function(self)
361 local i = self.height - 3
362 while not verifySpace(i,self.fixMap) or i==2 do
363 i = i - 1
364 end
365 self.barBottom = i
366 self.compoList[4000].y1 = i
367 self.compoList[4000].y2 = i+3
368 end,
369
370 updateScrollIndicator = function(self)
371 local scrollLength = self.maxY - self.height
372 if scrollLength <= 0 then
373 return
374 end
375 local barRoomLength = self.barBottom - self.barTop
376
377 local sf = barRoomLength / self.maxY
378
379 local segmentLength = math.floor(self.height * sf)
380
381 local barY = math.floor(self.scrollY * sf)
382
383 local term = self.mon
384
385 for i = self.width - 3, self.width - 1 do
386 for j = barY + self.barTop, barY + self.barTop + segmentLength do
387 term.setCursorPos(i, j)
388 term.setBackgroundColor(colors.gray)
389 term.write(" ")
390 term.setBackgroundColor(self.monColor)
391 end
392 end
393 end,
394
395 updateScrollButton = function(self,id,enable)
396 if enable then
397 self.compoList[id].label[2] = " "..(id==2000 and string.char(30) or string.char(31)).." "
398 self:setBGColor(id,colors.blue)
399 self:setColor(id,colors.white)
400 else
401 self.compoList[id].label[2] = " "
402 self:setBGColor(id,colors.lightGray)
403 self:setColor(id,colors.brown)
404 end
405 end,
406
407 run = function(self)
408 while true do
409 self:draw()
410 local event = {self:handleEvents(os.pullEvent(self.side=="term" and "mouse_click" or "monitor_touch"))}
411
412 if event[1]=="button_click" then
413 self.compoList[event[2]].func()
414 end
415
416 end
417 end,
418
419 handleEvents = function(self, ...)
420 local event = {...}
421
422 if #event == 0 then
423 event = {os.pullEvent()}
424 end
425
426 if (self.side=="term" and event[1]=="mouse_click") or (self.side ~= "term" and event[1]=="monitor_touch" and event[2]==self.side) then
427 local clicked = self.clickMap[event[3]][event[4]]
428 if clicked and self.compoList[clicked] and not self.compoList[clicked].hidden then
429 return "button_click", clicked
430 end
431 end
432
433 if (self.side=="term" and event[1]=="key") then
434 if (event[2]==200 or event[2]==203) then
435 return "key", -1
436 end
437 if (event[2]==205 or event[2]==208) then
438 return "key", 1
439 end
440 end
441
442 return unpack(event)
443 end
444}
445
446function new(monSide, monColor)
447 local termInstance = {
448 side = monSide or "term",
449 mon = monSide and peripheral.wrap(monSide) or term.current(),
450 monColor = monColor or colors.black,
451
452 maxY = 0,
453 scrollY = 0,
454 hiddenY = 0,
455 barTop = 0,
456 barBottom = 0,
457 scrollbarShown = false,
458 width = 0,
459 height = 0,
460
461 fixMap = {},
462 compoList = {},
463 clickMap = {}
464 }
465
466 if termInstance.mon~=term.current() then
467 termInstance.mon.setTextScale(0.5)
468 end
469
470 local w, h = termInstance.mon.getSize()
471
472 for i = 1, w do
473 termInstance.fixMap[i] = {}
474 termInstance.clickMap[i] = {}
475 end
476 setmetatable(termInstance, {__index = Term})
477
478 termInstance:addButton(2000," ",function()termInstance:scroll(-4)end,w-3,1,w,4,colors.lightGray,colors.lightGray)
479 termInstance:addButton(4000,string.char(31),function()termInstance:scroll(4)end,w-3,h-3,w,h,colors.white,colors.blue)
480
481 termInstance.width = w
482 termInstance.height = h
483
484 termInstance:hide(2000)
485 termInstance:hide(4000)
486
487 termInstance:fix(2000)
488 termInstance:fix(4000)
489
490 return termInstance
491end
492
493startup()