Advertisement
derkoch

guiElements v1.0

Oct 6th, 2013
275
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.75 KB | None | 0 0
  1. local version = 1.0
  2.  
  3. os.loadAPI("./RBB/config")
  4.  
  5.  
  6. --~ ##### Element START #####
  7. Element = {}
  8. Element.__index = Element
  9.  
  10. --- Creates a new Element
  11. -- @param name  the name of the element, should be unique
  12. -- @param elemtype  the type of the element (e.g. "button","label","picker")
  13. function Element.create (name, elemtype)
  14.     local elem = {}
  15.     setmetatable(elem, Element)
  16.     elem.name = name
  17.     elem.type = elemtype
  18.     elem.color = config.defaulTextColor
  19.     elem.bgcolor = config.defaultBackgroundColor
  20.     elem.target = nil
  21.     elem.minx = 0
  22.     elem.maxx = 0
  23.     elem.miny = 0
  24.     elem.maxy = 0
  25.     return elem
  26. end
  27.  
  28. --- Returns minimum and maximum x and y values of the element
  29. -- @return <code>minx, maxx, miny, maxy</code>
  30. function Element:getMinMaxXY()
  31.     return self.minx, self.maxx, self.miny, self.maxy
  32. end
  33.  
  34. --- Sets minimum and maximum x and y values for the the element
  35. -- @param minx minimum x value
  36. -- @param maxx maximum x value
  37. -- @param miny minimum y value
  38. -- @param maxy maximum y value
  39. function Element:setMinMaxXY(minx,maxx,miny,maxy)
  40.     -- if self == nil then
  41.         -- return
  42.     -- end
  43.     self.minx = minx
  44.     self.maxx = maxx
  45.     self.miny = miny
  46.     self.maxy = maxy
  47. end
  48.  
  49. --- Prints element information for debugging purposes
  50. function Element:debugPrint()
  51.     print("ElementDEBUG:")
  52.     print("\tname:\t" .. self.name)
  53.     print("\ttype:\t" .. self.type)
  54.     print("\txmin: " .. self.minx .. ", xmax: ".. self.maxx .. ", ymin: " .. self.miny .. ", ymax: " .. self.maxy)
  55. end
  56.  
  57. --- Checks if element was clicked at coordinate (<code>x</code>,<code>y</code>)
  58. -- @param x the x click position
  59. -- @param y the y click position
  60. -- @return <code>true</code> clicked<br><code>false</code> not clicked
  61. function Element:isClicked(x,y)
  62.     if x >= self.minx and x <= self.maxx then
  63.         if y >= self.miny and y <= self.maxy then
  64.             helper.debug_print("Element:isClicked", self.name)
  65.             return true
  66.         end
  67.     end
  68.     return false
  69. end
  70.  
  71. --- Sets the target of the element
  72. -- @param target the target, e.g. a monitor
  73. function Element:setTarget(target)
  74.     self.target = target
  75. end
  76.  
  77. --- Clears the area around <code>(minx, miny)</code> to <code>(maxx,maxy)</code> with
  78. -- the default colors.
  79. -- @param target the monitor the Element will be drawn to
  80. function Element:clear(target)
  81.     -- clear the grid with base colors, just in case...
  82.     -- self:debugPrint()
  83.     target.setTextColor(self.color)
  84.     target.setBackgroundColor(self.bgcolor)
  85.     for i = self.minx, self.maxx do
  86.         for j = self.miny, self.maxy do
  87.             target.setCursorPos(i,j)
  88.             target.write(" ")
  89.         end
  90.     end
  91. end
  92.  
  93. --- Sets the text color of the element
  94. -- Sets the color to a different one. For more info look in
  95. -- colors-API
  96. -- @param newcolor the new text color
  97. function Element:setTextColor(newcolor)
  98.     self.color = newcolor
  99. end
  100.  
  101. --- Sets the background color of the element
  102. -- @param newbgcolor the new background color
  103. function Element:setBGColor(newbgcolor)
  104.     --print("setting color to: " .. tostring(newbgcolor))
  105.     self.bgcolor = newbgcolor
  106. end
  107. --~ ##### Element END #####
  108.  
  109. --~ ##### Button START #####
  110. Button = {}
  111. Button.__index = Button
  112.  
  113. --- Creates a new Button
  114. -- @param name  the ame to of the button
  115. -- @param text  the button text, duh!
  116. -- @param active    the state of the button. <code>true</code> activated, <code>false</code> deactivated
  117. -- @param func  the function that will be executed when pressing the button
  118. -- @param funcparams    the parameters the function will be executed with (<code>table</code>)
  119. function Button.create(name, text, active, func, funcparams)
  120.     local button = Element.create(name, "button")
  121.     setmetatable(Button, Element)
  122.     setmetatable(button, Button)
  123.     button.text = text
  124.     button.active = active
  125.     button.func = func
  126.     if funcparams ~= nil and type(funcparams) ~= "table" then
  127.         error("Button.create: funcparams needs to be a table!")
  128.     end
  129.     button.params = funcparams
  130.     button.colorActive = config.defaultBtnActiveBackground
  131.     button.colorNonActive = config.defaultBtnNonActiveBackground
  132.     button.radioIndex = nil
  133.     button.textposition = {h = config.defaultHPosition, v = config.defaultVPosition}
  134.     return button
  135. end
  136.  
  137. --- Checks if button was clicked at coordinate (<code>x</code>,<code>y</code>)
  138. -- @param x the x click position
  139. -- @param y the y click position
  140. -- @return <code>true</code> clicked<br><code>false</code> not clicked
  141. function Button:isClicked(x,y)
  142.     if x >= self.minx and x <= self.maxx then
  143.         if y >= self.miny and y <= self.maxy then
  144.             helper.debug_print("Element:isClicked", self.name)
  145.             return true, self.active
  146.         end
  147.     end
  148.     return false, self.active
  149. end
  150.  
  151. --- Prints button information for debugging purposes
  152. function Button:debugPrint()
  153.     print("ButtonDEBUG:")
  154.     print("\tname:\t" .. self.name)
  155.     print("\ttext:\t" .. self.text)
  156.     print("\ttype:\t" .. self.type)
  157.     print("\tradioIndex:\t" .. tostring(self.radioIndex))
  158.     print("\tparams:\t" .. textutils.serialize(self.params))
  159.     print("\txmin: " .. self.minx .. ", xmax: ".. self.maxx .. ", ymin: " .. self.miny .. ", ymax: " .. self.maxy)
  160. end
  161.  
  162. --- Set position for button text
  163. -- @param textpos   the table with two keys: "h" (horizontal) and "v" (vertical). See also: <a href="helper#validPositions">helper.validPositions</a>
  164. -- @usage Button:setTextPosition({h = "center", v = "top"})
  165. function Button:setTextPosition(textpos)
  166.     self.textposition = textpos
  167.     --self:draw(self.target)
  168. end
  169.  
  170. --- Sets the parameters for the function
  171. -- @param funcparams    the parameters for the function (<code>table</code>)
  172. -- @usage Button:setFuncParams({"param1", "param2", 1})
  173. function Button:setFuncParams(funcparams)
  174.     if funcparams ~= nil and type(funcparams) ~= "table" then
  175.         error("Button.create: funcparams needs to be a table!")
  176.     end
  177.     self.params = funcparams
  178. end
  179.  
  180. --- Sets the radioIndex of the Button. Needed when using a set of buttons as RadioButtons
  181. -- @param index the value to group buttons
  182. function Button:setRadioIndex(index)
  183.     self.radioIndex = index
  184. end
  185.  
  186. --- Sets the button state
  187. -- @param state <code>true</code> activated<br><code>false</code> deactivated
  188. function Button:setState(state)
  189.     self.active = state
  190.     self:draw(self.target)
  191. end
  192.  
  193. --- Toggles the button state
  194. function Button:toggle()
  195.     self.active = not self.active
  196.     self:draw(self.target)
  197. end
  198.  
  199. --- Draws the button to <code>target</code>
  200. -- @param target the target, e.g. monitor
  201. function Button:draw(target)
  202.     -- clear the grid, just in case with base colors
  203.     self:clear(target)
  204.  
  205.     local posH = self.textposition["h"] or config.defaultHPosition
  206.     local posV = self.textposition["v"] or config.defaultVPosition
  207.  
  208.     local elemWidth = self.maxx - self.minx + 1
  209.     local elemHeight = self.maxy - self.miny + 1
  210.  
  211.     if self.active then
  212.         target.setBackgroundColor(self.colorActive)
  213.     else
  214.         target.setBackgroundColor(self.colorNonActive)
  215.     end
  216.  
  217.     -- validate position data, if not valid, then set to default -> "center"
  218.     -- also corrects 'textposition' attributes to default
  219.     -- if not helper.isValidPosition(posH) then
  220.         -- posH = config.defaultHPosition
  221.         -- self.textposition["h"] = posH
  222.     -- end
  223.     -- if not helper.isValidPosition(posV) then
  224.         -- posV = config.defaultVPosition
  225.         -- self.textposition["v"] = posV
  226.     -- end
  227.  
  228.     -- format text in horizontal position, I don't care about 'rest' atm!
  229.     local text, rest = helper.formatText(self.text, elemWidth, " ", posH)
  230.  
  231.     local filler = helper.formatText("", elemWidth, " ", "l")
  232.  
  233.     -- vertical position of label text
  234.     local position
  235.     if posV == "top" or posV == "t" then
  236.         position = 1
  237.     elseif posV == "center" or posV == "c" then
  238.         position = math.ceil(elemHeight/2)
  239.     elseif posV == "bottom" or posV == "b" then
  240.         position = elemHeight
  241.     end
  242.  
  243.     -- draw the actual Label
  244.     for i = 1, elemHeight do
  245.         -- DEBUG
  246.         -- filler = helper.formatText(""..i, elemWidth, " ", "l")
  247.         target.setCursorPos(self.minx, self.miny + i - 1)
  248.         if i == position then
  249.             target.write(text)
  250.         else
  251.             target.write(filler)
  252.         end
  253.     end
  254.     target.setBackgroundColor(config.defaultBackgroundColor)
  255.     return true
  256. end
  257.  
  258. --- Toggles other Buttons if they are int the same group of radio indices
  259. -- @param elements the set of other the elements
  260. function Button:toggleOthers(elements)
  261.     if not self.active then
  262.         -- Check each element  
  263.         for key1, value1 in pairs(elements) do
  264.             for key2, value2 in pairs(value1) do
  265.                 -- Element should not be nil and have a type of "button"
  266.                 if value2 ~= nil and value2.type == "button" then
  267.                     if value2.radioIndex == self.radioIndex then                   
  268.                         if value2.active then
  269.                             value2:toggle()                    
  270.                         end
  271.                     end
  272.                 end
  273.             end        
  274.         end
  275.     end
  276.     -- toggle self anyway
  277.     self:toggle()  
  278. end
  279.  
  280. --- Executes the call-back function with the specified parameters
  281. -- @return <code>true</code> valid function, <code>false</code> invalid function
  282. function Button:execFunction()
  283.     helper.debug_print("Button:execFunction", self.name)
  284.     if self.func == nil then
  285.         helper.printError("ERROR: no function on " .. self.type .. " \n\t\tname: " .. self.name .. ", text: " .. self.text)
  286.     else
  287.         if self.params then
  288.             self.func(unpack(self.params))
  289.             return true
  290.         else
  291.             self.func()
  292.             return true
  293.         end
  294.     end
  295.     return false
  296. end
  297. --~ ##### Button END #####
  298.  
  299. --~ ##### Label START#####
  300. Label = {}
  301. Label.__index = Label
  302.  
  303. --- Creates a new label
  304. -- @param name the ame to identify the element, should be unique!
  305. -- @param text the label text, duh!
  306. -- @param textpos   the table with two keys: "h" (horizontal) and "v" (vertical). See also: <a href="helper#validPositions">helper.validPositions</a>
  307. function Label.create(name, text, textpos)
  308.     local lbl = Element.create(name, "label")
  309.     setmetatable(Label, Element)
  310.     setmetatable(lbl, Label)
  311.     lbl.text = text
  312.     lbl.textposition = textpos
  313.     return lbl
  314. end
  315.  
  316. --- Draws the label to <code>target</code>
  317. -- @param target the target, e.g monitor
  318. function Label:draw(target)
  319.     -- clear the grid, just in case with base colors
  320.     self:clear(target)
  321.  
  322.     local posH = self.textposition["h"]
  323.     local posV = self.textposition["v"]
  324.  
  325.     local elemWidth = self.maxx - self.minx + 1
  326.     local elemHeight = self.maxy - self.miny + 1
  327.  
  328.     -- validate position data, if not valid, then set to default -> "center"
  329.     -- also corrects 'textposition' attributes to default
  330.     if not helper.isValidPosition(posH) then
  331.         posH = config.defaultHPosition
  332.         self.textposition["h"] = posH
  333.     end
  334.     if not helper.isValidPosition(posV) then
  335.         posV = config.defaultVPosition
  336.         self.textposition["v"] = posV
  337.     end
  338.  
  339.     -- format text in horizontal position, I don't care about 'rest' atm!
  340.     local text, rest = helper.formatText(self.text, elemWidth, " ", posH)
  341.  
  342.     --[[ Maybe feature: long text, automatic line break and so on...
  343.     local labeltext = {}
  344.     local index = 1
  345.     labeltext[index] = text
  346.     index = index + 1
  347.     while rest ~= nil do
  348.         text, rest = helper.formatText(rest, elemWidth, " ", posH)
  349.         labeltext[index] = text
  350.         index = index + 1
  351.     end
  352.     -- more than one line of text
  353.     if rest ~= nil then
  354.         rest = helper.formatText(rest, elemWidth, " ", posH)
  355.     end
  356.     --]]
  357.  
  358.     local filler = helper.formatText("", elemWidth, " ", "l")
  359.  
  360.     -- vertical position of label text
  361.     local position
  362.     if posV == "top" or posV == "t" then
  363.         position = 1
  364.     elseif posV == "center" or posV == "c" then
  365.         position = math.ceil(elemHeight/2)
  366.     elseif posV == "bottom" or posV == "b" then
  367.         position = elemHeight
  368.     end
  369.  
  370.     -- draw the actual Label
  371.     for i = 1, elemHeight do
  372.         -- DEBUG
  373.         -- filler = helper.formatText(""..i, elemWidth, " ", "l")
  374.         target.setCursorPos(self.minx, self.miny + i - 1)
  375.         if i == position then
  376.             target.write(text)
  377.         else
  378.             target.write(filler)
  379.         end
  380.     end
  381.     target.setBackgroundColor(config.defaultBackgroundColor)
  382.     return true
  383. end
  384. --~ ##### Label END #####
  385. --~ ##### Picker START #####
  386. Picker = {}
  387. Picker.__index = Picker
  388. --- Creates a new picker
  389. -- @param name  the name of the picker, should be unique
  390. -- @param text  the text over the picker
  391. -- @param startindex    the start index for valuerange
  392. -- @param valuerange    the table with values or a 2D table with
  393. --          containing another table and a step-value
  394. -- @usage Creates a new Picker with the Title "Data" and a table with values ranging from 0 to 100 in increments of 5 {0,5,10,15,..}<br>
  395. -- create("picky", "Data", 2, {{0,100}, 5})
  396. function Picker.create(name, text, startindex, valuerange)
  397.     local picker = Element.create(name, "picker")
  398.     setmetatable(Picker, Element)
  399.     setmetatable(picker, Picker)
  400.     picker.text = text
  401.     picker.buttonInc = Button.create(name, "+", true, func)
  402.     picker.buttonDec = Button.create(name, "-", true, func)
  403.     picker.clickedInc = false
  404.     picker.clickedDec = false
  405.  
  406.     if #valuerange == 2 and type(valuerange[1]) == "table" then
  407.         picker.values = helper.createNumberList(valuerange[1][1], valuerange[1][2], valuerange[2])
  408.     else
  409.         picker.values = valuerange
  410.     end
  411.     picker.currentIndex = startindex
  412.  
  413.     return picker
  414. end
  415.  
  416. --- Draws the picker to <code>target</code>
  417. -- @param target the target, e.g monitor
  418. function Picker:draw(target)
  419.     -- clear the grid, just in case with base colors
  420.     self:clear(target)
  421.     local elemWidth = self.maxx - self.minx + 1
  422.     local elemHeight = self.maxy - self.miny + 1
  423.  
  424.     local centerVpos = math.floor(elemHeight/2)
  425.     local value = helper.formatText(self.values[self.currentIndex], elemWidth, " ", "center")
  426.  
  427.     if self.text == "" or self.text == nil then
  428.         target.setCursorPos(self.minx, self.miny + centerVpos)
  429.         target.write(value)
  430.     else
  431.         local text = helper.formatText(self.text, elemWidth , " ", "center")
  432.         target.setCursorPos(self.minx, self.miny)
  433.         target.write(text)
  434.         target.setCursorPos(self.minx, self.miny + centerVpos)
  435.         target.write(value)
  436.     end
  437.     -- format text in horizontal position
  438.  
  439.     self.buttonInc:draw(target)
  440.     self.buttonDec:draw(target)
  441.  
  442.     target.setBackgroundColor(config.defaultBackgroundColor)
  443.     return true
  444. end
  445.  
  446. --- Checks if the picker was clicked at coordinate (<code>x</code>,<code>y</code>)
  447. -- @param x the x click position
  448. -- @param y the y click position
  449. -- @return <code>true</code> clicked<br><code>false</code> not clicked
  450. function Picker:isClicked(x,y)
  451.     if x >= self.minx and x <= self.maxx then
  452.         if y >= self.miny and y <= self.maxy then
  453.             helper.debug_print("Picker:isClicked", self.name)
  454.             self.clickedInc = self.buttonInc:isClicked(x,y)
  455.             self.clickedDec = self.buttonDec:isClicked(x,y)
  456.             return self.clickedInc or self.clickedDec
  457.         end
  458.     end
  459.     return false
  460. end
  461.  
  462. --- Sets the target of the element
  463. -- @param target the target, e.g. a monitor
  464. function Picker:setTarget(target)
  465.     self.target = target
  466.     self.buttonInc:setTarget(target)
  467.     self.buttonDec:setTarget(target)
  468. end
  469.  
  470. --- Sets minimum and maximum x and y values for the the picker
  471. -- @param minx minimum x value
  472. -- @param maxx maximum x value
  473. -- @param miny minimum y value
  474. -- @param maxy maximum y value
  475. function Picker:setMinMaxXY(minx,maxx,miny,maxy)
  476.     --print(string.format("picker changing to: %s, %s, %s, %s", minx,maxx,miny,maxy))
  477.     self.minx = minx
  478.     self.maxx = maxx
  479.     self.miny = miny
  480.     self.maxy = maxy
  481.  
  482.     local elemWidth = maxx - minx + 1
  483.     local elemHeight = maxy - miny + 1
  484.  
  485.     local centerVpos = math.floor(elemHeight/2)
  486.     --string.format("changed: %s, %s, %s, %s", minx,maxx,miny,maxy)
  487.     --print(string.format("changed: %s, %s, %s, %s", minx,maxx,miny,maxy))
  488.     --print(string.format("buttonInc: %s, %s, %s, %s", self.buttonDec:getMinMaxXY()))
  489.     self.buttonDec:setMinMaxXY(minx, minx+1, miny+1, maxy-1)
  490.     --print(string.format("buttonDec: %s, %s, %s, %s", self.buttonDec:getMinMaxXY()))
  491.     self.buttonDec:setTextPosition({h = "right", v = "center"})
  492.     self.buttonInc:setMinMaxXY(maxx-1, maxx, miny+1, maxy-1)
  493.     --print(string.format("buttonInc: %s, %s, %s, %s", self.buttonDec:getMinMaxXY()))
  494.     self.buttonInc:setTextPosition({h = "left", v = "center"})
  495.    
  496. end
  497.  
  498. --- Sets the function that should be executed when clicking on the "+"-button
  499. -- @param func the function
  500. function Picker:setIncFunction(func)
  501.     self.buttonInc.func = func
  502. end
  503. --- Sets the function that should be executed when clicking on the "-"-button
  504. -- @param func the function
  505. function Picker:setDecFunction(func)
  506.     self.buttonDec.func = func
  507. end
  508.  
  509. --- Executes decreasing or increasing function, according to which button was actualy clicked
  510. function Picker:execFunction()
  511.     if self.clickedInc then
  512.         self.currentIndex = self.currentIndex + 1
  513.         if self.currentIndex > #self.values then
  514.             self.currentIndex = 1
  515.         end
  516.         local param = tostring(self.values[self.currentIndex])
  517.         self.buttonInc:setFuncParams({param})
  518.         self.buttonInc:execFunction()
  519.         self.clickedInc = false
  520.         self:draw(self.target)
  521.     elseif self.clickedDec then
  522.         self.currentIndex = self.currentIndex - 1
  523.         if self.currentIndex < 1 then
  524.             self.currentIndex = #self.values
  525.         end
  526.         local param = tostring(self.values[self.currentIndex])
  527.         self.buttonDec:setFuncParams({param})
  528.         self.buttonDec:execFunction()
  529.         self.clickedInc = false
  530.         self:draw(self.target)
  531.     end
  532. end
  533. --~ ##### Picker END #####
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement