Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Stand alone installer for CCAppStore 2 by oeed, installer by CodedPixelCube/minimite. For the automatic installer for CCAppStore 2 OneOS Edition (adds direct program to OneOS), see http://pastebin.com/v1EJNw9t, or the full installer, http://pastebin.com/kkebdzsx.
- local pkg={
- Bedrock = "--Bedrock Build: 483\
- --This code is squished down in to one, rather hard to read file.\
- --As such it is not much good for anything other than being loaded as an API.\
- --If you want to look at the code to learn from it, copy parts or just take a look,\
- --you should go to the GitHub repo. http://github.com/oeed/Bedrock/\
- \
- --\
- -- Bedrock is the core program framework used by all OneOS and OneCode programs.\
- -- Inspired by Apple's Cocoa framework.\
- -- (c) oeed 2014\
- --\
- -- For documentation see the Bedrock wiki, github.com/oeed/Bedrock/wiki/\
- --\
- \
- local apis = {\
- [\"Drawing\"] = [[\
- local round = function(num, idp)\
- local mult = 10^(idp or 0)\
- return math.floor(num * mult + 0.5) / mult\
- end\
- \
- local _w, _h = term.getSize()\
- local copyBuffer = nil\
- \
- Screen = {\
- Width = _w,\
- Height = _h\
- }\
- \
- Constraints = {\
- \
- }\
- \
- CurrentConstraint = {1,1,_w,_h}\
- IgnoreConstraint = false\
- \
- function AddConstraint(x, y, width, height)\
- local x2 = x + width - 1\
- local y2 = y + height - 1\
- table.insert(Drawing.Constraints, {x, y, x2, y2})\
- Drawing.GetConstraint()\
- end\
- \
- function RemoveConstraint()\
- --table.remove(Drawing.Constraints, #Drawing.Constraints)\
- Drawing.Constraints[#Drawing.Constraints] = nil\
- Drawing.GetConstraint()\
- end\
- \
- function GetConstraint()\
- local x = 1\
- local y = 1\
- local x2 = Drawing.Screen.Width\
- local y2 = Drawing.Screen.Height\
- for i, c in ipairs(Drawing.Constraints) do\
- if x < c[1] then\
- x = c[1]\
- end\
- if y < c[2] then\
- y = c[2]\
- end\
- if x2 > c[3] then\
- x2 = c[3]\
- end\
- if y2 > c[4] then\
- y2 = c[4]\
- end\
- end\
- Drawing.CurrentConstraint = {x, y, x2, y2}\
- end\
- \
- function WithinContraint(x, y)\
- return Drawing.IgnoreConstraint or\
- (x >= Drawing.CurrentConstraint[1] and\
- y >= Drawing.CurrentConstraint[2] and\
- x <= Drawing.CurrentConstraint[3] and\
- y <= Drawing.CurrentConstraint[4])\
- end\
- \
- colours.transparent = 0\
- colors.transparent = 0\
- \
- Filters = {\
- None = {\
- [colours.white] = colours.white,\
- [colours.orange] = colours.orange,\
- [colours.magenta] = colours.magenta,\
- [colours.lightBlue] = colours.lightBlue,\
- [colours.yellow] = colours.yellow,\
- [colours.lime] = colours.lime,\
- [colours.pink] = colours.pink,\
- [colours.grey] = colours.grey,\
- [colours.lightGrey] = colours.lightGrey,\
- [colours.cyan] = colours.cyan,\
- [colours.purple] = colours.purple,\
- [colours.blue] = colours.blue,\
- [colours.brown] = colours.brown,\
- [colours.green] = colours.green,\
- [colours.red] = colours.red,\
- [colours.black] = colours.black,\
- [colours.transparent] = colours.transparent,\
- },\
- \
- Greyscale = {\
- [colours.white] = colours.white,\
- [colours.orange] = colours.lightGrey,\
- [colours.magenta] = colours.lightGrey,\
- [colours.lightBlue] = colours.lightGrey,\
- [colours.yellow] = colours.lightGrey,\
- [colours.lime] = colours.lightGrey,\
- [colours.pink] = colours.lightGrey,\
- [colours.grey] = colours.grey,\
- [colours.lightGrey] = colours.lightGrey,\
- [colours.cyan] = colours.grey,\
- [colours.purple] = colours.grey,\
- [colours.blue] = colours.grey,\
- [colours.brown] = colours.grey,\
- [colours.green] = colours.grey,\
- [colours.red] = colours.grey,\
- [colours.black] = colours.black,\
- [colours.transparent] = colours.transparent,\
- },\
- \
- BlackWhite = {\
- [colours.white] = colours.white,\
- [colours.orange] = colours.white,\
- [colours.magenta] = colours.white,\
- [colours.lightBlue] = colours.white,\
- [colours.yellow] = colours.white,\
- [colours.lime] = colours.white,\
- [colours.pink] = colours.white,\
- [colours.grey] = colours.black,\
- [colours.lightGrey] = colours.white,\
- [colours.cyan] = colours.black,\
- [colours.purple] = colours.black,\
- [colours.blue] = colours.black,\
- [colours.brown] = colours.black,\
- [colours.green] = colours.black,\
- [colours.red] = colours.black,\
- [colours.black] = colours.black,\
- [colours.transparent] = colours.transparent,\
- },\
- \
- Darker = {\
- [colours.white] = colours.lightGrey,\
- [colours.orange] = colours.red,\
- [colours.magenta] = colours.purple,\
- [colours.lightBlue] = colours.cyan,\
- [colours.yellow] = colours.orange,\
- [colours.lime] = colours.green,\
- [colours.pink] = colours.magenta,\
- [colours.grey] = colours.black,\
- [colours.lightGrey] = colours.grey,\
- [colours.cyan] = colours.blue,\
- [colours.purple] = colours.grey,\
- [colours.blue] = colours.grey,\
- [colours.brown] = colours.grey,\
- [colours.green] = colours.grey,\
- [colours.red] = colours.brown,\
- [colours.black] = colours.black,\
- [colours.transparent] = colours.transparent,\
- },\
- \
- Lighter = {\
- [colours.white] = colours.lightGrey,\
- [colours.orange] = colours.yellow,\
- [colours.magenta] = colours.pink,\
- [colours.lightBlue] = colours.cyan,\
- [colours.yellow] = colours.orange,\
- [colours.lime] = colours.green,\
- [colours.pink] = colours.magenta,\
- [colours.grey] = colours.lightGrey,\
- [colours.lightGrey] = colours.grey,\
- [colours.cyan] = colours.lightBlue,\
- [colours.purple] = colours.magenta,\
- [colours.blue] = colours.lightBlue,\
- [colours.brown] = colours.red,\
- [colours.green] = colours.lime,\
- [colours.red] = colours.orange,\
- [colours.black] = colours.grey,\
- [colours.transparent] = colours.transparent,\
- },\
- \
- Highlight = {\
- [colours.white] = colours.lightGrey,\
- [colours.orange] = colours.yellow,\
- [colours.magenta] = colours.pink,\
- [colours.lightBlue] = colours.cyan,\
- [colours.yellow] = colours.orange,\
- [colours.lime] = colours.green,\
- [colours.pink] = colours.magenta,\
- [colours.grey] = colours.lightGrey,\
- [colours.lightGrey] = colours.grey,\
- [colours.cyan] = colours.lightBlue,\
- [colours.purple] = colours.magenta,\
- [colours.blue] = colours.lightBlue,\
- [colours.brown] = colours.red,\
- [colours.green] = colours.lime,\
- [colours.red] = colours.orange,\
- [colours.black] = colours.grey,\
- [colours.transparent] = colours.transparent,\
- },\
- \
- Invert = {\
- [colours.white] = colours.black,\
- [colours.orange] = colours.blue,\
- [colours.magenta] = colours.green,\
- [colours.lightBlue] = colours.brown,\
- [colours.yellow] = colours.blue,\
- [colours.lime] = colours.purple,\
- [colours.pink] = colours.green,\
- [colours.grey] = colours.lightGrey,\
- [colours.lightGrey] = colours.grey,\
- [colours.cyan] = colours.red,\
- [colours.purple] = colours.green,\
- [colours.blue] = colours.yellow,\
- [colours.brown] = colours.lightBlue,\
- [colours.green] = colours.purple,\
- [colours.red] = colours.cyan,\
- [colours.black] = colours.white,\
- [colours.transparent] = colours.transparent,\
- },\
- }\
- \
- function FilterColour(colour, filter)\
- if filter[colour] then\
- return filter[colour]\
- else\
- return colour\
- end\
- end\
- \
- DrawCharacters = function (x, y, characters, textColour, bgColour)\
- Drawing.WriteStringToBuffer(x, y, tostring(characters), textColour, bgColour)\
- end\
- \
- DrawBlankArea = function (x, y, w, h, colour)\
- if colour ~= colours.transparent then\
- Drawing.DrawArea (x, y, w, h, \" \", 1, colour)\
- end\
- end\
- \
- DrawArea = function (x, y, w, h, character, textColour, bgColour)\
- --width must be greater than 1, otherwise we get problems\
- if w < 0 then\
- w = w * -1\
- elseif w == 0 then\
- w = 1\
- end\
- \
- for ix = 1, w do\
- local currX = x + ix - 1\
- for iy = 1, h do\
- local currY = y + iy - 1\
- Drawing.WriteToBuffer(currX, currY, character, textColour, bgColour)\
- end\
- end\
- end\
- \
- DrawImage = function(_x,_y,tImage, w, h)\
- if tImage then\
- for y = 1, h do\
- if not tImage[y] then\
- break\
- end\
- for x = 1, w do\
- if not tImage[y][x] then\
- break\
- end\
- local bgColour = tImage[y][x]\
- local textColour = tImage.textcol[y][x] or colours.white\
- local char = tImage.text[y][x]\
- Drawing.WriteToBuffer(x+_x-1, y+_y-1, char, textColour, bgColour)\
- end\
- end\
- elseif w and h then\
- Drawing.DrawBlankArea(_x, _y, w, h, colours.lightGrey)\
- end\
- end\
- \
- --using .nft\
- LoadImage = function(path, global)\
- local image = {\
- text = {},\
- textcol = {}\
- }\
- if fs.exists(path) then\
- local _io = io\
- if OneOS and global then\
- _io = OneOS.IO\
- end\
- local file = _io.open(path, \"r\")\
- if not file then\
- error('Error Occured. _io:'..tostring(_io)..' OneOS: '..tostring(OneOS)..' OneOS.IO'..tostring(OneOS.IO)..' io: '..tostring(io))\
- end\
- local sLine = file:read()\
- local num = 1\
- while sLine do \
- table.insert(image, num, {})\
- table.insert(image.text, num, {})\
- table.insert(image.textcol, num, {})\
- \
- --As we're no longer 1-1, we keep track of what index to write to\
- local writeIndex = 1\
- --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour\
- local bgNext, fgNext = false, false\
- --The current background and foreground colours\
- local currBG, currFG = nil,nil\
- for i=1,#sLine do\
- local nextChar = string.sub(sLine, i, i)\
- if nextChar:byte() == 30 then\
- bgNext = true\
- elseif nextChar:byte() == 31 then\
- fgNext = true\
- elseif bgNext then\
- currBG = Drawing.GetColour(nextChar)\
- if currBG == nil then\
- currBG = colours.transparent\
- end\
- bgNext = false\
- elseif fgNext then\
- currFG = Drawing.GetColour(nextChar)\
- if currFG == nil or currFG == colours.transparent then\
- currFG = colours.white\
- end\
- fgNext = false\
- else\
- if nextChar ~= \" \" and currFG == nil then\
- currFG = colours.white\
- end\
- image[num][writeIndex] = currBG\
- image.textcol[num][writeIndex] = currFG\
- image.text[num][writeIndex] = nextChar\
- writeIndex = writeIndex + 1\
- end\
- end\
- num = num+1\
- sLine = file:read()\
- end\
- file:close()\
- else\
- return nil\
- end\
- return image\
- end\
- \
- DrawCharactersCenter = function(x, y, w, h, characters, textColour,bgColour)\
- w = w or Drawing.Screen.Width\
- h = h or Drawing.Screen.Height\
- x = x or 0\
- y = y or 0\
- x = math.floor((w - #characters) / 2) + x\
- y = math.floor(h / 2) + y\
- \
- Drawing.DrawCharacters(x, y, characters, textColour, bgColour)\
- end\
- \
- GetColour = function(hex)\
- if hex == ' ' then\
- return colours.transparent\
- end\
- local value = tonumber(hex, 16)\
- if not value then return nil end\
- value = math.pow(2,value)\
- return value\
- end\
- \
- Clear = function (_colour)\
- _colour = _colour or colours.black\
- Drawing.DrawBlankArea(1, 1, Drawing.Screen.Width, Drawing.Screen.Height, _colour)\
- end\
- \
- Buffer = {}\
- BackBuffer = {}\
- \
- TryRestore = false\
- \
- \
- --TODO: make this quicker\
- -- maybe sort the pixels in order of colour so it doesn't have to set the colour each time\
- DrawBuffer = function()\
- if TryRestore and Restore then\
- Restore()\
- end\
- \
- for y,row in pairs(Drawing.Buffer) do\
- for x,pixel in pairs(row) do\
- local shouldDraw = true\
- local hasBackBuffer = true\
- if Drawing.BackBuffer[y] == nil or Drawing.BackBuffer[y][x] == nil or #Drawing.BackBuffer[y][x] ~= 3 then\
- hasBackBuffer = false\
- end\
- if hasBackBuffer and Drawing.BackBuffer[y][x][1] == Drawing.Buffer[y][x][1] and Drawing.BackBuffer[y][x][2] == Drawing.Buffer[y][x][2] and Drawing.BackBuffer[y][x][3] == Drawing.Buffer[y][x][3] then\
- shouldDraw = false\
- end\
- if shouldDraw then\
- term.setBackgroundColour(pixel[3])\
- term.setTextColour(pixel[2])\
- term.setCursorPos(x, y)\
- term.write(pixel[1])\
- end\
- end\
- end\
- Drawing.BackBuffer = Drawing.Buffer\
- Drawing.Buffer = {}\
- end\
- \
- ClearBuffer = function()\
- Drawing.Buffer = {}\
- end\
- \
- WriteStringToBuffer = function (x, y, characters, textColour,bgColour)\
- for i = 1, #characters do\
- local character = characters:sub(i,i)\
- Drawing.WriteToBuffer(x + i - 1, y, character, textColour, bgColour)\
- end\
- end\
- \
- WriteToBuffer = function(x, y, character, textColour,bgColour, cached)\
- if not cached and not Drawing.WithinContraint(x, y) then\
- return\
- end\
- x = round(x)\
- y = round(y)\
- \
- if textColour == colours.transparent then\
- character = ' '\
- end\
- \
- if bgColour == colours.transparent then\
- Drawing.Buffer[y] = Drawing.Buffer[y] or {}\
- Drawing.Buffer[y][x] = Drawing.Buffer[y][x] or {\"\", colours.white, colours.black}\
- Drawing.Buffer[y][x][1] = character\
- Drawing.Buffer[y][x][2] = textColour\
- else\
- Drawing.Buffer[y] = Drawing.Buffer[y] or {}\
- Drawing.Buffer[y][x] = {character, textColour, bgColour}\
- end\
- \
- if copyBuffer then\
- copyBuffer[y] = copyBuffer[y] or {}\
- copyBuffer[y][x] = {character, textColour, bgColour} \
- end\
- end\
- \
- DrawCachedBuffer = function(buffer)\
- for y, row in pairs(buffer) do\
- for x, pixel in pairs(row) do\
- WriteToBuffer(x, y, pixel[1], pixel[2], pixel[3], true)\
- end\
- end\
- end\
- \
- StartCopyBuffer = function()\
- copyBuffer = {}\
- end\
- \
- EndCopyBuffer = function()\
- local tmpCopy = copyBuffer\
- copyBuffer = nil\
- return tmpCopy\
- end\
- ]],\
- [\"Helpers\"] = [[\
- LongestString = function(input, key, isKey)\
- local length = 0\
- if isKey then\
- for k, v in pairs(input) do\
- local titleLength = string.len(k)\
- if titleLength > length then\
- length = titleLength\
- end\
- end\
- else\
- for i = 1, #input do\
- local value = input[i]\
- if key then\
- if value[key] then\
- value = value[key]\
- else\
- value = ''\
- end\
- end\
- local titleLength = string.len(value)\
- if titleLength > length then\
- length = titleLength\
- end\
- end\
- end\
- return length\
- end\
- \
- Split = function(str,sep)\
- sep=sep or'/'\
- return str:match(\"(.*\"..sep..\")\")\
- end\
- \
- Extension = function(path, addDot)\
- if not path then\
- return nil\
- elseif not string.find(fs.getName(path), '%.') then\
- return ''\
- else\
- local _path = path\
- if path:sub(#path) == '/' then\
- _path = path:sub(1,#path-1)\
- end\
- local extension = _path:gmatch('%.[0-9a-z]+$')()\
- if extension then\
- extension = extension:sub(2)\
- else\
- --extension = nil\
- return ''\
- end\
- if addDot then\
- extension = '.'..extension\
- end\
- return extension:lower()\
- end\
- end\
- \
- RemoveExtension = function(path)\
- --local name = string.match(fs.getName(path), '(%a+)%.?.-')\
- if not path:find('%.') then\
- return path\
- end\
- local extension = Helpers.Extension(path)\
- if extension == path then\
- return fs.getName(path)\
- end\
- return string.gsub(path, extension, ''):sub(1, -2)\
- end\
- \
- RemoveFileName = function(path)\
- if string.sub(path, -1) == '/' then\
- path = string.sub(path, 1, -2)\
- end\
- local v = string.match(path, \"(.-)([^\\\\/]-%.?([^%.\\\\/]*))$\")\
- if type(v) == 'string' then\
- return v\
- end\
- return v[1]\
- end\
- \
- TruncateString = function(sString, maxLength)\
- if #sString > maxLength then\
- sString = sString:sub(1,maxLength-3)\
- if sString:sub(-1) == ' ' then\
- sString = sString:sub(1,maxLength-4)\
- end\
- sString = sString .. '...'\
- end\
- return sString\
- end\
- \
- TruncateStringStart = function(sString, maxLength)\
- local len = #sString\
- if #sString > maxLength then\
- sString = sString:sub(len - maxLength, len - 3)\
- if sString:sub(-1) == ' ' then\
- sString = sString:sub(len - maxLength, len - 4)\
- end\
- sString = '...' .. sString\
- end\
- return sString\
- end\
- \
- WrapText = function(text, maxWidth)\
- local lines = {''}\
- for word, space in text:gmatch('(%S+)(%s*)') do\
- local temp = lines[#lines] .. word .. space:gsub('\\n','')\
- if #temp > maxWidth then\
- table.insert(lines, '')\
- end\
- if space:find('\\n') then\
- lines[#lines] = lines[#lines] .. word\
- \
- space = space:gsub('\\n', function()\
- table.insert(lines, '')\
- return ''\
- end)\
- else\
- lines[#lines] = lines[#lines] .. word .. space\
- end\
- end\
- if #lines[1] == 0 then\
- table.remove(lines,1)\
- end\
- return lines\
- end\
- \
- TidyPath = function(path)\
- path = '/'..path\
- if fs.exists(path) and fs.isDir(path) then\
- path = path .. '/'\
- end\
- \
- path, n = path:gsub(\"//\", \"/\")\
- while n > 0 do\
- path, n = path:gsub(\"//\", \"/\")\
- end\
- return path\
- end\
- \
- Capitalise = function(str)\
- return str:sub(1, 1):upper() .. str:sub(2, -1)\
- end\
- \
- Round = function(num, idp)\
- local mult = 10^(idp or 0)\
- return math.floor(num * mult + 0.5) / mult\
- end\
- ]],\
- [\"Object\"] = [[\
- X = 1\
- Y = 1\
- Width = 1\
- Height = 1\
- Parent = nil\
- OnClick = nil\
- Visible = true\
- IgnoreClick = false\
- Name = nil \
- ClipDrawing = true\
- UpdateDrawBlacklist = {}\
- Fixed = false\
- Ready = false\
- \
- DrawCache = {}\
- \
- NeedsDraw = function(self)\
- if not self.Visible then\
- return false\
- end\
- \
- if not self.DrawCache.Buffer or self.DrawCache.AlwaysDraw or self.DrawCache.NeedsDraw then\
- return true\
- end\
- \
- if self.OnNeedsUpdate then\
- if self.OnNeedsUpdate() then\
- return true\
- end\
- end\
- \
- if self.Children then\
- for i, v in ipairs(self.Children) do\
- if v:NeedsDraw() then\
- return true\
- end\
- end\
- end\
- end\
- \
- GetPosition = function(self)\
- return self.Bedrock:GetAbsolutePosition(self)\
- end\
- \
- GetOffsetPosition = function(self)\
- if not self.Parent then\
- return {X = 1, Y = 1}\
- end\
- \
- local offset = {X = 0, Y = 0}\
- if not self.Fixed and self.Parent.ChildOffset then\
- offset = self.Parent.ChildOffset\
- end\
- \
- return {X = self.X + offset.X, Y = self.Y + offset.Y}\
- end\
- \
- Draw = function(self)\
- if not self.Visible then\
- return\
- end\
- \
- self.DrawCache.NeedsDraw = false\
- local pos = self:GetPosition()\
- Drawing.StartCopyBuffer()\
- \
- if self.ClipDrawing then\
- Drawing.AddConstraint(pos.X, pos.Y, self.Width, self.Height)\
- end\
- \
- if self.OnDraw then\
- self:OnDraw(pos.X, pos.Y)\
- end\
- \
- self.DrawCache.Buffer = Drawing.EndCopyBuffer()\
- \
- if self.Children then\
- for i, child in ipairs(self.Children) do\
- local pos = child:GetOffsetPosition()\
- if pos.Y + self.Height > 1 and pos.Y <= self.Height and pos.X + self.Width > 1 and pos.X <= self.Width then\
- child:Draw()\
- end\
- end\
- end\
- \
- \
- if self.OnPostChildrenDraw then\
- self:OnPostChildrenDraw(pos.X, pos.Y)\
- end\
- \
- if self.ClipDrawing then\
- Drawing.RemoveConstraint()\
- end \
- end\
- \
- ForceDraw = function(self, ignoreChildren, ignoreParent, ignoreBedrock)\
- if not ignoreBedrock and self.Bedrock then\
- self.Bedrock:ForceDraw()\
- end\
- self.DrawCache.NeedsDraw = true\
- if not ignoreParent and self.Parent then\
- self.Parent:ForceDraw(true, nil, true)\
- end\
- if not ignoreChildren and self.Children then\
- for i, child in ipairs(self.Children) do\
- child:ForceDraw(nil, true, true)\
- end\
- end\
- end\
- \
- OnRemove = function(self)\
- if self == self.Bedrock:GetActiveObject() then\
- self.Bedrock:SetActiveObject()\
- end\
- end\
- \
- local function ParseColour(value)\
- if type(value) == 'string' then\
- if colours[value] and type(colours[value]) == 'number' then\
- return colours[value]\
- elseif colors[value] and type(colors[value]) == 'number' then\
- return colors[value]\
- end\
- elseif type(value) == 'number' and (value == colours.transparent or (value >= colours.white and value <= colours.black)) then\
- return value\
- end\
- error('Invalid colour: \"'..tostring(value)..'\"')\
- end\
- \
- Initialise = function(self, values)\
- local _new = values -- the new instance\
- _new.DrawCache = {\
- NeedsDraw = true,\
- AlwaysDraw = false,\
- Buffer = nil\
- }\
- setmetatable(_new, {__index = self} )\
- \
- local new = {} -- the proxy\
- setmetatable(new, {\
- __index = function(t, k)\
- if k:find('Color') then\
- k = k:gsub('Color', 'Colour')\
- end\
- \
- if k:find('Colour') and type(_new[k]) ~= 'table' and type(_new[k]) ~= 'function' then\
- if _new[k] then\
- return ParseColour(_new[k])\
- end\
- elseif _new[k] ~= nil then\
- return _new[k]\
- end\
- end,\
- \
- __newindex = function (t,k,v)\
- if k:find('Color') then\
- k = k:gsub('Color', 'Colour')\
- end\
- \
- if k == 'Width' or k == 'X' or k == 'Height' or k == 'Y' then\
- v = new.Bedrock:ParseStringSize(new.Parent, k, v)\
- end\
- \
- if v ~= _new[k] then\
- _new[k] = v\
- if t.OnUpdate then\
- t:OnUpdate(k)\
- end\
- \
- if t.UpdateDrawBlacklist[k] == nil then\
- t:ForceDraw()\
- end\
- end\
- end\
- })\
- if new.OnInitialise then\
- new:OnInitialise()\
- end\
- \
- return new\
- end\
- \
- AnimateValue = function(self, valueName, from, to, duration, done, tbl)\
- tbl = tbl or self\
- if type(tbl[valueName]) ~= 'number' then\
- error('Animated value ('..valueName..') must be number.')\
- elseif not self.Bedrock.AnimationEnabled then\
- tbl[valueName] = to\
- if done then\
- done()\
- end\
- return\
- end\
- from = from or tbl[valueName]\
- duration = duration or 0.2\
- local delta = to - from\
- \
- local startTime = os.clock()\
- local previousFrame = startTime\
- local frame\
- frame = function()\
- local time = os.clock()\
- local totalTime = time - startTime\
- local isLast = totalTime >= duration\
- \
- if isLast then\
- tbl[valueName] = to\
- self:ForceDraw()\
- if done then\
- done()\
- end\
- else\
- tbl[valueName] = self.Bedrock.Helpers.Round(from + delta * (totalTime / duration))\
- self:ForceDraw()\
- self.Bedrock:StartTimer(function()\
- frame()\
- end, 0.05)\
- end\
- end\
- frame()\
- end\
- \
- Click = function(self, event, side, x, y)\
- if self.Visible and not self.IgnoreClick then\
- if event == 'mouse_click' and self.OnClick and self:OnClick(event, side, x, y) ~= false then\
- return true\
- elseif event == 'mouse_drag' and self.OnDrag and self:OnDrag(event, side, x, y) ~= false then\
- return true\
- elseif event == 'mouse_scroll' and self.OnScroll and self:OnScroll(event, side, x, y) ~= false then\
- return true\
- else\
- return false\
- end\
- else\
- return false\
- end\
- \
- end\
- \
- ToggleMenu = function(self, name, x, y)\
- return self.Bedrock:ToggleMenu(name, self, x, y)\
- end\
- \
- function OnUpdate(self, value)\
- if value == 'Z' then\
- self.Bedrock:ReorderObjects()\
- end\
- end\
- ]],\
- }\
- local objects = {\
- [\"Button\"] = [[\
- BackgroundColour = colours.lightGrey\
- ActiveBackgroundColour = colours.blue\
- ActiveTextColour = colours.white\
- TextColour = colours.black\
- DisabledTextColour = colours.lightGrey\
- Text = \"\"\
- Toggle = nil\
- Momentary = true\
- AutoWidth = true\
- Align = 'Center'\
- Enabled = true\
- \
- OnUpdate = function(self, value)\
- if value == 'Text' and self.AutoWidth then\
- self.Width = #self.Text + 2\
- end\
- end\
- \
- OnDraw = function(self, x, y)\
- local bg = self.BackgroundColour\
- \
- if self.Toggle then\
- bg = self.ActiveBackgroundColour\
- end\
- \
- local txt = self.TextColour\
- if self.Toggle then\
- txt = self.ActiveTextColour\
- end\
- if not self.Enabled then\
- txt = self.DisabledTextColour\
- end\
- Drawing.DrawBlankArea(x, y, self.Width, self.Height, bg)\
- \
- local _x = 1\
- if self.Align == 'Right' then\
- _x = self.Width - #self.Text - 1\
- elseif self.Align == 'Center' then\
- _x = math.floor((self.Width - #self.Text) / 2)\
- end\
- \
- Drawing.DrawCharacters(x + _x, y-1+math.ceil(self.Height/2), self.Text, txt, bg)\
- end\
- \
- OnLoad = function(self)\
- if self.Toggle ~= nil then\
- self.Momentary = false\
- end\
- end\
- \
- Click = function(self, event, side, x, y)\
- if self.Visible and not self.IgnoreClick and self.Enabled and event ~= 'mouse_scroll' then\
- if self.OnClick then\
- if self.Momentary then\
- self.Toggle = true\
- self.Bedrock:StartTimer(function()self.Toggle = false end,0.25)\
- elseif self.Toggle ~= nil then\
- self.Toggle = not self.Toggle\
- end\
- \
- self:OnClick(event, side, x, y, self.Toggle)\
- else\
- self.Toggle = not self.Toggle\
- end\
- return true\
- else\
- return false\
- end\
- end\
- ]],\
- [\"CollectionView\"] = [[\
- Inherit = 'ScrollView'\
- UpdateDrawBlacklist = {['NeedsItemUpdate']=true}\
- \
- TextColour = colours.black\
- BackgroundColour = colours.white\
- Items = false\
- NeedsItemUpdate = false\
- SpacingX = 2\
- SpacingY = 1\
- \
- OnDraw = function(self, x, y)\
- if self.NeedsItemUpdate then\
- self:UpdateItems()\
- self.NeedsItemUpdate = false\
- end\
- Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
- end\
- \
- local function MaxIcons(self, obj)\
- local x, y = 2, 1\
- if not obj.Height or not obj.Width then\
- error('You must provide each object\\'s height when adding to a CollectionView.')\
- end\
- local slotHeight = obj.Height + self.SpacingY\
- local slotWidth = obj.Width + self.SpacingX\
- local maxX = math.floor((self.Width - 2) / slotWidth)\
- return x, y, maxX, slotWidth, slotHeight\
- end\
- \
- local function IconLocation(self, obj, i)\
- local x, y, maxX, slotWidth, slotHeight = MaxIcons(self, obj)\
- local rowPos = ((i - 1) % maxX)\
- local colPos = math.ceil(i / maxX) - 1\
- x = x + (slotWidth * rowPos)\
- y = y + colPos * slotHeight\
- return x, y\
- end\
- \
- local function AddItem(self, v, i)\
- local toggle = false\
- if not self.CanSelect then\
- toggle = nil\
- end\
- local x, y = IconLocation(self, v, i)\
- local item = {\
- [\"X\"]=x,\
- [\"Y\"]=y,\
- [\"Name\"]=\"CollectionViewItem\",\
- [\"Type\"]=\"View\",\
- [\"TextColour\"]=self.TextColour,\
- [\"BackgroundColour\"]=0,\
- OnClick = function(itm)\
- if self.CanSelect then\
- for i2, _v in ipairs(self.Children) do\
- _v.Toggle = false\
- end\
- self.Selected = itm\
- end\
- end\
- }\
- for k, _v in pairs(v) do\
- item[k] = _v\
- end\
- self:AddObject(item)\
- end\
- \
- \
- UpdateItems = function(self)\
- self:RemoveAllObjects()\
- local groupMode = false\
- for k, v in pairs(self.Items) do\
- if type(k) == 'string' then\
- groupMode = true\
- break\
- end\
- end\
- \
- for i, v in ipairs(self.Items) do\
- AddItem(self, v, i)\
- end\
- self:UpdateScroll()\
- end\
- \
- OnUpdate = function(self, value)\
- if value == 'Items' then\
- self.NeedsItemUpdate = true\
- end\
- end\
- ]],\
- [\"ImageView\"] = [[\
- Image = false\
- \
- OnDraw = function(self, x, y)\
- Drawing.DrawImage(x, y, self.Image, self.Width, self.Height)\
- end\
- \
- OnLoad = function(self)\
- if self.Path and fs.exists(self.Path) then\
- self.Image = Drawing.LoadImage(self.Path)\
- end\
- end\
- \
- OnUpdate = function(self, value)\
- if value == 'Path' then\
- if self.Path and fs.exists(self.Path) then\
- self.Image = Drawing.LoadImage(self.Path)\
- end\
- end\
- end\
- ]],\
- [\"Label\"] = [[\
- TextColour = colours.black\
- BackgroundColour = colours.transparent\
- Text = \"\"\
- AutoWidth = false\
- Align = 'Left'\
- \
- local wrapText = function(text, maxWidth)\
- local lines = {''}\
- for word, space in text:gmatch('(%S+)(%s*)') do\
- local temp = lines[#lines] .. word .. space:gsub('\\n','')\
- if #temp > maxWidth then\
- table.insert(lines, '')\
- end\
- if space:find('\\n') then\
- lines[#lines] = lines[#lines] .. word\
- \
- space = space:gsub('\\n', function()\
- table.insert(lines, '')\
- return ''\
- end)\
- else\
- lines[#lines] = lines[#lines] .. word .. space\
- end\
- end\
- if #lines[1] == 0 then\
- table.remove(lines,1)\
- end\
- return lines\
- end\
- \
- OnUpdate = function(self, value)\
- if value == 'Text' then\
- if self.AutoWidth then\
- self.Width = #self.Text\
- else\
- self.Height = #wrapText(self.Text, self.Width)\
- end\
- end\
- end\
- \
- OnDraw = function(self, x, y)\
- for i, v in ipairs(wrapText(self.Text, self.Width)) do\
- local _x = 0\
- if self.Align == 'Right' then\
- _x = self.Width - #v\
- elseif self.Align == 'Center' then\
- _x = math.floor((self.Width - #v) / 2)\
- end\
- Drawing.DrawCharacters(x + _x, y + i - 1, v, self.TextColour, self.BackgroundColour)\
- end\
- end\
- ]],\
- [\"ListView\"] = [[\
- Inherit = 'ScrollView'\
- UpdateDrawBlacklist = {['NeedsItemUpdate']=true}\
- \
- TextColour = colours.black\
- BackgroundColour = colours.white\
- HeadingColour = colours.lightGrey\
- SelectionBackgroundColour = colours.blue\
- SelectionTextColour = colours.white\
- Items = false\
- CanSelect = false\
- Selected = nil\
- NeedsItemUpdate = false\
- ItemMargin = 1\
- HeadingMargin = 0\
- TopMargin = 0\
- \
- OnDraw = function(self, x, y)\
- if self.NeedsItemUpdate then\
- self:UpdateItems()\
- end\
- Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
- end\
- \
- local function AddItem(self, v, x, y, group)\
- local toggle = false\
- if not self.CanSelect then\
- toggle = nil\
- elseif v.Selected then\
- toggle = true\
- end\
- local item = {\
- [\"Width\"]=self.Width,\
- [\"X\"]=x,\
- [\"Y\"]=y,\
- [\"Name\"]=\"ListViewItem\",\
- [\"Type\"]=\"Button\",\
- [\"TextColour\"]=self.TextColour,\
- [\"BackgroundColour\"]=0,\
- [\"ActiveTextColour\"]=self.SelectionTextColour,\
- [\"ActiveBackgroundColour\"]=self.SelectionBackgroundColour,\
- [\"Align\"]='Left',\
- [\"Toggle\"]=toggle,\
- [\"Group\"]=group,\
- OnClick = function(itm)\
- if self.CanSelect then\
- self:SelectItem(itm)\
- elseif self.OnSelect then\
- self:OnSelect(itm.Text)\
- end\
- end\
- }\
- if type(v) == 'table' then\
- for k, _v in pairs(v) do\
- item[k] = _v\
- end\
- else\
- item.Text = v\
- end\
- \
- local itm = self:AddObject(item)\
- if v.Selected then\
- self:SelectItem(itm)\
- end\
- end\
- \
- UpdateItems = function(self)\
- if not self.Items or type(self.Items) ~= 'table' then\
- self.Items = {}\
- end\
- self.Selected = nil\
- self:RemoveAllObjects()\
- local groupMode = false\
- for k, v in pairs(self.Items) do\
- if type(k) == 'string' then\
- groupMode = true\
- break\
- end\
- end\
- \
- if not groupMode then\
- for i, v in ipairs(self.Items) do\
- AddItem(self, v, self.ItemMargin, i)\
- end\
- else\
- local y = self.TopMargin\
- for k, v in pairs(self.Items) do\
- y = y + 1\
- AddItem(self, {Text = k, TextColour = self.HeadingColour, IgnoreClick = true}, self.HeadingMargin, y)\
- for i, _v in ipairs(v) do\
- y = y + 1\
- AddItem(self, _v, 1, y, k)\
- end\
- y = y + 1\
- end\
- end\
- self:UpdateScroll()\
- self.NeedsItemUpdate = false\
- end\
- \
- OnKeyChar = function(self, event, keychar)\
- if keychar == keys.up or keychar == keys.down then\
- local n = self:GetIndex(self.Selected)\
- if keychar == keys.up then\
- n = n - 1\
- else\
- n = n + 1\
- end\
- local new = self:GetNth(n)\
- if new then\
- self:SelectItem(new)\
- end\
- elseif keychar == keys.enter and self.Selected then\
- self.Selected:Click('mouse_click', 1, 1, 1)\
- end\
- end\
- \
- --returns the index/'n' of the given item\
- GetIndex = function(self, obj)\
- local n = 1\
- for i, v in ipairs(self.Children) do\
- if not v.IgnoreClick then\
- if obj == v then\
- return n\
- end\
- n = n + 1\
- end\
- end\
- end\
- \
- --gets the 'nth' list item (does not include headings)\
- GetNth = function(self, n)\
- local _n = 1\
- for i, v in ipairs(self.Children) do\
- if not v.IgnoreClick then\
- if n == _n then\
- return v\
- end\
- _n = _n + 1\
- end\
- end\
- end\
- \
- SelectItem = function(self, item)\
- for i, v in ipairs(self.Children) do\
- v.Toggle = false\
- end\
- self.Selected = item\
- item.Toggle = true\
- if self.OnSelect then\
- self:OnSelect(item.Text)\
- end\
- end\
- \
- OnUpdate = function(self, value)\
- if value == 'Items' then\
- self.NeedsItemUpdate = true\
- end\
- end\
- ]],\
- [\"Menu\"] = [[\
- Inherit = 'View'\
- \
- TextColour = colours.black\
- BackgroundColour = colours.white\
- HideTop = false\
- Prepared = false\
- \
- OnDraw = function(self, x, y)\
- Drawing.IgnoreConstraint = true\
- Drawing.DrawBlankArea(x + 1, y + (self.HideTop and 0 or 1), self.Width, self.Height + (self.HideTop and 1 or 0), colours.grey)\
- Drawing.IgnoreConstraint = false\
- Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
- end\
- \
- OnLoad = function(self)\
- local owner = self.Owner\
- if type(owner) == 'string' then\
- owner = self.Bedrock:GetObject(self.Owner)\
- end\
- \
- if owner then\
- if self.X == 0 and self.Y == 0 then\
- local pos = owner:GetPosition()\
- self.X = pos.X\
- self.Y = pos.Y + owner.Height\
- end\
- self.Owner = owner\
- else\
- self.Owner = nil\
- end\
- end\
- \
- OnUpdate = function(self, value)\
- if value == 'Children' then\
- self.Height = #self.Children + 1 + (self.HideTop and 0 or 1)\
- if not self.BaseY then\
- self.BaseY = self.Y\
- end\
- if #self.Children > 0 and self.Children[1].Type == 'Button' then\
- self.Width = self.Bedrock.Helpers.LongestString(self.Children, 'Text') + 2\
- for i, v in ipairs(self.Children) do\
- if v.TextColour then\
- v.TextColour = self.TextColour\
- end\
- if v.BackgroundColour then\
- v.BackgroundColour = colours.transparent\
- end\
- if v.Colour then\
- v.Colour = colours.lightGrey\
- end\
- v.Align = 'Left'\
- v.X = 1\
- v.Y = i + (self.HideTop and 0 or 1)\
- v.Width = self.Width\
- v.Height = 1\
- end\
- elseif #self.Children > 0 and self.Children[1].Type == 'MenuItem' then\
- local width = 1\
- for i, v in ipairs(self.Children) do\
- if v.Width > width then\
- width = v.Width\
- end\
- end\
- self.Width = width\
- for i, v in ipairs(self.Children) do\
- if v.TextColour then\
- v.TextColour = self.TextColour\
- end\
- if v.Colour then\
- v.Colour = colours.lightGrey\
- end\
- v.X = 1\
- v.Y = i + (self.HideTop and 0 or 1)\
- v.Width = width\
- v.Height = 1\
- end\
- end\
- \
- self.Y = self.BaseY\
- local pos = self:GetPosition()\
- if pos.Y + self.Height + 1 > Drawing.Screen.Height then\
- self.Y = self.BaseY - ((self.Height + pos.Y) - Drawing.Screen.Height)\
- end\
- \
- if pos.X + self.Width > Drawing.Screen.Width then\
- self.X = Drawing.Screen.Width - self.Width\
- end\
- end\
- end\
- \
- Close = function(self, isBedrockCall)\
- self.Bedrock.Menu = nil\
- if not self.Prepared then\
- self.Parent:RemoveObject(self)\
- else\
- self.Visible = false\
- end\
- \
- if self.Owner and self.Owner.Toggle then\
- self.Owner.Toggle = false\
- end\
- self.Parent:ForceDraw()\
- self = nil\
- end\
- \
- OnChildClick = function(self, child, event, side, x, y)\
- self:Close()\
- end\
- ]],\
- [\"MenuItem\"] = [[\
- BackgroundColour = colours.white\
- TextColour = colours.black\
- DisabledTextColour = colours.lightGrey\
- ShortcutTextColour = colours.grey\
- Text = \"\"\
- Enabled = true\
- Shortcut = nil\
- ShortcutPadding = 2\
- ShortcutName = nil\
- \
- OnUpdate = function(self, value)\
- if value == 'Text' then\
- if self.Shortcut then\
- self.Width = #self.Text + 2 + self.ShortcutPadding + #self.Shortcut\
- else\
- self.Width = #self.Text + 2\
- end\
- elseif value == 'OnClick' then\
- self:RegisterShortcut()\
- end\
- end\
- \
- OnDraw = function(self, x, y)\
- Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
- \
- local txt = self.TextColour\
- if not self.Enabled then\
- txt = self.DisabledTextColour\
- end\
- Drawing.DrawCharacters(x + 1, y, self.Text, txt, colours.transparent)\
- \
- if self.Shortcut then\
- local shrt = self.ShortcutTextColour\
- if not self.Enabled then\
- shrt = self.DisabledTextColour\
- end\
- Drawing.DrawCharacters(x + self.Width - #self.Shortcut - 1, y, self.Shortcut, shrt, colours.transparent)\
- end\
- end\
- \
- ParseShortcut = function(self)\
- local special = {\
- ['^'] = keys.leftShift,\
- ['<'] = keys.delete,\
- ['>'] = keys.delete,\
- ['#'] = keys.leftCtrl,\
- ['~'] = keys.leftAlt,\
- }\
- \
- local keys = {}\
- for i = 1, #self.Shortcut do\
- local c = self.Shortcut:sub(i,i)\
- table.insert(keys, special[c] or c:lower())\
- end\
- return keys\
- end\
- \
- RegisterShortcut = function(self)\
- if self.Shortcut then\
- self.Shortcut = self.Shortcut:upper()\
- self.ShortcutName = self.Bedrock:RegisterKeyboardShortcut(self:ParseShortcut(), function()\
- if self.OnClick and self.Enabled then\
- if self.Parent.Owner then\
- self.Parent:Close()\
- self.Parent.Owner.Toggle = true\
- self.Bedrock:StartTimer(function()\
- self.Parent.Owner.Toggle = false\
- end, 0.3)\
- end\
- return self:OnClick('keyboard_shortcut', 1, 1, 1)\
- else\
- return false\
- end\
- end)\
- end\
- end\
- \
- OnRemove = function(self)\
- if self.ShortcutName then\
- self.Bedrock:UnregisterKeyboardShortcut(self.ShortcutName)\
- end\
- end\
- \
- OnLoad = function(self)\
- if self.OnClick ~= nil then\
- self:RegisterShortcut()\
- end\
- -- self:OnUpdate('Text')\
- end\
- ]],\
- [\"NumberBox\"] = [[\
- Inherit = 'View'\
- \
- Value = 1\
- Minimum = 1\
- Maximum = 99\
- BackgroundColour = colours.lightGrey\
- TextBoxTimer = nil\
- Width = 7\
- \
- OnLoad = function(self)\
- self:AddObject({\
- X = self.Width - 1,\
- Y = 1,\
- Width = 1,\
- AutoWidth = false,\
- Text = '-',\
- Type = 'Button',\
- Name = 'AddButton',\
- BackgroundColour = colours.transparent,\
- OnClick = function()\
- self:ShiftValue(-1)\
- end\
- })\
- \
- self:AddObject({\
- X = self.Width,\
- Y = 1,\
- Width = 1,\
- AutoWidth = false,\
- Text = '+',\
- Type = 'Button',\
- Name = 'SubButton',\
- BackgroundColour = colours.transparent,\
- OnClick = function()\
- self:ShiftValue(1)\
- end\
- })\
- \
- self:AddObject({\
- X = 1,\
- Y = 1,\
- Width = self.Width - 2,\
- Text = tostring(self.Value),\
- Align = 'Center',\
- Type = 'TextBox',\
- BackgroundColour = colours.transparent,\
- OnChange = function(_self, event, keychar)\
- if keychar == keys.enter then\
- self:SetValue(tonumber(_self.Text))\
- self.TextBoxTimer = nil\
- end\
- if self.TextBoxTimer then\
- self.Bedrock:StopTimer(self.TextBoxTimer)\
- end\
- \
- self.TextBoxTimer = self.Bedrock:StartTimer(function(_, timer)\
- if timer and timer == self.TextBoxTimer then\
- self:SetValue(tonumber(_self.Text))\
- self.TextBoxTimer = nil\
- end\
- end, 2)\
- end\
- })\
- end\
- \
- OnScroll = function(self, event, dir, x, y)\
- self:ShiftValue(-dir)\
- end\
- \
- ShiftValue = function(self, delta)\
- local val = tonumber(self:GetObject('TextBox').Text) or self.Minimum\
- self:SetValue(val + delta)\
- end\
- \
- SetValue = function(self, newValue)\
- newValue = newValue or 0\
- if self.Maximum and newValue > self.Maximum then\
- newValue = self.Maximum\
- elseif self.Minimum and newValue < self.Minimum then\
- newValue = self.Minimum\
- end\
- self.Value = newValue\
- if self.OnChange then\
- self:OnChange()\
- end\
- end\
- \
- OnUpdate = function(self, value)\
- if value == 'Value' then\
- local textbox = self:GetObject('TextBox')\
- if textbox then\
- textbox.Text = tostring(self.Value)\
- end\
- end\
- end\
- ]],\
- [\"ProgressBar\"] = [[\
- BackgroundColour = colours.lightGrey\
- BarColour = colours.blue\
- TextColour = colours.white\
- ShowText = false\
- Value = 0\
- Maximum = 1\
- Indeterminate = false\
- AnimationStep = 0\
- \
- OnDraw = function(self, x, y)\
- Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
- \
- -- if self.Indeterminate then\
- -- for i = 1, self.Width do\
- -- local s = x + i - 1 + self.AnimationStep\
- -- if s % 4 == 1 or s % 4 == 2 then\
- -- Drawing.DrawBlankArea(s, y, 1, self.Height, self.BarColour)\
- -- end\
- -- end\
- -- self.AnimationStep = self.AnimationStep + 1\
- -- if self.AnimationStep >= 4 then\
- -- self.AnimationStep = 0\
- -- end\
- -- self.Bedrock:StartTimer(function()\
- -- self:Draw()\
- -- end, 0.25)\
- -- else\
- local values = self.Value\
- local barColours = self.BarColour\
- if type(values) == 'number' then\
- values = {values}\
- end\
- if type(barColours) == 'number' then\
- barColours = {barColours}\
- end\
- local total = 0\
- local _x = x\
- for i, v in ipairs(values) do\
- local width = self.Bedrock.Helpers.Round((v / self.Maximum) * self.Width)\
- total = total + v\
- Drawing.DrawBlankArea(_x, y, width, self.Height, barColours[((i-1)%#barColours)+1])\
- _x = _x + width\
- end\
- \
- if self.ShowText then\
- local text = self.Bedrock.Helpers.Round((total / self.Maximum) * 100) .. '%'\
- Drawing.DrawCharactersCenter(x, y, self.Width, self.Height, text, self.TextColour, colours.transparent)\
- end\
- -- end\
- end\
- ]],\
- [\"ScrollBar\"] = [[\
- BackgroundColour = colours.lightGrey\
- BarColour = colours.lightBlue\
- Scroll = 0\
- MaxScroll = 0\
- ClickPoint = nil\
- Fixed = true\
- \
- OnUpdate = function(self, value)\
- if value == 'Text' and self.AutoWidth then\
- self.Width = #self.Text + 2\
- end\
- end\
- \
- OnDraw = function(self, x, y)\
- local barHeight = self.Height * (self.Height / (self.Height + self.MaxScroll))\
- if barHeight < 3 then\
- barHeight = 3\
- end\
- local percentage = (self.Scroll/self.MaxScroll)\
- \
- Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
- Drawing.DrawBlankArea(x, y + math.ceil(self.Height*percentage - barHeight*percentage), self.Width, barHeight, self.BarColour)\
- end\
- \
- OnScroll = function(self, event, direction, x, y)\
- if event == 'mouse_scroll' then\
- direction = self.Bedrock.Helpers.Round(direction * 3)\
- end\
- if self.Scroll < 0 or self.Scroll > self.MaxScroll then\
- return false\
- end\
- local old = self.Scroll\
- self.Scroll = self.Bedrock.Helpers.Round(self.Scroll + direction)\
- if self.Scroll < 0 then\
- self.Scroll = 0\
- elseif self.Scroll > self.MaxScroll then\
- self.Scroll = self.MaxScroll\
- end\
- \
- if self.Scroll ~= old and self.OnChange then\
- self:OnChange()\
- end\
- end\
- \
- OnClick = function(self, event, side, x, y)\
- if event == 'mouse_click' then\
- self.ClickPoint = y\
- else\
- if self.ClickPoint then\
- local gapHeight = self.Height - (self.Height * (self.Height / (self.Height + self.MaxScroll)))\
- local barHeight = self.Height * (self.Height / (self.Height + self.MaxScroll))\
- --local delta = (self.Height + self.MaxScroll) * ((y - self.ClickPoint) / barHeight)\
- local delta = ((y - self.ClickPoint)/gapHeight)*self.MaxScroll\
- --l(((y - self.ClickPoint)/gapHeight))\
- --l(delta)\
- self.Scroll = self.Bedrock.Helpers.Round(delta)\
- --l(self.Scroll)\
- --l('----')\
- if self.Scroll < 0 then\
- self.Scroll = 0\
- elseif self.Scroll > self.MaxScroll then\
- self.Scroll = self.MaxScroll\
- end\
- if self.OnChange then\
- self:OnChange()\
- end\
- end\
- end\
- \
- local relScroll = self.MaxScroll * ((y-1)/self.Height)\
- if y == self.Height then\
- relScroll = self.MaxScroll\
- end\
- self.Scroll = self.Bedrock.Helpers.Round(relScroll)\
- \
- \
- end\
- \
- OnDrag = OnClick\
- ]],\
- [\"ScrollView\"] = [[\
- Inherit = 'View'\
- ChildOffset = false\
- ContentWidth = 0\
- ContentHeight = 0\
- ScrollBarBackgroundColour = colours.lightGrey\
- ScrollBarColour = colours.lightBlue\
- \
- CalculateContentSize = function(self)\
- local function calculateObject(obj)\
- local pos = obj:GetPosition()\
- local x2 = pos.X + obj.Width - 1\
- local y2 = pos.Y + obj.Height - 1\
- if obj.Children then\
- for i, child in ipairs(obj.Children) do\
- local _x2, _y2 = calculateObject(child)\
- if _x2 > x2 then\
- x2 = _x2\
- end\
- if _y2 > y2 then\
- y2 = _y2\
- end\
- end\
- end\
- return x2, y2\
- end\
- \
- local pos = self:GetPosition()\
- local x2, y2 = calculateObject(self)\
- self.ContentWidth = x2 - pos.X + 1\
- self.ContentHeight = y2 - pos.Y + 1\
- end\
- \
- UpdateScroll = function(self)\
- self.ChildOffset.Y = 0\
- self:CalculateContentSize()\
- if self.ContentHeight > self.Height then\
- if not self:GetObject('ScrollViewScrollBar') then\
- local _scrollBar = self:AddObject({\
- [\"Name\"] = 'ScrollViewScrollBar',\
- [\"Type\"] = 'ScrollBar',\
- [\"X\"] = self.Width,\
- [\"Y\"] = 1,\
- [\"Width\"] = 1,\
- [\"Height\"] = self.Height,\
- [\"BackgroundColour\"] = self.ScrollBarBackgroundColour,\
- [\"BarColour\"] = self.ScrollBarColour,\
- [\"Z\"]=999\
- })\
- \
- _scrollBar.OnChange = function(scrollBar)\
- self.ChildOffset.Y = -scrollBar.Scroll\
- for i, child in ipairs(self.Children) do\
- child:ForceDraw()\
- end\
- end\
- end\
- \
- if self:GetObject('ScrollViewScrollBar') then\
- self:GetObject('ScrollViewScrollBar').MaxScroll = self.ContentHeight - self.Height\
- end\
- else\
- self:RemoveObject('ScrollViewScrollBar')\
- end\
- end\
- \
- OnScroll = function(self, event, direction, x, y)\
- if self:GetObject('ScrollViewScrollBar') then\
- self:GetObject('ScrollViewScrollBar'):OnScroll(event, direction, x, y)\
- end\
- end\
- \
- OnLoad = function(self)\
- if not self.ChildOffset or not self.ChildOffset.X or not self.ChildOffset.Y then\
- self.ChildOffset = {X = 0, Y = 0}\
- end\
- self:UpdateScroll()\
- end\
- ]],\
- [\"SecureTextBox\"] = [[\
- Inherit = 'TextBox'\
- MaskCharacter = '*'\
- \
- OnDraw = function(self, x, y)\
- Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
- if self.CursorPos > #self.Text then\
- self.CursorPos = #self.Text\
- elseif self.CursorPos < 0 then\
- self.CursorPos = 0\
- end\
- local text = ''\
- \
- for i = 1, #self.Text do\
- text = text .. self.MaskCharacter\
- end\
- \
- if self.Bedrock:GetActiveObject() == self then\
- if #text > (self.Width - 2) then\
- text = text:sub(#text-(self.Width - 3))\
- self.Bedrock.CursorPos = {x + 1 + self.Width-2, y}\
- else\
- self.Bedrock.CursorPos = {x + 1 + self.CursorPos, y}\
- end\
- self.Bedrock.CursorColour = self.TextColour\
- end\
- \
- if #tostring(text) == 0 then\
- Drawing.DrawCharacters(x + 1, y, self.Placeholder, self.PlaceholderTextColour, self.BackgroundColour)\
- else\
- if not self.Selected then\
- Drawing.DrawCharacters(x + 1, y, text, self.TextColour, self.BackgroundColour)\
- else\
- for i = 1, #text do\
- local char = text:sub(i, i)\
- local textColour = self.TextColour\
- local backgroundColour = self.BackgroundColour\
- if i > self.DragStart and i - 1 <= self.CursorPos then\
- textColour = self.SelectedTextColour\
- backgroundColour = self.SelectedBackgroundColour\
- end\
- Drawing.DrawCharacters(x + i, y, char, textColour, backgroundColour)\
- end\
- end\
- end\
- end\
- ]],\
- [\"Separator\"] = [[\
- Colour = colours.grey\
- \
- OnDraw = function(self, x, y)\
- local char = \"|\"\
- if self.Width > self.Height then\
- char = '-'\
- end\
- Drawing.DrawArea(x, y, self.Width, self.Height, char, self.Colour, colours.transparent)\
- end\
- ]],\
- [\"TextBox\"] = [[\
- BackgroundColour = colours.lightGrey\
- SelectedBackgroundColour = colours.blue\
- SelectedTextColour = colours.white\
- TextColour = colours.black\
- PlaceholderTextColour = colours.grey\
- Placeholder = ''\
- AutoWidth = false\
- Text = \"\"\
- CursorPos = nil\
- Numerical = false\
- DragStart = nil\
- Selected = false\
- SelectOnClick = false\
- ActualDragStart = nil\
- \
- OnDraw = function(self, x, y)\
- Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
- if self.CursorPos > #self.Text then\
- self.CursorPos = #self.Text\
- elseif self.CursorPos < 0 then\
- self.CursorPos = 0\
- end\
- local text = self.Text\
- local offset = self:TextOffset()\
- if #text > (self.Width - 2) then\
- text = text:sub(offset+1, offset + self.Width - 2)\
- -- self.Bedrock.CursorPos = {x + 1 + self.Width-2, y}\
- -- else\
- end\
- if self.Bedrock:GetActiveObject() == self then\
- self.Bedrock.CursorPos = {x + 1 + self.CursorPos - offset, y}\
- self.Bedrock.CursorColour = self.TextColour\
- else\
- self.Selected = false\
- end\
- \
- if #tostring(text) == 0 then\
- Drawing.DrawCharacters(x + 1, y, self.Placeholder, self.PlaceholderTextColour, self.BackgroundColour)\
- else\
- if not self.Selected then\
- Drawing.DrawCharacters(x + 1, y, text, self.TextColour, self.BackgroundColour)\
- else\
- local startPos = self.DragStart - offset\
- local endPos = self.CursorPos - offset\
- if startPos > endPos then\
- startPos = self.CursorPos - offset\
- endPos = self.DragStart - offset\
- end\
- for i = 1, #text do\
- local char = text:sub(i, i)\
- local textColour = self.TextColour\
- local backgroundColour = self.BackgroundColour\
- \
- if i > startPos and i - 1 <= endPos then\
- textColour = self.SelectedTextColour\
- backgroundColour = self.SelectedBackgroundColour\
- end\
- Drawing.DrawCharacters(x + i, y, char, textColour, backgroundColour)\
- end\
- end\
- end\
- end\
- \
- TextOffset = function(self)\
- if #self.Text < (self.Width - 2) then\
- return 0\
- elseif self.Bedrock:GetActiveObject() ~= self then\
- return 0\
- else\
- local textWidth = (self.Width - 2)\
- local offset = self.CursorPos - textWidth\
- if offset < 0 then\
- offset = 0\
- end\
- return offset\
- end\
- end\
- \
- OnLoad = function(self)\
- if not self.CursorPos then\
- self.CursorPos = #self.Text\
- end\
- end\
- \
- OnClick = function(self, event, side, x, y)\
- if self.Bedrock:GetActiveObject() ~= self and self.SelectOnClick then\
- self.CursorPos = #self.Text - 1\
- self.DragStart = 0\
- self.ActualDragStart = x - 2 + self:TextOffset()\
- self.Selected = true\
- else\
- self.CursorPos = x - 2 + self:TextOffset()\
- self.DragStart = self.CursorPos\
- self.Selected = false\
- end\
- self.Bedrock:SetActiveObject(self)\
- end\
- \
- OnDrag = function(self, event, side, x, y)\
- self.CursorPos = x - 2 + self:TextOffset()\
- if self.ActualDragStart then\
- self.DragStart = self.ActualDragStart\
- self.ActualDragStart = nil\
- end\
- if self.DragStart then\
- self.Selected = true\
- end\
- end\
- \
- OnKeyChar = function(self, event, keychar)\
- local deleteSelected = function()\
- if self.Selected then\
- local startPos = self.DragStart\
- local endPos = self.CursorPos\
- if startPos > endPos then\
- startPos = self.CursorPos\
- endPos = self.DragStart\
- end\
- self.Text = self.Text:sub(1, startPos) .. self.Text:sub(endPos + 2)\
- self.CursorPos = startPos\
- self.DragStart = nil\
- self.Selected = false\
- return true\
- end\
- end\
- \
- if event == 'char' then\
- deleteSelected()\
- if self.Numerical then\
- keychar = tostring(tonumber(keychar))\
- end\
- if keychar == 'nil' then\
- return\
- end\
- self.Text = string.sub(self.Text, 1, self.CursorPos ) .. keychar .. string.sub( self.Text, self.CursorPos + 1 )\
- if self.Numerical then\
- self.Text = tostring(tonumber(self.Text))\
- if self.Text == 'nil' then\
- self.Text = '1'\
- end\
- end\
- \
- self.CursorPos = self.CursorPos + 1\
- if self.OnChange then\
- self:OnChange(event, keychar)\
- end\
- return false\
- elseif event == 'key' then\
- if keychar == keys.enter then\
- if self.OnChange then\
- self:OnChange(event, keychar)\
- end\
- elseif keychar == keys.left then\
- -- Left\
- if self.CursorPos > 0 then\
- if self.Selected then\
- self.CursorPos = self.DragStart\
- self.DragStart = nil\
- self.Selected = false\
- else\
- self.CursorPos = self.CursorPos - 1\
- end\
- if self.OnChange then\
- self:OnChange(event, keychar)\
- end\
- end\
- \
- elseif keychar == keys.right then\
- -- Right \
- if self.CursorPos < string.len(self.Text) then\
- if self.Selected then\
- self.CursorPos = self.CursorPos\
- self.DragStart = nil\
- self.Selected = false\
- else\
- self.CursorPos = self.CursorPos + 1\
- end\
- if self.OnChange then\
- self:OnChange(event, keychar)\
- end\
- end\
- \
- elseif keychar == keys.backspace then\
- -- Backspace\
- if not deleteSelected() and self.CursorPos > 0 then\
- self.Text = string.sub( self.Text, 1, self.CursorPos - 1 ) .. string.sub( self.Text, self.CursorPos + 1 )\
- self.CursorPos = self.CursorPos - 1 \
- if self.Numerical then\
- self.Text = tostring(tonumber(self.Text))\
- if self.Text == 'nil' then\
- self.Text = '1'\
- end\
- end\
- if self.OnChange then\
- self:OnChange(event, keychar)\
- end\
- end\
- elseif keychar == keys.home then\
- -- Home\
- self.CursorPos = 0\
- if self.OnChange then\
- self:OnChange(event, keychar)\
- end\
- elseif keychar == keys.delete then\
- if not deleteSelected() and self.CursorPos < string.len(self.Text) then\
- self.Text = string.sub( self.Text, 1, self.CursorPos ) .. string.sub( self.Text, self.CursorPos + 2 ) \
- if self.Numerical then\
- self.Text = tostring(tonumber(self.Text))\
- if self.Text == 'nil' then\
- self.Text = '1'\
- end\
- end\
- if self.OnChange then\
- self:OnChange(keychar)\
- end\
- end\
- elseif keychar == keys[\"end\"] then\
- -- End\
- self.CursorPos = string.len(self.Text)\
- else\
- if self.OnChange then\
- self:OnChange(event, keychar)\
- end\
- return false\
- end\
- end\
- end\
- ]],\
- [\"View\"] = [[\
- BackgroundColour = colours.transparent\
- Children = {}\
- \
- OnDraw = function(self, x, y)\
- if self.BackgroundColour then\
- Drawing.DrawBlankArea(x, y, self.Width, self.Height, self.BackgroundColour)\
- end\
- end\
- \
- OnInitialise = function(self)\
- self.Children = {}\
- end\
- \
- InitialiseFile = function(self, bedrock, file, name)\
- local _new = {}\
- _new.X = 1\
- _new.Y = 1\
- _new.Width = Drawing.Screen.Width\
- _new.Height = Drawing.Screen.Height\
- _new.BackgroundColour = file.BackgroundColour\
- _new.Name = name\
- _new.Children = {}\
- _new.Bedrock = bedrock\
- local new = self:Initialise(_new)\
- for i, obj in ipairs(file.Children) do\
- local view = bedrock:ObjectFromFile(obj, new)\
- if not view.Z then\
- view.Z = i\
- end\
- view.Parent = new\
- table.insert(new.Children, view)\
- end\
- return new\
- end\
- \
- function CheckClick(self, object, x, y)\
- local offset = {X = 0, Y = 0}\
- if not object.Fixed and self.ChildOffset then\
- offset = self.ChildOffset\
- end\
- if object.X + offset.X <= x and object.Y + offset.Y <= y and object.X + offset.X + object.Width > x and object.Y + offset.Y + object.Height > y then\
- return true\
- end\
- end\
- \
- function DoClick(self, object, event, side, x, y)\
- if object then\
- if self:CheckClick(object, x, y) then\
- local offset = {X = 0, Y = 0}\
- if not object.Fixed and self.ChildOffset then\
- offset = self.ChildOffset\
- end\
- return object:Click(event, side, x - object.X - offset.X + 1, y - object.Y + 1 - offset.Y)\
- end\
- end \
- end\
- \
- Click = function(self, event, side, x, y, z)\
- if self.Visible and not self.IgnoreClick then\
- for i = #self.Children, 1, -1 do --children are ordered from smallest Z to highest, so this is done in reverse\
- local child = self.Children[i]\
- if self:DoClick(child, event, side, x, y) then\
- if self.OnChildClick then\
- self:OnChildClick(child, event, side, x, y)\
- end\
- return true\
- end\
- end\
- if event == 'mouse_click' and self.OnClick and self:OnClick(event, side, x, y) ~= false then\
- return true\
- elseif event == 'mouse_drag' and self.OnDrag and self:OnDrag(event, side, x, y) ~= false then\
- return true\
- elseif event == 'mouse_scroll' and self.OnScroll and self:OnScroll(event, side, x, y) ~= false then\
- return true\
- else\
- return false\
- end\
- else\
- return false\
- end\
- end\
- \
- OnRemove = function(self)\
- if self == self.Bedrock:GetActiveObject() then\
- self.Bedrock:SetActiveObject()\
- end\
- for i, child in ipairs(self.Children) do\
- child:OnRemove()\
- end\
- end\
- \
- local function findObjectNamed(view, name, minI)\
- local minI = minI or 0\
- if view and view.Children then\
- for i, child in ipairs(view.Children) do\
- if child.Name == name or child == name then\
- return child, i, view\
- elseif child.Children then\
- local found, index, foundView = findObjectNamed(child, name)\
- if found and minI <= index then\
- return found, index, foundView\
- end\
- end\
- end\
- end\
- end\
- \
- function ReorderObjects(self)\
- if self.Children then\
- table.sort(self.Children, function(a,b)\
- return a.Z < b.Z \
- end)\
- for i, v in ipairs(self.Children) do\
- if v.ReorderObjects then\
- v:ReorderObjects()\
- end\
- end\
- end\
- end\
- \
- function AddObject(self, info, extra, first)\
- if type(info) == 'string' then\
- local h = fs.open(self.Bedrock.ViewPath..info..'.view', 'r')\
- if h then\
- info = textutils.unserialize(h.readAll())\
- h.close()\
- else\
- error('Error in opening object: '..info)\
- end\
- end\
- \
- if extra then\
- for k, v in pairs(extra) do\
- if v then\
- info[k] = v\
- end\
- end\
- end\
- \
- local view = self.Bedrock:ObjectFromFile(info, self)\
- if not view.Z then\
- if first then\
- view.Z = 1\
- else\
- view.Z = #self.Children + 1\
- end\
- end\
- \
- if first then\
- table.insert(self.Children, 1, view)\
- else\
- table.insert(self.Children, view)\
- end\
- if self.Bedrock.View then\
- self.Bedrock:ReorderObjects()\
- end\
- self:ForceDraw()\
- return view\
- end\
- \
- function GetObject(self, name)\
- return findObjectNamed(self, name)\
- end\
- \
- local function findObjects(view, name)\
- local objects = {}\
- if view and view.Children then\
- for i, child in ipairs(view.Children) do\
- if child.Name == name or child == name then\
- table.insert(objects, child)\
- elseif child.Children then\
- local objs = findObjects(child, name)\
- if objs then\
- for i2, v in ipairs(objs) do\
- table.insert(objects, v)\
- end\
- end\
- end\
- end\
- end\
- return objects\
- end\
- \
- function GetObjects(self, name)\
- return findObjects(self, name)\
- end\
- \
- function RemoveObject(self, name)\
- local obj, index, view = findObjectNamed(self, name, minI)\
- if index then\
- view.Children[index]:OnRemove()\
- table.remove(view.Children, index)\
- if view.OnUpdate then\
- view:OnUpdate('Children')\
- end\
- return true\
- end\
- return false\
- end\
- \
- function RemoveObjects(self, name)\
- local i = 1\
- while self:RemoveObject(name) and i < 100 do\
- i = i + 1\
- end\
- \
- end\
- \
- function RemoveAllObjects(self)\
- for i, child in ipairs(self.Children) do\
- child:OnRemove()\
- self.Children[i] = nil\
- end\
- self:ForceDraw()\
- end\
- ]],\
- [\"Window\"] = [[\
- Inherit = 'View'\
- \
- ToolBarColour = colours.lightGrey\
- ToolBarTextColour = colours.black\
- ShadowColour = colours.grey\
- Title = ''\
- Flashing = false\
- CanClose = true\
- OnCloseButton = nil\
- OldActiveObject = nil\
- \
- LoadView = function(self)\
- local view = self:GetObject('View')\
- if view.ToolBarColour then\
- window.ToolBarColour = view.ToolBarColour\
- end\
- if view.ToolBarTextColour then\
- window.ToolBarTextColour = view.ToolBarTextColour\
- end\
- view.X = 1\
- view.Y = 2\
- \
- view:ForceDraw()\
- self:OnUpdate('View')\
- if self.OnViewLoad then\
- self.OnViewLoad(view)\
- end\
- self.OldActiveObject = self.Bedrock:GetActiveObject()\
- self.Bedrock:SetActiveObject(view)\
- end\
- \
- SetView = function(self, view)\
- self:RemoveObject('View')\
- table.insert(self.Children, view)\
- view.Parent = self\
- self:LoadView()\
- end\
- \
- Flash = function(self)\
- self.Flashing = true\
- self:ForceDraw()\
- self.Bedrock:StartTimer(function()self.Flashing = false end, 0.4)\
- end\
- \
- OnDraw = function(self, x, y)\
- local toolBarColour = (self.Flashing and colours.grey or self.ToolBarColour)\
- local toolBarTextColour = (self.Flashing and colours.black or self.ToolBarTextColour)\
- if toolBarColour then\
- Drawing.DrawBlankArea(x, y, self.Width, 1, toolBarColour)\
- end\
- if toolBarTextColour then\
- local title = self.Bedrock.Helpers.TruncateString(self.Title, self.Width - 2)\
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, title, toolBarTextColour, toolBarColour)\
- end\
- Drawing.IgnoreConstraint = true\
- Drawing.DrawBlankArea(x + 1, y + 1, self.Width, self.Height, self.ShadowColour)\
- Drawing.IgnoreConstraint = false\
- end\
- \
- Close = function(self)\
- self.Bedrock:SetActiveObject(self.OldActiveObject)\
- self.Bedrock.Window = nil\
- self.Bedrock:RemoveObject(self)\
- if self.OnClose then\
- self:OnClose()\
- end\
- self = nil\
- end\
- \
- OnUpdate = function(self, value)\
- if value == 'View' and self:GetObject('View') then\
- self.Width = self:GetObject('View').Width\
- self.Height = self:GetObject('View').Height + 1\
- self.X = math.ceil((Drawing.Screen.Width - self.Width) / 2)\
- self.Y = math.ceil((Drawing.Screen.Height - self.Height) / 2)\
- elseif value == 'CanClose' then\
- self:RemoveObject('CloseButton')\
- if self.CanClose then\
- local button = self:AddObject({X = 1, Y = 1, Width = 1, Height = 1, Type = 'Button', BackgroundColour = colours.red, TextColour = colours.white, Text = 'x', Name = 'CloseButton'})\
- button.OnClick = function(btn)\
- if self.OnCloseButton then\
- self:OnCloseButton()\
- end\
- self:Close()\
- end\
- end\
- end\
- end\
- ]],\
- }\
- BasePath = ''\
- ProgramPath = nil\
- \
- -- Program functions...\
- \
- local function main(...)\
- -- Code here...\
- end\
- \
- -- Run\
- local args = {...}\
- local _, err = pcall(function() main(unpack(args)) end)\
- if err then\
- -- Make a nice error handling screen here...\
- term.setBackgroundColor(colors.black)\
- term.setTextColor(colors.white)\
- term.clear()\
- term.setCursorPos(1, 3)\
- print(\" An Error Has Occured! D:\\n\\n\")\
- print(\" \" .. tostring(err) .. \"\\n\\n\")\
- print(\" Press any key to exit...\")\
- os.pullEvent(\"key\")\
- end\
- \
- function LoadAPIs(self)\
- local function loadAPI(name, content)\
- local env = setmetatable({}, { __index = getfenv() })\
- local func, err = loadstring(content, name..' (Bedrock API)')\
- if not func then\
- return false, printError(err)\
- end\
- setfenv(func, env)\
- func()\
- local api = {}\
- for k,v in pairs(env) do\
- api[k] = v\
- end\
- _G[name] = api\
- return true\
- end\
- \
- local env = getfenv()\
- local function loadObject(name, content)\
- loadAPI(name, content)\
- if env[name].Inherit then\
- if not getfenv()[env[name].Inherit] then \
- if objects[env[name].Inherit] then\
- loadObject(env[name].Inherit, objects[env[name].Inherit])\
- elseif fs.exists(self.ProgramPath..'/Objects/'..env[name].Inherit..'.lua') then\
- local h = fs.open(self.ProgramPath..'/Objects/'..env[name].Inherit..'.lua', 'r')\
- loadObject(env[name].Inherit, h.readAll())\
- h.close()\
- loadObject(name, content)\
- return\
- end\
- end\
- env[name].__index = getfenv()[env[name].Inherit]\
- else\
- env[name].__index = Object\
- end\
- setmetatable(env[name], env[name])\
- end\
- \
- for k, v in pairs(apis) do\
- loadAPI(k, v)\
- if k == 'Helpers' then\
- self.Helpers = Helpers\
- end\
- end\
- \
- for k, v in pairs(objects) do\
- loadObject(k, v)\
- end\
- \
- local privateObjPath = self.ProgramPath..'/Objects/'\
- if fs.exists(privateObjPath) and fs.isDir(privateObjPath) then\
- for i, v in ipairs(fs.list(privateObjPath)) do\
- if v ~= '.DS_Store' then\
- local name = string.match(v, '(%a+)%.?.-')\
- local h = fs.open(privateObjPath..v, 'r')\
- loadObject(name, h.readAll())\
- h.close()\
- end\
- end\
- end\
- \
- local privateAPIPath = self.ProgramPath..'/APIs/'\
- if fs.exists(privateAPIPath) and fs.isDir(privateAPIPath) then\
- for i, v in ipairs(fs.list(privateAPIPath)) do\
- if v ~= '.DS_Store' then\
- local name = string.match(v, '(%a+)%.?.-')\
- local h = fs.open(privateAPIPath..v, 'r')\
- loadAPI(name, h.readAll())\
- h.close()\
- end\
- end\
- end\
- end\
- \
- AllowTerminate = true\
- \
- View = nil\
- Menu = nil\
- \
- ActiveObject = nil\
- \
- DrawTimer = nil\
- DrawTimerExpiry = 0\
- \
- IsDrawing = false\
- \
- Running = true\
- \
- DefaultView = 'main'\
- \
- AnimationEnabled = true\
- \
- EventHandlers = {\
- \
- }\
- \
- ObjectClickHandlers = {\
- \
- }\
- \
- ObjectUpdateHandlers = {\
- \
- }\
- \
- Timers = {\
- \
- }\
- \
- ModifierKeys = {}\
- KeyboardShortcuts = {}\
- \
- keys.leftCommand = 219\
- keys.rightCommand = 220\
- \
- function Initialise(self, programPath)\
- self.ProgramPath = programPath or self.ProgramPath\
- if not programPath then\
- if self.ProgramPath then\
- local prgPath = self.ProgramPath\
- local prgName = fs.getName(prgPath)\
- if prgPath:find('/') then \
- self.ProgramPath = prgPath:sub(1, #prgPath-#prgName-1)\
- self.ProgramPath = prgPath:sub(1, #prgPath-#prgName-1) \
- else \
- self.ProgramPath = '' \
- end\
- else\
- self.ProgramPath = ''\
- end\
- end\
- self:LoadAPIs()\
- self.ViewPath = self.ProgramPath .. '/Views/'\
- --first, check that the barebones APIs are available\
- local requiredApis = {\
- 'Drawing',\
- 'View'\
- }\
- local env = getfenv()\
- for i,v in ipairs(requiredApis) do\
- if not env[v] then\
- error('The API: '..v..' is not loaded. Please make sure you load it to use Bedrock.')\
- end\
- end\
- \
- local copy = { }\
- for k, v in pairs(self) do\
- if k ~= 'Initialise' then\
- copy[k] = v\
- end\
- end\
- return setmetatable(copy, getmetatable(self))\
- end\
- \
- function HandleClick(self, event, side, x, y)\
- if self.Menu then\
- if not self.View:DoClick(self.Menu, event, side, x, y) then\
- self.Menu:Close()\
- end\
- elseif self.Window then\
- if not self.View:CheckClick(self.Window, x, y) then\
- self.Window:Flash()\
- else\
- self.View:DoClick(self.Window, event, side, x, y)\
- end\
- elseif self.View then\
- if self.View:Click(event, side, x, y) ~= false then\
- end \
- end\
- end\
- \
- function UnregisterKeyboardShortcut(self, name)\
- if name then\
- self.KeyboardShortcuts[name] = nil\
- end\
- end\
- \
- function RegisterKeyboardShortcut(self, keys, func, name)\
- name = name or tostring(math.random(1, 10000))\
- if type(keys[1]) == 'table' then\
- for i, v in ipairs(keys) do\
- self.KeyboardShortcuts[name] = {Keys = v, Function = func}\
- end\
- else\
- self.KeyboardShortcuts[name] = {Keys = keys, Function = func}\
- end\
- return name\
- end\
- \
- function TryKeyboardShortcuts(self, keychar)\
- if keychar == keys.backspace then\
- keychar = keys.delete\
- end\
- \
- local len = 1 -- + keychar\
- for k, v in pairs(self.ModifierKeys) do\
- len = len + 1\
- end\
- \
- for _, shortcut in pairs(self.KeyboardShortcuts) do\
- local match = true\
- for i2, key in ipairs(shortcut.Keys) do\
- if self.ModifierKeys[key] == nil and key ~= keychar then\
- match = false\
- end\
- end\
- \
- if match and #shortcut.Keys == len then\
- return shortcut.Function() ~= false\
- end\
- end\
- end\
- \
- function HandleKeyChar(self, event, keychar)\
- if keychar == keys.leftCtrl or keychar == keys.leftShift or keychar == keys.leftAlt or keychar == keys.leftCommand or keychar == keys.rightCommand or keychar == keys.rightCtrl or keychar == keys.rightShift or keychar == keys.rightAlt then\
- if keychar == keys.leftCommand or keychar == keys.rightCommand or keychar == keys.rightCtrl then\
- keychar = keys.leftCtrl\
- elseif keychar == keys.rightAlt then\
- keychar = keys.leftAlt\
- elseif keychar == keys.rightShift then\
- keychar = keys.leftShift\
- end\
- self.ModifierKeys[keychar] = self:StartTimer(function(_, timer)\
- if timer == self.ModifierKeys[keychar] then\
- self.ModifierKeys[keychar] = nil\
- end\
- end, 1)\
- elseif self:TryKeyboardShortcuts(keychar) then\
- return\
- end\
- \
- if self:GetActiveObject() then\
- local activeObject = self:GetActiveObject()\
- if activeObject.OnKeyChar then\
- if activeObject:OnKeyChar(event, keychar) ~= false then\
- --self:Draw()\
- end\
- end\
- end\
- end\
- \
- PreparedMenus = {}\
- \
- function PrepareMenu(self, name)\
- local menu = self:AddObject(name, {Type = 'Menu', X = 1, Y = 1, Prepared = true})\
- menu.Visible = false\
- self.PreparedMenus[name] = menu\
- return menu\
- end\
- \
- function ToggleMenu(self, name, owner, x, y)\
- if self.Menu then\
- self.Menu:Close()\
- return false\
- else\
- self:SetMenu(name, owner, x, y)\
- return true\
- end\
- end\
- \
- function SetMenu(self, menu, owner, x, y)\
- x = x or 1\
- y = y or 1\
- if self.Menu then\
- self.Menu:Close()\
- end \
- if menu then\
- local pos = owner:GetPosition()\
- if self.PreparedMenus[menu] then\
- self.Menu = self.PreparedMenus[menu]\
- self.Menu.Visible = true\
- self.Menu.Owner = owner\
- self.Menu.X = pos.X + x - 1\
- self.Menu.Y = pos.Y + y\
- self.Menu.Z = self.View.Children[#self.View.Children].Z + 1\
- self:ReorderObjects()\
- else\
- self.Menu = self:AddObject(menu, {Type = 'Menu', Owner = owner, X = pos.X + x - 1, Y = pos.Y + y, Z = self.View.Children[#self.View.Children].Z + 1})\
- end\
- end\
- end\
- \
- function ObjectClick(self, name, func)\
- self.ObjectClickHandlers[name] = func\
- end\
- \
- function ClickObject(self, object, event, side, x, y)\
- if self.ObjectClickHandlers[object.Name] then\
- return self.ObjectClickHandlers[object.Name](object, event, side, x, y)\
- end\
- return false\
- end\
- \
- function ObjectUpdate(self, name, func)\
- self.ObjectUpdateHandlers[name] = func\
- end\
- \
- function UpdateObject(self, object, ...)\
- if self.ObjectUpdateHandlers[object.Name] then\
- self.ObjectUpdateHandlers[object.Name](object, ...)\
- --self:Draw()\
- end\
- end\
- \
- function GetAbsolutePosition(self, obj)\
- if not obj.Parent then\
- return {X = obj.X, Y = obj.Y}\
- else\
- local pos = self:GetAbsolutePosition(obj.Parent)\
- local x = pos.X + obj.X - 1\
- local y = pos.Y + obj.Y - 1\
- if not obj.Fixed and obj.Parent.ChildOffset then\
- x = x + obj.Parent.ChildOffset.X\
- y = y + obj.Parent.ChildOffset.Y\
- end\
- return {X = x, Y = y}\
- end\
- end\
- \
- function LoadView(self, name, draw)\
- if self.View and self.OnViewClose then\
- self.OnViewClose(self.View.Name)\
- end\
- if self.View then\
- self.View:OnRemove()\
- end\
- local success = false\
- \
- if Drawing.Screen.Width <= 26 and fs.exists(self.ViewPath..name..'-pocket.view') then\
- name = name..'-pocket'\
- elseif Drawing.Screen.Width <= 39 and fs.exists(self.ViewPath..name..'-turtle.view') then\
- name = name..'-turtle'\
- end\
- \
- if not fs.exists(self.ViewPath..name..'.view') then\
- error('The view: '..name..'.view does not exist.')\
- end\
- \
- local h = fs.open(self.ViewPath..name..'.view', 'r')\
- if h then\
- local view = textutils.unserialize(h.readAll())\
- h.close()\
- if view then\
- self.View = View:InitialiseFile(self, view, name)\
- self:ReorderObjects()\
- \
- if OneOS and view.ToolBarColour then\
- OneOS.ToolBarColour = view.ToolBarColour\
- end\
- if OneOS and view.ToolBarTextColour then\
- OneOS.ToolBarTextColour = view.ToolBarTextColour\
- end\
- if not self:GetActiveObject() then\
- self:SetActiveObject()\
- end\
- success = true\
- end\
- end\
- \
- if success and self.OnViewLoad then\
- self.OnViewLoad(name)\
- end\
- \
- if draw ~= false then\
- self:Draw()\
- end\
- \
- if not success then\
- error('Failed to load view: '..name..'. It probably isn\\'t formatted correctly. Did you forget a } or ,?')\
- end\
- \
- return success\
- end\
- \
- function InheritFile(self, file, name)\
- local h = fs.open(self.ViewPath..name..'.view', 'r')\
- if h then\
- local super = textutils.unserialize(h.readAll())\
- if super then\
- if type(super) ~= 'table' then\
- error('View: \"'..name..'.view\" is not formatted correctly.')\
- end\
- \
- for k, v in pairs(super) do\
- if not file[k] then\
- file[k] = v\
- end\
- end\
- return file\
- end\
- end\
- return file\
- end\
- \
- function ParseStringSize(self, parent, k, v)\
- local parentSize = parent.Width\
- if k == 'Height' or k == 'Y' then\
- parentSize = parent.Height\
- end\
- local parts = {v}\
- if type(v) == 'string' and string.find(v, ',') then\
- parts = {}\
- for word in string.gmatch(v, '([^,]+)') do\
- table.insert(parts, word)\
- end\
- end\
- \
- v = 0\
- for i2, part in ipairs(parts) do\
- if type(part) == 'string' and part:sub(#part) == '%' then\
- v = v + math.ceil(parentSize * (tonumber(part:sub(1, #part-1)) / 100))\
- else\
- v = v + tonumber(part)\
- end\
- end\
- return v\
- end\
- \
- function ObjectFromFile(self, file, view)\
- local env = getfenv()\
- if env[file.Type] then\
- if not env[file.Type].Initialise then\
- error('Malformed Object: '..file.Type)\
- end\
- local object = {}\
- \
- if file.InheritView then\
- file = self:InheritFile(file, file.InheritView)\
- end\
- \
- object.AutoWidth = true\
- for k, v in pairs(file) do\
- if k == 'Width' or k == 'X' or k == 'Height' or k == 'Y' then\
- v = self:ParseStringSize(view, k, v)\
- end\
- \
- if k == 'Width' then\
- object.AutoWidth = false\
- end\
- if k ~= 'Children' then\
- object[k] = v\
- else\
- object[k] = {}\
- end\
- end\
- \
- object.Parent = view\
- object.Bedrock = self\
- if not object.Name then\
- object.Name = file.Type\
- end\
- \
- object = env[file.Type]:Initialise(object)\
- \
- if file.Children then\
- for i, obj in ipairs(file.Children) do\
- local _view = self:ObjectFromFile(obj, object)\
- if not _view.Z then\
- _view.Z = i\
- end\
- _view.Parent = object\
- table.insert(object.Children, _view)\
- end\
- end\
- \
- if not object.OnClick then\
- object.OnClick = function(...) return self:ClickObject(...) end\
- end\
- --object.OnUpdate = function(...) self:UpdateObject(...) end\
- \
- if object.OnUpdate then\
- for k, v in pairs(env[file.Type]) do\
- object:OnUpdate(k)\
- end\
- \
- for k, v in pairs(object.__index) do\
- object:OnUpdate(k)\
- end\
- end\
- \
- if object.Active then\
- object.Bedrock:SetActiveObject(object)\
- end\
- if object.OnLoad then\
- object:OnLoad()\
- end\
- object.Ready = true\
- return object\
- elseif not file.Type then\
- error('No object type specified. (e.g. Type = \"Button\")')\
- else\
- error('No Object: '..file.Type..'. The API probably isn\\'t loaded')\
- end\
- end\
- \
- function ReorderObjects(self)\
- if self.View and self.View.Children then\
- self.View:ReorderObjects()\
- end\
- end\
- \
- function AddObject(self, info, extra, first)\
- return self.View:AddObject(info, extra, first)\
- end\
- \
- function GetObject(self, name)\
- return self.View:GetObject(name)\
- end\
- \
- function GetObjects(self, name)\
- return self.View:GetObjects(name)\
- end\
- \
- function RemoveObject(self, name)\
- return self.View:RemoveObject(name)\
- end\
- \
- function RemoveObjects(self, name)\
- return self.View:RemoveObjects(name)\
- end\
- \
- DrawEvent = nil\
- \
- function HandleDraw(self, event, id)\
- if id == self.DrawEvent then\
- self.DrawEvent = nil\
- self:Draw()\
- end\
- end\
- \
- function ForceDraw(self)\
- if not self.DrawEvent then--or self.DrawTimerExpiry <= os.clock() then\
- self.DrawEvent = math.random()\
- os.queueEvent('bedrock_draw', self.DrawEvent)\
- -- self:StartTimer(function()\
- -- self.DrawTimer = nil\
- -- self:Draw()\
- -- end, 0.05)\
- -- self.DrawTimerExpiry = os.clock() + 0.1\
- end\
- end\
- \
- function DisplayWindow(self, _view, title, canClose)\
- if canClose == nil then\
- canClose = true\
- end\
- if type(_view) == 'string' then\
- local h = fs.open(self.ViewPath.._view..'.view', 'r')\
- if h then\
- _view = textutils.unserialize(h.readAll())\
- h.close()\
- end\
- end\
- \
- self.Window = self:AddObject({Type = 'Window', Z = 999, Title = title, CanClose = canClose})\
- _view.Type = 'View'\
- _view.Name = 'View'\
- _view.BackgroundColour = _view.BackgroundColour or colours.white\
- self.Window:SetView(self:ObjectFromFile(_view, self.Window))\
- end\
- \
- function DisplayAlertWindow(self, title, text, buttons, callback)\
- local func = function(btn)\
- self.Window:Close()\
- if callback then\
- callback(btn.Text)\
- end\
- end\
- local children = {}\
- local usedX = -1\
- if buttons then\
- for i, text in ipairs(buttons) do\
- usedX = usedX + 3 + #text\
- table.insert(children, {\
- [\"Y\"]=\"100%,-1\",\
- [\"X\"]=\"100%,-\"..usedX,\
- [\"Name\"]=text..\"Button\",\
- [\"Type\"]=\"Button\",\
- [\"Text\"]=text,\
- OnClick = func\
- })\
- end\
- end\
- \
- local width = usedX + 2\
- if width < 28 then\
- width = 28\
- end\
- \
- local canClose = true\
- if buttons and #buttons~=0 then\
- canClose = false\
- end\
- \
- local height = 0\
- if text then\
- height = #Helpers.WrapText(text, width - 2)\
- table.insert(children, {\
- [\"Y\"]=2,\
- [\"X\"]=2,\
- [\"Width\"]=\"100%,-2\",\
- [\"Height\"]=height,\
- [\"Name\"]=\"Label\",\
- [\"Type\"]=\"Label\",\
- [\"Text\"]=text\
- })\
- end\
- local view = {\
- Children = children,\
- Width=width,\
- Height=3+height+(canClose and 0 or 1),\
- OnKeyChar = function(_view, keychar)\
- func({Text=buttons[1]})\
- end\
- }\
- self:DisplayWindow(view, title, canClose)\
- end\
- \
- function DisplayTextBoxWindow(self, title, text, callback, textboxText, cursorAtEnd)\
- textboxText = textboxText or ''\
- local children = {\
- {\
- [\"Y\"]=\"100%,-1\",\
- [\"X\"]=\"100%,-4\",\
- [\"Name\"]=\"OkButton\",\
- [\"Type\"]=\"Button\",\
- [\"Text\"]=\"Ok\",\
- OnClick = function()\
- local text = self.Window:GetObject('TextBox').Text\
- self.Window:Close()\
- callback(true, text)\
- end\
- },\
- {\
- [\"Y\"]=\"100%,-1\",\
- [\"X\"]=\"100%,-13\",\
- [\"Name\"]=\"CancelButton\",\
- [\"Type\"]=\"Button\",\
- [\"Text\"]=\"Cancel\",\
- OnClick = function()\
- self.Window:Close()\
- callback(false)\
- end\
- }\
- }\
- \
- local height = -1\
- if text and #text ~= 0 then\
- height = #Helpers.WrapText(text, 26)\
- table.insert(children, {\
- [\"Y\"]=2,\
- [\"X\"]=2,\
- [\"Width\"]=\"100%,-2\",\
- [\"Height\"]=height,\
- [\"Name\"]=\"Label\",\
- [\"Type\"]=\"Label\",\
- [\"Text\"]=text\
- })\
- end\
- table.insert(children,\
- {\
- [\"Y\"]=3+height,\
- [\"X\"]=2,\
- [\"Width\"]=\"100%,-2\",\
- [\"Name\"]=\"TextBox\",\
- [\"Type\"]=\"TextBox\",\
- [\"Text\"]=textboxText,\
- [\"CursorPos\"]=(cursorAtEnd or 0)\
- })\
- local view = {\
- Children = children,\
- Width=28,\
- Height=5+height+(canClose and 0 or 1),\
- }\
- self:DisplayWindow(view, title)\
- self.Window:GetObject('TextBox').OnChange = function(txtbox, event, keychar)\
- if keychar == keys.enter then\
- self.Window:Close()\
- callback(true, txtbox.Text)\
- end\
- end\
- self:SetActiveObject(self.Window:GetObject('TextBox'))\
- self.Window.OnCloseButton = function()callback(false)end\
- end\
- \
- function DisplayOpenFileWindow(self, title, callback)\
- title = title or 'Open File'\
- local func = function(btn)\
- self.Window:Close()\
- if callback then\
- callback(btn.Text)\
- end\
- end\
- \
- local sidebarItems = {}\
- \
- --this is a really, really super bad way of doing it\
- local separator = ' !'\
- \
- local function addFolder(path, level)\
- for i, v in ipairs(_fs.list(path)) do\
- local fPath = path .. '/' .. v\
- if fPath ~= '/rom' and _fs.isDir(fPath) then\
- table.insert(sidebarItems, level .. v..separator..fPath)\
- addFolder(fPath, level .. ' ')\
- end\
- end\
- end\
- \
- if OneOS then\
- _fs = OneOS.FS\
- end\
- \
- addFolder('','')\
- \
- local currentFolder = ''\
- local selectedPath = nil\
- \
- local goToFolder = nil\
- \
- local children = {\
- {\
- [\"Y\"]=\"100%,-2\",\
- [\"X\"]=1,\
- [\"Height\"]=3,\
- [\"Width\"]=\"100%\",\
- [\"BackgroundColour\"]=colours.lightGrey,\
- [\"Name\"]=\"SidebarListView\",\
- [\"Type\"]=\"View\"\
- },\
- {\
- [\"Y\"]=\"100%,-1\",\
- [\"X\"]=\"100%,-4\",\
- [\"Name\"]=\"OkButton\",\
- [\"Type\"]=\"Button\",\
- [\"Text\"]=\"Ok\",\
- [\"BackgroundColour\"]=colours.white,\
- [\"Enabled\"]=false,\
- OnClick = function()\
- if selectedPath then\
- self.Window:Close()\
- callback(true, Helpers.TidyPath(selectedPath))\
- end\
- end\
- },\
- {\
- [\"Y\"]=\"100%,-1\",\
- [\"X\"]=\"100%,-13\",\
- [\"Name\"]=\"CancelButton\",\
- [\"Type\"]=\"Button\",\
- [\"Text\"]=\"Cancel\",\
- [\"BackgroundColour\"]=colours.white,\
- OnClick = function()\
- self.Window:Close()\
- callback(false)\
- end\
- },\
- {\
- [\"Y\"]=1,\
- [\"X\"]=1,\
- [\"Height\"]=\"100%,-3\",\
- [\"Width\"]=\"40%,-1\",\
- [\"Name\"]=\"SidebarListView\",\
- [\"Type\"]=\"ListView\",\
- [\"CanSelect\"]=true,\
- [\"Items\"]={\
- [\"Computer\"] = sidebarItems\
- },\
- OnSelect = function(listView, text)\
- local _,s = text:find(separator)\
- if s then\
- local path = text:sub(s + 1)\
- goToFolder(path)\
- end\
- end,\
- OnClick = function(listView, event, side, x, y)\
- if y == 1 then\
- goToFolder('/')\
- end\
- end\
- },\
- {\
- [\"Y\"]=1,\
- [\"X\"]=\"40%\",\
- [\"Height\"]=\"100%,-3\",\
- [\"Width\"]=1,\
- [\"Type\"]=\"Separator\"\
- },\
- {\
- [\"Y\"]=1,\
- [\"X\"]=\"40%,2\",\
- [\"Width\"]=\"65%,-3\",\
- [\"Height\"]=1,\
- [\"Type\"]=\"Label\",\
- [\"Name\"]=\"PathLabel\",\
- [\"TextColour\"]=colours.lightGrey,\
- [\"Text\"]='/'\
- },\
- {\
- [\"Y\"]=2,\
- [\"X\"]=\"40%,1\",\
- [\"Height\"]=\"100%,-4\",\
- [\"Width\"]=\"65%,-1\",\
- [\"Name\"]=\"FilesListView\",\
- [\"Type\"]=\"ListView\",\
- [\"CanSelect\"]=true,\
- [\"Items\"]={},\
- OnSelect = function(listView, text)\
- selectedPath = Helpers.TidyPath(currentFolder .. '/' .. text)\
- self.Window:GetObject('OkButton').Enabled = true\
- end,\
- OnClick = function(listView, event, side, x, y)\
- if y == 1 then\
- goToFolder('/')\
- end\
- end\
- },\
- }\
- local view = {\
- Children = children,\
- Width=40,\
- Height= Drawing.Screen.Height - 4,\
- OnCloseButton=function()\
- callback(false)\
- end\
- }\
- self:DisplayWindow(view, title)\
- \
- goToFolder = function(path)\
- path = Helpers.TidyPath(path)\
- self.Window:GetObject('PathLabel').Text = path\
- currentFolder = path\
- \
- local filesListItems = {}\
- for i, v in ipairs(_fs.list(path)) do\
- if not _fs.isDir(currentFolder .. v) then\
- table.insert(filesListItems, v)\
- end\
- end\
- self.Window:GetObject('OkButton').Enabled = false\
- selectedPath = nil\
- self.Window:GetObject('FilesListView').Items = filesListItems\
- \
- end\
- \
- if startPath then\
- goToFolder(startPath)\
- elseif OneOS then\
- goToFolder('/Desktop/Documents/')\
- else\
- goToFolder('')\
- end\
- \
- self.Window.OnCloseButton = function()callback(false)end\
- end\
- \
- function DisplaySaveFileWindow(self, title, callback, extension, startPath)\
- local _fs = fs\
- if extension and extension:sub(1,1) ~= '.' then\
- extension = '.' .. extension\
- end\
- extension = extension or ''\
- \
- title = title or 'Save File'\
- local func = function(btn)\
- self.Window:Close()\
- if callback then\
- callback(btn.Text)\
- end\
- end\
- \
- local sidebarItems = {}\
- \
- --this is a really, really super bad way of doing it\
- local separator = ' !'\
- \
- local function addFolder(path, level)\
- for i, v in ipairs(_fs.list(path)) do\
- local fPath = path .. '/' .. v\
- if fPath ~= '/rom' and _fs.isDir(fPath) then\
- table.insert(sidebarItems, level .. v..separator..fPath)\
- addFolder(fPath, level .. ' ')\
- end\
- end\
- end\
- \
- if OneOS then\
- _fs = OneOS.FS\
- end\
- addFolder('','')\
- \
- local currentFolder = ''\
- local selectedPath = nil\
- \
- local goToFolder = nil\
- \
- local function updatePath()\
- local text = self:GetObject('FileNameTextBox').Text\
- if #text == 0 then\
- self.Window:GetObject('OkButton').Enabled = false\
- selectedPath = Helpers.TidyPath(currentFolder)\
- else\
- self.Window:GetObject('OkButton').Enabled = true\
- selectedPath = Helpers.TidyPath(currentFolder .. '/' .. text .. extension)\
- end\
- self:GetObject('PathLabel').Text = selectedPath\
- end\
- \
- local children = {\
- {\
- [\"Y\"]=\"100%,-2\",\
- [\"X\"]=1,\
- [\"Height\"]=3,\
- [\"Width\"]=\"100%\",\
- [\"BackgroundColour\"]=colours.lightGrey,\
- [\"Type\"]=\"View\"\
- },\
- {\
- [\"Y\"]=\"100%,-1\",\
- [\"X\"]=\"100%,-4\",\
- [\"Name\"]=\"OkButton\",\
- [\"Type\"]=\"Button\",\
- [\"Text\"]=\"Ok\",\
- [\"BackgroundColour\"]=colours.white,\
- [\"Enabled\"]=false,\
- OnClick = function()\
- if selectedPath then\
- local text = self:GetObject('FileNameTextBox').Text\
- self.Window:Close()\
- callback(true, selectedPath, text)\
- end\
- end\
- },\
- {\
- [\"Y\"]=\"100%,-1\",\
- [\"X\"]=\"100%,-13\",\
- [\"Name\"]=\"CancelButton\",\
- [\"Type\"]=\"Button\",\
- [\"Text\"]=\"Cancel\",\
- [\"BackgroundColour\"]=colours.white,\
- OnClick = function()\
- self.Window:Close()\
- callback(false)\
- end\
- },\
- {\
- [\"Y\"]=\"100%,-2\",\
- [\"X\"]=3,\
- [\"Width\"]=\"100%,-4\",\
- [\"Name\"]=\"PathLabel\",\
- [\"Type\"]=\"Label\",\
- [\"Text\"]=\"/\",\
- [\"TextColour\"]=colours.grey\
- },\
- {\
- [\"Y\"]=\"100%,-1\",\
- [\"X\"]=3,\
- [\"Width\"]=\"100%,-17\",\
- [\"Name\"]=\"FileNameTextBox\",\
- [\"Type\"]=\"TextBox\",\
- [\"Placeholder\"]=\"File Name\",\
- [\"Active\"]=true,\
- [\"BackgroundColour\"]=colours.white,\
- OnChange = function(_self, event, keychar)\
- if keychar == keys.enter then\
- self:GetObject('OkButton'):OnClick()\
- else\
- updatePath()\
- end\
- end\
- },\
- {\
- [\"Y\"]=1,\
- [\"X\"]=2,\
- [\"Height\"]=\"100%,-3\",\
- [\"Width\"]=\"100%,-1\",\
- [\"Name\"]=\"SidebarListView\",\
- [\"Type\"]=\"ListView\",\
- [\"CanSelect\"]=true,\
- [\"Items\"]={\
- [\"Computer\"] = sidebarItems\
- },\
- OnSelect = function(listView, text)\
- local _,s = text:find(separator)\
- if s then\
- local path = text:sub(s + 1)\
- goToFolder(path)\
- end\
- end,\
- OnClick = function(listView, event, side, x, y)\
- if y == 1 then\
- goToFolder('/')\
- end\
- end\
- },\
- }\
- local view = {\
- Children = children,\
- Width=35,\
- Height= Drawing.Screen.Height - 4,\
- OnCloseButton=function()\
- callback(false)\
- end\
- }\
- self:DisplayWindow(view, title)\
- \
- self:SetActiveObject(self.Window:GetObject('FileNameTextBox'))\
- \
- goToFolder = function(path)\
- path = Helpers.TidyPath(path)\
- currentFolder = path\
- selectedPath = nil\
- updatePath()\
- end\
- \
- if startPath then\
- goToFolder(startPath)\
- elseif OneOS then\
- goToFolder('/Desktop/Documents/')\
- else\
- goToFolder('')\
- end\
- \
- self.Window.OnCloseButton = function()callback(false)end\
- end\
- \
- function RegisterEvent(self, event, func)\
- if not self.EventHandlers[event] then\
- self.EventHandlers[event] = {}\
- end\
- table.insert(self.EventHandlers[event], func)\
- end\
- \
- function StartRepeatingTimer(self, func, interval)\
- local int = interval\
- if type(int) == 'function' then\
- int = int()\
- end\
- if not int or int <= 0 then\
- return\
- end\
- local timer = os.startTimer(int)\
- \
- self.Timers[timer] = {func, true, interval}\
- return timer\
- end\
- \
- function StartTimer(self, func, delay)\
- local timer = os.startTimer(delay)\
- self.Timers[timer] = {func, false}\
- return timer\
- end\
- \
- function StopTimer(self, timer)\
- if self.Timers[timer] then\
- self.Timers[timer] = nil\
- end\
- end\
- \
- function HandleTimer(self, event, timer)\
- if self.Timers[timer] then\
- local oldTimer = self.Timers[timer]\
- self.Timers[timer] = nil\
- local new = nil\
- if oldTimer[2] then\
- new = self:StartRepeatingTimer(oldTimer[1], oldTimer[3])\
- end\
- if oldTimer and oldTimer[1] then\
- oldTimer[1](new, timer)\
- end\
- elseif self.OnTimer then\
- self.OnTimer(self, event, timer)\
- end\
- end\
- \
- function SetActiveObject(self, object)\
- if object then\
- if object ~= self.ActiveObject then\
- self.ActiveObject = object\
- object:ForceDraw()\
- end\
- elseif self.ActiveObject ~= nil then\
- self.ActiveObject = nil\
- self.CursorPos = nil\
- self.View:ForceDraw()\
- end\
- end\
- \
- function GetActiveObject(self)\
- return self.ActiveObject\
- end\
- \
- OnTimer = nil\
- OnClick = nil\
- OnKeyChar = nil\
- OnDrag = nil\
- OnScroll = nil\
- OnViewLoad = nil\
- OnViewClose = nil\
- OnDraw = nil\
- OnQuit = nil\
- \
- local eventFuncs = {\
- OnClick = {'mouse_click', 'monitor_touch'},\
- OnKeyChar = {'key', 'char'},\
- OnDrag = {'mouse_drag'},\
- OnScroll = {'mouse_scroll'},\
- HandleClick = {'mouse_click', 'mouse_drag', 'mouse_scroll', 'monitor_touch'},\
- HandleKeyChar = {'key', 'char'},\
- HandleTimer = {'timer'},\
- HandleDraw = {'bedrock_draw'}\
- }\
- \
- local drawCalls = 0\
- local ignored = 0\
- function Draw(self)\
- self.IsDrawing = true\
- if self.OnDraw then\
- self:OnDraw()\
- end\
- \
- if self.View and self.View:NeedsDraw() then\
- self.View:Draw()\
- Drawing.DrawBuffer()\
- if isDebug then\
- drawCalls = drawCalls + 1\
- end\
- elseif not self.View then\
- print('No loaded view. You need to do program:LoadView first.')\
- end \
- \
- if self:GetActiveObject() and self.CursorPos and type(self.CursorPos[1]) == 'number' and type(self.CursorPos[2]) == 'number' then\
- term.setCursorPos(self.CursorPos[1], self.CursorPos[2])\
- term.setTextColour(self.CursorColour)\
- term.setCursorBlink(true)\
- else\
- term.setCursorBlink(false)\
- end\
- \
- self.IsDrawing = false\
- end\
- \
- function EventHandler(self)\
- local event = { os.pullEventRaw() }\
- \
- if self.EventHandlers[event[1]] then\
- for i, e in ipairs(self.EventHandlers[event[1]]) do\
- e(self, unpack(event))\
- end\
- end\
- end\
- \
- function Quit(self)\
- self.Running = false\
- if self.OnQuit then\
- self:OnQuit()\
- end\
- if OneOS then\
- OneOS.Close()\
- end\
- end\
- \
- function Run(self, ready)\
- if not term.isColour or not term.isColour() then\
- print('This program requires an advanced (golden) comptuer to run, sorry.')\
- error('', 0)\
- end\
- \
- for name, events in pairs(eventFuncs) do\
- if self[name] then\
- for i, event in ipairs(events) do\
- self:RegisterEvent(event, self[name])\
- end\
- end\
- end\
- \
- if self.AllowTerminate then\
- self:RegisterEvent('terminate', function()error('Terminated', 0) end)\
- end\
- \
- if self.DefaultView and self.DefaultView ~= '' and fs.exists(self.ViewPath..self.DefaultView..'.view') then\
- self:LoadView(self.DefaultView)\
- end\
- \
- if ready then\
- ready()\
- end\
- \
- self:Draw()\
- \
- while self.Running do\
- self:EventHandler()\
- end\
- end",
- APIs = {
- [ "JSON.lua" ] = "local base = _G\
- \
- -----------------------------------------------------------------------------\
- -- Module declaration\
- -----------------------------------------------------------------------------\
- \
- -- Public functions\
- \
- -- Private functions\
- local decode_scanArray\
- local decode_scanComment\
- local decode_scanConstant\
- local decode_scanNumber\
- local decode_scanObject\
- local decode_scanString\
- local decode_scanWhitespace\
- local encodeString\
- local isArray\
- local isEncodable\
- \
- -----------------------------------------------------------------------------\
- -- PUBLIC FUNCTIONS\
- -----------------------------------------------------------------------------\
- --- Encodes an arbitrary Lua object / variable.\
- -- @param v The Lua object / variable to be JSON encoded.\
- -- @return String containing the JSON encoding in internal Lua string format (i.e. not unicode)\
- function encode (v)\
- -- Handle nil values\
- if v==nil then\
- return \"null\"\
- end\
- \
- local vtype = base.type(v) \
- \
- -- Handle strings\
- if vtype=='string' then \
- return '\"' .. encodeString(v) .. '\"' -- Need to handle encoding in string\
- end\
- \
- -- Handle booleans\
- if vtype=='number' or vtype=='boolean' then\
- return base.tostring(v)\
- end\
- \
- -- Handle tables\
- if vtype=='table' then\
- local rval = {}\
- -- Consider arrays separately\
- local bArray, maxCount = isArray(v)\
- if bArray then\
- for i = 1,maxCount do\
- table.insert(rval, encode(v[i]))\
- end\
- else -- An object, not an array\
- for i,j in base.pairs(v) do\
- if isEncodable(i) and isEncodable(j) then\
- table.insert(rval, '\"' .. encodeString(i) .. '\":' .. encode(j))\
- end\
- end\
- end\
- if bArray then\
- return '[' .. table.concat(rval,',') ..']'\
- else\
- return '{' .. table.concat(rval,',') .. '}'\
- end\
- end\
- \
- -- Handle null values\
- if vtype=='function' and v==null then\
- return 'null'\
- end\
- \
- base.assert(false,'encode attempt to encode unsupported type ' .. vtype .. ':' .. base.tostring(v))\
- end\
- \
- \
- --- Decodes a JSON string and returns the decoded value as a Lua data structure / value.\
- -- @param s The string to scan.\
- -- @param [startPos] Optional starting position where the JSON string is located. Defaults to 1.\
- -- @param Lua object, number The object that was scanned, as a Lua table / string / number / boolean or nil,\
- -- and the position of the first character after\
- -- the scanned JSON object.\
- function decode(s, startPos)\
- startPos = startPos and startPos or 1\
- startPos = decode_scanWhitespace(s,startPos)\
- base.assert(startPos<=string.len(s), 'Unterminated JSON encoded object found at position in [' .. s .. ']')\
- local curChar = string.sub(s,startPos,startPos)\
- -- Object\
- if curChar=='{' then\
- return decode_scanObject(s,startPos)\
- end\
- -- Array\
- if curChar=='[' then\
- return decode_scanArray(s,startPos)\
- end\
- -- Number\
- if string.find(\"+-0123456789.e\", curChar, 1, true) then\
- return decode_scanNumber(s,startPos)\
- end\
- -- String\
- if curChar=='\"' or curChar==\"'\" then\
- return decode_scanString(s,startPos)\
- end\
- if string.sub(s,startPos,startPos+1)=='/*' then\
- return decode(s, decode_scanComment(s,startPos))\
- end\
- -- Otherwise, it must be a constant\
- return decode_scanConstant(s,startPos)\
- end\
- \
- --- The null function allows one to specify a null value in an associative array (which is otherwise\
- -- discarded if you set the value with 'nil' in Lua. Simply set t = { first=json.null }\
- function null()\
- return null -- so json.null() will also return null ;-)\
- end\
- -----------------------------------------------------------------------------\
- -- Internal, PRIVATE functions.\
- -- Following a Python-like convention, I have prefixed all these 'PRIVATE'\
- -- functions with an underscore.\
- -----------------------------------------------------------------------------\
- \
- --- Scans an array from JSON into a Lua object\
- -- startPos begins at the start of the array.\
- -- Returns the array and the next starting position\
- -- @param s The string being scanned.\
- -- @param startPos The starting position for the scan.\
- -- @return table, int The scanned array as a table, and the position of the next character to scan.\
- function decode_scanArray(s,startPos)\
- local array = {} -- The return value\
- local stringLen = string.len(s)\
- base.assert(string.sub(s,startPos,startPos)=='[','decode_scanArray called but array does not start at position ' .. startPos .. ' in string:\\n'..s )\
- startPos = startPos + 1\
- -- Infinite loop for array elements\
- repeat\
- startPos = decode_scanWhitespace(s,startPos)\
- base.assert(startPos<=stringLen,'JSON String ended unexpectedly scanning array.')\
- local curChar = string.sub(s,startPos,startPos)\
- if (curChar==']') then\
- return array, startPos+1\
- end\
- if (curChar==',') then\
- startPos = decode_scanWhitespace(s,startPos+1)\
- end\
- base.assert(startPos<=stringLen, 'JSON String ended unexpectedly scanning array.')\
- object, startPos = decode(s,startPos)\
- table.insert(array,object)\
- until false\
- end\
- \
- --- Scans a comment and discards the comment.\
- -- Returns the position of the next character following the comment.\
- -- @param string s The JSON string to scan.\
- -- @param int startPos The starting position of the comment\
- function decode_scanComment(s, startPos)\
- base.assert( string.sub(s,startPos,startPos+1)=='/*', \"decode_scanComment called but comment does not start at position \" .. startPos)\
- local endPos = string.find(s,'*/',startPos+2)\
- base.assert(endPos~=nil, \"Unterminated comment in string at \" .. startPos)\
- return endPos+2 \
- end\
- \
- --- Scans for given constants: true, false or null\
- -- Returns the appropriate Lua type, and the position of the next character to read.\
- -- @param s The string being scanned.\
- -- @param startPos The position in the string at which to start scanning.\
- -- @return object, int The object (true, false or nil) and the position at which the next character should be\
- -- scanned.\
- function decode_scanConstant(s, startPos)\
- local consts = { [\"true\"] = true, [\"false\"] = false, [\"null\"] = nil }\
- local constNames = {\"true\",\"false\",\"null\"}\
- \
- for i,k in base.pairs(constNames) do\
- --print (\"[\" .. string.sub(s,startPos, startPos + string.len(k) -1) ..\"]\", k)\
- if string.sub(s,startPos, startPos + string.len(k) -1 )==k then\
- return consts[k], startPos + string.len(k)\
- end\
- end\
- base.assert(nil, 'Failed to scan constant from string ' .. s .. ' at starting position ' .. startPos)\
- end\
- \
- --- Scans a number from the JSON encoded string.\
- -- (in fact, also is able to scan numeric +- eqns, which is not\
- -- in the JSON spec.)\
- -- Returns the number, and the position of the next character\
- -- after the number.\
- -- @param s The string being scanned.\
- -- @param startPos The position at which to start scanning.\
- -- @return number, int The extracted number and the position of the next character to scan.\
- function decode_scanNumber(s,startPos)\
- local endPos = startPos+1\
- local stringLen = string.len(s)\
- local acceptableChars = \"+-0123456789.e\"\
- while (string.find(acceptableChars, string.sub(s,endPos,endPos), 1, true)\
- and endPos<=stringLen\
- ) do\
- endPos = endPos + 1\
- end\
- local stringValue = 'return ' .. string.sub(s,startPos, endPos-1)\
- local stringEval = base.loadstring(stringValue)\
- base.assert(stringEval, 'Failed to scan number [ ' .. stringValue .. '] in JSON string at position ' .. startPos .. ' : ' .. endPos)\
- return stringEval(), endPos\
- end\
- \
- --- Scans a JSON object into a Lua object.\
- -- startPos begins at the start of the object.\
- -- Returns the object and the next starting position.\
- -- @param s The string being scanned.\
- -- @param startPos The starting position of the scan.\
- -- @return table, int The scanned object as a table and the position of the next character to scan.\
- function decode_scanObject(s,startPos)\
- local object = {}\
- local stringLen = string.len(s)\
- local key, value\
- base.assert(string.sub(s,startPos,startPos)=='{','decode_scanObject called but object does not start at position ' .. startPos .. ' in string:\\n' .. s)\
- startPos = startPos + 1\
- repeat\
- startPos = decode_scanWhitespace(s,startPos)\
- base.assert(startPos<=stringLen, 'JSON string ended unexpectedly while scanning object.')\
- local curChar = string.sub(s,startPos,startPos)\
- if (curChar=='}') then\
- return object,startPos+1\
- end\
- if (curChar==',') then\
- startPos = decode_scanWhitespace(s,startPos+1)\
- end\
- base.assert(startPos<=stringLen, 'JSON string ended unexpectedly scanning object.')\
- -- Scan the key\
- key, startPos = decode(s,startPos)\
- base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)\
- startPos = decode_scanWhitespace(s,startPos)\
- base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)\
- base.assert(string.sub(s,startPos,startPos)==':','JSON object key-value assignment mal-formed at ' .. startPos)\
- startPos = decode_scanWhitespace(s,startPos+1)\
- base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)\
- value, startPos = decode(s,startPos)\
- object[key]=value\
- until false -- infinite loop while key-value pairs are found\
- end\
- \
- --- Scans a JSON string from the opening inverted comma or single quote to the\
- -- end of the string.\
- -- Returns the string extracted as a Lua string,\
- -- and the position of the next non-string character\
- -- (after the closing inverted comma or single quote).\
- -- @param s The string being scanned.\
- -- @param startPos The starting position of the scan.\
- -- @return string, int The extracted string as a Lua string, and the next character to parse.\
- function decode_scanString(s,startPos)\
- base.assert(startPos, 'decode_scanString(..) called without start position')\
- local startChar = string.sub(s,startPos,startPos)\
- base.assert(startChar==\"'\" or startChar=='\"','decode_scanString called for a non-string')\
- local escaped = false\
- local endPos = startPos + 1\
- local bEnded = false\
- local stringLen = string.len(s)\
- repeat\
- local curChar = string.sub(s,endPos,endPos)\
- -- Character escaping is only used to escape the string delimiters\
- if not escaped then\
- if curChar=='\\\\' then\
- escaped = true\
- else\
- bEnded = curChar==startChar\
- end\
- else\
- -- If we're escaped, we accept the current character come what may\
- escaped = false\
- end\
- endPos = endPos + 1\
- base.assert(endPos <= stringLen+1, \"String decoding failed: unterminated string at position \" .. endPos)\
- until bEnded\
- local stringValue = 'return ' .. string.sub(s, startPos, endPos-1)\
- local stringEval = base.loadstring(stringValue)\
- base.assert(stringEval, 'Failed to load string [ ' .. stringValue .. '] in JSON4Lua.decode_scanString at position ' .. startPos .. ' : ' .. endPos)\
- return stringEval(), endPos \
- end\
- \
- --- Scans a JSON string skipping all whitespace from the current start position.\
- -- Returns the position of the first non-whitespace character, or nil if the whole end of string is reached.\
- -- @param s The string being scanned\
- -- @param startPos The starting position where we should begin removing whitespace.\
- -- @return int The first position where non-whitespace was encountered, or string.len(s)+1 if the end of string\
- -- was reached.\
- function decode_scanWhitespace(s,startPos)\
- local whitespace=\" \\n\\r\\t\"\
- local stringLen = string.len(s)\
- while ( string.find(whitespace, string.sub(s,startPos,startPos), 1, true) and startPos <= stringLen) do\
- startPos = startPos + 1\
- end\
- return startPos\
- end\
- \
- --- Encodes a string to be JSON-compatible.\
- -- This just involves back-quoting inverted commas, back-quotes and newlines, I think ;-)\
- -- @param s The string to return as a JSON encoded (i.e. backquoted string)\
- -- @return The string appropriately escaped.\
- function encodeString(s)\
- s = string.gsub(s,'\\\\','\\\\\\\\')\
- s = string.gsub(s,'\"','\\\\\"')\
- s = string.gsub(s,\"'\",\"\\\\'\")\
- s = string.gsub(s,'\\n','\\\\n')\
- s = string.gsub(s,'\\t','\\\\t')\
- return s\
- end\
- \
- -- Determines whether the given Lua type is an array or a table / dictionary.\
- -- We consider any table an array if it has indexes 1..n for its n items, and no\
- -- other data in the table.\
- -- I think this method is currently a little 'flaky', but can't think of a good way around it yet...\
- -- @param t The table to evaluate as an array\
- -- @return boolean, number True if the table can be represented as an array, false otherwise. If true,\
- -- the second returned value is the maximum\
- -- number of indexed elements in the array.\
- function isArray(t)\
- -- Next we count all the elements, ensuring that any non-indexed elements are not-encodable\
- -- (with the possible exception of 'n')\
- local maxIndex = 0\
- for k,v in base.pairs(t) do\
- if (base.type(k)=='number' and math.floor(k)==k and 1<=k) then -- k,v is an indexed pair\
- if (not isEncodable(v)) then return false end -- All array elements must be encodable\
- maxIndex = math.max(maxIndex,k)\
- else\
- if (k=='n') then\
- if v ~= table.getn(t) then return false end -- False if n does not hold the number of elements\
- else -- Else of (k=='n')\
- if isEncodable(v) then return false end\
- end -- End of (k~='n')\
- end -- End of k,v not an indexed pair\
- end -- End of loop across all pairs\
- return true, maxIndex\
- end\
- \
- --- Determines whether the given Lua object / table / variable can be JSON encoded. The only\
- -- types that are JSON encodable are: string, boolean, number, nil, table and json.null.\
- -- In this implementation, all other types are ignored.\
- -- @param o The object to examine.\
- -- @return boolean True if the object should be JSON encoded, false if it should be ignored.\
- function isEncodable(o)\
- local t = base.type(o)\
- return (t=='string' or t=='boolean' or t=='number' or t=='nil' or t=='table') or (t=='function' and o==null)\
- end",
- [ "App.lua" ] = "ID = nil\
- Author = nil\
- Category = nil\
- Name = nil\
- Description = nil\
- Icon = nil\
- \
- Bedrock = nil\
- \
- local function parseNFT(lines)\
- local image = {\
- text = {},\
- textcol = {}\
- }\
- for y, line in ipairs(lines) do\
- table.insert(image, y, {})\
- table.insert(image.text, y, {})\
- table.insert(image.textcol, y, {})\
- \
- local bgNext, fgNext = false, false\
- local currBG, currFG = nil,nil\
- local writePosition = 1\
- for x = 1, #line do\
- \
- local nextChar = string.sub(line, x, x)\
- if nextChar:byte() == 30 then\
- bgNext = true\
- elseif nextChar:byte() == 31 then\
- fgNext = true\
- elseif bgNext then\
- currBG = Drawing.GetColour(nextChar)\
- if currBG == nil then\
- currBG = colours.transparent\
- end\
- bgNext = false\
- elseif fgNext then\
- currFG = Drawing.GetColour(nextChar)\
- fgNext = false\
- else\
- if nextChar ~= \" \" and currFG == nil then\
- currFG = colours.white\
- end\
- image[y][writePosition] = currBG\
- image.textcol[y][writePosition] = currFG\
- image.text[y][writePosition] = nextChar\
- writePosition = writePosition + 1\
- end\
- end\
- end\
- return image\
- end\
- \
- local function split(a,e)\
- local t,e=e or\":\",{}\
- local t=string.format(\"([^%s]+)\",t)\
- a:gsub(t,function(t)e[#e+1]=t end)\
- return e\
- end\
- \
- Initialise = function(self, data, bedrock)\
- local new = {} -- the new instance\
- setmetatable(new, {__index = self} )\
- \
- new.ID = data.id\
- new.Author = tostring(data.user.username)\
- new.Category = tostring(data.category)\
- new.Name = tostring(data.name)\
- new.Description = tostring(data.description)\
- new.Icon = parseNFT(split(data.icon, '\\n'))\
- \
- new.Bedrock = bedrock\
- \
- return new\
- end\
- \
- Install = function(self)\
- self.Bedrock:OpenPage('InstallPageView', {\
- App = self\
- })\
- end\
- \
- InstallData = function(self, data)\
- if type(data) ~= 'string' or #data == 0 then\
- return false, 'EMPTY'\
- end\
- \
- local pack = JSON.decode(data)\
- \
- if not pack then\
- return false, 'PACKAGE'\
- end\
- \
- local _fs = fs\
- if OneOS then\
- _fs = OneOS.FS\
- end\
- local function makeFile(_path,_content)\
- local file=_fs.open(_path,\"w\")\
- if file then\
- file.write(_content)\
- file.close()\
- else\
- error(_path)\
- end\
- end\
- local function makeFolder(_path,_content)\
- _fs.makeDir(_path)\
- for k,v in pairs(_content) do\
- if type(v)==\"table\" then\
- makeFolder(_path..\"/\"..k,v)\
- else\
- makeFile(_path..\"/\"..k,v)\
- end\
- end\
- end\
- \
- local installPath = '/'\
- local removeSpaces = true\
- local alwaysFolder = false\
- local fullPath = false\
- \
- if OneOS then\
- installPath = '/Programs/' .. self.Name .. '.program/'\
- removeSpaces = false\
- alwaysFolder = true\
- fullPath = true\
- \
- -- TODO: app icon\
- end\
- \
- local appName = self.Name\
- local keyCount = 0\
- for k, v in pairs(pack) do\
- keyCount = keyCount + 1\
- end\
- if removeSpaces then\
- appName = appName:gsub(\" \", \"\")\
- end\
- local location = installPath .. '/'\
- \
- if not fullPath then\
- location = location .. appName\
- end\
- if keyCount == 1 and not alwaysFolder then\
- makeFile(location, pack['startup'])\
- else\
- makeFolder(location, pack)\
- location = location .. '/startup'\
- end\
- \
- return self.Bedrock.Helpers.TidyPath(location)\
- end",
- },
- Views = {
- [ "main.view" ] = "{\
- Children = {\
- {\
- X = '50%,-13',\
- Y = 1,\
- Text = 'Home',\
- TextColour = 'grey',\
- Name = 'HomeLabel',\
- Type = 'Label'\
- },\
- {\
- X = '50%,-5',\
- Y = 1,\
- Text = 'Categories',\
- TextColour = 'grey',\
- Name = 'CategoriesLabel',\
- Type = 'Label'\
- },\
- {\
- X = '50%,9',\
- Y = 1,\
- Text = 'Search',\
- TextColour = 'grey',\
- Name = 'SearchLabel',\
- Type = 'Label'\
- },\
- {\
- X = 1,\
- Y = 2,\
- Type = 'Separator',\
- Width = '100%',\
- Colour = 'lightGrey'\
- },\
- \
- {\
- X = 1,\
- Y = 3,\
- Width = '100%',\
- Height = '100%,-2',\
- Type = 'ScrollView',\
- Name = 'ContentScrollView',\
- Children = {\
- {\
- X = 1,\
- Y = 1,\
- Type = 'HomePageView',\
- Name = 'CurrentPage',\
- Width = '100%',\
- Height = '100%'\
- }\
- }\
- },\
- \
- {\
- X = '100%',\
- Y = 1,\
- Text = 'x',\
- TextColour = 'blue',\
- Name = 'QuitLabel',\
- Type = 'Label'\
- },\
- \
- \
- },\
- BackgroundColour = 'white'\
- }",
- },
- appstore = "local bedrockPath='/' if OneOS then OneOS.LoadAPI('/System/API/Bedrock.lua', false)elseif fs.exists(bedrockPath..'/Bedrock')then os.loadAPI(bedrockPath..'/Bedrock')else if http then print('Downloading Bedrock...')local h=http.get('http://pastebin.com/raw.php?i=0MgKNqpN')if h then local f=fs.open(bedrockPath..'/Bedrock','w')f.write(h.readAll())f.close()h.close()os.loadAPI(bedrockPath..'/Bedrock')else error('Failed to download Bedrock. Is your internet working?') end else error('This program needs to download Bedrock to work. Please enable HTTP.') end end if Bedrock then Bedrock.BasePath = bedrockPath Bedrock.ProgramPath = shell.getRunningProgram() end\
- \
- \
- local program = Bedrock:Initialise()\
- \
- program.AppStoreURL = 'http://appstore.olivercooper.me/'\
- \
- program:RegisterKeyboardShortcut({'\\\\'}, function()os.reboot()end)\
- \
- program.OnKeyChar = function(self, event, keychar)\
- if (keychar == keys.up or keychar == keys.down) then --and not program:GetActiveObject() then\
- local currentPage = self:GetObject('CurrentPage')\
- if currentPage then\
- currentPage:OnScroll('mouse_scroll', (keychar == keys.up) and -1 or 1, 1, 1)\
- end\
- end\
- end\
- \
- program.OpenPage = function(self, pageType, values)\
- program:SetActiveObject()\
- \
- local currentPage = self:GetObject('CurrentPage')\
- local previousPage = self:GetObject('PreviousPage')\
- \
- if currentPage then\
- currentPage.Name = 'PreviousPage'\
- currentPage.Visible = false\
- end\
- \
- if previousPage then\
- self:RemoveObject(previousPage)\
- end\
- \
- if not values then\
- values = {}\
- end\
- values.Type = pageType\
- values.Name = 'CurrentPage'\
- values.X = 1\
- values.Y = 1\
- values.Width = '100%'\
- values.Height = '100%'\
- self:GetObject('ContentScrollView'):AddObject(values)\
- end\
- \
- program.OpenPreviousPage = function(self)\
- program:SetActiveObject()\
- \
- local currentPage = self:GetObject('CurrentPage')\
- local previousPage = self:GetObject('PreviousPage')\
- if previousPage then\
- previousPage.Name = 'CurrentPage'\
- previousPage.Visible = true\
- \
- if currentPage then\
- self:RemoveObject(currentPage)\
- end\
- else\
- self:OpenPage('HomePageView')\
- end\
- end\
- \
- program:Run(function()\
- program:RegisterEvent('http_success', function(self, event, url, h)\
- local currentPage = self:GetObject('CurrentPage')\
- if currentPage and not currentPage.Failed and not currentPage.Success and currentPage.RequestURL == url then\
- currentPage.Success = true\
- currentPage:OnDataLoad(url, h.readAll())\
- h.close()\
- end\
- end)\
- \
- program:RegisterEvent('http_failure', function(self, event, url)\
- local currentPage = self:GetObject('CurrentPage')\
- if currentPage and not currentPage.Failed and not currentPage.Success and currentPage.RequestURL == url then\
- currentPage.Failed = true\
- currentPage:OnDataFailed(url, 'GENERIC')\
- end\
- end)\
- \
- program:GetObject('HomeLabel').OnClick = function(self)\
- program:OpenPage('HomePageView')\
- end\
- \
- program:GetObject('CategoriesLabel').OnClick = function(self)\
- program:OpenPage('CategoriesPageView')\
- end\
- \
- program:GetObject('SearchLabel').OnClick = function(self)\
- program:OpenPage('SearchPageView')\
- end\
- \
- if OneOS then\
- program:GetObject('QuitLabel').Visible = false\
- else\
- program:GetObject('QuitLabel').OnClick = function()\
- term.setCursorPos(1, 1)\
- term.setBackgroundColour(colors.black)\
- term.setTextColor(colours.white)\
- term.clear()\
- print('Thanks for using the App Store!')\
- print('(c) 2013 - 2015 oeed')\
- program:Quit()\
- end\
- end\
- \
- end)",
- Objects = {
- [ "InstallPageView.lua" ] = "Inherit = 'PageView'\
- \
- TimeoutLength = 40\
- \
- OnLoad = function(self)\
- self:RemoveAllObjects()\
- ScrollView.OnLoad(self)\
- self:AddObject({\
- X = '50%,-4',\
- Y = '50%,-3',\
- Type = 'LoadingIndicator',\
- })\
- self:AddObject({\
- X = 1,\
- Y = '50%,1',\
- Width = '100%',\
- Align = 'Center',\
- Type = 'Label',\
- TextColour = 'blue',\
- Text = 'Downloading ' .. self.App.Name\
- })\
- self:FetchData()\
- end\
- \
- OnDataLoad = function(self, url, data)\
- local location, err = self.App:InstallData(data)\
- if err then\
- self.Success = false\
- self.Failed = true\
- self:OnDataFailed(nil, err)\
- return\
- end\
- \
- self:RemoveAllObjects()\
- \
- self:AddObject({\
- X = 1,\
- Y = '50%,-1',\
- Width = '100%',\
- Align = 'Center',\
- Type = 'Label',\
- TextColour = 'blue',\
- Text = 'Installation Successful'\
- })\
- \
- self:AddObject({\
- X = 1,\
- Y = '50%,0',\
- Width = '100%',\
- Align = 'Center',\
- Type = 'Label',\
- TextColour = 'lightBlue',\
- Text = location\
- })\
- \
- self:AddObject({\
- X = 1,\
- Y = '50%,2',\
- X = '50%,-4',\
- Type = 'Button',\
- TextColour = 'white',\
- BackgroundColour = 'blue',\
- Text = 'Okay',\
- OnClick = function()\
- self.Bedrock:OpenPreviousPage()\
- end\
- })\
- end\
- \
- DataURL = function(self, info)\
- return self.Bedrock.AppStoreURL .. 'api/?command=application&subcommand=download&id=' .. textutils.urlEncode(self.App.ID)\
- end",
- [ "LoadingIndicator.lua" ] = "Width = 7\
- Height = 5\
- \
- Step = 1\
- \
- UpdateDrawBlacklist = {\
- ['Step'] = true,\
- }\
- \
- OnDraw = function(self, x, y)\
- local reverseStep = 9\
- local resetStep = 18\
- if self.Step > resetStep then\
- self.Step = 0\
- end\
- \
- self.Step = self.Step + 1\
- \
- for i = 0, 3 do\
- local _y = math.min(math.max(0, self.Step - 2 * i), 3)\
- if self.Step > reverseStep then\
- _y = 3 - math.min(math.max(0, self.Step - reverseStep - 2 * i), 3)\
- end\
- \
- local colour = (_y == 3 and colours.blue or (_y == 0 and colours.white or colours.lightBlue))\
- Drawing.WriteToBuffer(x + i * 2, y + _y - 1, ' ', colours.black, colour)\
- end\
- \
- Drawing.DrawCharacters(x, y + 4, 'Loading', colours.blue, colours.transparent)\
- \
- self.Bedrock:StartTimer(function()\
- self:ForceDraw()\
- end, 0.05)\
- end",
- [ "AppView.lua" ] = "Inherit = 'View'\
- \
- Width = 24\
- Height = 4\
- App = nil\
- \
- OnLoad = function(self)\
- self:AddObject({\
- X = 1,\
- Y = 1,\
- Width = 4,\
- Height = 3,\
- Type = 'ImageView',\
- -- Path = '/Resources/Ink'\
- })\
- \
- self:AddObject({\
- X = 6,\
- Y = 1,\
- Type = 'Label',\
- Name = 'NameLabel',\
- Text = ''\
- })\
- \
- self:AddObject({\
- X = 6,\
- Y = 2,\
- Type = 'Label',\
- Name = 'AuthorLabel',\
- Text = '',\
- TextColour = 'lightGrey'\
- })\
- \
- self:AddObject({\
- X = 6,\
- Y = 3,\
- Type = 'Label',\
- -- Name = 'AuthorLabel',\
- Text = 'Install >',\
- TextColour = 'blue',\
- OnClick = function()\
- if self.App then\
- self.App:Install()\
- end\
- end\
- })\
- \
- self:OnUpdate('App')\
- end\
- \
- \
- \
- OnUpdate = function(self, value)\
- if value == 'App' then\
- self:GetObject('NameLabel').Text = self.Bedrock.Helpers.TruncateString(self.App.Name, self.Width - 6)\
- self:GetObject('AuthorLabel').Text = self.Bedrock.Helpers.TruncateString(self.App.Author, self.Width - 6)\
- self:GetObject('ImageView').Image = self.App.Icon\
- end\
- end",
- [ "SearchPageView.lua" ] = "Inherit = 'PageView'\
- \
- OnLoad = function(self)\
- ScrollView.OnLoad(self)\
- \
- self:AddObject({\
- X = 1,\
- Y = '50%,-3',\
- Width = '100%',\
- Align = 'Center',\
- TextColour = 'grey',\
- Type = 'Label',\
- Text = 'Search'\
- })\
- \
- self:AddObject({\
- X = 1,\
- Y = '50%,-2',\
- Width = '100%',\
- Align = 'Center',\
- TextColour = 'lightGrey',\
- Type = 'Label',\
- Text = 'Find that app you\\'re looking for'\
- })\
- \
- self:AddObject({\
- X = '50%,-12',\
- Y = '50%',\
- Width = 21,\
- Type = 'TextBox',\
- Active = true,\
- Placeholder = 'Search...',\
- Name = 'SearchBox',\
- OnChange = function(_, event, keychar)\
- if keychar == keys.enter then\
- self:GetObject('SearchButton'):OnClick()\
- end\
- end\
- })\
- \
- self:AddObject({\
- X = '50%,10',\
- Y = '50%',\
- Type = 'Button',\
- BackgroundColour = 'blue',\
- TextColour = 'white',\
- Text = 'Go',\
- Name = 'SearchButton',\
- OnClick = function()\
- local text = self:GetObject('SearchBox').Text\
- \
- if text ~= '' then\
- self.Bedrock:OpenPage('SearchResultsPageView', {SearchTerm = text})\
- end\
- end\
- })\
- end",
- [ "PageView.lua" ] = "Inherit = 'ScrollView'\
- \
- PageInfo = nil\
- Failed = false\
- Success = false\
- RequestURL = nil\
- TimeoutTimer = nil\
- TimeoutLength = 5\
- LoadingText = nil\
- \
- OnLoad = function(self)\
- self.Failed = false\
- self.Success = false\
- self:RemoveAllObjects()\
- ScrollView.OnLoad(self)\
- self:AddObject({\
- X = '50%,-4',\
- Y = '50%,-3',\
- Type = 'LoadingIndicator',\
- })\
- self:FetchData()\
- end\
- \
- FetchData = function(self)\
- local url = self:DataURL(self.PageInfo)\
- self.RequestURL = url\
- local reason\
- \
- if not http then\
- reason = 'NOHTTP'\
- elseif http.checkURL and not http.checkURL(url) then\
- reason = 'BLOCKED'\
- end\
- \
- if not reason then\
- local ok = http.request(url)\
- if ok then\
- self.TimeoutTimer = self.Bedrock:StartTimer(function()\
- if not self.Failed and not self.Success then\
- self.Failed = true\
- self:OnDataFailed(url, 'TIMEOUT')\
- end\
- end, self.TimeoutLength)\
- else\
- reason = 'REQUEST'\
- end\
- end\
- \
- if reason then\
- self.Failed = true\
- self:OnDataFailed(url, reason)\
- end\
- end\
- \
- OnDataFailed = function(self, url, reason)\
- self:RemoveAllObjects()\
- self:AddObject({\
- X = 1,\
- Width = '100%',\
- Align = 'Center',\
- Y = '50%,-1',\
- Type = 'Label',\
- Text = 'Loading Failed '..reason,\
- TextColour = 'red'\
- })\
- \
- self:AddObject({\
- X = 1,\
- Y = '50%,1',\
- X = '50%,-7',\
- Type = 'Button',\
- TextColour = 'white',\
- BackgroundColour = 'red',\
- Text = 'Back',\
- OnClick = function()\
- self.Bedrock:OpenPreviousPage()\
- end\
- })\
- \
- self:AddObject({\
- X = 1,\
- Y = '50%,1',\
- X = '50%,1',\
- Type = 'Button',\
- TextColour = 'white',\
- BackgroundColour = 'red',\
- Text = 'Retry',\
- OnClick = function()\
- self:OnLoad()\
- end\
- })\
- end\
- \
- OnDataLoaded = function()\
- \
- end",
- [ "HomePageView.lua" ] = "Inherit = 'PageView'\
- \
- OnDataLoad = function(self, url, data)\
- self:RemoveAllObjects()\
- \
- local categories = textutils.unserialize(data)\
- \
- local function load(from)\
- local to = {}\
- for i, v in ipairs(from) do\
- local app = App:Initialise(v, self.Bedrock)\
- table.insert(to, app)\
- end\
- return to\
- end\
- \
- local topcharts = load(categories.topcharts)\
- \
- local newest = load(categories.newest)\
- \
- local featured = load(categories.featured)\
- \
- self:AddObject({\
- X = 1,\
- Y = 1,\
- Type = 'AppCollectionView',\
- Width = '100%',\
- Title = 'Most Popular Apps',\
- Height = 2 + math.ceil(#topcharts / 2) * 4,\
- Name = 'PopularAppCollectionView',\
- Items = topcharts\
- })\
- \
- self:AddObject({\
- X = 1,\
- Y = 4 + #topcharts * 2,\
- Type = 'AppCollectionView',\
- Width = '100%',\
- Title = 'Featured Apps',\
- Height = 2 + math.ceil(#featured / 2) * 4,\
- Name = 'FeaturedAppCollectionView',\
- Items = featured\
- })\
- \
- self:AddObject({\
- X = 1,\
- Y = 7 + #topcharts * 2 + #featured * 2,\
- Type = 'AppCollectionView',\
- Width = '100%',\
- Title = 'Most Recently Added Apps',\
- Height = 2 + math.ceil(#newest / 2) * 4,\
- Name = 'RecentAppCollectionView',\
- Items = newest\
- })\
- \
- self:UpdateScroll()\
- end\
- \
- DataURL = function(self, info)\
- return self.Bedrock.AppStoreURL .. 'api/?command=application&subcommand=home'\
- end",
- [ "CategoriesPageView.lua" ] = "Inherit = 'PageView'\
- \
- OnDataLoad = function(self, url, data)\
- self:RemoveAllObjects()\
- \
- local categories = textutils.unserialize(data)\
- \
- local function load(from)\
- local to = {}\
- for i, v in ipairs(from) do\
- local app = App:Initialise(v, self.Bedrock)\
- table.insert(to, app)\
- end\
- return to\
- end\
- \
- local y = 1\
- for category, programs in pairs(categories) do\
- local apps = load(programs)\
- \
- self:AddObject({\
- X = 1,\
- Y = y,\
- Type = 'AppCollectionView',\
- Width = '100%',\
- Title = 'Top ' .. category .. ' Programs',\
- Height = 2 + math.ceil(#apps / 2) * 4,\
- Name = category .. 'AppCollectionView',\
- Items = apps,\
- OnSeeMore = function()\
- self.Bedrock:OpenPage('CategoryPageView', {\
- CategoryName = category\
- })\
- end\
- })\
- \
- y = y + 4 + #apps * 2\
- end\
- \
- self:UpdateScroll()\
- end\
- \
- DataURL = function(self, info)\
- return self.Bedrock.AppStoreURL .. 'api/?command=application&subcommand=categories'\
- end",
- [ "AppCollectionView.lua" ] = "Inherit = 'View'\
- \
- Items = nil\
- Title = nil\
- \
- OnSeeMore = nil\
- \
- OnLoad = function(self)\
- self:OnUpdate('Items')\
- end\
- \
- OnUpdate = function(self, value)\
- if value == 'Items' then\
- self:RemoveAllObjects()\
- \
- self:AddObject({\
- X = 2, \
- Y = 2,\
- Type = 'Label',\
- Text = self.Title,\
- TextColour = colours.lightGrey\
- })\
- \
- if self.OnSeeMore then\
- self:AddObject({\
- X = 3 + #self.Title, \
- Y = 2,\
- Type = 'Label',\
- Text = 'See More >',\
- TextColour = colours.blue,\
- OnClick = self.OnSeeMore\
- })\
- end\
- \
- local xStart = 2 + math.floor((self.Width % AppView.Width) / 2)\
- local x = xStart\
- local y = 4\
- for i, app in ipairs(self.Items) do\
- self:AddObject({\
- X = x, \
- Y = y,\
- Type = 'AppView',\
- App = app\
- })\
- \
- x = x + AppView.Width\
- if x + AppView.Width > self.Width then\
- x = xStart\
- y = y + AppView.Height\
- end\
- end\
- end\
- end",
- [ "AppDetailsView.lua" ] = "Inherit = 'View'\
- \
- App = nil\
- \
- OnLoad = function(self)\
- self:AddObject({\
- X = 3,\
- Y = 2,\
- Width = 4,\
- Height = 3,\
- Type = 'ImageView',\
- })\
- \
- self:AddObject({\
- X = 8,\
- Y = 2,\
- Type = 'Label',\
- Name = 'NameLabel',\
- Text = ''\
- })\
- \
- self:AddObject({\
- X = 8,\
- Y = 3,\
- Type = 'Label',\
- Name = 'AuthorLabel',\
- Text = '',\
- TextColour = 'lightGrey'\
- })\
- \
- self:AddObject({\
- X = 8,\
- Y = 4,\
- Type = 'Label',\
- Name = 'CategoryLabel',\
- Text = '',\
- TextColour = 'grey'\
- })\
- \
- self:AddObject({\
- X = '100%,-10',\
- Y = 2,\
- Type = 'Button',\
- Name = 'InstallButton',\
- Text = 'Install',\
- TextColour = 'white',\
- BackgroundColour = 'blue',\
- -- Visible = false\
- })\
- \
- self:AddObject({\
- X = 3,\
- Y = 6,\
- Type = 'Label',\
- Text = 'Description',\
- TextColour = 'lightGrey'\
- })\
- \
- self:AddObject({\
- X = 3,\
- Y = 7,\
- Width = '100%,-4',\
- Type = 'Label',\
- Name = 'DescriptionLabel',\
- Text = 'No description',\
- TextColour = 'grey'\
- })\
- \
- self:AddObject({\
- X = 3,\
- Y = 6,\
- Type = 'Label',\
- Text = 'Description',\
- TextColour = 'lightGrey'\
- })\
- \
- \
- self:OnUpdate('App')\
- end\
- \
- OnUpdate = function(self, value)\
- if value == 'App' and self.App then\
- self:GetObject('NameLabel').Text = self.App.Name\
- self:GetObject('AuthorLabel').Text = self.App.Author\
- self:GetObject('CategoryLabel').Text = self.App.Category\
- self:GetObject('ImageView').Path = 'Resources/'..self.App.Name\
- -- self:GetObject('InstallButton').X = 10 + math.max(#self.App.Name, #self.App.Author, #self.App.Category)\
- \
- self:GetObject('DescriptionLabel').Text = self.App.Description\
- \
- end\
- end",
- [ "CategoryPageView.lua" ] = "Inherit = 'PageView'\
- \
- OnDataLoad = function(self, url, data)\
- self:RemoveAllObjects()\
- \
- local programs = textutils.unserialize(data)\
- \
- local function load(from)\
- local to = {}\
- for i, v in ipairs(from) do\
- local app = App:Initialise(v, self.Bedrock)\
- table.insert(to, app)\
- end\
- return to\
- end\
- \
- local apps = load(programs)\
- \
- self:AddObject({\
- X = 1,\
- Y = 1,\
- Type = 'AppCollectionView',\
- Width = '100%',\
- Title = 'All ' .. self.CategoryName .. ' Programs',\
- Height = 2 + math.ceil(#apps / 2) * 4,\
- Name = self.CategoryName .. 'AppCollectionView',\
- Items = apps\
- })\
- \
- self:UpdateScroll()\
- end\
- \
- DataURL = function(self, info)\
- return self.Bedrock.AppStoreURL .. 'api/?command=application&subcommand=category&name=' .. textutils.urlEncode(self.CategoryName)\
- end",
- [ "SearchResultsPageView.lua" ] = "Inherit = 'PageView'\
- \
- OnDataLoad = function(self, url, data)\
- self:RemoveAllObjects()\
- \
- local _data = textutils.unserialize(data)\
- \
- local function load(from)\
- local to = {}\
- for i, v in ipairs(from) do\
- local app = App:Initialise(v, self.Bedrock)\
- table.insert(to, app)\
- end\
- return to\
- end\
- \
- local results = load(_data)\
- \
- self:AddObject({\
- X = 1,\
- Y = 1,\
- Type = 'AppCollectionView',\
- Width = '100%',\
- Title = 'Search Results For: ' .. self.SearchTerm,\
- Height = 2 + math.ceil(#results / 2) * 4,\
- Name = 'SearchResultsCollectionView',\
- Items = results\
- })\
- \
- if #results == 0 then\
- self:AddObject({\
- X = 1,\
- Y = '50%',\
- Width = '100%',\
- Align = 'Center',\
- Type = 'Label',\
- TextColour = 'grey',\
- Text = 'No apps found'\
- })\
- end\
- \
- self:UpdateScroll()\
- end\
- \
- DataURL = function(self, info)\
- return self.Bedrock.AppStoreURL .. 'api/?command=application&subcommand=search&name=' .. textutils.urlEncode(self.SearchTerm)\
- end",
- },
- }
- local function makeFile(_path,_content)
- local file=fs.open(_path,"w")
- file.write(_content)
- file.close()
- end
- local function makeFolder(_path,_content)
- fs.makeDir(_path)
- for k,v in pairs(_content) do
- if type(v)=="table" then
- makeFolder(_path.."/"..k,v)
- else
- makeFile(_path.."/"..k,v)
- end
- end
- end
- local sDest= installLocation or '/'
- if sDest=="root" then
- sDest="/"
- end
- local tPackage=pkg
- makeFolder(sDest,tPackage)
- print("Installed Stand Alone CCAppStore by oeed, installer by CodedPixelCube/minimite. Run 'appstore' to boot up CCAppStore")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement