Advertisement
HPWebcamAble

[CC][2.3] Simple Screen Maker

Apr 9th, 2015
970
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 44.31 KB | None | 0 0
  1. --[[
  2. HPWebcamAble presents...
  3. Simple Screen Maker
  4.  
  5. --=== Description ===--
  6. ComputerCraft Forum Post:
  7. http://www.computercraft.info/forums2/index.php?/topic/22849-simple-screen-maker
  8.  
  9. This program allows you to make Screens from my Screen API
  10. Instead of using code, you 'draw' the screen!
  11.  
  12. Run 'ssm help' for usages
  13. Use 'h' to view the controls while in the program
  14.  
  15. Check out this ComputerCraft Forum Post to see how to use the save file:
  16. http://www.computercraft.info/forums2/index.php?/topic/22849-simple-screen-maker
  17.  
  18.  
  19. --=== Installation and Use ===--
  20. Pastebin Code: sw4PJVPK
  21.  
  22. To download a file from pastebin, run this command in a computer:
  23. pastebin get <code> <file name>
  24.  
  25.  
  26. --=== Update History ===--
  27. The pastebin will always have the most recent version
  28.  
  29. |2.3|
  30. -Better message when loading a file that uses the previous save format
  31. -Checks to make sure you are using at least CC 1.74
  32. -Fixed a bunch of typos
  33. -Cleaned up the code
  34. -Added a default of each element that can be modifed, new elements will use those properties
  35. -Changed to key bindings that should be easily reached with only one hand
  36. -Changed Edit Element screen
  37.   *Elements can be renamed now
  38. -Most text boxes and titles should fit on pocket computers now
  39.   *Let me know if you find one that doesn't
  40. -Updated how elements save their data to support my Screen API 2.0
  41.   *Cannot load saves from older versions
  42.  
  43. |2.2|
  44. -Added state editing!
  45. -Cleaned up the code
  46. -More text shortened to fit on all screens
  47. -Elements created with the program are compatible with my Screen API again (whoops)
  48.   *Cannot load saves from older versions
  49.  
  50. |2.1|
  51. -Cleaned up the code
  52. -Updated description
  53. -Fixed buffer causing anything off the right of the screen to become invisible
  54.   *Heading text should show up on pocket computers
  55.   *Objects and click areas show up when they are off the right edge
  56. -Shortned a lot of text, most should fit on pocket computers
  57.  
  58. |2.0|
  59. -Changed a few key bindings
  60. -Tweaked how elements are created
  61. -You can now import a background to use for positioning
  62. -New save file format
  63.   *Cannot load saves from older versions
  64.  
  65. |1.1|
  66. -Cleaned up the code
  67. -Changed Delete Element options to 'Delete' or 'Cancel'
  68. -Fixed a few minor bugs
  69.  
  70. |1.0|
  71. -Release
  72. ]]
  73.  
  74. --=== Variables ===--
  75.  
  76. --Change to suit your preferences (althogh some colors are hardcoded)
  77. --Note: Key binding can't be changed
  78. local settings = {
  79.   background = colors.white,
  80.   heading = colors.orange,
  81.   headingText = colors.black,
  82.   clickAreaBoarder = colors.black,
  83.   crosshair = colors.lightBlue,
  84.   cHCenter = colors.black,
  85.   listBackground = colors.white,
  86.   listText = colors.black,
  87.   listTextExitKey = colors.lightGray
  88. }
  89.  
  90. --Don't change these if you want to live
  91. local forumPostLink = "http://www.computercraft.info/forums2/index.php?/topic/22849-simple-screen-maker/#entry213270"
  92. local screen = {
  93.   objects = {},
  94.   clickAreas = {}
  95. }
  96. local screenBuffer = {} -- Stores each line of the computer's screen, for the buffer
  97. local buffer -- Tells the buffer API which lines have changed since the last update to the screen
  98. local originalTerm = term.current()
  99. local headingPos = true
  100. local loadedFileName = ""
  101. local w,h = term.getSize()
  102. local defaultHeading = "Press h to view help"
  103. local mainHeading = defaultHeading
  104. local selected = {}
  105. local drawClickAreas = true
  106. local background
  107. local backX,backY = 1,1
  108. local lastClick = {}
  109. local elementStringType = {
  110.   ["objects"] = "Object",
  111.   ["clickAreas"] = "Click Area",
  112.   ["Click Area"] = "clickAreas",
  113.   ["Object"] = "objects",
  114.   ["Objects"] = "objects",
  115.   ["Click Areas"] = "clickAreas"
  116. }
  117. local compColor = { --Complementry colors, to make sure a character can be seen on a specific background color
  118.   [colors.white] = colors.black,
  119.   [colors.orange] = colors.black,
  120.   [colors.magenta] = colors.black,
  121.   [colors.lightBlue] = colors.black,
  122.   [colors.yellow] = colors.black,
  123.   [colors.lime] = colors.black,
  124.   [colors.pink] = colors.black,
  125.   [colors.gray] = colors.white,
  126.   [colors.lightGray] = colors.black,
  127.   [colors.cyan] = colors.black,
  128.   [colors.purple] = colors.black,
  129.   [colors.blue] = colors.black,
  130.   [colors.brown] = colors.white,
  131.   [colors.green] = colors.black,
  132.   [colors.red] = colors.black,
  133.   [colors.black] = colors.white
  134. }
  135.  
  136. local toHex = {
  137.   [ colors.white ] = "0",
  138.   [ colors.orange ] = "1",
  139.   [ colors.magenta ] = "2",
  140.   [ colors.lightBlue ] = "3",
  141.   [ colors.yellow ] = "4",
  142.   [ colors.lime ] = "5",
  143.   [ colors.pink ] = "6",
  144.   [ colors.gray ] = "7",
  145.   [ colors.lightGray ] = "8",
  146.   [ colors.cyan ] = "9",
  147.   [ colors.purple ] = "a",
  148.   [ colors.blue ] = "b",
  149.   [ colors.brown ] = "c",
  150.   [ colors.green ] = "d",
  151.   [ colors.red ] = "e",
  152.   [ colors.black ] = "f",
  153. }
  154.  
  155. local toDecimal = {}
  156. for a,b in pairs(toHex) do -- Build the toDecimal table as the reverse of the toHex table
  157.   toDecimal[b] = a
  158. end
  159.  
  160. -- Made local for a small speed increase
  161. local string_rep = string.rep
  162. local string_sub = string.sub
  163.  
  164. local default = {
  165.   objects = {
  166.     text = nil,
  167.     name = "Default Object",
  168.     minX = 1,minY = 1,
  169.     maxX = 7,maxY = 3,
  170.     states = {
  171.       on = {text = colors.white, back = colors.lime},
  172.       off = {text = colors.white, back = colors.red}
  173.     },
  174.     clickable = true,
  175.     visible = true,
  176.     state = "off",
  177.     action = nil
  178.   },
  179.   clickAreas = {
  180.     name = "Default Click Area",
  181.     minX = 1,minY = 1,
  182.     maxX = 5,maxY = 3,
  183.     clickable = true,
  184.     action = nil
  185.   }
  186. }
  187.  
  188. --=== Functions ===--
  189. local function color(text,back)
  190.   local temp = text and term.setTextColor(text) or nil
  191.   temp = back and term.setBackgroundColor(back) or nil
  192. end
  193.  
  194. local function fillTable(toFill,fillWith) --Used by the API
  195.   if toFill == nil then toFill = {} end
  196.   for a,b in pairs(fillWith) do
  197.     if type(b) == "table" then
  198.       toFill[a] = fillTable(toFill[a],b)
  199.     else
  200.       if toFill[a] == nil then toFill[a] = b end
  201.     end
  202.   end
  203.   return toFill
  204. end
  205.  
  206. -- The following functions are part of my Buffer API, modified for this program
  207. -- http://pastebin.com/LVmgReu6
  208. local function createLine(backgroundColor)
  209.   local w,h = term.getSize()
  210.   local line = {
  211.     text = string_rep(" " , w),
  212.     backColor = string_rep( toHex[backgroundColor] , w ),
  213.     textColor = string_rep( toHex[colors.white] , w )
  214.   }
  215.   return line
  216. end
  217.  
  218. for i = 1, h do
  219.   screenBuffer[i] = createLine(settings.background)
  220. end
  221.  
  222. local function bufferText(text)
  223.   local w,h = term.getSize()
  224.   local curX,curY = term.getCursorPos()
  225.   if curY > h or curY < 1 or curX > w then return end -- Skip calls above, below, or to the right of the screen
  226.   if curX < 1 then -- Trim text outside the left of the screen
  227.     text = string_sub(text,math.abs(curX)+2)
  228.     curX = 1
  229.   end
  230.   local maxX = curX + #text
  231.   local minX = curX - 1
  232.  
  233.   screenBuffer[curY].text = screenBuffer[curY].text:sub(1,minX)..text..screenBuffer[curY].text:sub(maxX)
  234.   screenBuffer[curY].textColor = screenBuffer[curY].textColor:sub(1,minX)..string_rep( toHex[term.getTextColor()] ,#text)..screenBuffer[curY].textColor:sub(maxX)
  235.   screenBuffer[curY].backColor = screenBuffer[curY].backColor:sub(1,minX)..string_rep( toHex[term.getBackgroundColor()] ,#text)..screenBuffer[curY].backColor:sub(maxX)
  236.  
  237.   if not buffer then buffer = {} end
  238.   buffer[curY] = true
  239.   term.setCursorPos(maxX-1,curY)
  240. end
  241.  
  242. local function writeToScreen()
  243.   local startX,startY = term.getCursorPos()
  244.   local w,h = term.getSize()
  245.   if not buffer then return end
  246.   for i = 1, h do
  247.     if buffer[i] then
  248.       term.setCursorPos(1,i)
  249.       local line = screenBuffer[i]
  250.       term.blit(line.text,line.textColor,line.backColor)
  251.     end
  252.   end
  253.   buffer = nil
  254.   term.setCursorPos(startX,startY)
  255. end
  256.  
  257. local function clearScreen()
  258.   local w,h = term.getSize()
  259.   local curBack = term.getBackgroundColor()
  260.   if not buffer then buffer = {} end
  261.   for i = 1, h do
  262.     screenBuffer[i] = createLine(curBack)
  263.     buffer[i] = true
  264.   end
  265. end
  266.  
  267. local function getPixel(y,x)
  268.   if y > h or y < 1 then return 1 end
  269.   return toDecimal[string_sub(screenBuffer[y].backColor,x,x)]
  270. end
  271.  
  272. --Create new term object that buffers draw calls
  273. local newTerm = {}
  274. for a,b in pairs(originalTerm) do
  275.   newTerm[a] = b
  276. end
  277. newTerm.write = function(text)
  278.   bufferText(text)
  279. end
  280. newTerm.clear = function()
  281.   clearScreen()
  282. end
  283. newTerm.blit = function(...)
  284.   error("Cannot blit")
  285. end
  286. newTerm.clearLine = function(...)
  287.   error("Cannot clearLine")
  288. end
  289. -- End Buffer API
  290.  
  291. local function typeToString(sType)
  292.   return elementStringType[sType]
  293. end
  294.  
  295. local function stringToType(sString)
  296.   return elementStringType[sString]
  297. end
  298.  
  299. local function scrollRead(x,y,nLength,sInsertText,sWhitelist,sBlacklist) --This is a simple scrolling-read function I made
  300.   local cPos,input = 1,""
  301.   if sInsertText then
  302.     cPos,input = #tostring(sInsertText)+1,tostring(sInsertText)
  303.   end
  304.   term.setCursorBlink(true)
  305.   while true do
  306.     term.setCursorPos(x,y)
  307.     term.write(string.rep(" ",nLength))
  308.     term.setCursorPos(x,y)
  309.     if string.len(input) > nLength-1 then
  310.       term.write(string.sub(input,(nLength-1)*-1))
  311.     else
  312.       term.write(input)
  313.     end
  314.     local event,p1 = os.pullEvent()
  315.     if event == "char" and (not sWhitelist or string.find(sWhitelist,p1)) and (not sBlacklist or not string.find(sBlacklist,p1)) then
  316.       input = string.sub(input,1,cPos)..p1
  317.       cPos = cPos + 1                  
  318.     elseif event == "key" then
  319.       if p1 == keys.enter then
  320.         term.setCursorBlink(false)
  321.         return input
  322.       elseif p1 == keys.backspace then
  323.         if cPos > 1 then
  324.           input = string.sub(input,1,cPos-2)..string.sub(input,cPos)
  325.           cPos = cPos - 1
  326.         end
  327.       end    
  328.     end
  329.   end
  330. end
  331.  
  332. local function printC(text,y)
  333.   if type(text) ~= "string" or type(y) ~= "number" then error("expected string,number, got "..type(text)..","..type(y),2) end
  334.   local lenght = #text
  335.   local start = math.floor((w-lenght)/2)+1
  336.   term.setCursorPos(start,y)
  337.   term.write(text)
  338.   return start,start+lenght
  339. end
  340.  
  341. local function getHeadingY()
  342.   local pos = { [true] = 1, [false] = h }
  343.   return pos[headingPos]
  344. end
  345.  
  346. local function drawHeading(text,forcePos)
  347.   local pos = { [true] = 1, [false] = h }
  348.   color(settings.headingText,settings.heading)
  349.   term.setCursorPos(1,pos[forcePos or headingPos])
  350.   term.write(string.rep(" ",w))
  351.   printC(text,pos[forcePos or headingPos])
  352. end
  353.  
  354. local function waitForKey(key)
  355.   repeat
  356.     local event,pKey = os.pullEvent("key")
  357.   until pKey == key
  358. end
  359.  
  360. local function getInput(heading,requireText,insertText,setPadding,whitelist,blacklist)
  361.   os.startTimer(0.1) os.pullEvent()
  362.   local minY = 6
  363.   local padding = setPadding or 2
  364.   heading = tostring(heading) or "Enter some text"
  365.   local minX = math.floor(w/2)-math.ceil((#heading+padding*2)/2)
  366.   term.setCursorPos(minX,minY) color(colors.black,colors.orange)
  367.   term.write(string.rep(" ",padding)..heading..string.rep(" ",padding))
  368.   color(nil,colors.lightGray)
  369.   for i = 1, 3 do
  370.     term.setCursorPos(minX,minY+i)
  371.     term.write(string.rep(" ",#heading+padding*2))
  372.   end
  373.   color(colors.white,colors.black)
  374.   local lenght = #heading+padding*2-4
  375.   local sInput = scrollRead(minX+2,minY+2,lenght,insertText,whitelist,blacklist)
  376.   while sInput == "" and requireText do
  377.     sInput = scrollRead(minX+2,minY+2,lenght,nil,whitelist,blacklist)
  378.   end
  379.   return sInput
  380. end
  381.  
  382. local function getNum(heading,insertNum)
  383.   return tonumber(getInput(heading,true,insertNum,nil,"1234567890"))  
  384. end
  385.  
  386. local function option(heading,choices,choiceColors,setPadding)
  387.   os.startTimer(0.1)
  388.   os.pullEvent()
  389.   heading = tostring(heading) or "Select an option"
  390.   local choiceWidth = 0
  391.   for i = 1, #choices do
  392.     if #choices[i] > choiceWidth then
  393.       choiceWidth = #choices[i]
  394.     end
  395.   end
  396.   choiceWidth = choiceWidth + 2
  397.   local minY = 5
  398.   local padding = setPadding or (choiceWidth-#heading+2*2)/2
  399.   if padding < 0 then padding = 2 end
  400.   local minX = math.floor((w-(#heading+padding*2))/2)+1
  401.   term.setCursorPos(minX,minY)
  402.   color(colors.black,colors.orange)
  403.   term.write(string.rep(" ",math.floor(padding))..heading..string.rep(" ",math.ceil(padding)))
  404.   color(nil,colors.lightGray)
  405.   for i = 1, #choices*2+1 do
  406.     term.setCursorPos(minX,minY+i)
  407.     term.write(string.rep(" ",#heading+padding*2))
  408.   end
  409.   local choicePos = {}
  410.   local pos = 1
  411.   color(colors.white,colors.lime)
  412.   for i = 1, #choices do
  413.     local toWrite = string.rep(" ",math.floor((choiceWidth-#choices[i])/2))..choices[i]..string.rep(" ",math.ceil((choiceWidth-#choices[i])/2))
  414.     if choiceColors and choiceColors[i] then
  415.       color(choiceColors[i][1],choiceColors[i][2])
  416.     else
  417.       color(colors.white,colors.lime)
  418.     end
  419.     printC(toWrite,minY+1+pos)
  420.     choicePos[minY+1+pos] = choices[i]
  421.     pos = pos+2
  422.   end
  423.   while true do
  424.     local eArgs = {os.pullEvent("mouse_click")}
  425.     if choicePos[eArgs[4]] then
  426.       return choicePos[eArgs[4]]
  427.     end
  428.   end
  429. end
  430.  
  431. local function getColor(heading)
  432.   local minY,padding,numColors = 6,1,16
  433.   local colorPadding = 2
  434.   heading = heading==nil and "Select a color" or tostring(heading)
  435.  
  436.   if #heading+padding*2 < 16+colorPadding*2 then
  437.     padding = (16+colorPadding*2-#heading+padding*2)/2
  438.   end
  439.   color(colors.black,colors.orange)
  440.   printC(string.rep(" ",math.floor(padding))..heading..string.rep(" ",math.ceil(padding)),minY)
  441.   color(nil,colors.lightGray)
  442.   for i = 1, 3 do
  443.     printC(string.rep(" ",#heading+padding*2),minY+i)
  444.   end
  445.   local minColorPos = math.floor((w-numColors)/2)+1
  446.  
  447.   term.setCursorPos(minColorPos,minY+2)
  448.   local curColor,colorPos = 1,{}
  449.   for i = 1, numColors do
  450.     colorPos[minColorPos+i-1] = curColor
  451.     term.setBackgroundColor(curColor) term.write(" ")
  452.     curColor = 2^i
  453.   end
  454.   while true do
  455.     local eArgs = {os.pullEvent("mouse_click")}
  456.     if eArgs[4] == minY+2 and eArgs[3] >= minColorPos and eArgs[3] <= minColorPos+(numColors-1) then
  457.       return colorPos[eArgs[3]]
  458.     end
  459.   end
  460. end
  461.  
  462. local function drawObject(objData)
  463.   color(objData.states[objData.state].text,objData.states[objData.state].back)
  464.   for y = 0, objData.maxY-objData.minY do
  465.     term.setCursorPos(objData.minX,objData.minY+y)
  466.     term.write(string.rep(" ",objData.maxX-objData.minX+1))
  467.   end
  468.   if objData.text then
  469.     local xPos = objData.minX+math.floor(((objData.maxX-objData.minX+1)-#objData.text)/2)
  470.     local yPos = objData.minY+(objData.maxY-objData.minY)/2
  471.     term.setCursorPos(xPos,yPos)
  472.     term.write(objData.text)
  473.   end
  474. end
  475.  
  476. local function drawClickArea(data)
  477.   term.setCursorPos(data.minX,data.minY)
  478.   color(compColor[getPixel(data.minY,data.minX)],getPixel(data.minY,data.minX))
  479.   term.write("+")
  480.   term.setCursorPos(data.minX,data.maxY)
  481.   color(compColor[getPixel(data.maxY,data.minX)],getPixel(data.maxY,data.minX))
  482.   term.write("+")
  483.   term.setCursorPos(data.maxX,data.minY)
  484.   color(compColor[getPixel(data.minY,data.maxX)],getPixel(data.minY,data.maxX))
  485.   term.write("+")
  486.   term.setCursorPos(data.maxX,data.maxY)
  487.   color(compColor[getPixel(data.maxY,data.maxX)],getPixel(data.maxY,data.maxX))
  488.   term.write("+")
  489.   for x = 1, data.maxX-data.minX-1 do --draw top and bottom
  490.     term.setCursorPos(data.minX+x,data.minY)
  491.     color(compColor[getPixel(data.minY,data.minX+x)],getPixel(data.minY,data.minX+x))
  492.     term.write("-")
  493.     term.setCursorPos(data.minX+x,data.maxY)
  494.     color(compColor[getPixel(data.maxY,data.minX+x)],getPixel(data.maxY,data.minX+x))
  495.     term.write("-")
  496.   end
  497.   for y = 1, data.maxY-data.minY-1 do --Right and left side
  498.     term.setCursorPos(data.minX,data.minY+y)
  499.     color(compColor[getPixel(data.minY+y,data.minX)],getPixel(data.minY+y,data.minX))
  500.     term.write("|")
  501.     color(compColor[getPixel(data.minY+y,data.maxX)],getPixel(data.minY+y,data.maxX))
  502.     term.setCursorPos(data.maxX,data.minY+y)
  503.     term.write("|")
  504.   end
  505. end
  506.  
  507. function checkPos(x,y,onlyAcceptObjects)
  508.   local insideArea = {}
  509.   if not onlyAcceptObjects then
  510.     for name,data in pairs(screen.clickAreas) do
  511.       if x >= data.minX and x <= data.maxX and y >= data.minY and y <= data.maxY then
  512.         table.insert(insideArea,{"clickAreas","Click Area",name})
  513.       end
  514.     end
  515.   end
  516.   for name,data in pairs(screen.objects) do
  517.     if x >= data.minX and x <= data.maxX and y >= data.minY and y <= data.maxY then
  518.       table.insert(insideArea,{"objects","Object",name})
  519.     end
  520.   end
  521.   return insideArea
  522. end
  523.  
  524. local function redrawScreen(heading)
  525.   color(colors.black,settings.background)
  526.   clearScreen()
  527.   term.redirect(newTerm)
  528.   if type(background) == "table" then
  529.     paintutils.drawImage(background,backX,backY)
  530.   end
  531.   for a,b in pairs(screen.objects) do --Draw objects
  532.     drawObject(b)
  533.   end
  534.   if drawClickAreas then --Draw Click Areas
  535.     for name,data in pairs(screen.clickAreas) do
  536.       drawClickArea(data)
  537.     end
  538.   end
  539.   if #selected > 0 then --Draw x's on selected element
  540.     local data = screen[selected[1]][selected[2]]
  541.     color(settings.crosshair,settings.cHCenter)
  542.     term.setCursorPos(data.minX,data.minY) term.write("X")
  543.     term.setCursorPos(data.minX,data.maxY) term.write("X")
  544.     term.setCursorPos(data.maxX,data.minY) term.write("X")
  545.     term.setCursorPos(data.maxX,data.maxY) term.write("R")
  546.   end
  547.   if heading then
  548.     mainHeading = heading
  549.   end
  550.   drawHeading(mainHeading)
  551.   term.redirect(originalTerm)
  552.   writeToScreen()
  553. end
  554.  
  555. local function getNames(sType)
  556.   local names = {}
  557.   for a,b in pairs(screen[sType]) do
  558.     table.insert(names,a)
  559.   end
  560.   return names
  561. end
  562.  
  563. local function displayList(heading,elements,options,key)
  564.   local listTop = 3
  565.   local listBottom = h-1
  566.   local listLeft = 2
  567.   local dispExitKey = 2
  568.   local perPage = listBottom-listTop
  569.   local page = 1
  570.   local pages
  571.   local optionWidth = 0
  572.   local tLines = {}
  573.   if options then
  574.     for i = 1, #options do
  575.       optionWidth = optionWidth+(#options[i][1])+1
  576.     end
  577.   end
  578.  
  579.   local function refreshElements()
  580.     tLines = {}
  581.     for a = 1, #elements do
  582.       if elements[a][1] ~= false then
  583.         table.insert(tLines,{elements[a][1],false})
  584.       end
  585.       local curElements
  586.       if type(elements[a][2]) == "function" then
  587.         curElements = elements[a][2](unpack(elements[a][3]))
  588.       else
  589.         curElements = elements[a][2]
  590.       end
  591.       for b = 1, #curElements do
  592.         table.insert(tLines,{"  "..curElements[b],true,elements[a][1]})
  593.       end
  594.       table.insert(tLines,{" ",false})
  595.     end
  596.     pages = math.ceil(#tLines/perPage)
  597.     page = page<=pages and page or pages
  598.   end
  599.  
  600.   local function redrawList()
  601.     color(settings.listText,settings.listBackground)
  602.     term.clear()
  603.     drawHeading(heading or "List",true)
  604.     for i = 1, #tLines do
  605.       local cur = i+perPage*(page-1)
  606.       if i > perPage or cur > #tLines then break end
  607.       color(settings.listText,settings.listBackground)
  608.       term.setCursorPos(listLeft,listTop+i-1)
  609.       term.write(tLines[cur][1])
  610.       term.setCursorPos(w-optionWidth,listTop+i-1)
  611.       if options and tLines[cur][2] then
  612.         for i = 1, #options do
  613.           color(options[i][2] or colors.white, options[i][3] or colors.lightBlue)
  614.           term.write(options[i][1])
  615.           color(nil,settings.listBackground)
  616.           term.write(" ")
  617.         end
  618.       end
  619.     end
  620.     color(settings.listText,settings.listBackground)
  621.     printC("Page "..page.." out of "..pages,h)
  622.     color(settings.listTextExitKey,nil)
  623.     printC(keys.getName(key).." to exit",dispExitKey)
  624.   end
  625.  
  626.   refreshElements()
  627.   redrawList()
  628.   while true do
  629.     local eArgs = {os.pullEvent()}
  630.     if eArgs[1] == "key" then
  631.       if eArgs[2] == key then
  632.         return
  633.       elseif eArgs[2] == keys.up then
  634.         if page > 1 then
  635.           page = page-1
  636.           redrawList()
  637.         end
  638.       elseif eArgs[2] == keys.down then
  639.         if page < pages then
  640.           page = page+1
  641.           redrawList()
  642.         end
  643.       elseif eArgs[2] == keys.left then
  644.         if page > 1 then
  645.           page = page-1
  646.           redrawList()
  647.         end
  648.       elseif eArgs[2] == keys.right then
  649.         if page < pages then
  650.           page = page+1
  651.           redrawList()
  652.         end
  653.       end
  654.     elseif eArgs[1] == "mouse_click" and options then
  655.       if eArgs[4] >= listTop and eArgs[4]-listTop < #tLines+perPage*(page-1) and eArgs[3] >= w-optionWidth and eArgs[3] <= w-2 then
  656.         local totalWidth = 0
  657.         for i = 1, #options do
  658.           if eArgs[3] >= w-optionWidth+totalWidth and eArgs[3] < w-optionWidth+totalWidth+#options[i][1] then
  659.             local result = options[i][4](tLines[(eArgs[4]-listTop+1)+perPage*(page-1)][1]:sub(3),unpack(options[i][5]),tLines[(eArgs[4]-listTop+1)+perPage*(page-1)][3])
  660.             if result then
  661.               return result
  662.             end
  663.             refreshElements()
  664.             redrawList()
  665.           end
  666.           totalWidth = totalWidth+#options[i][1]+1
  667.         end
  668.       end
  669.     elseif eArgs[1] == "mouse_scroll" then
  670.       if eArgs[2] > 0 then --Scroll up
  671.         if page > 1 then
  672.           page = page-1
  673.           redrawList()
  674.         end
  675.       else -- Scroll down
  676.         if page < pages then
  677.           page = page+1
  678.           redrawList()
  679.         end
  680.       end
  681.     end
  682.   end
  683. end
  684.  
  685. local function drawHelp()
  686.   displayList( "Help", {
  687.     {"Help",{"h - Toggle Help (This screen)"}},
  688.     {"General",{
  689.       "x - Switch heading position",
  690.       "z - Change background",
  691.       "w - Edit default",
  692.       "q - Save and Exit"
  693.     }},
  694.     {"Elements",{
  695.       "c - Create new Element",
  696.       "s - Hide/Show Click Area Borders",
  697.       "a - View list of all Elements",
  698.       "Left Click - Select Element",
  699.       "Right Click - Edit Element"
  700.     }},
  701.     {"While an Element is selected",{
  702.       "d - Delete selected Element",
  703.       "e - Edit Element",
  704.       "Arrow keys/Drag Center - Move",
  705.       "Drag 'R' - Resize"
  706.     }}
  707.   }, nil, keys.h)
  708. end
  709.  
  710. local function deleteElement(name,sType)
  711.   if option("Delete '"..name.."'?",{"Delete","Cancel"},{{colors.white,colors.red}}) == "Delete" then
  712.     screen[sType][name] = nil
  713.     return true
  714.   end
  715.   return false
  716. end
  717.  
  718. local function editElementStates(object)
  719.   local listTop = 3
  720.   local listBottom = h-1
  721.   local listLeft = 2
  722.   local listRight = w-1
  723.   local optionWidth = 0
  724.   local numStates = {}
  725.   local states = object.states
  726.  
  727.   local function redrawStatesScreen()
  728.     color(settings.listText,settings.listBackground)
  729.     term.clear()
  730.     drawHeading("Edit States",true)
  731.     local i = 1
  732.     numStates = {}
  733.     for a,b in pairs(states) do
  734.       if a == object.state then
  735.         term.setCursorPos(1,listTop+i-1) color(colors.lightBlue,settings.listBackground) term.write("*")
  736.       end
  737.       color(settings.listText,settings.listBackground)
  738.       term.setCursorPos(listLeft,listTop+i-1)
  739.       term.write(a)
  740.       term.setCursorPos(listRight-(#"[  ] [  ]")+1,listTop+i-1)
  741.       term.write("[") color(nil,b.text) term.write("  ") color(nil,settings.listBackground) term.write("] ")
  742.       term.write("[") color(nil,b.back) term.write("  ") color(nil,settings.listBackground) term.write("]")
  743.       numStates[i] = a
  744.       i = i+1
  745.     end
  746.     term.setCursorPos(listLeft,listTop-1) color(colors.lightGray) term.write("Name")
  747.     term.setCursorPos(listRight-(#"[Text] [Back]")+1,listTop-1) term.write("[Text] [Back]")
  748.     color(colors.lightGray,colors.white) printC("Enter to save",h)
  749.     if #numStates < listBottom-listTop then
  750.       printC("Right click to select",h-1)
  751.       color(colors.white,colors.lime) printC("New State",listTop+i-1)
  752.     else
  753.       printC("Max states!",h-1)
  754.     end
  755.   end
  756.    
  757.   redrawStatesScreen()
  758.  
  759.   while true do
  760.     local eArgs = {os.pullEvent()}
  761.     if eArgs[1] == "key" then
  762.       if eArgs[2] == keys.enter then
  763.         return
  764.       end
  765.     elseif eArgs[1] == "mouse_click" then
  766.       if eArgs[4] >= listTop and eArgs[4]-listTop < #numStates then -- clicked a state
  767.         local curName = numStates[(eArgs[4]-listTop+1)]
  768.         if eArgs[2] == 1 then -- left click, edit
  769.           local choice = option("Edit "..curName,{"Rename","Change Text","Change Back","Delete","Cancel"},{{},{},{},{nil,colors.red},{nil,colors.red}})
  770.           redrawStatesScreen()
  771.           if choice == "Rename" then
  772.             local name = getInput("Rename State",true,curName)
  773.             if name ~= curName then
  774.               while states[name] ~= nil do
  775.                 name = getInput("That state exists",true,name)
  776.               end
  777.               states[name] = states[curName]
  778.               states[curName] = nil
  779.               object.state = object.state==curName and name or object.state -- Change current state if necesarry
  780.             end
  781.           elseif choice == "Change Text" then
  782.             states[curName].text = getColor("Change Text")
  783.           elseif choice == "Change Back" then
  784.             states[curName].back = getColor("Change Back")
  785.           elseif choice == "Delete" then
  786.             if option("Delete "..curName.."?",{"Yes","No"},{{},{nil,colors.red}}) == "Yes" then
  787.               if #numStates == 1 then
  788.                 redrawStatesScreen()
  789.                 option("Can't delete last state!",{"Ok"})
  790.               else
  791.                 states[curName] = nil
  792.                 object.state = object.state==curName and numStates[1] or object.state -- Change current state if necesarry
  793.               end
  794.             end
  795.           end
  796.         elseif eArgs[2] == 2 then -- right click, select as default
  797.           object.state = curName
  798.         end
  799.         redrawStatesScreen()
  800.       elseif eArgs[4] == #numStates+listTop and #numStates < listBottom-listTop then -- Add state
  801.         local name = getInput("Create State",true)
  802.         while states[name] ~= nil do
  803.           name = getInput("That state exists",true,name)
  804.         end
  805.         states[name] = {
  806.           text = getColor("Select Text Color"),
  807.           back = getColor("Select Back Color")
  808.         }
  809.         redrawStatesScreen()
  810.       end
  811.     end
  812.   end
  813. end
  814.  
  815. local function editElement(name,sType,data,disableNameEdit)
  816.   local left,right,top,bottom = 2,w-1,3,h-1
  817.   local saveKey,dispSaveKey = keys.enter,h
  818.   local curLine = top
  819.   data = data or screen[sType][name]
  820.  
  821.   local function drawText(name,text,textColor,canEdit,editText)
  822.     term.setCursorPos(left,curLine) color(colors.lightGray,colors.white) if name then term.write(name..":") end
  823.     color(textColor or colors.black) term.write(text)
  824.     if canEdit then
  825.       term.setCursorPos(right-#tostring(editText or "Edit")+1,curLine) color(colors.white,colors.lightBlue) term.write(editText or "Edit")
  826.     end
  827.     curLine=curLine + 1
  828.   end
  829.  
  830.   local function redrawEditScreen()
  831.     curLine = top
  832.     color(colors.black,colors.white) term.clear()
  833.     drawHeading("Edit Element",true)
  834.     color(colors.lightGray,colors.white) printC("Press Enter to save",dispSaveKey)
  835.    
  836.     drawText("Name",name,nil,not disableNameEdit)
  837.     drawText("Type",typeToString(sType))
  838.     drawText("Points","",nil,true)
  839.     drawText(nil,"("..data.minX..","..data.minY.."),("..data.maxX..","..data.maxY..")")
  840.    
  841.     if sType == "objects" then
  842.       curLine = curLine+1 drawText("Text",data.text or "None",data.text and colors.black or colors.lightGray,true)
  843.       curLine = curLine+1 drawText("Clickable",tostring(data.clickable),data.clickable and colors.lime or colors.red,true,"Toggle")
  844.       curLine = curLine+1 drawText("Visible",tostring(data.visible),data.visible and colors.lime or colors.red,true,"Toggle")
  845.       local numStates = 0
  846.       for a,b in pairs(data.states) do numStates = numStates + 1 end
  847.       curLine = curLine+1 drawText("States",numStates,nil,true)
  848.     end
  849.   end
  850.  
  851.   redrawEditScreen()
  852.   while true do
  853.     local eArgs = {os.pullEvent()}
  854.     if eArgs[1] == "mouse_click" then
  855.       if eArgs[4] == top and not disableNameEdit then --Name
  856.         local input = getInput("Change Name",true,name)
  857.         if input ~= name then
  858.           while screen[sType][input] ~= nil do
  859.             input = getInput("Already exists!",true,input)
  860.           end
  861.           screen[sType][input] = screen[sType][name]
  862.           screen[sType][name] = nil
  863.           name = input
  864.           selected = {}
  865.           redrawScreen(defaultHeading)
  866.         end
  867.         redrawEditScreen()
  868.       elseif eArgs[4] == top+2 then --Edit points
  869.         data.minX = getNum("Enter Point 1 x",data.minX)
  870.         data.minY = getNum("Enter Point 1 y",data.minY)
  871.         data.maxX = getNum("Enter Point 2 x",data.maxX)
  872.         data.maxY = getNum("Enter Point 2 y",data.maxY)
  873.         if data.maxY < data.minY then
  874.           local temp = data.maxY
  875.           data.maxY = data.minY
  876.           data.minY = temp
  877.         end
  878.         if data.maxX < data.minX then
  879.           local temp = data.maxX
  880.           data.maxX = data.minX
  881.           data.minX = temp
  882.         end
  883.         redrawEditScreen()
  884.       elseif sType == "objects" then
  885.         if eArgs[4] == top+5 then --Edit text
  886.           local input
  887.           if data.text then --Has text
  888.             input = option("Edit Text",{"Edit","Delete","Cancel"},{{},{nil,colors.red},{nil,colors.red}})
  889.             redrawEditScreen()
  890.             if input == "Edit" then
  891.               data.text = getInput("Edit Text",true,data.text)
  892.             elseif input == "Delete" then
  893.               data.text = nil
  894.             end
  895.           else --No text set
  896.             data.text = getInput("Edit Text",true)
  897.           end
  898.           redrawEditScreen()
  899.         elseif eArgs[4] == top+7 then --Toggle clickable
  900.           data.clickable = not data.clickable
  901.           redrawEditScreen()
  902.         elseif eArgs[4] == top+9 then --Toggle visible
  903.           data.visible = not data.visible
  904.           redrawEditScreen()
  905.         elseif eArgs[4] == top+11 then --Edit states
  906.           editElementStates(data)
  907.           redrawEditScreen()
  908.         end
  909.       end
  910.     elseif eArgs[1] == "key" and eArgs[2] == saveKey then
  911.       return
  912.     end
  913.   end
  914. end
  915.  
  916. local function newElement()
  917.   local element = {}
  918.   local sType = option("Create... ",{"Object","Click Area","Cancel"},{{},{},{nil,colors.red}})
  919.   redrawScreen()
  920.  
  921.   if sType == "Cancel" then
  922.     redrawScreen()
  923.     return
  924.   end
  925.  
  926.   element.name = getInput("  Enter "..sType.." name:  ",true)
  927.   while screen[stringToType(sType)][element.name] do
  928.     element.name = getInput(" That "..sType.." exists: ",true)
  929.   end
  930.  
  931.   fillTable(element,default[stringToType(sType)])
  932.  
  933.   redrawScreen("Click and drag to create")
  934.   while true do --Get positions of element
  935.     local eArgs = {os.pullEvent("mouse_click")}
  936.     if eArgs[4] ~= getHeadingY() then
  937.       element.minX = eArgs[3]
  938.       element.minY = eArgs[4]
  939.       element.maxX = eArgs[3]
  940.       element.maxY = eArgs[4]
  941.       selected = {stringToType(sType),element.name}
  942.       lastClick = {true,eArgs[3],eArgs[4]}
  943.       screen[stringToType(sType)][element.name] = element
  944.       redrawScreen(sType.." "..element.name)
  945.       return
  946.     end
  947.   end
  948. end
  949.  
  950. local function load(path)
  951.   if not fs.exists(path) then
  952.     printError("That path doesn't exist")
  953.     return false
  954.   elseif fs.isDir(path) then
  955.     printError("That's a directory!")
  956.     return false
  957.   end
  958.   print("Attempting to load from path...")
  959.   local env = {
  960.     addClickArea = function(data) screen.clickAreas[data.name] = data end,
  961.     addObject = function(data) if data.states == nil or data.visible == nil then error("This file uses an old save format!") end screen.objects[data.name] = data end
  962.   }
  963.   setmetatable(env, {__index = function() return function() end end})
  964.  
  965.   local func, err = loadfile(path,env)
  966.   if err then
  967.     printError("Unable to load: "..(err~="" and err or "Unknown Cause"))
  968.     return false
  969.   end
  970.   local state,err = pcall(func)
  971.   if not state then
  972.     printError("Unable to load: "..(err~=nil and err or "Unknown Cause"))
  973.     return false
  974.   end
  975.   loadedFileName = path
  976.   return true
  977. end
  978.  
  979. local function save()
  980.   redrawScreen()
  981.   local fPath = getInput("Enter path for file",true,loadedFileName)
  982.   while fs.exists(fPath) and not path == loadedFileName do
  983.     fPath = getInput("That path already exists",true,fPath)
  984.   end
  985.   redrawScreen()
  986.   local f = fs.open(fPath,"w")
  987.   if not f then option("Unable to open path",{"Ok"}) return false end
  988.   f.writeLine("--[[")
  989.   f.writeLine("Created with HPWebcamAble's Simple Screen Maker")
  990.   f.writeLine("More info here: "..forumPostLink)
  991.   f.writeLine("]]")
  992.   local function serialize(tbl)
  993.     return textutils.serialize(tbl):gsub("\n"," "):gsub(" ","") -- Remove the newlines
  994.   end
  995.   local function saveElements(elements,funcName)
  996.     for name,data in pairs(elements) do
  997.       local saveString = funcName.."({"
  998.       for key,value in pairs(data) do
  999.         if key == "name" then
  1000.           saveString = saveString.."name="..[["]]..value..[[", ]]
  1001.         else
  1002.           saveString = saveString..key.."="
  1003.           if type(value) == "string" then
  1004.             saveString = saveString..[["]]..tostring(value)..[[", ]]
  1005.           elseif type(value) == "table" then
  1006.             saveString = saveString..serialize(value)..", "
  1007.           else
  1008.             saveString = saveString..tostring(value)..", "
  1009.           end
  1010.         end
  1011.       end
  1012.       f.writeLine(saveString.."})")
  1013.     end
  1014.   end
  1015.   saveElements(screen.objects,"addObject")
  1016.   saveElements(screen.clickAreas,"addClickArea")
  1017.  
  1018.   f.close()
  1019.   return true
  1020. end
  1021.  
  1022.  
  1023. --=== Program ===--
  1024. local args = {...}
  1025. if not term.isColor() then
  1026.   printError("This program requires an Advanced Computer")
  1027.   return
  1028. elseif not _CC_VERSION and not _HOST then
  1029.   printError("This program requires ComputerCraft 1.74 or newer")
  1030.   return
  1031. elseif args[1] == "help" then
  1032.   print("Simple Screen Maker")
  1033.   print("This program lets you quickly create 'screens' from HPWebcamAble's Screen API")
  1034.   print()
  1035.   print("Usages:")
  1036.   print(shell.getRunningProgram())
  1037.   print("  Create a new Screen Object")
  1038.   print(shell.getRunningProgram().." <file path to load>")
  1039.   print("  Load an existing Screen Object")
  1040.   print()
  1041.   print("Need help using the program? Check out the documentation:")
  1042.   print(forumPostLink)
  1043.   return
  1044. elseif args[1] then
  1045.   if not load(args[1]) then
  1046.     return
  1047.   end
  1048. end
  1049.  
  1050.  
  1051. local function main()
  1052.   redrawScreen()
  1053.   while true do
  1054.     local eArgs = {os.pullEvent()}
  1055.     if eArgs[1] == "mouse_click" then --Click the mouse
  1056.       local elements = checkPos(eArgs[3],eArgs[4])
  1057.       if #selected > 0 then --Something is selected
  1058.         if #elements > 1 then --Multiple things clicked
  1059.           local objects = {}
  1060.           local clickAreas = {}
  1061.           for i = 1, #elements do
  1062.             if elements[i][1] == "clickAreas" then
  1063.               table.insert(clickAreas,elements[i][3])
  1064.             else
  1065.               table.insert(objects,elements[i][3])
  1066.             end
  1067.           end
  1068.           local toSelect = displayList("Multiple Elements clicked",{{"Objects",function() return objects end,{}},{"Click Areas",function() return clickAreas end,{}}},{{"Select",nil,nil,function(name,temp,sType) return {name,sType} end,{}}},keys.enter)
  1069.           if toSelect then
  1070.             selected = {stringToType(toSelect[2]),toSelect[1]}
  1071.           end
  1072.           redrawScreen(toSelect and typeToString(stringToType(toSelect[2])).." "..toSelect[1] or nil)
  1073.         elseif #elements == 1 then --Only 1 element clicked
  1074.           if elements[1][3] == selected[2] and elements[1][1] == typeToString(selected[1]) then --Click in the selected element
  1075.             if eArgs[2] == 1 then --Left Click
  1076.               lastClick = {eArgs[3] == screen[selected[1]][selected[2]].maxX and eArgs[4] == screen[selected[1]][selected[2]].maxY,eArgs[3],eArgs[4]}
  1077.             elseif eArgs[2] == 2 then --Right Click
  1078.               editElement(selected[2],selected[1])
  1079.               redrawScreen()
  1080.             end
  1081.           else --Click is outside of currently selected element            
  1082.             selected = {elements[1][1],elements[1][3]}
  1083.             if eArgs[2] == 1 then --Left Click  
  1084.               lastClick = {eArgs[3] == screen[selected[1]][selected[2]].maxX and eArgs[4] == screen[selected[1]][selected[2]].maxY,eArgs[3],eArgs[4]}
  1085.               redrawScreen(elements[1][2].." "..elements[1][3])
  1086.             elseif eArgs[2] == 2 then --Right Click
  1087.               editElement(selected[2],selected[1])
  1088.               redrawScreen()
  1089.             end            
  1090.           end
  1091.         else --Nothing clicked
  1092.           selected = {}
  1093.           lastClick = {}
  1094.           redrawScreen(defaultHeading)
  1095.         end
  1096.       else --Nothing is selected
  1097.         if #elements > 1 then --Multiple things clicked
  1098.           local objects = {}
  1099.           local clickAreas = {}
  1100.           for i = 1, #elements do
  1101.             if elements[i][1] == "clickAreas" then
  1102.               table.insert(clickAreas,elements[i][3])
  1103.             else
  1104.               table.insert(objects,elements[i][3])
  1105.             end
  1106.           end
  1107.           local toSelect = displayList("Multiple Elements clicked",{{"Objects",function() return objects end,{}},{"Click Areas",function() return clickAreas end,{}}},{{"Select",nil,nil,function(name,temp,sType) return {name,sType} end,{}}},keys.enter)
  1108.           if toSelect then
  1109.             selected = {stringToType(toSelect[2]),toSelect[1]}
  1110.           end
  1111.           redrawScreen(toSelect and typeToString(stringToType(toSelect[2])).." "..toSelect[1] or nil)
  1112.         elseif #elements == 1 then --Only 1 element clicked
  1113.           selected = {elements[1][1],elements[1][3]}
  1114.           if eArgs[2] == 1 then --Left Click
  1115.             lastClick = {eArgs[3] == screen[selected[1]][selected[2]].maxX and eArgs[4] == screen[selected[1]][selected[2]].maxY,eArgs[3],eArgs[4]}
  1116.             redrawScreen(elements[1][2].." "..elements[1][3])
  1117.           elseif eArgs[2] == 2 then --Right Click
  1118.             editElement(selected[2],selected[1])
  1119.             redrawScreen()
  1120.           end
  1121.         end
  1122.       end
  1123.     elseif eArgs[1] == "key" then --Key hit
  1124.       if eArgs[2] == keys.h then --Show help screen
  1125.         drawHelp()
  1126.         redrawScreen()
  1127.       elseif eArgs[2] == keys.e then --Edit an object
  1128.         if #selected > 0 then
  1129.           editElement(selected[2],selected[1])
  1130.         end
  1131.         redrawScreen()
  1132.       elseif eArgs[2] == keys.q then --Exit program
  1133.         local choice = option("Exit SSM",{"Save and exit","Exit without saving","Cancel"},{{nil,nil},{nil,colors.red},{nil,colors.red}})
  1134.         if choice == "Save and exit" then --Save and exit
  1135.           if save() then
  1136.             return
  1137.           else
  1138.             redrawScreen()
  1139.           end
  1140.         elseif choice == "Exit without saving" then --Dont save
  1141.           return
  1142.         end
  1143.         redrawScreen()
  1144.       elseif eArgs[2] == keys.z then --Change background
  1145.         local choice
  1146.         if background then
  1147.           choice = option("Change Background",{"Change solid color","Move Paint Image","Clear Paint Image","Cancel"},{{nil,nil},{nil,nil},{nil,colors.red},{nil,colors.red}})
  1148.         else
  1149.           choice = option("Change Background",{"Change solid color","Load Paint File","Cancel"},{{nil,nil},{nil,nil},{nil,colors.red}})
  1150.         end
  1151.         redrawScreen()
  1152.        
  1153.         if choice == "Change solid color" then
  1154.           settings.background = getColor("Select Color")
  1155.         elseif choice == "Move Paint Image" then
  1156.           redrawScreen("Arrow keys to move image")
  1157.           while true do
  1158.             local event = {os.pullEvent("key")}
  1159.             if event[2] == keys.up then
  1160.               backY = backY-1
  1161.               redrawScreen("Hit Enter to confirm")
  1162.             elseif event[2] == keys.down then
  1163.               backY = backY+1
  1164.               redrawScreen("Hit Enter to confirm")
  1165.             elseif event[2] == keys.left then
  1166.               backX = backX-1
  1167.               redrawScreen("Hit Enter to confirm")
  1168.             elseif event[2] == keys.right then
  1169.               backX = backX+1
  1170.               redrawScreen("Hit Enter to confirm")
  1171.             elseif event[2] == keys.enter then
  1172.               redrawScreen(defaultHeading)
  1173.               break
  1174.             end
  1175.           end
  1176.         elseif choice == "Clear Paint Image" then
  1177.           background = nil
  1178.         elseif choice == "Load Paint File" then
  1179.           local input = shell.resolve( getInput("Enter File Path",true) )
  1180.           redrawScreen()
  1181.           if fs.exists(input) and not fs.isDir(input) then
  1182.             background = paintutils.loadImage(input)
  1183.             backX,backY = 1,1
  1184.             if type(background) ~= "table" then
  1185.               option("Not a valid Paint File",{"Ok"})
  1186.               background = nil
  1187.             end
  1188.           else
  1189.             option("Not a valid Paint File",{"Ok"})
  1190.           end
  1191.         end
  1192.        
  1193.         redrawScreen()
  1194.       elseif eArgs[2] == keys.x then --Move the heading
  1195.         headingPos = not headingPos
  1196.         redrawScreen()
  1197.       elseif eArgs[2] == keys.c then --Make a new object/click area
  1198.         newElement()
  1199.         --newElement redraws the screen
  1200.       elseif eArgs[2] == keys.s then --Toggle Click area visibility
  1201.         drawClickAreas = not drawClickAreas
  1202.         redrawScreen("Click Areas are ".. (drawClickAreas and "" or "not") .." visible")
  1203.       elseif eArgs[2] == keys.a then --Element list
  1204.         local heading
  1205.         local sType
  1206.         if option("View list of...",{"Objects","Click Areas"}) == "Objects" then
  1207.           heading = "Objects"
  1208.           sType = "objects"
  1209.         else
  1210.           heading = "Click Areas"
  1211.           sType = "clickAreas"
  1212.         end
  1213.         displayList(heading,{{false,getNames,{sType}}},{{"Edit",nil,nil,editElement,{sType}},{"Delete",nil,colors.red,deleteElement,{sType}}},keys.enter)
  1214.         redrawScreen()
  1215.       elseif eArgs[2] == keys.w then
  1216.         local choice = option("Edit default",{"Object","Click Area","Cancel"},{{},{},{nil,colors.red}})
  1217.         if choice ~= "Cancel" then
  1218.           editElement("Default "..choice,stringToType(choice),default[stringToType(choice)],true)
  1219.         end
  1220.         redrawScreen()
  1221.       elseif #selected > 0 then --Key hit while somthing was selected
  1222.         if eArgs[2] == keys.right then --move right
  1223.           screen[selected[1]][selected[2]].minX = screen[selected[1]][selected[2]].minX+1
  1224.           screen[selected[1]][selected[2]].maxX = screen[selected[1]][selected[2]].maxX+1
  1225.           redrawScreen()
  1226.         elseif eArgs[2] == keys.left then --move left
  1227.           screen[selected[1]][selected[2]].minX = screen[selected[1]][selected[2]].minX-1
  1228.           screen[selected[1]][selected[2]].maxX = screen[selected[1]][selected[2]].maxX-1
  1229.           redrawScreen()
  1230.         elseif eArgs[2] == keys.up then --move up
  1231.           screen[selected[1]][selected[2]].minY = screen[selected[1]][selected[2]].minY-1
  1232.           screen[selected[1]][selected[2]].maxY = screen[selected[1]][selected[2]].maxY-1
  1233.           redrawScreen()
  1234.         elseif eArgs[2] == keys.down then --move down
  1235.           screen[selected[1]][selected[2]].minY = screen[selected[1]][selected[2]].minY+1
  1236.           screen[selected[1]][selected[2]].maxY = screen[selected[1]][selected[2]].maxY+1
  1237.           redrawScreen()
  1238.         elseif eArgs[2] == keys.d then --delete
  1239.           local result = deleteElement(selected[2],selected[1])
  1240.           if result then
  1241.             selected = {}
  1242.           end
  1243.           redrawScreen(result and defaultHeading or nil)
  1244.         end        
  1245.       end
  1246.     elseif eArgs[1] == "mouse_drag" then --Mouse was dragged
  1247.       if #selected > 0 and #lastClick > 0 then --Is able to drag
  1248.         if lastClick[1] then --resize
  1249.           if eArgs[3] >= screen[selected[1]][selected[2]].minX then
  1250.             screen[selected[1]][selected[2]].maxX = eArgs[3]
  1251.           end
  1252.           if eArgs[4] >= screen[selected[1]][selected[2]].minY then
  1253.             screen[selected[1]][selected[2]].maxY = eArgs[4]
  1254.           end
  1255.         else --Move
  1256.           screen[selected[1]][selected[2]].minY = screen[selected[1]][selected[2]].minY-(lastClick[3]-eArgs[4])
  1257.           screen[selected[1]][selected[2]].maxY = screen[selected[1]][selected[2]].maxY-(lastClick[3]-eArgs[4])
  1258.           screen[selected[1]][selected[2]].minX = screen[selected[1]][selected[2]].minX-(lastClick[2]-eArgs[3])
  1259.           screen[selected[1]][selected[2]].maxX = screen[selected[1]][selected[2]].maxX-(lastClick[2]-eArgs[3])
  1260.           lastClick[2] = eArgs[3]
  1261.           lastClick[3] = eArgs[4]
  1262.         end
  1263.         redrawScreen()
  1264.       end
  1265.     end
  1266.   end
  1267. end
  1268.  
  1269. local state,err = pcall(main) -- Run the actual program
  1270.  
  1271. if err and not err:find("Terminated") then
  1272.   term.redirect(originalTerm)
  1273.   color(colors.white,colors.black)
  1274.   term.clear()
  1275.   printC("An error occured:",1)
  1276.   term.setCursorPos(1,3)
  1277.   print(err)
  1278. else
  1279.   color(colors.white,colors.black)
  1280.   term.clear()
  1281.   term.setCursorPos(1,1)
  1282. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement