mirror of
https://github.com/kepler155c/opus
synced 2024-12-26 00:20:26 +00:00
simplify ui
This commit is contained in:
parent
05c99b583a
commit
852ad193f0
@ -1,8 +1,6 @@
|
|||||||
-- From http://lua-users.org/wiki/SimpleLuaClasses
|
-- From http://lua-users.org/wiki/SimpleLuaClasses
|
||||||
-- (with some modifications)
|
-- (with some modifications)
|
||||||
|
|
||||||
local uid = 1
|
|
||||||
|
|
||||||
-- class.lua
|
-- class.lua
|
||||||
-- Compatible with Lua 5.1 (not 5.0).
|
-- Compatible with Lua 5.1 (not 5.0).
|
||||||
return function(base)
|
return function(base)
|
||||||
@ -21,8 +19,7 @@ return function(base)
|
|||||||
-- expose a constructor which can be called by <classname>(<args>)
|
-- expose a constructor which can be called by <classname>(<args>)
|
||||||
setmetatable(c, {
|
setmetatable(c, {
|
||||||
__call = function(class_tbl, ...)
|
__call = function(class_tbl, ...)
|
||||||
local obj = { __uid = uid }
|
local obj = { }
|
||||||
uid = uid + 1
|
|
||||||
setmetatable(obj,c)
|
setmetatable(obj,c)
|
||||||
if class_tbl.init then
|
if class_tbl.init then
|
||||||
class_tbl.init(obj, ...)
|
class_tbl.init(obj, ...)
|
||||||
|
359
sys/apis/ui.lua
359
sys/apis/ui.lua
@ -6,8 +6,14 @@ local Util = require('util')
|
|||||||
|
|
||||||
local _rep = string.rep
|
local _rep = string.rep
|
||||||
local _sub = string.sub
|
local _sub = string.sub
|
||||||
|
local clipboard = _G.clipboard
|
||||||
local colors = _G.colors
|
local colors = _G.colors
|
||||||
|
local device = _G.device
|
||||||
|
local fs = _G.fs
|
||||||
local keys = _G.keys
|
local keys = _G.keys
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
local os = _G.os
|
||||||
|
local term = _G.term
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Using the shorthand window definition, elements are created from
|
Using the shorthand window definition, elements are created from
|
||||||
@ -35,12 +41,6 @@ local function getPosition(element)
|
|||||||
return x, y
|
return x, y
|
||||||
end
|
end
|
||||||
|
|
||||||
local function assertElement(el, msg)
|
|
||||||
if not el or not type(el) == 'table' or not el.UIElement then
|
|
||||||
error(msg, 3)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[-- Top Level Manager --]]--
|
--[[-- Top Level Manager --]]--
|
||||||
local Manager = class()
|
local Manager = class()
|
||||||
function Manager:init()
|
function Manager:init()
|
||||||
@ -232,11 +232,10 @@ function Manager:configure(appName, ...)
|
|||||||
if not dev then
|
if not dev then
|
||||||
error('Invalid display device')
|
error('Invalid display device')
|
||||||
end
|
end
|
||||||
local device = self.Device({
|
self:setDefaultDevice(self.Device({
|
||||||
device = dev,
|
device = dev,
|
||||||
textScale = defaults.device.textScale,
|
textScale = defaults.device.textScale,
|
||||||
})
|
}))
|
||||||
self:setDefaultDevice(device)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if defaults.theme then
|
if defaults.theme then
|
||||||
@ -273,7 +272,6 @@ function Manager:emitEvent(event)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Manager:inputEvent(parent, event)
|
function Manager:inputEvent(parent, event)
|
||||||
|
|
||||||
while parent do
|
while parent do
|
||||||
if parent.accelerators then
|
if parent.accelerators then
|
||||||
local acc = parent.accelerators[event.key]
|
local acc = parent.accelerators[event.key]
|
||||||
@ -376,9 +374,9 @@ function Manager:click(button, x, y)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:setDefaultDevice(device)
|
function Manager:setDefaultDevice(dev)
|
||||||
self.defaultDevice = device
|
self.defaultDevice = dev
|
||||||
self.term = device
|
self.term = dev
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:addPage(name, page)
|
function Manager:addPage(name, page)
|
||||||
@ -490,8 +488,8 @@ function Manager:setProperties(obj, args)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:dump(el)
|
function Manager:dump(inEl)
|
||||||
if el then
|
if inEl then
|
||||||
local function clean(el)
|
local function clean(el)
|
||||||
local o = el
|
local o = el
|
||||||
el = Util.shallowCopy(el)
|
el = Util.shallowCopy(el)
|
||||||
@ -511,7 +509,7 @@ function Manager:dump(el)
|
|||||||
|
|
||||||
return el
|
return el
|
||||||
end
|
end
|
||||||
return clean(el)
|
return clean(inEl)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -519,6 +517,7 @@ local UI = Manager()
|
|||||||
|
|
||||||
--[[-- Basic drawable area --]]--
|
--[[-- Basic drawable area --]]--
|
||||||
UI.Window = class()
|
UI.Window = class()
|
||||||
|
UI.Window.uid = 1
|
||||||
UI.Window.defaults = {
|
UI.Window.defaults = {
|
||||||
UIElement = 'Window',
|
UIElement = 'Window',
|
||||||
x = 1,
|
x = 1,
|
||||||
@ -528,12 +527,46 @@ UI.Window.defaults = {
|
|||||||
offy = 0,
|
offy = 0,
|
||||||
cursorX = 1,
|
cursorX = 1,
|
||||||
cursorY = 1,
|
cursorY = 1,
|
||||||
-- accelerators = { },
|
|
||||||
}
|
}
|
||||||
function UI.Window:init(args)
|
function UI.Window:init(args)
|
||||||
local defaults = UI:getDefaults(UI.Window, args)
|
-- merge defaults for all subclasses
|
||||||
|
local defaults = args
|
||||||
|
local m = self
|
||||||
|
repeat
|
||||||
|
defaults = UI:getDefaults(m, defaults)
|
||||||
|
m = m._base
|
||||||
|
until not m
|
||||||
UI:setProperties(self, defaults)
|
UI:setProperties(self, defaults)
|
||||||
|
|
||||||
|
-- each element has a unique ID
|
||||||
|
self.uid = UI.Window.uid
|
||||||
|
UI.Window.uid = UI.Window.uid + 1
|
||||||
|
|
||||||
|
-- at this time, the object has all the properties set
|
||||||
|
|
||||||
|
-- postInit is a special constructor. the element does not need to implement
|
||||||
|
-- the method. But we need to guarantee that each subclass which has this
|
||||||
|
-- method is called.
|
||||||
|
m = self
|
||||||
|
local lpi
|
||||||
|
repeat
|
||||||
|
if m.postInit and m.postInit ~= lpi then
|
||||||
|
--debug('calling ' .. m.defaults.UIElement)
|
||||||
|
--debug(rawget(m, 'postInit'))
|
||||||
|
m.postInit(self)
|
||||||
|
lpi = m.postInit
|
||||||
|
-- else
|
||||||
|
--debug('skipping ' .. m.defaults.UIElement)
|
||||||
|
--debug(rawget(m, 'postInit'))
|
||||||
|
end
|
||||||
|
m = m._base
|
||||||
|
until not m
|
||||||
|
end
|
||||||
|
|
||||||
|
function UI.Window:postInit()
|
||||||
if self.parent then
|
if self.parent then
|
||||||
|
-- this will cascade down the whole tree of elements starting at the
|
||||||
|
-- top level window (which has a device as a parent)
|
||||||
self:setParent()
|
self:setParent()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -749,7 +782,7 @@ function UI.Window:print(text, bg, fg)
|
|||||||
if #result > 1 and result[2] > cx then
|
if #result > 1 and result[2] > cx then
|
||||||
return _sub(line, cx, result[2] + 1)
|
return _sub(line, cx, result[2] + 1)
|
||||||
elseif #result > 0 and result[1] == cx then
|
elseif #result > 0 and result[1] == cx then
|
||||||
result = { line:find("(%w+)", result[2] + 1) }
|
result = { line:find("(%w+)", result[2]) }
|
||||||
if #result > 0 then
|
if #result > 0 then
|
||||||
return _sub(line, cx, result[1] + 1)
|
return _sub(line, cx, result[1] + 1)
|
||||||
end
|
end
|
||||||
@ -811,10 +844,10 @@ function UI.Window:print(text, bg, fg)
|
|||||||
if self.cursorX + #word > width then
|
if self.cursorX + #word > width then
|
||||||
self.cursorX = marginLeft + 1
|
self.cursorX = marginLeft + 1
|
||||||
self.cursorY = self.cursorY + 1
|
self.cursorY = self.cursorY + 1
|
||||||
w = word:gsub(' ', '')
|
w = word:gsub('^ ', '')
|
||||||
end
|
end
|
||||||
self:write(self.cursorX, self.cursorY, w, bg, fg)
|
self:write(self.cursorX, self.cursorY, w, bg, fg)
|
||||||
self.cursorX = self.cursorX + #word
|
self.cursorX = self.cursorX + #w
|
||||||
lx = lx + #word
|
lx = lx + #word
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -829,7 +862,6 @@ function UI.Window:print(text, bg, fg)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.Window:setFocus(focus)
|
function UI.Window:setFocus(focus)
|
||||||
assertElement(focus, 'UI.Window:setFocus: Invalid element passed')
|
|
||||||
if self.parent then
|
if self.parent then
|
||||||
self.parent:setFocus(focus)
|
self.parent:setFocus(focus)
|
||||||
end
|
end
|
||||||
@ -864,7 +896,6 @@ function UI.Window:getFocusables()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.Window:focusFirst()
|
function UI.Window:focusFirst()
|
||||||
|
|
||||||
local focusables = self:getFocusables()
|
local focusables = self:getFocusables()
|
||||||
local focused = focusables[1]
|
local focused = focusables[1]
|
||||||
if focused then
|
if focused then
|
||||||
@ -904,7 +935,6 @@ end
|
|||||||
|
|
||||||
function UI.Window:addLayer(bg, fg)
|
function UI.Window:addLayer(bg, fg)
|
||||||
local canvas = self:getCanvas()
|
local canvas = self:getCanvas()
|
||||||
|
|
||||||
return canvas:addLayer(self, bg, fg)
|
return canvas:addLayer(self, bg, fg)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -947,23 +977,19 @@ UI.Device.defaults = {
|
|||||||
textScale = 1,
|
textScale = 1,
|
||||||
effectsEnabled = true,
|
effectsEnabled = true,
|
||||||
}
|
}
|
||||||
function UI.Device:init(args)
|
function UI.Device:postInit()
|
||||||
local defaults = UI:getDefaults(UI.Device)
|
self.device = self.device or term.current()
|
||||||
defaults.device = term.current()
|
|
||||||
UI:setProperties(defaults, args)
|
|
||||||
|
|
||||||
if defaults.deviceType then
|
if self.deviceType then
|
||||||
defaults.device = device[defaults.deviceType]
|
self.device = device[self.deviceType]
|
||||||
end
|
end
|
||||||
|
|
||||||
if not defaults.device.setTextScale then
|
if not self.device.setTextScale then
|
||||||
defaults.device.setTextScale = function() end
|
self.device.setTextScale = function() end
|
||||||
end
|
end
|
||||||
|
|
||||||
defaults.device.setTextScale(defaults.textScale)
|
self.device.setTextScale(self.textScale)
|
||||||
defaults.width, defaults.height = defaults.device.getSize()
|
self.width, self.height = self.device.getSize()
|
||||||
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
|
|
||||||
self.isColor = self.device.isColor()
|
self.isColor = self.device.isColor()
|
||||||
|
|
||||||
@ -979,7 +1005,6 @@ function UI.Device:resize()
|
|||||||
self.lines = { }
|
self.lines = { }
|
||||||
self.canvas:resize(self.width, self.height)
|
self.canvas:resize(self.width, self.height)
|
||||||
self.canvas:clear(self.backgroundColor, self.textColor)
|
self.canvas:clear(self.backgroundColor, self.textColor)
|
||||||
--UI.Window.resize(self)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Device:setCursorPos(x, y)
|
function UI.Device:setCursorPos(x, y)
|
||||||
@ -1029,7 +1054,6 @@ function UI.Device:addTransition(effect, args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.Device:runTransitions(transitions, canvas)
|
function UI.Device:runTransitions(transitions, canvas)
|
||||||
|
|
||||||
for _,t in ipairs(transitions) do
|
for _,t in ipairs(transitions) do
|
||||||
canvas:punch(t.args) -- punch out the effect areas
|
canvas:punch(t.args) -- punch out the effect areas
|
||||||
end
|
end
|
||||||
@ -1051,7 +1075,6 @@ function UI.Device:runTransitions(transitions, canvas)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.Device:sync()
|
function UI.Device:sync()
|
||||||
|
|
||||||
local transitions
|
local transitions
|
||||||
if self.transitions and self.effectsEnabled then
|
if self.transitions and self.effectsEnabled then
|
||||||
transitions = self.transitions
|
transitions = self.transitions
|
||||||
@ -1146,14 +1169,14 @@ UI.Page.defaults = {
|
|||||||
backgroundColor = colors.cyan,
|
backgroundColor = colors.cyan,
|
||||||
textColor = colors.white,
|
textColor = colors.white,
|
||||||
}
|
}
|
||||||
function UI.Page:init(args)
|
function UI.Page:postInit()
|
||||||
local defaults = UI:getDefaults(UI.Page)
|
self.parent = self.parent or UI.defaultDevice
|
||||||
defaults.parent = UI.defaultDevice
|
end
|
||||||
UI:setProperties(defaults, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
|
|
||||||
|
function UI.Page:setParent()
|
||||||
|
UI.Window.setParent(self)
|
||||||
if self.z then
|
if self.z then
|
||||||
self.canvas = self.parent.canvas:addLayer(self, self.backgroundColor, self.textColor)
|
self.canvas = self:addLayer(self.backgroundColor, self.textColor)
|
||||||
else
|
else
|
||||||
self.canvas = self.parent.canvas
|
self.canvas = self.parent.canvas
|
||||||
end
|
end
|
||||||
@ -1179,7 +1202,6 @@ function UI.Page:getFocused()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.Page:focusPrevious()
|
function UI.Page:focusPrevious()
|
||||||
|
|
||||||
local function getPreviousFocus(focused)
|
local function getPreviousFocus(focused)
|
||||||
local focusables = self:getFocusables()
|
local focusables = self:getFocusables()
|
||||||
for k, v in ipairs(focusables) do
|
for k, v in ipairs(focusables) do
|
||||||
@ -1199,7 +1221,6 @@ function UI.Page:focusPrevious()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.Page:focusNext()
|
function UI.Page:focusNext()
|
||||||
|
|
||||||
local function getNextFocus(focused)
|
local function getNextFocus(focused)
|
||||||
local focusables = self:getFocusables()
|
local focusables = self:getFocusables()
|
||||||
for k, v in ipairs(focusables) do
|
for k, v in ipairs(focusables) do
|
||||||
@ -1219,8 +1240,6 @@ function UI.Page:focusNext()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.Page:setFocus(child)
|
function UI.Page:setFocus(child)
|
||||||
assertElement(child, 'UI.Page:setFocus: Invalid element passed')
|
|
||||||
|
|
||||||
if not child.focus then
|
if not child.focus then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -1287,9 +1306,8 @@ UI.Grid.defaults = {
|
|||||||
[ 'control-f' ] = 'scroll_pageDown',
|
[ 'control-f' ] = 'scroll_pageDown',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
function UI.Grid:init(args)
|
function UI.Grid:setParent()
|
||||||
local defaults = UI:getDefaults(UI.Grid, args)
|
UI.Window.setParent(self)
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
|
|
||||||
for _,c in pairs(self.columns) do
|
for _,c in pairs(self.columns) do
|
||||||
c.cw = c.width
|
c.cw = c.width
|
||||||
@ -1297,10 +1315,7 @@ function UI.Grid:init(args)
|
|||||||
c.heading = ''
|
c.heading = ''
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function UI.Grid:setParent()
|
|
||||||
UI.Window.setParent(self)
|
|
||||||
self:update()
|
self:update()
|
||||||
|
|
||||||
if not self.pageSize then
|
if not self.pageSize then
|
||||||
@ -1324,7 +1339,6 @@ function UI.Grid:resize()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.Grid:adjustWidth()
|
function UI.Grid:adjustWidth()
|
||||||
|
|
||||||
local t = { } -- cols without width
|
local t = { } -- cols without width
|
||||||
local w = self.width - #self.columns - 1 - self.marginRight -- width remaining
|
local w = self.width - #self.columns - 1 - self.marginRight -- width remaining
|
||||||
|
|
||||||
@ -1449,7 +1463,6 @@ end
|
|||||||
-- Something about the displayed table has changed
|
-- Something about the displayed table has changed
|
||||||
-- resort the table
|
-- resort the table
|
||||||
function UI.Grid:update()
|
function UI.Grid:update()
|
||||||
|
|
||||||
local function sort(a, b)
|
local function sort(a, b)
|
||||||
if not a[self.sortColumn] then
|
if not a[self.sortColumn] then
|
||||||
return false
|
return false
|
||||||
@ -1618,7 +1631,6 @@ function UI.Grid:setPage(pageNo)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.Grid:eventHandler(event)
|
function UI.Grid:eventHandler(event)
|
||||||
|
|
||||||
if event.type == 'mouse_click' or event.type == 'mouse_doubleclick' then
|
if event.type == 'mouse_click' or event.type == 'mouse_doubleclick' then
|
||||||
if not self.disableHeader then
|
if not self.disableHeader then
|
||||||
if event.y == 1 then
|
if event.y == 1 then
|
||||||
@ -1686,8 +1698,7 @@ UI.ScrollingGrid.defaults = {
|
|||||||
scrollOffset = 0,
|
scrollOffset = 0,
|
||||||
marginRight = 1,
|
marginRight = 1,
|
||||||
}
|
}
|
||||||
function UI.ScrollingGrid:init(args)
|
function UI.ScrollingGrid:postInit()
|
||||||
UI.Grid.init(self, UI:getDefaults(UI.ScrollingGrid, args))
|
|
||||||
self.scrollBar = UI.ScrollBar()
|
self.scrollBar = UI.ScrollBar()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1743,12 +1754,9 @@ UI.Menu.defaults = {
|
|||||||
disableHeader = true,
|
disableHeader = true,
|
||||||
columns = { { heading = 'Prompt', key = 'prompt', width = 20 } },
|
columns = { { heading = 'Prompt', key = 'prompt', width = 20 } },
|
||||||
}
|
}
|
||||||
function UI.Menu:init(args)
|
function UI.Menu:postInit()
|
||||||
local defaults = UI:getDefaults(UI.Menu)
|
self.values = self.menuItems
|
||||||
defaults.values = args['menuItems']
|
self.pageSize = #self.menuItems
|
||||||
UI:setProperties(defaults, args)
|
|
||||||
UI.Grid.init(self, defaults)
|
|
||||||
self.pageSize = #args.menuItems
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Menu:setParent()
|
function UI.Menu:setParent()
|
||||||
@ -1813,11 +1821,6 @@ UI.Viewport.defaults = {
|
|||||||
[ 'control-f' ] = 'scroll_pageDown',
|
[ 'control-f' ] = 'scroll_pageDown',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
function UI.Viewport:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.Viewport, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.Viewport:setScrollPosition(offset)
|
function UI.Viewport:setScrollPosition(offset)
|
||||||
local oldOffset = self.offy
|
local oldOffset = self.offy
|
||||||
self.offy = math.max(offset, 0)
|
self.offy = math.max(offset, 0)
|
||||||
@ -1849,7 +1852,6 @@ function UI.Viewport:getViewArea()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.Viewport:eventHandler(event)
|
function UI.Viewport:eventHandler(event)
|
||||||
|
|
||||||
if event.type == 'scroll_down' then
|
if event.type == 'scroll_down' then
|
||||||
self:setScrollPosition(self.offy + 1)
|
self:setScrollPosition(self.offy + 1)
|
||||||
elseif event.type == 'scroll_up' then
|
elseif event.type == 'scroll_up' then
|
||||||
@ -1868,36 +1870,6 @@ function UI.Viewport:eventHandler(event)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[-- ScrollingText --]]--
|
|
||||||
UI.ScrollingText = class(UI.Window)
|
|
||||||
UI.ScrollingText.defaults = {
|
|
||||||
UIElement = 'ScrollingText',
|
|
||||||
backgroundColor = colors.black,
|
|
||||||
buffer = { },
|
|
||||||
}
|
|
||||||
function UI.ScrollingText:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.ScrollingText, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.ScrollingText:appendLine(text)
|
|
||||||
if #self.buffer+1 >= self.height then
|
|
||||||
table.remove(self.buffer, 1)
|
|
||||||
end
|
|
||||||
table.insert(self.buffer, text)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.ScrollingText:clear()
|
|
||||||
self.buffer = { }
|
|
||||||
UI.Window.clear(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.ScrollingText:draw()
|
|
||||||
for k,text in ipairs(self.buffer) do
|
|
||||||
self:write(1, k, Util.widthify(text, self.width), self.backgroundColor)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[-- TitleBar --]]--
|
--[[-- TitleBar --]]--
|
||||||
UI.TitleBar = class(UI.Window)
|
UI.TitleBar = class(UI.Window)
|
||||||
UI.TitleBar.defaults = {
|
UI.TitleBar.defaults = {
|
||||||
@ -1909,11 +1881,6 @@ UI.TitleBar.defaults = {
|
|||||||
frameChar = '-',
|
frameChar = '-',
|
||||||
closeInd = '*',
|
closeInd = '*',
|
||||||
}
|
}
|
||||||
function UI.TitleBar:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.TitleBar, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.TitleBar:draw()
|
function UI.TitleBar:draw()
|
||||||
local sb = SB:new(self.width)
|
local sb = SB:new(self.width)
|
||||||
sb:fill(2, self.frameChar, sb.width - 3)
|
sb:fill(2, self.frameChar, sb.width - 3)
|
||||||
@ -1960,11 +1927,6 @@ UI.Button.defaults = {
|
|||||||
mouse_click = 'button_activate',
|
mouse_click = 'button_activate',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function UI.Button:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.Button, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.Button:setParent()
|
function UI.Button:setParent()
|
||||||
if not self.width and not self.ex then
|
if not self.width and not self.ex then
|
||||||
self.width = #self.text + 2
|
self.width = #self.text + 2
|
||||||
@ -2017,10 +1979,6 @@ UI.MenuItem.defaults = {
|
|||||||
backgroundFocusColor = colors.lightGray,
|
backgroundFocusColor = colors.lightGray,
|
||||||
}
|
}
|
||||||
|
|
||||||
function UI.MenuItem:init(args)
|
|
||||||
UI.Button.init(self, UI:getDefaults(UI.MenuItem, args))
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[-- MenuBar --]]--
|
--[[-- MenuBar --]]--
|
||||||
UI.MenuBar = class(UI.Window)
|
UI.MenuBar = class(UI.Window)
|
||||||
UI.MenuBar.defaults = {
|
UI.MenuBar.defaults = {
|
||||||
@ -2036,25 +1994,8 @@ UI.MenuBar.defaults = {
|
|||||||
}
|
}
|
||||||
UI.MenuBar.spacer = { spacer = true, text = 'spacer', inactive = true }
|
UI.MenuBar.spacer = { spacer = true, text = 'spacer', inactive = true }
|
||||||
|
|
||||||
function UI.MenuBar:init(args)
|
function UI.MenuBar:postInit()
|
||||||
local defaults = UI:getDefaults(UI.MenuBar, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
|
|
||||||
if not self.children then
|
|
||||||
self.children = { }
|
|
||||||
end
|
|
||||||
|
|
||||||
self:addButtons(self.buttons)
|
self:addButtons(self.buttons)
|
||||||
if self.showBackButton then -- need to remove
|
|
||||||
table.insert(self.children, UI.MenuItem({
|
|
||||||
x = UI.term.width - 2,
|
|
||||||
width = 3,
|
|
||||||
backgroundColor = self.backgroundColor,
|
|
||||||
textColor = self.textColor,
|
|
||||||
text = '^-',
|
|
||||||
event = 'back',
|
|
||||||
}))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.MenuBar:addButtons(buttons)
|
function UI.MenuBar:addButtons(buttons)
|
||||||
@ -2126,11 +2067,6 @@ UI.DropMenuItem.defaults = {
|
|||||||
textInactiveColor = colors.lightGray,
|
textInactiveColor = colors.lightGray,
|
||||||
backgroundFocusColor = colors.lightGray,
|
backgroundFocusColor = colors.lightGray,
|
||||||
}
|
}
|
||||||
|
|
||||||
function UI.DropMenuItem:init(args)
|
|
||||||
UI.Button.init(self, UI:getDefaults(UI.DropMenuItem, args))
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.DropMenuItem:eventHandler(event)
|
function UI.DropMenuItem:eventHandler(event)
|
||||||
if event.type == 'button_activate' then
|
if event.type == 'button_activate' then
|
||||||
self.parent:hide()
|
self.parent:hide()
|
||||||
@ -2145,11 +2081,6 @@ UI.DropMenu.defaults = {
|
|||||||
backgroundColor = colors.white,
|
backgroundColor = colors.white,
|
||||||
buttonClass = 'DropMenuItem',
|
buttonClass = 'DropMenuItem',
|
||||||
}
|
}
|
||||||
function UI.DropMenu:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.DropMenu, args)
|
|
||||||
UI.MenuBar.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.DropMenu:setParent()
|
function UI.DropMenu:setParent()
|
||||||
UI.MenuBar.setParent(self)
|
UI.MenuBar.setParent(self)
|
||||||
|
|
||||||
@ -2180,7 +2111,6 @@ function UI.DropMenu:enable()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.DropMenu:show(x, y)
|
function UI.DropMenu:show(x, y)
|
||||||
|
|
||||||
self.x, self.y = x, y
|
self.x, self.y = x, y
|
||||||
self.canvas:move(x, y)
|
self.canvas:move(x, y)
|
||||||
self.canvas:setVisible(true)
|
self.canvas:setVisible(true)
|
||||||
@ -2226,14 +2156,10 @@ UI.TabBar.defaults = {
|
|||||||
selectedBackgroundColor = colors.cyan,
|
selectedBackgroundColor = colors.cyan,
|
||||||
focusBackgroundColor = colors.green,
|
focusBackgroundColor = colors.green,
|
||||||
}
|
}
|
||||||
function UI.TabBar:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.TabBar, args)
|
|
||||||
UI.MenuBar.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.TabBar:selectTab(text)
|
function UI.TabBar:selectTab(text)
|
||||||
local selected, lastSelected
|
local selected, lastSelected
|
||||||
for k,child in pairs(self.children) do
|
|
||||||
|
for k,child in pairs(self:getFocusables()) do
|
||||||
if child.selected then
|
if child.selected then
|
||||||
lastSelected = k
|
lastSelected = k
|
||||||
end
|
end
|
||||||
@ -2258,23 +2184,19 @@ UI.Tabs = class(UI.Window)
|
|||||||
UI.Tabs.defaults = {
|
UI.Tabs.defaults = {
|
||||||
UIElement = 'Tabs',
|
UIElement = 'Tabs',
|
||||||
}
|
}
|
||||||
function UI.Tabs:init(args)
|
function UI.Tabs:postInit()
|
||||||
local defaults = UI:getDefaults(UI.Tabs, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
|
|
||||||
self:add(self)
|
self:add(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Tabs:add(children)
|
function UI.Tabs:add(children)
|
||||||
|
|
||||||
local buttons = { }
|
local buttons = { }
|
||||||
for _,child in pairs(children) do
|
for _,child in pairs(children) do
|
||||||
if type(child) == 'table' and child.UIElement then
|
if type(child) == 'table' and child.UIElement and child.tabTitle then
|
||||||
child.y = 2
|
child.y = 2
|
||||||
table.insert(buttons, {
|
table.insert(buttons, {
|
||||||
text = child.tabTitle or '',
|
text = child.tabTitle,
|
||||||
event = 'tab_select',
|
event = 'tab_select',
|
||||||
tabUid = child.__uid,
|
tabUid = child.uid,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -2294,32 +2216,35 @@ end
|
|||||||
|
|
||||||
function UI.Tabs:enable()
|
function UI.Tabs:enable()
|
||||||
self.enabled = true
|
self.enabled = true
|
||||||
|
|
||||||
local _, menuItem = Util.first(self.tabBar.children, function(a, b) return a.x < b.x end)
|
|
||||||
if menuItem then
|
|
||||||
self:activateTab(Util.find(self.children, '__uid', menuItem.tabUid))
|
|
||||||
end
|
|
||||||
self.tabBar:enable()
|
self.tabBar:enable()
|
||||||
|
|
||||||
|
-- focus first tab
|
||||||
|
local menuItem = self.tabBar:getFocusables()[1]
|
||||||
|
if menuItem then
|
||||||
|
self:activateTab(menuItem.tabUid)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Tabs:activateTab(tab)
|
function UI.Tabs:activateTab(uid)
|
||||||
for _,child in ipairs(self.children) do
|
local tab = Util.find(self.children, 'uid', uid)
|
||||||
if child ~= self.tabBar then
|
if tab then
|
||||||
|
for _,child in pairs(self.children) do
|
||||||
|
if child.uid ~= uid and child.tabTitle then
|
||||||
child:disable()
|
child:disable()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if not tab.enabled then
|
||||||
self.tabBar:selectTab(tab.tabTitle)
|
self.tabBar:selectTab(tab.tabTitle)
|
||||||
tab:enable()
|
tab:enable()
|
||||||
tab:draw()
|
tab:draw()
|
||||||
self:emit({ type = 'tab_activate', activated = tab, element = self })
|
self:emit({ type = 'tab_activate', activated = tab, element = self })
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function UI.Tabs:eventHandler(event)
|
function UI.Tabs:eventHandler(event)
|
||||||
if event.type == 'tab_select' then
|
if event.type == 'tab_select' then
|
||||||
local child = Util.find(self.children, '__uid', event.button.tabUid)
|
self:activateTab(event.button.tabUid)
|
||||||
if child then
|
|
||||||
self:activateTab(child)
|
|
||||||
end
|
|
||||||
elseif event.type == 'tab_change' then
|
elseif event.type == 'tab_change' then
|
||||||
for _,tab in ipairs(self.children) do
|
for _,tab in ipairs(self.children) do
|
||||||
if tab ~= self.tabBar then
|
if tab ~= self.tabBar then
|
||||||
@ -2340,11 +2265,6 @@ UI.WindowScroller.defaults = {
|
|||||||
UIElement = 'WindowScroller',
|
UIElement = 'WindowScroller',
|
||||||
children = { },
|
children = { },
|
||||||
}
|
}
|
||||||
function UI.WindowScroller:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.WindowScroller, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.WindowScroller:enable()
|
function UI.WindowScroller:enable()
|
||||||
self.enabled = true
|
self.enabled = true
|
||||||
if #self.children > 0 then
|
if #self.children > 0 then
|
||||||
@ -2385,11 +2305,6 @@ UI.Notification.defaults = {
|
|||||||
backgroundColor = colors.gray,
|
backgroundColor = colors.gray,
|
||||||
height = 3,
|
height = 3,
|
||||||
}
|
}
|
||||||
function UI.Notification:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.Notification, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.Notification:draw()
|
function UI.Notification:draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2430,8 +2345,7 @@ function UI.Notification:display(value, timeout)
|
|||||||
self.canvas:removeLayer()
|
self.canvas:removeLayer()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- need to get the current canvas - not ui.term.canvas
|
self.canvas = self:addLayer(self.backgroundColor, self.textColor)
|
||||||
self.canvas = UI.term.canvas:addLayer(self, self.backgroundColor, self.textColor or colors.white)
|
|
||||||
self:addTransition('expandUp', { ticks = self.height })
|
self:addTransition('expandUp', { ticks = self.height })
|
||||||
self.canvas:setVisible(true)
|
self.canvas:setVisible(true)
|
||||||
self:clear()
|
self:clear()
|
||||||
@ -2461,12 +2375,6 @@ UI.Throttle.defaults = {
|
|||||||
' //) (O ). @ \\-d ) (@ '
|
' //) (O ). @ \\-d ) (@ '
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function UI.Throttle:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.Throttle, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.Throttle:setParent()
|
function UI.Throttle:setParent()
|
||||||
self.x = math.ceil((self.parent.width - self.width) / 2)
|
self.x = math.ceil((self.parent.width - self.width) / 2)
|
||||||
self.y = math.ceil((self.parent.height - self.height) / 2)
|
self.y = math.ceil((self.parent.height - self.height) / 2)
|
||||||
@ -2495,7 +2403,7 @@ function UI.Throttle:update()
|
|||||||
self.c = os.clock()
|
self.c = os.clock()
|
||||||
self.enabled = true
|
self.enabled = true
|
||||||
if not self.canvas then
|
if not self.canvas then
|
||||||
self.canvas = UI.term.canvas:addLayer(self, self.backgroundColor, colors.cyan)
|
self.canvas = self:addLayer(self.backgroundColor, colors.cyan)
|
||||||
self.canvas:setVisible(true)
|
self.canvas:setVisible(true)
|
||||||
self:clear(colors.cyan)
|
self:clear(colors.cyan)
|
||||||
end
|
end
|
||||||
@ -2520,11 +2428,6 @@ UI.StatusBar.defaults = {
|
|||||||
height = 1,
|
height = 1,
|
||||||
ey = -1,
|
ey = -1,
|
||||||
}
|
}
|
||||||
function UI.StatusBar:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.StatusBar, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.StatusBar:adjustWidth()
|
function UI.StatusBar:adjustWidth()
|
||||||
-- Can only have 1 adjustable width
|
-- Can only have 1 adjustable width
|
||||||
if self.columns then
|
if self.columns then
|
||||||
@ -2624,11 +2527,6 @@ UI.ProgressBar.defaults = {
|
|||||||
height = 1,
|
height = 1,
|
||||||
value = 0,
|
value = 0,
|
||||||
}
|
}
|
||||||
function UI.ProgressBar:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.ProgressBar, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.ProgressBar:draw()
|
function UI.ProgressBar:draw()
|
||||||
self:clear()
|
self:clear()
|
||||||
local width = math.ceil(self.value / 100 * self.width)
|
local width = math.ceil(self.value / 100 * self.width)
|
||||||
@ -2644,11 +2542,6 @@ UI.VerticalMeter.defaults = {
|
|||||||
width = 1,
|
width = 1,
|
||||||
value = 0,
|
value = 0,
|
||||||
}
|
}
|
||||||
function UI.VerticalMeter:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.VerticalMeter, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.VerticalMeter:draw()
|
function UI.VerticalMeter:draw()
|
||||||
local height = self.height - math.ceil(self.value / 100 * self.height)
|
local height = self.height - math.ceil(self.value / 100 * self.height)
|
||||||
self:clear()
|
self:clear()
|
||||||
@ -2672,9 +2565,7 @@ UI.TextEntry.defaults = {
|
|||||||
[ 'control-c' ] = 'copy',
|
[ 'control-c' ] = 'copy',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function UI.TextEntry:init(args)
|
function UI.TextEntry:postInit()
|
||||||
local defaults = UI:getDefaults(UI.TextEntry, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
self.value = tostring(self.value)
|
self.value = tostring(self.value)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2721,6 +2612,9 @@ function UI.TextEntry:draw()
|
|||||||
if self.scroll and self.scroll > 0 then
|
if self.scroll and self.scroll > 0 then
|
||||||
text = text:sub(1 + self.scroll)
|
text = text:sub(1 + self.scroll)
|
||||||
end
|
end
|
||||||
|
if self.mask then
|
||||||
|
text = _rep('*', #text)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
tc = colors.gray
|
tc = colors.gray
|
||||||
text = self.shadowText
|
text = self.shadowText
|
||||||
@ -2844,15 +2738,9 @@ UI.Chooser.defaults = {
|
|||||||
UIElement = 'Chooser',
|
UIElement = 'Chooser',
|
||||||
choices = { },
|
choices = { },
|
||||||
nochoice = 'Select',
|
nochoice = 'Select',
|
||||||
--backgroundColor = colors.lightGray,
|
|
||||||
backgroundFocusColor = colors.lightGray,
|
backgroundFocusColor = colors.lightGray,
|
||||||
height = 1,
|
height = 1,
|
||||||
}
|
}
|
||||||
function UI.Chooser:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.Chooser, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.Chooser:setParent()
|
function UI.Chooser:setParent()
|
||||||
if not self.width and not self.ex then
|
if not self.width and not self.ex then
|
||||||
self.width = 1
|
self.width = 1
|
||||||
@ -2926,11 +2814,6 @@ UI.Text.defaults = {
|
|||||||
value = '',
|
value = '',
|
||||||
height = 1,
|
height = 1,
|
||||||
}
|
}
|
||||||
function UI.Text:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.Text, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.Text:setParent()
|
function UI.Text:setParent()
|
||||||
if not self.width and not self.ex then
|
if not self.width and not self.ex then
|
||||||
self.width = #tostring(self.value)
|
self.width = #tostring(self.value)
|
||||||
@ -2956,10 +2839,6 @@ UI.ScrollBar.defaults = {
|
|||||||
x = -1,
|
x = -1,
|
||||||
ey = -1,
|
ey = -1,
|
||||||
}
|
}
|
||||||
function UI.ScrollBar:init(args)
|
|
||||||
UI.Window.init(self, UI:getDefaults(UI.ScrollBar, args))
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.ScrollBar:draw()
|
function UI.ScrollBar:draw()
|
||||||
local parent = self.parent
|
local parent = self.parent
|
||||||
local view = parent:getViewArea()
|
local view = parent:getViewArea()
|
||||||
@ -3000,7 +2879,6 @@ function UI.ScrollBar:draw()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.ScrollBar:eventHandler(event)
|
function UI.ScrollBar:eventHandler(event)
|
||||||
|
|
||||||
if event.type == 'mouse_click' or event.type == 'mouse_doubleclick' then
|
if event.type == 'mouse_click' or event.type == 'mouse_doubleclick' then
|
||||||
if event.x == 1 then
|
if event.x == 1 then
|
||||||
local view = self.parent:getViewArea()
|
local view = self.parent:getViewArea()
|
||||||
@ -3025,8 +2903,7 @@ UI.TextArea.defaults = {
|
|||||||
marginRight = 2,
|
marginRight = 2,
|
||||||
value = '',
|
value = '',
|
||||||
}
|
}
|
||||||
function UI.TextArea:init(args)
|
function UI.TextArea:postInit()
|
||||||
UI.Viewport.init(self, UI:getDefaults(UI.TextArea, args))
|
|
||||||
self.scrollBar = UI.ScrollBar()
|
self.scrollBar = UI.ScrollBar()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3062,9 +2939,7 @@ UI.Form.defaults = {
|
|||||||
margin = 2,
|
margin = 2,
|
||||||
event = 'form_complete',
|
event = 'form_complete',
|
||||||
}
|
}
|
||||||
function UI.Form:init(args)
|
function UI.Form:postInit()
|
||||||
local defaults = UI:getDefaults(UI.Form, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
self:createForm()
|
self:createForm()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3185,20 +3060,17 @@ UI.Dialog.defaults = {
|
|||||||
textColor = colors.black,
|
textColor = colors.black,
|
||||||
backgroundColor = colors.white,
|
backgroundColor = colors.white,
|
||||||
}
|
}
|
||||||
function UI.Dialog:init(args)
|
function UI.Dialog:postInit()
|
||||||
local defaults = UI:getDefaults(UI.Dialog, args)
|
self.titleBar = UI.TitleBar({ previousPage = true, title = self.title })
|
||||||
|
|
||||||
if not defaults.width then
|
|
||||||
defaults.width = UI.term.width-11
|
|
||||||
end
|
|
||||||
defaults.titleBar = UI.TitleBar({ previousPage = true, title = defaults.title })
|
|
||||||
UI.Page.init(self, defaults)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Dialog:setParent()
|
function UI.Dialog:setParent()
|
||||||
UI.Window.setParent(self)
|
if not self.width then
|
||||||
|
self.width = self.parent.width - 11
|
||||||
|
end
|
||||||
self.x = math.floor((self.parent.width - self.width) / 2) + 1
|
self.x = math.floor((self.parent.width - self.width) / 2) + 1
|
||||||
self.y = math.floor((self.parent.height - self.height) / 2) + 1
|
self.y = math.floor((self.parent.height - self.height) / 2) + 1
|
||||||
|
UI.Page.setParent(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Dialog:disable()
|
function UI.Dialog:disable()
|
||||||
@ -3226,11 +3098,6 @@ UI.Image.defaults = {
|
|||||||
UIElement = 'Image',
|
UIElement = 'Image',
|
||||||
event = 'button_press',
|
event = 'button_press',
|
||||||
}
|
}
|
||||||
function UI.Image:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.Image, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.Image:setParent()
|
function UI.Image:setParent()
|
||||||
if self.image then
|
if self.image then
|
||||||
self.height = #self.image
|
self.height = #self.image
|
||||||
@ -3270,11 +3137,6 @@ UI.NftImage.defaults = {
|
|||||||
UIElement = 'NftImage',
|
UIElement = 'NftImage',
|
||||||
event = 'button_press',
|
event = 'button_press',
|
||||||
}
|
}
|
||||||
function UI.NftImage:init(args)
|
|
||||||
local defaults = UI:getDefaults(UI.NftImage, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.NftImage:setParent()
|
function UI.NftImage:setParent()
|
||||||
if self.image then
|
if self.image then
|
||||||
self.height = self.image.height
|
self.height = self.image.height
|
||||||
@ -3286,7 +3148,6 @@ function UI.NftImage:setParent()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function UI.NftImage:draw()
|
function UI.NftImage:draw()
|
||||||
-- self:clear()
|
|
||||||
if self.image then
|
if self.image then
|
||||||
for y = 1, self.image.height do
|
for y = 1, self.image.height do
|
||||||
for x = 1, #self.image.text[y] do
|
for x = 1, #self.image.text[y] do
|
||||||
|
@ -22,8 +22,6 @@ end
|
|||||||
function Canvas:init(args)
|
function Canvas:init(args)
|
||||||
self.x = 1
|
self.x = 1
|
||||||
self.y = 1
|
self.y = 1
|
||||||
self.bg = colors.black
|
|
||||||
self.fg = colors.white
|
|
||||||
self.layers = { }
|
self.layers = { }
|
||||||
|
|
||||||
Util.merge(self, args)
|
Util.merge(self, args)
|
||||||
@ -88,7 +86,7 @@ function Canvas:copy()
|
|||||||
return b
|
return b
|
||||||
end
|
end
|
||||||
|
|
||||||
function Canvas:addLayer(layer, bg, fg)
|
function Canvas:addLayer(layer)
|
||||||
local canvas = Canvas({
|
local canvas = Canvas({
|
||||||
x = layer.x,
|
x = layer.x,
|
||||||
y = layer.y,
|
y = layer.y,
|
||||||
@ -96,8 +94,6 @@ function Canvas:addLayer(layer, bg, fg)
|
|||||||
height = layer.height,
|
height = layer.height,
|
||||||
isColor = self.isColor,
|
isColor = self.isColor,
|
||||||
})
|
})
|
||||||
canvas:clear(bg, fg)
|
|
||||||
|
|
||||||
canvas.parent = self
|
canvas.parent = self
|
||||||
table.insert(self.layers, canvas)
|
table.insert(self.layers, canvas)
|
||||||
return canvas
|
return canvas
|
||||||
@ -199,8 +195,8 @@ end
|
|||||||
|
|
||||||
function Canvas:clear(bg, fg)
|
function Canvas:clear(bg, fg)
|
||||||
local text = _rep(' ', self.width)
|
local text = _rep(' ', self.width)
|
||||||
fg = _rep(self.palette[fg or self.fg], self.width)
|
fg = _rep(self.palette[fg or colors.white], self.width)
|
||||||
bg = _rep(self.palette[bg or self.bg], self.width)
|
bg = _rep(self.palette[bg or colors.black], self.width)
|
||||||
for i = 1, self.height do
|
for i = 1, self.height do
|
||||||
self:writeLine(i, text, fg, bg)
|
self:writeLine(i, text, fg, bg)
|
||||||
end
|
end
|
||||||
|
@ -204,7 +204,7 @@ function page:setResult(result)
|
|||||||
if Util.size(v) == 0 then
|
if Util.size(v) == 0 then
|
||||||
entry.value = 'table: (empty)'
|
entry.value = 'table: (empty)'
|
||||||
else
|
else
|
||||||
entry.value = 'table'
|
entry.value = tostring(v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.insert(t, entry)
|
table.insert(t, entry)
|
||||||
|
@ -34,6 +34,7 @@ local page = UI.Page {
|
|||||||
UI.MenuBar.spacer,
|
UI.MenuBar.spacer,
|
||||||
{ text = 'Reboot r', event = 'reboot' },
|
{ text = 'Reboot r', event = 'reboot' },
|
||||||
} },
|
} },
|
||||||
|
{ text = 'Chat', event = 'chat' },
|
||||||
{ text = 'Trust', dropdown = {
|
{ text = 'Trust', dropdown = {
|
||||||
{ text = 'Establish', event = 'trust' },
|
{ text = 'Establish', event = 'trust' },
|
||||||
{ text = 'Remove', event = 'untrust' },
|
{ text = 'Remove', event = 'untrust' },
|
||||||
@ -81,7 +82,7 @@ end
|
|||||||
function page:eventHandler(event)
|
function page:eventHandler(event)
|
||||||
local t = self.grid:getSelected()
|
local t = self.grid:getSelected()
|
||||||
if t then
|
if t then
|
||||||
if event.type == 'telnet' or event.type == 'grid_select' then
|
if event.type == 'telnet' then
|
||||||
multishell.openTab({
|
multishell.openTab({
|
||||||
path = 'sys/apps/telnet.lua',
|
path = 'sys/apps/telnet.lua',
|
||||||
focused = true,
|
focused = true,
|
||||||
@ -108,6 +109,13 @@ function page:eventHandler(event)
|
|||||||
trustList[t.id] = nil
|
trustList[t.id] = nil
|
||||||
Util.writeTable('usr/.known_hosts', trustList)
|
Util.writeTable('usr/.known_hosts', trustList)
|
||||||
|
|
||||||
|
elseif event.type == 'chat' then
|
||||||
|
multishell.openTab({
|
||||||
|
path = 'sys/apps/shell',
|
||||||
|
args = { 'chat join opusChat-' .. t.id .. ' guest'},
|
||||||
|
title = 'Chatroom',
|
||||||
|
focused = true,
|
||||||
|
})
|
||||||
elseif event.type == 'reboot' then
|
elseif event.type == 'reboot' then
|
||||||
sendCommand(t.id, 'reboot')
|
sendCommand(t.id, 'reboot')
|
||||||
|
|
||||||
|
@ -118,12 +118,12 @@ local function parseIcon(iconText)
|
|||||||
end
|
end
|
||||||
|
|
||||||
UI.VerticalTabBar = class(UI.TabBar)
|
UI.VerticalTabBar = class(UI.TabBar)
|
||||||
function UI.VerticalTabBar:init(args)
|
function UI.VerticalTabBar:setParent()
|
||||||
UI.TabBar.init(self, args)
|
|
||||||
self.x = 1
|
self.x = 1
|
||||||
self.width = 8
|
self.width = 8
|
||||||
self.height = nil
|
self.height = nil
|
||||||
self.ey = -1
|
self.ey = -1
|
||||||
|
UI.TabBar.setParent(self)
|
||||||
for k,c in pairs(self.children) do
|
for k,c in pairs(self.children) do
|
||||||
c.x = 1
|
c.x = 1
|
||||||
c.y = k + 1
|
c.y = k + 1
|
||||||
@ -160,16 +160,11 @@ local page = UI.Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UI.Icon = class(UI.Window)
|
UI.Icon = class(UI.Window)
|
||||||
function UI.Icon:init(args)
|
UI.Icon.defaults = {
|
||||||
local defaults = {
|
|
||||||
UIElement = 'Icon',
|
UIElement = 'Icon',
|
||||||
width = 14,
|
width = 14,
|
||||||
height = 4,
|
height = 4,
|
||||||
}
|
}
|
||||||
UI:setProperties(defaults, args)
|
|
||||||
UI.Window.init(self, defaults)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.Icon:eventHandler(event)
|
function UI.Icon:eventHandler(event)
|
||||||
if event.type == 'mouse_click' then
|
if event.type == 'mouse_click' then
|
||||||
self:setFocus(self.button)
|
self:setFocus(self.button)
|
||||||
@ -498,7 +493,6 @@ function editor:eventHandler(event)
|
|||||||
width = self.width,
|
width = self.width,
|
||||||
height = self.height,
|
height = self.height,
|
||||||
})
|
})
|
||||||
--fileui:setTransition(UI.effect.explode)
|
|
||||||
UI:setPage(fileui, fs.getDir(self.iconFile), function(fileName)
|
UI:setPage(fileui, fs.getDir(self.iconFile), function(fileName)
|
||||||
if fileName then
|
if fileName then
|
||||||
self.iconFile = fileName
|
self.iconFile = fileName
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
_G.requireInjector()
|
_G.requireInjector()
|
||||||
|
|
||||||
local Config = require('config')
|
local Config = require('config')
|
||||||
|
local Security = require('security')
|
||||||
|
local SHA1 = require('sha1')
|
||||||
local UI = require('ui')
|
local UI = require('ui')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
@ -24,7 +26,7 @@ end
|
|||||||
local env = {
|
local env = {
|
||||||
path = shell.path(),
|
path = shell.path(),
|
||||||
aliases = shell.aliases(),
|
aliases = shell.aliases(),
|
||||||
lua_path = LUA_PATH,
|
lua_path = _ENV.LUA_PATH,
|
||||||
}
|
}
|
||||||
Config.load('shell', env)
|
Config.load('shell', env)
|
||||||
|
|
||||||
@ -77,6 +79,36 @@ local systemPage = UI.Page {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
passwordTab = UI.Window {
|
||||||
|
tabTitle = 'Password',
|
||||||
|
oldPass = UI.TextEntry {
|
||||||
|
x = 2, y = 2, ex = -2,
|
||||||
|
limit = 32,
|
||||||
|
mask = true,
|
||||||
|
shadowText = 'old password',
|
||||||
|
inactive = not Security.getPassword(),
|
||||||
|
},
|
||||||
|
newPass = UI.TextEntry {
|
||||||
|
y = 3, x = 2, ex = -2,
|
||||||
|
limit = 32,
|
||||||
|
mask = true,
|
||||||
|
shadowText = 'new password',
|
||||||
|
accelerators = {
|
||||||
|
enter = 'new_password',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
button = UI.Button {
|
||||||
|
x = 2, y = 5,
|
||||||
|
text = 'Update',
|
||||||
|
event = 'update_password',
|
||||||
|
},
|
||||||
|
info = UI.TextArea {
|
||||||
|
x = 2, ex = -2,
|
||||||
|
y = 7,
|
||||||
|
value = 'Add a password to enable other computers to connect to this one.',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
infoTab = UI.Window {
|
infoTab = UI.Window {
|
||||||
tabTitle = 'Info',
|
tabTitle = 'Info',
|
||||||
labelText = UI.Text {
|
labelText = UI.Text {
|
||||||
@ -205,6 +237,22 @@ function systemPage.tabs.aliasTab:eventHandler(event)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function systemPage.tabs.passwordTab:eventHandler(event)
|
||||||
|
if event.type == 'update_password' then
|
||||||
|
if #self.newPass.value == 0 then
|
||||||
|
systemPage.notification:error('Invalid password')
|
||||||
|
elseif Security.getPassword() and not Security.verifyPassword(SHA1.sha1(self.oldPass.value)) then
|
||||||
|
systemPage.notification:error('Passwords do not match')
|
||||||
|
else
|
||||||
|
Security.updatePassword(SHA1.sha1(self.newPass.value))
|
||||||
|
self.oldPass.inactive = false
|
||||||
|
systemPage.notification:success('Password updated')
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function systemPage.tabs.infoTab:eventHandler(event)
|
function systemPage.tabs.infoTab:eventHandler(event)
|
||||||
if event.type == 'update_label' then
|
if event.type == 'update_label' then
|
||||||
os.setComputerLabel(self.label.value)
|
os.setComputerLabel(self.label.value)
|
||||||
|
@ -395,6 +395,13 @@ function multishell.hideTab(tabId)
|
|||||||
local tab = tabs[tabId]
|
local tab = tabs[tabId]
|
||||||
if tab then
|
if tab then
|
||||||
tab.hidden = true
|
tab.hidden = true
|
||||||
|
if currentTab.tabId == tabId then
|
||||||
|
if tabs[currentTab.previousTabId] then
|
||||||
|
multishell.setFocus(currentTab.previousTabId)
|
||||||
|
else
|
||||||
|
multishell.setFocus(overviewTab.tabId)
|
||||||
|
end
|
||||||
|
end
|
||||||
redrawMenu()
|
redrawMenu()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -29,10 +29,10 @@ if not password then
|
|||||||
end
|
end
|
||||||
|
|
||||||
print('connecting...')
|
print('connecting...')
|
||||||
local socket = Socket.connect(remoteId, 19)
|
local socket, msg = Socket.connect(remoteId, 19)
|
||||||
|
|
||||||
if not socket then
|
if not socket then
|
||||||
error('Unable to connect to ' .. remoteId .. ' on port 19')
|
error(msg)
|
||||||
end
|
end
|
||||||
|
|
||||||
local publicKey = Security.getPublicKey()
|
local publicKey = Security.getPublicKey()
|
||||||
|
@ -222,7 +222,7 @@
|
|||||||
[ "d8c298dd41e4a4ec20e8307901797b64688b3b77" ] = {
|
[ "d8c298dd41e4a4ec20e8307901797b64688b3b77" ] = {
|
||||||
title = "GPS Deploy",
|
title = "GPS Deploy",
|
||||||
category = "Apps",
|
category = "Apps",
|
||||||
run = "http://pastebin.com/raw/qLthLak5",
|
run = "http://pastebin.com/raw/VXAyXqBv",
|
||||||
requires = "turtle",
|
requires = "turtle",
|
||||||
},
|
},
|
||||||
[ "53a5d150062b1e03206b9e15854b81060e3c7552" ] = {
|
[ "53a5d150062b1e03206b9e15854b81060e3c7552" ] = {
|
||||||
|
58
sys/services/chat.lua
Normal file
58
sys/services/chat.lua
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
local device = _G.device
|
||||||
|
local multishell = _ENV.multishell
|
||||||
|
local os = _G.os
|
||||||
|
local parallel = _G.parallel
|
||||||
|
|
||||||
|
if device.wireless_modem then
|
||||||
|
|
||||||
|
multishell.setTitle(multishell.getCurrent(), 'Chat Daemon')
|
||||||
|
|
||||||
|
local tab
|
||||||
|
|
||||||
|
local function chatClient()
|
||||||
|
|
||||||
|
_G.requireInjector()
|
||||||
|
|
||||||
|
local Event = require('event')
|
||||||
|
local Util = require('util')
|
||||||
|
|
||||||
|
local h = Event.addRoutine(function()
|
||||||
|
while true do
|
||||||
|
Util.run(_ENV, 'rom/programs/rednet/chat',
|
||||||
|
'join', 'opusChat-' .. os.getComputerID(), 'owner')
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local e = { os.pullEventRaw() }
|
||||||
|
if e[1] == 'terminate' then
|
||||||
|
multishell.hideTab(tab.tabId)
|
||||||
|
else
|
||||||
|
if e[1] == 'rednet_message' and e[4] == 'chat' and e[3].sType == 'chat' then
|
||||||
|
if tab.hidden then
|
||||||
|
multishell.unhideTab(tab.tabId)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
h:resume(unpack(e))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
parallel.waitForAll(
|
||||||
|
function()
|
||||||
|
os.run(_ENV, 'rom/programs/rednet/chat',
|
||||||
|
'host', 'opusChat-' .. os.getComputerID())
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
os.sleep(3)
|
||||||
|
local tabId = multishell.openTab({
|
||||||
|
fn = chatClient,
|
||||||
|
title = 'Chatroom',
|
||||||
|
hidden = true,
|
||||||
|
})
|
||||||
|
tab = multishell.getTab(tabId)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
print('Chat daemon stopped')
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user