mirror of
https://github.com/kepler155c/opus
synced 2025-04-10 09:36:39 +00:00
partition manager + tab/wizard rework
This commit is contained in:
parent
b0d2ce0199
commit
ef9f0e09b6
@ -45,8 +45,9 @@ local page = UI.Page {
|
||||
},
|
||||
tabs = UI.Tabs {
|
||||
y = 3,
|
||||
[1] = UI.Tab {
|
||||
tabTitle = 'Formatted',
|
||||
formatted = UI.Tab {
|
||||
title = 'Formatted',
|
||||
index = 1,
|
||||
grid = UI.ScrollingGrid {
|
||||
columns = {
|
||||
{ heading = 'Key', key = 'name' },
|
||||
@ -56,8 +57,9 @@ local page = UI.Page {
|
||||
autospace = true,
|
||||
},
|
||||
},
|
||||
[2] = UI.Tab {
|
||||
tabTitle = 'Output',
|
||||
output = UI.Tab {
|
||||
title = 'Output',
|
||||
index = 2,
|
||||
backgroundColor = 'black',
|
||||
output = UI.Embedded {
|
||||
y = 2,
|
||||
@ -72,8 +74,8 @@ local page = UI.Page {
|
||||
},
|
||||
}
|
||||
|
||||
page.grid = page.tabs[1].grid
|
||||
page.output = page.tabs[2].output
|
||||
page.grid = page.tabs.formatted.grid
|
||||
page.output = page.tabs.output.output
|
||||
|
||||
function page:setPrompt(value, focus)
|
||||
self.prompt:setValue(value)
|
||||
@ -142,7 +144,7 @@ function page:eventHandler(event)
|
||||
self:setFocus(self.prompt)
|
||||
|
||||
elseif event.type == 'show_output' then
|
||||
self.tabs:selectTab(self.tabs[2])
|
||||
self.tabs:selectTab(self.tabs.output)
|
||||
|
||||
elseif event.type == 'autocomplete' then
|
||||
local value = self.prompt.value or ''
|
||||
|
@ -29,12 +29,14 @@ if not _ENV.multishell then
|
||||
end
|
||||
|
||||
local REGISTRY_DIR = 'usr/.registry'
|
||||
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")
|
||||
local TRANS_ICON = NFT.parse("\0302\0312\32\32\32\32\32\
|
||||
|
||||
-- icon:gsub('.', function(b) return '\\' .. b:byte() end)
|
||||
local DEFAULT_ICON = NFT.parse('\30\55\31\48\136\140\140\140\132\
|
||||
\30\48\31\55\149\31\48\128\128\128\30\55\149\
|
||||
\30\55\31\48\138\143\143\143\133')
|
||||
local TRANS_ICON = NFT.parse('\0302\0312\32\32\32\32\32\
|
||||
\0302\0312\32\32\32\32\32\
|
||||
\0302\0312\32\32\32\32\32")
|
||||
\0302\0312\32\32\32\32\32')
|
||||
|
||||
-- overview
|
||||
local uid = _ENV.multishell.getCurrent()
|
||||
|
238
sys/apps/Partition.lua
Normal file
238
sys/apps/Partition.lua
Normal file
@ -0,0 +1,238 @@
|
||||
local Ansi = require('opus.ansi')
|
||||
local Event = require('opus.event')
|
||||
local UI = require('opus.ui')
|
||||
local Util = require('opus.util')
|
||||
|
||||
local fs = _G.fs
|
||||
local peripheral = _G.peripheral
|
||||
|
||||
local source, target
|
||||
|
||||
local function getDriveInfo(tgt)
|
||||
local total = 0
|
||||
local throttle = Util.throttle()
|
||||
|
||||
tgt = fs.combine(tgt, '')
|
||||
local src = fs.getNode(tgt).source or tgt
|
||||
|
||||
local function recurse(path)
|
||||
throttle()
|
||||
if fs.isDir(path) then
|
||||
if path ~= src then
|
||||
total = total + 500
|
||||
end
|
||||
for _, v in pairs(fs.native.list(path)) do
|
||||
recurse(fs.combine(path, v))
|
||||
end
|
||||
else
|
||||
local sz = fs.getSize(path)
|
||||
total = total + math.max(500, sz)
|
||||
end
|
||||
end
|
||||
|
||||
recurse(src)
|
||||
|
||||
local drive = fs.getDrive(src)
|
||||
return {
|
||||
path = tgt,
|
||||
drive = drive,
|
||||
type = peripheral.getType(drive) or drive,
|
||||
used = total,
|
||||
free = fs.getFreeSpace(src),
|
||||
mountPoint = src,
|
||||
}
|
||||
end
|
||||
|
||||
local function getDrives(exclude)
|
||||
local drives = { }
|
||||
|
||||
for _, path in pairs(fs.native.list('/')) do
|
||||
local side = fs.getDrive(path)
|
||||
if side and not drives[side] and not fs.isReadOnly(path) and side ~= exclude then
|
||||
if side == 'hdd' then
|
||||
path = ''
|
||||
end
|
||||
drives[side] = getDriveInfo(path)
|
||||
end
|
||||
end
|
||||
return drives
|
||||
end
|
||||
|
||||
local page = UI.Page {
|
||||
wizard = UI.Wizard {
|
||||
ey = -2,
|
||||
partitions = UI.WizardPage {
|
||||
index = 1,
|
||||
info = UI.TextArea {
|
||||
x = 3, y = 2, ex = -3, ey = 5,
|
||||
value = [[Move the contents of a directory to another disk. A link will be created to point to that location.]]
|
||||
},
|
||||
grid = UI.Grid {
|
||||
x = 2, y = 7, ex = -2, ey = -2,
|
||||
columns = {
|
||||
{ heading = 'Path', key = 'path', textColor = 'yellow', width = 10 },
|
||||
{ heading = 'Mount Point', key = 'mountPoint' },
|
||||
{ heading = 'Used', key = 'used', width = 6 },
|
||||
},
|
||||
sortColumn = 'path',
|
||||
getDisplayValues = function (_, row)
|
||||
row = Util.shallowCopy(row)
|
||||
row.used = Util.toBytes(row.used)
|
||||
return row
|
||||
end,
|
||||
enable = function(self)
|
||||
Event.onTimeout(0, function()
|
||||
local mounts = {
|
||||
usr = getDriveInfo('usr/config'),
|
||||
packages = getDriveInfo('packages'),
|
||||
}
|
||||
self:setValues(mounts)
|
||||
self:draw()
|
||||
self:sync()
|
||||
end)
|
||||
self:setValues({ })
|
||||
UI.Grid.enable(self)
|
||||
end,
|
||||
},
|
||||
validate = function(self)
|
||||
target = self.grid:getSelected()
|
||||
return not not target
|
||||
end,
|
||||
},
|
||||
mounts = UI.WizardPage {
|
||||
index = 2,
|
||||
info = UI.TextArea {
|
||||
x = 3, y = 2, ex = -3, ey = 5,
|
||||
value = [[Select the target disk. Labeled computers can be inserted into disk drives for larger volumes.]]
|
||||
},
|
||||
grid = UI.Grid {
|
||||
x = 2, y = 7, ex = -2, ey = -2,
|
||||
columns = {
|
||||
{ heading = 'Path', key = 'path', textColor = 'yellow', width = 10 },
|
||||
{ heading = 'Type', key = 'type' },
|
||||
{ heading = 'Side', key = 'drive' },
|
||||
{ heading = 'Free', key = 'free', width = 6 },
|
||||
},
|
||||
sortColumn = 'path',
|
||||
getDisplayValues = function (_, row)
|
||||
row = Util.shallowCopy(row)
|
||||
row.free = Util.toBytes(row.free)
|
||||
return row
|
||||
end,
|
||||
getRowTextColor = function(self, row)
|
||||
if row.free < target.used then
|
||||
return 'lightGray'
|
||||
end
|
||||
return UI.Grid.getRowTextColor(self, row)
|
||||
end,
|
||||
enable = function(self)
|
||||
Event.on({ 'disk', 'disk_eject', 'partition_update' }, function()
|
||||
self:setValues(getDrives(target.drive))
|
||||
self:draw()
|
||||
self:sync()
|
||||
end)
|
||||
os.queueEvent('partition_update')
|
||||
self:setValues({ })
|
||||
UI.Grid.enable(self)
|
||||
end,
|
||||
},
|
||||
validate = function(self)
|
||||
source = self.grid:getSelected()
|
||||
if not source then
|
||||
self:emit({ type = 'notify', message = 'No drive selected' })
|
||||
elseif source.free < target.used then
|
||||
self:emit({ type = 'notify', message = 'Insufficient disk space' })
|
||||
else
|
||||
return true
|
||||
end
|
||||
end,
|
||||
},
|
||||
confirm = UI.WizardPage {
|
||||
index = 3,
|
||||
info = UI.TextArea {
|
||||
x = 2, y = 2, ex = -2, ey = -2,
|
||||
marginTop = 1, marginLeft = 1,
|
||||
backgroundColor = 'black',
|
||||
},
|
||||
enable = function(self)
|
||||
local fstab = Util.readFile('usr/etc/fstab')
|
||||
local lines = { }
|
||||
table.insert(lines, string.format('%sReview changes%s\n', Ansi.yellow, Ansi.reset))
|
||||
if fstab then
|
||||
for _,l in ipairs(Util.split(fstab)) do
|
||||
l = Util.trim(l)
|
||||
if #l > 0 and l:sub(1, 1) ~= '#' then
|
||||
local m = Util.matches(l)
|
||||
if m and m[1] and m[1] == target.path then
|
||||
table.insert(lines, string.format('Removed from usr/etc/fstab:\n%s%s%s\n', Ansi.red, l, Ansi.reset))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local t = target.path
|
||||
local s = fs.combine(source.path .. '/' .. target.path, '')
|
||||
if t ~= s then
|
||||
table.insert(lines, string.format('Added to usr/etc/fstab:\n%s%s linkfs %s%s\n', Ansi.green, t, s, Ansi.reset))
|
||||
end
|
||||
|
||||
table.insert(lines, string.format('Move directory:\n%s/%s -> /%s', Ansi.green, target.mountPoint, s))
|
||||
|
||||
self.info:setText(table.concat(lines, '\n'))
|
||||
UI.WizardPage.enable(self)
|
||||
end,
|
||||
validate = function(self)
|
||||
if self.changesApplied then
|
||||
return true
|
||||
end
|
||||
local fstab = Util.readFile('usr/etc/fstab')
|
||||
local lines = { }
|
||||
if fstab then
|
||||
for _,l in ipairs(Util.split(fstab)) do
|
||||
table.insert(lines, l)
|
||||
l = Util.trim(l)
|
||||
if #l > 0 and l:sub(1, 1) ~= '#' then
|
||||
local m = Util.matches(l)
|
||||
if m and m[1] and m[1] == target.path then
|
||||
fs.unmount(m[1])
|
||||
table.remove(lines)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local t = target.path
|
||||
local s = fs.combine(source.path .. '/' .. target.path, '')
|
||||
|
||||
fs.move('/' .. target.mountPoint, '/' .. s)
|
||||
|
||||
if t ~= s then
|
||||
table.insert(lines, string.format('%s linkfs %s', t, s))
|
||||
fs.mount(t, 'linkfs', s)
|
||||
end
|
||||
|
||||
Util.writeFile('usr/etc/fstab', table.concat(lines, '\n'))
|
||||
|
||||
self.parent.nextButton.text = 'Exit'
|
||||
self.parent.cancelButton:disable()
|
||||
self.parent.previousButton:disable()
|
||||
|
||||
self.changesApplied = true
|
||||
self.info:setValue('Changes have been applied')
|
||||
self.parent:draw()
|
||||
end,
|
||||
},
|
||||
},
|
||||
notification = UI.Notification { },
|
||||
eventHandler = function(self, event)
|
||||
if event.type == 'notify' then
|
||||
self.notification:error(event.message)
|
||||
elseif event.type == 'accept' or event.type == 'cancel' then
|
||||
UI:quit()
|
||||
end
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end,
|
||||
}
|
||||
|
||||
UI:disableEffects()
|
||||
UI:setPage(page)
|
||||
UI:start()
|
@ -46,7 +46,7 @@ local page = UI.Page {
|
||||
configTabs = UI.Tabs {
|
||||
y = 2,
|
||||
filterTab = UI.Tab {
|
||||
tabTitle = 'Filter',
|
||||
title = 'Filter',
|
||||
noFill = true,
|
||||
filterGridText = UI.Text {
|
||||
x = 2, y = 2,
|
||||
@ -93,7 +93,7 @@ local page = UI.Page {
|
||||
},
|
||||
},
|
||||
modemTab = UI.Tab {
|
||||
tabTitle = 'Modem',
|
||||
title = 'Modem',
|
||||
channelGrid = UI.ScrollingGrid {
|
||||
x = 2, y = 2,
|
||||
width = 12, height = 5,
|
||||
|
@ -6,62 +6,6 @@ local shell = _ENV.shell
|
||||
|
||||
UI:configure('System', ...)
|
||||
|
||||
local systemPage = UI.Page {
|
||||
tabs = UI.Tabs {
|
||||
settings = UI.Tab {
|
||||
tabTitle = 'Category',
|
||||
grid = UI.ScrollingGrid {
|
||||
x = 2, y = 2, ex = -2, ey = -2,
|
||||
columns = {
|
||||
{ heading = 'Name', key = 'name' },
|
||||
{ heading = 'Description', key = 'description' },
|
||||
},
|
||||
sortColumn = 'name',
|
||||
autospace = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
notification = UI.Notification(),
|
||||
accelerators = {
|
||||
[ 'control-q' ] = 'quit',
|
||||
},
|
||||
}
|
||||
|
||||
function systemPage.tabs.settings:eventHandler(event)
|
||||
if event.type == 'grid_select' then
|
||||
local tab = event.selected.tab
|
||||
if not systemPage.tabs[tab.tabTitle] then
|
||||
systemPage.tabs:add({ [ tab.tabTitle ] = tab })
|
||||
tab:disable()
|
||||
end
|
||||
systemPage.tabs:selectTab(tab)
|
||||
--self.parent:draw()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function systemPage:eventHandler(event)
|
||||
if event.type == 'quit' then
|
||||
UI:quit()
|
||||
|
||||
elseif event.type == 'success_message' then
|
||||
self.notification:success(event.message)
|
||||
|
||||
elseif event.type == 'info_message' then
|
||||
self.notification:info(event.message)
|
||||
|
||||
elseif event.type == 'error_message' then
|
||||
self.notification:error(event.message)
|
||||
|
||||
elseif event.type == 'tab_activate' then
|
||||
event.activated:focusFirst()
|
||||
|
||||
else
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function loadDirectory(dir)
|
||||
local plugins = { }
|
||||
for _, file in pairs(fs.list(dir)) do
|
||||
@ -70,7 +14,7 @@ local function loadDirectory(dir)
|
||||
_G.printError('Error loading: ' .. file)
|
||||
error(m or 'Unknown error')
|
||||
elseif s and m then
|
||||
table.insert(plugins, { tab = m, name = m.tabTitle, description = m.description })
|
||||
table.insert(plugins, { tab = m, name = m.title, description = m.description })
|
||||
end
|
||||
end
|
||||
return plugins
|
||||
@ -79,7 +23,60 @@ end
|
||||
local programDir = fs.getDir(shell.getRunningProgram())
|
||||
local plugins = loadDirectory(fs.combine(programDir, 'system'), { })
|
||||
|
||||
systemPage.tabs.settings.grid:setValues(plugins)
|
||||
local page = UI.Page {
|
||||
tabs = UI.Tabs {
|
||||
settings = UI.Tab {
|
||||
title = 'Category',
|
||||
grid = UI.ScrollingGrid {
|
||||
x = 2, y = 2, ex = -2, ey = -2,
|
||||
columns = {
|
||||
{ heading = 'Name', key = 'name' },
|
||||
{ heading = 'Description', key = 'description' },
|
||||
},
|
||||
sortColumn = 'name',
|
||||
autospace = true,
|
||||
values = plugins,
|
||||
},
|
||||
accelerators = {
|
||||
grid_select = 'category_select',
|
||||
}
|
||||
},
|
||||
},
|
||||
notification = UI.Notification(),
|
||||
accelerators = {
|
||||
[ 'control-q' ] = 'quit',
|
||||
},
|
||||
eventHandler = function(self, event)
|
||||
if event.type == 'quit' then
|
||||
UI:quit()
|
||||
|
||||
UI:setPage(systemPage)
|
||||
elseif event.type == 'category_select' then
|
||||
local tab = event.selected.tab
|
||||
|
||||
if not self.tabs[tab.title] then
|
||||
self.tabs:add({ [ tab.title ] = tab })
|
||||
end
|
||||
self.tabs:selectTab(tab)
|
||||
return true
|
||||
|
||||
elseif event.type == 'success_message' then
|
||||
self.notification:success(event.message)
|
||||
|
||||
elseif event.type == 'info_message' then
|
||||
self.notification:info(event.message)
|
||||
|
||||
elseif event.type == 'error_message' then
|
||||
self.notification:error(event.message)
|
||||
|
||||
elseif event.type == 'tab_activate' then
|
||||
event.activated:focusFirst()
|
||||
|
||||
else
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
return true
|
||||
end,
|
||||
}
|
||||
|
||||
UI:setPage(page)
|
||||
UI:start()
|
||||
|
@ -33,87 +33,85 @@ https://github.com/kepler155c/opus]]
|
||||
local page = UI.Page {
|
||||
wizard = UI.Wizard {
|
||||
ey = -2,
|
||||
pages = {
|
||||
splash = UI.WizardPage {
|
||||
index = 1,
|
||||
intro = UI.TextArea {
|
||||
textColor = colors.yellow,
|
||||
inactive = true,
|
||||
x = 3, ex = -3, y = 2, ey = -2,
|
||||
value = string.format(splashIntro, Ansi.white),
|
||||
},
|
||||
splash = UI.WizardPage {
|
||||
index = 1,
|
||||
intro = UI.TextArea {
|
||||
textColor = colors.yellow,
|
||||
inactive = true,
|
||||
x = 3, ex = -3, y = 2, ey = -2,
|
||||
value = string.format(splashIntro, Ansi.white),
|
||||
},
|
||||
label = UI.WizardPage {
|
||||
index = 2,
|
||||
labelText = UI.Text {
|
||||
x = 3, y = 2,
|
||||
value = 'Label'
|
||||
},
|
||||
label = UI.TextEntry {
|
||||
x = 9, y = 2, ex = -3,
|
||||
limit = 32,
|
||||
value = os.getComputerLabel(),
|
||||
},
|
||||
intro = UI.TextArea {
|
||||
textColor = colors.yellow,
|
||||
inactive = true,
|
||||
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,
|
||||
},
|
||||
label = UI.WizardPage {
|
||||
index = 2,
|
||||
labelText = UI.Text {
|
||||
x = 3, y = 2,
|
||||
value = 'Label'
|
||||
},
|
||||
password = UI.WizardPage {
|
||||
index = 3,
|
||||
passwordLabel = UI.Text {
|
||||
x = 3, y = 2,
|
||||
value = 'Password'
|
||||
},
|
||||
newPass = UI.TextEntry {
|
||||
x = 12, ex = -3, y = 2,
|
||||
limit = 32,
|
||||
mask = true,
|
||||
shadowText = 'password',
|
||||
},
|
||||
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,
|
||||
label = UI.TextEntry {
|
||||
x = 9, y = 2, ex = -3,
|
||||
limit = 32,
|
||||
value = os.getComputerLabel(),
|
||||
},
|
||||
packages = UI.WizardPage {
|
||||
index = 4,
|
||||
button = UI.Button {
|
||||
x = 3, y = -3,
|
||||
text = 'Open Package Manager',
|
||||
event = 'packages',
|
||||
},
|
||||
intro = UI.TextArea {
|
||||
textColor = colors.yellow,
|
||||
inactive = true,
|
||||
x = 3, ex = -3, y = 2, ey = -4,
|
||||
value = string.format(packagesIntro, Ansi.white),
|
||||
},
|
||||
intro = UI.TextArea {
|
||||
textColor = colors.yellow,
|
||||
inactive = true,
|
||||
x = 3, ex = -3, y = 4, ey = -3,
|
||||
value = string.format(labelIntro, Ansi.white),
|
||||
},
|
||||
contributors = UI.WizardPage {
|
||||
index = 5,
|
||||
intro = UI.TextArea {
|
||||
textColor = colors.yellow,
|
||||
inactive = true,
|
||||
x = 3, ex = -3, y = 2, ey = -2,
|
||||
value = string.format(contributorsIntro, Ansi.white, Ansi.yellow, Ansi.white),
|
||||
},
|
||||
validate = function (self)
|
||||
if self.label.value then
|
||||
os.setComputerLabel(self.label.value)
|
||||
end
|
||||
return true
|
||||
end,
|
||||
},
|
||||
password = UI.WizardPage {
|
||||
index = 3,
|
||||
passwordLabel = UI.Text {
|
||||
x = 3, y = 2,
|
||||
value = 'Password'
|
||||
},
|
||||
newPass = UI.TextEntry {
|
||||
x = 12, ex = -3, y = 2,
|
||||
limit = 32,
|
||||
mask = true,
|
||||
shadowText = 'password',
|
||||
},
|
||||
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,
|
||||
button = UI.Button {
|
||||
x = 3, y = -3,
|
||||
text = 'Open Package Manager',
|
||||
event = 'packages',
|
||||
},
|
||||
intro = UI.TextArea {
|
||||
textColor = colors.yellow,
|
||||
inactive = true,
|
||||
x = 3, ex = -3, y = 2, ey = -4,
|
||||
value = string.format(packagesIntro, Ansi.white),
|
||||
},
|
||||
},
|
||||
contributors = UI.WizardPage {
|
||||
index = 5,
|
||||
intro = UI.TextArea {
|
||||
textColor = colors.yellow,
|
||||
inactive = true,
|
||||
x = 3, ex = -3, y = 2, ey = -2,
|
||||
value = string.format(contributorsIntro, Ansi.white, Ansi.yellow, Ansi.white),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -49,7 +49,7 @@ page = UI.Page {
|
||||
backgroundColor = colors.red,
|
||||
y = '50%',
|
||||
properties = UI.Tab {
|
||||
tabTitle = 'Properties',
|
||||
title = 'Properties',
|
||||
grid = UI.ScrollingGrid {
|
||||
headerBackgroundColor = colors.red,
|
||||
sortColumn = 'key',
|
||||
@ -64,7 +64,7 @@ page = UI.Page {
|
||||
},
|
||||
methodsTab = UI.Tab {
|
||||
index = 2,
|
||||
tabTitle = 'Methods',
|
||||
title = 'Methods',
|
||||
grid = UI.ScrollingGrid {
|
||||
ex = '50%',
|
||||
headerBackgroundColor = colors.red,
|
||||
@ -85,7 +85,7 @@ page = UI.Page {
|
||||
},
|
||||
events = UI.Tab {
|
||||
index = 1,
|
||||
tabTitle = 'Events',
|
||||
title = 'Events',
|
||||
UI.MenuBar {
|
||||
y = -1,
|
||||
backgroundColor = colors.red,
|
||||
|
@ -4,7 +4,7 @@ local UI = require('opus.ui')
|
||||
local kernel = _G.kernel
|
||||
|
||||
local aliasTab = UI.Tab {
|
||||
tabTitle = 'Aliases',
|
||||
title = 'Aliases',
|
||||
description = 'Shell aliases',
|
||||
alias = UI.TextEntry {
|
||||
x = 2, y = 2, ex = -2,
|
||||
|
@ -3,7 +3,7 @@ local Config = require('opus.config')
|
||||
local UI = require('opus.ui')
|
||||
|
||||
local tab = UI.Tab {
|
||||
tabTitle = 'Preferred',
|
||||
title = 'Preferred',
|
||||
description = 'Select preferred applications',
|
||||
apps = UI.ScrollingGrid {
|
||||
x = 2, y = 2,
|
||||
|
@ -6,7 +6,7 @@ if _G.http.websocket then
|
||||
local config = Config.load('cloud')
|
||||
|
||||
local tab = UI.Tab {
|
||||
tabTitle = 'Cloud',
|
||||
title = 'Cloud',
|
||||
description = 'Cloud Catcher options',
|
||||
[1] = UI.Window {
|
||||
x = 2, y = 2, ex = -2, ey = 4,
|
||||
|
@ -16,7 +16,7 @@ local NftImages = {
|
||||
}
|
||||
|
||||
local tab = UI.Tab {
|
||||
tabTitle = 'Disks Usage',
|
||||
title = 'Disks Usage',
|
||||
description = 'Visualise HDD and disks usage',
|
||||
|
||||
drives = UI.ScrollingGrid {
|
||||
@ -138,11 +138,9 @@ function tab:enable()
|
||||
UI.Tab.enable(self)
|
||||
self.handler = Event.on({ 'disk', 'disk_eject' }, function()
|
||||
os.sleep(1)
|
||||
if tab.enabled then
|
||||
tab:updateDrives()
|
||||
tab:updateInfo()
|
||||
tab:sync()
|
||||
end
|
||||
tab:updateDrives()
|
||||
tab:updateInfo()
|
||||
tab:sync()
|
||||
end)
|
||||
end
|
||||
|
||||
|
@ -5,7 +5,7 @@ local peripheral = _G.peripheral
|
||||
local settings = _G.settings
|
||||
|
||||
return peripheral.find('monitor') and UI.Tab {
|
||||
tabTitle = 'Kiosk',
|
||||
title = 'Kiosk',
|
||||
description = 'Kiosk options',
|
||||
form = UI.Form {
|
||||
x = 2, y = 2, ex = -2, ey = 5,
|
||||
|
@ -5,7 +5,7 @@ local fs = _G.fs
|
||||
local os = _G.os
|
||||
|
||||
return UI.Tab {
|
||||
tabTitle = 'Label',
|
||||
title = 'Label',
|
||||
description = 'Set the computer label',
|
||||
labelText = UI.Text {
|
||||
x = 3, y = 3,
|
||||
|
@ -7,7 +7,7 @@ local fs = _G.fs
|
||||
local config = Config.load('multishell')
|
||||
|
||||
local tab = UI.Tab {
|
||||
tabTitle = 'Launcher',
|
||||
title = 'Launcher',
|
||||
description = 'Set the application launcher',
|
||||
[1] = UI.Window {
|
||||
x = 2, y = 2, ex = -2, ey = 5,
|
||||
|
@ -6,7 +6,7 @@ local colors = _G.colors
|
||||
local device = _G.device
|
||||
|
||||
return UI.Tab {
|
||||
tabTitle = 'Network',
|
||||
title = 'Network',
|
||||
description = 'Networking options',
|
||||
info = UI.TextArea {
|
||||
x = 2, y = 5, ex = -2, ey = -2,
|
||||
|
@ -3,7 +3,7 @@ local SHA = require('opus.crypto.sha2')
|
||||
local UI = require('opus.ui')
|
||||
|
||||
return UI.Tab {
|
||||
tabTitle = 'Password',
|
||||
title = 'Password',
|
||||
description = 'Wireless network password',
|
||||
[1] = UI.Window {
|
||||
x = 2, y = 2, ex = -2, ey = 4,
|
||||
|
@ -3,7 +3,7 @@ local UI = require('opus.ui')
|
||||
local Util = require('opus.util')
|
||||
|
||||
local tab = UI.Tab {
|
||||
tabTitle = 'Path',
|
||||
title = 'Path',
|
||||
description = 'Set the shell path',
|
||||
tabClose = true,
|
||||
[1] = UI.Window {
|
||||
|
@ -3,7 +3,7 @@ local UI = require('opus.ui')
|
||||
local Util = require('opus.util')
|
||||
|
||||
local tab = UI.Tab {
|
||||
tabTitle = 'Requires',
|
||||
title = 'Requires',
|
||||
description = 'Require path',
|
||||
tabClose = true,
|
||||
entry = UI.TextEntry {
|
||||
|
@ -8,7 +8,7 @@ local transform = {
|
||||
}
|
||||
|
||||
return settings and UI.Tab {
|
||||
tabTitle = 'Settings',
|
||||
title = 'Settings',
|
||||
description = 'Computercraft settings',
|
||||
grid = UI.Grid {
|
||||
x = 2, y = 2, ex = -2, ey = -2,
|
||||
|
@ -39,7 +39,7 @@ if not _colors.backgroundColor then
|
||||
end
|
||||
|
||||
return UI.Tab {
|
||||
tabTitle = 'Shell',
|
||||
title = 'Shell',
|
||||
description = 'Shell options',
|
||||
grid1 = UI.ScrollingGrid {
|
||||
y = 2, ey = -10, x = 2, ex = -17,
|
||||
|
@ -17,7 +17,7 @@ for k,v in pairs(UI.colors) do
|
||||
end
|
||||
|
||||
return UI.Tab {
|
||||
tabTitle = 'Theme',
|
||||
title = 'Theme',
|
||||
description = 'Theme colors',
|
||||
grid1 = UI.ScrollingGrid {
|
||||
y = 2, ey = -10, x = 2, ex = -17,
|
||||
|
@ -136,4 +136,10 @@
|
||||
iconExt = "\030 \031 \128\0307\143\131\131\131\131\143\030 \128\010\0307\031 \129\0317\128\0319\136\0309\031b\136\132\0307\0319\132\0317\128\031 \130\010\030 \0317\130\143\0307\128\128\128\128\030 \143\129",
|
||||
run = "/rom/programs/fun/dj",
|
||||
},
|
||||
[ "4dbdd221e957eff27cc47796f3ed8447290f71c7ad8b95e5bd828b31c1858f15" ] = {
|
||||
title = "Partition",
|
||||
category = "System",
|
||||
iconExt = "\30\55\31\55\128\30\48\135\131\139\30\55\128\128\128\10\30\48\31\55\149\31\48\128\30\55\145\30\48\31\56\140\30\55\157\144\144\10\30\55\31\55\128\31\48\139\143\135\31\55\128\31\56\142\133",
|
||||
run = "Partition",
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +134,8 @@ local function getNode(dir)
|
||||
return node
|
||||
end
|
||||
|
||||
fs.getNode = getNode
|
||||
|
||||
local methods = { 'delete', 'getFreeSpace', 'exists', 'isDir', 'getSize',
|
||||
'isReadOnly', 'makeDir', 'getDrive', 'list', 'open' }
|
||||
|
||||
|
@ -10,6 +10,13 @@ if not fs.exists('usr/autorun') then
|
||||
fs.makeDir('usr/autorun')
|
||||
end
|
||||
|
||||
-- move the fstab out of config so that the config directory
|
||||
-- can be remapped to another disk (and for consistency)
|
||||
if fs.exists('usr/config/fstab') and not fs.exists('usr/etc/fstab') then
|
||||
fs.move('usr/config/fstab', 'usr/etc/fstab')
|
||||
end
|
||||
fs.loadTab('usr/etc/fstab')
|
||||
|
||||
-- TODO: Temporary
|
||||
local upgrade = Util.readTable('usr/config/shell')
|
||||
if upgrade and (not upgrade.upgraded or upgrade.upgraded ~= 1) then
|
||||
@ -45,5 +52,3 @@ shell.setPath(table.concat(path, ':'))
|
||||
|
||||
--_G.LUA_PATH = config.lua_path
|
||||
--_G.settings.set('mbs.shell.require_path', config.lua_path)
|
||||
|
||||
fs.loadTab('usr/config/fstab')
|
||||
|
@ -14,7 +14,7 @@ for name in pairs(Packages:installed()) do
|
||||
local packageDir = fs.combine('packages', name)
|
||||
|
||||
table.insert(appPaths, 1, '/' .. packageDir)
|
||||
local apiPath = fs.combine(packageDir, 'apis')
|
||||
local apiPath = fs.combine(packageDir, 'apis') -- TODO: rename dir to 'modules' (someday)
|
||||
if fs.exists(apiPath) then
|
||||
fs.mount(fs.combine('rom/modules/main', name), 'linkfs', apiPath)
|
||||
end
|
||||
|
@ -675,7 +675,7 @@ function UI.Window:drawChildren()
|
||||
end
|
||||
|
||||
UI.Window.docs.getDoc = [[getDoc(STRING method)
|
||||
Gets the documentation for a method.]]
|
||||
Get the documentation for a method.]]
|
||||
function UI.Window:getDoc(method)
|
||||
local m = getmetatable(self) -- get the class for this instance
|
||||
repeat
|
||||
@ -743,6 +743,8 @@ function UI.Window:clear(bg, fg)
|
||||
Canvas.clear(self, bg or self:getProperty('backgroundColor'), fg or self:getProperty('textColor'))
|
||||
end
|
||||
|
||||
UI.Window.docs.clearLine = [[clearLine(NUMBER y, opt COLOR bg)
|
||||
Clears the specified line.]]
|
||||
function UI.Window:clearLine(y, bg)
|
||||
self:write(1, y, _rep(' ', self.width), bg)
|
||||
end
|
||||
@ -760,6 +762,10 @@ function UI.Window:fillArea(x, y, width, height, fillChar, bg, fg)
|
||||
end
|
||||
end
|
||||
|
||||
UI.Window.docs.write = [[write(NUMBER x, NUMBER y, String text, opt COLOR bg, opt COLOR fg)
|
||||
Write text to the canvas.
|
||||
If colors are not specified, the colors from the base class will be used.
|
||||
If the base class does not have colors defined, colors will be inherited from the parent container.]]
|
||||
function UI.Window:write(x, y, text, bg, fg)
|
||||
Canvas.write(self, x, y, text, bg or self:getProperty('backgroundColor'), fg or self:getProperty('textColor'))
|
||||
end
|
||||
|
@ -1,86 +1,75 @@
|
||||
local class = require('opus.class')
|
||||
local UI = require('opus.ui')
|
||||
local Util = require('opus.util')
|
||||
local UI = require('opus.ui')
|
||||
local Util = require('opus.util')
|
||||
|
||||
local colors = _G.colors
|
||||
local fs = _G.fs
|
||||
local fs = _G.fs
|
||||
|
||||
UI.FileSelect = class(UI.Window)
|
||||
UI.FileSelect.defaults = {
|
||||
UIElement = 'FileSelect',
|
||||
}
|
||||
function UI.FileSelect:postInit()
|
||||
self.grid = UI.ScrollingGrid {
|
||||
x = 2, y = 2, ex = -2, ey = -4,
|
||||
dir = '/',
|
||||
sortColumn = 'name',
|
||||
columns = {
|
||||
{ heading = 'Name', key = 'name' },
|
||||
{ heading = 'Size', key = 'size', width = 5 }
|
||||
},
|
||||
getDisplayValues = function(_, row)
|
||||
if row.size then
|
||||
row = Util.shallowCopy(row)
|
||||
row.size = Util.toBytes(row.size)
|
||||
end
|
||||
return row
|
||||
end,
|
||||
getRowTextColor = function(_, file)
|
||||
if file.isDir then
|
||||
return colors.cyan
|
||||
end
|
||||
if file.isReadOnly then
|
||||
return colors.pink
|
||||
end
|
||||
return colors.white
|
||||
end,
|
||||
sortCompare = function(self, a, b)
|
||||
if self.sortColumn == 'size' then
|
||||
return a.size < b.size
|
||||
end
|
||||
if a.isDir == b.isDir then
|
||||
return a.name:lower() < b.name:lower()
|
||||
end
|
||||
return a.isDir
|
||||
end,
|
||||
draw = function(self)
|
||||
local files = fs.listEx(self.dir)
|
||||
if #self.dir > 0 then
|
||||
table.insert(files, {
|
||||
name = '..',
|
||||
isDir = true,
|
||||
})
|
||||
end
|
||||
self:setValues(files)
|
||||
self:setIndex(1)
|
||||
UI.Grid.draw(self)
|
||||
end,
|
||||
}
|
||||
self.path = UI.TextEntry {
|
||||
x = 2,
|
||||
y = -2,
|
||||
ex = -11,
|
||||
limit = 256,
|
||||
accelerators = {
|
||||
enter = 'path_enter',
|
||||
}
|
||||
}
|
||||
self.cancel = UI.Button {
|
||||
text = 'Cancel',
|
||||
x = -9,
|
||||
y = -2,
|
||||
event = 'select_cancel',
|
||||
}
|
||||
self.grid = UI.ScrollingGrid {
|
||||
x = 2, y = 2, ex = -2, ey = -4,
|
||||
dir = '/',
|
||||
sortColumn = 'name',
|
||||
columns = {
|
||||
{ heading = 'Name', key = 'name' },
|
||||
{ heading = 'Size', key = 'size', width = 5 }
|
||||
},
|
||||
getDisplayValues = function(_, row)
|
||||
return {
|
||||
name = row.name,
|
||||
size = row.size and Util.toBytes(row.size),
|
||||
}
|
||||
end,
|
||||
getRowTextColor = function(_, file)
|
||||
return file.isDir and 'cyan' or file.isReadOnly and 'pink' or 'white'
|
||||
end,
|
||||
sortCompare = function(self, a, b)
|
||||
if self.sortColumn == 'size' then
|
||||
return a.size < b.size
|
||||
end
|
||||
if a.isDir == b.isDir then
|
||||
return a.name:lower() < b.name:lower()
|
||||
end
|
||||
return a.isDir
|
||||
end,
|
||||
draw = function(self)
|
||||
local files = fs.listEx(self.dir)
|
||||
if #self.dir > 0 then
|
||||
table.insert(files, {
|
||||
name = '..',
|
||||
isDir = true,
|
||||
})
|
||||
end
|
||||
self:setValues(files)
|
||||
self:setIndex(1)
|
||||
UI.Grid.draw(self)
|
||||
end,
|
||||
}
|
||||
self.path = UI.TextEntry {
|
||||
x = 2, y = -2, ex = -11,
|
||||
limit = 256,
|
||||
accelerators = {
|
||||
enter = 'path_enter',
|
||||
}
|
||||
}
|
||||
self.cancel = UI.Button {
|
||||
x = -9, y = -2,
|
||||
text = 'Cancel',
|
||||
event = 'select_cancel',
|
||||
}
|
||||
end
|
||||
|
||||
function UI.FileSelect:draw()
|
||||
self:fillArea(1, 1, self.width, self.height, string.rep('\127', self.width), colors.black, colors.gray)
|
||||
self:drawChildren()
|
||||
self:fillArea(1, 1, self.width, self.height, string.rep('\127', self.width), 'black', 'gray')
|
||||
self:drawChildren()
|
||||
end
|
||||
|
||||
function UI.FileSelect:enable(path)
|
||||
self:setPath(path or '')
|
||||
UI.Window.enable(self)
|
||||
self:setPath(path or '')
|
||||
UI.Window.enable(self)
|
||||
end
|
||||
|
||||
function UI.FileSelect:setPath(path)
|
||||
@ -98,21 +87,21 @@ function UI.FileSelect:eventHandler(event)
|
||||
if event.selected.isDir then
|
||||
self.grid:draw()
|
||||
self.path:draw()
|
||||
else
|
||||
self:emit({ type = 'select_file', file = '/' .. self.path.value, element = self })
|
||||
end
|
||||
return true
|
||||
else
|
||||
self:emit({ type = 'select_file', file = '/' .. self.path.value, element = self })
|
||||
end
|
||||
return true
|
||||
|
||||
elseif event.type == 'path_enter' then
|
||||
if self.path.value then
|
||||
if fs.isDir(self.path.value) then
|
||||
self:setPath(self.path.value)
|
||||
self.grid:draw()
|
||||
self.path:draw()
|
||||
else
|
||||
self:emit({ type = 'select_file', file = '/' .. self.path.value, element = self })
|
||||
end
|
||||
end
|
||||
return true
|
||||
elseif event.type == 'path_enter' then
|
||||
if self.path.value then
|
||||
if fs.isDir(self.path.value) then
|
||||
self:setPath(self.path.value)
|
||||
self.grid:draw()
|
||||
self.path:draw()
|
||||
else
|
||||
self:emit({ type = 'select_file', file = '/' .. self.path.value, element = self })
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
@ -33,7 +33,7 @@ function UI.Image:draw()
|
||||
for x = 1, #line do
|
||||
local ch = lookup:find(line:sub(x, x))
|
||||
if ch then
|
||||
self:write(x, y, ' ', 2 ^ (ch -1))
|
||||
self:write(x, y, ' ', 2 ^ (ch - 1))
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -47,6 +47,7 @@ end
|
||||
|
||||
function UI.Image.example()
|
||||
return UI.Image {
|
||||
backgroundColor = 'primary',
|
||||
filename = 'test.paint',
|
||||
}
|
||||
end
|
||||
|
@ -7,7 +7,7 @@ local colors = _G.colors
|
||||
UI.ScrollBar = class(UI.Window)
|
||||
UI.ScrollBar.defaults = {
|
||||
UIElement = 'ScrollBar',
|
||||
lineChar = '|',
|
||||
lineChar = '\166',
|
||||
sliderChar = UI.extChars and '\127' or '#',
|
||||
upArrowChar = UI.extChars and '\30' or '^',
|
||||
downArrowChar = UI.extChars and '\31' or 'v',
|
||||
|
@ -4,7 +4,7 @@ local UI = require('opus.ui')
|
||||
UI.Tab = class(UI.Window)
|
||||
UI.Tab.defaults = {
|
||||
UIElement = 'Tab',
|
||||
tabTitle = 'tab',
|
||||
title = 'tab',
|
||||
y = 2,
|
||||
}
|
||||
|
||||
@ -14,3 +14,8 @@ function UI.Tab:draw()
|
||||
end
|
||||
self:drawChildren()
|
||||
end
|
||||
|
||||
function UI.Tab:enable()
|
||||
UI.Window.enable(self)
|
||||
self:emit({ type = 'tab_activate', activated = self })
|
||||
end
|
||||
|
@ -37,9 +37,3 @@ function UI.TabBar:eventHandler(event)
|
||||
return UI.MenuBar.eventHandler(self, event)
|
||||
end
|
||||
|
||||
function UI.TabBar:selectTab(text)
|
||||
local menuItem = Util.find(self.children, 'text', text)
|
||||
if menuItem then
|
||||
menuItem.selected = true
|
||||
end
|
||||
end
|
||||
|
@ -14,11 +14,11 @@ end
|
||||
function UI.Tabs:add(children)
|
||||
local buttons = { }
|
||||
for _,child in pairs(children) do
|
||||
if type(child) == 'table' and child.UIElement and child.tabTitle then
|
||||
if type(child) == 'table' and child.UIElement and child.UIElement == 'Tab' then
|
||||
child.y = 2
|
||||
table.insert(buttons, {
|
||||
index = child.index,
|
||||
text = child.tabTitle,
|
||||
text = child.title,
|
||||
event = 'tab_select',
|
||||
tabUid = child.uid,
|
||||
})
|
||||
@ -34,7 +34,12 @@ function UI.Tabs:add(children)
|
||||
end
|
||||
|
||||
if self.parent then
|
||||
local enabled = self.enabled
|
||||
|
||||
-- don't enable children upon add
|
||||
self.enabled = nil
|
||||
UI.Window.add(self, children)
|
||||
self.enabled = enabled
|
||||
end
|
||||
end
|
||||
|
||||
@ -43,7 +48,15 @@ Make to the passed tab active.]]
|
||||
function UI.Tabs:selectTab(tab)
|
||||
local menuItem = Util.find(self.tabBar.children, 'tabUid', tab.uid)
|
||||
if menuItem then
|
||||
self.tabBar:emit({ type = 'tab_select', button = { uid = menuItem.uid } })
|
||||
if self.enabled then
|
||||
self.tabBar:emit({ type = 'tab_select', button = { uid = menuItem.uid } })
|
||||
else
|
||||
local previous = Util.find(self.tabBar.children, 'selected', true)
|
||||
if previous then
|
||||
previous.selected = false
|
||||
end
|
||||
menuItem.selected = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -59,14 +72,20 @@ function UI.Tabs:enable()
|
||||
self.tabBar:enable()
|
||||
|
||||
local menuItem = Util.find(self.tabBar.children, 'selected', true)
|
||||
self:enableTab(menuItem.tabUid)
|
||||
end
|
||||
|
||||
function UI.Tabs:enableTab(tabUid, hint)
|
||||
for child in self:eachChild() do
|
||||
child.transitionHint = nil
|
||||
if child.uid == menuItem.tabUid then
|
||||
child:enable()
|
||||
self:emit({ type = 'tab_activate', activated = child })
|
||||
elseif child.tabTitle then
|
||||
child:disable()
|
||||
child.transitionHint = hint
|
||||
if child.uid == tabUid then
|
||||
if not child.enabled then
|
||||
child:enable()
|
||||
end
|
||||
elseif child.UIElement == 'Tab' then
|
||||
if child.enabled then
|
||||
child:disable()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -76,15 +95,7 @@ function UI.Tabs:eventHandler(event)
|
||||
local tab = self:find(event.tab.tabUid)
|
||||
local hint = event.current > event.last and 'slideLeft' or 'slideRight'
|
||||
|
||||
for child in self:eachChild() do
|
||||
if child.uid == event.tab.tabUid then
|
||||
child.transitionHint = hint
|
||||
child:enable()
|
||||
elseif child.tabTitle then
|
||||
child:disable()
|
||||
end
|
||||
end
|
||||
self:emit({ type = 'tab_activate', activated = tab })
|
||||
self:enableTab(event.tab.tabUid, hint)
|
||||
tab:draw()
|
||||
return true
|
||||
end
|
||||
@ -94,28 +105,28 @@ function UI.Tabs.example()
|
||||
return UI.Tabs {
|
||||
tab1 = UI.Tab {
|
||||
index = 1,
|
||||
tabTitle = 'tab1',
|
||||
title = 'tab1',
|
||||
entry = UI.TextEntry { y = 3, shadowText = 'text' },
|
||||
},
|
||||
tab2 = UI.Tab {
|
||||
index = 2,
|
||||
tabTitle = 'tab2',
|
||||
title = 'tab2',
|
||||
subtabs = UI.Tabs {
|
||||
x = 3, y = 2, ex = -3, ey = -2,
|
||||
tab1 = UI.Tab {
|
||||
index = 1,
|
||||
tabTitle = 'tab4',
|
||||
title = 'tab4',
|
||||
entry = UI.TextEntry { y = 3, shadowText = 'text' },
|
||||
},
|
||||
tab3 = UI.Tab {
|
||||
index = 2,
|
||||
tabTitle = 'tab5',
|
||||
title = 'tab5',
|
||||
},
|
||||
},
|
||||
},
|
||||
tab3 = UI.Tab {
|
||||
index = 3,
|
||||
tabTitle = 'tab3',
|
||||
title = 'tab3',
|
||||
},
|
||||
enable = function(self)
|
||||
UI.Tabs.enable(self)
|
||||
|
@ -8,11 +8,12 @@ UI.TextArea.defaults = {
|
||||
value = '',
|
||||
showScrollBar = true,
|
||||
}
|
||||
function UI.TextArea:setText(text)
|
||||
function UI.TextArea:setValue(text)
|
||||
self:reset()
|
||||
self.value = text
|
||||
self:draw()
|
||||
end
|
||||
UI.TextArea.setText = UI.TextArea.setValue -- deprecate
|
||||
|
||||
function UI.TextArea.focus()
|
||||
-- allow keyboard scrolling
|
||||
|
@ -15,52 +15,50 @@ function UI.Wizard:postInit()
|
||||
}
|
||||
self.previousButton = UI.Button {
|
||||
x = -18, y = -1,
|
||||
text = '< Back',
|
||||
text = '\17 Back',
|
||||
event = 'previousView',
|
||||
}
|
||||
self.nextButton = UI.Button {
|
||||
x = -9, y = -1,
|
||||
text = 'Next >',
|
||||
text = 'Next \16',
|
||||
event = 'nextView',
|
||||
}
|
||||
|
||||
Util.merge(self, self.pages)
|
||||
end
|
||||
|
||||
function UI.Wizard:add(pages)
|
||||
Util.merge(self.pages, pages)
|
||||
Util.merge(self, pages)
|
||||
|
||||
for _, child in pairs(self.pages) do
|
||||
child.ey = child.ey or -2
|
||||
end
|
||||
|
||||
if self.parent then
|
||||
self:initChildren()
|
||||
function UI.Wizard:getPages()
|
||||
local t = { }
|
||||
for child in self:eachChild() do
|
||||
if type(child) == 'table' and child.UIElement == 'WizardPage' then
|
||||
table.insert(t, child)
|
||||
end
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
function UI.Wizard:getPage(index)
|
||||
return Util.find(self.pages, 'index', index)
|
||||
local pages = self:getPages()
|
||||
return Util.find(pages, 'index', index)
|
||||
end
|
||||
|
||||
function UI.Wizard:enable(...)
|
||||
function UI.Wizard:enable()
|
||||
self.enabled = true
|
||||
self.index = 1
|
||||
local initial = self:getPage(1)
|
||||
for child in self:eachChild() do
|
||||
if child == initial or not child.index then
|
||||
child:enable(...)
|
||||
else
|
||||
if child.UIElement ~= 'WizardPage' then
|
||||
child:enable()
|
||||
elseif child.enabled then
|
||||
child:disable()
|
||||
end
|
||||
end
|
||||
local initial = self:getPage(1)
|
||||
self:emit({ type = 'enable_view', next = initial })
|
||||
end
|
||||
|
||||
function UI.Wizard:isViewValid()
|
||||
local currentView = self:getPage(self.index)
|
||||
return not currentView.validate and true or currentView:validate()
|
||||
return currentView:validate()
|
||||
end
|
||||
|
||||
function UI.Wizard:eventHandler(event)
|
||||
@ -107,7 +105,7 @@ function UI.Wizard:eventHandler(event)
|
||||
end
|
||||
|
||||
if self:getPage(self.index + 1) then
|
||||
self.nextButton.text = 'Next >'
|
||||
self.nextButton.text = 'Next \16'
|
||||
self.nextButton.event = 'nextView'
|
||||
else
|
||||
self.nextButton.text = 'Accept'
|
||||
@ -124,29 +122,27 @@ 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',
|
||||
},
|
||||
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',
|
||||
},
|
||||
},
|
||||
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',
|
||||
},
|
||||
},
|
||||
password = UI.WizardPage {
|
||||
index = 3,
|
||||
text = UI.TextEntry {
|
||||
x = 12, ex = -3, y = 2,
|
||||
shadowText = 'tet',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -6,3 +6,6 @@ UI.WizardPage.defaults = {
|
||||
UIElement = 'WizardPage',
|
||||
ey = -2,
|
||||
}
|
||||
function UI.WizardPage.validate()
|
||||
return true
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user