diff --git a/sys/apis/ui.lua b/sys/apis/ui.lua index 098a56d..d97df26 100644 --- a/sys/apis/ui.lua +++ b/sys/apis/ui.lua @@ -317,6 +317,7 @@ end function Manager:setActivePage(page) page.parent.currentPage = page + page.parent.canvas = page.canvas end function Manager:setPage(pageOrName, ...) @@ -330,7 +331,6 @@ function Manager:setPage(pageOrName, ...) if page == currentPage then page:draw() else - local needSync if currentPage then if currentPage.focused then currentPage.focused.focused = false @@ -338,20 +338,16 @@ function Manager:setPage(pageOrName, ...) end currentPage:disable() page.previousPage = currentPage - else - needSync = true end self:setActivePage(page) - page:clear(page.backgroundColor) + --page:clear(page.backgroundColor) page:enable(...) page:draw() if page.focused then page.focused.focused = true page.focused:focus() end - if needSync then - page:sync() -- first time a page has been set - end + page:sync() end end @@ -607,12 +603,10 @@ function UI.Window:setTextScale(textScale) end function UI.Window:clear(bg, fg) - if self.enabled then - if self.canvas then - self.canvas:clear(bg or self.backgroundColor, fg or self.textColor) - else - self:clearArea(1 + self.offx, 1 + self.offy, self.width, self.height, bg) - end + if self.canvas then + self.canvas:clear(bg or self.backgroundColor, fg or self.textColor) + else + self:clearArea(1 + self.offx, 1 + self.offy, self.width, self.height, bg) end end @@ -630,18 +624,17 @@ function UI.Window:clearArea(x, y, width, height, bg) end function UI.Window:write(x, y, text, bg, tc) - if self.enabled then - bg = bg or self.backgroundColor - tc = tc or self.textColor - x = x - self.offx - y = y - self.offy - if y <= self.height and y > 0 then - if self.canvas then - self.canvas:write(x, y, text, bg, tc) - else - self.parent:write( - self.x + x - 1, self.y + y - 1, tostring(text), bg, tc) - end + bg = bg or self.backgroundColor + tc = tc or self.textColor + -- TODO: get rid of offx/y - scroll canvas instead + x = x - self.offx + y = y - self.offy + if y <= self.height and y > 0 then + if self.canvas then + self.canvas:write(x, y, text, bg, tc) + else + self.parent:write( + self.x + x - 1, self.y + y - 1, tostring(text), bg, tc) end end end @@ -933,12 +926,6 @@ function UI.Device:postInit() self.isColor = self.device.isColor() - self.canvas = Canvas({ - x = 1, y = 1, width = self.width, height = self.height, - isColor = self.isColor, - }) - self.canvas:clear(self.backgroundColor, self.textColor) - UI.devices[self.device.side or 'terminal'] = self end @@ -946,6 +933,7 @@ function UI.Device:resize() self.device.setTextScale(self.textScale) self.width, self.height = self.device.getSize() self.lines = { } + -- TODO: resize all pages added to this device self.canvas:resize(self.width, self.height) self.canvas:clear(self.backgroundColor, self.textColor) end @@ -997,11 +985,13 @@ function UI.Device:addTransition(effect, args) end function UI.Device:runTransitions(transitions, canvas) + --[[ for _,t in ipairs(transitions) do canvas:punch(t.args) -- punch out the effect areas end canvas:blitClipped(self.device) -- and blit the remainder canvas:reset() + ]] while true do for _,k in ipairs(Util.keys(transitions)) do @@ -1028,10 +1018,9 @@ function UI.Device:sync() self.device.setCursorBlink(false) end + self.canvas:render(self.device) if transitions then self:runTransitions(transitions, self.canvas) - else - self.canvas:render(self.device) end if self:getCursorBlink() then @@ -1126,16 +1115,23 @@ UI.Page.defaults = { 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:setParent() UI.Window.setParent(self) + --[[ if self.z then self.canvas = self:addLayer(self.backgroundColor, self.textColor) self.canvas:clear(self.backgroundColor, self.textColor) else self.canvas = self.parent.canvas end + ]] end function UI.Page:enable() @@ -1154,6 +1150,12 @@ function UI.Page:disable() 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 @@ -2293,9 +2295,9 @@ function UI.Tabs:eventHandler(event) if event.type == 'tab_change' then local tab = self:find(event.tab.tabUid) if event.current > event.last then - tab:addTransition('slideLeft') + self.transitionHint = 'slideLeft' else - tab:addTransition('slideRight') + self.transitionHint = 'slideRight' end for _,child in pairs(self.children) do @@ -2310,6 +2312,30 @@ function UI.Tabs:eventHandler(event) end end +--[[-- Tab --]]-- +UI.Tab = class(UI.Window) +UI.Tab.defaults = { + UIElement = 'Tab', + tabTitle = 'tab', + backgroundColor = colors.cyan, +} +function UI.Tab:setParent() + UI.Window.setParent(self) + self.canvas = self:addLayer() +end + +function UI.Tab:enable(...) + self.canvas:setVisible(true) + UI.Window.enable(self, ...) + self:addTransition(self.parent.transitionHint or 'slideLeft') + self:focusFirst() +end + +function UI.Tab:disable() + self.canvas:setVisible(false) + UI.Window.disable(self) +end + --[[-- Wizard --]]-- UI.Wizard = class(UI.Window) UI.Wizard.defaults = { @@ -3047,7 +3073,7 @@ function UI.Chooser:eventHandler(event) end end ---[[-- Chooser --]]-- +--[[-- Checkbox --]]-- UI.Checkbox = class(UI.Window) UI.Checkbox.defaults = { UIElement = 'Checkbox', @@ -3243,6 +3269,7 @@ UI.Form.defaults = { values = { }, margin = 2, event = 'form_complete', + cancelEvent = 'form_cancel', } function UI.Form:postInit() self:createForm() @@ -3319,7 +3346,7 @@ function UI.Form:createForm() table.insert(self.children, UI.Button { y = -self.margin, x = -7 - self.margin, text = 'Cancel', - event = 'form_cancel', + event = self.cancelEvent, }) end end @@ -3346,6 +3373,7 @@ function UI.Form:save() local s, m = self:validateField(child) if not s then self:setFocus(child) + Sound.play('entity.villager.no', .5) self:emit({ type = 'form_invalid', message = m, field = child }) return false end @@ -3372,7 +3400,7 @@ function UI.Form:eventHandler(event) if not self:save() then return false end - self:emit({ type = self.event, UIElement = self }) + self:emit({ type = self.event, UIElement = self, values = self.values }) else return UI.Window.eventHandler(self, event) end @@ -3380,49 +3408,38 @@ function UI.Form:eventHandler(event) end --[[-- Dialog --]]-- -UI.Dialog = class(UI.Page) +UI.Dialog = class(UI.SlideOut) UI.Dialog.defaults = { UIElement = 'Dialog', - x = 7, - y = 4, - z = 2, height = 7, textColor = colors.black, backgroundColor = colors.white, + okEvent ='dialog_ok', + cancelEvent = 'dialog_cancel', } function UI.Dialog:postInit() - self.titleBar = UI.TitleBar({ previousPage = true, title = self.title }) + self.y = -self.height + self.titleBar = UI.TitleBar({ event = self.cancelEvent, title = self.title }) end -function UI.Dialog:setParent() - if not self.width then - self.width = self.parent.width - 11 - end - if self.width > self.parent.width then - self.width = self.parent.width - end - self.x = math.floor((self.parent.width - self.width) / 2) + 1 - self.y = math.floor((self.parent.height - self.height) / 2) + 1 - UI.Page.setParent(self) +function UI.Dialog:show(...) + local canvas = self.parent:getCanvas() + self.oldPalette = canvas.palette + canvas:applyPalette(Canvas.darkPalette) + UI.SlideOut.show(self, ...) end -function UI.Dialog:disable() - self.previousPage.canvas.palette = self.oldPalette - UI.Page.disable(self) -end - -function UI.Dialog:enable(...) - self.oldPalette = self.previousPage.canvas.palette - self.previousPage.canvas:applyPalette(Canvas.darkPalette) - self:addTransition('grow') - UI.Page.enable(self, ...) +function UI.Dialog:hide(...) + self.parent:getCanvas().palette = self.oldPalette + UI.SlideOut.hide(self, ...) + self.parent:draw() end function UI.Dialog:eventHandler(event) - if event.type == 'cancel' then - UI:setPreviousPage() + if event.type == 'dialog_cancel' then + self:hide() end - return UI.Page.eventHandler(self, event) + return UI.SlideOut.eventHandler(self, event) end --[[-- Image --]]-- diff --git a/sys/apis/ui/transition.lua b/sys/apis/ui/transition.lua index 16e2127..f6c7af3 100644 --- a/sys/apis/ui/transition.lua +++ b/sys/apis/ui/transition.lua @@ -7,24 +7,14 @@ function Transition.slideLeft(args) local easing = args.easing or 'outQuint' local pos = { x = args.ex } local tween = Tween.new(ticks, pos, { x = args.x }, easing) - local lastScreen = args.canvas:copy() + + args.canvas:move(pos.x, args.canvas.y) return function(device) local finished = tween:update(1) - local x = math.floor(pos.x) - lastScreen:dirty() - lastScreen:blit(device, { - x = args.ex - x + args.x, - y = args.y, - ex = args.ex, - ey = args.ey }, - { x = args.x, y = args.y }) - args.canvas:blit(device, { - x = args.x, - y = args.y, - ex = args.ex - x + args.x, - ey = args.ey }, - { x = x, y = args.y }) + args.canvas:move(math.floor(pos.x), args.canvas.y) + args.canvas:dirty() + args.canvas:render(device) return not finished end end @@ -32,26 +22,16 @@ end function Transition.slideRight(args) local ticks = args.ticks or 6 local easing = args.easing or'outQuint' - local pos = { x = args.x } - local tween = Tween.new(ticks, pos, { x = args.ex }, easing) - local lastScreen = args.canvas:copy() + local pos = { x = -args.canvas.width } + local tween = Tween.new(ticks, pos, { x = 1 }, easing) + + args.canvas:move(pos.x, args.canvas.y) return function(device) local finished = tween:update(1) - local x = math.floor(pos.x) - lastScreen:dirty() - lastScreen:blit(device, { - x = args.x, - y = args.y, - ex = args.ex - x + args.x, - ey = args.ey }, - { x = x, y = args.y }) - args.canvas:blit(device, { - x = args.ex - x + args.x, - y = args.y, - ex = args.ex, - ey = args.ey }, - { x = args.x, y = args.y }) + args.canvas:move(math.floor(pos.x), args.canvas.y) + args.canvas:dirty() + args.canvas:render(device) return not finished end end @@ -62,27 +42,13 @@ function Transition.expandUp(args) local pos = { y = args.ey + 1 } local tween = Tween.new(ticks, pos, { y = args.y }, easing) - return function(device) - local finished = tween:update(1) - args.canvas:blit(device, nil, { x = args.x, y = math.floor(pos.y) }) - return not finished - end -end - -function Transition.grow(args) - local ticks = args.ticks or 3 - local easing = args.easing or 'linear' - local tween = Tween.new(ticks, - { x = args.width / 2 - 1, y = args.height / 2 - 1, w = 1, h = 1 }, - { x = 1, y = 1, w = args.width, h = args.height }, easing) + args.canvas:move(args.x, pos.y) return function(device) local finished = tween:update(1) - local subj = tween.subject - local rect = { x = math.floor(subj.x), y = math.floor(subj.y) } - rect.ex = math.floor(rect.x + subj.w - 1) - rect.ey = math.floor(rect.y + subj.h - 1) - args.canvas:blit(device, rect, { x = args.x + rect.x - 1, y = args.y + rect.y - 1}) + args.canvas:move(args.x, math.floor(pos.y)) + args.canvas:dirty() + args.canvas:render(device) return not finished end end diff --git a/sys/apps/Network.lua b/sys/apps/Network.lua index 802b8b5..f209aa1 100644 --- a/sys/apps/Network.lua +++ b/sys/apps/Network.lua @@ -72,6 +72,31 @@ local page = UI.Page { autospace = true, }, }, + help = UI.SlideOut { + backgroundColor = colors.cyan, + x = 5, ex = -5, height = 8, y = -8, + titleBar = UI.TitleBar { + title = 'Network Help', + event = 'slide_hide', + }, + text = UI.TextArea { + x = 2, y = 2, + backgroundColor = colors.cyan, + value = [[ + +In order to connect to another computer: + +1. The target computer must have a password set (run 'password' from the shell prompt). + +2. From this computer, click trust and enter the password for that computer. + +This only needs to be done once. + ]], + }, + accelerators = { + q = 'slide_hide', + } + }, notification = UI.Notification { }, accelerators = { t = 'telnet', @@ -180,27 +205,9 @@ function page:eventHandler(event) sendCommand(t.id, 'shutdown') end end + if event.type == 'help' then - UI:setPage(UI.Dialog { - title = 'Network Help', - height = 10, - backgroundColor = colors.white, - text = UI.TextArea { - x = 2, y = 2, - backgroundColor = colors.white, - value = [[ -In order to connect to another computer: - - 1. The target computer must have a password set (run 'password' from the shell prompt). - 2. From this computer, click trust and enter the password for that computer. - -This only needs to be done once. - ]], - }, - accelerators = { - q = 'cancel', - } - }) + self.help:show() elseif event.type == 'ports' then self.ports.grid:update() diff --git a/sys/apps/Overview.lua b/sys/apps/Overview.lua index 3bda2b1..8aa1cd8 100644 --- a/sys/apps/Overview.lua +++ b/sys/apps/Overview.lua @@ -106,6 +106,7 @@ local page = UI.Page { } }, editor = UI.SlideOut { + y = -12, height = 12, backgroundColor = colors.cyan, titleBar = UI.TitleBar { title = 'Edit Application', diff --git a/sys/apps/System.lua b/sys/apps/System.lua index 464f1f2..601edfe 100644 --- a/sys/apps/System.lua +++ b/sys/apps/System.lua @@ -8,7 +8,7 @@ UI:configure('System', ...) local systemPage = UI.Page { tabs = UI.Tabs { - settings = UI.Window { + settings = UI.Tab { tabTitle = 'Category', grid = UI.Grid { y = 2, diff --git a/sys/apps/system/aliases.lua b/sys/apps/system/aliases.lua index cdb38ca..0523f27 100644 --- a/sys/apps/system/aliases.lua +++ b/sys/apps/system/aliases.lua @@ -1,7 +1,7 @@ local Config = require('config') local UI = require('ui') -local aliasTab = UI.Window { +local aliasTab = UI.Tab { tabTitle = 'Aliases', description = 'Shell aliases', alias = UI.TextEntry { diff --git a/sys/apps/system/label.lua b/sys/apps/system/label.lua index 0d03425..7ed6f6f 100644 --- a/sys/apps/system/label.lua +++ b/sys/apps/system/label.lua @@ -4,7 +4,7 @@ local Util = require('util') local fs = _G.fs local os = _G.os -local labelTab = UI.Window { +local labelTab = UI.Tab { tabTitle = 'Label', description = 'Set the computer label', labelText = UI.Text { diff --git a/sys/apps/system/network.lua b/sys/apps/system/network.lua index 0b9737d..4f2199e 100644 --- a/sys/apps/system/network.lua +++ b/sys/apps/system/network.lua @@ -3,7 +3,7 @@ local UI = require('ui') local device = _G.device -local tab = UI.Window { +local tab = UI.Tab { tabTitle = 'Network', description = 'Networking options', form = UI.Form { @@ -40,7 +40,7 @@ function tab:enable() local config = Config.load('os') self.form.modem.value = config.wirelessModem or 'auto' - UI.Window.enable(self) + UI.Tab.enable(self) end function tab:eventHandler(event) diff --git a/sys/apps/system/password.lua b/sys/apps/system/password.lua index 23524fd..4c45616 100644 --- a/sys/apps/system/password.lua +++ b/sys/apps/system/password.lua @@ -2,7 +2,7 @@ local Security = require('security') local SHA1 = require('sha1') local UI = require('ui') -local passwordTab = UI.Window { +local passwordTab = UI.Tab { tabTitle = 'Password', description = 'Wireless network password', oldPass = UI.TextEntry { diff --git a/sys/apps/system/path.lua b/sys/apps/system/path.lua index 5374634..f2a7c98 100644 --- a/sys/apps/system/path.lua +++ b/sys/apps/system/path.lua @@ -2,7 +2,7 @@ local Config = require('config') local UI = require('ui') local Util = require('util') -local pathTab = UI.Window { +local pathTab = UI.Tab { tabTitle = 'Path', description = 'Set the shell path', tabClose = true, diff --git a/sys/apps/system/settings.lua b/sys/apps/system/settings.lua index 2722dab..dc919ff 100644 --- a/sys/apps/system/settings.lua +++ b/sys/apps/system/settings.lua @@ -3,7 +3,6 @@ local UI = require('ui') local settings = _G.settings if settings then - local values = { } for _,v in pairs(settings.getNames()) do local value = settings.get(v) @@ -16,11 +15,11 @@ if settings then }) end - local settingsTab = UI.Window { + local settingsTab = UI.Tab { tabTitle = 'Settings', description = 'Computercraft configurable settings', grid = UI.Grid { - y = 1, + y = 2, values = values, autospace = true, sortColumn = 'name', diff --git a/sys/apps/system/turtle.lua b/sys/apps/system/turtle.lua index 18150de..fe6fadf 100644 --- a/sys/apps/system/turtle.lua +++ b/sys/apps/system/turtle.lua @@ -9,7 +9,7 @@ if turtle then local values = { } Config.load('gps', values.home and { values.home } or { }) - local gpsTab = UI.Window { + local gpsTab = UI.Tab { tabTitle = 'GPS', labelText = UI.Text { x = 3, y = 2,