Encreedem

Graffiti v1.1.1

Jul 15th, 2013
262
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 34.83 KB | None | 0 0
  1. -- v1.1.1
  2.  
  3. -- fields for users
  4. local userFunctions = {}
  5. local userLists = {}
  6. local selectedItems = {}
  7. local userInputs = {}
  8.  
  9. --monitor
  10. local monitorSide = "right"
  11. local monitor = nil
  12.  
  13. -- texts
  14. local refreshText = "Refresh"
  15. local backText = "Back"
  16. local doneString = "Done"
  17.  
  18. -- colors
  19. local buttonDefaultColor = colors.red
  20. local buttonPressedColor = colors.lime
  21. local sliderLowValueColor = colors.red
  22. local sliderMediumValueColor = colors.yellow
  23. local sliderHighValueColor = colors.lime
  24. local inputDefaultColor = colors.white
  25. local inputPressedColor = colors.yellow
  26. local listDefaultColor = colors.lightBlue
  27. local listSelectedColor = colors.orange
  28. local editorMoveColor = colors.magenta
  29. local editorScaleColor = colors.pink
  30.  
  31. -- editor options
  32. local editMode = false
  33. local showEditorOptions = false
  34. local editActions = { "Design", "Attributes", "Delete" }
  35. local lastScreen = "mainScreen"
  36.  
  37. -- other
  38. local args = { ... }
  39. local quit = false
  40. local maxX, maxY = 51, 19
  41. local autoLoadObjects = true
  42. local changeButtonColor = true
  43. local screens = {}
  44. screens.mainScreen = {}
  45. local currentScreen = "mainScreen"
  46. local objectTypes = { "Button", "Text", "Variable", "Slider", "Input", "List" }
  47. local editorFunctions = {}
  48.  
  49. -- Displays a star in the upper left corner for a
  50. -- short amount of time. Used when you want to see
  51. -- when something certain happens.
  52. -- Should only be used when you are desperately
  53. -- looking for a bug.
  54. function extremeDebug()
  55.   term.setCursorPos(1, 1)
  56.   term.write("*")
  57.   os.sleep(0.5)
  58.   term.setCursorPos(1, 1)
  59.   term.write(" ")
  60.   os.sleep(0.5)
  61. end
  62.  
  63. -- user variables
  64. local randomValue= 50
  65.  
  66. -- user functions
  67.  
  68. function userFunctions.setRandomValue()
  69.   randomValue = math.random(100)
  70. end
  71.  
  72. -- user lists
  73.  
  74. userLists.testList = {
  75.   "Testitem 1",
  76.   "Testitem 2",
  77.   "Testitem 3"
  78. }
  79.  
  80. -- Define the value of a variable-object.
  81. function getVariableValue(variable)
  82.   if (variable == nil or variable.objType ~= "Variable") then
  83.     return
  84.   end
  85.  
  86.   variableID = variable.varID
  87.   if (variableID == "testVariable") then
  88.     return "Variable";
  89.   elseif (variableID == "Time") then
  90.     return textutils.formatTime(os.time(), true)
  91.   end
  92.  
  93.   return ""
  94. end
  95.  
  96. -- Definie the value of a slider-object
  97. -- 0: empty; 100: full
  98. function getSliderValue(slider)
  99.   if (slider == nil or slider.objType ~= "Slider") then
  100.     return
  101.   end
  102.  
  103.   sliderID = slider.sliderID
  104.  
  105.   if (sliderID == "testSlider") then
  106.     return 87;
  107.   elseif (sliderID == "randomSlider") then
  108.     return randomValue
  109.   end
  110. end
  111.  
  112. -- WARNING! Everything below this comment
  113. -- shouldn't be edited! If you do so and the program
  114. -- doesn't work any more then it's your fault!
  115.  
  116. function readUserInput(message, isPassword)
  117.   term.restore()
  118.   print(message)
  119.  
  120.   if isPassword  then
  121.     ret = read("*")
  122.   else
  123.     ret = read()
  124.   end
  125.  
  126.   term.redirect(monitor)
  127.   return ret
  128. end
  129.  
  130. -- Redirects the input to the computer and lets
  131. -- the user enter something. The result will be
  132. -- in the userInputs array with the inputID as the
  133. -- key.
  134. function getUserInput(inputObject)
  135.   if (inputObject == nil or inputObject.objType ~= "Input") then
  136.     return
  137.   end
  138.  
  139.   x = inputObject.x
  140.   y = inputObject.y
  141.   inputID = inputObject.inputID
  142.   message = inputObject.message
  143.   isPassword = (inputObject.isPassword == nil) and false or inputObject.isPassword
  144.   maxLength = inputObject.maxLength
  145.  
  146.   existingInput = userInputs[inputID]
  147.   if (existingInput ~= nil) then -- Clear the text on the input object.
  148.     term.setCursorPos(x, y)
  149.     for i = -1, string.len(existingInput) do
  150.       term.write(" ")
  151.     end
  152.    
  153.     userInputs[inputID] = nil
  154.   end
  155.  
  156.   -- make the input-object yellow
  157.   term.setCursorPos(x, y)
  158.   term.setBackgroundColor(colors.yellow)
  159.   term.write("  ")
  160.   term.setBackgroundColor(colors.black)
  161.  
  162.   userInput = readUserInput(message, isPassword)
  163.   if (userInput ~= nil) then
  164.     userInputs[inputID] = userInput
  165.   end
  166.  
  167.   term.setCursorPos(x, y)
  168.   term.setBackgroundColor(colors.white)
  169.   term.setTextColor(colors.black)
  170.  
  171.   term.write(" ")
  172.   if (userInput ~= nil and userInput ~= "") then
  173.     if isPassword then
  174.       for i = 1, string.len(userInput) do
  175.         term.write("*")
  176.       end
  177.     else
  178.       term.write(userInput)
  179.     end
  180.   end
  181.  
  182.   term.write(" ")
  183.   term.setBackgroundColor(colors.black)
  184.   term.setTextColor(colors.white)
  185.  
  186.   return ret
  187. end
  188.  
  189. -- Checks if dir is a valid direction-string
  190. function isValidDirection(dir)
  191.   if (dir == "left" or
  192.       dir == "up" or
  193.       dir == "right" or
  194.       dir == "down") then
  195.     return true
  196.   end
  197.  
  198.   return false
  199. end
  200.  
  201. -- display objects region start --
  202.  
  203. function showBox(x, y, width, height, color)
  204.   for row = x, x + width - 1 do
  205.     for col = y, y + height - 1 do
  206.       paintutils.drawPixel(row, col, color)
  207.     end
  208.   end
  209.  
  210.   term.setBackgroundColor(colors.black)
  211. end
  212.  
  213. -- Displays the text on the screen.
  214. function showText(textObject)
  215.   if (textObject.objType ~= "Text") then
  216.     return
  217.   end
  218.  
  219.   x = textObject.x
  220.   y = textObject.y
  221.   text = textObject.text
  222.   assert(x, "Text: X-coordinate has to be set!")
  223.   assert(y, "Text: Y-coordinate has to be set!")
  224.  
  225.   term.setCursorPos(x, y)
  226.   term.write(text)
  227. end
  228.  
  229. -- Displays the slider on the screen.
  230. function showSlider(slider, fillPercentage)
  231.   if (slider == nil or slider.objType ~= "Slider") then
  232.     return
  233.   end
  234.  
  235.   x = slider.x
  236.   y = slider.y
  237.   length = slider.length
  238.   direction = (isValidDirection(slider.direction)) and slider.direction or "right"
  239.  
  240.   startSymbol, endSymbol = "<", ">"
  241.   addX, addY = 1, 0 -- Sets the direction of the slider, therefore it could even be diagonal.
  242.  
  243.   if (direction == "left") then
  244.     addX, addY = -1, 0
  245.     startSymbol, endSymbol = ">", "<"
  246.     term.setCursorPos(x - length, y)
  247.     term.write(endSymbol)
  248.   elseif (direction == "up") then
  249.     addX, addY = 0, -1
  250.     startSymbol, endSymbol = "V", "^"
  251.     term.setCursorPos(x, y - length)
  252.     term.write(endSymbol)
  253.   elseif (direction == "right") then
  254.     addX, addY = 1, 0
  255.     startSymbol, endSymbol = "<", ">"
  256.     term.setCursorPos(x + length, y)
  257.     term.write(endSymbol)
  258.   elseif (direction == "down") then
  259.     addX, addY = 0, 1
  260.     startSymbol, endSymbol = "^", "V"
  261.     term.setCursorPos(x, y + length)
  262.     term.write(endSymbol)
  263.   else -- return if it's not a valid direction, even if I checked it before
  264.     return
  265.   end
  266.  
  267.   term.setCursorPos(x, y)
  268.   term.write(startSymbol)
  269.  
  270.   if (fillPercentage ~= nil) then
  271.     if (fillPercentage < 33) then
  272.       sliderColor = sliderLowValueColor
  273.     elseif (fillPercentage > 66) then
  274.       sliderColor = sliderHighValueColor
  275.     else
  276.       sliderColor = sliderMediumValueColor
  277.     end
  278.    
  279.     filled = math.floor((length / 100) * fillPercentage)
  280.     currentX = x + addX
  281.     currentY = y + addY
  282.    
  283.     for i = 1, filled do
  284.       paintutils.drawPixel(currentX, currentY, sliderColor)
  285.       currentX = currentX + addX
  286.       currentY = currentY + addY
  287.     end
  288.   end
  289.  
  290.   term.setBackgroundColor(colors.black)
  291. end
  292.  
  293. -- Displays the given button on the screen.
  294. function showButton(button, color)
  295.   if (button == nil or button.objType ~= "Button") then
  296.     return
  297.   end
  298.  
  299.   x = button.x
  300.   y = button.y
  301.   width = button.width
  302.   height = button.height
  303.   text = button.text
  304.  
  305.   showBox(x, y, width, height, color)
  306.  
  307.   -- Tries to center the text in the button.
  308.   textCol = x + math.floor((width - string.len(text)) / 2)
  309.   textRow = y + math.ceil(height / 2) - 1
  310.   term.setCursorPos(textCol, textRow)
  311.   term.setBackgroundColor(color)
  312.   term.write(text)
  313.  
  314.   term.setBackgroundColor(colors.black)
  315. end
  316.  
  317. -- Displays the input-object (two white spaces)
  318. function showInput(inputObject)
  319.   if (inputObject == nil or inputObject.objType ~= "Input") then
  320.     return
  321.   end
  322.  
  323.   inputId = inputObject.inputID
  324.   x = inputObject.x
  325.   y = inputObject.y
  326.  
  327.   term.setCursorPos(x, y)
  328.   term.setBackgroundColor(inputDefaultColor)
  329.   term.write(" ")
  330.   if (userInputs[inputID] ~= nil) then
  331.     term.write(userInputs[inputID])
  332.   end
  333.   term.write(" ")
  334.  
  335.   term.setBackgroundColor(colors.black)
  336. end
  337.  
  338. -- Used by "showList" and "showSelector" to
  339. -- determine how wide the list should be.
  340. function getLongestString(stringArray)
  341.   if (stringArray == nil or #stringArray == 0) then
  342.     return 0
  343.   end
  344.  
  345.   ret = 0
  346.  
  347.   for key, value in pairs(stringArray) do
  348.     length = string.len(value)
  349.     if (length > ret) then
  350.       ret = length
  351.     end
  352.   end
  353.  
  354.   return ret
  355. end
  356.  
  357. -- Displays a list on the monitor.
  358. function showList(listObject)
  359.   if (listObject == nil or listObject.objType ~= "List") then
  360.     return
  361.   end
  362.  
  363.   if (type(listObject.elements) == "string") then
  364.     listObject.elements = userLists[listObject.elements]
  365.   end
  366.  
  367.   x = listObject.x
  368.   y = listObject.y
  369.   elements = (listObject.elements ~= nil) and listObject.elements or { "empty" }
  370.   width = getLongestString(elements) + 2
  371.   listObject.width = width
  372.   height = #elements
  373.   listObject.height = height
  374.   elements = listObject.elements
  375.   listID = listObject.listID
  376.   isMultiselect = (listObject.isMultiselect ~= nil) and listObject.isMultiselect or false
  377.  
  378.   showBox(x, y, width, height, listDefaultColor)
  379.  
  380.   if (selectedItems[listID] == nil and isMultiselect) then
  381.     selectedItems[listID] = {  }
  382.     for index, elementKey in ipairs(elements) do
  383.       selectedItems[listID][elementKey] = false
  384.     end
  385.   end
  386.  
  387.   posY = 0
  388.   for key,element in pairs(elements) do
  389.     term.setCursorPos(x, y + posY)
  390.    
  391.     if (isMultiselect) then
  392.       if (selectedItems[listID][elements] == true) then
  393.         term.setBackgroundColor(listSelectedColor)
  394.       else
  395.         term.setBackgroundColor(listDefaultColor)
  396.       end
  397.     else
  398.       if (selectedItems[listID] == key) then
  399.         term.setBackgroundColor(listSelectedColor)
  400.       else
  401.         term.setBackgroundColor(listDefaultColor)
  402.       end
  403.     end
  404.    
  405.     term.write(" " .. element .. " ")
  406.     posY = posY + 1
  407.   end
  408.  
  409.   term.setBackgroundColor(colors.black)
  410. end
  411.  
  412. -- Displays a list and returns the field that the
  413. -- user touched.
  414. function showSelector(x, y, elements)
  415.   width = getLongestString(elements) + 2
  416.   height = #elements + 2 -- Elements + up and down
  417.   elementCount = #elements
  418.   displayCount = elementCount
  419.  
  420.   enoughXSpace = true
  421.   -- determine where the selector should actually be displayed
  422.   if (width > maxX) then -- Not enough monitors horizontally?
  423.     x = 1
  424.     enoughXSpace = false
  425.   elseif (maxX - x < width) then -- Not enough space to the right.
  426.     if (x >= width) then -- Let's see if there is space to the left.
  427.       x = x - width
  428.     else -- No space? Put the selector as much to the right as possible.
  429.       x = maxX - width
  430.       enoughXSpace = false
  431.     end
  432.   else -- Enough space to the right.
  433.     x = x + 1
  434.   end
  435.  
  436.   if (height > maxY - y) then -- Not enough space from y to bottom.
  437.     if ((maxY / 2) > y) then -- More space below y.
  438.       if enoughXSpace then
  439.         if (maxY < height) then -- Too small for the whole screen.
  440.           y = 1
  441.           displayCount = maxY - 2
  442.         else -- Enough space next to x and not too high.
  443.           y = maxY - height
  444.         end
  445.       else -- Can't display it next to the selected point.
  446.         y = y + 1
  447.         displayCount = maxY - y - 2
  448.       end
  449.     else -- More space above y.
  450.       if enoughXSpace then
  451.         if (y < height) then -- Not enough space from top to y.
  452.           if (maxY < height) then -- Too small for the whole screen.
  453.             y = 1
  454.             displayCount = maxY - 2
  455.           else -- Enough space next to x and not too high.
  456.             y = 1
  457.           end
  458.         else -- Enough space from top to y.
  459.           y = y - height + 1
  460.         end
  461.       else
  462.         y = 1
  463.         displayCount = y - 3
  464.       end
  465.     end
  466.   end
  467.  
  468.   term.setBackgroundColor(colors.black)
  469.  
  470.   -- Read the user input.
  471.   scroll = 1
  472.   right = x + width - 1
  473.   bottom = y + displayCount + 1
  474.  
  475.   finished = false
  476.   while not finished do
  477.     -- Display the actual selector.
  478.     showBox(x, y, width, height, listDefaultColor)
  479.    
  480.     term.setBackgroundColor(listDefaultColor)
  481.     middle = math.floor(width / 2)
  482.     term.setCursorPos(x + middle, y)
  483.     term.write("^")
  484.     term.setCursorPos(x + middle, bottom)
  485.     term.write("V")
  486.    
  487.     for i = 1, displayCount do
  488.       term.setCursorPos(x, y + i)
  489.       term.write(" " .. elements[i + scroll - 1] .. " ")
  490.     end
  491.     term.setBackgroundColor(colors.black)
  492.    
  493.     key, side, touchX, touchY = os.pullEvent("monitor_touch")
  494.    
  495.     if (touchX < x or touchX > right or touchY < y or touchY > bottom) then
  496.       selectedItem = nil
  497.       result = false
  498.       finished = true
  499.     else -- User touched the selector.
  500.       if (touchY == y) then -- up
  501.         if (scroll > 1) then -- Check if it makes sense to scroll up.
  502.           scroll = scroll - 1
  503.         end
  504.       elseif (touchY == bottom) then -- down
  505.         if (displayCount < elementCount) then
  506.           if (scroll <= elementCount - displayCount) then
  507.             scroll = scroll + 1
  508.           end
  509.         end
  510.       else
  511.         selectedItem = elements[touchY - y + scroll - 1]
  512.         result = true
  513.         finished = true
  514.       end
  515.     end
  516.   end
  517.  
  518.   showScreen(currentScreen)
  519.   return result
  520. end
  521.  
  522. -- Displays the text with red background colour.
  523. function showSimpleButton(x, y, text)
  524.   term.setCursorPos(x, y)
  525.   term.setBackgroundColor(colors.red)
  526.   term.write(text)
  527.   term.setBackgroundColor(colors.black)
  528. end
  529.  
  530. -- Displays the "Back"- and "Refresh"-Buttons
  531. function showDefaultButtons()
  532.   x = maxX - string.len(refreshText) + 1
  533.   showSimpleButton(x, maxY, refreshText)
  534.  
  535.   showSimpleButton(1, maxY, backText)
  536. end
  537.  
  538. -- display objects region end
  539.  
  540. -- Loads the values of all variables and sliders
  541. -- of the current screen.
  542. function loadObjects()
  543.   for objectID, object in pairs(screens[currentScreen]) do
  544.     objectType = object.objType
  545.     x = object.x
  546.     y = object.y
  547.    
  548.     if (objectType == "Variable") then
  549.       value = getVariableValue(object)
  550.       term.setCursorPos(x, y)
  551.       term.write(value)
  552.     elseif (objectType == "Slider") then
  553.       length = object.length
  554.       value = getSliderValue(object)
  555.       showSlider(object, value)
  556.     end
  557.   end
  558. end
  559.  
  560. -- Displays all objects of the selected screen.
  561. function showScreen(screenID)
  562.   term.clear()
  563.  
  564.   currentScreen = screenID
  565.  
  566.   if not editMode then
  567.     if (currentScreen == "mainScreen") then
  568.       backText = "Quit"
  569.     else
  570.       backText = "Back"
  571.     end
  572.   else
  573.     backText = "Quit"
  574.     refreshText = "Options"
  575.   end
  576.  
  577.   local screenObject
  578.   local objectType
  579.   if showEditorOptions then
  580.     screenObject = editorScreens[screenID]
  581.   else
  582.     screenObject = screens[screenID]
  583.   end
  584.  
  585.   for sObjectID, sObject in pairs(screenObject) do
  586.     objectType = sObject.objType
  587.    
  588.     if (objectType == "Button") then
  589.       showButton(sObject, buttonDefaultColor)
  590.     elseif (objectType == "Text") then
  591.       showText(sObject)
  592.     elseif (objectType == "Slider") then
  593.       showSlider(sObject, 0)
  594.     elseif (objectType == "Input") then
  595.       showInput(sObject)
  596.     elseif (objectType == "List") then
  597.       showList(sObject)
  598.     end
  599.   end
  600.  
  601.   if autoLoadObjects then
  602.     loadObjects()
  603.   end
  604.  
  605.   showDefaultButtons()
  606.  
  607.   term.setCursorPos(1, maxY)
  608. end
  609.  
  610. -- Waits until the user touches the monitor and
  611. -- if he touched a button, the function stored in
  612. -- it will be called.
  613. function getInput()
  614.   finished = false
  615.   key, side, x, y = os.pullEvent("monitor_touch")
  616.  
  617.   if (y == maxY) then -- Checking the default buttons
  618.     if (x <= string.len(backText)) then -- "Back"-Button pressed
  619.       if (currentScreen == "mainScreen" or editMode) then
  620.         quit = true
  621.       else
  622.         if (screens[currentScreen].parentScreen ~= nil) then
  623.           showScreen(screens[currentScreen].parentScreen)
  624.           finished = true
  625.         else
  626.           showScreen("mainScreen")
  627.           finished = true
  628.         end
  629.       end
  630.     elseif (x >= maxX - string.len(refreshText) and not editMode) then -- "Refresh"-Button pressed
  631.       showScreen(currentScreen)
  632.       finished = true
  633.     end
  634.   end
  635.  
  636.   if (finished == true or quit==true) then
  637.     return nil
  638.   end
  639.  
  640.   if editMode then
  641.     screenObject = editorScreens[currentScreen]
  642.   else
  643.     screenObject = screens[currentScreen]
  644.   end
  645.  
  646.   for sObjectID, sObject in pairs(screenObject) do
  647.     objectType = sObject.objType
  648.    
  649.     if (objectType == "Button") then
  650.       left = sObject.x
  651.       top = sObject.y
  652.       width = sObject.width
  653.       height = sObject.height
  654.       right = left + width
  655.       bottom = top + height
  656.      
  657.       if (x >= left and x < right and y >= top and y < bottom) then
  658.         if (sObject.funcType ~= nil and sObject.param ~= nil) then
  659.           callAction(sObject.funcType, sObject.param, sObject)
  660.           finished = true
  661.         end
  662.       end
  663.     elseif (objectType == "Input") then
  664.       left = sObject.x
  665.       top = sObject.y
  666.       inputID = sObject.inputID
  667.       message = sObject.message
  668.       isPassword = sObject.isPassword
  669.      
  670.       if ((x == left or x == left + 1) and y == top) then
  671.         getUserInput(sObject)
  672.       end
  673.     elseif (objectType == "List") then
  674.       left = sObject.x
  675.       top = sObject.y
  676.       width = sObject.width
  677.       height = #sObject.elements
  678.       right = left + width
  679.       bottom = top + height
  680.      
  681.       listID = sObject.listID
  682.       isMultiselect = sObject.isMultiselect
  683.      
  684.       if (x >= left and x < right and y >= top and y < bottom) then
  685.         if (isMultiselect) then
  686.           if (selectedItems[listID][y - top + 1]) then
  687.             selectedItems[listID][y - top + 1] = false
  688.           else
  689.             selectedItems[listID][y - top + 1] = true
  690.           end
  691.         else
  692.           selectedItems[listID] = y - top + 1
  693.         end
  694.        
  695.         showList(sObject)
  696.        
  697.         finished = true
  698.       end
  699.     end
  700.    
  701.     if (finished == true) then
  702.       break
  703.     end
  704.   end
  705.  
  706.   --print(key)
  707.   --print("X: " .. x .. ", Y: " .. y)
  708.   --print("max X: " .. maxX .. ", max Y: " .. maxY)
  709. end
  710.  
  711. function callAction(actionType, param, button)
  712.   if (actionType == "switch") then
  713.     showScreen(param)
  714.   elseif (actionType == "function") then
  715.     if changeButtonColor then
  716.       showButton(button, buttonPressedColor)
  717.     end
  718.    
  719.     if userFunctions[param] ~= nil then
  720.       userFunctions[param]()
  721.     elseif editorFunctions[param] ~= nil then
  722.       editorFunctions[param]()
  723.     end
  724.    
  725.     if changeButtonColor then
  726.       showButton(button, buttonDefaultColor)
  727.     else
  728.       changeButtonColor = true
  729.     end
  730.   end
  731. end
  732.  
  733. function getMonitor()
  734.   if (peripheral.getType(monitorSide) == "monitor") then
  735.     monitor = peripheral.wrap(monitorSide)
  736.     return true
  737.   else
  738.     return false
  739.   end
  740. end
  741.  
  742. function debugMessage(message)
  743.   term.restore()
  744.   print(message)
  745.   term.redirect(monitor)
  746. end
  747.  
  748. function main()
  749.   showScreen("mainScreen")
  750.  
  751.   while not quit do
  752.     getInput()
  753.   end
  754. end
  755.  
  756. function saveScreens()
  757.   saveString = textutils.serialize(screens)
  758.   file = fs.open("screens.sav", "w")
  759.   file.write(saveString)
  760.   file.close()
  761. end
  762.  
  763. function loadScreens()
  764.   if not fs.exists("screens.sav") then
  765.     return
  766.   end
  767.  
  768.   file = fs.open("screens.sav", "r")
  769.   loadString = file.readAll()
  770.   if (loadString ~= nil and loadString ~= "") then
  771.     screens = textutils.unserialize(loadString)
  772.   end
  773.   file.close()
  774. end
  775.  
  776. -- screen editor region start --
  777.  
  778. function generateScreenList()
  779.   ret = {  }
  780.   for key, value in pairs(screens) do
  781.     table.insert(ret, key)
  782.   end
  783.  
  784.   return ret
  785. end
  786.  
  787. editorScreens = {
  788.   mainScreen = {
  789.     { objType="Text", x=2, y=1, text="Mode:" };
  790.     { objType="List", x=2, y=2, elements=editActions, listID="editActionList", isMultiselect=false };
  791.     { objType="Button", x=2, y=6, width=14, height=1, text="last screen", funcType="function", param="editLastScreen" };
  792.     { objType="Button", x=2, y=8, width=14, height=1, text="edit screens", funcType="function", param="loadScreenList" };
  793.   };
  794.  
  795.   screenListScreen = {
  796.     { objType="List", x=2, y=2, elements=screenList, listID="screenList", isMultiselect=false };
  797.     { objType="Button", x=2, y=maxY-6, width=12, height=1, text="Set parent", funcType="function", param="setParent" };
  798.     { objType="Button", x=2, y=maxY-4, width=8, height=1, text="New", funcType="function", param="newScreen" };
  799.     { objType="Button", x=2, y=maxY-3, width=8, height=1, text="Edit", funcType="function", param="editScreen" };
  800.     { objType="Button", x=2, y=maxY-2, width=8, height=1, text="Delete", funcType="function", param="deleteScreen" };
  801.   };
  802. }
  803.  
  804. -- Used to give a List-object an array of all screens
  805. function editorFunctions.loadScreenList()
  806.   screenList = generateScreenList()
  807.   editorScreens["screenListScreen"][1].elements = screenList
  808.   changeButtonColor = false
  809.   showScreen("screenListScreen")
  810. end
  811.  
  812. function editorFunctions.editLastScreen()
  813.   if (lastScreen == nil) then
  814.     lastScreen = "mainScreen"
  815.   end
  816.  
  817.   showEditorOptions = false
  818.   showScreen(lastScreen)
  819.   changeButtonColor = false
  820. end
  821.  
  822. -- Let's the user define the parentScreen-attribute of the current screen.
  823. function editorFunctions.setParent()
  824.   if (selectedItems.screenList == nil) then
  825.     return
  826.   end
  827.  
  828.   list = editorScreens.screenListScreen[1]
  829.   height = list.height
  830.   for i = 1, height do
  831.     if (selectedItems.screenList ~= i) then
  832.       paintutils.drawPixel(1, i + 1, colors.lime)
  833.     end
  834.   end
  835.  
  836.   event, side, x, y = os.pullEvent("monitor_touch")
  837.  
  838.   if (y > 1 and y <= height + 1) then -- Clicked inside the list.
  839.     if (y - 1 ~= selectedItems.screenList) then -- Selected parentScreen is not selected screen.
  840.       screens[list.elements[selectedItems.screenList]].parentScreen = list.elements[y - 1]
  841.     end
  842.   end
  843.  
  844.   for i = 1, height do
  845.     paintutils.drawPixel(1, i + 1, colors.black)
  846.   end
  847. end
  848.  
  849. -- Creates a new screen. The user has to enter the screen name in the computer.
  850. function editorFunctions.newScreen()
  851.   term.clear()
  852.   term.setCursorPos(2, 2)
  853.   term.write("Enter a screen-name.")
  854.   message = "Pleas enter the name of the new screen."
  855.   userInput = readUserInput(message, false)
  856.  
  857.   while (userInput ~= nil and screens[userInput] ~= nil) do
  858.     message = "There is already a screen with that name!"
  859.     userInput = readUserInput(message, false)
  860.   end
  861.  
  862.   if (userInput ~= nil) then
  863.     screens[userInput] = { parentScreen="mainScreen" }
  864.     showEditorOptions = false
  865.     showScreen(userInput)
  866.     lastScreen = userInput
  867.     changeButtonColor = false
  868.   end
  869. end
  870.  
  871. -- Edits the screen that has been selected in the "screenList"-list.
  872. function editorFunctions.editScreen()
  873.   if (selectedItems.screenList ~= nil) then
  874.     showEditorOptions = false
  875.     lastScreen = screenList[selectedItems.screenList]
  876.     showScreen(screenList[selectedItems.screenList])
  877.     changeButtonColor = false
  878.   end
  879. end
  880.  
  881. -- Deletes the screen that has been selected in the "screenList"-list.
  882. function editorFunctions.deleteScreen()
  883.   if (selectedItems.screenList ~= nil and screenList[selectedItems.screenList] ~= "mainScreen") then
  884.     screens[screenList[selectedItems.screenList]] = nil
  885.     showEditorOptions = true
  886.     editorFunctions.loadScreenList()
  887.   end
  888. end
  889.  
  890. -- Displays an object with default attributes and adds it to the current screen.
  891. function showDefaultObject(objectType, xCoord, yCoord)
  892.   object = {  }
  893.   object.objType = objectType
  894.   object.x = xCoord
  895.   object.y = yCoord
  896.  
  897.   maxWidth = maxX - xCoord
  898.   maxHeight = maxY - yCoord
  899.  
  900.   if (objectType == "Button") then
  901.     object.width = (maxWidth < 8) and maxWidth or 8
  902.     object.height = (maxHeight < 3) and maxHeight or 3
  903.    
  904.     object.text = "Button"
  905.     object.funcType = ""
  906.     object.param = ""
  907.     showButton(object, buttonDefaultColor)
  908.   elseif (objectType == "Text") then
  909.     object.text = "Text"
  910.     showText(object)
  911.   elseif (objectType == "Variable") then
  912.     object.varID = "testVariable"
  913.   elseif (objectType == "Slider") then
  914.     object.length = (maxWidth < 10) and maxWidth or 10
  915.     object.direction = "right"
  916.     object.sliderID = "testSlider"
  917.     showSlider(object)
  918.   elseif (objectType == "Input") then
  919.     object.inputID = "testInput"
  920.     object.message = "Enter something."
  921.     object.isPassword = false
  922.     showInput(object)
  923.   elseif (objectType == "List") then
  924.     object.elements = {"List Item 1", "List Item 2", "List Item 3"}
  925.     object.listID = "testList"
  926.     object.isMultiselect = false
  927.     showList(object)
  928.   else
  929.     return
  930.   end
  931.  
  932.   table.insert(screens[currentScreen], object)
  933. end
  934.  
  935. -- Returns the right- and bottom-coordinates of the object.
  936. function getObjectDimensions(object)
  937.   if (type(object) ~= "table") then
  938.     return -1, -1, -1, -1
  939.   end
  940.  
  941.   objectType = object.objType
  942.   left = object.x
  943.   top = object.y
  944.  
  945.   if (objectType == "Button" or objectType == "List") then
  946.     right = left + object.width - 1
  947.     bottom = top + object.height - 1
  948.   elseif (objectType == "Text") then
  949.     right = left + string.len(object.text)
  950.     bottom = top
  951.   elseif (objectType == "Variable" or objectType == "Input") then
  952.     right = left + 1
  953.     bottom = top
  954.   elseif (objectType == "Slider") then
  955.     direction = object.direction
  956.     length = object.length
  957.    
  958.     if (direction == "left") then
  959.       left = object.x - length
  960.       top = object.y
  961.       right = object.x
  962.       bottom = top
  963.     elseif (direction == "up") then
  964.       left = object.x
  965.       top = object.y - length
  966.       right = object.x
  967.       bottom = object.y
  968.     elseif (direction == "down") then
  969.       left = object.x
  970.       top = object.y
  971.       right = object.x
  972.       bottom = top + length
  973.     else -- right
  974.       left = object.x
  975.       top = object.y
  976.       right = object.x + length
  977.       bottom = top
  978.     end
  979.   else
  980.     right = -1
  981.     bottom = -1
  982.   end
  983.  
  984.   return left, top, right, bottom
  985. end
  986.  
  987. -- Note for other users than me (and maybe me... yeah probably mostly for me):
  988. -- The function to determine if the object has been touched is different than the one in the "getInput" function. Don't be confused!
  989. function findObject(x, y)
  990.   if showEditorOptions then
  991.     screenObject = editorScreens[currentScreen]
  992.   else
  993.     screenObject = screens[currentScreen]
  994.   end
  995.   for sObjectID, sObject in pairs(screens[currentScreen]) do
  996.     left, top, right, bottom = getObjectDimensions(sObject)
  997.    
  998.     if (x >= left and x <= right and y >= top and y <= bottom) then
  999.       return sObjectID, sObject
  1000.     end
  1001.   end
  1002.  
  1003.   return nil, nil
  1004. end
  1005.  
  1006. -- Let's the user delete an object or change its attributes depending on the current edit-mode.
  1007. function editObject(objectKey)
  1008.   sObject = screens[currentScreen][objectKey]
  1009.   objType = sObject.objType
  1010.   left, top, right, bottom = getObjectDimensions(sObject)
  1011.  
  1012.   if (editActions[selectedItems.editActionList] == "Delete") then
  1013.     screens[currentScreen][objectKey] = nil
  1014.   elseif (editActions[selectedItems.editActionList] == "Attributes") then
  1015.     objAttr = {  }
  1016.    
  1017.     index = 1
  1018.     for key, value in pairs(sObject) do
  1019.       if (key ~= "objType" and key ~= "x" and key ~= "y" and key ~= "width" and key ~= "height" and key ~= "length" and key ~= "direction") then
  1020.         table.insert(objAttr, index, key)
  1021.         index = index + 1
  1022.       end
  1023.     end
  1024.    
  1025.     term.clear()
  1026.    
  1027.     yPos = 2
  1028.     top = yPos
  1029.     for attrKey, attrValue in ipairs(objAttr) do
  1030.       term.setCursorPos(2, yPos)
  1031.       term.write(attrValue .. ": ")
  1032.       print(sObject[attrValue])
  1033.       yPos = yPos + 1
  1034.     end
  1035.     term.setCursorPos(2, yPos + 1)
  1036.     term.setBackgroundColor(colors.red)
  1037.     term.write(doneString)
  1038.     term.setBackgroundColor(colors.black)
  1039.    
  1040.     bottom = yPos - 1
  1041.     finished = false
  1042.     while not finished do
  1043.       event, side, x, y = os.pullEvent("monitor_touch")
  1044.      
  1045.       if y >= top and y <= bottom then
  1046.         selectedAttr = objAttr[y - 1]
  1047.         paintutils.drawPixel(1, y, colors.yellow)
  1048.        
  1049.         if (selectedAttr == "text" or
  1050.             selectedAttr == "param" or
  1051.             selectedAttr == "varID" or
  1052.             selectedAttr == "sliderID" or
  1053.             selectedAttr == "inputID" or
  1054.             selectedAttr == "listID" or
  1055.             selectedAttr == "message" or
  1056.             selectedAttr == "elements" or
  1057.             selectedAttr == "message") then
  1058.           userInput = readUserInput("Please enter a value for the " .. selectedAttr .. ".", false)
  1059.           if (userInput ~= nil) then
  1060.             screens[currentScreen][objectKey][selectedAttr] = userInput
  1061.           end
  1062.         elseif (selectedAttr == "funcType") then -- Button attribute
  1063.           if (sObject.funcType == "switch") then
  1064.             screens[currentScreen][objectKey][selectedAttr] = "function"
  1065.           else
  1066.             screens[currentScreen][objectKey][selectedAttr] = "switch"
  1067.           end
  1068.         elseif (selectedAttr == "isPassword" or selectedAttr == "isMultiselect") then
  1069.           if (sObject[selectedAttr]) then
  1070.             screens[currentScreen][objectKey][selectedAttr] = false
  1071.           else
  1072.             screens[currentScreen][objectKey][selectedAttr] = true
  1073.           end
  1074.         end
  1075.         paintutils.drawPixel(1, y, colors.black)
  1076.         if (not finished and selectedAttr ~= nil) then
  1077.           term.setCursorPos(2, y) -- I don't know if that's neccessary...
  1078.           for i = 2, maxX do
  1079.             term.write(" ")
  1080.           end
  1081.           term.setCursorPos(2, y)
  1082.           term.write(selectedAttr .. ": ")
  1083.           term.write(sObject[selectedAttr])
  1084.         end
  1085.       elseif (y == yPos + 1 and x >= 2 and x <= 1 + string.len(doneString)) then
  1086.         finished = true
  1087.       end
  1088.     end
  1089.   else -- Design mode
  1090.     canScale = false
  1091.     moveX = left
  1092.     moveY = top
  1093.    
  1094.     if (objType == "Button") then
  1095.       paintutils.drawPixel(right, bottom, editorScaleColor)
  1096.       scaleX = right
  1097.       scaleY = bottom
  1098.       canScale = true
  1099.     elseif (objType == "Slider") then
  1100.       direction = sObject.direction
  1101.       assert(direction)
  1102.       canScale = true
  1103.      
  1104.       if (direction == "left") then
  1105.         moveX = right
  1106.         moveY = top
  1107.         scaleX = left
  1108.         scaleY = bottom
  1109.       elseif (direction == "up") then
  1110.         moveX = left
  1111.         moveY = bottom
  1112.         scaleX = right
  1113.         scaleY = top
  1114.       else -- right or down
  1115.         moveX = left
  1116.         moveY = top
  1117.         scaleX = right
  1118.         scaleY = bottom
  1119.       end
  1120.      
  1121.       paintutils.drawPixel(scaleX, scaleY, editorScaleColor)
  1122.     end
  1123.    
  1124.     paintutils.drawPixel(moveX, moveY, editorMoveColor)
  1125.     term.setBackgroundColor(colors.black)
  1126.    
  1127.     event, side, x, y = os.pullEvent("monitor_touch")
  1128.    
  1129.     if (x >= left and x <= right and y >= top and y <= bottom) then -- clicked inside the object
  1130.       if (x == moveX and y == moveY) then -- move object
  1131.         paintutils.drawPixel(moveX, moveY, colors.white)
  1132.         event, side, x, y = os.pullEvent("monitor_touch")
  1133.         screens[currentScreen][objectKey].x = x
  1134.         screens[currentScreen][objectKey].y = y
  1135.       elseif (canScale and x == scaleX and y == scaleY) then -- scale object
  1136.         paintutils.drawPixel(scaleX, scaleY, colors.white)
  1137.         term.setBackgroundColor(colors.black)
  1138.         event, side, x, y = os.pullEvent("monitor_touch")
  1139.        
  1140.         if (objType == "Button") then
  1141.           if (x > moveX + 2 and y >= moveY) then
  1142.             screens[currentScreen][objectKey].width = x - left + 1
  1143.             screens[currentScreen][objectKey].height = y - top + 1
  1144.           end
  1145.         elseif (objType == "Slider") then
  1146.           if (x < moveX and y == moveY) then -- Clicked left of the slider.
  1147.             screens[currentScreen][objectKey].direction = "left"
  1148.             screens[currentScreen][objectKey].length = moveX - x
  1149.           elseif (x == moveX and y < moveY) then -- Clicked above the slider.
  1150.             screens[currentScreen][objectKey].direction = "up"
  1151.             screens[currentScreen][objectKey].length = moveY - y
  1152.           elseif (x > moveX and y == moveY) then -- Clicked right of the slider.
  1153.             screens[currentScreen][objectKey].direction = "right"
  1154.             screens[currentScreen][objectKey].length = x - moveX
  1155.           elseif (x == moveX and y > moveY) then -- Clicked below the slider.
  1156.             screens[currentScreen][objectKey].direction = "down"
  1157.             screens[currentScreen][objectKey].length = y - moveY
  1158.           end
  1159.           --screens[currentScreen][objectKey].length = x - left + 1
  1160.         end
  1161.       else -- clicked something else inside the object (no idea what I could use this for)
  1162.        
  1163.       end
  1164.     end
  1165.   end
  1166.  
  1167.   term.setBackgroundColor(colors.black)
  1168.   showScreen(currentScreen)
  1169. end
  1170.  
  1171. function markVariables()
  1172.   for sObjectID, sObject in pairs(screens[currentScreen]) do
  1173.     if (sObject.objType == "Variable") then
  1174.       paintutils.drawPixel(sObject.x, sObject.y, colors.lime)
  1175.       term.setBackgroundColor(colors.black)
  1176.     end
  1177.   end
  1178. end
  1179.  
  1180. function getEditorInput()
  1181.   if not showEditorOptions then
  1182.     markVariables()
  1183.     key, side, xCoord, yCoord = os.pullEvent("monitor_touch")
  1184.   end
  1185.  
  1186.   if (showEditorOptions or yCoord == maxY and xCoord > maxX - string.len(refreshText)) then -- "Refresh" pressed => Options screen
  1187.     showEditorOptions = true
  1188.     showScreen("mainScreen")
  1189.     while showEditorOptions and not quit do
  1190.       getInput()
  1191.     end
  1192.   elseif (yCoord == maxY and xCoord >= 1 and xCoord <= string.len(backText)) then -- "Back" pressed => Quit
  1193.     quit = true
  1194.   else
  1195.     key, value = findObject(xCoord, yCoord) -- Find the object that the user touched.
  1196.     if (key == nil) then -- No object touched. Show selector for new object.
  1197.       paintutils.drawPixel(xCoord, yCoord, colors.white)
  1198.       if (showSelector(xCoord, yCoord, objectTypes)) then -- something has been selected
  1199.         showDefaultObject(selectedItem, xCoord, yCoord)
  1200.       end
  1201.     else
  1202.       editObject(key)
  1203.     end
  1204.   end
  1205. end
  1206.  
  1207. function screenEditor()
  1208.   editMode = true
  1209.   autoLoadObjects = false
  1210.  
  1211.   showEditorOptions = true
  1212.   showScreen("mainScreen")
  1213.  
  1214.   while not quit do
  1215.     getEditorInput()
  1216.   end
  1217. end
  1218.  
  1219. -- screen editor region end --
  1220.  
  1221. -- initialization
  1222.  
  1223. function init()
  1224.   if not getMonitor() then
  1225.     print("No monitor at " .. monitorSide .. " side!");
  1226.     return false
  1227.   end
  1228.  
  1229.   maxX, maxY = monitor.getSize()
  1230.   if (maxX < 16 or maxY < 10) then -- smaller than 2x2
  1231.     print("Screen too small! You need at least 2x2 monitors!")
  1232.     return false
  1233.   end
  1234.  
  1235.   term.redirect(monitor)
  1236.  
  1237.   return true
  1238. end
  1239.  
  1240. function checkArgs()
  1241.   doCall = main
  1242.  
  1243.   if (args[1] ~= nil) then
  1244.     if (args[1] == "edit") then
  1245.       doCall = screenEditor
  1246.     end
  1247.   end
  1248.  
  1249.   doCall()
  1250. end
  1251.  
  1252. if init() then
  1253.   loadScreens()
  1254.   checkArgs()
  1255.  
  1256.   if editMode then
  1257.     saveScreens()
  1258.   end
  1259.  
  1260.   term.clear()
  1261.   term.setCursorPos(1, 1)
  1262.   term.restore()
  1263. end
Advertisement
Add Comment
Please, Sign In to add comment