Advertisement
Guest User

Untitled

a guest
Aug 19th, 2019
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 34.14 KB | None | 0 0
  1. --Forms by Microeinstein
  2.  
  3. loadfile("std")()
  4.  
  5. __forms = {}
  6.  
  7. _running = false
  8. _dragging = false
  9. _texts = {
  10.     words = {[[[%w_]+%s*]], [[[^%w_]+]]},
  11.     dialogBtns = {"OK", "Cancel", "Yes", "No", "Retry", "Abort", "Ignore"}
  12. }
  13.  
  14. Bounds = {}
  15. Item = {}
  16. Panel = {}
  17. Label = {}
  18. Button = {}
  19. Image = {}
  20. TextBox = {}
  21. NumBox = {}
  22. CheckBox = {}
  23. Timer = {}
  24. Dialog = {}
  25. DragHandler = {}
  26.  
  27. mainPanel = nil
  28. shownDialog = nil
  29. _focused = nil
  30. _runningTimers = {}
  31. _keysTemp = {}
  32.  
  33. types = {
  34.     panel       = 1,
  35.     label       = 2,
  36.     button      = 3,
  37.     image       = 4,
  38.     textBox     = 5,
  39.     numBox      = 6,
  40.     checkBox    = 7
  41. }
  42. align = {
  43.     topLeft     = 0,
  44.     center      = 1,
  45.     bottomRight = 2
  46. }
  47. resolutions = {
  48.     computer    = { w = 51, h = 19 },
  49.     turtle      = { w = 39, h = 13 },
  50.     poket       = { w = 26, h = 20 }
  51. }
  52. events = {
  53.     click       = 1,
  54.     mouseUp     = 2,
  55.     drag        = 3,
  56.     scroll      = 4,
  57.     key         = 5,
  58.     text        = 6,
  59.     focusOn     = 7,
  60.     focusOff    = 8,
  61.     valueChange = 9
  62. }
  63. keyEvents = {
  64.     raw     = 0,
  65.     up      = 1,
  66.     press   = 2,
  67.     hold    = 3
  68. }
  69. valueTypes = {
  70.     text    = 1,
  71.     number  = 2,
  72.     checked = 3
  73. }
  74. buttonStyles = {
  75.     OK                  = 1,
  76.     OKCancel            = 2,
  77.     YesNo               = 3,
  78.     YesNoCancel         = 4,
  79.     RetryCancel         = 5,
  80.     AbortRetryIgnore    = 6
  81. }
  82. dialogResult = {
  83.     OK      = 1,
  84.     Cancel  = 2,
  85.     Yes     = 3,
  86.     No      = 4,
  87.     Retry   = 5,
  88.     Abort   = 6,
  89.     Ignore  = 7
  90. }
  91. _styleResult = {
  92.     {dialogResult.OK},
  93.     {dialogResult.OK, dialogResult.Cancel},
  94.     {dialogResult.Yes, dialogResult.No},
  95.     {dialogResult.Yes, dialogResult.No, dialogResult.Cancel},
  96.     {dialogResult.Retry, dialogResult.Cancel},
  97.     {dialogResult.Abort, dialogResult.Retry, dialogResult.Ignore},
  98. }
  99.  
  100. --Other
  101. function makeGrid(columns, rows)
  102.     local m = {}
  103.     columns = columns or {0}
  104.     rows = rows or {0}
  105.     local ix, iy, sx, sy = 1, 1, 0, 0
  106.     for col = 1, #columns do
  107.         m[col] = {}
  108.         iy = 1
  109.         sy = 0
  110.         sx = sx + columns[ix]
  111.         for row = 1, #rows do
  112.             sy = sy + rows[iy]
  113.             m[col][row] = {
  114.                 x = sx + (col - 1),
  115.                 y = sy + (row - 1)
  116.             }
  117.             iy = iy + 1
  118.         end
  119.         ix = ix + 1
  120.     end
  121.     return m
  122. end
  123. function typeName(t)
  124.     local pT = "generic item"
  125.     if t then
  126.         if     t == 0 then pT = "panel"
  127.         elseif t == 1 then pT = "label"
  128.         elseif t == 2 then pT = "button"
  129.         elseif t == 3 then pT = "image"
  130.         elseif t == 4 then pT = "textBox"
  131.         elseif t == 5 then pT = "numBox"
  132.         elseif t == 6 then pT = "checkBox"
  133.         end
  134.     end
  135.     return pT
  136. end
  137. function keyIsDown(key)
  138.     return _keysTemp[key] ~= nil
  139. end
  140. function _dragHandler(self, event, ...)
  141.     if event == events.click then
  142.         local mB, x, y, diffx, diffy = unpack(arg)
  143.         if not touch then
  144.             self._to._oldX = x
  145.             self._to._oldY = y
  146.         end
  147.        
  148.     elseif event == events.drag then
  149.         local mB, x, y, diffx, diffy = unpack(arg)
  150.         _dragging = true
  151.         self._to.x = self._to.x + (x - self._to._oldX)
  152.         self._to.y = self._to.y + (y - self._to._oldY)
  153.         self._to._oldX = x
  154.         self._to._oldY = y
  155.         refresh()
  156.    
  157.     elseif event == events.mouseUp then
  158.         _dragging = false
  159.         refresh()
  160.        
  161.     end
  162. end
  163. function attachDragHandler(from, to)
  164.     from._to = to
  165.     from._dragHandler = _dragHandler
  166. end
  167.  
  168. --Bounds
  169. function Bounds.x1(self)
  170.     local r = self.bind.x
  171.     if self.bind.parent then
  172.         r = self.bind.parent.bounds:x1() + r
  173.     end
  174.     return r
  175. end
  176. function Bounds.y1(self)
  177.     local r = self.bind.y
  178.     if self.bind.parent then
  179.         r = self.bind.parent.bounds:y1() + r
  180.     end
  181.     return r
  182. end
  183. function Bounds.x2(self)
  184.     local r = self:x1() + self.bind.width - 1
  185.     if self.bind.parent then
  186.         r = math.min(self.bind.parent.bounds:x2(), r)
  187.     end
  188.     return r
  189. end
  190. function Bounds.y2(self)
  191.     local r = self:y1() + self.bind.height - 1
  192.     if self.bind.parent then
  193.         r = math.min(self.bind.parent.bounds:y2(), r)
  194.     end
  195.     return r
  196. end
  197. function Bounds.rect(self)
  198.     return self:x1(), self:y1(), self:x2(), self:y2()
  199. end
  200. function Bounds.inside(self, x, y)
  201.     return (x >= self:x1() and x <= self:x2()) and (y >= self:y1() and y <= self:y2())
  202. end
  203. function Bounds.new(item)
  204.     local b = {}
  205.     b.x1 = Bounds.x1
  206.     b.y1 = Bounds.y1
  207.     b.x2 = Bounds.x2
  208.     b.y2 = Bounds.y2
  209.     b.rect = Bounds.rect
  210.     b.inside = Bounds.inside
  211.     b.bind = item or {}
  212.     return b
  213. end
  214.  
  215. --Item
  216. function Item.foreground(self)
  217.     if not self.enabled then
  218.         return colors.black
  219.     elseif self._foreground then
  220.         return self._foreground
  221.     elseif self.parent then
  222.         return self.parent:foreground()
  223.     else
  224.         return colors.white
  225.     end
  226. end
  227. function Item.background(self)
  228.     if not self.enabled then
  229.         return colors.gray
  230.     elseif self._background then
  231.         return self._background
  232.     elseif self.parent then
  233.         return self.parent:background()
  234.     else
  235.         return colors.black
  236.     end
  237. end
  238. function Item.isEnabled(self)
  239.     if not self.parent then
  240.         return self.enabled
  241.     else
  242.         return self.enabled and self.parent:isEnabled()
  243.     end
  244. end
  245. function Item.isVisible(self)
  246.     if not self.parent then
  247.         return self.visible
  248.     else
  249.         return self.visible and self.parent:isVisible()
  250.     end
  251. end
  252. function Item.isInverted(self)
  253.     if not self.parent then
  254.         return self._inverted
  255.     else
  256.         return self._inverted ~= self.parent:isInverted()
  257.     end
  258. end
  259. function Item.txtFix(self)
  260.     self.tLines = self.tLines or {}
  261.     local r = true
  262.     for l, txt in pairs(self.tLines) do
  263.         if string.contains(txt, "\n") then
  264.             r = true
  265.             for i, part in pairs(string.split(txt, "\n")) do
  266.                 if r then
  267.                     self.tLines[l] = part
  268.                     r = false
  269.                 else
  270.                     table.insert(self.tLines, l + i - 1, part)
  271.                 end
  272.             end
  273.         end
  274.     end
  275. end
  276. --[[function Item.txtLX(self)
  277.     local m = -1
  278.     for i, l in pairs(self.tLines) do
  279.         if m == -1 then
  280.             m = #l
  281.         else
  282.             m = math.max(m, #l)
  283.         end
  284.     end
  285.     return m
  286. end
  287. function Item.txtLY(self)
  288.     return #self.tLines
  289. end]]
  290. function Item.txtX(self, text)
  291.     local r = 0
  292.     if self._type == types.textBox then
  293.         self.alignX = align.topLeft
  294.     end
  295.     if not self.alignX or self.alignX == align.center then
  296.         r = math.max(math.center(self.bounds:x1(), self.bounds:x2(), #text - 0.5), self.bounds:x1())
  297.     elseif self.alignX == align.topLeft then
  298.         r = self.bounds:x1()
  299.     elseif self.alignX == align.bottomRight then
  300.         r = self.bounds:x2() - #text + 1
  301.     end
  302.     return r
  303. end
  304. function Item.txtY(self, lineNumber)
  305.     local r = 0
  306.     if self._type == types.textBox and self.multiLine then
  307.         self.alignY = align.topLeft
  308.     end
  309.     if not self.alignY or self.alignY == align.center then
  310.         r = math.center(self.bounds:y1(), self.bounds:y2(), #self.tLines - 1)
  311.     elseif self.alignY == align.topLeft then
  312.         r = self.bounds:y1()
  313.     elseif self.alignY == align.bottomRight then
  314.         r = self.bounds:y2() - #self.tLines + 1
  315.     end
  316.     return r + lineNumber - 1
  317. end
  318. function Item.paint(self)
  319.     if not (_running and self:isVisible()) then
  320.         return
  321.     end
  322.    
  323.     --Values
  324.     local x1, y1, x2, y2 = self.bounds:rect()
  325.     local fg, bg = self:foreground(), self:background()
  326.     if self:isInverted() then
  327.         local tbg = bg
  328.         bg = fg
  329.         fg = tbg
  330.     end
  331.    
  332.     --Paint background and borders
  333.     if term.isColor() then
  334.         if not _dragging then
  335.             paintutils.drawFilledBox(x1, y1, x2, y2, bg)
  336.             if self.image then
  337.                 paintutils.drawImage(self.image, x1, y1)
  338.             end
  339.             if self.border then
  340.                 paintutils.drawBox(x1 - 1, y1 - 1, x2 + 1, y2 + 1, self.border)
  341.             elseif self.shadow then
  342.                 paintutils.drawLine(x2 + 1, y1 + 1, x2 + 1, y2, self.shadow)
  343.                 paintutils.drawLine(x1 + 1, y2 + 1, x2 + 1, y2 + 1, self.shadow)
  344.             end
  345.         else
  346.             if self.shadow then
  347.                 paintutils.drawBox(x1 + 1, y1 + 1, x2 + 1, y2 + 1, self.shadow)
  348.             end
  349.             paintutils.drawBox(x1, y1, x2, y2, bg)
  350.         end
  351.     end
  352.    
  353.     --Write text
  354.     if not _dragging and self.tLines and #self.tLines > 0 then
  355.         local vX, vY = self._vX or 0, self._vY or 0
  356.         if term.isColor() then
  357.             term.setTextColor(fg)
  358.             term.setBackgroundColor(bg)
  359.         end
  360.        
  361.         for i, l in pairs(self.tLines) do
  362.             local txtX, txtY = self:txtX(l), self:txtY(i) - vY
  363.             if txtY >= y1 and txtY <= y2 then
  364.                 term.setCursorPos(txtX, txtY)
  365.                 term.write(l:sub(vX + 1, vX + self.width))
  366.             end
  367.         end
  368.     end
  369.    
  370.     --Paint content
  371.     if not _dragging and self.items then
  372.         for id, it in pairs(table.reverse(self.items, true)) do
  373.             it:paint()
  374.         end
  375.     end
  376. end
  377. function Item.getText(self)
  378.     local txt = ""
  379.     if self.tLines then
  380.         local l = #self.tLines
  381.         for i = 1, l do
  382.             txt = txt .. self.tLines[i]
  383.             if i < l then
  384.                 txt = txt .. "\n"
  385.             end
  386.         end
  387.     end
  388.     return txt
  389. end
  390. function Item.setText(self, text)
  391.     if type(text) == "table" then
  392.         self.tLines = {}
  393.         for i, l in pairs(text) do
  394.             table.insert(self.tLines, l)
  395.         end
  396.     else
  397.         self.tLines = {(text or "") .. ""}
  398.     end
  399.     self:txtFix()
  400.     if self.caretMove then
  401.         self:caretMove()
  402.     end
  403.     self:paint()
  404.     if _running then
  405.         self:_valueChange(valueTypes.text)
  406.     end
  407. end
  408.  
  409. --Events
  410. function Item._click(self, mB, x, y, diffx, diffy)
  411.     if not self.enabled then
  412.         return
  413.     end
  414.    
  415.     diffx = (diffx or x) - self.x
  416.     diffy = (diffy or y) - self.y
  417.    
  418.     if self._dragHandler then
  419.         self:_dragHandler(events.click, mB, x, y, diffx, diffy)
  420.     end
  421.     if self._eventHandler then
  422.         if self:_eventHandler(events.click, mB, x, y, diffx, diffy) then
  423.             return
  424.         end
  425.     end
  426.     if _focused ~= nil and _focused ~= self then
  427.         _focused:_focusOff()
  428.     end
  429.     self:_focusOn()
  430.     if self.eClick then
  431.         for k, e in pairs(self.eClick) do
  432.             e(self, mB, diffx, diffy)
  433.         end
  434.     end
  435. end
  436. function Item._mouseUp(self, mB, x, y, diffx, diffy)
  437.     if not self:isEnabled() then
  438.         return
  439.     end
  440.    
  441.     diffx = (diffx or x) - self.x
  442.     diffy = (diffy or y) - self.y
  443.    
  444.     if self._dragHandler then
  445.         self:_dragHandler(events.mouseUp, mB, x, y, diffx, diffy)
  446.     end
  447.     if self._eventHandler then
  448.         if self:_eventHandler(events.mouseUp, mB, x, y, diffx, diffy) then
  449.             return
  450.         end
  451.     end
  452.     if self.bounds:inside(x, y) and self.eMouseUp then
  453.         for k, e in pairs(self.eMouseUp) do
  454.             e(self, mB, x, y, diffx, diffy)
  455.         end
  456.     end
  457. end
  458. function Item._drag(self, mB, x, y, diffx, diffy)
  459.     if not self:isEnabled() then
  460.         return
  461.     end
  462.    
  463.     diffx = (diffx or x) - self.x
  464.     diffy = (diffy or y) - self.y
  465.    
  466.     if self._dragHandler then
  467.         self:_dragHandler(events.drag, mB, x, y, diffx, diffy)
  468.     end
  469.     if self._eventHandler then
  470.         self:_eventHandler(events.drag, mB, x, y, diffx, diffy)
  471.     end
  472.     if self.eDrag then
  473.         for k, e in pairs(self.eDrag) do
  474.             e(self, mB, diffx, diffy)
  475.         end
  476.     end
  477. end
  478. function Item._scroll(self, dir, x, y, diffx, diffy)
  479.     if not self:isEnabled() then
  480.         return
  481.     end
  482.    
  483.     diffx = (diffx or x) - self.x
  484.     diffy = (diffy or y) - self.y
  485.    
  486.     if self._eventHandler then
  487.         self:_eventHandler(events.scroll, dir, x, y, diffx, diffy)
  488.     end
  489.     if self.eScroll then
  490.         for k, e in pairs(self.eScroll) do
  491.             e(self, dir, diffx, diffy)
  492.         end
  493.     end
  494. end
  495. function Item._key(self, key, state)
  496.     if not self:isEnabled() then
  497.         return
  498.     end
  499.    
  500.     if self._eventHandler then
  501.         self:_eventHandler(events.key, key, state)
  502.     end
  503.     if self.eKey then
  504.         for k, e in pairs(self.eKey) do
  505.             e(self, key, state)
  506.         end
  507.     end
  508. end
  509. function Item._text(self, text, paste)
  510.     if not self:isEnabled() then
  511.         return
  512.     end
  513.    
  514.     if self._eventHandler then
  515.         self:_eventHandler(events.text, text, paste)
  516.     end
  517.     if self.eText then
  518.         for k, e in pairs(self.eText) do
  519.             e(self, text, paste)
  520.         end
  521.     end
  522. end
  523. function Item._focusOn(self)
  524.     if not self:isEnabled() then
  525.         return
  526.     end
  527.    
  528.     _focused = self
  529.     if self._eventHandler then
  530.         self:_eventHandler(events.focusOn)
  531.     end
  532.     if self.eFocusOn then
  533.         for k, e in pairs(self.eFocusOn) do
  534.             e(self)
  535.         end
  536.     end
  537. end
  538. function Item._focusOff(self)
  539.     if not self:isEnabled() then
  540.         return
  541.     end
  542.    
  543.     _focused = nil
  544.     if self._eventHandler then
  545.         self:_eventHandler(events.focusOff)
  546.     end
  547.     if self.eFocusOff then
  548.         for k, e in pairs(self.eFocusOff) do
  549.             e(self)
  550.         end
  551.     end
  552. end
  553. function Item._valueChange(self, vtype)
  554.     if not self:isEnabled() then
  555.         return
  556.     end
  557.     if self.eValueChange then
  558.         for k, e in pairs(self.eValueChange) do
  559.             e(self, vtype)
  560.         end
  561.     end
  562. end
  563. function Item.uniEvent(self)
  564.     self.eClick         = self.eClick or {}
  565.     self.eMouseUp       = self.eMouseUp or {}
  566.     self.eDrag          = self.eDrag or {}
  567.     self.eScroll        = self.eScroll or {}
  568.     self.eKey           = self.eKey or {}
  569.     self.eText          = self.eText or {}
  570.     self.eFocusOn       = self.eFocusOn or {}
  571.     self.eFocusOff      = self.eFocusOff or {}
  572.     self.eValueChange   = self.eValueChange or {}
  573. end
  574. function Item.remEvent(self, eType, event)
  575.     self:uniEvent()
  576.     if eType ~= nil and event ~= nil then
  577.         if      eType == events.click       then table.remove(self.eClick, event)
  578.         elseif  eType == events.mouseUp     then table.remove(self.eMouseUp, event)
  579.         elseif  eType == events.drag        then table.remove(self.eDrag, event)
  580.         elseif  eType == events.scroll      then table.remove(self.eScroll, event)
  581.         elseif  eType == events.key         then table.remove(self.eKey, event)
  582.         elseif  eType == events.text        then table.remove(self.eText, event)
  583.         elseif  eType == events.focusOn     then table.remove(self.eFocusOn, event)
  584.         elseif  eType == events.focusOff    then table.remove(self.eFocusOff, event)
  585.         elseif  eType == events.valueChange then table.remove(self.eValueChange, event)
  586.         end
  587.     end
  588. end
  589. function Item.addEvent(self, eType, event)
  590.     self:uniEvent()
  591.     if eType ~= nil and event ~= nil then
  592.         if      eType == events.click       then table.insert(self.eClick, event)
  593.         elseif  eType == events.mouseUp     then table.insert(self.eMouseUp, event)
  594.         elseif  eType == events.drag        then table.insert(self.eDrag, event)
  595.         elseif  eType == events.scroll      then table.insert(self.eScroll, event)
  596.         elseif  eType == events.key         then table.insert(self.eKey, event)
  597.         elseif  eType == events.text        then table.insert(self.eText, event)
  598.         elseif  eType == events.focusOn     then table.insert(self.eFocusOn, event)
  599.         elseif  eType == events.focusOff    then table.insert(self.eFocusOff, event)
  600.         elseif  eType == events.valueChange then table.insert(self.eValueChange, event)
  601.         end
  602.     end
  603. end
  604. function Item.new(x, y, text, w, h, fg, bg, border, _type, enabled)
  605.     --print("New ", typeName(_type))
  606.     --os.sleep(0.025)
  607.    
  608.     local i = {}
  609.     i.bounds = Bounds.new(i)
  610.     i.foreground = Item.foreground
  611.     i.background = Item.background
  612.     i.isEnabled = Item.isEnabled
  613.     i.isVisible = Item.isVisible
  614.     i.isInverted = Item.isInverted
  615.     i.txtFix = Item.txtFix
  616.     --i.txtLX = Item.txtLX
  617.     --i.txtLY = Item.txtLY
  618.     i.txtX = Item.txtX
  619.     i.txtY = Item.txtY
  620.     i.paint = Item.paint
  621.     i.getText = Item.getText
  622.     i.setText = Item.setText
  623.    
  624.     i.x = x
  625.     i.y = y
  626.     i:setText(text)
  627.     i.width = w or (text and string.lenX(text)) or 1
  628.     i.height = h or (text and string.lenY(text)) or 1
  629.     i._foreground = fg
  630.     i._background = bg
  631.     i.border = border
  632.     i.shadow = nil
  633.     i.enabled = enabled or true
  634.     i.visible = true
  635.     i._inverted = false
  636.     i._type = _type
  637.     i.alignX = nil
  638.     i.alignY = nil
  639.     i.image = nil
  640.    
  641.     i._eventHandler = nil
  642.     i._click = Item._click
  643.     i._mouseUp = Item._mouseUp
  644.     i._drag = Item._drag
  645.     i._scroll = Item._scroll
  646.     i._key = Item._key
  647.     i._text = Item._text
  648.     i._focusOn = Item._focusOn
  649.     i._focusOff = Item._focusOff
  650.     i._valueChange = Item._valueChange
  651.     i.uniEvent = Item.uniEvent
  652.     i.addEvent = Item.addEvent
  653.     i.remEvent = Item.remEvent
  654.     i.eClick = {}
  655.     i.eMouseUp = {}
  656.     i.eDrag = {}
  657.     i.eScroll = {}
  658.     i.eKey = {}
  659.     i.eText = {}
  660.     i.eFocusOn = {}
  661.     i.eFocusOff = {}
  662.     i.eValueChange = {}
  663.    
  664.     return i
  665. end
  666.  
  667. --Button
  668. function Button.eventHandler(self, event, ...)
  669.     if event == events.click then
  670.         local mB, x, y, diffx, diffy = unpack(arg)
  671.         self._inverted = true
  672.         self:paint()
  673.        
  674.     elseif event == events.mouseUp then
  675.         self._inverted = false
  676.         self:paint()
  677.    
  678.     end
  679. end
  680. function Button.new(x, y, text, w, h, fg, bg, eClick)
  681.     local b = Item.new(x, y, text, w, h, fg, bg, nil, types.button)
  682.     b._eventHandler = Button.eventHandler
  683.     b:addEvent(events.mouseUp, eClick)
  684.     return b
  685. end
  686.  
  687. --Panel
  688. function Panel.eventHandler(self, event, ...)
  689.     if event == events.click then
  690.         local mB, x, y, diffx, diffy = unpack(arg)
  691.         for n, i in pairs(self.items) do
  692.             if i.bounds:inside(x, y) then
  693.                 i:_click(mB, x, y, diffx, diffy)
  694.                 return true
  695.             end
  696.         end
  697.        
  698.     end
  699. end
  700. function Panel.addItem(self, it, name, noPaint)
  701.     local can = (it ~= nil)
  702.     if can then
  703.         if it.parent == nil or it.parent ~= self then
  704.             it.parent = self
  705.         end
  706.         if not self.items then
  707.             self.items = {}
  708.         end
  709.         it.name = name
  710.         table.insert(self.items, it)
  711.         if not noPaint then
  712.             refresh()
  713.         end
  714.     end
  715.     return can
  716. end
  717. function Panel.addItems(self, items)
  718.     for k, i in pairs(items) do
  719.         self:addItem(i, k, true)
  720.     end
  721.     refresh()
  722. end
  723. function Panel.remItem(self, name)
  724.     local is = self.items and self.items[name]
  725.     if is then
  726.         table.remove(self.items, name)
  727.         refresh()
  728.     end
  729.     return is
  730. end
  731. function Panel.addControlBar(self, title, canClose, canDrag)
  732.     local t, c;
  733.    
  734.     t = Label.new(0, 0, title, self.width - 3, 1, colors.white, colors.blue)
  735.     if canClose then
  736.         c = Button.new(self.width - 3, 0, "x", 3, 1, colors.white, colors.red,
  737.             function()
  738.                 if self.parent then
  739.                     self.parent:remItem(self.name)
  740.                 else
  741.                     stop()
  742.                 end
  743.             end
  744.         )
  745.     end
  746.     if canDrag then
  747.         attachDragHandler(t, self)
  748.     end
  749.    
  750.     self.controlBox = {t, c}
  751.     self:addItems(self.controlBox)
  752.    
  753.     return t, c;
  754. end
  755. function Panel.new(x, y, w, h, fg, bg, border)
  756.     local p = Item.new(x, y, nil, w, h, fg, bg, border, types.panel)
  757.     p._eventHandler = Panel.eventHandler
  758.     p.items = {}
  759.     p.addItem = Panel.addItem
  760.     p.addItems = Panel.addItems
  761.     p.remItem = Panel.remItem
  762.     p.addControlBar = Panel.addControlBar
  763.     return p
  764. end
  765.  
  766. --TextBox
  767. function TextBox.eventHandler(self, event, ...)
  768.     if event == events.key then
  769.         local key, state = unpack(arg)
  770.         self:handleKey(key, state)
  771.        
  772.     elseif event == events.click then
  773.         local mB, x, y, diffx, diffy = unpack(arg)
  774.         self:caretMove(diffx, diffy, true)
  775.        
  776.     elseif event == events.scroll then
  777.         local dir, x, y, diffx, diffy = unpack(arg)
  778.         self._vY = self._vY + dir
  779.         self:caretMove()
  780.        
  781.     elseif event == events.text then
  782.         local text, paste = unpack(arg)
  783.         self:addText(text, paste)
  784.        
  785.     elseif event == events.focusOn then
  786.         self:caretUpdate()
  787.        
  788.     elseif event == events.focusOff then
  789.         term.setCursorBlink(false)
  790.        
  791.     end
  792. end
  793. function TextBox.handleKey(self, key, state)
  794.     local p1, p2, l1, l2, words
  795.     if state == keyEvents.raw then
  796.         if key == keys.backspace then
  797.             if self._cX > 0 then
  798.                 p1, p2 = string.split(self:line(), self._cX)
  799.                 if keyIsDown(keys.leftCtrl) or keyIsDown(keys.rightCtrl) then
  800.                     words = string.multimatch(p1, unpack(_texts.words))[1]
  801.                     self:line(0, table.concat(words, "", 1, #words - 1) .. p2)
  802.                     self:caretMove(-(#(words[#words])))
  803.                 else
  804.                     self:line(0, p1:sub(1, #p1 - 1) .. p2)
  805.                     self:caretMove(-1)
  806.                 end
  807.             elseif self._cY > 0 then
  808.                 l1, l2 = self:line(-1), self:line()
  809.                 self:line(-1, l1 .. l2)
  810.                 table.remove(self.tLines, self._cY + 1)
  811.                 self:caretMove(-#l2 - 1)
  812.             end
  813.            
  814.         elseif key == keys.delete then
  815.             if self._cX < #(self:line()) then
  816.                 p1, p2 = string.split(self:line(), self._cX)
  817.                 if keyIsDown(keys.leftCtrl) or keyIsDown(keys.rightCtrl) then
  818.                     words = string.multimatch(p2, unpack(_texts.words))[1]
  819.                     self:line(0, p1 .. table.concat(words, "", 2))
  820.                 else
  821.                     self:line(0, p1 .. p2:sub(2, #p2))
  822.                 end
  823.                 self:caretMove()
  824.             elseif self._cY < #self.tLines then
  825.                 l1, l2 = self:line(), self:line(1)
  826.                 self:line(0, l1 .. l2)
  827.                 table.remove(self.tLines, self._cY + 2)
  828.                 self:caretMove()
  829.             end
  830.            
  831.         elseif key == keys.tab then
  832.             self:addText("  ")
  833.            
  834.         elseif key == keys.enter then
  835.             local initSpace = string.match(self:line(), [[%s+]]) or ""
  836.             self:addText("\n"..initSpace)
  837.            
  838.         elseif key == keys.home then
  839.             self:caretMove(-self._cX)
  840.            
  841.         elseif key == keys["end"] then
  842.             self:caretMove(#(self:line()) - self._cX)
  843.            
  844.         elseif key == keys.pageUp then
  845.             self:caretMove(0, -self.height)
  846.            
  847.         elseif key == keys.pageDown then
  848.             self:caretMove(0, self.height)
  849.            
  850.         elseif key == keys.up then
  851.             if keyIsDown(keys.leftAlt) or keyIsDown(keys.rightAlt) then
  852.                 if self._cY > 0 then
  853.                     local l, lp = self:line(), self:line(-1)
  854.                     self:line(-1, l)
  855.                     self:line(0, lp)
  856.                     self:caretMove(0, -1, false, true)
  857.                 end
  858.             else
  859.                 self:caretMove(0, -1)
  860.             end
  861.            
  862.         elseif key == keys.down then
  863.             if keyIsDown(keys.leftAlt) or keyIsDown(keys.rightAlt) then
  864.                 if self._cY < #self.tLines - 1 then
  865.                     local l, ln = self:line(), self:line(1)
  866.                     self:line(1, l)
  867.                     self:line(0, ln)
  868.                     self:caretMove(0, 1, false, true)
  869.                 end
  870.             else
  871.                 self:caretMove(0, 1)
  872.             end
  873.            
  874.         elseif key == keys.left then
  875.             if keyIsDown(keys.leftCtrl) or keyIsDown(keys.rightCtrl) then
  876.                 p1, p2 = string.split(self:line(), self._cX)
  877.                 words = string.multimatch(p1, unpack(_texts.words))[1]
  878.             end
  879.             if words and #words > 0 then
  880.                 self:caretMove(-(#(words[#words])))
  881.             else
  882.                 self:caretMove(-1)
  883.             end
  884.            
  885.         elseif key == keys.right then
  886.             if keyIsDown(keys.leftCtrl) or keyIsDown(keys.rightCtrl) then
  887.                 p1, p2 = string.split(self:line(), self._cX)
  888.                 words = string.multimatch(p2, unpack(_texts.words))[1]
  889.             end
  890.             if words and #words > 0 then
  891.                 self:caretMove(#(words[1]))
  892.             else
  893.                 self:caretMove(1)
  894.             end
  895.            
  896.         end
  897.     end
  898. end
  899. function TextBox.caretPos(self)
  900.     return (self._cX - self._vX), (self._cY - self._vY)
  901. end
  902. function TextBox.caretFinal(self)
  903.     local cx, cy = self:caretPos()
  904.     return self.bounds:x1() + cx, self.bounds:y1() + cy
  905. end
  906. function TextBox.caretUpdate(self)
  907.     local fX, fY = self:caretFinal()
  908.     local ok = (_focused ~= nil
  909.             and _focused == self
  910.             and self:isEnabled()
  911.             and (self.width < 3 or self.bounds:inside(fX, fY)))
  912.     term.setCursorBlink(ok)
  913.     term.setCursorPos(fX, fY)
  914. end
  915. function TextBox.caretMove(self, diffX, diffY, fixed, uncheck)
  916.     diffX = diffX or 0
  917.     diffY = diffY or 0
  918.     local lns = #self.tLines
  919.    
  920.     --Move caret position
  921.     if not fixed then
  922.         if not uncheck then
  923.             self._cX = self._cX + diffX
  924.             if self._cX > #(self:line()) then
  925.                 if self._cY < lns - 1 then
  926.                     self._cX = self._cX - #(self:line()) - 1
  927.                     self._cY = self._cY + 1
  928.                 else
  929.                     self._cX = #(self:line())
  930.                 end
  931.             elseif self._cX < 0 then
  932.                 if self._cY > 0 then
  933.                     self._cX = #(self:line(-1)) + self._cX + 1
  934.                     self._cY = self._cY - 1
  935.                 else
  936.                     self._cX = 0
  937.                 end
  938.             end
  939.             self._cY = math.between(0, self._cY + diffY, lns - 1)
  940.             self._cX = math.between(0, self._cX, #(self:line()))
  941.         else
  942.             self._cY = math.between(0, self._cY + diffY, lns - 1)
  943.             self._cX = math.between(0, self._cX + diffX, #(self:line()))
  944.         end
  945.     else
  946.         self._cY = math.between(0, self._vY + diffY, lns - 1)
  947.         self._cX = math.between(0, self._vX + diffX, #(self:line()))
  948.     end
  949.    
  950.     --Move viewing position
  951.     local cX, cY = self:caretPos()
  952.     local fX, fY = self:caretFinal()
  953.     local x1, y1, x2, y2 = self.bounds:rect()
  954.    
  955.     if diffX ~= 0 then
  956.         if fX < x1 then
  957.             self._vX = self._vX - (x1 - fX)
  958.         elseif fX > x2 then
  959.             self._vX = self._vX + (fX - x2)
  960.         --elseif self._cX >= self.width - 1 and self._vX + self.width - 1 > table.len(self:line()) then
  961.         --  self._vX = math.max(0, self._vX - 1)
  962.         end
  963.     end
  964.     if diffY ~= 0 then
  965.         if fY < y1 then
  966.             self._vY = self._vY - (y1 - fY)
  967.         elseif fY > y2 then
  968.             self._vY = self._vY + (fY - y2)
  969.         --elseif self._cY >= self.height - 2 and self._vY + self.height > lns then
  970.         --  self._vY = math.max(0, self._vY - 1)
  971.         end
  972.     end
  973.     self._vX = math.between(0, self._vX, #(self:line()) - self.width + (self.width > 2 and 1 or 0))
  974.     self._vY = math.between(0, self._vY, lns - self.height)
  975.    
  976.     --term.log(false, self._vX, self._vY, self._cX, self._cY)
  977.    
  978.     self:paint()
  979.     self:caretUpdate()
  980. end
  981. function TextBox.addText(self, text, paste)
  982.     --LONG\nTEXT\nOVER\nMULTIPLE\nLINES
  983.     --Becouse CC doesn't allow multiline paste
  984.     if paste and self.parseNewLine then
  985.         text = string.replace(text, "\\n", "\n")
  986.     end
  987.     local chrz = string.chars(text)
  988.     for i, c in pairs(chrz) do
  989.         if c == "\n" then
  990.             self:addLine()
  991.         else
  992.             local p1, p2 = string.split(self:line(0), self._cX)
  993.             self:line(0, p1 .. c .. p2)
  994.             self:caretMove(1)
  995.         end
  996.     end
  997.     self:txtFix()
  998.     self:caretMove()
  999.     if _running then
  1000.         self:_valueChange(valueTypes.text)
  1001.     end
  1002. end
  1003. function TextBox.addLine(self)
  1004.     if self.multiLine then
  1005.         local p1, p2 = string.split(self:line(), self._cX)
  1006.         self:line(0, p1)
  1007.         table.insert(self.tLines, self._cY + 2, p2)
  1008.         self:caretMove(-#p1, 1)
  1009.         if _running then
  1010.             self:_valueChange(valueTypes.text)
  1011.         end
  1012.     end
  1013. end
  1014. function TextBox.line(self, delta, new)
  1015.     delta = delta or 0
  1016.     if new then
  1017.         self.tLines[self._cY + 1 + delta] = new
  1018.         return new
  1019.     else
  1020.         local l = self.tLines[self._cY + 1 + delta]
  1021.         if l then
  1022.             return l
  1023.         else
  1024.             return ""
  1025.         end
  1026.     end
  1027. end
  1028. function TextBox.new(x, y, text, w, h, fg, bg, multi)
  1029.     text = text or ""
  1030.    
  1031.     local t = Item.new(x, y, text, w, h, fg, bg, nil, types.textBox)
  1032.     t._vX = 0
  1033.     t._vY = 0
  1034.     t._cX = 0
  1035.     t._cY = 0
  1036.     t.multiLine = multi or string.contains(text, "\n")
  1037.     t.parseNewLine = true
  1038.    
  1039.     t._eventHandler = TextBox.eventHandler
  1040.     t.viewPosX = TextBox.viewPosX
  1041.     t.viewPosY = TextBox.viewPosY
  1042.     t.caretPos = TextBox.caretPos
  1043.     t.caretFinal = TextBox.caretFinal
  1044.     t.caretUpdate = TextBox.caretUpdate
  1045.     t.caretMove = TextBox.caretMove
  1046.     t.addText = TextBox.addText
  1047.     t.addLine = TextBox.addLine
  1048.     t.handleKey = TextBox.handleKey
  1049.     t.line = TextBox.line
  1050.     return t
  1051. end
  1052.  
  1053. --NumBox
  1054. function NumBox.eventHandler(self, event, ...)
  1055.     if event == events.key then
  1056.         local key, state = unpack(arg)
  1057.         self:handleKey(key, state)
  1058.        
  1059.     elseif event == events.scroll then
  1060.         local dir, x, y, diffx, diffy = unpack(arg)
  1061.         self:changeNum(self.step * -dir)
  1062.        
  1063.     elseif event == events.text then
  1064.         local text, paste = unpack(arg)
  1065.         if #(string.remChars(text, "0123456789")) > 0 then
  1066.             if text == "-" then
  1067.                 self:setNum(-self.num)
  1068.             elseif text == "+" then
  1069.                 self:setNum(math.abs(self.num))
  1070.             end
  1071.         else
  1072.             self:setNum(self.num..text)
  1073.         end
  1074.    
  1075.     elseif event == events.focusOn then
  1076.         self:caretUpdate()
  1077.         term.setCursorBlink(true)
  1078.        
  1079.     elseif event == events.focusOff then
  1080.         term.setCursorBlink(false)
  1081.        
  1082.     end
  1083. end
  1084. function NumBox.handleKey(self, key, state)
  1085.     if state == keyEvents.raw then
  1086.         if key == keys.up then
  1087.             self:changeNum(self.step)
  1088.            
  1089.         elseif key == keys.down then
  1090.             self:changeNum(-self.step)
  1091.            
  1092.         elseif key == keys.backspace then
  1093.             local s = self.num..""
  1094.             self:setNum(string.sub(s, 1, #s - 1))
  1095.            
  1096.         end
  1097.     end
  1098. end
  1099. function NumBox.changeNum(self, step)
  1100.     if keyIsDown(keys.leftCtrl) or keyIsDown(keys.rightCtrl) then
  1101.         step = step * 2
  1102.     end
  1103.     if keyIsDown(keys.leftShift) or keyIsDown(keys.rightShift) then
  1104.         step = step / 2
  1105.     end
  1106.     if self.noFloat then
  1107.         step = math.ceil(step)
  1108.     end
  1109.     self:setNum(self.num + step)
  1110. end
  1111. function NumBox.setNum(self, num)
  1112.     if type(num) == "string" then
  1113.         self.num = tonumber(num) or 0
  1114.     else
  1115.         self.num = num
  1116.     end
  1117.     self.num = math.between(self.nmin, self.num, self.nmax)
  1118.     self:setText(self.num.."")
  1119.     self:caretUpdate()
  1120.     if _running then
  1121.         self:_valueChange(valueTypes.number)
  1122.     end
  1123. end
  1124. function NumBox.caretUpdate(self)
  1125.     term.setCursorPos(math.min(self.bounds:x1() + #(self.num..""), self.bounds:x2()), self.bounds:y1())
  1126. end
  1127. function NumBox.new(x, y, num, nmin, nmax, step, noFloat, w, h, fg, bg)
  1128.     num  = num or 0
  1129.     nmin = nmin or 0
  1130.     nmax = nmax or 0
  1131.     step = step or 1
  1132.    
  1133.     local n = Item.new(x, y, num.."", w, h, fg, bg, nil, types.numBox)
  1134.     n.nmin = nmin
  1135.     n.nmax = nmax
  1136.     n.step = step or 1
  1137.     n.num = math.between(nmin, num, nmax)
  1138.     n.noFloat = noFloat
  1139.     n.alignX = align.topLeft
  1140.    
  1141.     n._eventHandler = NumBox.eventHandler
  1142.     n.handleKey = NumBox.handleKey
  1143.     n.changeNum = NumBox.changeNum
  1144.     n.setNum = NumBox.setNum
  1145.     n.caretUpdate = NumBox.caretUpdate
  1146.    
  1147.     return n
  1148. end
  1149.  
  1150. --CheckBox
  1151. function CheckBox.eventHandler(self, event, ...)
  1152.     if event == events.click then
  1153.         self:setChecked(not self.checked)
  1154.        
  1155.     end
  1156. end
  1157. function CheckBox.setChecked(self, state)
  1158.     self.checked = state
  1159.     self._foreground = state and self.foregroundT or self._background
  1160.     self:paint()
  1161.     if _running then
  1162.         self:_valueChange(valueTypes.checked)
  1163.     end
  1164. end
  1165. function CheckBox.new(x, y, checked, fg, bg)
  1166.     local c = Item.new(x, y, "#", 1, 1, checked and fg or bg, bg, nil, types.checkBox)
  1167.     c.foregroundT = fg
  1168.     c.checked = checked
  1169.    
  1170.     c._eventHandler = CheckBox.eventHandler
  1171.     c.setChecked = CheckBox.setChecked
  1172.    
  1173.     return c
  1174. end
  1175.  
  1176. --Timer
  1177. function Timer.start(self)
  1178.     self.enabled = true
  1179.     self.id = os.startTimer(self.tick)
  1180.     _runningTimers[self.id] = self
  1181. end
  1182. function Timer.stop(self)
  1183.     os.cancelTimer(self.id)
  1184.     self.enabled = false
  1185.     _runningTimers[self.id] = nil
  1186.     self.id = nil
  1187. end
  1188. function Timer.raise(self)
  1189.     os.cancelTimer(self.id)
  1190.     _runningTimers[self.id] = nil
  1191.     if self.enabled then
  1192.         self.id = os.startTimer(self.tick)
  1193.         _runningTimers[self.id] = self
  1194.         if self.action then
  1195.             self.action(unpack(self.params))
  1196.         end
  1197.     end
  1198. end
  1199. function Timer.new(sec, started, eTick, ...)
  1200.     local t = {}
  1201.     t.tick = sec
  1202.     t.enabled = false
  1203.     t.action = eTick
  1204.     t.params = arg
  1205.    
  1206.     t.start = Timer.start
  1207.     t.stop = Timer.stop
  1208.     t.raise = Timer.raise
  1209.    
  1210.     if started then
  1211.         t:start()
  1212.     end
  1213.     return t
  1214. end
  1215.  
  1216. --Dialog
  1217. function Dialog.show(self)
  1218.     if shownDialog == nil then
  1219.         shownDialog = self
  1220.         self.visible = true
  1221.         refresh()
  1222.     end
  1223. end
  1224. function Dialog.close(self, result)
  1225.     if shownDialog == self then
  1226.         shownDialog = nil
  1227.         self.visible = false
  1228.         refresh()
  1229.         if self.event then
  1230.             if self.txt then
  1231.                 self:event(result, self.txt:getText())
  1232.             else
  1233.                 self:event(result)
  1234.             end
  1235.         end
  1236.     end
  1237. end
  1238. function Dialog._click(self)
  1239.     self.dialog:close(self.result)
  1240. end
  1241. function Dialog.new(delegate, message, buttonStyle, isPrompt, title)
  1242.     if (not buttonStyle) or buttonStyle < 1 or buttonStyle > 6 then
  1243.         buttonStyle = buttonStyles.OK
  1244.     end
  1245.     message = message or ""
  1246.     title = title or ""
  1247.     isPrompt = isPrompt or false
  1248.    
  1249.     local d = Panel.new(0, 0, 8, 5, colors.black, colors.lightGray)
  1250.     d.shadow = colors.gray
  1251.     local dialogW
  1252.     local dialogH = 0
  1253.    
  1254.     local bar, _ = d:addControlBar(title, false, true)
  1255.     dialogH = math.max(dialogH, bar.y + bar.height)
  1256.     local msg = Label.new(1, dialogH + 1, message, nil, nil, colors.black)
  1257.     dialogH = math.max(dialogH, msg.y + msg.height)
  1258.     local txt
  1259.     if isPrompt then
  1260.         txt = TextBox.new(1, dialogH, "", math.max(8, msg.width), 1, colors.black, colors.white)
  1261.         dialogH = math.max(dialogH, txt.y + txt.height)
  1262.     end
  1263.     local pbtns = Panel.new(1, dialogH + 2, 1, 1)
  1264.     dialogH = math.max(dialogH, pbtns.y + pbtns.height)
  1265.    
  1266.     local btns = {}
  1267.     for _, dR in pairs(_styleResult[buttonStyle]) do
  1268.         local btxt = _texts.dialogBtns[dR]
  1269.         local x2 = (#btns > 0) and (btns[#btns].x + btns[#btns].width) or -1
  1270.         local btn = Button.new(x2 + 1, 0, btxt, math.min(#btxt + 2, 8), 1, colors.white, colors.brown, Dialog._click)
  1271.         btn.dialog = d
  1272.         btn.result = dR
  1273.         table.insert(btns, btn)
  1274.     end
  1275.     pbtns:addItems(btns)
  1276.     pbtns.width = btns[#btns].x + btns[#btns].width
  1277.    
  1278.     local dialogW = math.max(d.width, bar.width, msg.width + 2, isPrompt and txt.width + 2 or 0, pbtns.width + 2)
  1279.     bar.width = dialogW
  1280.     attachDragHandler(bar, d)
  1281.     if isPrompt then
  1282.         txt.width = dialogW - 2
  1283.     end
  1284.     pbtns.x = dialogW - pbtns.width - 1
  1285.     pbtns.y = dialogH - 2
  1286.     d.width = dialogW
  1287.     d.height = dialogH
  1288.     local tw, th = term.getSize()
  1289.     d.x = math.center(0, tw, d.width)
  1290.     d.y = math.center(0, th, d.height)
  1291.     d.visible = false
  1292.     d.event = delegate
  1293.     d.txt = txt
  1294.     d:addItems({bar, msg, txt, pbtns})
  1295.    
  1296.     d.show = Dialog.show
  1297.     d.close = Dialog.close
  1298.    
  1299.     return d
  1300. end
  1301.  
  1302. -- ...
  1303. function Label.new(x, y, text, w, h, fg, bg)
  1304.     local l = Item.new(x, y, text, w, h, fg, bg, nil, types.label)
  1305.     return l
  1306. end
  1307. function Image.new(x, y, image)
  1308.     local w, h = 0, 0
  1309.     if image ~= nil then
  1310.         for n, r in pairs(image) do
  1311.             w = w + 1
  1312.             local lh = 0
  1313.             for p, c in pairs(r) do
  1314.                 lh = lh + 1
  1315.             end
  1316.             h = math.max(h, lh)
  1317.         end
  1318.     end
  1319.    
  1320.     local i = Item.new(x, y, nil, w, h, nil, nil, nil, types.image)
  1321.     i.image = image
  1322.     return i
  1323. end
  1324.  
  1325. --Form
  1326. function init(fg, bg, size)
  1327.     print("Form Init")
  1328.     local tw, th = term.getSize()
  1329.     local w, h = 0, 0
  1330.     if not size then
  1331.         w, h = tw, th
  1332.     else
  1333.         w, h = size.w, size.h
  1334.     end
  1335.     mainPanel = Panel.new(math.center(1, tw, w), math.center(1, th, h), w, h, fg or colors.white, bg or colors.black)
  1336.     mainPanel.shadow = colors.gray
  1337. end
  1338. function click(mButton, x, y)
  1339.     if _dragging then
  1340.         return
  1341.     end
  1342.     if shownDialog then
  1343.         shownDialog:_click(mButton, x, y)
  1344.     else
  1345.         mainPanel:_click(mButton, x, y)
  1346.     end
  1347. end
  1348. function refresh()
  1349.     if _running then
  1350.         term.setBackgroundColor(colors.black)
  1351.         term.clear()
  1352.         mainPanel:paint()
  1353.         if shownDialog then
  1354.             shownDialog:paint()
  1355.         end
  1356.     end
  1357. end
  1358. function run()
  1359.     _running = true
  1360.     term.setCursorPos(1, 1)
  1361.     term.setCursorBlink(false)
  1362.     refresh()
  1363.     while true do
  1364.         local event, p1, p2, p3, p4, p5 = os.pullEvent()
  1365.         if event == "mouse_click" then
  1366.             --mButton, x, y
  1367.             click(p1, p2, p3)
  1368.         elseif event == "mouse_up" then
  1369.             --mButton, x, y
  1370.             if _focused then
  1371.                 _focused:_mouseUp(p1, p2, p3)
  1372.             end
  1373.         elseif event == "mouse_drag" then
  1374.             --mButton, x, y
  1375.             if _focused then
  1376.                 _focused:_drag(p1, p2, p3)
  1377.             end
  1378.         elseif event == "mouse_scroll" then
  1379.             -- +1 Down / -1 Up, x, y1
  1380.             if _focused then
  1381.                 _focused:_scroll(p1, p2, p3)
  1382.             end
  1383.         elseif event == "monitor_touch" then
  1384.             --mButton, x, y
  1385.             click(p1, p2, p3)
  1386.             os.sleep(0.05)
  1387.             if _focused then
  1388.                 _focused:_mouseUp(p1, p2, p3)
  1389.             end
  1390.         elseif event == "char" or event == "paste" then
  1391.             --p1 = letter / text
  1392.             if _focused then
  1393.                 _focused:_text(p1, event == "paste")
  1394.             end
  1395.         elseif event == "key" then
  1396.             --keyNumber, repeat
  1397.             if _keysTemp[p1] ~= nil and _keysTemp[p1] then
  1398.                 --if key is pressed and repeating
  1399.                 if p2 then
  1400.                     os.queueEvent("managed_key", keyNumber, keyEvents.hold)
  1401.                 end
  1402.             end
  1403.             _keysTemp[p1] = p2
  1404.             if _focused then
  1405.                 _focused:_key(p1, keyEvents.raw)
  1406.             end
  1407.         elseif event == "key_up" then
  1408.             --keyNumber
  1409.             if _keysTemp[p1] ~= nil and not _keysTemp[p1] then
  1410.                 --if key is pressed and released
  1411.                 os.queueEvent("managed_key", keyNumber, keyEvents.press)
  1412.             end
  1413.             _keysTemp[p1] = nil
  1414.             os.queueEvent("managed_key", keyNumber, keyEvents.up)
  1415.         elseif event == "managed_key" then
  1416.             --keyNumber, keyState
  1417.             if _focused then
  1418.                 _focused:_key(p1, p2)
  1419.             end
  1420.         elseif event == "timer" then
  1421.             --timerID
  1422.             if _runningTimers[p1] then
  1423.                 _runningTimers[p1]:raise()
  1424.             end
  1425.         elseif event == "term_resize" then
  1426.             if _focused then
  1427.                 _focused:_focusOff()
  1428.             end
  1429.             mainPanel.width, mainPanel.height = term.getSize()
  1430.             term.wash()
  1431.             refresh()
  1432.         elseif event == "forms_stop" then
  1433.             term.wash()
  1434.             return
  1435.         end
  1436.     end
  1437. end
  1438. function stop()
  1439.     os.queueEvent("forms_stop")
  1440.     __forms = nil
  1441. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement