Advertisement
TheOddByte

[ComputerCraft][API] Object

Sep 28th, 2014
336
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.45 KB | None | 0 0
  1. --[[
  2.     [API] Object
  3.     @version 1.0, 2014-09-028
  4.     @author TheOddByte
  5. --]]
  6.  
  7.  
  8.  
  9.  
  10. local w, h = term.getSize()
  11.  
  12.  
  13. function load( self, path )
  14.     if not fs.isDir( path ) then
  15.         self[fs.getName( path )] = dofile( path )
  16.     end    
  17. end
  18.  
  19.  
  20.  
  21. Dropdown = {}
  22. Dropdown.__index = Dropdown
  23.  
  24. Dropdown.new = function( properties )
  25.  
  26.     local dropdown    = {}
  27.     local properties  = properties or error( "dropdown: no properties inputted", 2 )
  28.     dropdown.options  = properties.options or error( "dropdown: no options inputted", 2 )
  29.     dropdown.centered = properties.centered or false
  30.     dropdown.width    = type( properties.width ) == "number" and properties.width or error( "dropdown:width: number expected, got " .. type( properties.width ) )
  31.     if not dropdown.centered then
  32.         dropdown.x = type( properties.x ) == "number" and properties.x or error( "dropdown:x: number expected, got " .. type( properties.x ), 2 )
  33.     else
  34.         dropdown.x = math.ceil( (w-dropdown.width)/2 ) - 1
  35.     end
  36.     dropdown.y                = type( properties.y ) == "number" and properties.y or error( "dropdown:y: number expected, got " .. type( properties.y ), 2 )
  37.     dropdown.index            = 1;
  38.     dropdown.drop             = false;
  39.     dropdown.text_color       = properties.text_color or colors.white;
  40.     dropdown.background_color = properties.background_color or colors.gray;
  41.     dropdown.button           = properties.button or { background_color = colors.lightGray; text_color = colors.white; }
  42.     dropdown.type             = "dropdown"
  43.    
  44.     return setmetatable( dropdown, Dropdown )
  45. end
  46.  
  47.  
  48. function Dropdown:draw()
  49.     draw.line( self.x, self.y, self.width, self.text_color, self.background_color )
  50.     draw.setColors( self.button.text_color, self.button.background_color )
  51.     if self.drop then
  52.         term.write( "^" )
  53.         draw.line( self.x, self.y + 1, self.width, self.text_color, self.background_color )
  54.         draw.at( self.x, self.y + 1, string.rep( "-", self.width ) )
  55.         for i = 1, #self.options do
  56.             draw.line( self.x, self.y + i + 1, self.width, self.text_color, self.background_color )
  57.             draw.midpoint( self.x, (self.x + self.width)-1, self.y + i + 1, self.options[i] )
  58.         end
  59.     else
  60.         term.write( "v" )
  61.     end
  62.     draw.setColors( self.text_color, self.background_color )
  63.     draw.midpoint( self.x, (self.x + self.width)-1, self.y, self.options[self.index] )
  64. end
  65.  
  66.  
  67. function Dropdown:handle( ... )
  68.     local e = { ... }
  69.     if e[1] == "mouse_click" then
  70.         if e[4] == self.y then
  71.             if e[3] >= self.x and e[3] <= self.x + self.width then
  72.                 if self.drop then
  73.                     self.drop = false
  74.                 else
  75.                     self.drop = true
  76.                 end
  77.             end
  78.         end
  79.         if self.drop then
  80.             if e[4] < self.y or e[4] > self.y + #self.options+1 or e[3] < self.x or e[3] > self.x + self.width then
  81.                 self.drop = false
  82.             end
  83.         end
  84.         if self.drop then
  85.             for i = 1, #self.options do
  86.                 if e[4] == self.y + i + 1 and e[3] >= self.x and e[3] <= self.x + self.width-1 then
  87.                     self.index = i
  88.                     self.drop = false
  89.                     break
  90.                 end
  91.             end
  92.         end
  93.     end    
  94. end
  95.  
  96.  
  97.  
  98.  
  99. Textbox = {}
  100. Textbox.__index = Textbox
  101.  
  102. Textbox.new = function( properties )
  103.     local textbox = {}
  104.    
  105.    
  106.     local properties      = properties or {}
  107.     textbox.type          = "textbox"
  108.     textbox.text          = ""
  109.     textbox.pos           = 0;
  110.     textbox.sPos          = 0;
  111.     textbox.fPos          = 0;
  112.     textbox.selected      = false;
  113.     textbox.mark          = false;
  114.     textbox.mx            = false;
  115.     textbox.cursor_blink  = properties.cursor_blink or true
  116.     textbox.placeholder   = properties.placeholder.text and properties.placeholder or nil
  117.     textbox.text_limit    = properties.text_limit
  118.     textbox.width         = properties.width
  119.     textbox.mask          = properties.mask
  120.     textbox.blocked_chars = properties.blocked_chars
  121.     textbox.allowed_chars = properties.allowed_chars
  122.     textbox.marker        = properties.marker
  123.     textbox.x             = properties.x
  124.     textbox.y             = properties.y
  125.     textbox.active        = properties.active or false
  126.    
  127.     textbox.native_text_color       = properties.native_text_color
  128.     textbox.native_background_color = properties.native_background_color
  129.    
  130.     return setmetatable( textbox, Textbox )
  131. end
  132.  
  133.  
  134. function Textbox:draw()
  135.    
  136.     --# Format text( remove blocked characters )
  137.     if self.blocked_chars then
  138.         for i = 1, #self.blocked_chars do
  139.             self.text = self.text:gsub( self.blocked_chars:sub( i, i ), "" )
  140.         end
  141.     end
  142.     if self.allowed_chars then
  143.         local _text = ""
  144.         for i = 1, #self.text do
  145.             for k = 1, #self.allowed_chars do
  146.                 if self.text:sub( i,i ) == self.allowed_chars:sub( k, k ) then
  147.                     _text = _text .. self.text:sub( i,i )
  148.                     break
  149.                 end
  150.             end
  151.         end
  152.         self.text = _text
  153.     end
  154.     if self.pos > #self.text then
  155.         self.pos = #self.text
  156.     end
  157.            
  158.    
  159.     --# Redraw text
  160.     draw.line( self.x, self.y, self.width, self.native_text_color, self.native_background_color )
  161.     term.setCursorPos( self.x + #self.text, self.y )
  162.     term.write( " " )
  163.     term.setCursorPos( self.x + 1, self.y )
  164.     if self.placeholder then
  165.         if #self.text == 0 then
  166.             if self.placeholder.text_color then
  167.                 pcall( term.setTextColor, self.placeholder.text_color )
  168.             end
  169.             term.setCursorBlink( self.active and self.placeholder.cursor_blink or true )
  170.         else
  171.             if self.native_text_color then
  172.                 pcall( term.setTextColor, self.native_text_color )
  173.             end
  174.         end
  175.         if self.mask then
  176.             term.write( #self.text > 0 and string.rep( self.mask:sub(1,1), #self.text ) or self.placeholder.text )
  177.         else
  178.             term.write( #self.text > 0 and self.text or self.placeholder.text )
  179.         end
  180.     else
  181.         term.write( self.mask and string.rep( self.mask:sub(1,1), #self.text ) or self.text )
  182.     end
  183.     if self.selected then
  184.         term.setCursorBlink( self.active and false )
  185.         pcall( term.setTextColor, self.marker and self.marker.text_color or colors.white )
  186.         pcall( term.setBackgroundColor, self.marker and self.marker.background_color or colors.blue )
  187.         local str = ""
  188.         for i = self.sPos, self.fPos do
  189.             str = str .. self.text:sub( i, i )
  190.         end
  191.         term.setCursorPos( self.x + 1 + (self.sPos-1), self.y )
  192.         term.write( self.mask and string.rep( self.mask, #str ) or str )
  193.         pcall( term.setTextColor, self.native_text_color )
  194.         pcall( term.setBackgroundColor, self.native_background_color )
  195.     else
  196.         term.setCursorBlink( self.active and self.cursor_blink )
  197.     end
  198.     term.setCursorPos( self.placeholder and #self.text > 0 and self.x + 1 + self.pos or self.x + 1 + #self.placeholder.text, self.y )
  199.  
  200. end
  201.  
  202.  
  203. function Textbox:handle( ... )
  204.  
  205.     term.setCursorBlink( self.active and self.cursor_blink )
  206.    
  207.     local function redraw()
  208.         pcall( term.setTextColor, self.native_text_color )
  209.         pcall( term.setBackgroundColor, self.native_background_color )
  210.         term.setCursorPos( self.x, self.y )
  211.         term.write( string.rep( " ", #self.text + 1 ) )
  212.     end
  213.  
  214.  
  215.     --# Handle events
  216.     local e = { ... }
  217.     if self.active then
  218.         if e[1] == "char" then
  219.             if self.placeholder.text and #self.text == 0 then
  220.                 for i = 1, #self.placeholder.text do
  221.                     term.setCursorPos( self.x + (i-1), self.y )
  222.                     term.write( " " )
  223.                 end
  224.             end
  225.             if not self.text_limit then
  226.                 if not self.selected then
  227.                     self.text = self.text:sub( 1, self.pos ) .. e[2] .. self.text:sub( self.pos + 1 )
  228.                     self.pos = self.pos + 1
  229.                 else
  230.                     redraw()
  231.                     self.text = self.text:sub( 1, self.sPos - 1 ) .. e[2] .. self.text:sub( self.fPos + 1 )
  232.                     self.pos = self.sPos
  233.                     self.selected = false
  234.                 end                
  235.             else
  236.                 if #self.text < self.text_limit then
  237.                     if not self.selected then
  238.                         self.text = self.text:sub( 1, self.pos ) .. e[2] .. self.text:sub( self.pos + 1 )
  239.                         self.pos = self.pos + 1
  240.                     else
  241.                         redraw()
  242.                         self.text = self.text:sub( 1, self.sPos - 1 ) .. e[2] .. self.text:sub( self.fPos + 1 )
  243.                         self.pos = self.sPos
  244.                         self.selected = false
  245.                     end
  246.                 else
  247.                     if self.selected then
  248.                         self.text = self.text:sub( 1, self.sPos - 1 ) .. e[2] .. self.text:sub( self.fPos + 1 )
  249.                         self.pos = self.pos + 1
  250.                         self.selected = false
  251.                     end
  252.                 end
  253.             end
  254.        
  255.         elseif e[1] == "key" then
  256.             if e[2] == 14 then
  257.                 if self.selected then
  258.                     redraw()
  259.                     self.text = self.text:sub( 1, self.sPos - 1 ) .. self.text:sub( self.fPos + 1 )
  260.                     self.selected = false
  261.                     self.pos = self.sPos - 1
  262.                 else
  263.                     if #self.text > 0 and self.pos > 0 then
  264.                         self.text = self.text:sub( 1, self.pos - 1 ) .. self.text:sub( self.pos + 1 )
  265.                         self.pos = self.pos - 1
  266.                     end
  267.                 end
  268.            
  269.             elseif e[2] == keys.left then
  270.                 self.selected = false
  271.                 self.pos = self.pos > 0 and self.pos - 1 or self.pos
  272.                
  273.             elseif e[2] == keys.right then
  274.                 self.selected = false
  275.                 self.pos = self.pos < #self.text and self.pos + 1 or self.pos
  276.            
  277.             elseif e[2] == 28 then
  278.                 self.active = false
  279.             end
  280.            
  281.         elseif e[1] == "mouse_click" then
  282.             if e[3] >= self.x + 1 and e[3] <= self.x + 1 + #self.text and e[4] == self.y then
  283.                 self.pos = e[3] - (self.x+1)
  284.                 self.mark = true
  285.                 self.mx = e[3]
  286.             else
  287.                 self.mx = nil
  288.                 self.mark = false
  289.             end
  290.             if e[4] == self.y and e[3] > self.x + 1 + #self.text and e[3] <= self.x + (self.width-1) then
  291.                 self.pos = self.x + 2 + #self.text
  292.             end
  293.             self.selected = false
  294.            
  295.             if e[4] ~= self.y or e[3] < self.x or e[3] > self.x + ( self.width - 1 ) then
  296.                 self.active = false
  297.             end
  298.            
  299.         elseif e[1] == "mouse_drag" then
  300.             if self.mark then
  301.                 self.selected = true;
  302.                 if e[3] == self.mx then
  303.                     self.selected = false
  304.                 else
  305.                     self.selected = true
  306.                     if e[3] >= self.x + 1 and e[3] <= self.x + 1 + #self.text then
  307.                         if e[3] < self.mx then
  308.                             self.sPos = (e[3] - (self.x+1)) + 1;
  309.                             self.fPos = (self.mx - (self.x+1)) + 1;
  310.                         elseif e[3] > self.mx then
  311.                             self.sPos = (self.mx - (self.x+1)) + 1;
  312.                             self.fPos = (e[3] - (self.x+1)) + 1;
  313.                         end
  314.                     else
  315.                         if self.mx == self.x + #self.text then
  316.                             if e[3] > self.x + #self.text then
  317.                                 self.selected = false;
  318.                             end
  319.                         end
  320.                     end
  321.                 end
  322.             end
  323.         end
  324.     else
  325.         if e[1] == "mouse_click" then
  326.             if e[4] == self.y and e[3] >= self.x and e[3] <= self.x + ( self.width - 1 ) then
  327.                 self.active = true;
  328.             end
  329.         end
  330.     end
  331. end
  332.  
  333.  
  334.  
  335.  
  336. Button = {}
  337. Button.__index = Button
  338.  
  339. function Button.new( properties )
  340.     local button = {}
  341.     button.text             = type( properties.text ) == "string" and properties.text or "Unlabeled"
  342.     button.text_color       = type( properties.text_color ) == "number" and properties.text_color or colors.white
  343.     button.background_color = type( properties.background_color ) == "number" and properties.background_color or colors.red
  344.     button.centered         = type( properties.centered ) == "boolean" and properties.centered or false
  345.     button.width            = type( properties.width ) == "number" and properties.width or #button.text + 2
  346.     button.y                = type( properties.y ) == "number" and properties.y or error( "no y coordinate assigned",2 )
  347.     if button.width < #button.text + 2 then
  348.         button.width = #button.text + 2
  349.     end
  350.     button.x                = button.centered and math.ceil( (w-button.width)/2 ) or type( properties.x ) == "number" and properties.x or error( "no x coordinate assigned", 2 )
  351.     button.type             = "button"
  352.     button.action           = type( properties.action ) == "function" and properties.action or nil
  353.    
  354.  
  355.     return setmetatable( button, Button )
  356. end
  357.  
  358.  
  359. function Button:draw()
  360.     draw.line( self.x, self.y, self.width, self.text_color, self.background_color )
  361.     draw.midpoint( self.x, self.x + (self.width-1), self.y, self.text )
  362. end
  363.  
  364.  
  365. function Button:handle( ... )
  366.    
  367.     local e = { ... }
  368.     if e[1] == "mouse_click" then
  369.         if e[3] >= self.x and e[3] <= self.x + (self.width-1) and e[4] == self.y then
  370.             if type( self.action ) == "function" then
  371.                 self.action( self )
  372.             end
  373.         end
  374.     end
  375.    
  376. end
  377.  
  378.  
  379.  
  380.  
  381. local function format_body( body, max_width )
  382.     local formatted_body = {}
  383.     for _, text in ipairs( body ) do
  384.    
  385.         if #text > max_width then
  386.             local txt = ""
  387.             for word in text:gmatch("%S+") do
  388.                 local str = txt
  389.                 if str ~= "" then
  390.                     str = str .. " " .. word
  391.                 else
  392.                     str = str .. word
  393.                 end
  394.                 if #str > max_width then
  395.                     table.insert( formatted_body, txt )
  396.                     txt = ""
  397.                     txt = txt .. word
  398.                 else
  399.                     if txt ~= "" then
  400.                         txt = txt .. " " .. word
  401.                     else
  402.                         txt = txt .. word
  403.                     end
  404.                 end
  405.             end
  406.             if txt ~= "" then
  407.                 table.insert( formatted_body, txt )
  408.             end
  409.            
  410.         else
  411.             table.insert( formatted_body, text )
  412.         end
  413.        
  414.     end
  415.     return formatted_body
  416. end
  417.  
  418.  
  419. Text = {}
  420. Text.__index = Text
  421.  
  422. Text.new = function( properties )
  423.     local text = {}
  424.     local properties = properties or error( "no properties inputted", 2 )
  425.     text.body = properties.body or error( "no body!", 2 )
  426.     text.text_color = properties.text_color
  427.     text.background_color = properties.background_color
  428.     text.width      = properties.width or nil
  429.     text.x          = properties.x
  430.     text.y          = properties.y
  431.     text.centered   = properties.centered or false
  432.    
  433.    
  434.     if text.width then
  435.         if type( text.body ) == "string" then
  436.             local txt = text.body
  437.             text.body = {}
  438.             table.insert( text.body, txt )
  439.         end
  440.         text.body = format_body( text.body, text.width )
  441.     end
  442.    
  443.     return setmetatable( text, Text )
  444. end
  445.  
  446.  
  447. function Text:draw()
  448.     draw.setColors( self.text_color, self.background_color )
  449.     if type( self.body ) == "string" then
  450.         draw.at( self.centered == true and math.ceil( (w-#self.body)/2 ) or self.x, self.y, self.body )
  451.        
  452.     elseif type( self.body ) == "table" then
  453.         for i = 1, #self.body do
  454.             draw.at( self.centered and math.ceil((w-#self.body[i])/2) or self.x, self.y + (i-1), self.body[i] )
  455.         end
  456.     end
  457. end
  458.  
  459. function Text:handle() end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement