From f21ff42e44d2ea7bb260c153b8d5f6887bf82997 Mon Sep 17 00:00:00 2001 From: kepler155c Date: Sun, 30 Dec 2018 13:53:20 -0500 Subject: [PATCH 01/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b78a99..3a2d070 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,6 @@ ## Install ``` -pastebin run sj4VMVJj +pastebin run uzghlbnc reboot ``` -- 2.49.1 From 16843bdb78c3b7259acd4c812ae057260cf09016 Mon Sep 17 00:00:00 2001 From: kepler155c Date: Fri, 18 Jan 2019 14:25:44 -0500 Subject: [PATCH 02/23] Update git.lua --- sys/apis/git.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/apis/git.lua b/sys/apis/git.lua index 77c398c..02fa103 100644 --- a/sys/apis/git.lua +++ b/sys/apis/git.lua @@ -8,6 +8,10 @@ local TREE_URL = 'https://api.github.com/repos/%s/%s/git/trees/%s?recursive=1' local FILE_URL = 'https://raw.githubusercontent.com/%s/%s/%s/%s' local git = { } +if _G._GIT_API_KEY then + TREE_URL = TREE_URL .. '&access_token=' .. _G._GIT_API_KEY +end + local fs = _G.fs local os = _G.os -- 2.49.1 From cef5b21921705736249428274d12062b982c0bbc Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Sun, 10 Nov 2019 18:52:28 -0700 Subject: [PATCH 03/23] update to master --- sys/boot/opus.boot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/boot/opus.boot b/sys/boot/opus.boot index 2a02d14..1ed1de8 100644 --- a/sys/boot/opus.boot +++ b/sys/boot/opus.boot @@ -19,7 +19,7 @@ local function run(file, ...) end _G._syslog = function() end -_G.OPUS_BRANCH = 'develop-1.8' +_G.OPUS_BRANCH = 'master' -- Install require shim _G.requireInjector = run('sys/modules/opus/injector.lua') -- 2.49.1 From 25405f15c8d60bc9d6ae66ee580c6efb829719ae Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Tue, 12 Nov 2019 21:13:17 -0700 Subject: [PATCH 04/23] UI inspector --- sys/apps/inspect.lua | 154 ++++++++++++++++++ sys/modules/opus/ui/components/Button.lua | 20 +++ .../opus/ui/components/CheckboxGrid.lua | 54 ++++++ sys/modules/opus/ui/components/Tabs.lua | 16 ++ sys/modules/opus/ui/components/TextArea.lua | 6 + sys/modules/opus/ui/components/TextEntry.lua | 32 ++++ 6 files changed, 282 insertions(+) create mode 100644 sys/apps/inspect.lua create mode 100644 sys/modules/opus/ui/components/CheckboxGrid.lua diff --git a/sys/apps/inspect.lua b/sys/apps/inspect.lua new file mode 100644 index 0000000..1824fde --- /dev/null +++ b/sys/apps/inspect.lua @@ -0,0 +1,154 @@ +local Event = require('opus.event') +local UI = require('opus.ui') + +local colors = _G.colors +local multishell = _ENV.multishell + +local args = { ... } +local name = args[1] or error('Syntax: inspect COMPONENT') +local events = { } +local page + +local function isRelevant(el) + return page.testContainer == el or el.parent and isRelevant(el.parent) +end + +local emitter = UI.Window.emit +function UI.Window:emit(event) + if not event.recorded and isRelevant(self) then + event.recorded = true + local t = { } + for k,v in pairs(event) do + if k ~= 'type' and k ~= 'recorded' then + table.insert(t, k .. ':' .. (type(v) == 'table' and (v.UIElement and v.uid or 'tbl') or tostring(v))) + end + end + table.insert(events, 1, { type = event.type, value = table.concat(t, ' '), raw = event }) + while #events > 10 do + table.remove(events) + end + end + return emitter(self, event) +end + +page = UI.Page { + testContainer = UI.Window { + ey = 10, + }, + tabs = UI.Tabs { + y = 11, + properties = UI.Tab { + backgroundColor = colors.red, + tabTitle = 'Properties', + grid = UI.ScrollingGrid { + headerBackgroundColor = colors.red, + sortColumn = 'key', + columns = { + { heading = 'key', key = 'key' }, + { heading = 'value', key = 'value', } + }, + accelerators = { + grid_select = 'edit_property', + }, + }, + }, + methodsTab = UI.Tab { + backgroundColor = colors.red, + tabTitle = 'Methods', + grid = UI.ScrollingGrid { + headerBackgroundColor = colors.red, + sortColumn = 'key', + columns = { + { heading = 'key', key = 'key' }, + }, + }, + }, + events = UI.Tab { + backgroundColor = colors.red, + tabTitle = 'Events', + grid = UI.ScrollingGrid { + headerBackgroundColor = colors.red, + values = events, + autospace = true, + columns = { + { heading = 'type', key = 'type' }, + { heading = 'value', key = 'value', } + }, + } + } + }, + editor = UI.SlideOut { + y = -4, height = 4, + backgroundColor = colors.green, + titleBar = UI.TitleBar { + event = 'editor_cancel', + title = 'Enter value', + }, + entry = UI.TextEntry { + y = 3, x = 2, ex = 10, + accelerators = { + enter = 'editor_apply', + }, + }, + }, + eventHandler = function (self, event) + if event.type == 'focus_change' and isRelevant(event.focused) then + local t = { } + for k,v in pairs(event.focused) do + table.insert(t, { + key = k, + value = tostring(v), + }) + end + self.tabs.properties.grid:setValues(t) + self.tabs.properties.grid:update() + self.tabs.properties.grid:draw() + + t = { } + for k,v in pairs(getmetatable(event.focused)) do + if type(v) == 'function' then + table.insert(t, { + key = k, + }) + end + end + self.tabs.methodsTab.grid:setValues(t) + self.tabs.methodsTab.grid:update() + self.tabs.methodsTab.grid:draw() + + elseif event.type == 'grid_select' and event.element == self.tabs.events.grid then + event.selected.raw.recorded = nil + multishell.openTab({ + path = 'sys/apps/Lua.lua', + args = { event.selected.raw }, + focused = true, + }) + + elseif event.type == 'grid_select' and event.element == self.tabs.properties.grid then + self.editor.entry.value = event.selected.value + self.editor:show() + + elseif event.type == 'editor_cancel' then + self.editor:hide() + + elseif event.type == 'editor_apply' then + self.editor:hide() + end + + return UI.Page.eventHandler(self, event) + end +} + +Event.onInterval(1, function() + page.tabs.events.grid:update() + page.tabs.events.grid:draw() + page.tabs.events.grid:sync() +end) + +local component = UI[name]() +local testing = component.example() + +page.testContainer:add({ test = testing }) + +UI:setPage(page) +UI:pullEvents() diff --git a/sys/modules/opus/ui/components/Button.lua b/sys/modules/opus/ui/components/Button.lua index c6ea3bf..2442614 100644 --- a/sys/modules/opus/ui/components/Button.lua +++ b/sys/modules/opus/ui/components/Button.lua @@ -64,3 +64,23 @@ function UI.Button:eventHandler(event) end return false end + +function UI.Button.example() + return UI.Window { + button1 = UI.Button { + x = 2, y = 2, + text = 'Press', + }, + button2 = UI.Button { + x = 2, y = 4, + backgroundColor = colors.green, + event = 'custom_event', + }, + button3 = UI.Button { + x = 12, y = 2, + height = 5, + event = 'big_event', + text = 'large button' + } + } +end diff --git a/sys/modules/opus/ui/components/CheckboxGrid.lua b/sys/modules/opus/ui/components/CheckboxGrid.lua new file mode 100644 index 0000000..c57c098 --- /dev/null +++ b/sys/modules/opus/ui/components/CheckboxGrid.lua @@ -0,0 +1,54 @@ +local class = require('opus.class') +local UI = require('opus.ui') + +local function safeValue(v) + local t = type(v) + if t == 'string' or t == 'number' then + return v + end + return tostring(v) +end + +UI.CheckboxGrid = class(UI.Grid) +UI.CheckboxGrid.defaults = { + UIElement = 'CheckboxGrid', + checkedKey = 'checked', + accelerators = { + space = 'grid_toggle', + }, +} +function UI.CheckboxGrid:drawRow(sb, row, focused, bg, fg) + local ind = focused and self.focusIndicator or ' ' + + for _,col in pairs(self.columns) do + sb:write(ind .. safeValue(row[col.key] or ''), + col.cw + 1, + col.align, + col.backgroundColor or bg, + col.textColor or fg) + ind = ' ' + end +end + +function UI.CheckboxGrid:eventHandler(event) + if event.type == 'key_enter' and self.selected then + self.selected.checked = not self.selected.checked + self:draw() + self:emit({ type = 'grid_check', checked = self.selected, element = self }) + else + return UI.Grid.eventHandler(self, event) + end +end + +function UI.CheckboxGrid.example() + return UI.CheckboxGrid { + values = { + { checked = false, name = 'unchecked' }, + { checked = true, name = 'checked' }, + }, + columns = { + { heading = 'Checked', key = 'checked' }, + { heading = 'Data', key = 'name', } + }, + } +end diff --git a/sys/modules/opus/ui/components/Tabs.lua b/sys/modules/opus/ui/components/Tabs.lua index 46f87d1..a27bcbb 100644 --- a/sys/modules/opus/ui/components/Tabs.lua +++ b/sys/modules/opus/ui/components/Tabs.lua @@ -87,3 +87,19 @@ function UI.Tabs:eventHandler(event) tab:draw() end end + +function UI.Tabs.example() + return UI.Tabs { + [1] = UI.Tab { + tabTitle = 'tab1', + entry = UI.TextEntry { y = 3, shadowText = 'text' }, + }, + [2] = UI.Tab { + tabTitle = 'tab2', + button = UI.Button { y = 3 }, + }, + [3] = UI.Tab { + tabTitle = 'tab3', + } + } +end diff --git a/sys/modules/opus/ui/components/TextArea.lua b/sys/modules/opus/ui/components/TextArea.lua index 51b8972..ea7540f 100644 --- a/sys/modules/opus/ui/components/TextArea.lua +++ b/sys/modules/opus/ui/components/TextArea.lua @@ -34,3 +34,9 @@ function UI.TextArea:draw() end end end + +function UI.TextArea.example() + return UI.TextArea { + value = 'sample text\nabc' + } +end \ No newline at end of file diff --git a/sys/modules/opus/ui/components/TextEntry.lua b/sys/modules/opus/ui/components/TextEntry.lua index dda3766..ea507c8 100644 --- a/sys/modules/opus/ui/components/TextEntry.lua +++ b/sys/modules/opus/ui/components/TextEntry.lua @@ -134,3 +134,35 @@ function UI.TextEntry:eventHandler(event) return false end + +function UI.TextEntry.example() + return UI.Window { + text = UI.TextEntry { + x = 2, y = 2, + width = 12, + limit = 36, + shadowText = 'normal', + }, + upper = UI.TextEntry { + x = 2, y = 3, + width = 12, + limit = 36, + shadowText = 'upper', + transform = 'uppercase', + }, + lower = UI.TextEntry { + x = 2, y = 4, + width = 12, + limit = 36, + shadowText = 'lower', + transform = 'lowercase', + }, + number = UI.TextEntry { + x = 2, y = 5, + width = 12, + limit = 36, + transform = 'number', + shadowText = 'number', + }, + } +end -- 2.49.1 From 053003f429e35978d53ed562f1d426c255d93e5b Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Tue, 12 Nov 2019 23:04:31 -0700 Subject: [PATCH 05/23] inspect cleanup --- sys/apps/inspect.lua | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/sys/apps/inspect.lua b/sys/apps/inspect.lua index 1824fde..ce41738 100644 --- a/sys/apps/inspect.lua +++ b/sys/apps/inspect.lua @@ -1,13 +1,16 @@ -local Event = require('opus.event') -local UI = require('opus.ui') +local UI = require('opus.ui') local colors = _G.colors local multishell = _ENV.multishell -local args = { ... } -local name = args[1] or error('Syntax: inspect COMPONENT') +local name = ({ ... })[1] or error('Syntax: inspect COMPONENT') local events = { } local page +local component = UI[name] and UI[name]() or error('Invalid component') + +if not component.example then + error('No example present') +end local function isRelevant(el) return page.testContainer == el or el.parent and isRelevant(el.parent) @@ -27,6 +30,10 @@ function UI.Window:emit(event) while #events > 10 do table.remove(events) end + page.tabs.events.grid:update() + if page.tabs.events.enabled then + page.tabs.events.grid:draw() + end end return emitter(self, event) end @@ -34,11 +41,11 @@ end page = UI.Page { testContainer = UI.Window { ey = 10, + testing = component.example(), }, tabs = UI.Tabs { y = 11, properties = UI.Tab { - backgroundColor = colors.red, tabTitle = 'Properties', grid = UI.ScrollingGrid { headerBackgroundColor = colors.red, @@ -53,7 +60,6 @@ page = UI.Page { }, }, methodsTab = UI.Tab { - backgroundColor = colors.red, tabTitle = 'Methods', grid = UI.ScrollingGrid { headerBackgroundColor = colors.red, @@ -64,7 +70,6 @@ page = UI.Page { }, }, events = UI.Tab { - backgroundColor = colors.red, tabTitle = 'Events', grid = UI.ScrollingGrid { headerBackgroundColor = colors.red, @@ -139,16 +144,5 @@ page = UI.Page { end } -Event.onInterval(1, function() - page.tabs.events.grid:update() - page.tabs.events.grid:draw() - page.tabs.events.grid:sync() -end) - -local component = UI[name]() -local testing = component.example() - -page.testContainer:add({ test = testing }) - UI:setPage(page) UI:pullEvents() -- 2.49.1 From 65c6ebf7114f6790f56922e92d7c540ab2676e75 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Wed, 13 Nov 2019 14:24:43 -0700 Subject: [PATCH 06/23] properly handle empty text entry fields (including transformations) --- sys/apps/Help.lua | 2 +- sys/apps/Lua.lua | 9 ++- sys/apps/Welcome.lua | 4 +- sys/apps/inspect.lua | 17 ++-- sys/apps/system/label.lua | 2 +- sys/apps/system/path.lua | 2 +- sys/modules/opus/entry.lua | 81 ++++++++++++-------- sys/modules/opus/ui/components/Form.lua | 18 +---- sys/modules/opus/ui/components/Grid.lua | 40 ++++++++++ sys/modules/opus/ui/components/TextEntry.lua | 39 ++++------ 10 files changed, 131 insertions(+), 83 deletions(-) diff --git a/sys/apps/Help.lua b/sys/apps/Help.lua index ffd0486..8bae671 100644 --- a/sys/apps/Help.lua +++ b/sys/apps/Help.lua @@ -81,7 +81,7 @@ function page:eventHandler(event) end elseif event.type == 'text_change' then - if #event.text == 0 then + if not event.text then self.grid.values = topics else self.grid.values = { } diff --git a/sys/apps/Lua.lua b/sys/apps/Lua.lua index 45cec04..2de6195 100644 --- a/sys/apps/Lua.lua +++ b/sys/apps/Lua.lua @@ -153,10 +153,11 @@ function page:eventHandler(event) self.tabs:selectTab(self.tabs[2]) elseif event.type == 'autocomplete' then - local sz = #self.prompt.value + local value = self.prompt.value or '' + local sz = #value local pos = self.prompt.entry.pos - self:setPrompt(autocomplete(sandboxEnv, self.prompt.value, self.prompt.entry.pos)) - self.prompt:setPosition(pos + #self.prompt.value - sz) + self:setPrompt(autocomplete(sandboxEnv, value, self.prompt.entry.pos)) + self.prompt:setPosition(pos + #value - sz) self.prompt:updateCursor() elseif event.type == 'device' then @@ -177,7 +178,7 @@ function page:eventHandler(event) history:reset() elseif event.type == 'command_enter' then - local s = tostring(self.prompt.value) + local s = tostring(self.prompt.value or '') if #s > 0 then self:executeStatement(s) diff --git a/sys/apps/Welcome.lua b/sys/apps/Welcome.lua index 04b60f9..a25278f 100644 --- a/sys/apps/Welcome.lua +++ b/sys/apps/Welcome.lua @@ -120,7 +120,9 @@ local page = UI.Page { } function page.wizard.pages.label:validate() - os.setComputerLabel(self.label.value) + if self.label.value then + os.setComputerLabel(self.label.value) + end return true end diff --git a/sys/apps/inspect.lua b/sys/apps/inspect.lua index ce41738..ae991d6 100644 --- a/sys/apps/inspect.lua +++ b/sys/apps/inspect.lua @@ -6,11 +6,6 @@ local multishell = _ENV.multishell local name = ({ ... })[1] or error('Syntax: inspect COMPONENT') local events = { } local page -local component = UI[name] and UI[name]() or error('Invalid component') - -if not component.example then - error('No example present') -end local function isRelevant(el) return page.testContainer == el or el.parent and isRelevant(el.parent) @@ -18,8 +13,7 @@ end local emitter = UI.Window.emit function UI.Window:emit(event) - if not event.recorded and isRelevant(self) then - event.recorded = true + if not event._recorded and isRelevant(self) then local t = { } for k,v in pairs(event) do if k ~= 'type' and k ~= 'recorded' then @@ -35,9 +29,16 @@ function UI.Window:emit(event) page.tabs.events.grid:draw() end end + event._recorded = true return emitter(self, event) end +-- do not load component until emit hook is in place +local component = UI[name] and UI[name]() or error('Invalid component') +if not component.example then + error('No example present') +end + page = UI.Page { testContainer = UI.Window { ey = 10, @@ -122,7 +123,7 @@ page = UI.Page { self.tabs.methodsTab.grid:draw() elseif event.type == 'grid_select' and event.element == self.tabs.events.grid then - event.selected.raw.recorded = nil + event.selected.raw._recorded = nil multishell.openTab({ path = 'sys/apps/Lua.lua', args = { event.selected.raw }, diff --git a/sys/apps/system/label.lua b/sys/apps/system/label.lua index e4a73f2..0dc77a7 100644 --- a/sys/apps/system/label.lua +++ b/sys/apps/system/label.lua @@ -39,7 +39,7 @@ local labelTab = UI.Tab { } function labelTab:eventHandler(event) - if event.type == 'update_label' then + if event.type == 'update_label' and self.label.value then os.setComputerLabel(self.label.value) self:emit({ type = 'success_message', message = 'Label updated' }) return true diff --git a/sys/apps/system/path.lua b/sys/apps/system/path.lua index bf30f7e..33249dd 100644 --- a/sys/apps/system/path.lua +++ b/sys/apps/system/path.lua @@ -59,7 +59,7 @@ function tab:save() end function tab:eventHandler(event) - if event.type == 'update_path' then + if event.type == 'update_path' and self.entry.value then table.insert(self.grid.values, { value = self.entry.value, }) diff --git a/sys/modules/opus/entry.lua b/sys/modules/opus/entry.lua index 693fe87..46e4eeb 100644 --- a/sys/modules/opus/entry.lua +++ b/sys/modules/opus/entry.lua @@ -2,39 +2,48 @@ local class = require('opus.class') local os = _G.os +-- convert value to a string (supporting nils or numbers in value) +local function _val(a) + return a and tostring(a) or '' +end + local Entry = class() function Entry:init(args) self.pos = 0 self.scroll = 0 - self.value = '' + self.value = args.value self.width = args.width or 256 self.limit = args.limit or 1024 self.mark = { } self.offset = args.offset or 1 + self.transform = args.transform or function(a) return a end end function Entry:reset() self.pos = 0 self.scroll = 0 - self.value = '' + self.value = nil self.mark = { } end function Entry:nextWord() - return select(2, self.value:find("[%s%p]?%w[%s%p]", self.pos + 1)) or #self.value + local value = _val(self.value) + return select(2, value:find("[%s%p]?%w[%s%p]", self.pos + 1)) or #value end function Entry:prevWord() - local x = #self.value - (self.pos - 1) - local _, n = self.value:reverse():find("[%s%p]?%w[%s%p]", x) - return n and #self.value - n + 1 or 0 + local value = _val(self.value) + local x = #value - (self.pos - 1) + local _, n = value:reverse():find("[%s%p]?%w[%s%p]", x) + return n and #value - n + 1 or 0 end function Entry:updateScroll() local ps = self.scroll - if self.pos > #self.value then - self.pos = #self.value + local value = _val(self.value) + if self.pos > #value then + self.pos = #value self.scroll = 0 -- ?? end if self.pos - self.scroll > self.width then @@ -48,21 +57,25 @@ function Entry:updateScroll() end function Entry:copyText(cx, ex) - return self.value:sub(cx + 1, ex) + -- this should be transformed (ie. if number) + return _val(self.value):sub(cx + 1, ex) end function Entry:insertText(x, text) - if #self.value + #text > self.limit then - text = text:sub(1, self.limit-#self.value) + text = tostring(self.transform(text)) or '' + local value = _val(self.value) + if #value + #text > self.limit then + text = text:sub(1, self.limit-#value) end - self.value = self.value:sub(1, x) .. text .. self.value:sub(x + 1) + self.value = self.transform(value:sub(1, x) .. text .. value:sub(x + 1)) self.pos = self.pos + #text end function Entry:deleteText(sx, ex) - local front = self.value:sub(1, sx) - local back = self.value:sub(ex + 1, #self.value) - self.value = front .. back + local value = _val(self.value) + local front = value:sub(1, sx) + local back = value:sub(ex + 1, #value) + self.value = self.transform(front .. back) self.pos = sx end @@ -74,7 +87,7 @@ function Entry:moveLeft() end function Entry:moveRight() - if self.pos < #self.value then + if self.pos < #_val(self.value) then self.pos = self.pos + 1 return true end @@ -88,14 +101,14 @@ function Entry:moveHome() end function Entry:moveEnd() - if self.pos ~= #self.value then - self.pos = #self.value + if self.pos ~= #_val(self.value) then + self.pos = #_val(self.value) return true end end function Entry:moveTo(ie) - self.pos = math.max(0, math.min(ie.x + self.scroll - self.offset, #self.value)) + self.pos = math.max(0, math.min(ie.x + self.scroll - self.offset, #_val(self.value))) end function Entry:backspace() @@ -107,7 +120,7 @@ function Entry:backspace() end function Entry:moveWordRight() - if self.pos < #self.value then + if self.pos < #_val(self.value) then self.pos = self:nextWord(self.value, self.pos + 1) return true end @@ -123,7 +136,7 @@ end function Entry:delete() if self.mark.active then self:deleteText(self.mark.x, self.mark.ex) - elseif self.pos < #self.value then + elseif self.pos < #_val(self.value) then self:deleteText(self.pos, self.pos + 1) end end @@ -137,15 +150,16 @@ function Entry:cutFromStart() end function Entry:cutToEnd() - if self.pos < #self.value then - local text = self:copyText(self.pos, #self.value) - self:deleteText(self.pos, #self.value) + local value = _val(self.value) + if self.pos < #value then + local text = self:copyText(self.pos, #value) + self:deleteText(self.pos, #value) os.queueEvent('clipboard_copy', text) end end function Entry:cutNextWord() - if self.pos < #self.value then + if self.pos < #_val(self.value) then local ex = self:nextWord(self.value, self.pos) local text = self:copyText(self.pos, ex) self:deleteText(self.pos, ex) @@ -170,7 +184,7 @@ function Entry:insertChar(ie) end function Entry:copy() - if #self.value > 0 then + if #_val(self.value) > 0 then self.mark.continue = true if self.mark.active then self:copyMarked() @@ -202,7 +216,7 @@ function Entry:paste(ie) end function Entry:clearLine() - if #self.value > 0 then + if #_val(self.value) > 0 then self:reset() end end @@ -233,10 +247,13 @@ function Entry:unmark() end function Entry:markAnchor(ie) + local wasMarking = self.mark.active self:unmark() self:moveTo(ie) self:markBegin() self:markFinish() + + self.textChanged = wasMarking end function Entry:markLeft() @@ -257,7 +274,7 @@ function Entry:markWord(ie) local index = 1 self:moveTo(ie) while true do - local s, e = self.value:find('%w+', index) + local s, e = _val(self.value):find('%w+', index) if not s or s - 1 > self.pos then break end @@ -288,12 +305,12 @@ function Entry:markPrevWord() end function Entry:markAll() - if #self.value > 0 then + if #_val(self.value) > 0 then self.mark.anchor = { x = 1 } self.mark.active = true self.mark.continue = true self.mark.x = 0 - self.mark.ex = #self.value + self.mark.ex = #_val(self.value) self.textChanged = true end end @@ -373,6 +390,10 @@ function Entry:process(ie) action(self, ie) + if not self.value or #_val(self.value) == 0 then + self.value = nil + end +_syslog(tostring(line) .. ' ' .. tostring(self.value) .. ' ' .. tostring(self.textChanged)) self.textChanged = self.textChanged or self.value ~= line self.posChanged = pos ~= self.pos self:updateScroll() diff --git a/sys/modules/opus/ui/components/Form.lua b/sys/modules/opus/ui/components/Form.lua index ed9ae0d..da312d9 100644 --- a/sys/modules/opus/ui/components/Form.lua +++ b/sys/modules/opus/ui/components/Form.lua @@ -32,7 +32,7 @@ function UI.Form:setValues(values) if child.setValue then child:setValue(self.values[child.formKey]) else - child.value = self.values[child.formKey] or '' + child.value = self.values[child.formKey] end end end @@ -56,7 +56,7 @@ function UI.Form:createForm() for _, child in pairs(self) do if type(child) == 'table' and child.UIElement then if child.formKey then - child.value = self.values[child.formKey] or '' + child.value = self.values[child.formKey] end if child.formLabel then child.x = self.labelWidth + self.margin - 1 @@ -99,14 +99,6 @@ function UI.Form:validateField(field) return false, 'Field is required' end end - if field.validate == 'numeric' then - field.value = field.value or '' - if #tostring(field.value) > 0 then - if not tonumber(field.value) then - return false, 'Invalid number' - end - end - end return true end @@ -124,11 +116,7 @@ function UI.Form:save() end for _,child in pairs(self.children) do if child.formKey then - if child.validate == 'numeric' then - self.values[child.formKey] = tonumber(child.value) - else - self.values[child.formKey] = child.value - end + self.values[child.formKey] = child.value end end diff --git a/sys/modules/opus/ui/components/Grid.lua b/sys/modules/opus/ui/components/Grid.lua index bcdab81..e1edfe8 100644 --- a/sys/modules/opus/ui/components/Grid.lua +++ b/sys/modules/opus/ui/components/Grid.lua @@ -493,3 +493,43 @@ function UI.Grid:eventHandler(event) end return true end + +function UI.Grid.example() + local values = { + { key = 'key1', value = 'value1' }, + { key = 'key2', value = 'value2' }, + { key = 'key3', value = 'value3-longer value text' }, + { key = 'key4', value = 'value4' }, + { key = 'key5', value = 'value5' }, + } + return UI.Window { + regular = UI.Grid { + ex = '48%', ey = 4, + values = values, + sortColumn = 'key', + inverseSort = true, + columns = { + { heading = 'key', key = 'key' }, + { heading = 'value', key = 'value' }, + }, + }, + noheader = UI.Grid { + ex = '48%', y = 6, ey = -2, + disableHeader = true, + values = values, + columns = { + { heading = 'key', key = 'key', width = 6, }, + { heading = 'value', key = 'value', textColor = colors.yellow }, + }, + }, + autospace = UI.Grid { + x = '52%', ey = 4, + autospace = true, + values = values, + columns = { + { heading = 'key', key = 'key' }, + { heading = 'value', key = 'value' }, + }, + }, + } +end diff --git a/sys/modules/opus/ui/components/TextEntry.lua b/sys/modules/opus/ui/components/TextEntry.lua index ea507c8..1a3f604 100644 --- a/sys/modules/opus/ui/components/TextEntry.lua +++ b/sys/modules/opus/ui/components/TextEntry.lua @@ -5,8 +5,15 @@ local Util = require('opus.util') local colors = _G.colors local _rep = string.rep -local _lower = string.lower -local _upper = string.upper + +local function transform(directive) + local transforms = { + lowercase = string.lower, + uppercase = string.upper, + number = tonumber, + } + return transforms[directive] +end UI.TextEntry = class(UI.Window) UI.TextEntry.defaults = { @@ -25,7 +32,7 @@ UI.TextEntry.defaults = { } } function UI.TextEntry:postInit() - self.entry = entry({ limit = self.limit, offset = 2 }) + self.entry = entry({ limit = self.limit, offset = 2, transform = transform(self.transform) }) end function UI.TextEntry:layout() @@ -36,13 +43,13 @@ end function UI.TextEntry:setValue(value) self.value = value --or '' self.entry:unmark() - self.entry.value = tostring(value) + self.entry.value = value --tostring(value or '') self.entry:updateScroll() end function UI.TextEntry:setPosition(pos) self.entry.pos = pos - self.entry.value = tostring(self.value or '') + self.entry.value = self.value --tostring(self.value or '') -- WHY HERE ? self.entry:updateScroll() end @@ -105,27 +112,15 @@ function UI.TextEntry:focus() end end -function UI.TextEntry:_transform(text) - if self.transform == 'lowercase' then - return _lower(text) - elseif self.transform == 'uppercase' then - return _upper(text) - elseif self.transform == 'number' then - return tonumber(text) --or 0 - end - return text -end - function UI.TextEntry:eventHandler(event) - local text = self.value --or '' - self.entry.value = tostring(text or '') + local text = self.value + self.entry.value = text if event.ie and self.entry:process(event.ie) then if self.entry.textChanged then - self.value = self:_transform(self.entry.value) +--_syslog(tostring(self.entry.value) .. ' ' .. tostring(self.value)) + self.value = self.entry.value self:draw() - if text ~= self.value then - self:emit({ type = 'text_change', text = self.value, element = self }) - end + self:emit({ type = 'text_change', text = self.value, element = self }) elseif self.entry.posChanged then self:updateCursor() end -- 2.49.1 From 0a828fecc558394e82e2e0948c098f733de78736 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Wed, 13 Nov 2019 14:38:24 -0700 Subject: [PATCH 07/23] oops --- sys/apps/shell.lua | 5 ++++- sys/modules/opus/entry.lua | 2 +- sys/modules/opus/ui/components/TextEntry.lua | 7 +++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/sys/apps/shell.lua b/sys/apps/shell.lua index d64f046..6124a3d 100644 --- a/sys/apps/shell.lua +++ b/sys/apps/shell.lua @@ -586,6 +586,7 @@ local function shellRead(history) end local _,cy = term.getCursorPos() term.setCursorPos(3, cy) + entry.value = entry.value or '' local filler = #entry.value < lastLen and string.rep(' ', lastLen - #entry.value) or '' @@ -635,6 +636,7 @@ local function shellRead(history) redraw() elseif ie.code == 'tab' then + entry.value = entry.value or '' if entry.pos == #entry.value then local cline = autocomplete(entry.value) if cline then @@ -650,6 +652,7 @@ local function shellRead(history) else entry:process(ie) + entry.value = entry.value or '' if entry.textChanged then redraw() elseif entry.posChanged then @@ -666,7 +669,7 @@ local function shellRead(history) print() term.setCursorBlink( false ) - return entry.value + return entry.value or '' end local history = History.load('usr/.shell_history', 25) diff --git a/sys/modules/opus/entry.lua b/sys/modules/opus/entry.lua index 46e4eeb..7deb36f 100644 --- a/sys/modules/opus/entry.lua +++ b/sys/modules/opus/entry.lua @@ -393,7 +393,7 @@ function Entry:process(ie) if not self.value or #_val(self.value) == 0 then self.value = nil end -_syslog(tostring(line) .. ' ' .. tostring(self.value) .. ' ' .. tostring(self.textChanged)) + self.textChanged = self.textChanged or self.value ~= line self.posChanged = pos ~= self.pos self:updateScroll() diff --git a/sys/modules/opus/ui/components/TextEntry.lua b/sys/modules/opus/ui/components/TextEntry.lua index 1a3f604..75665a6 100644 --- a/sys/modules/opus/ui/components/TextEntry.lua +++ b/sys/modules/opus/ui/components/TextEntry.lua @@ -41,15 +41,15 @@ function UI.TextEntry:layout() end function UI.TextEntry:setValue(value) - self.value = value --or '' + self.value = value self.entry:unmark() - self.entry.value = value --tostring(value or '') + self.entry.value = value self.entry:updateScroll() end function UI.TextEntry:setPosition(pos) self.entry.pos = pos - self.entry.value = self.value --tostring(self.value or '') -- WHY HERE ? + self.entry.value = self.value -- WHY HERE ? self.entry:updateScroll() end @@ -117,7 +117,6 @@ function UI.TextEntry:eventHandler(event) self.entry.value = text if event.ie and self.entry:process(event.ie) then if self.entry.textChanged then ---_syslog(tostring(self.entry.value) .. ' ' .. tostring(self.value)) self.value = self.entry.value self:draw() self:emit({ type = 'text_change', text = self.value, element = self }) -- 2.49.1 From db48031c7c19fbaa9ba2fa210e14dc3cc1c922f1 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Wed, 13 Nov 2019 15:17:23 -0700 Subject: [PATCH 08/23] funnel all events through emit --- sys/modules/opus/entry.lua | 14 ++++++++------ sys/modules/opus/ui.lua | 27 ++++++++++----------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/sys/modules/opus/entry.lua b/sys/modules/opus/entry.lua index 7deb36f..aa2397f 100644 --- a/sys/modules/opus/entry.lua +++ b/sys/modules/opus/entry.lua @@ -62,13 +62,15 @@ function Entry:copyText(cx, ex) end function Entry:insertText(x, text) - text = tostring(self.transform(text)) or '' - local value = _val(self.value) - if #value + #text > self.limit then - text = text:sub(1, self.limit-#value) + text = tostring(self.transform(text) or '') + if #text > 0 then + local value = _val(self.value) + if #value + #text > self.limit then + text = text:sub(1, self.limit-#value) + end + self.value = self.transform(value:sub(1, x) .. text .. value:sub(x + 1)) + self.pos = self.pos + #text end - self.value = self.transform(value:sub(1, x) .. text .. value:sub(x + 1)) - self.pos = self.pos + #text end function Entry:deleteText(sx, ex) diff --git a/sys/modules/opus/ui.lua b/sys/modules/opus/ui.lua index 9e9a4c5..2ab507d 100644 --- a/sys/modules/opus/ui.lua +++ b/sys/modules/opus/ui.lua @@ -248,23 +248,8 @@ function Manager:emitEvent(event) end end -function Manager:inputEvent(parent, event) - while parent do - if parent.accelerators then - local acc = parent.accelerators[event.key] - if acc then - if parent:emit({ type = acc, element = parent }) then - return true - end - end - end - if parent.eventHandler then - if parent:eventHandler(event) then - return true - end - end - parent = parent.parent - end +function Manager:inputEvent(parent, event) -- deprecate ? + return parent and parent:emit(event) end function Manager:click(target, code, button, x, y) @@ -927,6 +912,14 @@ end function UI.Window:emit(event) local parent = self while parent do + if parent.accelerators and event.key then -- not ideal + -- could be [event.key or event.type] to support accelerators + -- for non-input type events + local acc = parent.accelerators[event.key] + if acc and parent:emit({ type = acc, element = parent }) then + return true + end + end if parent.eventHandler then if parent:eventHandler(event) then return true -- 2.49.1 From 3241326a2f1662fdd312a868ab1eab49ed4c1257 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Wed, 13 Nov 2019 21:50:00 -0700 Subject: [PATCH 09/23] accelerators for any event + more inspect examples --- sys/apps/inspect.lua | 30 ++++++++++++++----- sys/modules/opus/ui.lua | 16 ++++++---- sys/modules/opus/ui/components/Checkbox.lua | 6 ++++ sys/modules/opus/ui/components/Chooser.lua | 24 ++++++++++++++- sys/modules/opus/ui/components/DropMenu.lua | 13 ++++++++ sys/modules/opus/ui/components/Form.lua | 20 +++++++++++++ sys/modules/opus/ui/components/Grid.lua | 3 ++ sys/modules/opus/ui/components/MenuBar.lua | 9 ++++++ .../opus/ui/components/Notification.lua | 25 ++++++++++++++++ sys/modules/opus/ui/components/Slider.lua | 8 +++++ 10 files changed, 140 insertions(+), 14 deletions(-) diff --git a/sys/apps/inspect.lua b/sys/apps/inspect.lua index ae991d6..48feeb4 100644 --- a/sys/apps/inspect.lua +++ b/sys/apps/inspect.lua @@ -1,4 +1,5 @@ -local UI = require('opus.ui') +local UI = require('opus.ui') +local Util = require('opus.util') local colors = _G.colors local multishell = _ENV.multishell @@ -6,6 +7,7 @@ local multishell = _ENV.multishell local name = ({ ... })[1] or error('Syntax: inspect COMPONENT') local events = { } local page +local lastEvent local function isRelevant(el) return page.testContainer == el or el.parent and isRelevant(el.parent) @@ -13,7 +15,8 @@ end local emitter = UI.Window.emit function UI.Window:emit(event) - if not event._recorded and isRelevant(self) then + if event ~= lastEvent and isRelevant(self) then + lastEvent = event local t = { } for k,v in pairs(event) do if k ~= 'type' and k ~= 'recorded' then @@ -21,7 +24,7 @@ function UI.Window:emit(event) end end table.insert(events, 1, { type = event.type, value = table.concat(t, ' '), raw = event }) - while #events > 10 do + while #events > 20 do table.remove(events) end page.tabs.events.grid:update() @@ -29,7 +32,6 @@ function UI.Window:emit(event) page.tabs.events.grid:draw() end end - event._recorded = true return emitter(self, event) end @@ -72,7 +74,14 @@ page = UI.Page { }, events = UI.Tab { tabTitle = 'Events', + UI.MenuBar { + y = -1, + buttons = { + { text = 'Clear', event = 'event_clear' }, + } + }, grid = UI.ScrollingGrid { + ey = -2, headerBackgroundColor = colors.red, values = events, autospace = true, @@ -80,6 +89,9 @@ page = UI.Page { { heading = 'type', key = 'type' }, { heading = 'value', key = 'value', } }, + accelerators = { + grid_select = 'event_inspect', + }, } } }, @@ -122,15 +134,19 @@ page = UI.Page { self.tabs.methodsTab.grid:update() self.tabs.methodsTab.grid:draw() - elseif event.type == 'grid_select' and event.element == self.tabs.events.grid then - event.selected.raw._recorded = nil + 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 == 'grid_select' and event.element == self.tabs.properties.grid then + elseif event.type == 'edit_property' then self.editor.entry.value = event.selected.value self.editor:show() diff --git a/sys/modules/opus/ui.lua b/sys/modules/opus/ui.lua index 2ab507d..5686f93 100644 --- a/sys/modules/opus/ui.lua +++ b/sys/modules/opus/ui.lua @@ -912,12 +912,16 @@ end function UI.Window:emit(event) local parent = self while parent do - if parent.accelerators and event.key then -- not ideal - -- could be [event.key or event.type] to support accelerators - -- for non-input type events - local acc = parent.accelerators[event.key] - if acc and parent:emit({ type = acc, element = parent }) then - return true + if parent.accelerators then + -- events types can be made unique via accelerators + local acc = parent.accelerators[event.key or event.type] + if acc and acc ~= event.type then -- don't get stuck in a loop + local event2 = Util.shallowCopy(event) + event2.type = acc + event2.key = nil + if parent:emit(event2) then + return true + end end end if parent.eventHandler then diff --git a/sys/modules/opus/ui/components/Checkbox.lua b/sys/modules/opus/ui/components/Checkbox.lua index a90e911..54343e5 100644 --- a/sys/modules/opus/ui/components/Checkbox.lua +++ b/sys/modules/opus/ui/components/Checkbox.lua @@ -61,3 +61,9 @@ function UI.Checkbox:eventHandler(event) return true end end + +function UI.Checkbox.example() + return UI.Checkbox { + x = 2, y = 2, + } +end diff --git a/sys/modules/opus/ui/components/Chooser.lua b/sys/modules/opus/ui/components/Chooser.lua index e4d41fa..9698f6f 100644 --- a/sys/modules/opus/ui/components/Chooser.lua +++ b/sys/modules/opus/ui/components/Chooser.lua @@ -53,7 +53,7 @@ function UI.Chooser:eventHandler(event) if event.key == 'right' or event.key == 'space' then local _,k = Util.find(self.choices, 'value', self.value) local choice - if not k then k = 1 end + if not k then k = 0 end if k and k < #self.choices then choice = self.choices[k+1] else @@ -86,3 +86,25 @@ function UI.Chooser:eventHandler(event) end end end + +function UI.Chooser.example() + return UI.Window { + a = UI.Chooser { + x = 2, y = 2, + choices = { + { name = 'choice1', value = 'value1' }, + { name = 'choice2', value = 'value2' }, + { name = 'choice3', value = 'value3' }, + }, + value = 'value2', + }, + b = UI.Chooser { + x = 2, y = 4, + choices = { + { name = 'choice1', value = 'value1' }, + { name = 'choice2', value = 'value2' }, + { name = 'choice3', value = 'value3' }, + }, + } + } +end diff --git a/sys/modules/opus/ui/components/DropMenu.lua b/sys/modules/opus/ui/components/DropMenu.lua index 5cce43a..41bdaf9 100644 --- a/sys/modules/opus/ui/components/DropMenu.lua +++ b/sys/modules/opus/ui/components/DropMenu.lua @@ -73,3 +73,16 @@ function UI.DropMenu:eventHandler(event) end return true end + +function UI.DropMenu.example() + return UI.MenuBar { + buttons = { + { text = 'File', dropdown = { + { text = 'Run', event = 'run' }, + { text = 'Shell s', event = 'shell' }, + { spacer = true }, + { text = 'Quit ^q', event = 'quit' }, + } }, + } + } +end diff --git a/sys/modules/opus/ui/components/Form.lua b/sys/modules/opus/ui/components/Form.lua index da312d9..69cb7ca 100644 --- a/sys/modules/opus/ui/components/Form.lua +++ b/sys/modules/opus/ui/components/Form.lua @@ -134,3 +134,23 @@ function UI.Form:eventHandler(event) end return true end + +function UI.Form.example() + return UI.Form { + x = 2, ex = -2, y = 2, + ptype = UI.Chooser { + formLabel = 'Type', formKey = 'type', + width = 10, + choices = { + { name = 'Modem', value = 'wireless_modem' }, + { name = 'Drive', value = 'disk_drive' }, + }, + }, + drive_id = UI.TextEntry { + formLabel = 'Drive', formKey = 'drive_id', + required = true, + width = 5, + transform = 'number', + }, + } +end diff --git a/sys/modules/opus/ui/components/Grid.lua b/sys/modules/opus/ui/components/Grid.lua index e1edfe8..1d6e480 100644 --- a/sys/modules/opus/ui/components/Grid.lua +++ b/sys/modules/opus/ui/components/Grid.lua @@ -512,6 +512,9 @@ function UI.Grid.example() { heading = 'key', key = 'key' }, { heading = 'value', key = 'value' }, }, + accelerators = { + grid_select = 'custom_select', + } }, noheader = UI.Grid { ex = '48%', y = 6, ey = -2, diff --git a/sys/modules/opus/ui/components/MenuBar.lua b/sys/modules/opus/ui/components/MenuBar.lua index bccb9be..85f435b 100644 --- a/sys/modules/opus/ui/components/MenuBar.lua +++ b/sys/modules/opus/ui/components/MenuBar.lua @@ -88,3 +88,12 @@ function UI.MenuBar:eventHandler(event) return true end end + +function UI.MenuBar.example() + return UI.MenuBar { + buttons = { + { text = 'Choice1', event = 'event1' }, + { text = 'Choice2', event = 'event2' }, + } + } +end diff --git a/sys/modules/opus/ui/components/Notification.lua b/sys/modules/opus/ui/components/Notification.lua index f1b38f6..bf02256 100644 --- a/sys/modules/opus/ui/components/Notification.lua +++ b/sys/modules/opus/ui/components/Notification.lua @@ -90,3 +90,28 @@ function UI.Notification:eventHandler(event) end end end + +function UI.Notification.example() + return UI.Window { + notify = UI.Notification { + anchor = 'top', + }, + button1 = UI.Button { + x = 2, y = 3, + text = 'success', + event = 'test_success', + }, + button2 = UI.Button { + x = 2, y = 5, + text = 'error', + event = 'test_error', + }, + eventHandler = function (self, event) + if event.type == 'test_success' then + self.notify:success('Example text') + elseif event.type == 'test_error' then + self.notify:error('Example text') + end + end, + } +end diff --git a/sys/modules/opus/ui/components/Slider.lua b/sys/modules/opus/ui/components/Slider.lua index 9dee765..09325b4 100644 --- a/sys/modules/opus/ui/components/Slider.lua +++ b/sys/modules/opus/ui/components/Slider.lua @@ -75,3 +75,11 @@ function UI.Slider:eventHandler(event) self:draw() end end + +function UI.Slider.example() + return UI.Slider { + y = 2, x = 2, ex = -2, + min = 0, max = 1, + help = 'Volume setting', + } +end -- 2.49.1 From 14057c2bf9a06ee5f2aebeeda28d3e39df890af8 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Thu, 14 Nov 2019 15:43:20 -0700 Subject: [PATCH 10/23] moar ui examples --- sys/modules/opus/ui/components/Embedded.lua | 23 ++++++++++++++ .../opus/ui/components/Notification.lua | 2 +- sys/modules/opus/ui/components/SlideOut.lua | 26 ++++++++++++++++ sys/modules/opus/ui/components/Slider.lua | 3 +- sys/modules/opus/ui/components/StatusBar.lua | 17 ++++++++++ sys/modules/opus/ui/components/TextEntry.lua | 7 ++++- sys/modules/opus/ui/components/Wizard.lua | 31 +++++++++++++++++++ 7 files changed, 105 insertions(+), 4 deletions(-) diff --git a/sys/modules/opus/ui/components/Embedded.lua b/sys/modules/opus/ui/components/Embedded.lua index fcdee82..e15df33 100644 --- a/sys/modules/opus/ui/components/Embedded.lua +++ b/sys/modules/opus/ui/components/Embedded.lua @@ -74,3 +74,26 @@ end function UI.Embedded:focus() -- allow scrolling end + +function UI.Embedded.example() + local Event = require('opus.event') + local Util = require('opus.util') + local term = _G.term + + return UI.Embedded { + visible = true, + enable = function (self) + UI.Embedded.enable(self) + Event.addRoutine(function() + local oterm = term.redirect(self.win) + Util.run(_ENV, '/sys/apps/shell.lua') + term.redirect(oterm) + end) + end, + eventHandler = function(_, event) + if event.type == 'key' then + return true + end + end + } +end diff --git a/sys/modules/opus/ui/components/Notification.lua b/sys/modules/opus/ui/components/Notification.lua index bf02256..7b11543 100644 --- a/sys/modules/opus/ui/components/Notification.lua +++ b/sys/modules/opus/ui/components/Notification.lua @@ -110,7 +110,7 @@ function UI.Notification.example() if event.type == 'test_success' then self.notify:success('Example text') elseif event.type == 'test_error' then - self.notify:error('Example text') + self.notify:error('Example text', 0) end end, } diff --git a/sys/modules/opus/ui/components/SlideOut.lua b/sys/modules/opus/ui/components/SlideOut.lua index 37f5e37..c5779dd 100644 --- a/sys/modules/opus/ui/components/SlideOut.lua +++ b/sys/modules/opus/ui/components/SlideOut.lua @@ -50,3 +50,29 @@ function UI.SlideOut:eventHandler(event) return true end end + +function UI.SlideOut.example() + return UI.Window { + button = UI.Button { + x = 2, y = 2, + text = 'show', + }, + slideOut = UI.SlideOut { + backgroundColor = colors.yellow, + y = -4, height = 4, + button = UI.Button { + x = 2, y = 2, + text = 'hide', + }, + }, + eventHandler = function (self, event) + if event.type == 'button_press' then + if self.slideOut.enabled then + self.slideOut:hide() + else + self.slideOut:show() + end + end + end, + } +end diff --git a/sys/modules/opus/ui/components/Slider.lua b/sys/modules/opus/ui/components/Slider.lua index 09325b4..9a58cdb 100644 --- a/sys/modules/opus/ui/components/Slider.lua +++ b/sys/modules/opus/ui/components/Slider.lua @@ -49,7 +49,7 @@ function UI.Slider:draw() i == self.width and self.rightBorder or self.barChar - table.insert(bar, filler) + table.insert(bar, filler) end self:write(1, 1, table.concat(bar), nil, self.barColor) self:write(progress, 1, self.sliderChar, nil, self.focused and self.sliderFocusColor or self.sliderColor) @@ -80,6 +80,5 @@ function UI.Slider.example() return UI.Slider { y = 2, x = 2, ex = -2, min = 0, max = 1, - help = 'Volume setting', } end diff --git a/sys/modules/opus/ui/components/StatusBar.lua b/sys/modules/opus/ui/components/StatusBar.lua index a92c0c2..96a1943 100644 --- a/sys/modules/opus/ui/components/StatusBar.lua +++ b/sys/modules/opus/ui/components/StatusBar.lua @@ -96,3 +96,20 @@ function UI.StatusBar:draw() self:write(1, 1, Util.widthify(s, self.width)) end end + +function UI.StatusBar.example() + return UI.Window { + status1 = UI.StatusBar { values = 'standard' }, + status2 = UI.StatusBar { + ey = -3, + columns = { + { key = 'field1' }, + { key = 'field2', width = 6 }, + }, + values = { + field1 = 'test', + field2 = '42', + } + } + } +end diff --git a/sys/modules/opus/ui/components/TextEntry.lua b/sys/modules/opus/ui/components/TextEntry.lua index 75665a6..523208c 100644 --- a/sys/modules/opus/ui/components/TextEntry.lua +++ b/sys/modules/opus/ui/components/TextEntry.lua @@ -117,9 +117,14 @@ function UI.TextEntry:eventHandler(event) self.entry.value = text if event.ie and self.entry:process(event.ie) then if self.entry.textChanged then + local changed = self.value ~= self.entry.value self.value = self.entry.value self:draw() - self:emit({ type = 'text_change', text = self.value, element = self }) + if changed then + -- we get entry.textChanged when marking is updated + -- no need to emit in that case + self:emit({ type = 'text_change', text = self.value, element = self }) + end elseif self.entry.posChanged then self:updateCursor() end diff --git a/sys/modules/opus/ui/components/Wizard.lua b/sys/modules/opus/ui/components/Wizard.lua index e6bce7e..549669e 100644 --- a/sys/modules/opus/ui/components/Wizard.lua +++ b/sys/modules/opus/ui/components/Wizard.lua @@ -122,3 +122,34 @@ function UI.Wizard:eventHandler(event) self:draw() end end + +function UI.Wizard.example() + return UI.Wizard { + ey = -2, + pages = { + splash = UI.WizardPage { + index = 1, + intro = UI.TextArea { + inactive = true, + x = 3, ex = -3, y = 2, ey = -2, + value = 'sample text', + }, + }, + label = UI.WizardPage { + index = 2, + intro = UI.TextArea { + inactive = true, + x = 3, ex = -3, y = 2, ey = -2, + value = 'sample more text', + }, + }, + password = UI.WizardPage { + index = 3, + text = UI.TextEntry { + x = 12, ex = -3, y = 2, + shadowText = 'tet', + }, + }, + }, + } +end -- 2.49.1 From efa1a5bbf5b5a8bed1ff216e51d75185fc5b8bbe Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Fri, 15 Nov 2019 12:51:44 -0700 Subject: [PATCH 11/23] clipping for transistions + tab ordering via index + more examples --- sys/apps/Tasks.lua | 50 +++++++++---------- sys/apps/inspect.lua | 35 ++++++------- sys/autorun/complete.lua | 13 +++++ sys/modules/opus/ui/canvas.lua | 6 +++ sys/modules/opus/ui/components/Form.lua | 4 +- sys/modules/opus/ui/components/Menu.lua | 11 ++++ sys/modules/opus/ui/components/MenuBar.lua | 9 ++++ .../opus/ui/components/ProgressBar.lua | 16 ++++++ sys/modules/opus/ui/components/SlideOut.lua | 19 ++++--- sys/modules/opus/ui/components/Tabs.lua | 16 +++--- .../opus/ui/components/VerticalMeter.lua | 16 ++++++ 11 files changed, 138 insertions(+), 57 deletions(-) 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 -- 2.49.1 From a3a8c64be8d73ef0d7c65c6ce37b3696d6af6c2b Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Sat, 16 Nov 2019 22:12:02 -0700 Subject: [PATCH 12/23] UI docs --- sys/apps/inspect.lua | 20 ++++-- sys/modules/opus/ui.lua | 68 +++++++++++++++++-- sys/modules/opus/ui/canvas.lua | 4 +- sys/modules/opus/ui/components/Checkbox.lua | 32 +++++---- .../opus/ui/components/DropMenuItem.lua | 1 - sys/modules/opus/ui/components/Menu.lua | 1 - sys/modules/opus/ui/components/MenuBar.lua | 1 + sys/modules/opus/ui/components/MenuItem.lua | 1 - .../opus/ui/components/Notification.lua | 13 ++-- .../opus/ui/components/ScrollingGrid.lua | 1 - sys/modules/opus/ui/components/SlideOut.lua | 6 +- sys/modules/opus/ui/components/Tab.lua | 3 - sys/modules/opus/ui/components/TabBar.lua | 6 +- .../opus/ui/components/TabBarMenuItem.lua | 4 +- sys/modules/opus/ui/components/Tabs.lua | 3 + sys/modules/opus/ui/components/TextArea.lua | 1 - sys/modules/opus/ui/components/TextEntry.lua | 3 + sys/modules/opus/ui/components/Viewport.lua | 1 - 18 files changed, 123 insertions(+), 46 deletions(-) diff --git a/sys/apps/inspect.lua b/sys/apps/inspect.lua index 6cc4048..1d4f95b 100644 --- a/sys/apps/inspect.lua +++ b/sys/apps/inspect.lua @@ -6,8 +6,7 @@ local multishell = _ENV.multishell local name = ({ ... })[1] or error('Syntax: inspect COMPONENT') local events = { } -local page -local lastEvent +local page, lastEvent, focused local function isRelevant(el) return page.testContainer == el or el.parent and isRelevant(el.parent) @@ -43,11 +42,12 @@ end page = UI.Page { testContainer = UI.Window { - ey = 10, + ey = '50%', testing = component.example(), }, tabs = UI.Tabs { - y = 11, + backgroundColor = colors.red, + y = '50%', properties = UI.Tab { tabTitle = 'Properties', grid = UI.ScrollingGrid { @@ -66,18 +66,29 @@ page = UI.Page { index = 2, tabTitle = 'Methods', grid = UI.ScrollingGrid { + ex = '50%', headerBackgroundColor = colors.red, sortColumn = 'key', columns = { { heading = 'key', key = 'key' }, }, }, + docs = UI.TextArea { + x = '50%', + backgroundColor = colors.black, + }, + eventHandler = function (self, event) + if event.type == 'grid_focus_row' and focused then + self.docs:setText(focused:getDoc(event.selected.key) or '') + end + end, }, events = UI.Tab { index = 1, tabTitle = 'Events', UI.MenuBar { y = -1, + backgroundColor = colors.red, buttons = { { text = 'Clear' }, } @@ -124,6 +135,7 @@ page = UI.Page { }, eventHandler = function (self, event) if event.type == 'focus_change' and isRelevant(event.focused) then + focused = event.focused local t = { } for k,v in pairs(event.focused) do table.insert(t, { diff --git a/sys/modules/opus/ui.lua b/sys/modules/opus/ui.lua index 5686f93..6e464ad 100644 --- a/sys/modules/opus/ui.lua +++ b/sys/modules/opus/ui.lua @@ -398,6 +398,7 @@ local UI = Manager() --[[-- Basic drawable area --]]-- UI.Window = class() UI.Window.uid = 1 +UI.Window.docs = { } UI.Window.defaults = { UIElement = 'Window', x = 1, @@ -482,13 +483,14 @@ function UI.Window:layout() end if type(self.x) == 'string' then - self.x = calc(self.x, self.parent.width) + self.x = calc(self.x, self.parent.width) + 1 + -- +1 in order to allow both x and ex to use the same % end if type(self.ex) == 'string' then self.ex = calc(self.ex, self.parent.width) end if type(self.y) == 'string' then - self.y = calc(self.y, self.parent.height) + self.y = calc(self.y, self.parent.height) + 1 end if type(self.ey) == 'string' then self.ey = calc(self.ey, self.parent.height) @@ -539,6 +541,22 @@ function UI.Window:setParent() self:layout() + -- Experimental + -- Inherit properties from the parent container + -- does this need to be in reverse order ? + local m = getmetatable(self) -- get the class for this instance + repeat + if m.inherits then + for k, v in pairs(m.inherits) do + local value = self.parent:getProperty(v) + if value then + self[k] = value + end + end + end + m = m._base + until not m + self:initChildren() end @@ -555,6 +573,13 @@ function UI.Window:resize() end end +UI.Window.docs.add = [[add(TABLE) +Add element(s) to a window. Example: +page:add({ + text = UI.Text { + x=5,value='help' + } +})]] function UI.Window:add(children) UI:mergeProperties(self, children) self:initChildren() @@ -574,6 +599,8 @@ function UI.Window:setCursorBlink(blink) self.parent:setCursorBlink(blink) end +UI.Window.docs.draw = [[draw(VOID) +Redraws the window in the internal buffer.]] function UI.Window:draw() self:clear(self.backgroundColor) if self.children then @@ -585,6 +612,21 @@ function UI.Window:draw() end end +UI.Window.docs.getDoc = [[getDoc(STRING method) +Gets the documentation for a method.]] +function UI.Window:getDoc(method) + local m = getmetatable(self) -- get the class for this instance + repeat + if m.docs and m.docs[method] then + return m.docs[method] + end + m = m._base + until not m +end + +UI.Window.docs.sync = [[sync(VOID) +Invoke a screen update. Automatically called at top level after an input event. +Call to force a screen update.]] function UI.Window:sync() if self.parent then self.parent:sync() @@ -614,9 +656,11 @@ function UI.Window:setTextScale(textScale) self.parent:setTextScale(textScale) end +UI.Window.docs.clear = [[clear(opt COLOR bg, opt COLOR fg) +Clears the window using the either the passed values or the defaults for that window.]] function UI.Window:clear(bg, fg) if self.canvas then - self.canvas:clear(bg or self.backgroundColor, fg or self.textColor) + self.canvas:clear(bg or self:getProperty('backgroundColor'), fg or self:getProperty('textColor')) else self:clearArea(1 + self.offx, 1 + self.offy, self.width, self.height, bg) end @@ -635,18 +679,18 @@ function UI.Window:clearArea(x, y, width, height, bg) end end -function UI.Window:write(x, y, text, bg, tc) +function UI.Window:write(x, y, text, bg, fg) bg = bg or self.backgroundColor - tc = tc or self.textColor + fg = fg or self.textColor if self.canvas then - self.canvas:write(x, y, text, bg, tc) + self.canvas:write(x, y, text, bg or self:getProperty('backgroundColor'), fg or self:getProperty('textColor')) else x = x - self.offx y = y - self.offy if y <= self.height and y > 0 then self.parent:write( - self.x + x - 1, self.y + y - 1, tostring(text), bg, tc) + self.x + x - 1, self.y + y - 1, tostring(text), bg, fg) end end end @@ -752,12 +796,20 @@ function UI.Window:print(text, bg, fg) return self.cursorX, self.cursorY end +UI.Window.docs.focus = [[focus(VOID) +If the function is present on a class, it indicates +that this element can accept focus. Called when receiving focus.]] + +UI.Window.docs.setFocus = [[setFocus(ELEMENT el) +Set the page's focus to the passed element.]] function UI.Window:setFocus(focus) if self.parent then self.parent:setFocus(focus) end end +UI.Window.docs.capture = [[capture(ELEMENT el) +Restricts input to the passed element's tree.]] function UI.Window:capture(child) if self.parent then self.parent:capture(child) @@ -793,6 +845,8 @@ function UI.Window:pointToChild(x, y) } end +UI.Window.docs.getFocusables = [[getFocusables(VOID) +Returns a list of children that can accept focus.]] function UI.Window:getFocusables() local focusable = { } diff --git a/sys/modules/opus/ui/canvas.lua b/sys/modules/opus/ui/canvas.lua index d0d4ee9..cb46ede 100644 --- a/sys/modules/opus/ui/canvas.lua +++ b/sys/modules/opus/ui/canvas.lua @@ -355,7 +355,9 @@ 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) + local p = Region.new(1, 1, + self.parent.width + offset.x - self.x + 1, + self.parent.height + offset.y - self.y + 1) self.regions:andRegion(p) end diff --git a/sys/modules/opus/ui/components/Checkbox.lua b/sys/modules/opus/ui/components/Checkbox.lua index 54343e5..567833e 100644 --- a/sys/modules/opus/ui/components/Checkbox.lua +++ b/sys/modules/opus/ui/components/Checkbox.lua @@ -21,21 +21,20 @@ UI.Checkbox.defaults = { mouse_click = 'checkbox_toggle', } } +UI.Checkbox.inherits = { + labelBackgroundColor = 'backgroundColor', +} +function UI.Checkbox:postInit() + self.width = self.label and #self.label + 4 or 3 +end + function UI.Checkbox:draw() - local bg = self.backgroundColor - if self.focused then - bg = self.backgroundFocusColor - end - if type(self.value) == 'string' then - self.value = nil -- TODO: fix form - end - local text = string.format('[%s]', not self.value and ' ' or self.checkedIndicator) + local bg = self.focused and self.backgroundFocusColor or self.backgroundColor local x = 1 if self.label then - self:write(1, 1, self.label) + self:write(1, 1, self.label, self.labelBackgroundColor) x = #self.label + 2 end - self:write(x, 1, text, bg) self:write(x, 1, self.leftMarker, self.backgroundColor, self.textColor) self:write(x + 1, 1, not self.value and ' ' or self.checkedIndicator, bg) self:write(x + 2, 1, self.rightMarker, self.backgroundColor, self.textColor) @@ -46,11 +45,12 @@ function UI.Checkbox:focus() end function UI.Checkbox:setValue(v) - self.value = v + self.value = not not v end function UI.Checkbox:reset() self.value = false + self:draw() end function UI.Checkbox:eventHandler(event) @@ -63,7 +63,13 @@ function UI.Checkbox:eventHandler(event) end function UI.Checkbox.example() - return UI.Checkbox { - x = 2, y = 2, + return UI.Window { + ex1 = UI.Checkbox { + label = 'test', + x = 2, y = 2, + }, + ex2 = UI.Checkbox { + x = 2, y = 4, + }, } end diff --git a/sys/modules/opus/ui/components/DropMenuItem.lua b/sys/modules/opus/ui/components/DropMenuItem.lua index 09263da..ff28047 100644 --- a/sys/modules/opus/ui/components/DropMenuItem.lua +++ b/sys/modules/opus/ui/components/DropMenuItem.lua @@ -3,7 +3,6 @@ local UI = require('opus.ui') local colors = _G.colors ---[[-- DropMenuItem --]]-- UI.DropMenuItem = class(UI.Button) UI.DropMenuItem.defaults = { UIElement = 'DropMenuItem', diff --git a/sys/modules/opus/ui/components/Menu.lua b/sys/modules/opus/ui/components/Menu.lua index 8f1c837..0e18682 100644 --- a/sys/modules/opus/ui/components/Menu.lua +++ b/sys/modules/opus/ui/components/Menu.lua @@ -1,7 +1,6 @@ local class = require('opus.class') local UI = require('opus.ui') ---[[-- Menu --]]-- UI.Menu = class(UI.Grid) UI.Menu.defaults = { UIElement = 'Menu', diff --git a/sys/modules/opus/ui/components/MenuBar.lua b/sys/modules/opus/ui/components/MenuBar.lua index 217fccd..1b544cc 100644 --- a/sys/modules/opus/ui/components/MenuBar.lua +++ b/sys/modules/opus/ui/components/MenuBar.lua @@ -51,6 +51,7 @@ function UI.MenuBar:addButtons(buttons) x = self.lastx, width = #(button.text or 'button') + self.spacing, centered = false, + backgroundColor = self.backgroundColor, } self.lastx = self.lastx + buttonProperties.width UI:mergeProperties(buttonProperties, button) diff --git a/sys/modules/opus/ui/components/MenuItem.lua b/sys/modules/opus/ui/components/MenuItem.lua index 2f0efe8..61bc0b1 100644 --- a/sys/modules/opus/ui/components/MenuItem.lua +++ b/sys/modules/opus/ui/components/MenuItem.lua @@ -3,7 +3,6 @@ local UI = require('opus.ui') local colors = _G.colors ---[[-- MenuItem --]]-- UI.MenuItem = class(UI.Button) UI.MenuItem.defaults = { UIElement = 'MenuItem', diff --git a/sys/modules/opus/ui/components/Notification.lua b/sys/modules/opus/ui/components/Notification.lua index 7b11543..701733e 100644 --- a/sys/modules/opus/ui/components/Notification.lua +++ b/sys/modules/opus/ui/components/Notification.lua @@ -92,25 +92,26 @@ function UI.Notification:eventHandler(event) end function UI.Notification.example() - return UI.Window { - notify = UI.Notification { + return UI.ActiveLayer { + notify1 = UI.Notification { anchor = 'top', }, + notify2 = UI.Notification { }, button1 = UI.Button { x = 2, y = 3, - text = 'success', + text = 'example 1', event = 'test_success', }, button2 = UI.Button { x = 2, y = 5, - text = 'error', + text = 'example 2', event = 'test_error', }, eventHandler = function (self, event) if event.type == 'test_success' then - self.notify:success('Example text') + self.notify1:success('Example text') elseif event.type == 'test_error' then - self.notify:error('Example text', 0) + self.notify2:error('Example text', 0) end end, } diff --git a/sys/modules/opus/ui/components/ScrollingGrid.lua b/sys/modules/opus/ui/components/ScrollingGrid.lua index 93a35e6..06dd5b8 100644 --- a/sys/modules/opus/ui/components/ScrollingGrid.lua +++ b/sys/modules/opus/ui/components/ScrollingGrid.lua @@ -2,7 +2,6 @@ local class = require('opus.class') local UI = require('opus.ui') local Util = require('opus.util') ---[[-- ScrollingGrid --]]-- UI.ScrollingGrid = class(UI.Grid) UI.ScrollingGrid.defaults = { UIElement = 'ScrollingGrid', diff --git a/sys/modules/opus/ui/components/SlideOut.lua b/sys/modules/opus/ui/components/SlideOut.lua index 1e9558f..789220f 100644 --- a/sys/modules/opus/ui/components/SlideOut.lua +++ b/sys/modules/opus/ui/components/SlideOut.lua @@ -1,7 +1,6 @@ local class = require('opus.class') local UI = require('opus.ui') ---[[-- SlideOut --]]-- UI.SlideOut = class(UI.Window) UI.SlideOut.defaults = { UIElement = 'SlideOut', @@ -62,9 +61,12 @@ end function UI.SlideOut.example() -- for the transistion to work properly, the parent must have a canvas return UI.ActiveLayer { + y = 1, -- TODO: if this is set to anything greater than 1, then + -- the layer is not rendered in the correct location + -- a general issue in canvas layers backgroundColor = colors.cyan, button = UI.Button { - x = 2, y = 2, + x = 2, y = 5, text = 'show', }, slideOut = UI.SlideOut { diff --git a/sys/modules/opus/ui/components/Tab.lua b/sys/modules/opus/ui/components/Tab.lua index 2f86b2f..1e31de6 100644 --- a/sys/modules/opus/ui/components/Tab.lua +++ b/sys/modules/opus/ui/components/Tab.lua @@ -1,12 +1,9 @@ local class = require('opus.class') local UI = require('opus.ui') -local colors = _G.colors - UI.Tab = class(UI.ActiveLayer) UI.Tab.defaults = { UIElement = 'Tab', tabTitle = 'tab', - backgroundColor = colors.cyan, y = 2, } diff --git a/sys/modules/opus/ui/components/TabBar.lua b/sys/modules/opus/ui/components/TabBar.lua index 72e07f6..e684cae 100644 --- a/sys/modules/opus/ui/components/TabBar.lua +++ b/sys/modules/opus/ui/components/TabBar.lua @@ -2,13 +2,13 @@ local class = require('opus.class') local UI = require('opus.ui') local Util = require('opus.util') -local colors = _G.colors - UI.TabBar = class(UI.MenuBar) UI.TabBar.defaults = { UIElement = 'TabBar', buttonClass = 'TabBarMenuItem', - selectedBackgroundColor = colors.cyan, +} +UI.TabBar.inherits = { + selectedBackgroundColor = 'backgroundColor', } function UI.TabBar:enable() UI.MenuBar.enable(self) diff --git a/sys/modules/opus/ui/components/TabBarMenuItem.lua b/sys/modules/opus/ui/components/TabBarMenuItem.lua index 0a7799c..f9f549b 100644 --- a/sys/modules/opus/ui/components/TabBarMenuItem.lua +++ b/sys/modules/opus/ui/components/TabBarMenuItem.lua @@ -3,7 +3,6 @@ local UI = require('opus.ui') local colors = _G.colors ---[[-- TabBarMenuItem --]]-- UI.TabBarMenuItem = class(UI.Button) UI.TabBarMenuItem.defaults = { UIElement = 'TabBarMenuItem', @@ -13,6 +12,9 @@ UI.TabBarMenuItem.defaults = { unselectedBackgroundColor = colors.lightGray, backgroundColor = colors.lightGray, } +UI.TabBarMenuItem.inherits = { + selectedBackgroundColor = 'selectedBackgroundColor', +} function UI.TabBarMenuItem:draw() if self.selected then self.backgroundColor = self.selectedBackgroundColor diff --git a/sys/modules/opus/ui/components/Tabs.lua b/sys/modules/opus/ui/components/Tabs.lua index c9c0075..2b0c824 100644 --- a/sys/modules/opus/ui/components/Tabs.lua +++ b/sys/modules/opus/ui/components/Tabs.lua @@ -3,6 +3,7 @@ local UI = require('opus.ui') local Util = require('opus.util') UI.Tabs = class(UI.Window) +UI.Tabs.docs = { } UI.Tabs.defaults = { UIElement = 'Tabs', } @@ -37,6 +38,8 @@ function UI.Tabs:add(children) end end +UI.Tabs.docs.selectTab = [[selectTab(TAB) +Make to the passed tab active.]] function UI.Tabs:selectTab(tab) local menuItem = Util.find(self.tabBar.children, 'tabUid', tab.uid) if menuItem then diff --git a/sys/modules/opus/ui/components/TextArea.lua b/sys/modules/opus/ui/components/TextArea.lua index ea7540f..2b8c342 100644 --- a/sys/modules/opus/ui/components/TextArea.lua +++ b/sys/modules/opus/ui/components/TextArea.lua @@ -1,7 +1,6 @@ local class = require('opus.class') local UI = require('opus.ui') ---[[-- TextArea --]]-- UI.TextArea = class(UI.Viewport) UI.TextArea.defaults = { UIElement = 'TextArea', diff --git a/sys/modules/opus/ui/components/TextEntry.lua b/sys/modules/opus/ui/components/TextEntry.lua index 523208c..929cb3c 100644 --- a/sys/modules/opus/ui/components/TextEntry.lua +++ b/sys/modules/opus/ui/components/TextEntry.lua @@ -16,6 +16,7 @@ local function transform(directive) end UI.TextEntry = class(UI.Window) +UI.TextEntry.docs = { } UI.TextEntry.defaults = { UIElement = 'TextEntry', --value = '', @@ -92,6 +93,8 @@ function UI.TextEntry:draw() end end +UI.TextEntry.docs.reset = [[reset() +Clears the value and resets the cursor.]] function UI.TextEntry:reset() self.entry:reset() self.value = nil--'' diff --git a/sys/modules/opus/ui/components/Viewport.lua b/sys/modules/opus/ui/components/Viewport.lua index acb84cd..35cd0eb 100644 --- a/sys/modules/opus/ui/components/Viewport.lua +++ b/sys/modules/opus/ui/components/Viewport.lua @@ -3,7 +3,6 @@ local UI = require('opus.ui') local colors = _G.colors ---[[-- Viewport --]]-- UI.Viewport = class(UI.Window) UI.Viewport.defaults = { UIElement = 'Viewport', -- 2.49.1 From ffa412c59d158fcc2d0c7c42a0c7b569f37de5c0 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Mon, 18 Nov 2019 14:32:10 -0700 Subject: [PATCH 13/23] ui fixes --- sys/apps/Tasks.lua | 2 +- sys/apps/Welcome.lua | 44 ++--- sys/modules/opus/ui.lua | 170 ++------------------ sys/modules/opus/ui/canvas.lua | 37 +++-- sys/modules/opus/ui/components/Chooser.lua | 70 ++++---- sys/modules/opus/ui/components/Page.lua | 163 +++++++++++++++++++ sys/modules/opus/ui/components/SlideOut.lua | 9 +- sys/modules/opus/ui/transition.lua | 2 +- 8 files changed, 245 insertions(+), 252 deletions(-) create mode 100644 sys/modules/opus/ui/components/Page.lua diff --git a/sys/apps/Tasks.lua b/sys/apps/Tasks.lua index 3dbd395..cde082a 100644 --- a/sys/apps/Tasks.lua +++ b/sys/apps/Tasks.lua @@ -24,7 +24,7 @@ local page = UI.Page { values = kernel.routines, sortColumn = 'uid', autospace = true, - getDisplayValues = function(_, row) + getDisplayValues = function (_, row) local elapsed = os.clock()-row.timestamp return { uid = row.uid, diff --git a/sys/apps/Welcome.lua b/sys/apps/Welcome.lua index a25278f..980f27f 100644 --- a/sys/apps/Welcome.lua +++ b/sys/apps/Welcome.lua @@ -60,6 +60,12 @@ local page = UI.Page { x = 3, ex = -3, y = 4, ey = -3, value = string.format(labelIntro, Ansi.white), }, + validate = function (self) + if self.label.value then + os.setComputerLabel(self.label.value) + end + return true + end, }, password = UI.WizardPage { index = 3, @@ -73,23 +79,18 @@ local page = UI.Page { mask = true, shadowText = 'password', }, ---[[ - groupLabel = UI.Text { - x = 3, y = 3, - value = 'Group' - }, - group = UI.TextEntry { - x = 12, ex = -3, y = 3, - limit = 32, - shadowText = 'network group', - }, -]] intro = UI.TextArea { textColor = colors.yellow, inactive = true, x = 3, ex = -3, y = 5, ey = -3, value = string.format(passwordIntro, Ansi.white), }, + validate = function (self) + if type(self.newPass.value) == "string" and #self.newPass.value > 0 then + Security.updatePassword(SHA.compute(self.newPass.value)) + end + return true + end, }, packages = UI.WizardPage { index = 4, @@ -119,27 +120,6 @@ local page = UI.Page { notification = UI.Notification { }, } -function page.wizard.pages.label:validate() - if self.label.value then - os.setComputerLabel(self.label.value) - end - return true -end - -function page.wizard.pages.password:validate() - if type(self.newPass.value) == "string" and #self.newPass.value > 0 then - Security.updatePassword(SHA.compute(self.newPass.value)) - end - --[[ - if #self.group.value > 0 then - local config = Config.load('os') - config.group = self.group.value - Config.update('os', config) - end - ]] - return true -end - function page:eventHandler(event) if event.type == 'skip' then self.wizard:emit({ type = 'nextView' }) diff --git a/sys/modules/opus/ui.lua b/sys/modules/opus/ui.lua index 6e464ad..4ff0bea 100644 --- a/sys/modules/opus/ui.lua +++ b/sys/modules/opus/ui.lua @@ -1,4 +1,3 @@ -local Canvas = require('opus.ui.canvas') local class = require('opus.class') local Event = require('opus.event') local Input = require('opus.input') @@ -19,18 +18,18 @@ local textutils = _G.textutils the bottom up. Once reaching the top, setParent is called top down. On :init(), elements do not know the parent or can calculate sizing. -]] --- need to add offsets to this test -local function getPosition(element) - local x, y = 1, 1 - repeat - x = element.x + x - 1 - y = element.y + y - 1 - element = element.parent - until not element - return x, y -end + Calling order: + window:postInit() + at this point, the window has all default values set + window:setParent() + parent has been assigned + following are called: + window:layout() + sizing / positioning is performed + window:initChildren() + each child of window will get initialized +]] --[[-- Top Level Manager --]]-- local Manager = class() @@ -953,7 +952,7 @@ function UI.Window:addTransition(effect, args) if self.parent then args = args or { } if not args.x then -- not good - args.x, args.y = getPosition(self) + args.x, args.y = self.x, self.y -- getPosition(self) args.width = self.width args.height = self.height end @@ -1117,149 +1116,7 @@ function UI.Device:sync() end end ---[[-- Page (focus manager) --]]-- -UI.Page = class(UI.Window) -UI.Page.defaults = { - UIElement = 'Page', - accelerators = { - down = 'focus_next', - enter = 'focus_next', - tab = 'focus_next', - ['shift-tab' ] = 'focus_prev', - up = 'focus_prev', - }, - backgroundColor = colors.cyan, - textColor = colors.white, -} -function UI.Page:postInit() - self.parent = self.parent or UI.defaultDevice - self.__target = self - self.canvas = Canvas({ - x = 1, y = 1, width = self.parent.width, height = self.parent.height, - isColor = self.parent.isColor, - }) - self.canvas:clear(self.backgroundColor, self.textColor) -end - -function UI.Page:enable() - self.canvas.visible = true - UI.Window.enable(self) - - if not self.focused or not self.focused.enabled then - self:focusFirst() - end -end - -function UI.Page:disable() - self.canvas.visible = false - UI.Window.disable(self) -end - -function UI.Page:sync() - if self.enabled then - self.parent:sync() - end -end - -function UI.Page:capture(child) - self.__target = child -end - -function UI.Page:release(child) - if self.__target == child then - self.__target = self - end -end - -function UI.Page:pointToChild(x, y) - if self.__target == self then - return UI.Window.pointToChild(self, x, y) - end - x = x + self.offx - self.x + 1 - y = y + self.offy - self.y + 1 - return self.__target:pointToChild(x, y) -end - -function UI.Page:getFocusables() - if self.__target == self or self.__target.pageType ~= 'modal' then - return UI.Window.getFocusables(self) - end - return self.__target:getFocusables() -end - -function UI.Page:getFocused() - return self.focused -end - -function UI.Page:focusPrevious() - local function getPreviousFocus(focused) - local focusables = self:getFocusables() - local k = Util.contains(focusables, focused) - if k then - if k > 1 then - return focusables[k - 1] - end - return focusables[#focusables] - end - end - - local focused = getPreviousFocus(self.focused) - if focused then - self:setFocus(focused) - end -end - -function UI.Page:focusNext() - local function getNextFocus(focused) - local focusables = self:getFocusables() - local k = Util.contains(focusables, focused) - if k then - if k < #focusables then - return focusables[k + 1] - end - return focusables[1] - end - end - - local focused = getNextFocus(self.focused) - if focused then - self:setFocus(focused) - end -end - -function UI.Page:setFocus(child) - if not child or not child.focus then - return - end - - if self.focused and self.focused ~= child then - self.focused.focused = false - self.focused:focus() - self.focused:emit({ type = 'focus_lost', focused = child }) - end - - self.focused = child - if not child.focused then - child.focused = true - child:emit({ type = 'focus_change', focused = child }) - --self:emit({ type = 'focus_change', focused = child }) - end - - child:focus() -end - -function UI.Page:eventHandler(event) - if self.focused then - if event.type == 'focus_next' then - self:focusNext() - return true - elseif event.type == 'focus_prev' then - self:focusPrevious() - return true - end - end -end - +-- lazy load components local function loadComponents() local function load(name) local s, m = Util.run(_ENV, 'sys/modules/opus/ui/components/' .. name .. '.lua') @@ -1295,7 +1152,6 @@ end loadComponents() UI:loadTheme('usr/config/ui.theme') Util.merge(UI.Window.defaults, UI.theme.Window) -Util.merge(UI.Page.defaults, UI.theme.Page) UI:setDefaultDevice(UI.Device({ device = term.current() })) return UI diff --git a/sys/modules/opus/ui/canvas.lua b/sys/modules/opus/ui/canvas.lua index cb46ede..6fe12b1 100644 --- a/sys/modules/opus/ui/canvas.lua +++ b/sys/modules/opus/ui/canvas.lua @@ -9,6 +9,7 @@ local colors = _G.colors local Canvas = class() +Canvas.__visualize = false Canvas.colorPalette = { } Canvas.darkPalette = { } Canvas.grayscalePalette = { } @@ -303,7 +304,7 @@ end -- the array. function Canvas:__renderLayers(device, offset) if #self.layers > 0 then - self.regions = self.regions or Region.new(self.x, self.y, self.ex, self.ey) + self.regions = self.regions or Region.new(self.x + offset.x, self.y + offset.y, self.ex + offset.x, self.ey + offset.y) for i = 1, #self.layers do local canvas = self.layers[i] @@ -379,31 +380,29 @@ function Canvas:__punch(rect, offset) rect.ey + offset.y) end +-- performance can probably be improved by using one more buffer tied to the device function Canvas:__blitRect(device, src, tgt) src = src or { x = 1, y = 1, ex = self.ex - self.x + 1, ey = self.ey - self.y + 1 } tgt = tgt or self - --[[ - -- for visualizing updates on the screen - local drew - for i = 0, src.ey - src.y do - local line = self.lines[src.y + i + (self.offy or 0)] - if line and line.dirty then - drew = true - local t, fg, bg = line.text, line.fg, line.bg - if src.x > 1 or src.ex < self.ex then - t = _sub(t, src.x, src.ex) - fg = _rep(1, src.ex-src.x + 1) - bg = _rep(2, src.ex-src.x + 1) + -- for visualizing updates on the screen + if Canvas.__visualize then + local drew + local t = _rep(' ', src.ex-src.x + 1) + local bg = _rep(2, src.ex-src.x + 1) + for i = 0, src.ey - src.y do + local line = self.lines[src.y + i + (self.offy or 0)] + if line and line.dirty then + drew = true + device.setCursorPos(tgt.x, tgt.y + i) + device.blit(t, bg, bg) end - device.setCursorPos(tgt.x, tgt.y + i) - device.blit(t, fg, bg) + end + if drew then + local t = os.clock() + repeat until os.clock()-t > .2 end end - if drew then - os.sleep(.3) - end - ]] for i = 0, src.ey - src.y do local line = self.lines[src.y + i + (self.offy or 0)] if line and line.dirty then diff --git a/sys/modules/opus/ui/components/Chooser.lua b/sys/modules/opus/ui/components/Chooser.lua index 9698f6f..32fd3e2 100644 --- a/sys/modules/opus/ui/components/Chooser.lua +++ b/sys/modules/opus/ui/components/Chooser.lua @@ -14,6 +14,11 @@ UI.Chooser.defaults = { leftIndicator = UI.extChars and '\17' or '<', rightIndicator = UI.extChars and '\16' or '>', height = 1, + accelerators = { + space = 'choice_next', + right = 'choice_next', + left = 'choice_prev', + } } function UI.Chooser:setParent() if not self.width and not self.ex then @@ -29,16 +34,11 @@ function UI.Chooser:setParent() end function UI.Chooser:draw() - local bg = self.backgroundColor - if self.focused then - bg = self.backgroundFocusColor - end + local bg = self.focused and self.backgroundFocusColor or self.backgroundColor local fg = self.inactive and self.textInactiveColor or self.textColor local choice = Util.find(self.choices, 'value', self.value) - local value = self.nochoice - if choice then - value = choice.name - end + local value = choice and choice.name or self.nochoice + self:write(1, 1, self.leftIndicator, self.backgroundColor, colors.black) self:write(2, 1, ' ' .. Util.widthify(tostring(value), self.width-4) .. ' ', bg, fg) self:write(self.width, 1, self.rightIndicator, self.backgroundColor, colors.black) @@ -49,39 +49,37 @@ function UI.Chooser:focus() end function UI.Chooser:eventHandler(event) - if event.type == 'key' then - if event.key == 'right' or event.key == 'space' then - local _,k = Util.find(self.choices, 'value', self.value) - local choice - if not k then k = 0 end - if k and k < #self.choices then - choice = self.choices[k+1] - else - choice = self.choices[1] - end - self.value = choice.value - self:emit({ type = 'choice_change', value = self.value, element = self, choice = choice }) - self:draw() - return true - elseif event.key == 'left' then - local _,k = Util.find(self.choices, 'value', self.value) - local choice - if k and k > 1 then - choice = self.choices[k-1] - else - choice = self.choices[#self.choices] - end - self.value = choice.value - self:emit({ type = 'choice_change', value = self.value, element = self, choice = choice }) - self:draw() - return true + if event.type == 'choice_next' then + local _,k = Util.find(self.choices, 'value', self.value) + local choice + if not k then k = 0 end + if k and k < #self.choices then + choice = self.choices[k+1] + else + choice = self.choices[1] end + self.value = choice.value + self:emit({ type = 'choice_change', value = self.value, element = self, choice = choice }) + self:draw() + return true + elseif event.type == 'choice_prev' then + local _,k = Util.find(self.choices, 'value', self.value) + local choice + if k and k > 1 then + choice = self.choices[k-1] + else + choice = self.choices[#self.choices] + end + self.value = choice.value + self:emit({ type = 'choice_change', value = self.value, element = self, choice = choice }) + self:draw() + return true elseif event.type == 'mouse_click' or event.type == 'mouse_doubleclick' then if event.x == 1 then - self:emit({ type = 'key', key = 'left' }) + self:emit({ type = 'choice_prev' }) return true elseif event.x == self.width then - self:emit({ type = 'key', key = 'right' }) + self:emit({ type = 'choice_next' }) return true end end diff --git a/sys/modules/opus/ui/components/Page.lua b/sys/modules/opus/ui/components/Page.lua new file mode 100644 index 0000000..7fbaa0f --- /dev/null +++ b/sys/modules/opus/ui/components/Page.lua @@ -0,0 +1,163 @@ +local Canvas = require('opus.ui.canvas') +local class = require('opus.class') +local UI = require('opus.ui') +local Util = require('opus.util') + +local colors = _G.colors + +-- need to add offsets to this test +local function getPosition(element) + local x, y = 1, 1 + repeat + x = element.x + x - 1 + y = element.y + y - 1 + element = element.parent + until not element + return x, y +end + +UI.Page = class(UI.Window) +UI.Page.defaults = { + UIElement = 'Page', + accelerators = { + down = 'focus_next', + enter = 'focus_next', + tab = 'focus_next', + ['shift-tab' ] = 'focus_prev', + up = 'focus_prev', + }, + backgroundColor = colors.cyan, + textColor = colors.white, +} +function UI.Page:postInit() + self.parent = self.parent or UI.defaultDevice + self.__target = self + self.canvas = Canvas({ + x = 1, y = 1, width = self.parent.width, height = self.parent.height, + isColor = self.parent.isColor, + }) + self.canvas:clear(self.backgroundColor, self.textColor) +end + +function UI.Page:enable() + self.canvas.visible = true + UI.Window.enable(self) + + if not self.focused or not self.focused.enabled then + self:focusFirst() + end +end + +function UI.Page:disable() + self.canvas.visible = false + UI.Window.disable(self) +end + +function UI.Page:sync() + if self.enabled then + self.parent:sync() + end +end + +function UI.Page:capture(child) + self.__target = child +end + +function UI.Page:release(child) + if self.__target == child then + self.__target = self + end +end + +function UI.Page:pointToChild(x, y) + if self.__target == self then + return UI.Window.pointToChild(self, x, y) + end + local absX, absY = getPosition(self.__target) + + -- this is sketchy + x = x + self.offx - self.x - (absX - self.__target.x) + 1 + y = y + self.offy - self.y - (absY - self.__target.y) + 1 + + return self.__target:pointToChild(x, y) +end + +function UI.Page:getFocusables() + if self.__target == self or self.__target.pageType ~= 'modal' then + return UI.Window.getFocusables(self) + end + return self.__target:getFocusables() +end + +function UI.Page:getFocused() + return self.focused +end + +function UI.Page:focusPrevious() + local function getPreviousFocus(focused) + local focusables = self:getFocusables() + local k = Util.contains(focusables, focused) + if k then + if k > 1 then + return focusables[k - 1] + end + return focusables[#focusables] + end + end + + local focused = getPreviousFocus(self.focused) + if focused then + self:setFocus(focused) + end +end + +function UI.Page:focusNext() + local function getNextFocus(focused) + local focusables = self:getFocusables() + local k = Util.contains(focusables, focused) + if k then + if k < #focusables then + return focusables[k + 1] + end + return focusables[1] + end + end + + local focused = getNextFocus(self.focused) + if focused then + self:setFocus(focused) + end +end + +function UI.Page:setFocus(child) + if not child or not child.focus then + return + end + + if self.focused and self.focused ~= child then + self.focused.focused = false + self.focused:focus() + self.focused:emit({ type = 'focus_lost', focused = child, unfocused = self.focused }) + end + + self.focused = child + if not child.focused then + child.focused = true + child:emit({ type = 'focus_change', focused = child }) + --self:emit({ type = 'focus_change', focused = child }) + end + + child:focus() +end + +function UI.Page:eventHandler(event) + if self.focused then + if event.type == 'focus_next' then + self:focusNext() + return true + elseif event.type == 'focus_prev' then + self:focusPrevious() + return true + end + end +end diff --git a/sys/modules/opus/ui/components/SlideOut.lua b/sys/modules/opus/ui/components/SlideOut.lua index 789220f..479be4b 100644 --- a/sys/modules/opus/ui/components/SlideOut.lua +++ b/sys/modules/opus/ui/components/SlideOut.lua @@ -61,17 +61,14 @@ end function UI.SlideOut.example() -- for the transistion to work properly, the parent must have a canvas return UI.ActiveLayer { - y = 1, -- TODO: if this is set to anything greater than 1, then - -- the layer is not rendered in the correct location - -- a general issue in canvas layers - backgroundColor = colors.cyan, + y = 2, button = UI.Button { x = 2, y = 5, text = 'show', }, slideOut = UI.SlideOut { - backgroundColor = colors.yellow, - y = -4, height = 4, + backgroundColor = _G.colors.yellow, + y = -4, height = 4, x = 3, ex = -3, button = UI.Button { x = 2, y = 2, text = 'hide', diff --git a/sys/modules/opus/ui/transition.lua b/sys/modules/opus/ui/transition.lua index 4448760..f8cee0b 100644 --- a/sys/modules/opus/ui/transition.lua +++ b/sys/modules/opus/ui/transition.lua @@ -39,7 +39,7 @@ function Transition.expandUp(args) local easing = args.easing or 'linear' local pos = { y = args.ey + 1 } local tween = Tween.new(ticks, pos, { y = args.y }, easing) - +_syslog(args) args.canvas:move(args.x, pos.y) return function() -- 2.49.1 From 1e675a2e3523411b45655e450be62b137f41230a Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Sun, 1 Dec 2019 13:25:26 -0700 Subject: [PATCH 14/23] revert multiple sub-canvas mouse click --- sys/modules/opus/ui/components/Page.lua | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sys/modules/opus/ui/components/Page.lua b/sys/modules/opus/ui/components/Page.lua index 7fbaa0f..7bc8e70 100644 --- a/sys/modules/opus/ui/components/Page.lua +++ b/sys/modules/opus/ui/components/Page.lua @@ -73,12 +73,17 @@ function UI.Page:pointToChild(x, y) if self.__target == self then return UI.Window.pointToChild(self, x, y) end + x = x + self.offx - self.x + 1 + y = y + self.offy - self.y + 1 +--[[ + -- this is supposed to fix when there are multiple sub canvases local absX, absY = getPosition(self.__target) - - -- this is sketchy - x = x + self.offx - self.x - (absX - self.__target.x) + 1 - y = y + self.offy - self.y - (absY - self.__target.y) + 1 - + if self.__target.canvas then + x = x - (self.__target.canvas.x - self.__target.x) + y = y - (self.__target.canvas.y - self.__target.y) + _syslog({'raw', self.__target.canvas.y, self.__target.y}) + end + ]] return self.__target:pointToChild(x, y) end -- 2.49.1 From 424fff784211d88a5f1d59debf6832d4796449e8 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Thu, 5 Dec 2019 13:44:35 -0700 Subject: [PATCH 15/23] apparently read was added to fs.open "r" mode in 2017 --- sys/modules/opus/fs/ramfs.lua | 4 ++++ sys/modules/opus/fs/urlfs.lua | 4 ++++ sys/modules/opus/ui/transition.lua | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/sys/modules/opus/fs/ramfs.lua b/sys/modules/opus/fs/ramfs.lua index 1ed2f7a..a516d80 100644 --- a/sys/modules/opus/fs/ramfs.lua +++ b/sys/modules/opus/fs/ramfs.lua @@ -77,6 +77,10 @@ function ramfs.open(node, fn, fl) local ctr = 0 local lines return { + read = function() + ctr = ctr + 1 + return node.contents:sub(ctr, ctr) + end, readLine = function() if not lines then lines = Util.split(node.contents) diff --git a/sys/modules/opus/fs/urlfs.lua b/sys/modules/opus/fs/urlfs.lua index 960806e..3595cb3 100644 --- a/sys/modules/opus/fs/urlfs.lua +++ b/sys/modules/opus/fs/urlfs.lua @@ -74,6 +74,10 @@ function urlfs.open(node, fn, fl) if fl == 'r' then return { + read = function() + ctr = ctr + 1 + return c:sub(ctr, ctr) + end, readLine = function() if not lines then lines = Util.split(c) diff --git a/sys/modules/opus/ui/transition.lua b/sys/modules/opus/ui/transition.lua index f8cee0b..4448760 100644 --- a/sys/modules/opus/ui/transition.lua +++ b/sys/modules/opus/ui/transition.lua @@ -39,7 +39,7 @@ function Transition.expandUp(args) local easing = args.easing or 'linear' local pos = { y = args.ey + 1 } local tween = Tween.new(ticks, pos, { y = args.y }, easing) -_syslog(args) + args.canvas:move(args.x, pos.y) return function() -- 2.49.1 From 31f43067bf747ceeef3aa6d628357818837bc8fe Mon Sep 17 00:00:00 2001 From: Anavrins Date: Fri, 6 Dec 2019 20:14:18 -0500 Subject: [PATCH 16/23] Change how Sniff.lua detects modem --- sys/apps/Sniff.lua | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sys/apps/Sniff.lua b/sys/apps/Sniff.lua index 2bda4f0..3b4ca9c 100644 --- a/sys/apps/Sniff.lua +++ b/sys/apps/Sniff.lua @@ -307,14 +307,16 @@ end function page:enable() modemConfig.modems = {} - peripheral.find('modem', function(side, dev) - modemConfig.modems[side] = { - type = dev.isWireless() and 'Wireless' or 'Wired', - side = side, - openChannels = { }, - device = dev, - loaded = false - } + Util.each(_G.device, function(dev) + if dev.type == "modem" then + modemConfig.modems[dev.side] = { + type = dev.isWireless() and 'Wireless' or 'Wired', + side = dev.side, + openChannels = { }, + device = dev, + loaded = false + } + end end) modemConfig.currentModem = device.wireless_modem and modemConfig.modems[device.wireless_modem.side] or -- 2.49.1 From 28b2ba3386056e1422dfbaef7a5fdd32556cc71c Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Sat, 7 Dec 2019 12:04:58 -0700 Subject: [PATCH 17/23] tweaks --- sys/apps/Help.lua | 100 ++++++++++++++++++--------------------- sys/apps/Overview.lua | 6 +++ sys/autorun/hotkeys.lua | 51 ++++++++------------ sys/autorun/log.lua | 19 +++----- sys/autorun/upgraded.lua | 4 ++ sys/modules/opus/ui.lua | 6 +-- 6 files changed, 85 insertions(+), 101 deletions(-) diff --git a/sys/apps/Help.lua b/sys/apps/Help.lua index 8bae671..3702371 100644 --- a/sys/apps/Help.lua +++ b/sys/apps/Help.lua @@ -8,12 +8,10 @@ UI:configure('Help', ...) local topics = { } for _,topic in pairs(help.topics()) do - if help.lookup(topic) then - table.insert(topics, { name = topic }) - end + table.insert(topics, { name = topic, lname = topic:lower() }) end -local page = UI.Page { +UI:addPage('main', UI.Page { labelText = UI.Text { x = 3, y = 2, value = 'Search', @@ -21,7 +19,6 @@ local page = UI.Page { filter = UI.TextEntry { x = 10, y = 2, ex = -3, limit = 32, - transform = 'lowercase', }, grid = UI.ScrollingGrid { y = 4, @@ -29,15 +26,44 @@ local page = UI.Page { columns = { { heading = 'Topic', key = 'name' }, }, - sortColumn = 'name', + sortColumn = 'lname', }, accelerators = { [ 'control-q' ] = 'quit', enter = 'grid_select', }, -} + eventHandler = function(self, event) + if event.type == 'quit' then + UI:quit() -local topicPage = UI.Page { + elseif event.type == 'grid_select' then + if self.grid:getSelected() then + local name = self.grid:getSelected().name + + UI:setPage('topic', name) + end + + elseif event.type == 'text_change' then + if not event.text then + self.grid.values = topics + else + self.grid.values = { } + for _,f in pairs(topics) do + if string.find(f.lname, event.text:lower()) then + table.insert(self.grid.values, f) + end + end + end + self.grid:update() + self.grid:setIndex(1) + self.grid:draw() + else + return UI.Page.eventHandler(self, event) + end + end, +}) + +UI:addPage('topic', UI.Page { backgroundColor = colors.black, titleBar = UI.TitleBar { title = 'text', @@ -51,54 +77,22 @@ local topicPage = UI.Page { [ 'control-q' ] = 'back', backspace = 'back', }, -} + enable = function(self, name) + local f = help.lookup(name) -function topicPage:enable(name) - local f = help.lookup(name) + self.titleBar.title = name + self.helpText:setText(f and Util.readFile(f) or 'No help available for ' .. name) - self.titleBar.title = name - self.helpText:setText(f and Util.readFile(f) or 'No help available for ' .. name) - - return UI.Page.enable(self) -end - -function topicPage:eventHandler(event) - if event.type == 'back' then - UI:setPage(page) - end - return UI.Page.eventHandler(self, event) -end - -function page:eventHandler(event) - if event.type == 'quit' then - UI:exitPullEvents() - - elseif event.type == 'grid_select' then - if self.grid:getSelected() then - local name = self.grid:getSelected().name - - UI:setPage(topicPage, name) + return UI.Page.enable(self) + end, + eventHandler = function(self, event) + if event.type == 'back' then + UI:setPage('main') end - - elseif event.type == 'text_change' then - if not event.text then - self.grid.values = topics - else - self.grid.values = { } - for _,f in pairs(topics) do - if string.find(f.name, event.text) then - table.insert(self.grid.values, f) - end - end - end - self.grid:update() - self.grid:setIndex(1) - self.grid:draw() - else return UI.Page.eventHandler(self, event) - end -end + end, +}) local args = Util.parse(...) -UI:setPage(args[1] and topicPage or page, args[1]) -UI:pullEvents() +UI:setPage(args[1] and 'topic' or 'main', args[1]) +UI:start() diff --git a/sys/apps/Overview.lua b/sys/apps/Overview.lua index 92c09bf..b4b524f 100644 --- a/sys/apps/Overview.lua +++ b/sys/apps/Overview.lua @@ -27,6 +27,12 @@ local DEFAULT_ICON = NFT.parse("\0308\0317\153\153\153\153\153\ \0307\0318\153\153\153\153\153\ \0308\0317\153\153\153\153\153") +-- overview +local uid = _ENV.multishell.getCurrent() +device.keyboard.addHotkey('control-o', function() + _ENV.multishell.setFocus(uid) +end) + UI:configure('Overview', ...) local config = { diff --git a/sys/autorun/hotkeys.lua b/sys/autorun/hotkeys.lua index cbd93bf..ab591e0 100644 --- a/sys/autorun/hotkeys.lua +++ b/sys/autorun/hotkeys.lua @@ -4,58 +4,45 @@ local kernel = _G.kernel local keyboard = _G.device.keyboard local multishell = _ENV.multishell -if not multishell or not multishell.getTabs then - return -end - --- overview -keyboard.addHotkey('control-o', function() - for _,tab in pairs(multishell.getTabs()) do - if tab.isOverview then - multishell.setFocus(tab.uid) +if multishell and multishell.getTabs then + -- restart tab + keyboard.addHotkey('control-backspace', function() + local tab = kernel.getFocused() + if tab and not tab.noTerminate then + multishell.terminate(tab.uid) + multishell.openTab({ + path = tab.path, + env = tab.env, + args = tab.args, + focused = true, + }) end - end -end) - --- restart tab -keyboard.addHotkey('control-backspace', function() - local uid = multishell.getFocus() - local tab = kernel.find(uid) - if not tab.isOverview then - multishell.terminate(uid) - multishell.openTab({ - path = tab.path, - env = tab.env, - args = tab.args, - focused = true, - }) - end -end) + end) +end -- next tab keyboard.addHotkey('control-tab', function() - local tabs = multishell.getTabs() local visibleTabs = { } - local currentTabId = multishell.getFocus() + local currentTab = kernel.getFocused() local function compareTab(a, b) return a.uid < b.uid end - for _,tab in Util.spairs(tabs, compareTab) do + for _,tab in Util.spairs(kernel.routines, compareTab) do if not tab.hidden and not tab.noFocus then table.insert(visibleTabs, tab) end end for k,tab in ipairs(visibleTabs) do - if tab.uid == currentTabId then + if tab.uid == currentTab.uid then if k < #visibleTabs then - multishell.setFocus(visibleTabs[k + 1].uid) + kernel.raise(visibleTabs[k + 1].uid) return end end end if #visibleTabs > 0 then - multishell.setFocus(visibleTabs[1].uid) + kernel.raise(visibleTabs[1].uid) end end) diff --git a/sys/autorun/log.lua b/sys/autorun/log.lua index 91bb193..5e2b5e7 100644 --- a/sys/autorun/log.lua +++ b/sys/autorun/log.lua @@ -50,16 +50,9 @@ local function systemLog() keyboard.removeHotkey('control-d') end -if multishell and multishell.openTab then - multishell.openTab({ - title = 'System Log', - fn = systemLog, - noTerminate = true, - hidden = true, - }) -else - kernel.run({ - title = 'Syslog', - fn = systemLog, - }) -end +kernel.run({ + title = 'System Log', + fn = systemLog, + noTerminate = true, + hidden = true, +}) diff --git a/sys/autorun/upgraded.lua b/sys/autorun/upgraded.lua index 5922c3a..141bf1d 100644 --- a/sys/autorun/upgraded.lua +++ b/sys/autorun/upgraded.lua @@ -18,3 +18,7 @@ deleteIfExists('sys/autorun/gpshost.lua') deleteIfExists('sys/apps/network/redserver.lua') deleteIfExists('sys/apis') deleteIfExists('sys/autorun/apps.lua') +deleteIfExists('sys/init/6.tl3.lua') + +-- remove this file +deleteIfExists('sys/autorun/upgraded.lua') \ No newline at end of file diff --git a/sys/modules/opus/ui.lua b/sys/modules/opus/ui.lua index 4ff0bea..c627005 100644 --- a/sys/modules/opus/ui.lua +++ b/sys/modules/opus/ui.lua @@ -388,9 +388,9 @@ function Manager:pullEvents(...) end end -function Manager:exitPullEvents() - Event.exitPullEvents() -end +Manager.exitPullEvents = Event.exitPullEvents +Manager.quit = Event.exitPullEvents +Manager.start = Manager.pullEvents local UI = Manager() -- 2.49.1 From 6204c46cc4971f800cb3ca8a4759dcb868ae5cd7 Mon Sep 17 00:00:00 2001 From: Anavrins Date: Wed, 11 Dec 2019 11:18:02 -0500 Subject: [PATCH 18/23] Fix empty TextEntry in cloud config --- sys/apps/system/cloud.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/apps/system/cloud.lua b/sys/apps/system/cloud.lua index 221c828..66078f6 100644 --- a/sys/apps/system/cloud.lua +++ b/sys/apps/system/cloud.lua @@ -42,7 +42,7 @@ To obtain a key, visit: function tab:eventHandler(event) if event.type == 'update_key' then - if #self.key.value > 0 then + if self.key.value then config.key = self.key.value else config.key = nil -- 2.49.1 From 9e3cf50ccc153346e675233fe65fa4fab67fcb2f Mon Sep 17 00:00:00 2001 From: Anavrins Date: Wed, 11 Dec 2019 11:20:12 -0500 Subject: [PATCH 19/23] socket.lua: Option to pass user generated keypairs --- sys/modules/opus/socket.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sys/modules/opus/socket.lua b/sys/modules/opus/socket.lua index 8151855..b126643 100644 --- a/sys/modules/opus/socket.lua +++ b/sys/modules/opus/socket.lua @@ -126,7 +126,11 @@ function Socket.connect(host, port, options) local socket = newSocket(host == os.getComputerID()) socket.dhost = tonumber(host) - socket.privKey, socket.pubKey = network.getKeyPair() + if options and options.keypair then + socket.privKey, socket.pubKey = unpack(options.keypair) + else + socket.privKey, socket.pubKey = network.getKeyPair() + end local identifier = options and options.identifier or Security.getIdentifier() socket.transmit(port, socket.sport, { -- 2.49.1 From cc80e084073f2c890cef6c1c7dabeff1453682ff Mon Sep 17 00:00:00 2001 From: Anavrins Date: Wed, 11 Dec 2019 11:38:12 -0500 Subject: [PATCH 20/23] gps.lua: Added nil and nan checks --- sys/modules/opus/gps.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/modules/opus/gps.lua b/sys/modules/opus/gps.lua index 0ca7a66..8e85977 100644 --- a/sys/modules/opus/gps.lua +++ b/sys/modules/opus/gps.lua @@ -98,7 +98,7 @@ function GPS.trilaterate(tFixes) if pos2 then pos1, pos2 = narrow(pos1, pos2, tFixes[1]) end - if not pos2 then + if not pos2 and pos1 and not (pos1.x ~= pos1.x) then return pos1, attemps end end -- 2.49.1 From 942f0bda92f0aac48bf157ebef9a2c79791a294a Mon Sep 17 00:00:00 2001 From: Anavrins Date: Fri, 27 Dec 2019 01:11:36 -0500 Subject: [PATCH 21/23] GPS overhaul Changes how GPS works to avoid returning ambiguous coordinates and nan errors --- sys/modules/opus/gps.lua | 76 ++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 11 deletions(-) diff --git a/sys/modules/opus/gps.lua b/sys/modules/opus/gps.lua index 8e85977..3b0ae74 100644 --- a/sys/modules/opus/gps.lua +++ b/sys/modules/opus/gps.lua @@ -1,17 +1,71 @@ local Util = require('opus.util') local GPS = { } +GPS.CHANNEL_GPS = 65534 local device = _G.device -local gps = _G.gps +local vector = _G.vector function GPS.locate(timeout, debug) - local pt = { } - timeout = timeout or 10 - pt.x, pt.y, pt.z = gps.locate(timeout, debug) - if pt.x then - return pt + if not device.wireless_modem then + if debug then + print('No wireless modem attached') + end + return nil end + + if debug then + print('Finding position...') + end + + local modem = device.wireless_modem + local closeChannel = false + local selfID = os.getComputerID() + if not modem.isOpen(selfID) then + modem.open(selfID) + closeChannel = true + end + + modem.transmit(GPS.CHANNEL_GPS, selfID, "PING") + + local fixes = {} + local pos = nil + local timer = os.startTimer(timeout or 1) + while true do + local e, side, chan, reply, msg, dist = os.pullEvent() + if e == "modem_message" then + if side == modem.side and chan == selfID and reply == GPS.CHANNEL_GPS and dist then + if type(msg) == "table" and #msg == 3 and tonumber(msg[1]) and tonumber(msg[2]) and tonumber(msg[3]) then + local fix = { + position = vector.new(unpack(msg)), + distance = dist, + } + if debug then + print(fix.distance..' meters from '..fix.position:tostring()) + end + if fix.distance == 0 then + pos = fix.position + else + fixes[#fixes+1] = fix + if #fixes > 3 then + pos = GPS.trilaterate(fixes) + if pos then break end + end + end + end + end + elseif e == "timer" and side == timer then + break + end + end + + if closeChannel then + modem.close(selfID) + end + if debug then + print("Position is "..pos.x..","..pos.y..","..pos.z) + end + return vector.new(pos.x, pos.y, pos.z) end function GPS.isAvailable() @@ -66,26 +120,26 @@ local function trilaterate(A, B, C) local result1 = result + (ez * z) local result2 = result - (ez * z) - local rounded1, rounded2 = result1:round(), result2:round() + local rounded1, rounded2 = result1:round(0.01), result2:round(0.01) if rounded1.x ~= rounded2.x or rounded1.y ~= rounded2.y or rounded1.z ~= rounded2.z then return rounded1, rounded2 else return rounded1 end end - return result:round() + return result:round(0.01) end local function narrow( p1, p2, fix ) local dist1 = math.abs( (p1 - fix.position):length() - fix.distance ) local dist2 = math.abs( (p2 - fix.position):length() - fix.distance ) - if math.abs(dist1 - dist2) < 0.05 then + if math.abs(dist1 - dist2) < 0.01 then return p1, p2 elseif dist1 < dist2 then - return p1:round() + return p1:round(0.01) else - return p2:round() + return p2:round(0.01) end end -- end stock gps api -- 2.49.1 From 0fd349a48752cf344a44f3b873858ca88eb94401 Mon Sep 17 00:00:00 2001 From: Anavrins Date: Wed, 15 Jan 2020 00:12:29 -0500 Subject: [PATCH 22/23] Fix wrong branch name this also fixes packages loading on master-1.8 --- sys/boot/opus.boot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/boot/opus.boot b/sys/boot/opus.boot index 1ed1de8..fbf23a0 100644 --- a/sys/boot/opus.boot +++ b/sys/boot/opus.boot @@ -19,7 +19,7 @@ local function run(file, ...) end _G._syslog = function() end -_G.OPUS_BRANCH = 'master' +_G.OPUS_BRANCH = 'master-1.8' -- Install require shim _G.requireInjector = run('sys/modules/opus/injector.lua') -- 2.49.1 From c99a8990696077d58622dd4ad5734ccca803f80a Mon Sep 17 00:00:00 2001 From: Wojbie Date: Sun, 9 Feb 2020 15:09:42 +0100 Subject: [PATCH 23/23] Update git.lua to use headers authorization. --- sys/modules/opus/git.lua | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sys/modules/opus/git.lua b/sys/modules/opus/git.lua index da18ecf..055fe8b 100644 --- a/sys/modules/opus/git.lua +++ b/sys/modules/opus/git.lua @@ -3,10 +3,11 @@ local Util = require('opus.util') local TREE_URL = 'https://api.github.com/repos/%s/%s/git/trees/%s?recursive=1' local FILE_URL = 'https://raw.githubusercontent.com/%s/%s/%s/%s' +local TREE_HEADERS = {} local git = { } if _G._GIT_API_KEY then - TREE_URL = TREE_URL .. '&access_token=' .. _G._GIT_API_KEY + TREE_HEADERS.Authorization = 'token ' .. _G._GIT_API_KEY end local fs = _G.fs @@ -26,8 +27,10 @@ function git.list(repository) local function getContents() local dataUrl = string.format(TREE_URL, user, repo, branch) - local contents = Util.download(dataUrl) - if contents then + local contents, msg = Util.httpGet(dataUrl,TREE_HEADERS) + if not contents then + error(_sformat('Failed to download %s\n%s', dataUrl, msg), 2) + else return json.decode(contents) end end -- 2.49.1