color rework + cleanup

This commit is contained in:
kepler155c@gmail.com 2020-04-16 23:13:19 -06:00
parent 3e41996b9b
commit 9d2a76f4ea
28 changed files with 364 additions and 238 deletions

View File

@ -184,9 +184,7 @@ local Browser = UI.Page {
text = 'Add', event = 'add_association',
},
},
statusBar = UI.StatusBar {
backgroundColor = colors.cyan,
},
statusBar = UI.StatusBar { },
},
accelerators = {
[ 'control-q' ] = 'quit',
@ -547,6 +545,4 @@ local args = Util.parse(...)
Browser:setDir(args[1] or shell.dir())
UI:setPage(Browser)
Event.pullEvents()
UI.term:reset()
UI:start()

View File

@ -382,11 +382,12 @@ function page:executeStatement(statement)
end
end
local args = Util.parse(...)
local args = { ... }
if args[1] then
command = 'args[1]'
sandboxEnv.args = args
page:setResult(args[1])
page:setPrompt(command)
end
UI:setPage(page)

View File

@ -95,6 +95,7 @@ local page = UI.Page {
ey = -2,
width = 8,
selectedBackgroundColor = UI.colors.primary,
backgroundColor = UI.colors.tertiary,
layout = function(self)
self.height = nil
UI.TabBar.layout(self)

View File

@ -12,7 +12,7 @@ local gridColumns = {}
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 = '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' })
end
table.insert(gridColumns, { heading = 'Msg', key = 'packetStr' })
@ -42,7 +42,7 @@ local page = UI.Page {
configSlide = UI.SlideOut {
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' },
configTabs = UI.Tabs {
y = 2,

View File

@ -28,10 +28,10 @@ if _G.http.websocket then
event = 'update_key',
},
labelText = UI.TextArea {
x = 2, ex = -2, y = 6, ey = -4,
x = 2, ex = -2, y = 5, ey = -4,
textColor = colors.yellow,
backgroundColor = colors.black,
marginLeft = 0, marginRight = 0,
marginLeft = 1, marginRight = 1, marginTop = 1,
value = string.format(
[[Use a non-changing cloud key. Note that only a single computer can use this session at one time.
To obtain a key, visit:

View File

@ -23,7 +23,7 @@ return UI.Tab {
x = 2, y = 2, ex = -2, ey = 4,
},
grid = UI.ScrollingGrid {
x = 2, y = 6, ex = -2, ey = -2,
x = 2, y = 5, ex = -2, ey = -2,
values = {
{ name = '', value = '' },
{ name = 'CC version', value = Util.getVersion() },

View File

@ -35,9 +35,10 @@ local tab = UI.Tab {
event = 'update',
},
labelText = UI.TextArea {
x = 2, ex = -2, y = 7, ey = -4,
x = 2, ex = -2, y = 6, ey = -4,
backgroundColor = colors.black,
textColor = colors.yellow,
marginLeft = 1, marginRight = 1, marginTop = 1,
value = 'Choose an application launcher',
},
}

View File

@ -9,8 +9,9 @@ return UI.Tab {
tabTitle = 'Network',
description = 'Networking options',
info = UI.TextArea {
x = 2, y = 6, ex = -2, ey = -2,
x = 2, y = 5, ex = -2, ey = -2,
backgroundColor = colors.black,
marginLeft = 1, marginRight = 1, marginTop = 1,
value = string.format(
[[%sSet the primary modem used for wireless communications.%s

View File

@ -25,10 +25,11 @@ return UI.Tab {
event = 'update_password',
},
info = UI.TextArea {
x = 2, ex = -2, y = 6, ey = -4,
x = 2, ex = -2, y = 5, ey = -4,
backgroundColor = colors.black,
textColor = colors.yellow,
inactive = true,
marginLeft = 1, marginRight = 1, marginTop = 1,
value = 'Add a password to enable other computers to connect to this one.',
},
eventHandler = function(self, event)

View File

@ -2,49 +2,94 @@ local UI = require('opus.ui')
local settings = _G.settings
if settings then
local settingsTab = UI.Tab {
tabTitle = 'Settings',
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' },
},
},
}
local transform = {
string = tostring,
number = tonumber,
}
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 = { }
for _,v in pairs(settings.getNames()) do
local value = settings.get(v)
if not value then
value = false
end
table.insert(values, {
name = v,
value = value,
value = settings.get(v) or false,
})
end
self.grid:setValues(values)
self.grid:setIndex(1)
end,
enable = function(self)
self:reload()
UI.Tab.enable(self)
end
function settingsTab:eventHandler(event)
end,
eventHandler = function(self, event)
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
settings.set(event.selected.name, event.selected.value)
settings.save('.settings')
self.grid:draw()
else
self.editor:show(event.selected)
end
settings.set(event.selected.name, event.selected.value)
settings.save('.settings')
self.grid:draw()
return true
end
end
-- this needs lots of work - currently only works with booleans
--return settingsTab
end
end,
}

View File

@ -32,3 +32,23 @@ end
help.setPath(table.concat(helpPaths, ':'))
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

View File

@ -65,7 +65,7 @@ function GPS.locate(timeout, debug)
if debug then
print("Position is "..pos.x..","..pos.y..","..pos.z)
end
return vector.new(pos.x, pos.y, pos.z)
return pos and vector.new(pos.x, pos.y, pos.z)
end
function GPS.isAvailable()

View File

@ -1,4 +1,5 @@
local Array = require('opus.array')
local Blit = require('opus.ui.blit')
local class = require('opus.class')
local Event = require('opus.event')
local Input = require('opus.input')
@ -34,11 +35,16 @@ local textutils = _G.textutils
]]
--[[-- Top Level Manager --]]--
local Manager = class()
function Manager:init()
local UI = { }
function UI:init()
self.devices = { }
self.theme = { }
self.extChars = Util.getVersion() >= 1.76
self.colors = {
primary = colors.green,
secondary = colors.lightGray,
tertiary = colors.gray,
}
local function keyFunction(event, code, held)
local ie = Input:translate(event, code, held)
@ -151,7 +157,7 @@ function Manager:init()
end)
end
function Manager:configure(appName, ...)
function UI:configure(appName, ...)
local defaults = Util.loadTable('usr/config/' .. appName) or { }
if not defaults.device then
defaults.device = { }
@ -193,11 +199,11 @@ function Manager:configure(appName, ...)
end
end
function Manager:disableEffects()
self.defaultDevice.effectsEnabled = false
function UI:disableEffects()
self.term.effectsEnabled = false
end
function Manager:loadTheme(filename)
function UI:loadTheme(filename)
if fs.exists(filename) then
local theme, err = Util.loadTable(filename)
if not theme then
@ -207,7 +213,7 @@ function Manager:loadTheme(filename)
end
end
function Manager:generateTheme(filename)
function UI:generateTheme(filename)
local t = { }
local function getName(d)
@ -244,14 +250,14 @@ function Manager:generateTheme(filename)
Util.writeFile(filename, textutils.serialize(t):gsub('(")', ''))
end
function Manager:emitEvent(event)
function UI:emitEvent(event)
local currentPage = self:getActivePage()
if currentPage and currentPage.focused then
return currentPage.focused:emit(event)
end
end
function Manager:click(target, ie)
function UI:click(target, ie)
local clickEvent
if ie.code == 'mouse_drag' then
@ -304,23 +310,22 @@ function Manager:click(target, ie)
target:sync()
end
function Manager:setDefaultDevice(dev)
self.defaultDevice = dev
function UI:setDefaultDevice(dev)
self.term = dev
end
function Manager:addPage(name, page)
function UI:addPage(name, page)
if not self.pages then
self.pages = { }
end
self.pages[name] = page
end
function Manager:setPages(pages)
function UI:setPages(pages)
self.pages = pages
end
function Manager:getPage(pageName)
function UI:getPage(pageName)
local page = self.pages[pageName]
if not page then
@ -330,18 +335,18 @@ function Manager:getPage(pageName)
return page
end
function Manager:getActivePage(page)
function UI:getActivePage(page)
if page then
return page.parent.currentPage
end
return self.defaultDevice.currentPage
return self.term.currentPage
end
function Manager:setActivePage(page)
function UI:setActivePage(page)
page.parent.currentPage = page
end
function Manager:setPage(pageOrName, ...)
function UI:setPage(pageOrName, ...)
local page = pageOrName
if type(pageOrName) == 'string' then
@ -361,7 +366,6 @@ function Manager:setPage(pageOrName, ...)
page.previousPage = currentPage
end
self:setActivePage(page)
--page:clear(page.backgroundColor)
page:enable(...)
page:draw()
if page.focused then
@ -372,27 +376,27 @@ function Manager:setPage(pageOrName, ...)
end
end
function Manager:getCurrentPage()
return self.defaultDevice.currentPage
function UI:getCurrentPage()
return self.term.currentPage
end
function Manager:setPreviousPage()
if self.defaultDevice.currentPage.previousPage then
local previousPage = self.defaultDevice.currentPage.previousPage.previousPage
self:setPage(self.defaultDevice.currentPage.previousPage)
self.defaultDevice.currentPage.previousPage = previousPage
function UI:setPreviousPage()
if self.term.currentPage.previousPage then
local previousPage = self.term.currentPage.previousPage.previousPage
self:setPage(self.term.currentPage.previousPage)
self.term.currentPage.previousPage = previousPage
end
end
function Manager:getDefaults(element, args)
function UI:getDefaults(element, args)
local defaults = Util.deepCopy(element.defaults)
if args then
Manager:mergeProperties(defaults, args)
UI:mergeProperties(defaults, args)
end
return defaults
end
function Manager:mergeProperties(obj, args)
function UI:mergeProperties(obj, args)
if args then
for k,v in pairs(args) do
if k == 'accelerators' then
@ -408,7 +412,7 @@ function Manager:mergeProperties(obj, args)
end
end
function Manager:pullEvents(...)
function UI:pullEvents(...)
local s, m = pcall(Event.pullEvents, ...)
self.term:reset()
if not s and m then
@ -416,17 +420,11 @@ function Manager:pullEvents(...)
end
end
Manager.colors = {
primary = colors.cyan,
secondary = colors.lightGray,
tertiary = colors.gray,
}
UI.exitPullEvents = Event.exitPullEvents
UI.quit = Event.exitPullEvents
UI.start = UI.pullEvents
Manager.exitPullEvents = Event.exitPullEvents
Manager.quit = Event.exitPullEvents
Manager.start = Manager.pullEvents
local UI = Manager()
UI:init()
--[[-- Basic drawable area --]]--
UI.Window = class(Canvas)
@ -785,89 +783,19 @@ function UI.Window:print(text, bg, fg)
local marginLeft = self.marginLeft or 0
local marginRight = self.marginRight or 0
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 result = { line:find("(%w+)", cx) }
if #result > 1 and result[2] > cx then
return _sub(line, cx, result[2] + 1)
elseif #result > 0 and result[1] == cx then
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)
local y = (self.marginTop or 0) + 1
for _,line in pairs(Util.split(text)) do
for _, ln in ipairs(Blit(line, cs):wrap(width)) do
self:blit(marginLeft + 1, y, ln.text, ln.bg, ln.fg)
y = y + 1
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
UI.Window.docs.focus = [[focus(VOID)
@ -1126,7 +1054,7 @@ function UI.Device:runTransitions(transitions)
transitions[k] = nil
end
end
self.currentPage:render(self.device)
self.currentPage:render(self, true)
if Util.empty(transitions) then
break
end
@ -1143,7 +1071,7 @@ function UI.Device:sync()
if transitions then
self:runTransitions(transitions)
else
self.currentPage:render(self.device)
self.currentPage:render(self, true)
end
if self:getCursorBlink() then
@ -1179,7 +1107,7 @@ local function loadComponents()
return self(...)
end
})
UI[name]._preload = function(self)
UI[name]._preload = function()
return load(name)
end
end

View File

@ -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

View File

@ -71,7 +71,7 @@ end
-- resize the canvas buffer - not the canvas itself
function Canvas:resizeBuffer(w, h)
for i = #self.lines, h do
for i = #self.lines + 1, h do
self.lines[i] = { }
self:clearLine(i)
end
@ -297,40 +297,38 @@ function Canvas:applyPalette(palette)
self.palette = palette
end
function Canvas:render(device)
local offset = { x = 0, y = 0 }
-- 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)
-- either render directly to the device
-- or use another canvas as a backing buffer
function Canvas:render(device, doubleBuffer)
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
-- 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.
-- layers in the beginning of the array are overlayed by layers further down in
-- the array.
function Canvas:__renderLayers(device, offset)
function Canvas:__renderLayers(device, offset, doubleBuffer)
if self.children then
for i = #self.children, 1, -1 do
local canvas = self.children[i]
@ -364,7 +362,7 @@ function Canvas:__renderLayers(device, offset)
canvas:__renderLayers(device, {
x = canvas.x + offset.x - 1 - (self.offx or 0),
y = canvas.y + offset.y - 1 - (self.offy or 0),
})
}, doubleBuffer)
end
canvas.regions = nil
end
@ -377,19 +375,19 @@ function Canvas:__renderLayers(device, offset)
y = region[2] - offset.y,
ex = region[3] - offset.x,
ey = region[4] - offset.y },
{ x = region[1], y = region[2] })
{ x = region[1], y = region[2] }, doubleBuffer)
end
self.regions = nil
self:clean()
end
-- performance can probably be improved by using one more buffer tied to the device
function Canvas:__blitRect(device, src, tgt)
function Canvas:__blitRect(device, src, tgt, doubleBuffer)
src = src or { x = 1, y = 1, ex = self.ex - self.x + 1, ey = self.ey - self.y + 1 }
tgt = tgt or self
-- for visualizing updates on the screen
--[[
if Canvas.__visualize or self.visualize then
local drew
local t = _rep(' ', src.ex-src.x + 1)
@ -407,6 +405,7 @@ function Canvas:__blitRect(device, src, tgt)
repeat until os.clock()-c > .03
end
end
]]
for i = 0, src.ey - src.y do
local line = self.lines[src.y + i + (self.offy or 0)]
if line and line.dirty then
@ -416,8 +415,13 @@ function Canvas:__blitRect(device, src, tgt)
fg = _sub(fg, src.x, src.ex)
bg = _sub(bg, src.x, src.ex)
end
device.setCursorPos(tgt.x, tgt.y + i)
device.blit(t, fg, bg)
if doubleBuffer then
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

View File

@ -7,8 +7,7 @@ UI.Dialog = class(UI.SlideOut)
UI.Dialog.defaults = {
UIElement = 'Dialog',
height = 7,
textColor = colors.black,
backgroundColor = colors.white,
noFill = true,
okEvent ='dialog_ok',
cancelEvent = 'dialog_cancel',
}
@ -17,19 +16,6 @@ function UI.Dialog:postInit()
self.titleBar = UI.TitleBar({ event = self.cancelEvent, title = self.title })
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)
if event.type == 'dialog_cancel' then
self:hide()

View File

@ -1,4 +1,5 @@
local class = require('opus.class')
local Event = require('opus.event')
local Terminal = require('opus.terminal')
local UI = require('opus.ui')
@ -19,10 +20,16 @@ function UI.Embedded:layout()
UI.Window.layout(self)
if not self.win then
local t
function self.render()
self:sync()
if self.focused then
self:setCursorPos(self.win.getCursorPos())
if not t then
t = Event.onTimeout(0, function()
t = nil
if self.focused then
self:setCursorPos(self.win.getCursorPos())
end
self:sync()
end)
end
end
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
function UI.Embedded.example()
local Event = require('opus.event')
local Util = require('opus.util')
local term = _G.term

View File

@ -93,7 +93,8 @@ function UI.MenuBar.example()
return UI.MenuBar {
buttons = {
{ text = 'Choice1', event = 'event1' },
{ text = 'Choice2', event = 'event2' },
{ text = 'Choice2', event = 'event2', inactive = true },
{ text = 'Choice3', event = 'event3' },
}
}
end

View File

@ -5,4 +5,5 @@ UI.MenuItem = class(UI.FlatButton)
UI.MenuItem.defaults = {
UIElement = 'MenuItem',
noPadding = false,
textInactiveColor = colors.gray,
}

View File

@ -20,7 +20,7 @@ UI.Page.defaults = {
textColor = colors.white,
}
function UI.Page:postInit()
self.parent = self.parent or UI.defaultDevice
self.parent = self.parent or UI.term
self.__target = self
end

View File

@ -22,6 +22,9 @@ function UI.ScrollBar:draw()
self:clear()
-- ...
self:write(1, 1, ' ', view.fill)
if view.totalHeight > view.height then
local maxScroll = view.totalHeight - view.height
local percent = view.offsetY / maxScroll

View File

@ -29,6 +29,7 @@ function UI.ScrollingGrid:getViewArea()
height = self.pageSize, -- viewable height
totalHeight = Util.size(self.values), -- total height
offsetY = self.scrollOffset, -- scroll offset
fill = not self.disableHeader and self.headerBackgroundColor,
}
end

View File

@ -6,7 +6,7 @@ UI.TabBar = class(UI.MenuBar)
UI.TabBar.defaults = {
UIElement = 'TabBar',
buttonClass = 'TabBarMenuItem',
backgroundColor = UI.colors.tertiary,
backgroundColor = colors.black,
selectedBackgroundColor = UI.colors.primary,
unselectedBackgroundColor = UI.colors.tertiary,
}
@ -32,7 +32,7 @@ function UI.TabBar:eventHandler(event)
self:emit({ type = 'tab_change', current = si, last = pi, tab = selected })
end
end
UI.MenuBar.draw(self)
self:draw(self)
end
return UI.MenuBar.eventHandler(self, event)
end

View File

@ -5,6 +5,7 @@ UI.TabBarMenuItem = class(UI.Button)
UI.TabBarMenuItem.defaults = {
UIElement = 'TabBarMenuItem',
event = 'tab_select',
textInactiveColor = colors.lightGray,
}
function UI.TabBarMenuItem:draw()
if self.selected then

View File

@ -117,5 +117,9 @@ function UI.Tabs.example()
index = 3,
tabTitle = 'tab3',
},
enable = function(self)
UI.Tabs.enable(self)
self:setActive(self.tab3, false)
end,
}
end

View File

@ -20,7 +20,6 @@ end
function UI.TextArea:draw()
self:clear()
self.cursorX, self.cursorY = 1, 1
self:print(self.value)
self:drawChildren()
end

View File

@ -47,11 +47,18 @@ function UI.Viewport:setScrollPosition(offy, offx) -- argh - reverse
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
self:resizeBuffer(self.width, y)
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
function UI.Viewport:setViewHeight(h)

View File

@ -699,6 +699,31 @@ local function paragraphwrap(text, linewidth, res)
end
-- 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)
local longLines = Util.split(str)
local lines = { }