diff --git a/sys/apis/class.lua b/sys/apis/class.lua index ced9020..4b5ed06 100644 --- a/sys/apis/class.lua +++ b/sys/apis/class.lua @@ -1,6 +1,8 @@ -- From http://lua-users.org/wiki/SimpleLuaClasses -- (with some modifications) +local uid = 1 + -- class.lua -- Compatible with Lua 5.1 (not 5.0). return function(base) @@ -19,7 +21,8 @@ return function(base) -- expose a constructor which can be called by () setmetatable(c, { __call = function(class_tbl, ...) - local obj = {} + local obj = { __uid = uid } + uid = uid + 1 setmetatable(obj,c) if class_tbl.init then class_tbl.init(obj, ...) diff --git a/sys/apis/injector.lua b/sys/apis/injector.lua index 7e3f847..12c92ad 100644 --- a/sys/apis/injector.lua +++ b/sys/apis/injector.lua @@ -21,16 +21,13 @@ if not http._patched then else syncLocks[key] = { } end - local s, m = pcall(fn) + fn() local co = table.remove(syncLocks[key], 1) if co then os.queueEvent('sync_lock', co) else syncLocks[key] = nil end - if not s then - error(m) - end end -- todo -- completely replace http.get with function that diff --git a/sys/apis/ui.lua b/sys/apis/ui.lua index 650a2fb..b468d0f 100644 --- a/sys/apis/ui.lua +++ b/sys/apis/ui.lua @@ -9,6 +9,13 @@ local _sub = string.sub local colors = _G.colors local keys = _G.keys +--[[ + Using the shorthand window definition, elements are created from + the bottom up. Once reaching the top, setParent is called top down. + + On :init(), elements do not know the parent or can calculate sizing. +]] + local function safeValue(v) local t = type(v) if t == 'string' or t == 'number' then @@ -526,7 +533,6 @@ UI.Window.defaults = { function UI.Window:init(args) local defaults = UI:getDefaults(UI.Window, args) UI:setProperties(self, defaults) - if self.parent then self:setParent() end @@ -2024,6 +2030,7 @@ UI.MenuBar.defaults = { backgroundColor = colors.lightGray, textColor = colors.black, spacing = 2, + lastx = 1, showBackButton = false, buttonClass = 'MenuItem', } @@ -2031,23 +2038,40 @@ UI.MenuBar.spacer = { spacer = true, text = 'spacer', inactive = true } function UI.MenuBar:init(args) local defaults = UI:getDefaults(UI.MenuBar, args) - UI:setProperties(self, defaults) + UI.Window.init(self, defaults) if not self.children then self.children = { } end - local x = 1 - for _,button in pairs(self.buttons) do + self:addButtons(self.buttons) + if self.showBackButton then + table.insert(self.children, UI.MenuItem({ + x = UI.term.width - 2, + width = 3, + backgroundColor = self.backgroundColor, + textColor = self.textColor, + text = '^-', + event = 'back', + })) + end +end + +function UI.MenuBar:addButtons(buttons) + if not self.children then + self.children = { } + end + + for _,button in pairs(buttons) do if button.UIElement then table.insert(self.children, button) else local buttonProperties = { - x = x, + x = self.lastx, width = #button.text + self.spacing, centered = false, } - x = x + buttonProperties.width + self.lastx = self.lastx + buttonProperties.width UI:setProperties(buttonProperties, button) button = UI[self.buttonClass](buttonProperties) @@ -2059,21 +2083,10 @@ function UI.MenuBar:init(args) if button.dropdown then button.dropmenu = UI.DropMenu { buttons = button.dropdown } - --table.insert(self.children, buttonProperties.dropmenu) end end end - if self.showBackButton then - table.insert(self.children, UI.MenuItem({ - x = UI.term.width - 2, - width = 3, - backgroundColor = self.backgroundColor, - textColor = self.textColor, - text = '^-', - event = 'back', - })) - end - UI.Window.init(self, defaults) + self:initChildren() end function UI.MenuBar:getActive(menuItem) @@ -2238,42 +2251,44 @@ UI.Tabs.defaults = { } function UI.Tabs:init(args) local defaults = UI:getDefaults(UI.Tabs, args) + UI.Window.init(self, defaults) + + self:add(self) +end + +function UI.Tabs:add(children) local buttons = { } - for _,child in pairs(defaults) do + for _,child in pairs(children) do if type(child) == 'table' and child.UIElement then + child.y = 2 table.insert(buttons, { - text = child.tabTitle or '', event = 'tab_select', + text = child.tabTitle or '', + event = 'tab_select', + tabUid = child.__uid, }) end end - self.tabBar = UI.TabBar({ - buttons = buttons, - }) + if not self.tabBar then + self.tabBar = UI.TabBar({ + buttons = buttons, + }) + else + self.tabBar:addButtons(buttons) + end - UI.Window.init(self, defaults) -end - -function UI.Tabs:setParent() - UI.Window.setParent(self) - - for _,child in pairs(self.children) do - if child ~= self.tabBar then - child.oy = 2 - --child.height = self.height - 1 - child:resize() - end + if self.parent then + return UI.Window.add(self, children) end end function UI.Tabs:enable() self.enabled = true - for _,child in ipairs(self.children) do - if child.tabTitle == self.tabBar.buttons[1].text then - self:activateTab(child) - break - end + + local _, menuItem = Util.first(self.tabBar.children, function(a, b) return a.x < b.x end) + if menuItem then + self:activateTab(Util.find(self.children, '__uid', menuItem.tabUid)) end self.tabBar:enable() end @@ -2292,11 +2307,9 @@ end function UI.Tabs:eventHandler(event) if event.type == 'tab_select' then - for _,child in ipairs(self.children) do - if child.tabTitle == event.button.text then - self:activateTab(child) - break - end + local child = Util.find(self.children, '__uid', event.button.tabUid) + if child then + self:activateTab(child) end elseif event.type == 'tab_change' then for _,tab in ipairs(self.children) do diff --git a/sys/apps/System.lua b/sys/apps/System.lua index 33a48eb..b21826c 100644 --- a/sys/apps/System.lua +++ b/sys/apps/System.lua @@ -7,6 +7,7 @@ local Util = require('util') local fs = _G.fs local multishell = _ENV.multishell local os = _G.os +local settings = _G.settings local shell = _ENV.shell multishell.setTitle(multishell.getCurrent(), 'System') @@ -57,7 +58,6 @@ local systemPage = UI.Page { }, grid = UI.Grid { y = 5, - autospace = true, sortColumn = 'alias', columns = { { heading = 'Alias', key = 'alias' }, @@ -108,6 +108,43 @@ local systemPage = UI.Page { }, } +if settings then + local values = { } + for _,v in pairs(settings.getNames()) do + table.insert(values, { + name = v, + value = not not settings.get(v), + }) + end + + systemPage.tabs:add({ + systemTab = UI.Window { + tabTitle = 'Settings', + grid = UI.Grid { + y = 1, + values = values, + --autospace = true, + sortColumn = 'name', + columns = { + { heading = 'Setting', key = 'name' }, + { heading = 'Value', key = 'value' }, + }, + accelerators = { + }, + }, + } + }) + function systemPage.tabs.systemTab:eventHandler(event) + if event.type == 'grid_select' then + event.selected.value = not event.selected.value + settings.set(event.selected.name, event.selected.value) + settings.save('.settings') + self.grid:draw() + return true + end + end +end + function systemPage.tabs.pathTab.grid:draw() self.values = { } for _,v in ipairs(Util.split(env.path, '(.-):')) do