MiStAWaFFlEZZ

curllib

Apr 21st, 2019
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.31 KB | None | 0 0
  1. local component = require("component");
  2. local term = require("term");
  3. local keyboard = require("keyboard");
  4. local txt = require("text");
  5. local s = require("serialization");
  6. local event = require("event");
  7. local computer = require("computer");
  8. local align = require("textalign");
  9. local unicode = require("unicode")
  10.  
  11. local gpu = component.gpu;
  12.  
  13. if gpu.getDepth() < 4 then
  14.   error("curlib requires at least a tier2 screen/gpu... ");
  15. end
  16.  
  17. local curlib = {};
  18.  
  19. curlib.getParamErrorMsg = function (fnc, param)
  20.   fnc = fnc or "fnc";
  21.   param = param or "parameter"
  22.   return param .. " cannot be nil! did you forgot do call function '"
  23.     .. fnc .. "' as 'obj:" .. fnc .. "'?";
  24. end
  25.  
  26. curlib.defaults = {};
  27. curlib.defaults.app = {};
  28. curlib.defaults.control = {};
  29. curlib.defaults.window = {};
  30. curlib.defaults.button = {};
  31. curlib.defaults.input = {};
  32.  
  33. --TODO get this from a configuration file;
  34. curlib.defaults.shadow = 0x101010;
  35. curlib.defaults.app.background = 0x484848;
  36. curlib.defaults.app.foreground = 0xCCCCCC;
  37. curlib.defaults.control.background = 0x333333;
  38. curlib.defaults.control.foreground = 0xCCCCCC;
  39. curlib.defaults.window.foreground = 0x383838;
  40. curlib.defaults.window.background = 0xA0A0A0;
  41. curlib.defaults.button.foreground = 0xCCCC00;
  42. curlib.defaults.button.background = 0x000066;
  43. curlib.defaults.input.foreground = 0x101010;
  44. curlib.defaults.input.background = 0xE0E0E0;
  45.  
  46. curlib.palette = {};
  47. curlib.orgPalette = {};
  48.  
  49. if gpu.getDepth() == 4 then
  50.   local pNum = 1
  51.   for k, v in pairs(curlib.defaults) do
  52.     if k == "shadow"
  53.       or k == "foreground"
  54.       or k == "background"
  55.       or k == "color"
  56.     then
  57.       if curlib.palette[v] == nil then
  58.         curlib.palette[v] = pNum;
  59.         pNum = pNum + 1;
  60.       end
  61.     else
  62.       if type(v) == "table" then
  63.         for kl, vl in pairs(v) do
  64.           if kl == "shadow"
  65.             or kl == "foreground"
  66.             or kl == "background"
  67.             or kl == "color"
  68.           then
  69.             if curlib.palette[vl] == nil then
  70.               curlib.palette[vl] = pNum;
  71.               pNum = pNum + 1;
  72.             end
  73.           end
  74.         end
  75.       end
  76.     end
  77.     if (pNum > 16) then
  78.       error("curlib: more then 16 unique colors found in configuration. we need a better screen/gpu");    
  79.     end
  80.   end
  81.   for k, v in pairs(curlib.palette) do
  82.     curlib.orgPalette[v] = gpu.getPaletteColor(v);
  83.     gpu.setPaletteColor(v, k);
  84.   end
  85. end
  86.  
  87. curlib.cleanPalette = function()
  88.   for k, v in pairs(curlib.orgPalette) do
  89.     gpu.setPaletteColor(k, v);
  90.   end
  91. end
  92.  
  93. curlib.screen = {};
  94. curlib.screen.cursor = {}
  95. curlib.screen.cursor.blink = false;
  96. curlib.screen.cursor.x = 1;
  97. curlib.screen.cursor.y = 1;
  98.  
  99. curlib.control = {};
  100.  
  101. curlib.control.new = function(self, obj)
  102.   if not self then error(curlib.getParamErrorMsg("new", "self")); end
  103.   obj = obj or {};
  104.   setmetatable(obj, self);
  105.   self.__index = self;    
  106.  
  107.   gpu.setForeground(0xFFFFFF);
  108.  
  109.   --defaults
  110.   obj.x = obj.x or 1;
  111.   obj.y = obj.y or 1;
  112.   obj.width = obj.width or 10;
  113.   obj.height = obj.height or 1;
  114.   obj.children = obj.children or {};
  115.   obj.dirty = true;
  116.   obj.visible = true;
  117.   obj.shadow = obj.shadow or false;
  118.   obj.foreground = obj.foreground or curlib.defaults.control.foreground;
  119.   obj.background = obj.background or curlib.defaults.control.background;
  120.  
  121.   return obj;
  122. end
  123.  
  124. curlib.control.status = function(text)
  125.   local width, height = gpu.getResolution();
  126.   gpu.setForeground(0xFF0000);
  127.   gpu.fill(1, height, width, height, " ");
  128.   gpu.set(1, height, text);
  129. end
  130.  
  131. curlib.control.clearFocus = function(self, fulltree)
  132.   if not self then error(curlib.getParameterErrorMsg("clearFocus", "self")); end
  133.  
  134.   if fulltree then
  135.     local root = self;
  136.  
  137.     while root.parent do
  138.       root = root.parent;
  139.     end
  140.  
  141.     self = root;    
  142.   end
  143.  
  144.   for k, v in ipairs(self.children) do
  145.     v:clearFocus(false);
  146.   end
  147.  
  148.   if self.focus then
  149.     self.focus = false;
  150.     self.lostFocus = true;
  151.   end
  152.  
  153. end
  154.  
  155. curlib.control.setFocus = function(self, focus)
  156.   if not self then error(curlib.getParamErrorMsg("focus", "self")); end
  157.   focus = (focus == nil) or true;
  158.  
  159.   if focus then
  160.     self:clearFocus(true);
  161.   elseif self.focus then
  162.     self.lostFocus = true;
  163.   end
  164.  
  165.   self.focus = focus;
  166. end
  167.  
  168. curlib.control.addChild = function(self, control)
  169.   if not self then error(curlib.getParamErrorMsg("addChild", "self")); end
  170.   if not control then error(curlib.getParamErrorMsg("new", "control")); end
  171.   if not self.children then self.children = {}; end
  172.   table.insert(self.children, control);
  173.   control.parent = self;
  174. end
  175.  
  176. curlib.control.updateColors = function(self)
  177.   if not self then error(curlib.getParamErrorMsg("updateColors", "self")); end
  178.   if not self.foreground then self.foreground = curlib.defaults.foreground; end
  179.   if not self.background then self.background = curlib.defaults.background; end
  180.  
  181.   local fg = self.flashColors and self.background or self.foreground;
  182.   local bg = self.flashColors and self.foreground or self.background;
  183.  
  184.   gpu.setForeground(fg);
  185.   gpu.setBackground(bg);
  186.  
  187.   return fg, bg;
  188. end
  189.  
  190. curlib.control.invalidate = function(self, invalidateChildren)
  191.   if not self then error(curlib.getParamErrorMsg("invalidate", "self")); end
  192.   self.dirty = true;
  193.   if invalidateChildren == nil and invalidateChildren or true then
  194.     for k, v in ipairs(self.children) do
  195.       v:invalidate(invalidateChildren);
  196.     end
  197.   end
  198. end
  199.  
  200. curlib.control.drawChildren = function(self)
  201.   if not self then error(curlib.getParamErrorMsg("drawChildren", "self")); end
  202.   if self.children then
  203.     for k, v in ipairs(self.children) do
  204.       v:draw();
  205.     end
  206.   end  
  207. end
  208.  
  209. curlib.control.getScreenCoords = function (self)
  210.  
  211.   local px = 1;
  212.   local py = 1;
  213.  
  214.   if self.parent then
  215.     px, py = self.parent:getScreenCoords();
  216.   end
  217.  
  218.   local x = self.x + px -1;
  219.   local y = self.y + py -1;
  220.   return x, y;
  221. end
  222.  
  223. curlib.control.drawShadow = function(self)
  224.   if not self then error(curlib.getParamErrorMsg("drawShadow", "self")); end
  225.   if not self.shadow then return; end
  226.   if not self.parent then return; end;
  227.  
  228.   local bg = self.parent.background;
  229.  
  230.   gpu.setForeground(curlib.defaults.shadow);
  231.   gpu.setBackground(bg);
  232.  
  233.   local x, y  = self:getScreenCoords();
  234.  
  235.   gpu.set(x + self.width, y, "▄");
  236.   gpu.fill(x + self.width, y + 1, 1, self.height -1, "█");
  237.   gpu.fill(x + 1, y + self.height, self.width, 1, "▀");
  238.  
  239. end
  240.  
  241. curlib.control.draw = function(self)
  242.   if not self then error(curlib.getParamErrorMsg("draw", "self")); end
  243.   if self.visible then
  244.     if self.dirty then
  245.       self.dirty = false;
  246.       self:updateColors();
  247.  
  248.       local x, y = self:getScreenCoords();
  249.  
  250.       gpu.fill(x, y, self.width, self.height, " ");
  251.       self:drawShadow();
  252.     end
  253.  
  254.     self:drawChildren();
  255.   end
  256.  
  257. end
  258.  
  259. curlib.control.__onClick = function(self, x, y)
  260.  
  261.   self.status("click " .. x .. "," .. y);
  262.  
  263.   local done = false;
  264.  
  265.   if self.children then
  266.     for k, v in ipairs(self.children) do
  267.       done = v:__onClick(x, y);
  268.       if (done) then goto ctrlOnClickContinue; end
  269.     end
  270.     ::ctrlOnClickContinue::
  271.   end
  272.  
  273.   local sx, sy = self:getScreenCoords();
  274.  
  275.   if not done
  276.     and x >= sx
  277.     and y >= sy
  278.     and x <= sx + self.width
  279.     and y <= sy + self.height
  280.   then
  281.     self:setFocus(true);
  282.     if self.onClick then self:onClick(x, y); end
  283.     return true;
  284.   else
  285.     return done;
  286.   end
  287. end
  288.  
  289.  
  290. curlib.control.__onKeyDown = function(self, char, code)
  291.  
  292.   local done = false;
  293.   if self and self.children then
  294.     for k, v in ipairs(self.children) do
  295.       done = v:__onKeyDown(char, code);
  296.       if (done) then goto ctrlOnKeyDownContinue; end
  297.     end
  298.     ::ctrlOnKeyDownContinue::
  299.   end
  300.  
  301.   if self and self.focus then
  302.     if self.onKeyDown then
  303.       self:onKeyDown(char, code);
  304.     end
  305.     return true;
  306.   else
  307.     return done;
  308.   end
  309. end
  310.  
  311. curlib.control.__onKeyUp = function(self, char, code)
  312.  
  313.   local done = false;
  314.   if self and self.children then
  315.     for k, v in ipairs(self.children) do
  316.       done = v:__onKeyUp(char, code);
  317.       if (done) then goto ctrlOnKeyUpContinue; end
  318.     end
  319.     ::ctrlOnKeyUpContinue::
  320.   end
  321.  
  322.   if self and self.focus then
  323.     if self.onKeyUp then
  324.       self:onKeyUp(char, code);
  325.     end
  326.     return true;
  327.   else
  328.     return done;
  329.   end
  330. end
  331.  
  332.  
  333. curlib.control.doEvent = function (self, eventId, addr, arg1, arg2, arg3)
  334.   if not self then error(curlib.getParamErrorMsg("doEvent", "self")); end
  335.   if eventId == "key_down" then
  336.     return self:__onKeyDown(arg1, arg2);
  337.   elseif eventId == "touch" or eventId == "drag" then
  338.     return self:__onClick(arg1, arg2);
  339.   else return false; end
  340. end
  341.  
  342. curlib.app = curlib.control:new();
  343.  
  344. curlib.app.new = function (self, obj)
  345.   obj = obj or {};
  346.   obj.background = obj.background or curlib.defaults.app.background;
  347.   obj.foreground = obj.foreground or curlib.defaults.app.foreground;
  348.   obj = curlib.control.new(self, obj);
  349.   obj.width, obj.height = gpu.getResolution();
  350.   return obj;
  351. end
  352.  
  353. curlib.app.init = function(self)
  354.   if not self then error(curlib.getParamErrorMsg("init", "self")); end
  355.   self:draw();
  356. end
  357.  
  358. curlib.app.doEvents = function(self)
  359.   if not self then error(curlib.getParamErrorMsg("doEvents", "self")); end
  360.  
  361. --  self.status("free memory "
  362. --    .. tostring(computer.freeMemory()) .. " of "
  363. --    .. tostring(computer.totalMemory())
  364. --  );    
  365. --  os.sleep();
  366.  
  367.   local eventId, attr, arg1, arg2, arg3 = event.pull();
  368.  
  369.   if (eventId) then
  370.     os.sleep();
  371.     done = self:doEvent(eventId, attr, arg1, arg2, arg3)
  372.  
  373.     if done then
  374.       curlib.screen.cursor.blink = false;
  375.       term.setCursorBlink(false);
  376.  
  377.       self:draw();
  378.  
  379.       if (curlib.screen.cursor.blink) then
  380.         gpu.setForeground(curlib.screen.cursor.foreground);
  381.         gpu.setBackground(curlib.screen.cursor.background);
  382.         term.setCursorBlink(true)
  383.         term.setCursor(curlib.screen.cursor.x, curlib.screen.cursor.y);
  384.       else
  385.         term.setCursorBlink(false)
  386.       end
  387.     end
  388.  
  389.   end
  390.  
  391.   return eventId, addr, arg1, arg2, arg3; --this event is not mine
  392.  
  393. end
  394.  
  395. curlib.window = curlib.control:new()
  396.  
  397. curlib.window.new = function(self, obj)
  398.   obj = obj or {};
  399.   obj.background = obj.background or curlib.defaults.window.background;
  400.   obj.foreground = obj.foreground or curlib.defaults.window.foreground;
  401.   obj.title = obj.title or "window";
  402.   obj.shadow = obj.shadow or true;
  403.   obj = curlib.control.new(self, obj);
  404.   return obj;
  405. end
  406.  
  407. curlib.button = curlib.control:new()
  408.  
  409. curlib.button.new = function(self, obj)
  410.   obj = obj or {};
  411.   obj.foreground = obj.foreground or curlib.defaults.button.foreground;
  412.   obj.background = obj.background or curlib.defaults.button.background;
  413.   obj.shadow = obj.shadow or true;
  414.   obj.align = obj.align or align.direction.middleCenter;
  415.   obj = curlib.control.new(self, obj);
  416.   return obj;
  417. end
  418.  
  419. curlib.button.__onClick = function (self, x, y)
  420.   local ok = curlib.control.__onClick(self, x, y);
  421.   if (ok) then
  422.     self.dirty = true;
  423.     self.flashColors = true;
  424.   end
  425.   return ok;
  426. end
  427.  
  428. curlib.button.draw = function (self)
  429.   if not self then error(curlib.getParamErrorMsg("draw", "self")); end
  430.   if not self.text then self.text = "BTN"; end
  431.  
  432.   if self.visible then
  433.     if self.dirty then
  434.      
  435.       gpu.setForeground(self.parent and self.parent.foreground or self.foreground);
  436.       gpu.setBackground(self.parent and self.parent.background or self.background);
  437.       local x, y = self:getScreenCoords();
  438.  
  439.       local txtTable = align.align(self.text, self.width, self.height or 1, self.align);      
  440.  
  441.       self:updateColors();
  442.      
  443.       local ln = 0;
  444.       for k, v in ipairs(txtTable) do
  445.         gpu.set(x, y + ln, v);
  446.         ln = ln + 1;
  447.       end
  448.      
  449.       self:drawShadow();
  450.  
  451.       if self.flashColors then
  452.         self.flashColors = false;
  453.         for n = 1, 10 do os.sleep(); end
  454.         self:draw();
  455.       end
  456.       self.dirty = false;
  457.  
  458.     end
  459.     self:drawChildren();    
  460.   end      
  461. end
  462.  
  463. curlib.text = curlib.control:new();
  464.  
  465. curlib.text.draw = function(self)
  466.   if not self then error(curlib.getParamErrorMsg("draw", "self")); end
  467.   if not self.text then self.text = "..."; end;
  468.  
  469.  
  470.   if self.visible then
  471.     if self.dirty then
  472.  
  473.       gpu.setForeground(self.parent and self.parent.foreground or self.foreground);
  474.       gpu.setBackground(self.parent and self.parent.background or self.background);
  475.       local x, y = self:getScreenCoords();
  476.  
  477.       local txtTable = align.align(self.text, self.width, nil, self.align);      
  478.       local ln = 0;
  479.       for k, v in ipairs(txtTable) do
  480.         gpu.set(x, y + ln, v);
  481.         ln = ln + 1;
  482.       end
  483.  
  484.       self.dirty = false;
  485.     end
  486.   end  
  487.  
  488. end
  489.  
  490. curlib.input = curlib.control:new();
  491.  
  492. curlib.input.new = function (self, obj)
  493.   obj = obj or {};
  494.   obj.foreground = obj.foreground or curlib.defaults.input.foreground;
  495.   obj.background = obj.background or curlib.defaults.input.background;
  496.   obj.width = obj.width or 10;
  497.   obj.height = 1;
  498.   obj.text = obj.text or "";
  499.   obj.shadow = obj.shadow or true;
  500.   obj.cursor = {};
  501.   obj.cursor.position = unicode.len(obj.text) + 1;
  502.   obj.cursor.scrollX = 0;
  503.   obj.focus = false;
  504.   obj = curlib.control.new(self, obj);
  505.   return obj;
  506. end
  507.  
  508. curlib.input.insert = function (self, value)
  509.   if not value or unicode.len(value) < 1 then
  510.     return
  511.   end
  512.   term.setCursorBlink(false)
  513.   self.text = unicode.sub(self.text, 1, self.cursor.position - 1) ..
  514.                 value ..
  515.                 unicode.sub(self.text, self.cursor.position)
  516.   self.cursor.position = self.cursor.position + 1;
  517.   if (self.cursor.position > self.width) then
  518.     self.cursor.scrollX =
  519.       self.cursor.position - self.width;
  520.   end
  521.   self.dirty = true;
  522.  
  523.   --we need to be fast with this draw so, we will just draw the input
  524.   --and return false to avoid a a search and draw of every dirty control out there
  525.   self:draw();
  526.   return false;
  527. end
  528.  
  529. curlib.input.delete = function (self)
  530.   term.setCursorBlink(false)
  531.   local p1 = unicode.sub(self.text, 1, self.cursor.position - 1)
  532.   local p2 = unicode.sub(self.text, self.cursor.position)
  533.   if p2 and unicode.len(p2) > 0 then
  534.     p2 = unicode.sub(p2, 2);
  535.   end
  536.   self.text = p1 .. p2;
  537.   self.dirty = true;
  538.   self:draw();
  539.   return false;
  540. end
  541.  
  542. curlib.input.backspace = function (self)
  543.   term.setCursorBlink(false)
  544.   local p1 = unicode.sub(self.text, 1, self.cursor.position - 1)
  545.   local p2 = unicode.sub(self.text, self.cursor.position)
  546.   if p1 and unicode.len(p1) > 0 then
  547.     p1 = unicode.sub(p1, 1, unicode.len(p1) -1);
  548.     self.cursor.position = self.cursor.position -1;
  549.   end
  550.   self.text = p1 .. p2;
  551.   self.dirty = true;
  552.   return true;
  553. end
  554.  
  555. curlib.input.__onKeyDown = function (self, char, code)
  556.   if self and self.focus then
  557.     if code == keyboard.keys.enter then
  558.       self.focus = false;
  559.       self.lostFocus = true;
  560.       return true;
  561.     elseif code == keyboard.keys.delete then
  562.       return self:delete();
  563.     elseif code == keyboard.keys.back then
  564.       return self:backspace();
  565.     elseif not keyboard.isControl(char) then
  566.       return self:insert(unicode.char(char))
  567.     end
  568.   end
  569.   return false;
  570. end
  571.  
  572. curlib.input.__onClick = function (self, x, y)  
  573.   local ok = curlib.control.__onClick(self, x, y);
  574.   if (ok) then
  575.     self.dirty = true;
  576.   end
  577.   return ok;
  578. end
  579.  
  580. curlib.input.draw = function(self, fast)
  581.   if not self then error(curlib.getParamErrorMsg("draw", "self")); end
  582.  
  583.   if self.visible then
  584.     if self.dirty or self.lostFocus then    
  585.       fg, bg = self:updateColors();
  586.       local x, y = self:getScreenCoords();
  587.  
  588.       local scrText = self.focus
  589.         and unicode.sub(self.text, self.cursor.scrollX)
  590.         or self.text;
  591.  
  592.       gpu.set(x, y, align.left(scrText, self.width));
  593.  
  594.       if (not fast) then self:drawShadow(); end
  595.  
  596. --      curlib.control.status(self.text .. "|" .. self.cursor.position
  597. --        .. "|" .. self.cursor.scrollX .. "|" .. (self.focus and "yes" or "no"));
  598.      
  599.       if self.focus then
  600.         curlib.screen.cursor.blink = true;
  601.         curlib.screen.cursor.x = x + self.cursor.position - self.cursor.scrollX -1;
  602.         curlib.screen.cursor.y = y;
  603.         curlib.screen.cursor.foreground = fg;
  604.         curlib.screen.cursor.background = bg;
  605.       end
  606.       self.dirty = false;
  607.       self.lostFocus = false;
  608.     end
  609.   end
  610.  
  611. end
  612.  
  613. return curlib;
Add Comment
Please, Sign In to add comment