diff --git a/sys/apps/Tasks.lua b/sys/apps/Tasks.lua index f67d71b..3dbd395 100644 --- a/sys/apps/Tasks.lua +++ b/sys/apps/Tasks.lua @@ -24,40 +24,38 @@ local page = UI.Page { values = kernel.routines, sortColumn = 'uid', autospace = true, + getDisplayValues = function(_, row) + local elapsed = os.clock()-row.timestamp + return { + uid = row.uid, + title = row.title, + status = row.isDead and 'error' or coroutine.status(row.co), + timestamp = elapsed < 60 and + string.format("%ds", math.floor(elapsed)) or + string.format("%sm", math.floor(elapsed/6)/10), + } + end }, accelerators = { [ 'control-q' ] = 'quit', space = 'activate', t = 'terminate', }, -} - -function page:eventHandler(event) - local t = self.grid:getSelected() - if t then - if event.type == 'activate' or event.type == 'grid_select' then - multishell.setFocus(t.uid) - elseif event.type == 'terminate' then - multishell.terminate(t.uid) + eventHandler = function (self, event) + local t = self.grid:getSelected() + if t then + if event.type == 'activate' or event.type == 'grid_select' then + multishell.setFocus(t.uid) + elseif event.type == 'terminate' then + multishell.terminate(t.uid) + end end + if event.type == 'quit' then + Event.exitPullEvents() + end + UI.Page.eventHandler(self, event) end - if event.type == 'quit' then - Event.exitPullEvents() - end - UI.Page.eventHandler(self, event) -end - -function page.grid:getDisplayValues(row) - local elapsed = os.clock()-row.timestamp - return { - uid = row.uid, - title = row.title, - status = row.isDead and 'error' or coroutine.status(row.co), - timestamp = elapsed < 60 and - string.format("%ds", math.floor(elapsed)) or - string.format("%sm", math.floor(elapsed/6)/10), - } -end +} Event.onInterval(1, function() page.grid:update() diff --git a/sys/apps/inspect.lua b/sys/apps/inspect.lua index 48feeb4..6cc4048 100644 --- a/sys/apps/inspect.lua +++ b/sys/apps/inspect.lua @@ -63,6 +63,7 @@ page = UI.Page { }, }, methodsTab = UI.Tab { + index = 2, tabTitle = 'Methods', grid = UI.ScrollingGrid { headerBackgroundColor = colors.red, @@ -73,11 +74,12 @@ page = UI.Page { }, }, events = UI.Tab { + index = 1, tabTitle = 'Events', UI.MenuBar { y = -1, buttons = { - { text = 'Clear', event = 'event_clear' }, + { text = 'Clear' }, } }, grid = UI.ScrollingGrid { @@ -89,10 +91,21 @@ page = UI.Page { { heading = 'type', key = 'type' }, { heading = 'value', key = 'value', } }, - accelerators = { - grid_select = 'event_inspect', - }, - } + }, + eventHandler = function (self, event) + if event.type == 'button_press' then + Util.clear(self.grid.values) + self.grid:update() + self.grid:draw() + + elseif event.type == 'grid_select' then + multishell.openTab({ + path = 'sys/apps/Lua.lua', + args = { event.selected.raw }, + focused = true, + }) + end + end } }, editor = UI.SlideOut { @@ -134,18 +147,6 @@ page = UI.Page { self.tabs.methodsTab.grid:update() self.tabs.methodsTab.grid:draw() - elseif event.type == 'event_clear' then - Util.clear(self.tabs.events.grid.values) - self.tabs.events.grid:update() - self.tabs.events.grid:draw() - - elseif event.type == 'event_inspect' then - multishell.openTab({ - path = 'sys/apps/Lua.lua', - args = { event.selected.raw }, - focused = true, - }) - elseif event.type == 'edit_property' then self.editor.entry.value = event.selected.value self.editor:show() diff --git a/sys/autorun/complete.lua b/sys/autorun/complete.lua index 31a6bd9..584fd97 100644 --- a/sys/autorun/complete.lua +++ b/sys/autorun/complete.lua @@ -1,3 +1,5 @@ +local fs = _G.fs + local function completeMultipleChoice(sText, tOptions, bAddSpaces) local tResults = { } for n = 1,#tOptions do @@ -20,3 +22,14 @@ _ENV.shell.setCompletionFunction("sys/apps/package.lua", return completeMultipleChoice(text, { "install ", "update ", "uninstall ", "updateall ", "refresh" }) end end) + +_ENV.shell.setCompletionFunction("sys/apps/inspect.lua", + function(_, index, text) + if index == 1 then + local components = { } + for _, f in pairs(fs.list('sys/modules/opus/ui/components')) do + table.insert(components, (f:gsub("%.lua$", ""))) + end + return completeMultipleChoice(text, components) + end + end) diff --git a/sys/modules/opus/ui/canvas.lua b/sys/modules/opus/ui/canvas.lua index 75e1792..d0d4ee9 100644 --- a/sys/modules/opus/ui/canvas.lua +++ b/sys/modules/opus/ui/canvas.lua @@ -353,6 +353,12 @@ function Canvas:__renderLayers(device, offset) end function Canvas:__blitClipped(device, offset) + if self.parent then + -- contain the rendered region in the parent's region + local p = Region.new(1, 1, self.parent.width, self.parent.height) + self.regions:andRegion(p) + end + for _,region in ipairs(self.regions.region) do self:__blitRect(device, { x = region[1] - offset.x, diff --git a/sys/modules/opus/ui/components/Form.lua b/sys/modules/opus/ui/components/Form.lua index 69cb7ca..bda9850 100644 --- a/sys/modules/opus/ui/components/Form.lua +++ b/sys/modules/opus/ui/components/Form.lua @@ -139,7 +139,7 @@ function UI.Form.example() return UI.Form { x = 2, ex = -2, y = 2, ptype = UI.Chooser { - formLabel = 'Type', formKey = 'type', + formLabel = 'Type', formKey = 'type', formIndex = 1, width = 10, choices = { { name = 'Modem', value = 'wireless_modem' }, @@ -147,7 +147,7 @@ function UI.Form.example() }, }, drive_id = UI.TextEntry { - formLabel = 'Drive', formKey = 'drive_id', + formLabel = 'Drive', formKey = 'drive_id', formIndex = 2, required = true, width = 5, transform = 'number', diff --git a/sys/modules/opus/ui/components/Menu.lua b/sys/modules/opus/ui/components/Menu.lua index e31e8df..8f1c837 100644 --- a/sys/modules/opus/ui/components/Menu.lua +++ b/sys/modules/opus/ui/components/Menu.lua @@ -59,3 +59,14 @@ function UI.Menu:eventHandler(event) end return UI.Grid.eventHandler(self, event) end + +function UI.Menu.example() + return UI.Menu { + x = 2, y = 2, height = 3, + menuItems = { + { prompt = 'Start', event = 'start' }, + { prompt = 'Continue', event = 'continue' }, + { prompt = 'Quit', event = 'quit' } + } + } +end diff --git a/sys/modules/opus/ui/components/MenuBar.lua b/sys/modules/opus/ui/components/MenuBar.lua index 85f435b..217fccd 100644 --- a/sys/modules/opus/ui/components/MenuBar.lua +++ b/sys/modules/opus/ui/components/MenuBar.lua @@ -34,6 +34,15 @@ function UI.MenuBar:addButtons(buttons) self.children = { } end + for _,button in pairs(buttons) do + if button.index then -- don't sort unless needed + table.sort(buttons, function(a, b) + return (a.index or 999) < (b.index or 999) + end) + break + end + end + for _,button in pairs(buttons) do if button.UIElement then table.insert(self.children, button) diff --git a/sys/modules/opus/ui/components/ProgressBar.lua b/sys/modules/opus/ui/components/ProgressBar.lua index af12708..a066952 100644 --- a/sys/modules/opus/ui/components/ProgressBar.lua +++ b/sys/modules/opus/ui/components/ProgressBar.lua @@ -26,3 +26,19 @@ function UI.ProgressBar:draw() self:write(1, i, progress, self.progressColor) end end + +function UI.ProgressBar.example() + local Event = require('opus.event') + return UI.ProgressBar { + x = 2, ex = -2, y = 2, + focus = function() end, + enable = function(self) + Event.onInterval(.25, function() + self.value = self.value == 100 and 0 or self.value + 5 + self:draw() + self:sync() + end) + return UI.ProgressBar.enable(self) + end + } +end diff --git a/sys/modules/opus/ui/components/SlideOut.lua b/sys/modules/opus/ui/components/SlideOut.lua index c5779dd..1e9558f 100644 --- a/sys/modules/opus/ui/components/SlideOut.lua +++ b/sys/modules/opus/ui/components/SlideOut.lua @@ -19,6 +19,14 @@ end function UI.SlideOut:enable() end +function UI.SlideOut:toggle() + if self.enabled then + self:hide() + else + self:show() + end +end + function UI.SlideOut:show(...) self:addTransition('expandUp') self.canvas:raise() @@ -52,7 +60,9 @@ function UI.SlideOut:eventHandler(event) end function UI.SlideOut.example() - return UI.Window { + -- for the transistion to work properly, the parent must have a canvas + return UI.ActiveLayer { + backgroundColor = colors.cyan, button = UI.Button { x = 2, y = 2, text = 'show', @@ -67,11 +77,8 @@ function UI.SlideOut.example() }, eventHandler = function (self, event) if event.type == 'button_press' then - if self.slideOut.enabled then - self.slideOut:hide() - else - self.slideOut:show() - end + self.slideOut.canvas.xxx = true + self.slideOut:toggle() end end, } diff --git a/sys/modules/opus/ui/components/Tabs.lua b/sys/modules/opus/ui/components/Tabs.lua index a27bcbb..c9c0075 100644 --- a/sys/modules/opus/ui/components/Tabs.lua +++ b/sys/modules/opus/ui/components/Tabs.lua @@ -16,6 +16,7 @@ function UI.Tabs:add(children) if type(child) == 'table' and child.UIElement and child.tabTitle then child.y = 2 table.insert(buttons, { + index = child.index, text = child.tabTitle, event = 'tab_select', tabUid = child.uid, @@ -32,7 +33,7 @@ function UI.Tabs:add(children) end if self.parent then - return UI.Window.add(self, children) + UI.Window.add(self, children) end end @@ -57,7 +58,7 @@ function UI.Tabs:enable() local menuItem = Util.find(self.tabBar.children, 'selected', true) - for _,child in pairs(self.children) do + for _,child in pairs(self.children or { }) do if child.uid == menuItem.tabUid then child:enable() self:emit({ type = 'tab_activate', activated = child }) @@ -90,16 +91,19 @@ end function UI.Tabs.example() return UI.Tabs { - [1] = UI.Tab { + tab1 = UI.Tab { + index = 1, tabTitle = 'tab1', entry = UI.TextEntry { y = 3, shadowText = 'text' }, }, - [2] = UI.Tab { + tab2 = UI.Tab { + index = 2, tabTitle = 'tab2', button = UI.Button { y = 3 }, }, - [3] = UI.Tab { + tab3 = UI.Tab { + index = 3, tabTitle = 'tab3', - } + }, } end diff --git a/sys/modules/opus/ui/components/VerticalMeter.lua b/sys/modules/opus/ui/components/VerticalMeter.lua index 012d0e5..051d740 100644 --- a/sys/modules/opus/ui/components/VerticalMeter.lua +++ b/sys/modules/opus/ui/components/VerticalMeter.lua @@ -16,3 +16,19 @@ function UI.VerticalMeter:draw() self:clear() self:clearArea(1, height + 1, self.width, self.height, self.meterColor) end + +function UI.VerticalMeter.example() + local Event = require('opus.event') + return UI.VerticalMeter { + x = 2, width = 3, y = 2, ey = -2, + focus = function() end, + enable = function(self) + Event.onInterval(.25, function() + self.value = self.value == 100 and 0 or self.value + 5 + self:draw() + self:sync() + end) + return UI.VerticalMeter.enable(self) + end + } +end \ No newline at end of file