jille_Jr

CC: Cannon mail [Client] - gui.lua

Feb 22nd, 2016
121
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- gui.lua
  2.  
  3. --(( Settings ))--
  4.  
  5. --(( Variables ))--
  6.  
  7. local termW,termH = term.getSize()
  8. local pageW,pageH = 25,21
  9.  
  10. local lockedSender = "kalle"
  11.  
  12. local grid = {}
  13.  
  14. --(( Functions ))--
  15.  
  16. function updateGrid()
  17.     -- Add lost parts
  18.     for x = 1,termW do
  19.         if type(grid[x]) ~= "table" then
  20.             grid[x] = {}
  21.         end
  22.         for y = 1,termH do
  23.             if type(grid[x][y]) ~= "table" then
  24.                 grid[x][y] = {
  25.                     fg = util.colorToHex(colors.white),
  26.                     bg = util.colorToHex(colors.black),
  27.                     char = " ",
  28.                 }
  29.             end
  30.         end
  31.     end
  32.  
  33.     -- Remove excess
  34.     for x in pairs(grid) do
  35.         if type(x) ~= "number"
  36.         or (x < 1 or x > termW) then
  37.             grid[x] = nil
  38.         else
  39.             for y in pairs(grid[x]) do
  40.                 if type(y) ~= "number"
  41.                 or (y < 1 or y > termH) then
  42.                     grid[x][y] = nil
  43.                 end
  44.             end
  45.         end
  46.     end
  47. end
  48.  
  49. -- Get each row seperatly
  50. -- so you can draw it with term.blit
  51. function blitReadyGrid()
  52.     local rows = {}
  53.     -- note that I'm looping Y first
  54.     for y = 1,termH do
  55.         local row = {"","",""}
  56.         for x = 1,termW do
  57.             local pixel = getPixel(x,y)
  58.             row[1] = row[1] .. pixel.char
  59.             row[2] = row[2] .. pixel.fg
  60.             row[3] = row[3] .. pixel.bg
  61.         end
  62.         rows[y] = row
  63.     end
  64.  
  65.     return rows
  66. end
  67.  
  68. function drawGrid()
  69.     updateGrid()
  70.     local rows = blitReadyGrid()
  71.     for y,row in ipairs(rows) do
  72.         term.setCursorPos(1,y)
  73.         term.blit(unpack(row))
  74.     end
  75. end
  76.  
  77. function validPixel(x,y)
  78.     return (x >= 1 and x <= termW)
  79.     and (y >= 1 and y <= termH)
  80.     and (x%1==0) and (y%1==0)
  81. end
  82.  
  83. function getPixel( x,y )
  84.     if validPixel(x,y) then
  85.         return grid[x][y]
  86.     end
  87. end
  88.  
  89. function setPixel(char,x,y,fg,bg)
  90.     if type(fg) == "number" then fg = util.colorToHex(fg) end
  91.     if type(bg) == "number" then bg = util.colorToHex(bg) end
  92.  
  93.     if validPixel(x,y) then
  94.         grid[x][y].char = ((char or grid[x][y].char or "") .. " "):sub(1,1)
  95.         grid[x][y].fg = fg or grid[x][y].fg
  96.         grid[x][y].bg = bg or grid[x][y].bg
  97.     end
  98. end
  99.  
  100. function setRect(char,x1,y1,x2,y2,fg,bg)
  101.     for x = x1,x2 or x1 do
  102.         for y = y1,y2 or y1 do
  103.             setPixel(char,x,y,fg,bg)
  104.         end
  105.     end
  106. end
  107.  
  108. function writeText(text,x,y,fg,bg)
  109.     text = tostring(text)
  110.     for i = 1,#text do
  111.         setPixel(text:sub(i,i),x+i-1,y,fg,bg)
  112.     end
  113. end
  114.  
  115. function writeCentered(text,y,fg,bg)
  116.     writeText(text,math.floor(termW/2-#text/2),y,fg,bg)
  117. end
  118.  
  119. function previewMail(data)
  120.     local tPages = mail.splitPages(mail.prepareMessage(data))
  121.     local nPage = 1
  122.     local pageTitle = mail.getTitle(data,nPage,#tPages)
  123.  
  124.     local scroll = -1
  125.     local scrollbarH = 4
  126.  
  127.     local pageX = 20
  128.     local pageY = 3
  129.  
  130.     -- height of visable area
  131.     local viewH = 17
  132.  
  133.     local running = true
  134.     local redraw = true
  135.  
  136.     local function changePage(newPage)
  137.         nPage = math.max(1,math.min(#tPages, newPage))
  138.         scroll = -1
  139.         redraw = true
  140.         pageTitle = mail.getTitle(data,nPage,#tPages)
  141.     end
  142.  
  143.     local function nextPage() changePage(nPage+1) end
  144.     local function prevPage() changePage(nPage-1) end
  145.  
  146.     local function draw()
  147.         -- Draw header
  148.         setRect(" ",1,1,termW,2,_,colors.cyan)
  149.         writeCentered("Preview of",1,colors.white)
  150.         writeCentered(pageTitle,2,colors.white)
  151.  
  152.         -- Draw background
  153.         setRect(" ",1,3,termW,termH,_,colors.lightBlue)
  154.         -- paper edge
  155.         local y2 = scroll == 5 and termH-1 or termH
  156.         setRect("|",pageX-1,3,_,y2,colors.lightBlue,colors.white)
  157.         setRect("|",pageX+pageW,3,_,y2,colors.lightBlue,colors.white)
  158.  
  159.         -- Draw message
  160.         local tPage = tPages[nPage]
  161.         for nRow = 1+scroll, termH-2+scroll do
  162.             -- filler char
  163.             if nRow == 0 then
  164.                 -- row before page
  165.                 setRect("~",pageX,3,pageX+pageW-1,_,colors.lightBlue,colors.white)
  166.             elseif nRow == pageH+1 then
  167.                 -- row after page
  168.                 setRect("~",pageX,termH,pageX+pageW-1,_,colors.white,colors.lightBlue)
  169.             else
  170.                 -- get page
  171.                 sRow = tPage[nRow] or ""
  172.                 -- fill out so it redraws the entire thing
  173.                 sRow = sRow .. string.rep(" ", pageW - #sRow)
  174.  
  175.                 -- write it out
  176.                 local y = pageY+nRow-scroll-1
  177.                 writeText(sRow,pageX,y,colors.gray,colors.white)
  178.             end
  179.         end
  180.  
  181.         -- Draw scrollbar
  182.         local y = math.floor(pageY+(viewH-scrollbarH)*(scroll+1)/(6))
  183.         setRect(" ", termW, 3, _, termH, _, colors.lightGray)
  184.         setRect(" ", termW, y, _, y+scrollbarH-1, _, colors.gray)
  185.         setPixel("^", termW, y, colors.lightGray)
  186.         setPixel("v", termW, y+scrollbarH-1,colors.lightGray)
  187.  
  188.         -- Draw buttons
  189.         setRect(" ", 1, pageY, 13, termH, _, colors.gray)
  190.         writeText("Page", 2, termH-4, colors.lightGray)
  191.         local txt = nPage.."/"..#tPages
  192.         writeText(txt, 13-#txt, termH-4, colors.lightGray)
  193.         writeText("  <  ", 2, termH-3, colors.white, (nPage > 1) and colors.cyan or colors.lightGray)
  194.         writeText("  >  ", 8, termH-3, colors.white, (nPage < #tPages) and colors.cyan or colors.lightGray)
  195.  
  196.         writeText("   Back    ", 2, termH-1, colors.white, colors.cyan)
  197.  
  198.         -- Draw to screen
  199.         drawGrid()
  200.     end
  201.  
  202.     local function changeScroll(delta)
  203.         scroll = math.min(math.max(math.floor(scroll + delta),-1),pageH-viewH+1)
  204.         redraw = true
  205.     end
  206.  
  207.     local function handleEvents(ev,p1,p2,p3,p4,p5)
  208.         if ev == "key" then
  209.             if p1 == keys.down then
  210.                 changeScroll(1)
  211.             elseif p1 == keys.up then
  212.                 changeScroll(-1)
  213.             elseif p1 == keys.q then
  214.                 running = false
  215.             end
  216.         end
  217.         if ev == "mouse_scroll" then
  218.             changeScroll(p1)
  219.         end
  220.         if ev == "mouse_click" and p1 == 1 then
  221.             if p3 == termH-3 then
  222.                 -- prev page
  223.                 if p2 >= 2 and p2 <= 6 and nPage > 1 then
  224.                     prevPage()
  225.                 end
  226.                 -- next page
  227.                 if p2 >= 8 and p2 <= 12 and nPage < #tPages then
  228.                     nextPage()
  229.                 end
  230.             end
  231.             -- exit
  232.             if p3 == termH-1 and p2 >= 2 and p2 <= 12 then
  233.                 running = false
  234.             end
  235.         end
  236.     end
  237.  
  238.     -- Main loop
  239.     while running do
  240.         if redraw then
  241.             draw()
  242.         end
  243.         handleEvents(os.pullEvent())
  244.     end
  245. end
  246.  
  247. function writeMail()
  248.  
  249.     local running = true
  250.     local redraw = true
  251.     local selected = false
  252.     local fields = {}
  253.  
  254.     local lshift = false
  255.     local rshift = false
  256.     local rctrl = false
  257.     local lctrl = false
  258.     local tabJump = false
  259.  
  260.     local diskAvailable = false
  261.     local anyReceivers = false
  262.  
  263.     local function newTextArea(x1,y1,x2,y2,multiline)
  264.         x2 = x2 or x1
  265.         y2 = y2 or y1
  266.  
  267.         local textArea = {
  268.             x1 = x1, x2 = x2,
  269.             y1 = y1, y2 = y2,
  270.             w = x2 - x1 + 1, h = y2 - y1 + 1,
  271.             multiline = multiline,
  272.             scrollX = 0, scrollY = 0,
  273.             cursorX = 1, cursorY = 1,
  274.             visableCursor = false,
  275.             enabled = true,
  276.  
  277.             onSelect = false,
  278.             onDeselect = false,
  279.             lateDraw = false,
  280.             elemType = "textArea",
  281.  
  282.             nextElem = false,
  283.             prevElem = false,
  284.  
  285.             text = {""}
  286.         }
  287.         table.insert(fields,textArea)
  288.  
  289.         function textArea.destroy(self)
  290.             for i,v in ipairs(fields) do
  291.                 if v == self then
  292.                     table.remove(fields, i)
  293.                     break
  294.                 end
  295.             end
  296.         end
  297.  
  298.         function textArea.localToWorld(self,x,y)
  299.             return x + self.x1 - self.scrollX - 1, y + self.y1 - self.scrollY - 1
  300.         end
  301.  
  302.         function textArea.worldtoLocal(self,x,y)
  303.             return x - self.x1 + self.scrollX + 1, y - self.y1 + self.scrollY + 1
  304.         end
  305.  
  306.         function textArea.pointInArea(self,x,y)
  307.             return x >= self.x1 and x <= self.x2
  308.             and y >= self.y1 and y <= self.y2
  309.         end
  310.  
  311.         function textArea.draw(self)
  312.             local bg = self==selected and colors.black or colors.gray
  313.             local fg = self==selected and colors.white or colors.lightGray
  314.  
  315.             if self.elemType == "button" then
  316.                 bg = self.enabled and colors.cyan or colors.gray
  317.                 fg = self.enabled and colors.white or colors.lightGray
  318.             end
  319.  
  320.             setRect(" ",self.x1,self.y1,self.x2,self.y2,_,bg)
  321.  
  322.             for row = 1 + self.scrollY, self.h + self.scrollY do
  323.                 if row <= #self.text then
  324.                     local x = self.x1
  325.                     local y = self.y1 + row - self.scrollY - 1
  326.                     local text = self.text[row]
  327.                     if row == 1 and self.elemType == "textArea" and not self.enabled then
  328.                         text = "(locked) "..text
  329.                     end
  330.                     writeText(text:sub(1+self.scrollX,self.scrollX+self.w),x,y,fg)
  331.                 end
  332.             end
  333.  
  334.             if selected == self then
  335.                 local x,y = self:localToWorld(self.cursorX,self.cursorY)
  336.                 self.visableCursor = self:pointInArea(self:localToWorld(self.cursorX,self.cursorY))
  337.             end
  338.         end
  339.  
  340.         function textArea.setScroll(self, x,y)
  341.             local maxW = 0
  342.             for _,line in ipairs(self.text) do
  343.                 maxW = math.max(maxW, #line)
  344.             end
  345.  
  346.             -- lock
  347.             self.scrollX = math.max(math.min(maxW-1,x),0)
  348.             self.scrollY = math.max(math.min(y,#self.text-self.h),0)
  349.         end
  350.  
  351.         function textArea.changeScroll(self,dx,dy)
  352.             self:setScroll(self.scrollX+dx,self.scrollY+dy)
  353.         end
  354.  
  355.         function textArea.focusCursor(self)
  356.             self:setScroll(
  357.                 math.min(math.max(self.scrollX,self.cursorX-self.w),self.cursorX-1),
  358.                 math.min(math.max(self.scrollY,self.cursorY-self.h),self.cursorY-1)
  359.             )
  360.         end
  361.  
  362.         function textArea.getText(self)
  363.             local text = ""
  364.             for row,str in ipairs(self.text) do
  365.                 text = text .. str
  366.                 if row < #self.text then -- not last row
  367.                     text = text .. " \n"
  368.                 end
  369.             end
  370.             return text
  371.         end
  372.  
  373.         function textArea.isChecked(self)
  374.             return self.elemType == "checkbox" and self.text[1] == "[x]"
  375.         end
  376.  
  377.         function textArea.handleEvents(self,ev,p1,p2,p3,p4,p5)
  378.             if not self.enabled then
  379.                 return false
  380.             end
  381.             if self==selected then
  382.                 if ev == "char" or ev == "paste" then
  383.                     -- Add character
  384.                     local line = self.text[self.cursorY]
  385.  
  386.                     self.text[self.cursorY] = line:sub(1,self.cursorX) .. p1 .. line:sub(self.cursorX + 1,-1)
  387.                     self.cursorX = self.cursorX + 1
  388.                     self:focusCursor()
  389.                     return true
  390.                 elseif ev == "key" then
  391.                     if p1 == keys.left then
  392.                         if lctrl or rctrl then
  393.                             self:changeScroll(-1,0)
  394.                         else
  395.                             -- left
  396.                             self.cursorX = self.cursorX - 1
  397.                             if self.cursorX < 1 then
  398.                                 if self.cursorY > 1 then -- not first row
  399.                                     self.cursorY = self.cursorY - 1
  400.                                     self.cursorX = #self.text[self.cursorY] + 1
  401.                                 else
  402.                                     self.cursorX = 1
  403.                                 end
  404.                             end
  405.                             self:focusCursor()
  406.                         end
  407.                         return true
  408.                     elseif p1 == keys.right then
  409.                         if lctrl or rctrl then
  410.                             self:changeScroll(1,0)
  411.                         else
  412.                             -- right
  413.                             self.cursorX = self.cursorX + 1
  414.                             if self.cursorX > #self.text[self.cursorY] + 1 then
  415.                                 if self.cursorY < #self.text then -- not last row
  416.                                     self.cursorY = self.cursorY + 1
  417.                                     self.cursorX = 1
  418.                                 else
  419.                                     self.cursorX = #self.text[self.cursorY] + 1
  420.                                 end
  421.                             end
  422.                             self:focusCursor()
  423.                         end
  424.                         return true
  425.                     elseif p1 == keys.up then
  426.                         if lctrl or rctrl then
  427.                             self:changeScroll(0,1)
  428.                         else
  429.                             -- up
  430.                             if self.cursorY > 1 then -- not first row
  431.                                 self.cursorX = math.min(self.cursorX,#self.text[self.cursorY - 1] + 1)
  432.                                 self.cursorY = self.cursorY - 1
  433.                             else
  434.                                 self.cursorX = 1
  435.                             end
  436.                             self:focusCursor()
  437.                         end
  438.                         return true
  439.                     elseif p1 == keys.down then
  440.                         if lctrl or rctrl then
  441.                             self:changeScroll(0,-1)
  442.                         else
  443.                             -- down
  444.                             if self.cursorY < #self.text then -- not last row
  445.                                 self.cursorX = math.min(self.cursorX,#self.text[self.cursorY + 1] + 1)
  446.                                 self.cursorY = self.cursorY + 1
  447.                             else
  448.                                 self.cursorX = #self.text[self.cursorY] + 1
  449.                             end
  450.                             self:focusCursor()
  451.                         end
  452.                         return true
  453.                     elseif p1 == keys.backspace then
  454.                         if self.cursorX > 1 then
  455.                             -- remove a char
  456.                             local line = self.text[self.cursorY]
  457.                             self.text[self.cursorY] = line:sub(1,self.cursorX - 2) .. line:sub(self.cursorX,-1)
  458.                             self.cursorX = self.cursorX - 1
  459.                             self:focusCursor()
  460.                             return true
  461.                         else
  462.                             if self.cursorY > 1 then
  463.                                 -- compress two lines
  464.                                 self.text[self.cursorY - 1] = self.text[self.cursorY - 1] .. self.text[self.cursorY]
  465.                                 table.remove(self.text,self.cursorY)
  466.                                 self.cursorY = self.cursorY - 1
  467.                                 self.cursorX = #self.text[self.cursorY] + 1
  468.                                 self:focusCursor()
  469.                                 return true
  470.                             end
  471.                         end
  472.                     elseif p1 == keys.delete then
  473.                         if self.cursorX < #self.text[self.cursorY]+1 then
  474.                             -- remove a char
  475.                             local line = self.text[self.cursorY]
  476.                             self.text[self.cursorY] = line:sub(1,self.cursorX - 1) .. line:sub(self.cursorX + 1,-1)
  477.                             return true
  478.                         else
  479.                             if self.cursorY < #self.text then
  480.                                 -- compress two lines
  481.                                 self.text[self.cursorY] = self.text[self.cursorY] .. self.text[self.cursorY + 1]
  482.                                 table.remove(self.text,self.cursorY + 1)
  483.                                 self:focusCursor()
  484.                                 return true
  485.                             end
  486.                         end
  487.                     elseif p1 == keys.enter then
  488.                         if self.multiline then
  489.                             -- split into new line
  490.                             local line = self.text[self.cursorY]
  491.                             self.text[self.cursorY] = line:sub(1, self.cursorX - 1)
  492.                             line = line:sub(self.cursorX, -1)
  493.  
  494.                             table.insert(self.text, self.cursorY + 1, line)
  495.                             self.cursorY = self.cursorY + 1
  496.                             self.cursorX = 1
  497.                             self:focusCursor()
  498.                             return true
  499.                         end
  500.                     elseif p1 == keys["end"] then
  501.                         self.cursorX = #self.text[self.cursorY] + 1
  502.                         self:focusCursor()
  503.                         return true
  504.                     elseif p1 == keys.home then
  505.                         self.cursorX = 1
  506.                         self:focusCursor()
  507.                         return true
  508.                     elseif p1 == keys.tab then
  509.                         if not tabJump then
  510.                             if rshift or lshift then
  511.                                 -- prev
  512.                                 if self.prevElem then
  513.                                     if type(self.onDeselect) == "function" then
  514.                                         self:onDeselect()
  515.                                     end
  516.                                     selected = self.prevElem
  517.                                     if type(selected.onSelect) == "function" then
  518.                                         selected:onSelect()
  519.                                     end
  520.                                     tabJump = true
  521.                                     return true
  522.                                 end
  523.                             else
  524.                                 -- next
  525.                                 if self.nextElem then
  526.                                     if type(self.onDeselect) == "function" then
  527.                                         self:onDeselect()
  528.                                     end
  529.                                     selected = self.nextElem
  530.                                     if type(selected.onSelect) == "function" then
  531.                                         selected:onSelect()
  532.                                     end
  533.                                     tabJump = true
  534.                                     return true
  535.                                 end
  536.                             end
  537.                         end
  538.                     end
  539.                 elseif ev == "mouse_scroll" then
  540.                     self:changeScroll(0,p1)
  541.                     return true
  542.                 end
  543.             end
  544.             if ev == "mouse_click" and p1 == 1 then
  545.                 if self:pointInArea(p2,p3) then
  546.                     if self.elemType == "textArea" then
  547.                         selected = self
  548.                         local x,y = self:worldtoLocal(p2,p3)
  549.                         self.cursorY = math.min(#self.text, y)
  550.                         self.cursorX = math.min(#self.text[self.cursorY]+1, x)
  551.                         self:focusCursor()
  552.                     elseif self.elemType == "checkbox" then
  553.                         local checked = self:isChecked()
  554.                         self.text[1] = checked and "[ ]" or "[x]"
  555.                     end
  556.                     if type(self.onSelect) == "function" then
  557.                         self:onSelect()
  558.                     end
  559.                     return true
  560.                 elseif selected == self then
  561.                     if type(self.onDeselect) == "function" then
  562.                         self:onDeselect()
  563.                     end
  564.                     selected = false
  565.                     return true
  566.                 end
  567.             end
  568.  
  569.             return false
  570.         end
  571.  
  572.         return textArea
  573.     end
  574.  
  575.     local function newCheckbox( x,y,checked )
  576.         local textArea = newTextArea(x,y,x+2,_,false)
  577.         textArea.elemType = "checkbox"
  578.         textArea.text[1] = checked and "[x]" or "[ ]"
  579.         return textArea
  580.     end
  581.  
  582.     local function newButton(x1,y1,x2,y2,str,onSelect)
  583.         local button = newTextArea(x1,y1,x2,y2,true)
  584.         button.elemType = "button"
  585.         button.onSelect = onSelect
  586.         button.enabled = true
  587.  
  588.         button.text = {}
  589.         for i=1,button.h do
  590.             if i == math.floor(button.h/2)+1 then
  591.                 table.insert(button.text,string.rep(" ",math.floor(button.w/2-#str/2))..str)
  592.             else
  593.                 table.insert(button.text,"")
  594.             end
  595.         end
  596.  
  597.         return button
  598.     end
  599.  
  600.     local exitField = newButton(termW,1,_,_,"X")
  601.     local fromField = newTextArea(10,4,termW-1,_,false)
  602.     local subjectField = newTextArea(10,6,termW-1,_,false)
  603.     local messageField = newTextArea(10,8,termW-1,14,true)
  604.     local previewField = newButton(termW - 14,termH-3,termW-1,_,"Preview")
  605.     local sendField = newButton(termW - 14,termH-1,termW-1,_,"Send")
  606.  
  607.     fromField.nextElem = subjectField
  608.     fromField.prevElem = messageField
  609.     subjectField.nextElem = messageField
  610.     subjectField.prevElem = fromField
  611.     messageField.nextElem = fromField
  612.     messageField.prevElem = subjectField
  613.     sendField.enabled = false
  614.  
  615.     if type(lockedSender) == "string" and #lockedSender > 0 then
  616.         fromField.enabled = false
  617.         fromField.text[1] = lockedSender
  618.  
  619.         subjectField.prevElem = messageField
  620.         messageField.nextElem = subjectField
  621.     end
  622.  
  623.     local jagField = newCheckbox(10,termH - 3)
  624.     local knautField = newCheckbox(10,termH - 2)
  625.     local bejnoField = newCheckbox(10,termH - 1)
  626.  
  627.     local function getReceivers()
  628.         local receivers = {}
  629.         if jagField:isChecked() then table.insert(receivers,"jag") end
  630.         if knautField:isChecked() then table.insert(receivers,"knaut") end
  631.         if bejnoField:isChecked() then table.insert(receivers,"bejno") end
  632.         return receivers
  633.     end
  634.  
  635.     local function checkForErrors()
  636.         local oldA,oldB = diskAvailable,anyReceivers
  637.         diskAvailable = mail.getDrive().hasData()
  638.         anyReceivers = #getReceivers() > 0
  639.         sendField.enabled = diskAvailable and anyReceivers
  640.         if diskAvailable ~= oldA or anyReceivers ~= oldB then redraw = true end
  641.     end
  642.  
  643.     local function getMailData()
  644.         return {
  645.             sender = fromField:getText(),
  646.             receivers = getReceivers(),
  647.             message = messageField:getText(),
  648.             subject = subjectField:getText(),
  649.         }
  650.     end
  651.  
  652.     previewField.onSelect = function(self)
  653.         previewMail(getMailData())
  654.     end
  655.  
  656.     sendField.onSelect = function(self)
  657.         if self.enabled then
  658.             mail.writeMail(getMailData())
  659.         end
  660.     end
  661.  
  662.     exitField.onSelect = function(self)
  663.         running = false
  664.     end
  665.  
  666.     local function draw()
  667.         term.setCursorBlink(false)
  668.  
  669.         -- draw background
  670.         setRect(" ",1,1,termW,2,_,colors.cyan)
  671.         setRect(" ",1,3,termW,termH, _, colors.lightBlue)
  672.  
  673.         -- Draw text
  674.         writeCentered("Write new mail",2,colors.white)
  675.  
  676.         writeText("From", 2, 4, colors.gray)
  677.         writeText("Subject", 2, 6, colors.gray)
  678.         writeText("Message", 2, 8, colors.gray)
  679.  
  680.         writeText("Send to", 2, termH - 3, colors.gray)
  681.         writeText("- jag", 14, termH - 3, jagField:isChecked() and colors.black or colors.gray)
  682.         writeText("- knaut", 14, termH - 2, knautField:isChecked() and colors.black or colors.gray)
  683.         writeText("- bejno", 14, termH - 1, bejnoField:isChecked() and colors.black or colors.gray)
  684.  
  685.         if not diskAvailable then
  686.             writeText("Requires disk in disk drive!",23,termH,colors.red)
  687.         elseif not anyReceivers then
  688.             writeText("   Need at least 1 receiver!",23,termH,colors.red)
  689.         end
  690.  
  691.         -- Draw fields
  692.         for _,field in pairs(fields) do
  693.             if type(field.draw) == "function" then
  694.                 field:draw()
  695.             end
  696.         end
  697.  
  698.         for _,field in pairs(fields) do
  699.             if type(field.lateDraw) == "function" then
  700.                 field:lateDraw()
  701.             end
  702.         end
  703.  
  704.         -- Draw to screen
  705.         drawGrid()
  706.  
  707.         -- Show cursor
  708.         if selected and selected.visableCursor then
  709.             term.setCursorPos(selected:localToWorld(selected.cursorX,selected.cursorY))
  710.             term.setCursorBlink(true)
  711.         else
  712.             term.setCursorBlink(false)
  713.         end
  714.     end
  715.  
  716.     local function handleEvents(ev,p1,p2,p3,p4,p5)
  717.         checkForErrors()
  718.  
  719.         if ev == "key" then
  720.             if p1 == keys.leftShift then lshift = true end
  721.             if p1 == keys.rightShift then rshift = true end
  722.             if p1 == keys.leftCtrl then lctrl = true end
  723.             if p1 == keys.rightCtrl then rctrl = true end
  724.         end
  725.         if ev == "key_up" then
  726.             if p1 == keys.leftShift then lshift = false end
  727.             if p1 == keys.rightShift then rshift = false end
  728.             if p1 == keys.leftCtrl then lctrl = false end
  729.             if p1 == keys.rightCtrl then rctrl = false end
  730.         end
  731.  
  732.         -- Update fields
  733.         tabJump = false
  734.         for _,field in pairs(fields) do
  735.             if field:handleEvents(ev,p1,p2,p3,p4,p5) then
  736.                 redraw = true
  737.             end
  738.         end
  739.     end
  740.  
  741.     -- Main loop
  742.     checkForErrors()
  743.     while running do
  744.         if redraw then
  745.             draw()
  746.             redraw = false
  747.         end
  748.         handleEvents(os.pullEvent())
  749.     end
  750.  
  751.     term.setBackgroundColor(colors.black)
  752.     term.clear()
  753.     term.setCursorPos(1,1)
  754.  
  755.     return data
  756. end
  757.  
  758. -- eof
RAW Paste Data