BIOSFERA

Untitled

Oct 18th, 2017
350
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.65 KB | None | 0 0
  1. -------------------------------------------------------------------------------------------
  2. ---Custon drawing API
  3. -------------------------------------------------------------------------------------------
  4. local function drawPixelInternal( target, xPos, yPos )
  5. target.setCursorPos(xPos, yPos)
  6. target.write(" ")
  7. end
  8.  
  9. local function drawPixel(target, xPos, yPos, nColour )
  10. if nColour then
  11. target.setBackgroundColor( nColour )
  12. end
  13. drawPixelInternal( target, xPos, yPos )
  14. end
  15.  
  16. local function drawLine(target, startX, startY, endX, endY, nColour )
  17. if nColour then
  18. target.setBackgroundColor( nColour )
  19. end
  20.  
  21. startX = math.floor(startX)
  22. startY = math.floor(startY)
  23. endX = math.floor(endX)
  24. endY = math.floor(endY)
  25.  
  26. if startX == endX and startY == endY then
  27. drawPixelInternal( target, startX, startY )
  28. return
  29. end
  30.  
  31. local minX = math.min( startX, endX )
  32. if minX == startX then
  33. minY = startY
  34. maxX = endX
  35. maxY = endY
  36. else
  37. minY = endY
  38. maxX = startX
  39. maxY = startY
  40. end
  41.  
  42. local xDiff = maxX - minX
  43. local yDiff = maxY - minY
  44.  
  45. if xDiff > math.abs(yDiff) then
  46. local y = minY
  47. local dy = yDiff / xDiff
  48. for x=minX,maxX do
  49. drawPixelInternal( target, x, math.floor( y + 0.5 ) )
  50. y = y + dy
  51. end
  52. else
  53. local x = minX
  54. local dx = xDiff / yDiff
  55. if maxY >= minY then
  56. for y=minY,maxY do
  57. drawPixelInternal( target, math.floor( x + 0.5 ), y )
  58. x = x + dx
  59. end
  60. else
  61. for y=minY,maxY,-1 do
  62. drawPixelInternal( target, math.floor( x + 0.5 ), y )
  63. x = x - dx
  64. end
  65. end
  66. end
  67. end
  68.  
  69. local function drawRect(target, x1, y1, x2, y2, nColour)
  70. for i = 0, y2 - 1 do
  71. drawLine(target, x1, y1 + i, x1 + x2 - 1, y1 + i, nColour)
  72. end
  73. end
  74. -------------------------------------------------------------------------------------------
  75. ---End of custom drawing API
  76. -------------------------------------------------------------------------------------------
  77. local peripheralPool = {}
  78. local SELECTED_OBJECT = nil
  79. local backupPullEvent = nil
  80. -------------------------------------------------------------------------------------------
  81. ---PUBLIC GUI API
  82. -------------------------------------------------------------------------------------------
  83. function SET_SELECTED_OBJECT(OBJ)
  84. SELECTED_OBJECT = OBJ
  85. end
  86.  
  87. function CLEAR_SCREEN(color, target)
  88. if not target then target = term.native() end
  89. target.setBackgroundColor(color)
  90. target.clear()
  91. end
  92.  
  93. function NO_EXIT()
  94. os.pullEvent("GUI_USER_EXIT")
  95. cleanup(MainPanel)
  96. end
  97.  
  98. function EXIT()
  99. os.queueEvent("GUI_USER_EXIT")
  100. end
  101.  
  102. local function cleanup(object)
  103. for _, child in pairs(object._CHILDREN) do
  104. cleanup(child)
  105. child = nil
  106. end
  107. end
  108.  
  109. local function getPeripheralName(p)
  110. return peripheralPool[p]
  111. end
  112.  
  113. function connectPeripheral(name)
  114. local p = peripheral.wrap(name)
  115. peripheralPool[p] = name
  116. return p
  117. end
  118.  
  119. local function getTextLayoutPos(layout, text, x, y, width, height, px, py)
  120. if layout == "topleft" then
  121. return x, y
  122. elseif layout == "top" then
  123. local cx = x + math.floor( ( width - string.len(text) ) / 2)
  124. return cx, y
  125. elseif layout == "topright" then
  126. local cx = x + ( width - string.len(text) ) + 1
  127. return cx, y
  128. elseif layout == "center" then
  129. local cy = y + math.floor(height / 2)
  130. local cx = x + math.floor( ( width - string.len(text) ) / 2)
  131. return cx, cy
  132. elseif layout == "left" then
  133. local cy = y + math.floor(height / 2)
  134. return x, cy
  135. elseif layout == "right" then
  136. local cx = x +( width - string.len(text) ) + 1
  137. local cy = y + math.floor(height / 2)
  138. return cx, cy
  139. elseif layout == "bottomleft" then
  140. local cy = y + math.floor(height / 2) + 1
  141. return x, cy
  142. elseif layout == "bottom" then
  143. local cx = x + math.floor( ( width - string.len(text) ) / 2)
  144. local cy = y + math.floor(height / 2) + 1
  145. return cx, cy
  146. elseif layout == "bottomright" then
  147. local cx = x +( width - string.len(text) ) + 1
  148. local cy = y + math.floor(height / 2) + 1
  149. return cx, cy
  150. end
  151. end
  152.  
  153. local function inBounds(x, y, x1, y1, w, h)
  154. if ( ( x >= x1 and x <= ( x1 + w) ) and (y >= y1 and y <= ( y1 + h ) ) ) then
  155. return true
  156. end
  157. return false
  158. end
  159.  
  160. --Defaults for all objects
  161. local function getDefaults()
  162. local mt = {
  163. target = term.native(),
  164. x = 1,
  165. y = 1,
  166. dynX = 1,
  167. dynY = 1,
  168. width = 1,
  169. height = 1,
  170. enabled = true,
  171. visible = true,
  172. text = "",
  173. func = nil,
  174. text_pos = "center",
  175. color_text = colors.white,
  176. color_bg = colors.blue,
  177. color_used = colors.red,
  178. _PARENT = nil,
  179. _CHILDREN = {},
  180.  
  181. addPARENT = function(s, object)
  182. s._PARENT = object
  183. end,
  184.  
  185. addCHILD = function(s, object) end,
  186.  
  187. enable = function(s)
  188. s.enabled = true
  189. end,
  190.  
  191. disable = function(s)
  192. s.enabled = false
  193. end,
  194.  
  195. show = function(s)
  196. s.visible = true
  197. end,
  198.  
  199. showNDraw = function(s)
  200. s:show()
  201. s:draw()
  202. end,
  203.  
  204. showNDrawNEnable = function(s)
  205. s:showNDraw()
  206. s:enable()
  207. end,
  208.  
  209. hide = function(s)
  210. s.visible = false
  211. end,
  212.  
  213. hideNDisable = function(s)
  214. s:hide()
  215. s:disable()
  216. end,
  217.  
  218. showNEnable = function(s)
  219. s:showNDraw()
  220. s:enable()
  221. end,
  222.  
  223. setText = function(s, t)
  224. s.text = t
  225. s:draw()
  226. end,
  227.  
  228. move = function(s, x, y)
  229. s.x = x
  230. s.y = y
  231. s:_dynRefresh()
  232. end,
  233.  
  234. resize = function(s, w, h)
  235. s.width = w
  236. s.height = h
  237. end,
  238.  
  239. _dynRefresh = function(s)
  240. px, py = 1, 1
  241. if s._PARENT then
  242. px, py = s._PARENT.dynX, s._PARENT.dynY
  243. end
  244. s.dynX = s.x + px - 1
  245. s.dynY = s.y + py - 1
  246. end,
  247.  
  248. clickCheck = function(s) return false end,
  249. draw = function(s) end,
  250. eventReact = function(s, e) end,
  251.  
  252. used = function(s)
  253. if s.func then s:func() end
  254. end
  255.  
  256. }
  257. return {__index = mt}
  258. end
  259.  
  260. --Panel constructor
  261. function NewPanel(x, y, visible, enabled)
  262. local panel = {
  263. addCHILD = function(s, ...)
  264. local args = {...}
  265. for _, object in pairs(args) do
  266. table.insert(s._CHILDREN, object)
  267. object:addPARENT(s)
  268. end
  269. end,
  270.  
  271. draw = function(s)
  272. if not s.visible then return end
  273. s:_dynRefresh()
  274. for _, child in pairs(s._CHILDREN) do
  275. child:draw()
  276. end
  277. end
  278. }
  279. panel = setmetatable(panel, getDefaults())
  280.  
  281. panel.x = x
  282. panel.y = y
  283. panel.visible = visible
  284. panel.enabled = enabled
  285.  
  286. return panel
  287. end
  288.  
  289. --Button constructor
  290. function NewButton(target, x, y, width, height, text, func, color_bg, color_text, color_used)
  291. local button = {
  292. draw = function(s, color)
  293. if not s.visible then return end
  294. if not color then color = s.color_bg end
  295. local cursorX, cursorY = s.target.getCursorPos()
  296.  
  297. s:_dynRefresh()
  298.  
  299. drawRect(s.target, s.dynX, s.dynY, s.width, s.height, color)
  300.  
  301. local cx, cy = getTextLayoutPos(s.text_pos, s.text, s.dynX, s.dynY, s.width, s.height)
  302. s.target.setTextColor(s.color_text)
  303. s.target.setCursorPos(cx, cy)
  304. s.target.write(s.text)
  305.  
  306. s.target.setCursorPos(cursorX, cursorY)
  307. end,
  308.  
  309. clickCheck = function(s, t)
  310. if not s.enabled then return end
  311.  
  312. if t[1] == "monitor_touch" and t[2] ~= getPeripheralName(s.target)
  313. or s.target ~= term.native() and t[1] == "mouse_click" then
  314. return
  315. end
  316.  
  317. s:_dynRefresh()
  318.  
  319. if inBounds(t[3], t[4], s.dynX, s.dynY, s.width - 1, s.height - 1) then
  320. s:used()
  321. return true
  322. end
  323. return false
  324. end,
  325. }
  326. button = setmetatable(button, getDefaults())
  327.  
  328. button.target = target
  329. button.x = x
  330. button.y = y
  331. button.width = width
  332. button.height = height
  333. button.text = text
  334. button.func = func
  335. button.color_text = color_text
  336. button.color_bg = color_bg
  337. button.color_used = color_used
  338.  
  339. return button
  340. end
  341.  
  342. --CheckBox constructor
  343. function NewCheckBox(target, x, y, width, height, text, func, color_bg, color_text, color_used)
  344. local chbox = {
  345. check = false,
  346.  
  347. draw = function(s, color)
  348. if not s.visible then return end
  349. if not color then color = s.color_bg end
  350. local cursorX, cursorY = s.target.getCursorPos()
  351.  
  352. s:_dynRefresh()
  353.  
  354. drawRect(s.target, s.dynX, s.dynY, s.width, s.height, color)
  355.  
  356. local cx, cy = getTextLayoutPos(s.text_pos, "[ ]-" .. s.text, s.dynX, s.dynY, s.width, s.height)
  357. s.target.setTextColor(s.color_text)
  358. s.target.setCursorPos(cx, cy)
  359. s.target.write("["..( (s.check == true) and "X" or " ") .. "]-"..s.text)
  360.  
  361. s.target.setCursorPos(cursorX, cursorY)
  362. end,
  363.  
  364. clickCheck = function(s, t)
  365. if not s.enabled then return end
  366.  
  367. if t[1] == "monitor_touch" and t[2] ~= getPeripheralName(s.target)
  368. or s.target ~= term.native() and t[1] == "mouse_click" then
  369. return
  370. end
  371.  
  372. s:_dynRefresh()
  373.  
  374. if inBounds(t[3], t[4], s.dynX, s.dynY, s.width - 1, s.height - 1) then
  375. s:used()
  376. return true
  377. end
  378. return false
  379. end,
  380.  
  381. used = function(s)
  382. s.check = not s.check
  383. if s.func then s:func() end
  384. s:draw()
  385. end,
  386. }
  387. chbox = setmetatable(chbox, getDefaults())
  388.  
  389. chbox.target = target
  390. chbox.x = x
  391. chbox.y = y
  392. chbox.width = width
  393. chbox.height = height
  394. chbox.text = text
  395. chbox.func = func
  396. chbox.color_text = color_text
  397. chbox.color_bg = color_bg
  398. chbox.color_used = color_used
  399.  
  400. return chbox
  401. end
  402.  
  403. --Progress Bar constructor
  404. function NewProgressBar(target, x, y, width, height, color_bg, color_used)
  405. local pbar = {
  406. step = 0.01,
  407. progress = 0.0,
  408.  
  409. setProgress = function(s, np)
  410. s.progress = (np > 1) and 1 or np
  411. s:draw()
  412. end,
  413.  
  414. clear = function(s)
  415. s.progress = 0
  416. s:draw()
  417. end,
  418.  
  419. stepIt = function(s)
  420. s.progress = s.progress + s.step
  421. if s.progress > 1 then s.progress = 1 end
  422. s:draw()
  423. end,
  424.  
  425. draw = function(s)
  426. if not s.visible then return end
  427. local cursorX, cursorY = s.target.getCursorPos()
  428. s:_dynRefresh()
  429.  
  430. local pos = s.width * s.progress
  431. if pos < s.width then
  432. drawRect(s.target, s.dynX + pos, s.dynY, s.width - pos, s.height, s.color_bg)
  433. end
  434. if pos > 0 and pos ~= s.width then
  435. drawRect(s.target, s.dynX, s.dynY, pos+1, s.height, s.color_used)
  436. end
  437.  
  438. s.text = tostring( math.floor(s.progress * 100) ).."%"
  439.  
  440. local cx, cy = getTextLayoutPos(s.text_pos, s.text, s.dynX, s.dynY, s.width, s.height)
  441. s.target.setTextColor(s.color_text)
  442. s.target.setCursorPos(cx, cy)
  443.  
  444. if cx > s.dynX + pos then
  445. s.target.setBackgroundColor(s.color_bg)
  446. s.target.write(s.text)
  447. else
  448. s.target.write(string.sub(s.text, 1, math.floor(s.dynX + pos - cx + 1) ) )
  449. s.target.setBackgroundColor(s.color_bg)
  450. s.target.write(string.sub(s.text, math.floor(s.dynX + pos - cx + 2), #s.text))
  451. end
  452.  
  453. s.target.setCursorPos(cursorX, cursorY)
  454. end,
  455. }
  456. pbar = setmetatable(pbar, getDefaults())
  457. pbar.target = target
  458. pbar.x = x
  459. pbar.y = y
  460. pbar.width = width
  461. pbar.height = height
  462. pbar.color_bg = color_bg
  463. pbar.color_used = color_used
  464.  
  465. return pbar
  466. end
  467.  
  468. function NewTextLine(target, x, y, width, text, func, color_bg, color_text)
  469. local textline = {
  470. secure = false,
  471. _textpos = 1,
  472. _cursorpos = 1,
  473.  
  474. draw = function(s)
  475. if not s.visible then return end
  476. local cursorX, cursorY = s.target.getCursorPos()
  477.  
  478. s:_dynRefresh()
  479.  
  480. drawRect(s.target, s.dynX, s.dynY, s.width, 1, s.color_bg)
  481.  
  482. s.target.setTextColor(s.color_text)
  483. s.target.setCursorPos(s.dynX, s.dynY)
  484. local temp = string.sub(s.text, s._textpos, s._textpos + s.width)
  485. if s.secure then
  486. for i = 1, #temp do
  487. s.target.write("*")
  488. end
  489. else
  490. s.target.write(temp)
  491. end
  492.  
  493. s.target.setCursorPos(cursorX, cursorY)
  494. end,
  495.  
  496. clickCheck = function(s, t)
  497. if not s.enabled then return end
  498.  
  499. if t[1] == "monitor_touch" and t[2] ~= getPeripheralName(s.target)
  500. or s.target ~= term.native() and t[1] == "mouse_click" then
  501. return
  502. end
  503.  
  504. s:_dynRefresh()
  505.  
  506. if inBounds(t[3], t[4], s.dynX, s.dynY, s.width - 1, s.height - 1) then
  507. SELECTED_OBJECT = s
  508. return true
  509. end
  510. return false
  511. end,
  512.  
  513. eventReact = function(s, e)
  514. if not s.enabled then return end
  515. if e[1] == "key" then
  516. if e[2] == 28 then
  517. SELECTED_OBJECT = nil
  518. s:used()
  519. elseif e[2] == 14 then
  520. s.text = string.sub(s.text, 1, #s.text - 1)
  521. s._cursorpos = s._cursorpos - 1
  522.  
  523. if s._cursorpos <= s._textpos then
  524. s._textpos = s._textpos - 4
  525. end
  526. if s._textpos < 1 then
  527. s._textpos = 1
  528. end
  529. if s._cursorpos < 1 then
  530. s._cursorpos = 1
  531. end
  532.  
  533. s:draw()
  534. elseif e[2] == 203 then
  535. --left
  536. elseif e[2] == 205 then
  537. --right
  538. end
  539. elseif e[1] == "char" then
  540. s.text = s.text .. e[2] --testing
  541.  
  542. s._cursorpos = s._cursorpos + 1
  543.  
  544. if s._cursorpos > s._textpos + s.width - 1 then
  545. s._textpos = s._textpos + 1
  546. end
  547.  
  548. s:draw()
  549. end
  550. end,
  551. }
  552. textline = setmetatable(textline, getDefaults())
  553. textline.target = target
  554. textline.x = x
  555. textline.y = y
  556. textline.width = width
  557. textline.text = text
  558. textline.func = func
  559. textline.color_bg = color_bg
  560. textline.color_text = color_text
  561. return textline
  562. end
  563.  
  564. --TextArea constructor
  565. function NewTextArea(target, x, y, width, height, text, color_bg, color_text)
  566. local textarea = {
  567. draw = function(s)
  568. if not s.visible then return end
  569. local cursorX, cursorY = s.target.t()
  570.  
  571. s:_dynRefresh()
  572.  
  573. drawRect(s.target, s.dynX, s.dynY, s.width, s.height, s.color_bg)
  574.  
  575. local k = 0
  576. for i = 1, string.len(s.text), s.width do
  577. s.target.setCursorPos(s.dynX, s.dynY + k)
  578. k = k + 1
  579. s.target.setTextColor(s.color_text)
  580. s.target.write(string.sub(s.text, i, i + s.width - 1))
  581. end
  582.  
  583. s.target.setCursorPos(cursorX, cursorY)
  584. end,
  585.  
  586. clickCheck = function(s, t)
  587. if not s.enabled then return end
  588.  
  589. if t[1] == "monitor_touch" and t[2] ~= getPeripheralName(s.target)
  590. or s.target ~= term.native() and t[1] == "mouse_click" then
  591. return
  592. end
  593.  
  594. s:_dynRefresh()
  595.  
  596. if inBounds(t[3], t[4], s.dynX, s.dynY, s.width - 1, s.height - 1) then
  597. SELECTED_OBJECT = s
  598. return true
  599. end
  600. return false
  601. end,
  602.  
  603. eventReact = function(s, e)
  604. if not s.enabled then return end
  605. if e[1] == "key" then
  606. if e[2] == 28 then
  607. --testing
  608. elseif e[2] == 14 then
  609. s.text = string.sub(s.text, 1, #s.text - 1)
  610. s:draw()
  611. end
  612. elseif e[1] == "char" then
  613. s.text = s.text .. e[2] --testing
  614. s:draw()
  615. end
  616. end,
  617. }
  618. textarea = setmetatable(textarea, getDefaults())
  619. textarea.target = target
  620. textarea.x = x
  621. textarea.y = y
  622. textarea.width = width
  623. textarea.height = height
  624. textarea.text = text
  625. textarea.color_bg = color_bg
  626. textarea.color_text = color_text
  627. return textarea
  628. end
  629.  
  630. --Label constructor
  631. function NewLabel(target, x, y, text, color_bg, color_text)
  632. local label = {
  633. draw = function(s)
  634. if not s.visible then return end
  635. local cursorX, cursorY = s.target.getCursorPos()
  636.  
  637. s:_dynRefresh()
  638.  
  639. drawLine(s.target, s.dynX, s.dynY, s.dynX + string.len(s.text) - 1, s.dynY , s.color_bg)
  640. s.target.setTextColor(s.color_text)
  641. s.target.setCursorPos(s.dynX, s.dynY)
  642. s.target.write(s.text)
  643.  
  644. s.target.setCursorPos(cursorX, cursorY)
  645. end,
  646. }
  647. label = setmetatable(label, getDefaults())
  648. label.target = target
  649. label.x = x
  650. label.y = y
  651. label.text = text
  652. label.color_bg = color_bg
  653. label.color_text = color_text
  654. return label
  655. end
  656.  
  657. --click/touch handler
  658. local function exec(event, object)
  659. if not object.enabled then return end
  660. for _, child in pairs(object._CHILDREN) do
  661. exec(event, child)
  662. if child:clickCheck(event) then
  663. return true
  664. end
  665. end
  666. end
  667.  
  668. MainPanel = NewPanel()
  669.  
  670. --Event handler. Call this if overwrite os.pullEvent()
  671. function eventHandler(e)
  672. if e[1] == "mouse_click" or e[1] == "monitor_touch" then
  673. --Check if selected object or its children clicked
  674. if SELECTED_OBJECT then
  675. exec(e, SELECTED_OBJECT)
  676. end
  677. SELECTED_OBJECT = nil
  678. exec(e, MainPanel)
  679. elseif e[1] == "key" or e[1] == "char"then
  680. if SELECTED_OBJECT then
  681. SELECTED_OBJECT:eventReact(e)
  682. end
  683. end
  684. end
  685.  
  686. backupPullEvent = os.pullEvent
  687.  
  688. function os.pullEvent()
  689. local e = { os.pullEventRaw() }
  690. eventHandler(e)
  691. return e[1], e[2], e[3], e[4], e[5]
  692. end
Add Comment
Please, Sign In to add comment