Advertisement
tahg

gui

Feb 7th, 2014
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.52 KB | None | 0 0
  1. Object = {}
  2. Object_mt = { __index = Object }
  3.  
  4. function new (class, ...)
  5. return class:create(unpack(arg))
  6. end
  7.  
  8. function extends (baseClass)
  9. local new_class = {}
  10. local class_mt = { __index = new_class }
  11. baseClass = baseClass or Object
  12.  
  13. function new_class:create(...)
  14. local newinst = {}
  15. setmetatable(newinst, class_mt)
  16. self.__parent = parent
  17. self:__init(newinst, unpack(arg))
  18. return newinst
  19. end
  20.  
  21. function new_class.super()
  22. return baseClass
  23. end
  24.  
  25. if baseClass then
  26. setmetatable(new_class, { __index = baseClass })
  27. end
  28.  
  29. return new_class
  30. end
  31.  
  32. function Object:create(...)
  33. local new_inst = {}
  34. setmetatable( new_inst, Control_mt )
  35. self:__init(new_inst, unpack(arg))
  36. return new_inst
  37. end
  38.  
  39. function Object:__init(instance, ...)
  40. if self.super and self.super() then
  41. self.super():__init(instance)
  42. end
  43. if self.init then
  44. self.init(instance, unpack(arg))
  45. end
  46. end
  47.  
  48. Control = extends()
  49. Control.unique = 1
  50.  
  51. function Control:init()
  52. self:setPos(0, 0)
  53. self:setSize(0, 0)
  54. self:setVisible(true)
  55. self:setName("Control_"..Control.unique)
  56. Control.unique = Control.unique + 1
  57. end
  58.  
  59. function Control:setPos(x, y)
  60. self.x = x
  61. self.y = y
  62. return self
  63. end
  64.  
  65. function Control:getPos()
  66. return self.x, self.y
  67. end
  68.  
  69. function Control:getAbsPos()
  70. local x, y = 0, 0
  71. if self.__parent then
  72. x, y = self.__parent:getAbsPos()
  73. end
  74. x = x + self.x
  75. y = y + self.y
  76. return x, y
  77. end
  78.  
  79. function Control:setSize(w, h)
  80. self.width = w
  81. self.height = h
  82. return self
  83. end
  84.  
  85. function Control:getSize()
  86. return self.width, self.height
  87. end
  88.  
  89. function Control:getMinSize()
  90. return 1, 1
  91. end
  92.  
  93. function Control:setName(name)
  94. self.name = name
  95. return self
  96. end
  97.  
  98. function Control:setFGColor(color)
  99. self.fgc = color
  100. return self
  101. end
  102.  
  103. function Control:setBGColor(color)
  104. self.bgc = color
  105. return self
  106. end
  107.  
  108. function Control:click(x, y)
  109. end
  110.  
  111. function Control:onClick()
  112. end
  113.  
  114. function Control:setVisible(visible)
  115. self.visible = visible
  116. return self
  117. end
  118.  
  119. function Control:isVisible()
  120. return self.visible
  121. end
  122.  
  123. function Control:draw()
  124. if not self:isVisible() then return nil end
  125. local device = self:getDevice()
  126. if device then
  127. local l, t = self:getAbsPos()
  128. local w, h = self:getSize()
  129. local r, b = l + w - 1, t + h - 1
  130. local dx, dy = device.getSize()
  131. print("Drawing control at ("..l..","..t..")")
  132. if l < 1 then l = 1 end
  133. if t < 1 then t = 1 end
  134. if r > dx then r = dx end
  135. if b > dy then b = dy end
  136. if self.bgc then
  137. if device.setBackgroundColor then
  138. device.setBackgroundColor(self.bgc)
  139. end
  140. for row = t, b do
  141. device.setCursorPos(l, row)
  142. for col = l, r do
  143. device.write(" ")
  144. end
  145. end
  146. end
  147. end
  148. return device
  149. end
  150.  
  151. function Control:getDevice()
  152. if self.__parent then
  153. return self.__parent:getDevice()
  154. else return nil
  155. end
  156. end
  157.  
  158. function Control:contains(x, y)
  159. return x >= self.x and x < self.x + self.width and
  160. y >= self.y and y < self.y + self.height
  161. end
  162.  
  163. Label = inheritsfrom(Control)
  164.  
  165. function Label:init()
  166. self:setAlign("center"):setVAlign(center):setText("")
  167. end
  168.  
  169. function Label:getMinSize()
  170. return #(self.text), 1
  171. end
  172.  
  173. function Label:setText(text)
  174. self.text = text
  175. return self
  176. end
  177.  
  178. function Label:setAlign(align)
  179. self.align = align
  180. return self
  181. end
  182.  
  183. function Label:setVAlign(align)
  184. self.valign = align
  185. return self
  186. end
  187.  
  188. function Label:draw()
  189. local device = Label.super().draw(self)
  190. if not device then return end
  191. -- print("drawing label "..self.name)
  192. local x, y = self:getAbsPos()
  193. local text = self.text
  194. local slackx = self.width - #text
  195. local slacky = self.height - 1
  196. if self.align == "center" then
  197. x = x + slackx / 2
  198. elseif self.align == "right" then
  199. x = x + slackx
  200. end
  201. if self.valign == "center" then
  202. y = y + slacky / 2
  203. elseif self.valign == "bottom" then
  204. y = y + slacky
  205. end
  206. -- print("Displaying text '"..text.."' at ("..x..", "..y..")")
  207. device.setCursorPos(x, y)
  208. device.setTextColor(self.fgc)
  209. device.write(text)
  210. return device
  211. end
  212.  
  213. Button = inheritsfrom(Label)
  214.  
  215. function Button:setActive(state)
  216. self.state = state
  217. end
  218.  
  219. function Button:setActiveColor(color)
  220. self.hlc = color
  221. end
  222.  
  223. function Button:setInactiveColor(color)
  224. self.iac = color
  225. end
  226.  
  227. function Button:update()
  228. self.bgc = self.state and hlc or iac
  229. self:draw()
  230. end
  231.  
  232. function Button:click()
  233. self:setActive(true)
  234. self:update()
  235. self:onClick()
  236. self:setActive(false)
  237. self:update()
  238. end
  239.  
  240. Container = inheritsfrom(Control)
  241.  
  242. function Container:clear()
  243. self.controls = {}
  244. self.controlsByName = {}
  245. end
  246.  
  247. function Container:init()
  248. self:clear()
  249. end
  250.  
  251. function Container:add(control)
  252. self.controls[#(self.controls)+1] = control
  253. -- print(control.name)
  254. self.controlsByName[control.name] = control
  255. control.__parent = self
  256. control.__idx = #(self.controls)
  257. end
  258.  
  259. function Container:find(name)
  260. return controlsByName[name]
  261. end
  262.  
  263. function Container:findIndex(control)
  264. if type(control) == "string" then
  265. control = self:find(control)
  266. end
  267. if control.__parent ~= self then return nil end
  268. if control.__idx and controls[control.__idx] == control then
  269. return control.__idx
  270. end
  271. for i = 1, #controls do
  272. if controls[i] == control then
  273. control.__idx = i
  274. return i
  275. end
  276. end
  277. return nil
  278. end
  279.  
  280. function Container:moveUp(control)
  281. idx = self:findIndex(control)
  282. if not idx or idx >= #controls then return nil end
  283. controls[idx] = controls[idx+1]
  284. controls[idx].__idx = idx
  285. controls[idx+1] = control
  286. control.__idx = idx+1
  287. end
  288.  
  289. function Container:moveDown(control)
  290. idx = self:findIndex(control)
  291. if not idx or idx <= 1 then return nil end
  292. controls[idx] = controls[idx-1]
  293. controls[idx]._idx = idx
  294. controls[idx-1] = control
  295. control.__idx = idx-1
  296. end
  297.  
  298. function Container:moveTop(control)
  299. while self:moveUp(control) do end
  300. end
  301.  
  302. function Container:moveBottom(control)
  303. while self:moveDown(control) do end
  304. end
  305.  
  306. function Container:addButton(name, text, func, param, x, y, w, h)
  307. b = Button:create()
  308. b.name = name
  309. b:setText(text)
  310. b:setPos(x, y)
  311. b:setSize(w, h)
  312. b:setAction(func, param)
  313. b:setActive(false)
  314. self:add(b)
  315. end
  316.  
  317. function Container:addLabel(name, text, x, y, w, h)
  318. l = Label:create()
  319. l.name = name
  320. l:setText(text)
  321. l:setPos(x, y)
  322. l:setSize(w, h)
  323. self:add(l)
  324. end
  325.  
  326. function Container:draw()
  327. local device = Container.super().draw(self)
  328. if not device then return end
  329. for k, v in ipairs(self.controls) do
  330. v:draw()
  331. end
  332. return device
  333. end
  334.  
  335. Screen = inheritsfrom(Container)
  336.  
  337. function Screen:init()
  338. self:setPos(1,1)
  339. end
  340.  
  341. function Screen:setDevice(device)
  342. self.device = device
  343. if device then self:setSize(device.getSize()) end
  344. return self
  345. end
  346.  
  347. function Screen:getDevice()
  348. return self.device
  349. end
  350.  
  351. function Screen:draw()
  352. if self.device then
  353. self.device.clear()
  354. return Screen.super().draw(self)
  355. end
  356. end
  357.  
  358. Scrollbar = inheritsfrom(Control)
  359.  
  360. function Scrollbar:init()
  361. self.thumb = Control:create()
  362. self.thumb.__parent = self
  363. self.pos = 0
  364. self.max = 0
  365. end
  366.  
  367. function Scrollbar:setBounds(min, max)
  368. self.pos = 0
  369. self.min = min
  370. self.max = max
  371. return self
  372. end
  373.  
  374. function Scrollbar:setProgress(value)
  375. if value >= self.min and value <= self.max then
  376. self.pos = value
  377. end
  378. return self
  379. end
  380.  
  381. function Scrollbar:getProgress()
  382. return self.pos
  383. end
  384.  
  385. function Scrollbar:setPercent(value)
  386. local range = self.max - self.min
  387. if range > 0 and value >= 0 and value <= 100 then
  388. self.pos = self.min + range * value
  389. end
  390. return self
  391. end
  392.  
  393. function Scrollbar:setType(value)
  394. self.type = value
  395. return self
  396. end
  397.  
  398. function Scrollbar:draw()
  399. device = Scrollbar.super().draw(self)
  400. if not device then return end
  401. if self.width >= 1 and self.height >= 1 then
  402. print("Drawing scrollbar at ("..self.x..","..self.y..")")
  403. print("Min "..self.min.." Max "..self.max)
  404. if self.max > self.min then
  405. if self.type == "horizontal" then
  406. self.thumb:setSize(1, self.height)
  407. self.thumb:setPos((self.pos - self.min) / (self.max - self.min) * (self.width-1), 0)
  408. else
  409. self.thumb:setSize(self.width, 1)
  410. self.thumb:setPos(0, (self.pos - self.min) / (self.max - self.min) * (self.height-1))
  411. end
  412. print(self.thumb.name)
  413. print(self.thumb:isVisible())
  414. self.thumb:setBGColor(colors.blue)
  415. local tx, ty = self.thumb:getAbsPos()
  416. print("Drawing thumb at ("..tx..","..ty..")")
  417.  
  418. self.thumb:draw()
  419. end
  420. end
  421. return device
  422. end
  423.  
  424. Grid = inheritsfrom(Container)
  425.  
  426. function Grid:init()
  427. self.hscroll = Scrollbar:create(self)
  428. :setFGColor(colors.gray)
  429. :setBGColor(colors.lightGray)
  430. :setType("horizontal")
  431. self.vscroll = Scrollbar:create(self)
  432. :setFGColor(colors.gray)
  433. :setBGColor(colors.lightGray)
  434. :setType("vertical")
  435. self.rows, self.cols = 0, 0
  436. end
  437. function Grid:setMargins(ml, mt, mr, mb)
  438. self.ml, self.mt, self.mr, self.mb = ml, mt, mr, mb
  439. return self
  440. end
  441.  
  442. function Grid:setHGap(gap)
  443. self.hgap = gap
  444. return self
  445. end
  446.  
  447. function Grid:setVGap(gap)
  448. self.vgap = gap
  449. return self
  450. end
  451.  
  452. function Grid:setRows(rows)
  453. self.rows = rows
  454. return self
  455. end
  456.  
  457. function Grid:setCols(cols)
  458. self.cols = cols
  459. return self
  460. end
  461.  
  462. --"horizontal": will lay out by columns
  463. --"vertical": will lay out by rows
  464. function Grid:setDirection(dir)
  465. self.dir = dir
  466. return self
  467. end
  468.  
  469. function Grid:doLayout()
  470. local minx, miny = 0, 0
  471. for k, v in ipairs(self.controls) do
  472. local w, h = v:getMinSize()
  473. if w > minx then minx = w end
  474. if h > miny then miny = h end
  475. end
  476. self.vcols = math.floor((self.width - self.ml - self.mr - 1 + self.hgap) / (minx + self.hgap))
  477. self.vrows = math.floor((self.height - self.mt - self.mb - 1 + self.vgap) / (miny + self.vgap))
  478. if self.rows < 1 and self.cols >= 1 then
  479. self.rows = math.ceil(#(self.controls) / self.cols)
  480. elseif self.cols < 1 and self.rows >=1 then
  481. self.cols = math.ceil(#(self.controls) / self.rows)
  482. else
  483. if self.dir == "vertical" then
  484. if self.cols < 1 then self.cols = self.vcols end
  485. self.rows = math.ceil(#(self.controls) / self.cols)
  486. else
  487. if self.rows < 1 then self.rows = self.vrows end
  488. self.cols = math.ceil(#(self.controls) / self.rows)
  489. end
  490. end
  491. if self.rows > self.vrows then
  492. self.vscroll:setBounds(0, self.rows - self.vrows)
  493. self.vscroll:setVisible(true)
  494. else
  495. self.vscroll:setBounds(0, 0)
  496. self.vscroll:setVisible(false)
  497. end
  498. if self.cols > self.vcols then
  499. self.hscroll:setBounds(0, self.cols - self.vcols)
  500. self.hscroll:setVisible(true)
  501. else
  502. self.hscroll:setBounds(0, 0)
  503. self.hscroll:setVisible(false)
  504. end
  505. self.vscroll:setPos(self.width - 1 - self.mr, self.mt)
  506. if self.hscroll:isVisible() then
  507. self.vscroll:setSize(1, self.height - self.mt - self.mb - 1)
  508. else self.vscroll:setSize(1, self.height - self.mt - self.mb)
  509. end
  510. self.hscroll:setPos(self.ml, self.height - 1 - self.mb)
  511. if self.vscroll:isVisible() then
  512. self.hscroll:setSize(self.width - self.ml - self.mr - 1, 1)
  513. else self.hscroll:setSize(self.width - self.ml - self.mr, 1)
  514. end
  515. self.cwidth = math.floor((self.width - self.ml - self.mr - 1 + self.hgap) / self.vcols) - self.hgap
  516. self.cheight = math.floor((self.height - self.mt - self.mb - 1 + self.vgap) / self.vrows) - self.vgap
  517. for k, v in ipairs(self.controls) do
  518. v:setSize(self.cwidth, self.cheight)
  519. end
  520. end
  521.  
  522. function Grid:draw()
  523. local voff = self.vscroll:getProgress()
  524. local hoff = self.hscroll:getProgress()
  525. if self.dir == "vertical" then
  526. local y = self.mt
  527. for row = 0, self.vrows - 1 do
  528. local x = self.ml
  529. for col = 0, self.vcols - 1 do
  530. local index = (row + voff) * self.cols + col + hoff + 1
  531. local control = self.controls[index]
  532. if control then
  533. control:setPos(x, y)
  534. control:draw()
  535. end
  536. x = x + self.cwidth + self.hgap
  537. end
  538. y = y + self.cheight + self.vgap
  539. end
  540. else
  541. local x = self.ml
  542. for col = 0, self.vcols - 1 do
  543. local y = self.mt
  544. for row = 0, self.vrows - 1 do
  545. local index = (col + hoff) * self.rows + row + voff + 1
  546. local control = self.controls[index]
  547. if control then
  548. control:setPos(x, y)
  549. control:draw()
  550. end
  551. y = y + self.cheight + self.vgap
  552. end
  553. x = x + self.cwidth + self.hgap
  554. end
  555. end
  556. self.vscroll:draw()
  557. self.hscroll:draw()
  558. end
  559.  
  560. function screen()
  561. local currColor
  562. for name,data in pairs(button) do
  563. local on = data["active"]
  564. if on == true then currColor = colors.lime else currColor = colors.red end
  565. fill(name, currColor, data)
  566. end
  567. end
  568.  
  569. function Button:toggle()
  570. self.state = not self.state
  571. screen()
  572. end
  573.  
  574. function flash(name)
  575. toggleButton(name)
  576. screen()
  577. sleep(0.15)
  578. toggleButton(name)
  579. screen()
  580. end
  581.  
  582. function checkxy(x, y)
  583. for name, data in pairs(button) do
  584. if y>=data["ymin"] and y <= data["ymax"] then
  585. if x>=data["xmin"] and x<= data["xmax"] then
  586. if data["param"] == "" then
  587. data["func"]()
  588. else
  589. data["func"](data["param"])
  590. end
  591. return true
  592. --data["active"] = not data["active"]
  593. --print(name)
  594. end
  595. end
  596. end
  597. return false
  598. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement