mirror of https://github.com/kepler155c/opus
color rework + cleanup
This commit is contained in:
parent
3e41996b9b
commit
9d2a76f4ea
|
@ -184,9 +184,7 @@ local Browser = UI.Page {
|
||||||
text = 'Add', event = 'add_association',
|
text = 'Add', event = 'add_association',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
statusBar = UI.StatusBar {
|
statusBar = UI.StatusBar { },
|
||||||
backgroundColor = colors.cyan,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
accelerators = {
|
accelerators = {
|
||||||
[ 'control-q' ] = 'quit',
|
[ 'control-q' ] = 'quit',
|
||||||
|
@ -547,6 +545,4 @@ local args = Util.parse(...)
|
||||||
Browser:setDir(args[1] or shell.dir())
|
Browser:setDir(args[1] or shell.dir())
|
||||||
|
|
||||||
UI:setPage(Browser)
|
UI:setPage(Browser)
|
||||||
|
UI:start()
|
||||||
Event.pullEvents()
|
|
||||||
UI.term:reset()
|
|
||||||
|
|
|
@ -382,11 +382,12 @@ function page:executeStatement(statement)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local args = Util.parse(...)
|
local args = { ... }
|
||||||
if args[1] then
|
if args[1] then
|
||||||
command = 'args[1]'
|
command = 'args[1]'
|
||||||
sandboxEnv.args = args
|
sandboxEnv.args = args
|
||||||
page:setResult(args[1])
|
page:setResult(args[1])
|
||||||
|
page:setPrompt(command)
|
||||||
end
|
end
|
||||||
|
|
||||||
UI:setPage(page)
|
UI:setPage(page)
|
||||||
|
|
|
@ -95,6 +95,7 @@ local page = UI.Page {
|
||||||
ey = -2,
|
ey = -2,
|
||||||
width = 8,
|
width = 8,
|
||||||
selectedBackgroundColor = UI.colors.primary,
|
selectedBackgroundColor = UI.colors.primary,
|
||||||
|
backgroundColor = UI.colors.tertiary,
|
||||||
layout = function(self)
|
layout = function(self)
|
||||||
self.height = nil
|
self.height = nil
|
||||||
UI.TabBar.layout(self)
|
UI.TabBar.layout(self)
|
||||||
|
|
|
@ -12,7 +12,7 @@ local gridColumns = {}
|
||||||
table.insert(gridColumns, { heading = '#', key = 'id', width = 5, align = 'right' })
|
table.insert(gridColumns, { heading = '#', key = 'id', width = 5, align = 'right' })
|
||||||
table.insert(gridColumns, { heading = 'Port', key = 'portid', width = 5, align = 'right' })
|
table.insert(gridColumns, { heading = 'Port', key = 'portid', width = 5, align = 'right' })
|
||||||
table.insert(gridColumns, { heading = 'Reply', key = 'replyid', width = 5, align = 'right' })
|
table.insert(gridColumns, { heading = 'Reply', key = 'replyid', width = 5, align = 'right' })
|
||||||
if UI.defaultDevice.width > 50 then
|
if UI.term.width > 50 then
|
||||||
table.insert(gridColumns, { heading = 'Dist', key = 'distance', width = 6, align = 'right' })
|
table.insert(gridColumns, { heading = 'Dist', key = 'distance', width = 6, align = 'right' })
|
||||||
end
|
end
|
||||||
table.insert(gridColumns, { heading = 'Msg', key = 'packetStr' })
|
table.insert(gridColumns, { heading = 'Msg', key = 'packetStr' })
|
||||||
|
@ -42,7 +42,7 @@ local page = UI.Page {
|
||||||
|
|
||||||
configSlide = UI.SlideOut {
|
configSlide = UI.SlideOut {
|
||||||
y = -11,
|
y = -11,
|
||||||
titleBar = UI.TitleBar { title = 'Sniffer Config', event = 'config_close' },
|
titleBar = UI.TitleBar { title = 'Sniffer Config', event = 'config_close', backgroundColor = colors.black },
|
||||||
accelerators = { ['backspace'] = 'config_close' },
|
accelerators = { ['backspace'] = 'config_close' },
|
||||||
configTabs = UI.Tabs {
|
configTabs = UI.Tabs {
|
||||||
y = 2,
|
y = 2,
|
||||||
|
|
|
@ -28,10 +28,10 @@ if _G.http.websocket then
|
||||||
event = 'update_key',
|
event = 'update_key',
|
||||||
},
|
},
|
||||||
labelText = UI.TextArea {
|
labelText = UI.TextArea {
|
||||||
x = 2, ex = -2, y = 6, ey = -4,
|
x = 2, ex = -2, y = 5, ey = -4,
|
||||||
textColor = colors.yellow,
|
textColor = colors.yellow,
|
||||||
backgroundColor = colors.black,
|
backgroundColor = colors.black,
|
||||||
marginLeft = 0, marginRight = 0,
|
marginLeft = 1, marginRight = 1, marginTop = 1,
|
||||||
value = string.format(
|
value = string.format(
|
||||||
[[Use a non-changing cloud key. Note that only a single computer can use this session at one time.
|
[[Use a non-changing cloud key. Note that only a single computer can use this session at one time.
|
||||||
To obtain a key, visit:
|
To obtain a key, visit:
|
||||||
|
|
|
@ -23,7 +23,7 @@ return UI.Tab {
|
||||||
x = 2, y = 2, ex = -2, ey = 4,
|
x = 2, y = 2, ex = -2, ey = 4,
|
||||||
},
|
},
|
||||||
grid = UI.ScrollingGrid {
|
grid = UI.ScrollingGrid {
|
||||||
x = 2, y = 6, ex = -2, ey = -2,
|
x = 2, y = 5, ex = -2, ey = -2,
|
||||||
values = {
|
values = {
|
||||||
{ name = '', value = '' },
|
{ name = '', value = '' },
|
||||||
{ name = 'CC version', value = Util.getVersion() },
|
{ name = 'CC version', value = Util.getVersion() },
|
||||||
|
|
|
@ -35,9 +35,10 @@ local tab = UI.Tab {
|
||||||
event = 'update',
|
event = 'update',
|
||||||
},
|
},
|
||||||
labelText = UI.TextArea {
|
labelText = UI.TextArea {
|
||||||
x = 2, ex = -2, y = 7, ey = -4,
|
x = 2, ex = -2, y = 6, ey = -4,
|
||||||
backgroundColor = colors.black,
|
backgroundColor = colors.black,
|
||||||
textColor = colors.yellow,
|
textColor = colors.yellow,
|
||||||
|
marginLeft = 1, marginRight = 1, marginTop = 1,
|
||||||
value = 'Choose an application launcher',
|
value = 'Choose an application launcher',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,9 @@ return UI.Tab {
|
||||||
tabTitle = 'Network',
|
tabTitle = 'Network',
|
||||||
description = 'Networking options',
|
description = 'Networking options',
|
||||||
info = UI.TextArea {
|
info = UI.TextArea {
|
||||||
x = 2, y = 6, ex = -2, ey = -2,
|
x = 2, y = 5, ex = -2, ey = -2,
|
||||||
backgroundColor = colors.black,
|
backgroundColor = colors.black,
|
||||||
|
marginLeft = 1, marginRight = 1, marginTop = 1,
|
||||||
value = string.format(
|
value = string.format(
|
||||||
[[%sSet the primary modem used for wireless communications.%s
|
[[%sSet the primary modem used for wireless communications.%s
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,11 @@ return UI.Tab {
|
||||||
event = 'update_password',
|
event = 'update_password',
|
||||||
},
|
},
|
||||||
info = UI.TextArea {
|
info = UI.TextArea {
|
||||||
x = 2, ex = -2, y = 6, ey = -4,
|
x = 2, ex = -2, y = 5, ey = -4,
|
||||||
backgroundColor = colors.black,
|
backgroundColor = colors.black,
|
||||||
textColor = colors.yellow,
|
textColor = colors.yellow,
|
||||||
inactive = true,
|
inactive = true,
|
||||||
|
marginLeft = 1, marginRight = 1, marginTop = 1,
|
||||||
value = 'Add a password to enable other computers to connect to this one.',
|
value = 'Add a password to enable other computers to connect to this one.',
|
||||||
},
|
},
|
||||||
eventHandler = function(self, event)
|
eventHandler = function(self, event)
|
||||||
|
|
|
@ -2,49 +2,94 @@ local UI = require('opus.ui')
|
||||||
|
|
||||||
local settings = _G.settings
|
local settings = _G.settings
|
||||||
|
|
||||||
if settings then
|
local transform = {
|
||||||
local settingsTab = UI.Tab {
|
string = tostring,
|
||||||
tabTitle = 'Settings',
|
number = tonumber,
|
||||||
description = 'Computercraft configurable settings',
|
}
|
||||||
grid = UI.Grid {
|
|
||||||
x = 2, y = 2, ex = -2, ey = -2,
|
|
||||||
autospace = true,
|
|
||||||
sortColumn = 'name',
|
|
||||||
columns = {
|
|
||||||
{ heading = 'Setting', key = 'name' },
|
|
||||||
{ heading = 'Value', key = 'value' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
function settingsTab:enable()
|
return settings and UI.Tab {
|
||||||
|
tabTitle = 'Settings',
|
||||||
|
description = 'Computercraft settings',
|
||||||
|
grid = UI.Grid {
|
||||||
|
x = 2, y = 2, ex = -2, ey = -2,
|
||||||
|
sortColumn = 'name',
|
||||||
|
columns = {
|
||||||
|
{ heading = 'Setting', key = 'name' },
|
||||||
|
{ heading = 'Value', key = 'value' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
editor = UI.SlideOut {
|
||||||
|
y = -6, height = 6,
|
||||||
|
titleBar = UI.TitleBar {
|
||||||
|
event = 'slide_hide',
|
||||||
|
title = 'Enter value',
|
||||||
|
},
|
||||||
|
form = UI.Form {
|
||||||
|
y = 2,
|
||||||
|
value = UI.TextEntry {
|
||||||
|
limit = 256,
|
||||||
|
formIndex = 1,
|
||||||
|
formLabel = 'Value',
|
||||||
|
formKey = 'value',
|
||||||
|
},
|
||||||
|
validateField = function(self, entry)
|
||||||
|
if entry.value then
|
||||||
|
return transform[self.type](entry.value)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
accelerators = {
|
||||||
|
form_cancel = 'slide_hide',
|
||||||
|
},
|
||||||
|
show = function(self, entry)
|
||||||
|
self.form.type = type(entry.value) or 'string'
|
||||||
|
self.form:setValues(entry)
|
||||||
|
self.titleBar.title = entry.name
|
||||||
|
UI.SlideOut.show(self)
|
||||||
|
end,
|
||||||
|
eventHandler = function(self, event)
|
||||||
|
if event.type == 'form_complete' then
|
||||||
|
if not event.values.value then
|
||||||
|
settings.unset(event.values.name)
|
||||||
|
self.parent:reload()
|
||||||
|
else
|
||||||
|
event.values.value = transform[self.form.type](event.values.value)
|
||||||
|
settings.set(event.values.name, event.values.value)
|
||||||
|
end
|
||||||
|
self.parent.grid:draw()
|
||||||
|
self:hide()
|
||||||
|
settings.save('.settings')
|
||||||
|
end
|
||||||
|
return UI.SlideOut.eventHandler(self, event)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
reload = function(self)
|
||||||
local values = { }
|
local values = { }
|
||||||
for _,v in pairs(settings.getNames()) do
|
for _,v in pairs(settings.getNames()) do
|
||||||
local value = settings.get(v)
|
|
||||||
if not value then
|
|
||||||
value = false
|
|
||||||
end
|
|
||||||
table.insert(values, {
|
table.insert(values, {
|
||||||
name = v,
|
name = v,
|
||||||
value = value,
|
value = settings.get(v) or false,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
self.grid:setValues(values)
|
self.grid:setValues(values)
|
||||||
|
self.grid:setIndex(1)
|
||||||
|
end,
|
||||||
|
enable = function(self)
|
||||||
|
self:reload()
|
||||||
UI.Tab.enable(self)
|
UI.Tab.enable(self)
|
||||||
end
|
end,
|
||||||
|
eventHandler = function(self, event)
|
||||||
function settingsTab:eventHandler(event)
|
|
||||||
if event.type == 'grid_select' then
|
if event.type == 'grid_select' then
|
||||||
if not event.selected.value or type(event.selected.value) == 'boolean' then
|
if type(event.selected.value) == 'boolean' then
|
||||||
event.selected.value = not event.selected.value
|
event.selected.value = not event.selected.value
|
||||||
|
settings.set(event.selected.name, event.selected.value)
|
||||||
|
settings.save('.settings')
|
||||||
|
self.grid:draw()
|
||||||
|
else
|
||||||
|
self.editor:show(event.selected)
|
||||||
end
|
end
|
||||||
settings.set(event.selected.name, event.selected.value)
|
|
||||||
settings.save('.settings')
|
|
||||||
self.grid:draw()
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end,
|
||||||
|
}
|
||||||
-- this needs lots of work - currently only works with booleans
|
|
||||||
--return settingsTab
|
|
||||||
end
|
|
||||||
|
|
|
@ -32,3 +32,23 @@ end
|
||||||
|
|
||||||
help.setPath(table.concat(helpPaths, ':'))
|
help.setPath(table.concat(helpPaths, ':'))
|
||||||
shell.setPath(table.concat(appPaths, ':'))
|
shell.setPath(table.concat(appPaths, ':'))
|
||||||
|
|
||||||
|
local function runDir(directory)
|
||||||
|
local files = fs.list(directory)
|
||||||
|
table.sort(files)
|
||||||
|
|
||||||
|
for _,file in ipairs(files) do
|
||||||
|
os.sleep(0)
|
||||||
|
local result, err = shell.run(directory .. '/' .. file)
|
||||||
|
if not result and err then
|
||||||
|
_G.printError('\n' .. err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, package in pairs(Packages:installedSorted()) do
|
||||||
|
local packageDir = 'packages/' .. package.name .. '/init'
|
||||||
|
if fs.exists(packageDir) and fs.isDir(packageDir) then
|
||||||
|
runDir(packageDir)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -65,7 +65,7 @@ function GPS.locate(timeout, debug)
|
||||||
if debug then
|
if debug then
|
||||||
print("Position is "..pos.x..","..pos.y..","..pos.z)
|
print("Position is "..pos.x..","..pos.y..","..pos.z)
|
||||||
end
|
end
|
||||||
return vector.new(pos.x, pos.y, pos.z)
|
return pos and vector.new(pos.x, pos.y, pos.z)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GPS.isAvailable()
|
function GPS.isAvailable()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
local Array = require('opus.array')
|
local Array = require('opus.array')
|
||||||
|
local Blit = require('opus.ui.blit')
|
||||||
local class = require('opus.class')
|
local class = require('opus.class')
|
||||||
local Event = require('opus.event')
|
local Event = require('opus.event')
|
||||||
local Input = require('opus.input')
|
local Input = require('opus.input')
|
||||||
|
@ -34,11 +35,16 @@ local textutils = _G.textutils
|
||||||
]]
|
]]
|
||||||
|
|
||||||
--[[-- Top Level Manager --]]--
|
--[[-- Top Level Manager --]]--
|
||||||
local Manager = class()
|
local UI = { }
|
||||||
function Manager:init()
|
function UI:init()
|
||||||
self.devices = { }
|
self.devices = { }
|
||||||
self.theme = { }
|
self.theme = { }
|
||||||
self.extChars = Util.getVersion() >= 1.76
|
self.extChars = Util.getVersion() >= 1.76
|
||||||
|
self.colors = {
|
||||||
|
primary = colors.green,
|
||||||
|
secondary = colors.lightGray,
|
||||||
|
tertiary = colors.gray,
|
||||||
|
}
|
||||||
|
|
||||||
local function keyFunction(event, code, held)
|
local function keyFunction(event, code, held)
|
||||||
local ie = Input:translate(event, code, held)
|
local ie = Input:translate(event, code, held)
|
||||||
|
@ -151,7 +157,7 @@ function Manager:init()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:configure(appName, ...)
|
function UI:configure(appName, ...)
|
||||||
local defaults = Util.loadTable('usr/config/' .. appName) or { }
|
local defaults = Util.loadTable('usr/config/' .. appName) or { }
|
||||||
if not defaults.device then
|
if not defaults.device then
|
||||||
defaults.device = { }
|
defaults.device = { }
|
||||||
|
@ -193,11 +199,11 @@ function Manager:configure(appName, ...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:disableEffects()
|
function UI:disableEffects()
|
||||||
self.defaultDevice.effectsEnabled = false
|
self.term.effectsEnabled = false
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:loadTheme(filename)
|
function UI:loadTheme(filename)
|
||||||
if fs.exists(filename) then
|
if fs.exists(filename) then
|
||||||
local theme, err = Util.loadTable(filename)
|
local theme, err = Util.loadTable(filename)
|
||||||
if not theme then
|
if not theme then
|
||||||
|
@ -207,7 +213,7 @@ function Manager:loadTheme(filename)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:generateTheme(filename)
|
function UI:generateTheme(filename)
|
||||||
local t = { }
|
local t = { }
|
||||||
|
|
||||||
local function getName(d)
|
local function getName(d)
|
||||||
|
@ -244,14 +250,14 @@ function Manager:generateTheme(filename)
|
||||||
Util.writeFile(filename, textutils.serialize(t):gsub('(")', ''))
|
Util.writeFile(filename, textutils.serialize(t):gsub('(")', ''))
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:emitEvent(event)
|
function UI:emitEvent(event)
|
||||||
local currentPage = self:getActivePage()
|
local currentPage = self:getActivePage()
|
||||||
if currentPage and currentPage.focused then
|
if currentPage and currentPage.focused then
|
||||||
return currentPage.focused:emit(event)
|
return currentPage.focused:emit(event)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:click(target, ie)
|
function UI:click(target, ie)
|
||||||
local clickEvent
|
local clickEvent
|
||||||
|
|
||||||
if ie.code == 'mouse_drag' then
|
if ie.code == 'mouse_drag' then
|
||||||
|
@ -304,23 +310,22 @@ function Manager:click(target, ie)
|
||||||
target:sync()
|
target:sync()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:setDefaultDevice(dev)
|
function UI:setDefaultDevice(dev)
|
||||||
self.defaultDevice = dev
|
|
||||||
self.term = dev
|
self.term = dev
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:addPage(name, page)
|
function UI:addPage(name, page)
|
||||||
if not self.pages then
|
if not self.pages then
|
||||||
self.pages = { }
|
self.pages = { }
|
||||||
end
|
end
|
||||||
self.pages[name] = page
|
self.pages[name] = page
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:setPages(pages)
|
function UI:setPages(pages)
|
||||||
self.pages = pages
|
self.pages = pages
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:getPage(pageName)
|
function UI:getPage(pageName)
|
||||||
local page = self.pages[pageName]
|
local page = self.pages[pageName]
|
||||||
|
|
||||||
if not page then
|
if not page then
|
||||||
|
@ -330,18 +335,18 @@ function Manager:getPage(pageName)
|
||||||
return page
|
return page
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:getActivePage(page)
|
function UI:getActivePage(page)
|
||||||
if page then
|
if page then
|
||||||
return page.parent.currentPage
|
return page.parent.currentPage
|
||||||
end
|
end
|
||||||
return self.defaultDevice.currentPage
|
return self.term.currentPage
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:setActivePage(page)
|
function UI:setActivePage(page)
|
||||||
page.parent.currentPage = page
|
page.parent.currentPage = page
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:setPage(pageOrName, ...)
|
function UI:setPage(pageOrName, ...)
|
||||||
local page = pageOrName
|
local page = pageOrName
|
||||||
|
|
||||||
if type(pageOrName) == 'string' then
|
if type(pageOrName) == 'string' then
|
||||||
|
@ -361,7 +366,6 @@ function Manager:setPage(pageOrName, ...)
|
||||||
page.previousPage = currentPage
|
page.previousPage = currentPage
|
||||||
end
|
end
|
||||||
self:setActivePage(page)
|
self:setActivePage(page)
|
||||||
--page:clear(page.backgroundColor)
|
|
||||||
page:enable(...)
|
page:enable(...)
|
||||||
page:draw()
|
page:draw()
|
||||||
if page.focused then
|
if page.focused then
|
||||||
|
@ -372,27 +376,27 @@ function Manager:setPage(pageOrName, ...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:getCurrentPage()
|
function UI:getCurrentPage()
|
||||||
return self.defaultDevice.currentPage
|
return self.term.currentPage
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:setPreviousPage()
|
function UI:setPreviousPage()
|
||||||
if self.defaultDevice.currentPage.previousPage then
|
if self.term.currentPage.previousPage then
|
||||||
local previousPage = self.defaultDevice.currentPage.previousPage.previousPage
|
local previousPage = self.term.currentPage.previousPage.previousPage
|
||||||
self:setPage(self.defaultDevice.currentPage.previousPage)
|
self:setPage(self.term.currentPage.previousPage)
|
||||||
self.defaultDevice.currentPage.previousPage = previousPage
|
self.term.currentPage.previousPage = previousPage
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:getDefaults(element, args)
|
function UI:getDefaults(element, args)
|
||||||
local defaults = Util.deepCopy(element.defaults)
|
local defaults = Util.deepCopy(element.defaults)
|
||||||
if args then
|
if args then
|
||||||
Manager:mergeProperties(defaults, args)
|
UI:mergeProperties(defaults, args)
|
||||||
end
|
end
|
||||||
return defaults
|
return defaults
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:mergeProperties(obj, args)
|
function UI:mergeProperties(obj, args)
|
||||||
if args then
|
if args then
|
||||||
for k,v in pairs(args) do
|
for k,v in pairs(args) do
|
||||||
if k == 'accelerators' then
|
if k == 'accelerators' then
|
||||||
|
@ -408,7 +412,7 @@ function Manager:mergeProperties(obj, args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Manager:pullEvents(...)
|
function UI:pullEvents(...)
|
||||||
local s, m = pcall(Event.pullEvents, ...)
|
local s, m = pcall(Event.pullEvents, ...)
|
||||||
self.term:reset()
|
self.term:reset()
|
||||||
if not s and m then
|
if not s and m then
|
||||||
|
@ -416,17 +420,11 @@ function Manager:pullEvents(...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Manager.colors = {
|
UI.exitPullEvents = Event.exitPullEvents
|
||||||
primary = colors.cyan,
|
UI.quit = Event.exitPullEvents
|
||||||
secondary = colors.lightGray,
|
UI.start = UI.pullEvents
|
||||||
tertiary = colors.gray,
|
|
||||||
}
|
|
||||||
|
|
||||||
Manager.exitPullEvents = Event.exitPullEvents
|
UI:init()
|
||||||
Manager.quit = Event.exitPullEvents
|
|
||||||
Manager.start = Manager.pullEvents
|
|
||||||
|
|
||||||
local UI = Manager()
|
|
||||||
|
|
||||||
--[[-- Basic drawable area --]]--
|
--[[-- Basic drawable area --]]--
|
||||||
UI.Window = class(Canvas)
|
UI.Window = class(Canvas)
|
||||||
|
@ -785,89 +783,19 @@ function UI.Window:print(text, bg, fg)
|
||||||
local marginLeft = self.marginLeft or 0
|
local marginLeft = self.marginLeft or 0
|
||||||
local marginRight = self.marginRight or 0
|
local marginRight = self.marginRight or 0
|
||||||
local width = self.width - marginLeft - marginRight
|
local width = self.width - marginLeft - marginRight
|
||||||
|
local cs = {
|
||||||
|
bg = bg or self:getProperty('backgroundColor'),
|
||||||
|
fg = fg or self:getProperty('textColor'),
|
||||||
|
palette = self.palette,
|
||||||
|
}
|
||||||
|
|
||||||
local function nextWord(line, cx)
|
local y = (self.marginTop or 0) + 1
|
||||||
local result = { line:find("(%w+)", cx) }
|
for _,line in pairs(Util.split(text)) do
|
||||||
if #result > 1 and result[2] > cx then
|
for _, ln in ipairs(Blit(line, cs):wrap(width)) do
|
||||||
return _sub(line, cx, result[2] + 1)
|
self:blit(marginLeft + 1, y, ln.text, ln.bg, ln.fg)
|
||||||
elseif #result > 0 and result[1] == cx then
|
y = y + 1
|
||||||
result = { line:find("(%w+)", result[2]) }
|
|
||||||
if #result > 0 then
|
|
||||||
return _sub(line, cx, result[1] + 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if cx <= #line then
|
|
||||||
return _sub(line, cx, #line)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function pieces(f, bg, fg)
|
|
||||||
local pos = 1
|
|
||||||
local t = { }
|
|
||||||
while true do
|
|
||||||
local s = string.find(f, '\027', pos, true)
|
|
||||||
if not s then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if pos < s then
|
|
||||||
table.insert(t, _sub(f, pos, s - 1))
|
|
||||||
end
|
|
||||||
local seq = _sub(f, s)
|
|
||||||
seq = seq:match("\027%[([%d;]+)m")
|
|
||||||
local e = { }
|
|
||||||
for color in string.gmatch(seq, "%d+") do
|
|
||||||
color = tonumber(color)
|
|
||||||
if color == 0 then
|
|
||||||
e.fg = fg
|
|
||||||
e.bg = bg
|
|
||||||
elseif color > 20 then
|
|
||||||
e.bg = 2 ^ (color - 21)
|
|
||||||
else
|
|
||||||
e.fg = 2 ^ (color - 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table.insert(t, e)
|
|
||||||
pos = s + #seq + 3
|
|
||||||
end
|
|
||||||
if pos <= #f then
|
|
||||||
table.insert(t, _sub(f, pos))
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
local lines = Util.split(text)
|
|
||||||
for k,line in pairs(lines) do
|
|
||||||
local fragments = pieces(line, bg, fg)
|
|
||||||
for _, fragment in ipairs(fragments) do
|
|
||||||
local lx = 1
|
|
||||||
if type(fragment) == 'table' then -- ansi sequence
|
|
||||||
fg = fragment.fg
|
|
||||||
bg = fragment.bg
|
|
||||||
else
|
|
||||||
while true do
|
|
||||||
local word = nextWord(fragment, lx)
|
|
||||||
if not word then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
local w = word
|
|
||||||
if self.cursorX + #word > width then
|
|
||||||
self.cursorX = marginLeft + 1
|
|
||||||
self.cursorY = self.cursorY + 1
|
|
||||||
w = word:gsub('^ ', '')
|
|
||||||
end
|
|
||||||
self:write(self.cursorX, self.cursorY, w, bg, fg)
|
|
||||||
self.cursorX = self.cursorX + #w
|
|
||||||
lx = lx + #word
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if lines[k + 1] then
|
|
||||||
self.cursorX = marginLeft + 1
|
|
||||||
self.cursorY = self.cursorY + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return self.cursorX, self.cursorY
|
|
||||||
end
|
end
|
||||||
|
|
||||||
UI.Window.docs.focus = [[focus(VOID)
|
UI.Window.docs.focus = [[focus(VOID)
|
||||||
|
@ -1126,7 +1054,7 @@ function UI.Device:runTransitions(transitions)
|
||||||
transitions[k] = nil
|
transitions[k] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.currentPage:render(self.device)
|
self.currentPage:render(self, true)
|
||||||
if Util.empty(transitions) then
|
if Util.empty(transitions) then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
@ -1143,7 +1071,7 @@ function UI.Device:sync()
|
||||||
if transitions then
|
if transitions then
|
||||||
self:runTransitions(transitions)
|
self:runTransitions(transitions)
|
||||||
else
|
else
|
||||||
self.currentPage:render(self.device)
|
self.currentPage:render(self, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
if self:getCursorBlink() then
|
if self:getCursorBlink() then
|
||||||
|
@ -1179,7 +1107,7 @@ local function loadComponents()
|
||||||
return self(...)
|
return self(...)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
UI[name]._preload = function(self)
|
UI[name]._preload = function()
|
||||||
return load(name)
|
return load(name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
local class = require('opus.class')
|
||||||
|
|
||||||
|
local colors = _G.colors
|
||||||
|
|
||||||
|
local Blit = class()
|
||||||
|
|
||||||
|
function Blit:init(t, cs)
|
||||||
|
if type(t) == 'string' then
|
||||||
|
t = Blit.toblit(t, cs or { })
|
||||||
|
end
|
||||||
|
self.text = t.text
|
||||||
|
self.bg = t.bg
|
||||||
|
self.fg = t.fg
|
||||||
|
end
|
||||||
|
|
||||||
|
function Blit:sub(s, e)
|
||||||
|
return Blit({
|
||||||
|
text = self.text:sub(s, e),
|
||||||
|
bg = self.bg:sub(s, e),
|
||||||
|
fg = self.fg:sub(s, e),
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function Blit:wrap(max)
|
||||||
|
local index = 1
|
||||||
|
local lines = { }
|
||||||
|
local data = self
|
||||||
|
|
||||||
|
repeat
|
||||||
|
if #data.text <= max then
|
||||||
|
table.insert(lines, data)
|
||||||
|
break
|
||||||
|
elseif data.text:sub(max+1, max+1) == ' ' then
|
||||||
|
table.insert(lines, data:sub(index, max))
|
||||||
|
data = data:sub(max + 2)
|
||||||
|
else
|
||||||
|
local x = data.text:sub(1, max)
|
||||||
|
local s = x:match('(.*) ') or x
|
||||||
|
table.insert(lines, data:sub(1, #s))
|
||||||
|
data = data:sub(#s + 1)
|
||||||
|
end
|
||||||
|
local t = data.text:match('^%s*(.*)')
|
||||||
|
local spaces = #data.text - #t
|
||||||
|
if spaces > 0 then
|
||||||
|
data = data:sub(spaces + 1)
|
||||||
|
end
|
||||||
|
until not data.text or #data.text == 0
|
||||||
|
|
||||||
|
return lines
|
||||||
|
end
|
||||||
|
|
||||||
|
-- convert a string of text to blit format doing color conversion
|
||||||
|
-- and processing ansi color sequences
|
||||||
|
function Blit.toblit(str, cs)
|
||||||
|
local text, fg, bg = '', '', ''
|
||||||
|
|
||||||
|
if not cs.cbg then
|
||||||
|
-- reset colors
|
||||||
|
cs.rbg = cs.palette[cs.bg or colors.black]
|
||||||
|
cs.rfg = cs.palette[cs.fg or colors.white]
|
||||||
|
-- current colors
|
||||||
|
cs.cbg = cs.rbg
|
||||||
|
cs.cfg = cs.rfg
|
||||||
|
end
|
||||||
|
|
||||||
|
str = str:gsub('(.-)\027%[([%d;]+)m',
|
||||||
|
function(k, seq)
|
||||||
|
text = text .. k
|
||||||
|
bg = bg .. string.rep(cs.cbg, #k)
|
||||||
|
fg = fg .. string.rep(cs.cfg, #k)
|
||||||
|
for color in string.gmatch(seq, "%d+") do
|
||||||
|
color = tonumber(color)
|
||||||
|
if color == 0 then
|
||||||
|
-- reset to default
|
||||||
|
cs.cfg = cs.rfg
|
||||||
|
cs.cbg = cs.rbg
|
||||||
|
elseif color > 20 then
|
||||||
|
cs.cbg = string.sub("0123456789abcdef", color - 21, color - 21)
|
||||||
|
else
|
||||||
|
cs.cfg = string.sub("0123456789abcdef", color, color)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return k
|
||||||
|
end)
|
||||||
|
|
||||||
|
local k = str:sub(#text + 1)
|
||||||
|
return {
|
||||||
|
text = text .. k,
|
||||||
|
bg = bg .. string.rep(cs.cbg, #k),
|
||||||
|
fg = fg .. string.rep(cs.cfg, #k),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
return Blit
|
|
@ -71,7 +71,7 @@ end
|
||||||
|
|
||||||
-- resize the canvas buffer - not the canvas itself
|
-- resize the canvas buffer - not the canvas itself
|
||||||
function Canvas:resizeBuffer(w, h)
|
function Canvas:resizeBuffer(w, h)
|
||||||
for i = #self.lines, h do
|
for i = #self.lines + 1, h do
|
||||||
self.lines[i] = { }
|
self.lines[i] = { }
|
||||||
self:clearLine(i)
|
self:clearLine(i)
|
||||||
end
|
end
|
||||||
|
@ -297,40 +297,38 @@ function Canvas:applyPalette(palette)
|
||||||
self.palette = palette
|
self.palette = palette
|
||||||
end
|
end
|
||||||
|
|
||||||
function Canvas:render(device)
|
-- either render directly to the device
|
||||||
local offset = { x = 0, y = 0 }
|
-- or use another canvas as a backing buffer
|
||||||
|
function Canvas:render(device, doubleBuffer)
|
||||||
-- WIP
|
|
||||||
local function getRegion(canvas)
|
|
||||||
local region
|
|
||||||
if canvas.parent then
|
|
||||||
region = getRegion(canvas.parent)
|
|
||||||
else
|
|
||||||
region = Region.new(self.x, self.y, self.ex, self.ey)
|
|
||||||
end
|
|
||||||
offset.x = offset.x + canvas.x - 1
|
|
||||||
offset.y = offset.y + canvas.y - 1
|
|
||||||
-- clip against parent
|
|
||||||
return region
|
|
||||||
end
|
|
||||||
|
|
||||||
-- this code works - but is all kinds of wrong
|
|
||||||
-- adding a margin to UI.Page will cause issues
|
|
||||||
-- and could be clipping issues
|
|
||||||
offset = { x = self.x - 1, y = self.y - 1 }
|
|
||||||
local parent = self.parent
|
|
||||||
while parent do
|
|
||||||
offset.x = offset.x + parent.x - 1
|
|
||||||
offset.y = offset.y + parent.y - 1
|
|
||||||
parent = parent.parent
|
|
||||||
end
|
|
||||||
|
|
||||||
-- TODO: need to clip if there is a parent
|
|
||||||
--self.regions = Region.new(self.x + offset.x, self.y + offset.y, self.ex + offset.x, self.ey + offset.y)
|
|
||||||
--self:__renderLayers(device, offset)
|
|
||||||
|
|
||||||
self.regions = Region.new(self.x, self.y, self.ex, self.ey)
|
self.regions = Region.new(self.x, self.y, self.ex, self.ey)
|
||||||
self:__renderLayers(device, { x = self.x - 1, y = self.y - 1 })
|
self:__renderLayers(device, { x = self.x - 1, y = self.y - 1 }, doubleBuffer)
|
||||||
|
|
||||||
|
-- doubleBuffering to reduce the amount of
|
||||||
|
-- setCursorPos, blits
|
||||||
|
if doubleBuffer then
|
||||||
|
--[[
|
||||||
|
local drew = false
|
||||||
|
local bg = _rep(2, device.width)
|
||||||
|
for k,v in pairs(device.lines) do
|
||||||
|
if v.dirty then
|
||||||
|
device.device.setCursorPos(device.x, device.y + k - 1)
|
||||||
|
device.device.blit(v.text, v.fg, bg)
|
||||||
|
drew = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if drew then
|
||||||
|
local c = os.clock()
|
||||||
|
repeat until os.clock()-c > .1
|
||||||
|
end
|
||||||
|
]]
|
||||||
|
for k,v in pairs(device.lines) do
|
||||||
|
if v.dirty then
|
||||||
|
device.device.setCursorPos(device.x, device.y + k - 1)
|
||||||
|
device.device.blit(v.text, v.fg, v.bg)
|
||||||
|
v.dirty = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- regions are comprised of absolute values that correspond to the output device.
|
-- regions are comprised of absolute values that correspond to the output device.
|
||||||
|
@ -338,7 +336,7 @@ end
|
||||||
-- canvas layer's stacking order is determined by the position within the array.
|
-- canvas layer's stacking order is determined by the position within the array.
|
||||||
-- layers in the beginning of the array are overlayed by layers further down in
|
-- layers in the beginning of the array are overlayed by layers further down in
|
||||||
-- the array.
|
-- the array.
|
||||||
function Canvas:__renderLayers(device, offset)
|
function Canvas:__renderLayers(device, offset, doubleBuffer)
|
||||||
if self.children then
|
if self.children then
|
||||||
for i = #self.children, 1, -1 do
|
for i = #self.children, 1, -1 do
|
||||||
local canvas = self.children[i]
|
local canvas = self.children[i]
|
||||||
|
@ -364,7 +362,7 @@ function Canvas:__renderLayers(device, offset)
|
||||||
canvas:__renderLayers(device, {
|
canvas:__renderLayers(device, {
|
||||||
x = canvas.x + offset.x - 1 - (self.offx or 0),
|
x = canvas.x + offset.x - 1 - (self.offx or 0),
|
||||||
y = canvas.y + offset.y - 1 - (self.offy or 0),
|
y = canvas.y + offset.y - 1 - (self.offy or 0),
|
||||||
})
|
}, doubleBuffer)
|
||||||
end
|
end
|
||||||
canvas.regions = nil
|
canvas.regions = nil
|
||||||
end
|
end
|
||||||
|
@ -377,19 +375,19 @@ function Canvas:__renderLayers(device, offset)
|
||||||
y = region[2] - offset.y,
|
y = region[2] - offset.y,
|
||||||
ex = region[3] - offset.x,
|
ex = region[3] - offset.x,
|
||||||
ey = region[4] - offset.y },
|
ey = region[4] - offset.y },
|
||||||
{ x = region[1], y = region[2] })
|
{ x = region[1], y = region[2] }, doubleBuffer)
|
||||||
end
|
end
|
||||||
self.regions = nil
|
self.regions = nil
|
||||||
|
|
||||||
self:clean()
|
self:clean()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- performance can probably be improved by using one more buffer tied to the device
|
function Canvas:__blitRect(device, src, tgt, doubleBuffer)
|
||||||
function Canvas:__blitRect(device, src, tgt)
|
|
||||||
src = src or { x = 1, y = 1, ex = self.ex - self.x + 1, ey = self.ey - self.y + 1 }
|
src = src or { x = 1, y = 1, ex = self.ex - self.x + 1, ey = self.ey - self.y + 1 }
|
||||||
tgt = tgt or self
|
tgt = tgt or self
|
||||||
|
|
||||||
-- for visualizing updates on the screen
|
-- for visualizing updates on the screen
|
||||||
|
--[[
|
||||||
if Canvas.__visualize or self.visualize then
|
if Canvas.__visualize or self.visualize then
|
||||||
local drew
|
local drew
|
||||||
local t = _rep(' ', src.ex-src.x + 1)
|
local t = _rep(' ', src.ex-src.x + 1)
|
||||||
|
@ -407,6 +405,7 @@ function Canvas:__blitRect(device, src, tgt)
|
||||||
repeat until os.clock()-c > .03
|
repeat until os.clock()-c > .03
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
]]
|
||||||
for i = 0, src.ey - src.y do
|
for i = 0, src.ey - src.y do
|
||||||
local line = self.lines[src.y + i + (self.offy or 0)]
|
local line = self.lines[src.y + i + (self.offy or 0)]
|
||||||
if line and line.dirty then
|
if line and line.dirty then
|
||||||
|
@ -416,8 +415,13 @@ function Canvas:__blitRect(device, src, tgt)
|
||||||
fg = _sub(fg, src.x, src.ex)
|
fg = _sub(fg, src.x, src.ex)
|
||||||
bg = _sub(bg, src.x, src.ex)
|
bg = _sub(bg, src.x, src.ex)
|
||||||
end
|
end
|
||||||
device.setCursorPos(tgt.x, tgt.y + i)
|
if doubleBuffer then
|
||||||
device.blit(t, fg, bg)
|
Canvas.blit(device, tgt.x, tgt.y + i,
|
||||||
|
t, bg, fg)
|
||||||
|
else
|
||||||
|
device.setCursorPos(tgt.x, tgt.y + i)
|
||||||
|
device.blit(t, fg, bg)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,8 +7,7 @@ UI.Dialog = class(UI.SlideOut)
|
||||||
UI.Dialog.defaults = {
|
UI.Dialog.defaults = {
|
||||||
UIElement = 'Dialog',
|
UIElement = 'Dialog',
|
||||||
height = 7,
|
height = 7,
|
||||||
textColor = colors.black,
|
noFill = true,
|
||||||
backgroundColor = colors.white,
|
|
||||||
okEvent ='dialog_ok',
|
okEvent ='dialog_ok',
|
||||||
cancelEvent = 'dialog_cancel',
|
cancelEvent = 'dialog_cancel',
|
||||||
}
|
}
|
||||||
|
@ -17,19 +16,6 @@ function UI.Dialog:postInit()
|
||||||
self.titleBar = UI.TitleBar({ event = self.cancelEvent, title = self.title })
|
self.titleBar = UI.TitleBar({ event = self.cancelEvent, title = self.title })
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Dialog:show(...)
|
|
||||||
local canvas = self.parent
|
|
||||||
self.oldPalette = canvas.palette
|
|
||||||
canvas:applyPalette(self.darkPalette)
|
|
||||||
UI.SlideOut.show(self, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.Dialog:hide(...)
|
|
||||||
self.parent.palette = self.oldPalette
|
|
||||||
UI.SlideOut.hide(self, ...)
|
|
||||||
self.parent:draw()
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.Dialog:eventHandler(event)
|
function UI.Dialog:eventHandler(event)
|
||||||
if event.type == 'dialog_cancel' then
|
if event.type == 'dialog_cancel' then
|
||||||
self:hide()
|
self:hide()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
local class = require('opus.class')
|
local class = require('opus.class')
|
||||||
|
local Event = require('opus.event')
|
||||||
local Terminal = require('opus.terminal')
|
local Terminal = require('opus.terminal')
|
||||||
local UI = require('opus.ui')
|
local UI = require('opus.ui')
|
||||||
|
|
||||||
|
@ -19,10 +20,16 @@ function UI.Embedded:layout()
|
||||||
UI.Window.layout(self)
|
UI.Window.layout(self)
|
||||||
|
|
||||||
if not self.win then
|
if not self.win then
|
||||||
|
local t
|
||||||
function self.render()
|
function self.render()
|
||||||
self:sync()
|
if not t then
|
||||||
if self.focused then
|
t = Event.onTimeout(0, function()
|
||||||
self:setCursorPos(self.win.getCursorPos())
|
t = nil
|
||||||
|
if self.focused then
|
||||||
|
self:setCursorPos(self.win.getCursorPos())
|
||||||
|
end
|
||||||
|
self:sync()
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.win = Terminal.window(UI.term.device, self.x, self.y, self.width, self.height, false)
|
self.win = Terminal.window(UI.term.device, self.x, self.y, self.width, self.height, false)
|
||||||
|
@ -68,7 +75,6 @@ function UI.Embedded:eventHandler(event)
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Embedded.example()
|
function UI.Embedded.example()
|
||||||
local Event = require('opus.event')
|
|
||||||
local Util = require('opus.util')
|
local Util = require('opus.util')
|
||||||
local term = _G.term
|
local term = _G.term
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,8 @@ function UI.MenuBar.example()
|
||||||
return UI.MenuBar {
|
return UI.MenuBar {
|
||||||
buttons = {
|
buttons = {
|
||||||
{ text = 'Choice1', event = 'event1' },
|
{ text = 'Choice1', event = 'event1' },
|
||||||
{ text = 'Choice2', event = 'event2' },
|
{ text = 'Choice2', event = 'event2', inactive = true },
|
||||||
|
{ text = 'Choice3', event = 'event3' },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,4 +5,5 @@ UI.MenuItem = class(UI.FlatButton)
|
||||||
UI.MenuItem.defaults = {
|
UI.MenuItem.defaults = {
|
||||||
UIElement = 'MenuItem',
|
UIElement = 'MenuItem',
|
||||||
noPadding = false,
|
noPadding = false,
|
||||||
|
textInactiveColor = colors.gray,
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ UI.Page.defaults = {
|
||||||
textColor = colors.white,
|
textColor = colors.white,
|
||||||
}
|
}
|
||||||
function UI.Page:postInit()
|
function UI.Page:postInit()
|
||||||
self.parent = self.parent or UI.defaultDevice
|
self.parent = self.parent or UI.term
|
||||||
self.__target = self
|
self.__target = self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,9 @@ function UI.ScrollBar:draw()
|
||||||
|
|
||||||
self:clear()
|
self:clear()
|
||||||
|
|
||||||
|
-- ...
|
||||||
|
self:write(1, 1, ' ', view.fill)
|
||||||
|
|
||||||
if view.totalHeight > view.height then
|
if view.totalHeight > view.height then
|
||||||
local maxScroll = view.totalHeight - view.height
|
local maxScroll = view.totalHeight - view.height
|
||||||
local percent = view.offsetY / maxScroll
|
local percent = view.offsetY / maxScroll
|
||||||
|
|
|
@ -29,6 +29,7 @@ function UI.ScrollingGrid:getViewArea()
|
||||||
height = self.pageSize, -- viewable height
|
height = self.pageSize, -- viewable height
|
||||||
totalHeight = Util.size(self.values), -- total height
|
totalHeight = Util.size(self.values), -- total height
|
||||||
offsetY = self.scrollOffset, -- scroll offset
|
offsetY = self.scrollOffset, -- scroll offset
|
||||||
|
fill = not self.disableHeader and self.headerBackgroundColor,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ UI.TabBar = class(UI.MenuBar)
|
||||||
UI.TabBar.defaults = {
|
UI.TabBar.defaults = {
|
||||||
UIElement = 'TabBar',
|
UIElement = 'TabBar',
|
||||||
buttonClass = 'TabBarMenuItem',
|
buttonClass = 'TabBarMenuItem',
|
||||||
backgroundColor = UI.colors.tertiary,
|
backgroundColor = colors.black,
|
||||||
selectedBackgroundColor = UI.colors.primary,
|
selectedBackgroundColor = UI.colors.primary,
|
||||||
unselectedBackgroundColor = UI.colors.tertiary,
|
unselectedBackgroundColor = UI.colors.tertiary,
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ function UI.TabBar:eventHandler(event)
|
||||||
self:emit({ type = 'tab_change', current = si, last = pi, tab = selected })
|
self:emit({ type = 'tab_change', current = si, last = pi, tab = selected })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
UI.MenuBar.draw(self)
|
self:draw(self)
|
||||||
end
|
end
|
||||||
return UI.MenuBar.eventHandler(self, event)
|
return UI.MenuBar.eventHandler(self, event)
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@ UI.TabBarMenuItem = class(UI.Button)
|
||||||
UI.TabBarMenuItem.defaults = {
|
UI.TabBarMenuItem.defaults = {
|
||||||
UIElement = 'TabBarMenuItem',
|
UIElement = 'TabBarMenuItem',
|
||||||
event = 'tab_select',
|
event = 'tab_select',
|
||||||
|
textInactiveColor = colors.lightGray,
|
||||||
}
|
}
|
||||||
function UI.TabBarMenuItem:draw()
|
function UI.TabBarMenuItem:draw()
|
||||||
if self.selected then
|
if self.selected then
|
||||||
|
|
|
@ -117,5 +117,9 @@ function UI.Tabs.example()
|
||||||
index = 3,
|
index = 3,
|
||||||
tabTitle = 'tab3',
|
tabTitle = 'tab3',
|
||||||
},
|
},
|
||||||
|
enable = function(self)
|
||||||
|
UI.Tabs.enable(self)
|
||||||
|
self:setActive(self.tab3, false)
|
||||||
|
end,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,7 +20,6 @@ end
|
||||||
|
|
||||||
function UI.TextArea:draw()
|
function UI.TextArea:draw()
|
||||||
self:clear()
|
self:clear()
|
||||||
self.cursorX, self.cursorY = 1, 1
|
|
||||||
self:print(self.value)
|
self:print(self.value)
|
||||||
self:drawChildren()
|
self:drawChildren()
|
||||||
end
|
end
|
||||||
|
|
|
@ -47,11 +47,18 @@ function UI.Viewport:setScrollPosition(offy, offx) -- argh - reverse
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Viewport:write(x, y, text, bg, tc)
|
function UI.Viewport:blit(x, y, text, bg, fg)
|
||||||
if y > #self.lines then
|
if y > #self.lines then
|
||||||
self:resizeBuffer(self.width, y)
|
self:resizeBuffer(self.width, y)
|
||||||
end
|
end
|
||||||
return UI.Window.write(self, x, y, text, bg, tc)
|
return UI.Window.blit(self, x, y, text, bg, fg)
|
||||||
|
end
|
||||||
|
|
||||||
|
function UI.Viewport:write(x, y, text, bg, fg)
|
||||||
|
if y > #self.lines then
|
||||||
|
self:resizeBuffer(self.width, y)
|
||||||
|
end
|
||||||
|
return UI.Window.write(self, x, y, text, bg, fg)
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Viewport:setViewHeight(h)
|
function UI.Viewport:setViewHeight(h)
|
||||||
|
|
|
@ -699,6 +699,31 @@ local function paragraphwrap(text, linewidth, res)
|
||||||
end
|
end
|
||||||
-- end word wrapping
|
-- end word wrapping
|
||||||
|
|
||||||
|
--[[
|
||||||
|
-- better wrapping - needs further testing before replacing the current wrapping
|
||||||
|
functions
|
||||||
|
local function wrap(text, max)
|
||||||
|
local index = 1
|
||||||
|
local lines = { }
|
||||||
|
repeat
|
||||||
|
if #text <= max then
|
||||||
|
table.insert(lines, text)
|
||||||
|
text = ''
|
||||||
|
elseif text:sub(max+1, max+1) == ' ' then
|
||||||
|
table.insert(lines, text:sub(index, max))
|
||||||
|
text = text:sub(max + 2)
|
||||||
|
else
|
||||||
|
local x = text:sub(1, max)
|
||||||
|
local s = x:match('(.*) ') or x
|
||||||
|
text = text:sub(#s + 1)
|
||||||
|
table.insert(lines, s)
|
||||||
|
end
|
||||||
|
text = text:match('^%s*(.*)')
|
||||||
|
until not text or #text == 0
|
||||||
|
return lines
|
||||||
|
end
|
||||||
|
]]
|
||||||
|
|
||||||
function Util.wordWrap(str, limit)
|
function Util.wordWrap(str, limit)
|
||||||
local longLines = Util.split(str)
|
local longLines = Util.split(str)
|
||||||
local lines = { }
|
local lines = { }
|
||||||
|
|
Loading…
Reference in New Issue