Ui enhancements 2.0 #29

Merged
kepler155c merged 13 commits from ui-enhancements-2.0 into develop-1.8 2020-04-22 00:40:48 -04:00
65 changed files with 1842 additions and 1310 deletions

View File

@@ -236,10 +236,7 @@ function substitutionPage.info:draw()
end end
self:clear() self:clear()
self:setCursorPos(1, 1) self:print(' Replace ' .. inName .. '\n' .. ' With ' .. outName)
self:print(' Replace ' .. inName .. '\n')
--self:print(' ' .. sub.id .. ':' .. sub.dmg .. '\n', nil, colors.yellow)
self:print(' With ' .. outName)
end end
function substitutionPage:enable() function substitutionPage:enable()
@@ -536,7 +533,7 @@ local startPage = UI.Page {
event = 'setStartLevel', event = 'setStartLevel',
cancelEvent = 'slide_hide', cancelEvent = 'slide_hide',
text = UI.Text { text = UI.Text {
x = 5, y = 1, width = 20, x = 5, y = 1, width = 10,
textColor = colors.gray, textColor = colors.gray,
}, },
textEntry = UI.TextEntry { textEntry = UI.TextEntry {
@@ -554,7 +551,7 @@ local startPage = UI.Page {
event = 'setStartBlock', event = 'setStartBlock',
cancelEvent = 'slide_hide', cancelEvent = 'slide_hide',
text = UI.Text { text = UI.Text {
x = 2, y = 1, width = 20, x = 2, y = 1, width = 13,
textColor = colors.gray, textColor = colors.gray,
}, },
textEntry = UI.TextEntry { textEntry = UI.TextEntry {
@@ -727,8 +724,7 @@ function startPage:eventHandler(event)
Builder:begin() Builder:begin()
elseif event.type == 'quit' then elseif event.type == 'quit' then
UI.term:reset() UI:quit()
Event.exitPullEvents()
end end
return UI.Page.eventHandler(self, event) return UI.Page.eventHandler(self, event)
@@ -772,5 +768,4 @@ UI:setPages({
}) })
UI:setPage('start') UI:setPage('start')
UI:start()
UI:pullEvents()

12
ccemux/etc/apps.db Normal file
View File

@@ -0,0 +1,12 @@
{
[ "87e89abb4c1c551fe08d355d097f18b8de78edca5f556997085681662fce8eed" ] = {
title = "Config",
category = "CCEmuX",
run = "emu config",
},
[ "cec3a9b89b2e391393d0f68e4bc12a9fa6cf358b3cdf79496dc442d52b8dd528" ] = {
title = "Data",
category = "CCEmuX",
run = "emu data",
},
}

View File

@@ -9,7 +9,7 @@ local tab = UI.Tab {
tabTitle = 'CCEmuX', tabTitle = 'CCEmuX',
description = 'CCEmuX peripherals', description = 'CCEmuX peripherals',
form = UI.Form { form = UI.Form {
x = 2, ex = -2, y = 1, ey = 4, x = 2, ex = -2, y = 2, ey = 5,
values = { values = {
side = 'bottom', side = 'bottom',
type = 'wireless_modem', type = 'wireless_modem',
@@ -28,7 +28,7 @@ local tab = UI.Tab {
}, },
}, },
drive_id = UI.TextEntry { drive_id = UI.TextEntry {
x = 20, y = 3, x = 19, y = 3,
formKey = 'drive_id', formKey = 'drive_id',
shadowText = 'id', shadowText = 'id',
width = 5, width = 5,
@@ -36,13 +36,13 @@ local tab = UI.Tab {
transform = 'number', transform = 'number',
}, },
add = UI.Button { add = UI.Button {
x = 28, y = 3, x = -6, y = 3, width = 5,
text = 'Add', event = 'form_ok', text = 'Add', event = 'form_ok',
help = 'Add items to turtle to add to filter', help = 'Add items to turtle to add to filter',
}, },
}, },
grid = UI.Grid { grid = UI.Grid {
x = 3, ex = -3, y = 6, ey = -2, x = 2, ex = -2, y = 7, ey = -2,
columns = { columns = {
{ heading = 'Side', key = 'side', width = 8 }, { heading = 'Side', key = 'side', width = 8 },
{ heading = 'Type', key = 'type' }, { heading = 'Type', key = 'type' },

View File

@@ -8,10 +8,10 @@ local http = _G.http
local multishell = _ENV.multishell local multishell = _ENV.multishell
local os = _G.os local os = _G.os
local shell = _ENV.shell local shell = _ENV.shell
local colors = _G.colors
local REGISTRY_DIR = 'usr/.registry' local REGISTRY_DIR = 'usr/.registry'
-- FIX SOMEDAY -- FIX SOMEDAY
local function registerApp(app, key) local function registerApp(app, key)
app.key = SHA.compute(key) app.key = SHA.compute(key)
@@ -27,7 +27,6 @@ local function unregisterApp(key)
end end
end end
local sandboxEnv = Util.shallowCopy(_ENV) local sandboxEnv = Util.shallowCopy(_ENV)
setmetatable(sandboxEnv, { __index = _G }) setmetatable(sandboxEnv, { __index = _G })
@@ -36,21 +35,10 @@ UI:configure('Appstore', ...)
local APP_DIR = 'usr/apps' local APP_DIR = 'usr/apps'
local sources = { local source = {
text = "STD Default",
{ text = "STD Default", event = 'source',
event = 'source', url = "https://github.com/LDDestroier/STD-GUI/raw/master/list.lua",
url = "https://github.com/LDDestroier/STD-GUI/raw/master/list.lua" }, --stock
--[[
{ text = "Discover",
event = 'source',
generateName = true,
url = "http://pastebin.com/raw/9bXfCz6M" }, --owned by dannysmc95
{ text = "Opus",
event = 'source',
url = "http://pastebin.com/raw/ajQ91Rmn" },
]]
} }
shell.setDir(APP_DIR) shell.setDir(APP_DIR)
@@ -87,14 +75,14 @@ local function runApp(app, checkExists, ...)
error('Failed to download') error('Failed to download')
end end
local fn = loadstring(program, app.name) fn = _G.loadstring(program, app.name)
if not fn then if not fn then
error('Failed to download') error('Failed to download')
end end
setfenv(fn, sandboxEnv) _G.setfenv(fn, sandboxEnv)
fn(unpack(args)) fn(table.unpack(args))
end end
end end
@@ -134,16 +122,16 @@ local viewApp = function(app)
return true return true
end end
local getSourceListing = function(source) local getSourceListing = function()
local contents = http.get(source.url) local contents = http.get(source.url)
if contents then if contents then
local fn = loadstring(contents.readAll(), source.text) local fn = _G.loadstring(contents.readAll(), source.text)
contents.close() contents.close()
local env = { std = { } } local env = { std = { } }
setmetatable(env, { __index = _G }) setmetatable(env, { __index = _G })
setfenv(fn, env) _G.setfenv(fn, env)
fn() fn()
if env.contextualGet then if env.contextualGet then
@@ -172,9 +160,28 @@ local getSourceListing = function(source)
end end
end end
getSourceListing()
if not source.storeURLs then
error('Unable to download application list')
end
local buttons = { }
for k,v in Util.spairs(source.storeCatagoryNames,
function(a, b) return a:lower() < b:lower() end) do
if v ~= 'Operating System' then
table.insert(buttons, {
text = v,
event = 'category',
index = k,
})
end
end
source.index, source.name = Util.first(source.storeCatagoryNames)
local appPage = UI.Page { local appPage = UI.Page {
menuBar = UI.MenuBar { menuBar = UI.MenuBar {
-- showBackButton = not pocket,
buttons = { buttons = {
{ text = '\027', event = 'back' }, { text = '\027', event = 'back' },
{ text = 'Install', event = 'install' }, { text = 'Install', event = 'install' },
@@ -204,16 +211,14 @@ function appPage.container.viewport:draw()
Ansi.yellow .. app.description .. Ansi.reset) Ansi.yellow .. app.description .. Ansi.reset)
self:clear() self:clear()
self:setCursorPos(1, 1)
self:print(str) self:print(str)
self.ymax = self.cursorY
if appPage.notification.enabled then if appPage.notification.enabled then
appPage.notification:draw() appPage.notification:draw()
end end
end end
function appPage:enable(source, app) function appPage:enable(app)
self.source = source self.source = source
self.app = app self.app = app
UI.Page.enable(self) UI.Page.enable(self)
@@ -293,8 +298,7 @@ end
local categoryPage = UI.Page { local categoryPage = UI.Page {
menuBar = UI.MenuBar { menuBar = UI.MenuBar {
buttons = { buttons = {
{ text = 'Catalog', dropdown = sources }, { text = 'Category', name = 'categoryButton', dropdown = buttons },
{ text = 'Category', name = 'categoryButton', dropdown = { } },
}, },
}, },
grid = UI.ScrollingGrid { grid = UI.ScrollingGrid {
@@ -309,62 +313,21 @@ local categoryPage = UI.Page {
l = 'lua', l = 'lua',
[ 'control-q' ] = 'quit', [ 'control-q' ] = 'quit',
}, },
source = source,
} }
function categoryPage:setCategory(source, name, index) function categoryPage:setCategory(name, index)
self.grid.values = { } self.grid.values = { }
for _,v in pairs(source.storeURLs) do for _,v in pairs(source.storeURLs) do
if index == 0 or index == v.catagory then if index == 0 or index == v.catagory then
table.insert(self.grid.values, v) table.insert(self.grid.values, v)
end end
end end
self.statusBar:setStatus(string.format('%s: %s', source.text, name)) self.statusBar:setStatus(string.format('%s: %s', self.source.text or '', name))
self.grid:update() self.grid:update()
self.grid:setIndex(1) self.grid:setIndex(1)
end end
function categoryPage:setSource(source)
if not source.categoryMenu then
self.statusBar:setStatus('Loading...')
self.statusBar:draw()
self:sync()
getSourceListing(source)
if not source.storeURLs then
error('Unable to download application list')
end
local buttons = { }
for k,v in Util.spairs(source.storeCatagoryNames,
function(a, b) return a:lower() < b:lower() end) do
if v ~= 'Operating System' then
table.insert(buttons, {
text = v,
event = 'category',
index = k,
})
end
end
source.categoryMenu = UI.DropMenu({
buttons = buttons,
})
source.index, source.name = Util.first(source.storeCatagoryNames)
categoryPage.menuBar.categoryButton:add({
categoryMenu = source.categoryMenu
})
end
self.source = source
self.menuBar.categoryButton.dropmenu = source.categoryMenu
categoryPage:setCategory(source, source.name, source.index)
end
function categoryPage.grid:sortCompare(a, b) function categoryPage.grid:sortCompare(a, b)
return a.ltitle < b.ltitle return a.ltitle < b.ltitle
end end
@@ -377,12 +340,11 @@ function categoryPage.grid:getRowTextColor(row, selected)
end end
function categoryPage:eventHandler(event) function categoryPage:eventHandler(event)
if event.type == 'grid_select' or event.type == 'select' then if event.type == 'grid_select' or event.type == 'select' then
UI:setPage(appPage, self.source, self.grid:getSelected()) UI:setPage(appPage, self.grid:getSelected())
elseif event.type == 'category' then elseif event.type == 'category' then
self:setCategory(self.source, event.button.text, event.button.index) self:setCategory(event.button.text, event.button.index)
self:setFocus(self.grid) self:setFocus(self.grid)
self:draw() self:draw()
@@ -392,7 +354,7 @@ function categoryPage:eventHandler(event)
self:draw() self:draw()
elseif event.type == 'quit' then elseif event.type == 'quit' then
UI:exitPullEvents() UI:quit()
else else
return UI.Page.eventHandler(self, event) return UI.Page.eventHandler(self, event)
@@ -401,8 +363,7 @@ function categoryPage:eventHandler(event)
end end
print("Retrieving catalog list") print("Retrieving catalog list")
categoryPage:setSource(sources[1]) categoryPage:setCategory(source.name, source.index)
UI:setPage(categoryPage) UI:setPage(categoryPage)
UI:pullEvents() UI:start()
UI.term:reset()

View File

@@ -3,7 +3,6 @@ local Event = require('opus.event')
local UI = require('opus.ui') local UI = require('opus.ui')
local Util = require('opus.util') local Util = require('opus.util')
local colors = _G.colors
local peripheral = _G.peripheral local peripheral = _G.peripheral
--[[ -- PeripheralsPage -- ]] -- --[[ -- PeripheralsPage -- ]] --
@@ -16,6 +15,20 @@ local peripheralsPage = UI.Page {
}, },
sortColumn = 'type', sortColumn = 'type',
autospace = true, autospace = true,
enable = function(self)
local sides = peripheral.getNames()
Util.clear(self.values)
for _,side in pairs(sides) do
table.insert(self.values, {
type = peripheral.getType(side),
side = side
})
end
self:update()
self:adjustWidth()
UI.Grid.enable(self)
end,
}, },
statusBar = UI.StatusBar { statusBar = UI.StatusBar {
values = 'Select peripheral', values = 'Select peripheral',
@@ -23,52 +36,35 @@ local peripheralsPage = UI.Page {
accelerators = { accelerators = {
[ 'control-q' ] = 'quit', [ 'control-q' ] = 'quit',
}, },
updatePeripherals = function(self)
if UI:getCurrentPage() == self then
self.grid:draw()
self:sync()
end
end,
eventHandler = function(self, event)
if event.type == 'quit' then
UI:quit()
elseif event.type == 'grid_select' then
UI:setPage('methods', event.selected)
end
return UI.Page.eventHandler(self, event)
end,
} }
function peripheralsPage.grid:enable()
local sides = peripheral.getNames()
Util.clear(self.values)
for _,side in pairs(sides) do
table.insert(self.values, {
type = peripheral.getType(side),
side = side
})
end
self:update()
self:adjustWidth()
UI.Grid.enable(self)
end
function peripheralsPage:updatePeripherals()
if UI:getCurrentPage() == self then
self.grid:draw()
self:sync()
end
end
function peripheralsPage:eventHandler(event)
if event.type == 'quit' then
Event.exitPullEvents()
elseif event.type == 'grid_select' then
UI:setPage('methods', event.selected)
end
return UI.Page.eventHandler(self, event)
end
--[[ -- MethodsPage -- ]] -- --[[ -- MethodsPage -- ]] --
local methodsPage = UI.Page { local methodsPage = UI.Page {
backgroundColor = colors.black,
doc = UI.TextArea { doc = UI.TextArea {
backgroundColor = colors.black, backgroundColor = 'black',
x = 2, y = 2, ex = -1, ey = -7, ey = -7,
marginLeft = 1, marginTop = 1,
}, },
grid = UI.ScrollingGrid { grid = UI.ScrollingGrid {
y = -6, ey = -2, y = -6, ey = -2,
columns = { columns = {
{ heading = 'Name', key = 'name', width = UI.term.width } { heading = 'Name', key = 'name' }
}, },
sortColumn = 'name', sortColumn = 'name',
}, },
@@ -198,4 +194,4 @@ UI:setPages({
methods = methodsPage, methods = methodsPage,
}) })
UI:pullEvents() UI:start()

View File

@@ -122,7 +122,6 @@ function page:drawInfo(drive, textArea)
return isValid(drive) and fs.getFreeSpace(drive.getMountPath()) or 0 return isValid(drive) and fs.getFreeSpace(drive.getMountPath()) or 0
end end
textArea:setCursorPos(1, 1)
textArea:print(string.format('Drive: %s%s%s\nLabel: %s%s%s\nUsed: %s%s%s\nFree: %s%s%s', textArea:print(string.format('Drive: %s%s%s\nLabel: %s%s%s\nUsed: %s%s%s\nFree: %s%s%s',
Ansi.yellow, drive.name, Ansi.reset, Ansi.yellow, drive.name, Ansi.reset,
isValid(drive) and Ansi.yellow or Ansi.orange, getLabel():sub(1, 10), Ansi.reset, isValid(drive) and Ansi.yellow or Ansi.orange, getLabel():sub(1, 10), Ansi.reset,
@@ -138,6 +137,7 @@ function page:scan()
self.copyButton.inactive = not valid self.copyButton.inactive = not valid
self:draw() self:draw()
self.progress:clear()
self.progress:centeredWrite(1, 'Analyzing Disks..') self.progress:centeredWrite(1, 'Analyzing Disks..')
self.progress:sync() self.progress:sync()
@@ -167,6 +167,7 @@ function page:copy()
throttle() throttle()
end end
self.progress:clear()
self.progress:centeredWrite(1, 'Computing..') self.progress:centeredWrite(1, 'Computing..')
self.progress:sync() self.progress:sync()
@@ -211,6 +212,8 @@ function page:copy()
self.progress:clear() self.progress:clear()
rawCopy(sdrive.getMountPath(), tdrive.getMountPath()) rawCopy(sdrive.getMountPath(), tdrive.getMountPath())
cleanup() cleanup()
self.progress:clear()
self.progress:centeredWrite(1, 'Copy Complete', colors.lime, colors.black) self.progress:centeredWrite(1, 'Copy Complete', colors.lime, colors.black)
self.progress:sync() self.progress:sync()
@@ -270,4 +273,4 @@ Event.onTimeout(.2, function()
end) end)
UI:setPage(page) UI:setPage(page)
UI:pullEvents() UI:start()

View File

@@ -27,6 +27,26 @@ local page = UI.Page {
}, },
autospace = true, autospace = true,
disableHeader = true, disableHeader = true,
getDisplayValues = function(_, row)
row = Util.shallowCopy(row)
local function tovalue(s)
if type(s) == 'table' then
return 'table'
end
return s
end
for k,v in pairs(row) do
row[k] = tovalue(v)
end
return row
end,
draw = function(self)
self:adjustWidth()
UI.Grid.draw(self)
end,
}, },
accelerators = { accelerators = {
f = 'filter', f = 'filter',
@@ -36,81 +56,48 @@ local page = UI.Page {
[ 'control-q' ] = 'quit', [ 'control-q' ] = 'quit',
}, },
filtered = { }, filtered = { },
} eventHandler = function(self, event)
if event.type == 'filter' then
local entry = self.grid:getSelected()
self.filtered[entry.event] = true
function page:eventHandler(event) elseif event.type == 'toggle' then
self.paused = not self.paused
if self.paused then
self.menuBar.pauseButton.text = 'Resume'
else
self.menuBar.pauseButton.text = 'Pause '
end
self.menuBar:draw()
if event.type == 'filter' then elseif event.type == 'grid_select' then
local entry = self.grid:getSelected() multishell.openTab({
self.filtered[entry.event] = true path = 'sys/apps/Lua.lua',
args = { event.selected },
focused = true,
})
elseif event.type == 'toggle' then elseif event.type == 'reset' then
self.paused = not self.paused self.filtered = { }
if self.paused then self.grid:setValues({ })
self.menuBar.pauseButton.text = 'Resume' self.grid:draw()
else if self.paused then
self.menuBar.pauseButton.text = 'Pause '
end
self.menuBar:draw()
elseif event.type == 'grid_select' then
multishell.openTab({
path = 'sys/apps/Lua.lua',
args = { event.selected },
focused = true,
})
elseif event.type == 'reset' then
self.filtered = { }
self.grid:setValues({ })
self.grid:draw()
if self.paused then
self:emit({ type = 'toggle' })
end
elseif event.type == 'clear' then
self.grid:setValues({ })
self.grid:draw()
elseif event.type == 'quit' then
UI:exitPullEvents()
--[[
elseif event.type == 'focus_change' then
if event.focused == self.grid then
if not self.paused then
self:emit({ type = 'toggle' }) self:emit({ type = 'toggle' })
end end
elseif event.type == 'clear' then
self.grid:setValues({ })
self.grid:draw()
elseif event.type == 'quit' then
UI:quit()
else
return UI.Page.eventHandler(self, event)
end end
--]] return true
end,
else }
return UI.Page.eventHandler(self, event)
end
return true
end
function page.grid:getDisplayValues(row)
row = Util.shallowCopy(row)
local function tovalue(s)
if type(s) == 'table' then
return 'table'
end
return s
end
for k,v in pairs(row) do
row[k] = tovalue(v)
end
return row
end
function page.grid:draw()
self:adjustWidth()
UI.Grid.draw(self)
end
local updated = false local updated = false
local timerId = os.startTimer(1) local timerId = os.startTimer(1)
@@ -150,6 +137,6 @@ end
kernel.hook('*', hookFunction) kernel.hook('*', hookFunction)
UI:setPage(page) UI:setPage(page)
UI:pullEvents() UI:start()
kernel.unhook('*', hookFunction) kernel.unhook('*', hookFunction)

View File

@@ -42,7 +42,6 @@ local page = UI.Page {
}, },
range = UI.SlideOut { range = UI.SlideOut {
y = -7, height = 7, y = -7, height = 7,
backgroundColor = colors.cyan,
titleBar = UI.TitleBar { titleBar = UI.TitleBar {
event = 'cancel', event = 'cancel',
title = 'Enter range', title = 'Enter range',
@@ -239,6 +238,6 @@ Event.addRoutine(function()
end) end)
UI:setPage(page) UI:setPage(page)
UI:pullEvents() UI:start()
swarm:stop() swarm:stop()

View File

@@ -60,4 +60,4 @@ function page:eventHandler(event)
end end
UI:setPage(page) UI:setPage(page)
UI:pullEvents() UI:start()

View File

@@ -2,7 +2,6 @@ local Config = require('opus.config')
local Event = require('opus.event') local Event = require('opus.event')
local itemDB = require('core.itemDB') local itemDB = require('core.itemDB')
local Socket = require('opus.socket') local Socket = require('opus.socket')
local Terminal = require('opus.terminal')
local UI = require('opus.ui') local UI = require('opus.ui')
local Util = require('opus.util') local Util = require('opus.util')
@@ -11,10 +10,7 @@ local fs = _G.fs
local multishell = _ENV.multishell local multishell = _ENV.multishell
local network = _G.network local network = _G.network
local os = _G.os local os = _G.os
local shell = _ENV.shell
local term = _G.term
--UI.Button.defaults.focusIndicator = ' '
UI:configure('Turtles', ...) UI:configure('Turtles', ...)
local config = { } local config = { }
@@ -31,13 +27,26 @@ local options = {
local SCRIPTS_PATH = 'packages/common/etc/scripts' local SCRIPTS_PATH = 'packages/common/etc/scripts'
local nullTerm = Terminal.getNullTerm(term.current()) local socket, turtle, page
local socket
local page = UI.Page { page = UI.Page {
coords = UI.Window { coords = UI.Window {
backgroundColor = colors.black, backgroundColor = colors.black,
height = 3, height = 3,
marginTop = 1, marginLeft = 1,
draw = function(self)
local t = turtle
self:clear()
if t then
self:setCursorPos(2, 2)
local ind = 'GPS'
if not t.point.gps then
ind = 'REL'
end
self:print(string.format('%s : %d,%d,%d',
ind, t.point.x, t.point.y, t.point.z))
end
end,
}, },
tabs = UI.Tabs { tabs = UI.Tabs {
x = 1, y = 4, ey = -2, x = 1, y = 4, ey = -2,
@@ -50,6 +59,23 @@ local page = UI.Page {
disableHeader = true, disableHeader = true,
sortColumn = 'label', sortColumn = 'label',
autospace = true, autospace = true,
draw = function(self)
Util.clear(self.values)
local files = fs.list(SCRIPTS_PATH)
for _,path in pairs(files) do
table.insert(self.values, { label = path, path = fs.combine(SCRIPTS_PATH, path) })
end
self:update()
UI.ScrollingGrid.draw(self)
end,
eventHandler = function(self, event)
if event.type == 'grid_select' then
page:runScript(event.selected.label)
else
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end,
}, },
turtles = UI.ScrollingGrid { turtles = UI.ScrollingGrid {
tabTitle = 'Select', tabTitle = 'Select',
@@ -63,6 +89,41 @@ local page = UI.Page {
disableHeader = true, disableHeader = true,
sortColumn = 'label', sortColumn = 'label',
autospace = true, autospace = true,
getDisplayValues = function(_, row)
row = Util.shallowCopy(row)
if row.fuel then
row.fuel = Util.toBytes(row.fuel)
end
if row.distance then
row.distance = Util.round(row.distance, 1)
end
return row
end,
draw = function(self)
Util.clear(self.values)
for _,v in pairs(network) do
if v.fuel then
table.insert(self.values, v)
end
end
self:update()
UI.ScrollingGrid.draw(self)
end,
eventHandler = function(self, event)
if event.type == 'grid_select' then
turtle = event.selected
config.id = event.selected.id
Config.update('Turtles', config)
multishell.setTitle(multishell.getCurrent(), turtle.label)
if socket then
socket:close()
socket = nil
end
else
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end,
}, },
inventory = UI.ScrollingGrid { inventory = UI.ScrollingGrid {
backgroundColor = colors.cyan, backgroundColor = colors.cyan,
@@ -70,10 +131,58 @@ local page = UI.Page {
columns = { columns = {
{ heading = '', key = 'index', width = 2 }, { heading = '', key = 'index', width = 2 },
{ heading = '', key = 'count', width = 2 }, { heading = '', key = 'count', width = 2 },
{ heading = 'Inventory', key = 'key', width = UI.term.width - 7 }, { heading = 'Inventory', key = 'key' },
}, },
disableHeader = true, disableHeader = true,
sortColumn = 'index', sortColumn = 'index',
getRowTextColor = function(self, row, selected)
if turtle and row.selected then
return colors.yellow
end
return UI.ScrollingGrid.getRowTextColor(self, row, selected)
end,
draw = function(self)
local t = turtle
Util.clear(self.values)
if t then
for k,v in pairs(t.inv or { }) do -- new method (less data)
local index, count = k:match('(%d+),(%d+)')
v = {
index = tonumber(index),
key = v,
count = tonumber(count),
}
table.insert(self.values, v)
end
for _,v in pairs(t.inventory or { }) do
if v.count > 0 then
table.insert(self.values, v)
end
end
for _,v in pairs(self.values) do
if v.index == t.slotIndex then
v.selected = true
end
if v.key then
v.key = itemDB:getName(v.key)
end
end
end
self:adjustWidth()
self:update()
UI.ScrollingGrid.draw(self)
end,
eventHandler = function(self, event)
if event.type == 'grid_select' then
local fn = string.format('turtle.select(%d)', event.selected.index)
page:runFunction(fn)
else
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end,
}, },
--[[ --[[
policy = UI.ScrollingGrid { policy = UI.ScrollingGrid {
@@ -134,6 +243,15 @@ local page = UI.Page {
{ key = 'distance', width = 6 }, { key = 'distance', width = 6 },
{ key = 'fuel', width = 6 }, { key = 'fuel', width = 6 },
}, },
draw = function(self)
local t = turtle
if t then
self.values.status = t.status
self.values.distance = t.distance and Util.round(t.distance, 2)
self.values.fuel = Util.toBytes(t.fuel)
end
UI.StatusBar.draw(self)
end,
}, },
notification = UI.Notification(), notification = UI.Notification(),
accelerators = { accelerators = {
@@ -141,15 +259,10 @@ local page = UI.Page {
}, },
} }
function page:enable(turtle)
self.turtle = turtle
UI.Page.enable(self)
end
function page:runFunction(script, nowrap) function page:runFunction(script, nowrap)
for _ = 1, 2 do for _ = 1, 2 do
if not socket then if not socket then
socket = Socket.connect(self.turtle.id, 161) socket = Socket.connect(turtle.id, 161)
end end
if socket then if socket then
@@ -170,149 +283,52 @@ function page:runFunction(script, nowrap)
end end
function page:runScript(scriptName) function page:runScript(scriptName)
if self.turtle then if turtle then
self.notification:info('Connecting') self.notification:info('Connecting')
self:sync() self:sync()
local cmd = string.format('Script %d %s', self.turtle.id, scriptName) local script = Util.readFile(fs.combine(SCRIPTS_PATH, scriptName))
local ot = term.redirect(nullTerm) if not script then
pcall(function() shell.run(cmd) end) print('Unable to read script file')
term.redirect(ot)
self.notification:success('Sent')
end
end
function page.coords:draw()
local t = self.parent.turtle
self:clear()
if t then
self:setCursorPos(2, 2)
local ind = 'GPS'
if not t.point.gps then
ind = 'REL'
end end
self:print(string.format('%s : %d,%d,%d',
ind, t.point.x, t.point.y, t.point.z))
end
end
--[[ Inventory Tab ]]-- local function processVariables()
function page.tabs.inventory:getRowTextColor(row, selected) local variables = {
if page.turtle and row.selected then COMPUTER_ID = os.getComputerID,
return colors.yellow GPS = function()
end local pt = require('opus.gps').getPoint()
return UI.ScrollingGrid.getRowTextColor(self, row, selected) if not pt then
end error('Unable to determine location')
end
function page.tabs.inventory:draw() return _G.textutils.serialize(pt)
local t = page.turtle end,
Util.clear(self.values)
if t then
for k,v in pairs(t.inv or { }) do -- new method (less data)
local index, count = k:match('(%d+),(%d+)')
v = {
index = tonumber(index),
key = v,
count = tonumber(count),
} }
table.insert(self.values, v) for k,v in pairs(variables) do
end local token = string.format('{%s}', k)
if script:find(token, 1, true) then
for _,v in pairs(t.inventory or { }) do local s, m = pcall(v)
if v.count > 0 then if not s then
table.insert(self.values, v) self.notification:error(m)
return
end
script = script:gsub(token, m)
end
end end
return true
end end
for _,v in pairs(self.values) do if processVariables(script) then
if v.index == t.slotIndex then local socket = Socket.connect(turtle.id, 161)
v.selected = true if not socket then
self.notification:error('Unable to connect')
return
end end
if v.key then socket:write({ type = 'script', args = script })
v.key = itemDB:getName(v.key)
end
end
end
self:adjustWidth()
self:update()
UI.ScrollingGrid.draw(self)
end
function page.tabs.inventory:eventHandler(event)
if event.type == 'grid_select' then
local fn = string.format('turtle.select(%d)', event.selected.index)
page:runFunction(fn)
else
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end
function page.tabs.scripts:draw()
Util.clear(self.values)
local files = fs.list(SCRIPTS_PATH)
for _,path in pairs(files) do
table.insert(self.values, { label = path, path = fs.combine(SCRIPTS_PATH, path) })
end
self:update()
UI.ScrollingGrid.draw(self)
end
function page.tabs.scripts:eventHandler(event)
if event.type == 'grid_select' then
page:runScript(event.selected.label)
else
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end
function page.tabs.turtles:getDisplayValues(row)
row = Util.shallowCopy(row)
if row.fuel then
row.fuel = Util.toBytes(row.fuel)
end
if row.distance then
row.distance = Util.round(row.distance, 1)
end
return row
end
function page.tabs.turtles:draw()
Util.clear(self.values)
for _,v in pairs(network) do
if v.fuel then
table.insert(self.values, v)
end
end
self:update()
UI.ScrollingGrid.draw(self)
end
function page.tabs.turtles:eventHandler(event)
if event.type == 'grid_select' then
page.turtle = event.selected
config.id = event.selected.id
Config.update('Turtles', config)
multishell.setTitle(multishell.getCurrent(), page.turtle.label)
if socket then
socket:close() socket:close()
socket = nil
end
else
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end
function page.statusBar:draw() self.notification:success('Sent')
local t = self.parent.turtle end
if t then
self.values.status = t.status
self.values.distance = t.distance and Util.round(t.distance, 2)
self.values.fuel = Util.toBytes(t.fuel)
end end
UI.StatusBar.draw(self)
end end
function page:showBlocks() function page:showBlocks()
@@ -335,7 +351,7 @@ end
function page:eventHandler(event) function page:eventHandler(event)
if event.type == 'quit' then if event.type == 'quit' then
UI:exitPullEvents() UI:quit()
elseif event.type == 'tab_select' then elseif event.type == 'tab_select' then
config.tab = event.button.text config.tab = event.button.text
@@ -354,19 +370,14 @@ function page:eventHandler(event)
return true return true
end end
function page:enable()
UI.Page.enable(self)
-- self.tabs:activateTab(page.tabs.turtles)
end
if not Util.getOptions(options, { ... }, true) then if not Util.getOptions(options, { ... }, true) then
return return
end end
if options.turtle.value >= 0 then if options.turtle.value >= 0 then
for _ = 1, 10 do for _ = 1, 10 do
page.turtle = _G.network[options.turtle.value] turtle = _G.network[options.turtle.value]
if page.turtle then if turtle then
break break
end end
os.sleep(1) os.sleep(1)
@@ -374,9 +385,9 @@ if options.turtle.value >= 0 then
end end
Event.onInterval(1, function() Event.onInterval(1, function()
if page.turtle then if turtle then
local t = _G.network[page.turtle.id] --local t = _G.network[turtle.id]
page.turtle = t --turtle = t
page:draw() page:draw()
page:sync() page:sync()
end end
@@ -387,5 +398,4 @@ if config.tab then
end end
UI:setPage(page) UI:setPage(page)
UI:start()
UI:pullEvents()

File diff suppressed because it is too large Load Diff

View File

@@ -57,7 +57,7 @@
category = "Apps", category = "Apps",
requires = "advancedComputer", requires = "advancedComputer",
iconExt = "\030 \031 \128\030d\159\030 \031d\140\030d\031 \155\030 \0315\140\0305\031 \155\030 \128\010\030 \031d\136\145\0315\136\145\031d\153\031 \128\0315\153\010\030 \031 \128\031d\130\140\134\0315\140\134\031 \128", iconExt = "\030 \031 \128\030d\159\030 \031d\140\030d\031 \155\030 \0315\140\0305\031 \155\030 \128\010\030 \031d\136\145\0315\136\145\031d\153\031 \128\0315\153\010\030 \031 \128\031d\130\140\134\0315\140\134\031 \128",
run = "packages/common/hexedit.lua", run = "fileui --exec=hexedit.lua",
}, },
[ "fb1c39e9f4f3c2628ad173ab401a6e4e4baf783d" ] = { [ "fb1c39e9f4f3c2628ad173ab401a6e4e4baf783d" ] = {
title = "Sounds", title = "Sounds",
@@ -65,4 +65,17 @@
run = "SoundPlayer", run = "SoundPlayer",
iconExt = "\030 \031 \128\0307\159\129\030 \0317\149\0310\144\0300\031 \155\030 \0310\137\144\010\0307\0317\128\128\128\030 \149\0300\031 \149\030 \128\0310\149\0300\031 \149\010\030 \031 \128\0317\130\0307\031 \144\030 \0317\149\0310\129\134\152\129", iconExt = "\030 \031 \128\0307\159\129\030 \0317\149\0310\144\0300\031 \155\030 \0310\137\144\010\0307\0317\128\128\128\030 \149\0300\031 \149\030 \128\0310\149\0300\031 \149\010\030 \031 \128\0317\130\0307\031 \144\030 \0317\149\0310\129\134\152\129",
}, },
[ "464c4ffd019e1e9691dcf0537c797353ef2b1c1d4833d3d463e5b74ae4547344" ] = {
title = "Editor",
category = "Apps",
run = "edit",
iconExt = "7\
¨¨¨¨f€0¨\
¨¨f€0¨¨f€",
},
[ "3f00927a719345edd4a8316599d3b328857987547f8884306861161ffa09647e" ] = {
title = "Write",
category = "Apps",
run = "write",
},
} }

View File

@@ -1,5 +1,5 @@
_G.requireInjector(_ENV) _G.requireInjector(_ENV)
local config = require('config').load('gps') local config = require('opus.config').load('gps')
if config.home then if config.home then
if turtle.enableGPS() then if turtle.enableGPS() then
return turtle.pathfind(config.home) return turtle.pathfind(config.home)

View File

@@ -1,29 +0,0 @@
turtle.run(function()
_G.requireInjector(_ENV)
local GPS = require('gps')
local Socket = require('socket')
local id = {COMPUTER_ID}
if not turtle.enableGPS() then
error('turtle: No GPS found')
end
local socket = Socket.connect(id, 161)
if not socket then
error('turtle: Unable to connect to ' .. id)
end
socket:write({ type = 'gps' })
local pt = socket:read(3)
if not pt then
error('turtle: No GPS response')
end
if not turtle.pathfind(pt) then
error('Unable to go to location')
end
end)

View File

@@ -0,0 +1,17 @@
local turtle = _G.turtle
turtle.run(function()
_G.requireInjector(_ENV)
local GPS = require('opus.gps')
if not turtle.enableGPS() then
error('turtle: No GPS found')
end
local pt = {GPS}
if not turtle.pathfind(pt) then
error('Unable to go to location')
end
end)

View File

@@ -1,5 +1,5 @@
_G.requireInjector(_ENV) _G.requireInjector(_ENV)
local Config = require('config') local Config = require('opus.config')
local pt = turtle.enableGPS() local pt = turtle.enableGPS()
if pt then if pt then
local config = Config.load('gps', { }) local config = Config.load('gps', { })

View File

@@ -2,9 +2,9 @@ local function summon(id)
_G.requireInjector(_ENV) _G.requireInjector(_ENV)
local GPS = require('gps') local GPS = require('opus.gps')
local Point = require('point') local Point = require('opus.point')
local Socket = require('socket') local Socket = require('opus.socket')
turtle.setStatus('GPSing') turtle.setStatus('GPSing')
turtle.setPoint({ x = 0, y = 0, z = 0, heading = 0 }) turtle.setPoint({ x = 0, y = 0, z = 0, heading = 0 })

View File

@@ -19,10 +19,14 @@ local Util = require('opus.util')
local multishell = _ENV.multishell local multishell = _ENV.multishell
local os = _G.os local os = _G.os
local recTerm, oldTerm, arg, showInput, skipLast, lastDelay, curInput = {}, Util.shallowCopy(multishell.term), {...}, false, false, 2, "" local colours = _G.colors
local args, options = Util.parse(...)
local oldTerm, showInput, skipLast, lastDelay, curInput = Util.shallowCopy(multishell.term), false, false, 2, ""
local curBlink, oldBlink, tTerm, buffer, colourNum, xPos, yPos, oldXPos, oldYPos, tCol, bCol, xSize, ySize = false, false, {}, {}, {}, 1, 1, 1, 1, colours.white, colours.black, oldTerm.getSize() local curBlink, oldBlink, tTerm, buffer, colourNum, xPos, yPos, oldXPos, oldYPos, tCol, bCol, xSize, ySize = false, false, {}, {}, {}, 1, 1, 1, 1, colours.white, colours.black, oldTerm.getSize()
local greys, buttons = {["0"] = true, ["7"] = true, ["8"] = true, ["f"] = true}, {"l", "r", "m"} local greys, buttons = {["0"] = true, ["7"] = true, ["8"] = true, ["f"] = true}, {"l", "r", "m"}
local charW, charH, chars, resp local charW, charH, chars
local calls = { } local calls = { }
local curCalls = { delay = 0 } local curCalls = { delay = 0 }
@@ -32,38 +36,44 @@ local callCount = 0
local function showSyntax() local function showSyntax()
print('Gif Recorder by Bomb Bloke\n') print('Gif Recorder by Bomb Bloke\n')
print('Syntax: recGif [-i] [-s] [-ld:<delay>] filename') print('Syntax: recGif [-i] [-s] [-ld:<delay>] filename')
print(' -i : show input') print(' --showInput : show input')
print(' -s : skip last') print(' --skipLast : skip last')
print(' -ld : last delay') print(' --lastDelay : last delay')
print(' --noResize : dont resize')
end end
for i = #arg, 1, -1 do if options.showInput then
local curArg = arg[i]:lower() showInput, ySize = true, ySize + 1
if curArg == "-i" then
showInput, ySize = true, ySize + 1
table.remove(arg, i)
elseif curArg == "-s" then
skipLast = true
table.remove(arg, i)
elseif curArg:sub(1, 4) == "-ld:" then
curArg = tonumber(curArg:sub(5))
if curArg then lastDelay = curArg end
table.remove(arg, i)
elseif curArg == '-?' then
showSyntax()
return
elseif i ~= #arg then
showSyntax()
printError('\nInvalid argument')
return
end
end end
print('Gif Recorder by Bomb Bloke\n') if options.skipLast then
print('Press control-p to stop recording') skipLast = true
end
local filename = arg[#arg] if options.lastDelay then
lastDelay = options.lastDelay
end
if options.help then
showSyntax()
return
end
if options.daemon then
device.keyboard.addHotkey('control-P', function()
multishell.openTab({
path = 'sys/apps/shell.lua',
args = { arg[0], '--noResize', '--rawOutput', 'recorder.gif' },
})
end)
return
end
print('Gif Recorder by Bomb Bloke')
print(version)
print('\nPress control-p to stop recording')
local filename = args[1]
if not filename then if not filename then
print('Enter file name:') print('Enter file name:')
filename = read() filename = read()
@@ -131,37 +141,34 @@ end
-- Build a terminal that records stuff: -- Build a terminal that records stuff:
recTerm = multishell.term local recTerm = multishell.term
for key, func in pairs(oldTerm) do for key, func in pairs(oldTerm) do
recTerm[key] = function(...) if type(func) == 'function' then
local result = { func(...) } recTerm[key] = function(...)
local result = { func(...) }
if callCount == 0 then if callCount == 0 then
os.queueEvent('capture_frame') os.queueEvent('capture_frame')
end
callCount = callCount + 1
curCalls[callCount] = { key, ... }
return unpack(result)
end end
callCount = callCount + 1
curCalls[callCount] = { key, ... }
return unpack(result)
end end
end end
local tabId = multishell.getCurrent() local tabId = multishell.getCurrent()
multishell.hideTab(tabId)
if not options.noResize then
os.queueEvent('term_resize')
end
_G.device.keyboard.addHotkey('control-p', function() _G.device.keyboard.addHotkey('control-p', function()
os.queueEvent('recorder_stop') os.queueEvent('recorder_stop')
end) end)
local tabs = multishell.getTabs()
for _,tab in pairs(tabs) do
if tab.isOverview then
multishell.hideTab(tabId)
multishell.setFocus(tab.tabId)
os.queueEvent('term_resize')
break
end
end
local curTime = os.clock() - 1 local curTime = os.clock() - 1
while true do while true do
@@ -200,8 +207,12 @@ if skipLast and #calls > 1 then calls[#calls] = nil end
calls[#calls].delay = lastDelay calls[#calls].delay = lastDelay
if options.rawOutput then
Util.writeTable('tmp/raw.txt', calls)
return
end
print(string.format("Encoding %d frames...", #calls)) print(string.format("Encoding %d frames...", #calls))
--Util.writeTable('tmp/raw.txt', calls)
-- Perform a quick re-parse of the recorded data (adding frames for when the cursor blinks): -- Perform a quick re-parse of the recorded data (adding frames for when the cursor blinks):

View File

@@ -1,6 +0,0 @@
{
title = 'Example programs for coding in Opus',
repository = 'kepler155c/opus-apps/{{OPUS_BRANCH}}/examples',
description = [[Starter/example programs for creating Opus programs.]],
license = 'MIT',
}

View File

@@ -1,44 +0,0 @@
local UI = require('opus.ui')
local page = UI.Page {
menuBar = UI.MenuBar {
buttons = {
{ text = 'Shuffle', event = 'shuffle' },
{ text = 'Clear', event = 'clear', },
}
},
grid = UI.ScrollingGrid {
y = 2, ey = -2,
values = {
{ col = 'column1', value = 'value1' },
{ col = 'column2', value = 'value2' },
{ col = 'column3', value = 'value3' },
},
columns = {
{ heading = 'HDR1', key = 'col' },
{ heading = 'HDR2', key = 'value' },
}
},
statusBar = UI.StatusBar { },
}
function page:eventHandler(event)
if event.type == 'grid_select' then
self.statusBar:setStatus('Selected: ' .. event.selected.value)
elseif event.type == 'shuffle' then
for _,v in pairs(self.grid.values) do
v.col = 'column' .. math.random(1,3)
end
self.grid:update()
self.grid:draw()
elseif event.type == 'clear' then
self.grid:setValues({ })
self.grid:draw()
end
return UI.Page.eventHandler(self, event)
end
UI:setPage(page)
UI:pullEvents()

View File

@@ -313,4 +313,4 @@ else
end end
UI:setPage(page) UI:setPage(page)
UI:pullEvents() UI:start()

View File

@@ -250,5 +250,3 @@ turtle.setStatus('Jamming')
UI:pullEvents() UI:pullEvents()
turtle.setStatus('idle') turtle.setStatus('idle')
page:play(false) page:play(false)
UI.term:reset()

174
ignore/passthrough.lua Normal file
View File

@@ -0,0 +1,174 @@
local _rep = string.rep
local _sub = string.sub
local colors = _G.colors
local palette = { }
for n = 1, 16 do
palette[2 ^ (n - 1)] = _sub("0123456789abcdef", n, n)
end
local swindow = { }
function swindow.createPassthrough(parent, wx, wy, width, height)
local window = { }
local cx, cy = 1, 1
local blink = false
local fg = colors.white
local bg = colors.black
local function crop(text, x)
local w = #text
if x < 1 then
text = _sub(text, 2 - x)
w = w + x - 1
x = 1
end
if x + w - 1 > width then
text = _sub(text, 1, width - x + 1)
end
return text
end
local function blit(text, fg, bg)
parent.setCursorPos(cx + wx - 1, cy + wy - 1)
parent.blit(text, fg, bg)
cx = cx + #text
end
function window.write(text)
if cy > 0 and cy <= height then
text = crop(tostring(text), cx)
if #text > 0 then
--parent.setCursorPos(cx + wx - 1, cy + wy - 1)
blit(text, _rep(palette[fg], #text), _rep(palette[bg], #text))
end
end
end
function window.blit(text, fg, bg)
if cy > 0 and cy <= height then
text = crop(tostring(text), cx)
if #text > 0 then
blit(text, crop(tostring(fg), cx), crop(tostring(bg), cx))
end
end
end
function window.clear()
local filler = _rep(' ', width)
for i = 1, height do
parent.setCursorPos(wx, i + wy - 1)
parent.write(filler)
end
end
function window.clearLine()
if cy > 0 and cy <= height then
local filler = _rep(' ', width)
parent.setCursorPos(cx + wx - 1, cy + wy - 1)
parent.write(filler)
end
end
function window.getCursorPos()
return cx, cy
end
function window.setCursorPos(x, y)
cx = math.floor(x)
cy = math.floor(y)
parent.setCursorPos(cx + wx - 1, cy + wy - 1)
end
function window.setCursorBlink(b)
blink = b
parent.setCursorBlink(b)
end
function window.getCursorBlink()
return blink
end
window.isColor = parent.isColor
window.isColour = parent.isColour
window.setPaletteColour = parent.setPaletteColour
window.setPaletteColor = parent.setPaletteColor
window.getPaletteColour = parent.getPaletteColour
window.getPaletteColor = parent.getPaletteColour
window.setBackgroundColor = parent.setBackgroundColor
window.setBackgroundColour = parent.setBackgroundColor
window.getBackgroundColor = parent.getBackgroundColor
window.getBackgroundColour = parent.getBackgroundColor
window.setVisible = parent.setVisible
window.redraw = function() end --parent.redraw
function window.getTextColor()
return fg
end
window.getTextColour = window.getTextColor
function window.setTextColor(textColor)
fg = textColor
parent.setTextColor(fg)
end
window.setTextColour = window.setTextColor
function window.restoreCursor()
parent.setCursorPos(cx + wx - 1, cy + wy - 1)
parent.setTextColor(fg)
parent.setCursorBlink(blink)
end
function window.getSize()
return width, height
end
function window.scroll( n )
if n ~= 0 then
local lines = { }
for i = 1, height do
lines[i] = { parent.getLine(wy + i - 1) }
end
for newY = 1, height do
local y = newY + n
parent.setCursorPos(wx, wy + newY - 1)
if y >= 1 and y <= height then
parent.blit(table.unpack(lines[y]))
else
parent.blit(
_rep(' ', width),
_rep(palette[fg], width),
_rep(palette[bg], width))
end
end
parent.setCursorPos(cx + wx - 1, cy + wy - 1)
end
end
function window.getLine(y)
local t, tc, bc = parent.getLine(y + cy - 1)
return t:sub(1, width), tc:sub(1, width), bc:sub(1, width)
end
function window.getPosition()
return wx, wy
end
function window.reposition(nNewX, nNewY, nNewWidth, nNewHeight, newParent)
wx = nNewX
wy = nNewY
width = nNewWidth
height = nNewHeight
window.restoreCursor()
end
return window
end
return swindow

View File

@@ -4,42 +4,21 @@ local Util = require('opus.util')
local colors = _G.colors local colors = _G.colors
local os = _G.os local os = _G.os
local peripheral = _G.peripheral
local printError = _G.printError local printError = _G.printError
local shell = _ENV.shell
local term = _G.term local term = _G.term
local window = _G.window local window = _G.window
local function syntax()
printError('Syntax:')
error('mwm [--config=filename] [monitor]')
end
local args = Util.parse(...)
local UID = 0 local UID = 0
local multishell = { } local multishell = { }
local processes = { } local processes = { }
local parentTerm = term.current() local parentTerm = term.current()
local sessionFile = args.config or 'usr/config/mwm' local sessionFile = 'usr/config/twm'
local monName = args[1]
local running local running
local parentMon local parentMon = term.current()
local defaultEnv = Util.shallowCopy(_ENV) local defaultEnv = Util.shallowCopy(_ENV)
defaultEnv.multishell = multishell defaultEnv.multishell = multishell
if monName == 'terminal' then
parentMon = term.current()
elseif monName then
parentMon = peripheral.wrap(monName) or syntax()
else
parentMon = peripheral.find('monitor') or syntax()
end
if parentMon.setTextScale then
parentMon.setTextScale(.5)
end
local monDim, termDim = { }, { } local monDim, termDim = { }, { }
monDim.width, monDim.height = parentMon.getSize() monDim.width, monDim.height = parentMon.getSize()
termDim.width, termDim.height = parentTerm.getSize() termDim.width, termDim.height = parentTerm.getSize()
@@ -73,13 +52,10 @@ local function write(win, x, y, text)
end end
local function redraw() local function redraw()
--monitor.clear()
monitor.canvas:dirty() monitor.canvas:dirty()
--monitor.setBackgroundColor(colors.gray)
monitor.canvas:clear(colors.gray) monitor.canvas:clear(colors.gray)
for k, process in ipairs(processes) do for _, process in ipairs(processes) do
process.container.canvas:dirty() process.container.canvas:dirty()
process:focus(k == #processes)
end end
end end
@@ -112,7 +88,8 @@ function Process:new(args)
height = args.height + 1, height = args.height + 1,
path = args.path, path = args.path,
args = args.args or { }, args = args.args or { },
title = args.title or 'shell', title = args.title or 'shell',
timestamp = os.clock(),
isMoving = false, isMoving = false,
isResizing = false, isResizing = false,
}, { __index = Process }) }, { __index = Process })
@@ -155,20 +132,12 @@ function Process:new(args)
end end
function Process:focus(focused) function Process:focus(focused)
if focused then self.container.setBackgroundColor(focused and colors.yellow or colors.lightGray)
self.container.setBackgroundColor(colors.yellow)
else
self.container.setBackgroundColor(colors.lightGray)
end
self.container.setTextColor(colors.black) self.container.setTextColor(colors.black)
write(self.container, 1, 1, string.rep(' ', self.width)) write(self.container, 1, 1, string.rep(' ', self.width))
write(self.container, 2, 1, self.title) write(self.container, 2, 1, self.title)
write(self.container, self.width - 1, 1, '*') write(self.container, self.width - 1, 1, '*')
write(self.container, self.width - 3, 1, '\029') write(self.container, self.width - 3, 1, '\029')
if focused then
self.window.restoreCursor()
end
end end
function Process:drawSizers() function Process:drawSizers()
@@ -188,17 +157,18 @@ function Process:adjustDimensions()
self.y = math.min(self.y, monDim.height - self.height + 1) self.y = math.min(self.y, monDim.height - self.height + 1)
end end
function Process:reposition() function Process:reposition(resizing)
self:adjustDimensions() self:adjustDimensions()
self.container.reposition(self.x, self.y, self.width, self.height) self.container.reposition(self.x, self.y, self.width, self.height)
self.container.setBackgroundColor(colors.black)
self.container.clear()
self.window.reposition(1, 2, self.width, self.height - 1) self.window.reposition(1, 2, self.width, self.height - 1)
if self.window ~= self.terminal then if self.window ~= self.terminal then
if self.terminal.reposition then -- ?? if self.terminal.reposition then -- ??
self.terminal.reposition(1, 1, self.width, self.height - 1) self.terminal.reposition(1, 1, self.width, self.height - 1)
end end
end end
if resizing then
self:focus(self == processes[#processes])
end
redraw() redraw()
end end
@@ -225,7 +195,7 @@ function Process:resize(x, y)
self.height = y - self.isResizing.y + self.isResizing.h self.height = y - self.isResizing.y + self.isResizing.h
self.width = x - self.isResizing.x + self.isResizing.w self.width = x - self.isResizing.x + self.isResizing.w
self:reposition() self:reposition(true)
self:resume('term_resize') self:resume('term_resize')
self:drawSizers() self:drawSizers()
multishell.saveSession(sessionFile) multishell.saveSession(sessionFile)
@@ -278,7 +248,8 @@ function multishell.setFocus(uid)
process.container.canvas:raise() process.container.canvas:raise()
process:focus(true) process:focus(true)
process.container.canvas:dirty() process.container.canvas:dirty()
process.window.restoreCursor()
end end
return true return true
end end
@@ -423,14 +394,15 @@ function multishell.start()
elseif focused.isMoving then elseif focused.isMoving then
focused.x = event[3] - focused.isMoving.x + focused.isMoving.ox focused.x = event[3] - focused.isMoving.x + focused.isMoving.ox
focused.y = event[4] - focused.isMoving.y + focused.isMoving.oy focused.y = event[4] - focused.isMoving.y + focused.isMoving.oy
focused:reposition() focused:reposition(false)
end end
end end
elseif event[1] == 'char' or elseif event[1] == 'char' or
event[1] == 'key' or event[1] == 'key' or
event[1] == 'key_up' or event[1] == 'key_up' or
event[1] == 'paste' then event[1] == 'paste' or
event[1] == 'mouse_scroll' then
local focused = processes[#processes] local focused = processes[#processes]
if focused then if focused then

View File

@@ -16,16 +16,19 @@ local config = Config.load('lzwfs', {
local tab = UI.Tab { local tab = UI.Tab {
tabTitle = 'Compression', tabTitle = 'Compression',
description = 'Disk compression', description = 'Disk compression',
[1] = UI.Window {
x = 2, y = 2, ex = -2, ey = 6,
},
label1 = UI.Text { label1 = UI.Text {
x = 2, y = 2, x = 3, y = 3,
value = 'Enable compression', value = 'Enable compression',
}, },
checkbox = UI.Checkbox { checkbox = UI.Checkbox {
x = 20, y = 2, x = 21, y = 3,
value = config.enabled value = config.enabled
}, },
entry = UI.TextEntry { entry = UI.TextEntry {
x = 2, y = 4, ex = -2, x = 3, y = 5 , ex = -3,
limit = 256, limit = 256,
shadowText = 'enter new path', shadowText = 'enter new path',
accelerators = { accelerators = {
@@ -34,7 +37,7 @@ local tab = UI.Tab {
help = 'add a new path', help = 'add a new path',
}, },
grid = UI.Grid { grid = UI.Grid {
x = 2, ex = -2, y = 6, ey = -5, x = 2, ex = -2, y = 8, ey = -5,
disableHeader = true, disableHeader = true,
columns = { { key = 'value' } }, columns = { { key = 'value' } },
autospace = true, autospace = true,
@@ -45,7 +48,7 @@ local tab = UI.Tab {
}, },
}, },
button = UI.Button { button = UI.Button {
x = -9, ex = -2, y = -3, x = -8, ex = -2, y = -3,
text = 'Apply', text = 'Apply',
event = 'apply', event = 'apply',
}, },

View File

@@ -216,7 +216,7 @@ _G._syslog = function(...)
end end
local s, m = pcall(function() local s, m = pcall(function()
UI:pullEvents() UI:start()
end) end)
turtle.setStatus('idle') turtle.setStatus('idle')

View File

@@ -1,6 +1,6 @@
local Config = require('opus.config') local Config = require('opus.config')
local Event = require('opus.event') local Event = require('opus.event')
local fuzzy = require('milo.fuzzyMatch') local fuzzy = require('opus.fuzzy')
local Sound = require('opus.sound') local Sound = require('opus.sound')
local Socket = require('opus.socket') local Socket = require('opus.socket')
local sync = require('opus.sync').sync local sync = require('opus.sync').sync
@@ -63,8 +63,8 @@ local page = UI.Page {
x = 1, ex = -13, x = 1, ex = -13,
limit = 50, limit = 50,
shadowText = 'filter', shadowText = 'filter',
backgroundColor = colors.cyan, backgroundColor = 'primary',
backgroundFocusColor = colors.cyan, backgroundFocusColor = 'primary',
accelerators = { accelerators = {
[ 'enter' ] = 'eject', [ 'enter' ] = 'eject',
[ 'up' ] = 'grid_up', [ 'up' ] = 'grid_up',
@@ -169,7 +169,7 @@ end
function page:eventHandler(event) function page:eventHandler(event)
if event.type == 'quit' then if event.type == 'quit' then
UI:exitPullEvents() UI:quit()
elseif event.type == 'setup' then elseif event.type == 'setup' then
self.setup.form:setValues(context.state) self.setup.form:setValues(context.state)
@@ -517,14 +517,14 @@ local function loadDirectory(dir)
}) })
end end
end end
page.menuBar.config:add({ dropmenu = UI.DropMenu { buttons = dropdown } }) page.menuBar.config.dropdown = dropdown
end end
local programDir = fs.getDir(shell.getRunningProgram()) local programDir = fs.getDir(shell.getRunningProgram())
loadDirectory(fs.combine(programDir, 'plugins/remote')) loadDirectory(fs.combine(programDir, 'plugins/remote'))
UI:setPage(page) UI:setPage(page)
UI:pullEvents() UI:start()
if context.socket then if context.socket then
context.socket:close() context.socket:close()

View File

@@ -1,19 +0,0 @@
-- Based on Squid's fuzzy search
-- https://github.com/SquidDev-CC/artist/blob/vnext/artist/lib/match.lua
--
-- not very fuzzy anymore
local SCORE_WEIGHT = 1000
local LEADING_LETTER_PENALTY = -3
local LEADING_LETTER_PENALTY_MAX = -9
local _find = string.find
local _max = math.max
return function(str, pattern)
local start = _find(str, pattern, 1, true)
if start then
-- All letters before the current one are considered leading, so add them to our penalty
return SCORE_WEIGHT + _max(LEADING_LETTER_PENALTY * (start - 1), LEADING_LETTER_PENALTY_MAX)
end
end

View File

@@ -1,53 +0,0 @@
local class = require('opus.class')
local itemDB = require('core.itemDB')
local Mini = require('milo.miniAdapter')
local os = _G.os
local Adapter = class(Mini)
function Adapter:init(args)
Mini.init(self, args)
self._rawList = self.list
function self.list()
-- wait for up to 1 sec until any items that have been inserted
-- into interface are added to the system
for _ = 0, 20 do
if #self._rawList() == 0 then
break
end
os.sleep(0)
end
local list = { }
for _, v in pairs(self.listAvailableItems()) do
list[itemDB:makeKey(v)] = v
end
return list
end
function self.getItemMeta(key)
local item = self.findItem(itemDB:splitKey(key))
if item and item.getMetadata then
return item.getMetadata()
end
end
function self.pushItems(target, key, amount, slot)
local item = self.findItem(itemDB:splitKey(key))
if item and item.export then
return item.export(target, amount, slot)
end
return 0
end
function self.pullItems(target, key, amount, slot)
_G._syslog({target, key, amount, slot })
return 0
end
end
return Adapter

View File

@@ -1,6 +1,6 @@
local Craft = require('milo.craft2') local Craft = require('milo.craft2')
local Event = require('opus.event') local Event = require('opus.event')
local fuzzy = require('milo.fuzzyMatch') local fuzzy = require('opus.fuzzy')
local Milo = require('milo') local Milo = require('milo')
local Sound = require('opus.sound') local Sound = require('opus.sound')
local UI = require('opus.ui') local UI = require('opus.ui')
@@ -54,8 +54,8 @@ local page = UI.Page {
limit = 50, limit = 50,
shadowText = 'filter', shadowText = 'filter',
shadowTextColor = colors.gray, shadowTextColor = colors.gray,
backgroundColor = colors.cyan, backgroundColor = 'primary',
backgroundFocusColor = colors.cyan, backgroundFocusColor = 'primary',
accelerators = { accelerators = {
[ 'enter' ] = 'eject', [ 'enter' ] = 'eject',
[ 'up' ] = 'grid_up', [ 'up' ] = 'grid_up',
@@ -66,7 +66,7 @@ local page = UI.Page {
storageStatus = UI.Text { storageStatus = UI.Text {
x = -17, ex = -10, x = -17, ex = -10,
textColor = colors.lime, textColor = colors.lime,
backgroundColor = colors.cyan, backgroundColor = 'primary',
value = '', value = '',
}, },
amount = UI.TextEntry { amount = UI.TextEntry {
@@ -208,7 +208,7 @@ end
function page:eventHandler(event) function page:eventHandler(event)
if event.type == 'quit' then if event.type == 'quit' then
UI:exitPullEvents() UI:quit()
elseif event.type == 'eject' or event.type == 'grid_select' then elseif event.type == 'eject' or event.type == 'grid_select' then
self:eject(1) self:eject(1)

View File

@@ -7,7 +7,6 @@ local Util = require('opus.util')
local colors = _G.colors local colors = _G.colors
local device = _G.device local device = _G.device
local turtle = _G.turtle
local context = Milo:getContext() local context = Milo:getContext()
@@ -22,8 +21,8 @@ local networkPage = UI.Page {
y = -2, x = 1, ex = -9, y = -2, x = 1, ex = -9,
limit = 50, limit = 50,
shadowText = 'filter', shadowText = 'filter',
backgroundColor = colors.cyan, backgroundColor = 'primary',
backgroundFocusColor = colors.cyan, backgroundFocusColor = 'primary',
}, },
grid = UI.ScrollingGrid { grid = UI.ScrollingGrid {
y = 2, ey = -3, y = 2, ey = -3,
@@ -195,7 +194,6 @@ nodeWizard = UI.Page {
pages = { pages = {
general = UI.WizardPage { general = UI.WizardPage {
index = 1, index = 1,
backgroundColor = colors.cyan,
form = UI.Form { form = UI.Form {
x = 2, ex = -2, y = 1, ey = 3, x = 2, ex = -2, y = 1, ey = 3,
manualControls = true, manualControls = true,
@@ -236,11 +234,11 @@ The settings will take effect immediately!]],
}, },
}, },
statusBar = UI.StatusBar { statusBar = UI.StatusBar {
backgroundColor = colors.cyan, backgroundColor = 'primary',
}, },
notification = UI.Notification { }, notification = UI.Notification { },
filter = UI.SlideOut { filter = UI.SlideOut {
backgroundColor = colors.cyan, noFill = true,
menuBar = UI.MenuBar { menuBar = UI.MenuBar {
buttons = { buttons = {
{ text = 'Save', event = 'save' }, { text = 'Save', event = 'save' },
@@ -248,7 +246,8 @@ The settings will take effect immediately!]],
}, },
}, },
grid = UI.ScrollingGrid { grid = UI.ScrollingGrid {
x = 2, ex = -6, y = 2, ey = -6, x = 2, ex = -6, y = 3, ey = -7,
disableHeader = true,
columns = { columns = {
{ heading = 'Name', key = 'displayName' }, { heading = 'Name', key = 'displayName' },
}, },
@@ -262,7 +261,7 @@ The settings will take effect immediately!]],
text = '-', event = 'remove_entry', help = 'Remove', text = '-', event = 'remove_entry', help = 'Remove',
}, },
form = UI.Form { form = UI.Form {
x = 2, y = -4, height = 3, x = 2, y = -5, height = 3,
margin = 1, margin = 1,
manualControls = true, manualControls = true,
[1] = UI.Checkbox { [1] = UI.Checkbox {
@@ -290,7 +289,7 @@ The settings will take effect immediately!]],
}, },
}, },
statusBar = UI.StatusBar { statusBar = UI.StatusBar {
backgroundColor = colors.cyan, backgroundColor = 'primary',
}, },
}, },
} }

View File

@@ -17,7 +17,6 @@ Right-clicking on the activity monitor will reset the totals.]]
local wizardPage = UI.WizardPage { local wizardPage = UI.WizardPage {
title = 'Activity Monitor', title = 'Activity Monitor',
index = 2, index = 2,
backgroundColor = colors.cyan,
[1] = UI.TextArea { [1] = UI.TextArea {
x = 2, ex = -2, y = 2, ey = 6, x = 2, ex = -2, y = 2, ey = 6,
marginRight = 0, marginRight = 0,

View File

@@ -3,7 +3,6 @@ local Event = require('opus.event')
local Milo = require('milo') local Milo = require('milo')
local UI = require('opus.ui') local UI = require('opus.ui')
local colors = _G.colors
local device = _G.device local device = _G.device
local fs = _G.fs local fs = _G.fs
local os = _G.os local os = _G.os
@@ -23,7 +22,6 @@ Backup configuration files each minecraft day.
local wizardPage = UI.WizardPage { local wizardPage = UI.WizardPage {
title = 'Backup Drive', title = 'Backup Drive',
index = 2, index = 2,
backgroundColor = colors.cyan,
[1] = UI.TextArea { [1] = UI.TextArea {
x = 2, ex = -2, y = 2, ey = -2, x = 2, ex = -2, y = 2, ey = -2,
value = string.format(template, Ansi.yellow, Ansi.reset), value = string.format(template, Ansi.yellow, Ansi.reset),

View File

@@ -18,7 +18,6 @@ Note that you do not need to import items from the brewing stand or export blaze
local wizardPage = UI.WizardPage { local wizardPage = UI.WizardPage {
title = 'Brewing Stand', title = 'Brewing Stand',
index = 2, index = 2,
backgroundColor = colors.cyan,
[1] = UI.TextArea { [1] = UI.TextArea {
x = 2, ex = -2, y = 2, ey = -2, x = 2, ex = -2, y = 2, ey = -2,
value = string.format(template, Ansi.yellow, Ansi.reset), value = string.format(template, Ansi.yellow, Ansi.reset),

View File

@@ -4,12 +4,10 @@ local itemDB = require('core.itemDB')
local colors = _G.colors local colors = _G.colors
local device = _G.device local device = _G.device
local context = Milo:getContext()
local wizardPage = UI.WizardPage { local wizardPage = UI.WizardPage {
title = 'Level Emitter', title = 'Level Emitter',
index = 2, index = 2,
backgroundColor = colors.cyan,
[1] = UI.TextArea { [1] = UI.TextArea {
x = 2, y = 1, x = 2, y = 1,
height = 2, height = 2,

View File

@@ -1,7 +1,6 @@
local Ansi = require('opus.ansi') local Ansi = require('opus.ansi')
local UI = require('opus.ui') local UI = require('opus.ui')
local colors = _G.colors
local device = _G.device local device = _G.device
--[[ Configuration Screen ]] --[[ Configuration Screen ]]
@@ -14,7 +13,6 @@ Any items placed in this chest will be imported into storage.
local inputChestWizardPage = UI.WizardPage { local inputChestWizardPage = UI.WizardPage {
title = 'Input Chest', title = 'Input Chest',
index = 2, index = 2,
backgroundColor = colors.cyan,
[1] = UI.TextArea { [1] = UI.TextArea {
x = 2, ex = -2, y = 2, ey = -2, x = 2, ex = -2, y = 2, ey = -2,
value = string.format(template, Ansi.yellow, Ansi.reset), value = string.format(template, Ansi.yellow, Ansi.reset),

View File

@@ -41,7 +41,6 @@ function page:eventHandler(event)
elseif event.type == 'focus_change' then elseif event.type == 'focus_change' then
self.statusBar:setStatus(event.focused.help) self.statusBar:setStatus(event.focused.help)
self.statusBar:draw()
elseif event.type == 'success_message' then elseif event.type == 'success_message' then
self.notification:success(event.message) self.notification:success(event.message)

View File

@@ -1,14 +1,11 @@
local Ansi = require('opus.ansi') local Ansi = require('opus.ansi')
local UI = require('opus.ui') local UI = require('opus.ui')
local colors = _G.colors
local infoTab = UI.Tab { local infoTab = UI.Tab {
tabTitle = 'Info', tabTitle = 'Info',
index = 4, index = 4,
backgroundColor = colors.cyan,
textArea = UI.TextArea { textArea = UI.TextArea {
x = 2, ex = -2, y = 2, x = 2, ex = -2, y = 2, ey = -2,
}, },
} }

View File

@@ -9,7 +9,6 @@ local context = Milo:getContext()
local machinesTab = UI.Tab { local machinesTab = UI.Tab {
tabTitle = 'Machine', tabTitle = 'Machine',
index = 3, index = 3,
backgroundColor = colors.cyan,
grid = UI.ScrollingGrid { grid = UI.ScrollingGrid {
x = 2, ex = -2, y = 2, ey = -2, x = 2, ex = -2, y = 2, ey = -2,
disableHeader = true, disableHeader = true,

View File

@@ -3,12 +3,9 @@ local itemDB = require('core.itemDB')
local Milo = require('milo') local Milo = require('milo')
local UI = require('opus.ui') local UI = require('opus.ui')
local colors = _G.colors
local recipeTab = UI.Tab { local recipeTab = UI.Tab {
tabTitle = 'Recipe', tabTitle = 'Recipe',
index = 2, index = 2,
backgroundColor = colors.cyan,
grid = UI.ScrollingGrid { grid = UI.ScrollingGrid {
x = 2, ex = -2, y = 2, ey = -4, x = 2, ex = -2, y = 2, ey = -4,
disableHeader = true, disableHeader = true,

View File

@@ -9,7 +9,7 @@ local context = Milo:getContext()
local resetTab = UI.Tab { local resetTab = UI.Tab {
tabTitle = 'Reset', tabTitle = 'Reset',
index = 5, index = 5,
backgroundColor = colors.cyan, noFill = true,
textArea = UI.TextArea { textArea = UI.TextArea {
y = 2, ey = 6, y = 2, ey = 6,
textColor = colors.yellow, textColor = colors.yellow,

View File

@@ -15,7 +15,6 @@ local os = _G.os
local wizardPage = UI.WizardPage { local wizardPage = UI.WizardPage {
title = 'Crafting Monitor', title = 'Crafting Monitor',
index = 2, index = 2,
backgroundColor = colors.cyan,
[1] = UI.TextArea { [1] = UI.TextArea {
x = 2, ex = -2, y = 2, ey = 3, x = 2, ex = -2, y = 2, ey = 3,
marginRight = 0, marginRight = 0,

View File

@@ -1,43 +0,0 @@
local Ansi = require('opus.ansi')
local UI = require('opus.ui')
local colors = _G.colors
local device = _G.device
--[[ Configuration Screen ]]
local template =
[[%sWarning%s
Must an interface for Refined Storage / Applied Energistics.
Add all speed upgrades possible.
]]
local wizardPage = UI.WizardPage {
title = 'Mass Storage',
index = 2,
backgroundColor = colors.cyan,
[1] = UI.TextArea {
x = 2, ex = -2, y = 2, ey = -2,
value = string.format(template, Ansi.red, Ansi.reset),
},
}
function wizardPage:isValidFor(node)
if node.mtype == 'storage' then
local m = device[node.name]
return m and m.listAvailableItems
end
end
function wizardPage:setNode(node)
self.node = node
end
function wizardPage:validate()
self.node.adapterType = 'massAdapter'
return true
end
-- disable until a way is found to transfer between 2 non-transferrable nodes
-- UI:getPage('nodeWizard').wizard:add({ inputChest = wizardPage })

View File

@@ -10,12 +10,11 @@ local STARTUP_FILE = 'usr/autorun/miloRemote.lua'
local context = ({ ... })[1] local context = ({ ... })[1]
local setup = UI.SlideOut { local setup = UI.SlideOut {
backgroundColor = colors.cyan,
titleBar = UI.TitleBar { titleBar = UI.TitleBar {
title = 'Remote Setup', title = 'Remote Setup',
}, },
form = UI.Form { form = UI.Form {
x = 2, ex = -2, y = 2, ey = -1, y = 2, ey = -1,
[1] = UI.TextEntry { [1] = UI.TextEntry {
formLabel = 'Server', formKey = 'server', formLabel = 'Server', formKey = 'server',
help = 'ID for the server', help = 'ID for the server',
@@ -40,18 +39,18 @@ local setup = UI.SlideOut {
formLabel = 'Run on startup', formKey = 'runOnStartup', formLabel = 'Run on startup', formKey = 'runOnStartup',
help = 'Run this program on startup' help = 'Run this program on startup'
}, },
info = UI.TextArea { },
x = 1, ex = -1, y = 6, ey = -4, info = UI.TextArea {
textColor = colors.yellow, x = 2, ex = -2, y = 8, ey = -4,
marginLeft = 0, textColor = colors.yellow,
marginRight = 0, marginLeft = 0,
value = [[The Milo turtle must connect to a manipulator with a ]] .. marginRight = 0,
[[bound introspection module. The neural interface must ]] .. value = [[The Milo turtle must connect to a manipulator with a ]] ..
[[also have an introspection module.]], [[bound introspection module. The neural interface must ]] ..
}, [[also have an introspection module.]],
}, },
statusBar = UI.StatusBar { statusBar = UI.StatusBar {
backgroundColor = colors.cyan, backgroundColor = 'primary',
}, },
} }

View File

@@ -14,7 +14,6 @@ end
local wizardPage = UI.WizardPage { local wizardPage = UI.WizardPage {
title = 'Speaker', title = 'Speaker',
index = 2, index = 2,
backgroundColor = colors.cyan,
[1] = UI.Text { [1] = UI.Text {
x = 2, y = 2, x = 2, y = 2,
textColor = colors.yellow, textColor = colors.yellow,

View File

@@ -18,7 +18,6 @@ Right-clicking on the activity monitor will reset the totals.]]
local wizardPage = UI.WizardPage { local wizardPage = UI.WizardPage {
title = 'Status Monitor', title = 'Status Monitor',
index = 2, index = 2,
backgroundColor = colors.cyan,
[1] = UI.TextArea { [1] = UI.TextArea {
x = 2, ex = -2, y = 2, ey = 6, x = 2, ex = -2, y = 2, ey = 6,
marginRight = 0, marginRight = 0,
@@ -86,6 +85,7 @@ local function createPage(node)
[1] = UI.Tab { [1] = UI.Tab {
tabTitle = 'Overview', tabTitle = 'Overview',
backgroundColor = colors.black, backgroundColor = colors.black,
noFill = true,
onlineLabel = UI.Text { onlineLabel = UI.Text {
x = 2, y = 2, x = 2, y = 2,
value = 'Storage Status', value = 'Storage Status',
@@ -136,12 +136,14 @@ local function createPage(node)
}, },
[2] = UI.Tab { [2] = UI.Tab {
tabTitle = 'Stats', tabTitle = 'Stats',
noFill = true,
textArea = UI.TextArea { textArea = UI.TextArea {
y = 3, y = 3,
}, },
}, },
[3] = UI.Tab { [3] = UI.Tab {
tabTitle = 'Storage', tabTitle = 'Storage',
noFill = true,
grid = UI.ScrollingGrid { grid = UI.ScrollingGrid {
y = 2, y = 2,
columns = { columns = {
@@ -156,6 +158,7 @@ local function createPage(node)
}, },
[4] = UI.Tab { [4] = UI.Tab {
tabTitle = 'Offline', tabTitle = 'Offline',
noFill = true,
grid = UI.ScrollingGrid { grid = UI.ScrollingGrid {
y = 2, y = 2,
columns = { columns = {
@@ -166,12 +169,14 @@ local function createPage(node)
}, },
[5] = UI.Tab { [5] = UI.Tab {
tabTitle = 'Activity', tabTitle = 'Activity',
noFill = true,
term = UI.Embedded { term = UI.Embedded {
--visible = true, --visible = true,
}, },
}, },
[6] = UI.Tab { [6] = UI.Tab {
tabTitle = 'Tasks', tabTitle = 'Tasks',
noFill = true,
grid = UI.ScrollingGrid { grid = UI.ScrollingGrid {
y = 2, y = 2,
values = context.tasks, values = context.tasks,

View File

@@ -7,7 +7,6 @@ local device = _G.device
local storageView = UI.WizardPage { local storageView = UI.WizardPage {
title = 'Storage Options - General', title = 'Storage Options - General',
index = 2, index = 2,
backgroundColor = colors.cyan,
form = UI.Form { form = UI.Form {
x = 2, ex = -2, y = 1, ey = -2, x = 2, ex = -2, y = 1, ey = -2,
manualControls = true, manualControls = true,
@@ -62,7 +61,6 @@ UI:getPage('nodeWizard').wizard:add({ storageGeneral = storageView })
local lockView = UI.WizardPage { local lockView = UI.WizardPage {
title = 'Storage Options - Locking', title = 'Storage Options - Locking',
index = 3, index = 3,
backgroundColor = colors.cyan,
form = UI.Form { form = UI.Form {
x = 2, ex = -2, y = 1, ey = 3, x = 2, ex = -2, y = 1, ey = 3,
manualControls = true, manualControls = true,

View File

@@ -12,7 +12,6 @@ local context = Milo:getContext()
local wizardPage = UI.WizardPage { local wizardPage = UI.WizardPage {
title = 'Transfer Inventory', title = 'Transfer Inventory',
index = 2, index = 2,
backgroundColor = colors.cyan,
grid = UI.ScrollingGrid { grid = UI.ScrollingGrid {
y = 2, ey = -2, y = 2, ey = -2,
values = context.storage.nodes, values = context.storage.nodes,

View File

@@ -9,7 +9,6 @@ local device = _G.device
local wizardPage = UI.WizardPage { local wizardPage = UI.WizardPage {
title = 'Trashcan', title = 'Trashcan',
index = 2, index = 2,
backgroundColor = colors.cyan,
info = UI.TextArea { info = UI.TextArea {
x = 1, ex = -1, y = 2, ey = 4, x = 1, ex = -1, y = 2, ey = 4,
textColor = colors.yellow, textColor = colors.yellow,

View File

@@ -637,8 +637,7 @@ Event.addRoutine(function()
end) end)
UI:setPage(page) UI:setPage(page)
UI:pullEvents() UI:start()
UI.term:reset()
turtle.reset() turtle.reset()

View File

@@ -121,7 +121,10 @@ function Process:new(args)
self.terminal = self.window self.terminal = self.window
self.container.canvas.parent = monitor.canvas self.container.canvas.parent = monitor.canvas
table.insert(monitor.canvas.layers, 1, self.container.canvas) if not monitor.canvas.children then
monitor.canvas.children = { }
end
table.insert(monitor.canvas.children, 1, self.container.canvas)
self.container.canvas:setVisible(true) self.container.canvas:setVisible(true)
--self.container.getSize = self.window.getSize --self.container.getSize = self.window.getSize

142
neural/Equipment.lua Normal file
View File

@@ -0,0 +1,142 @@
local Event = require('opus.event')
local itemDB = require('core.itemDB')
local neural = require('neural.interface')
local UI = require('opus.ui')
local Util = require('opus.util')
local device = _G.device
neural.assertModules({
'plethora:sensor',
'plethora:kinetic',
'plethora:introspection',
})
UI:configure('Equipment', ...)
local equipment = device.neuralInterface.getEquipment()
local slots = {
'primary',
'offhand',
'boots',
'leggings',
'chest',
'helmet',
}
local page = UI.Page {
menuBar = UI.MenuBar {
buttons = {
{ text = 'Drop', event = 'drop' },
{ text = 'Suck', event = 'suck' },
},
},
grid = UI.Grid {
y = 2,
columns = {
{ heading = 'Slot', key = 'index', width = 7 },
{ heading = 'Name', key = 'displayName' },
{ heading = 'Count', key = 'count', width = 5, align = 'right' },
},
sortColumn = 'index',
accelerators = {
grid_select = 'show_detail',
},
getDisplayValues = function(_, row)
row = Util.shallowCopy(row)
if row.name then
local item = itemDB:get(
table.concat({ row.name, row.damage, row.nbtHash }, ':'),
function()
return equipment.getItemMeta(row.index)
end)
row.displayName = item.displayName
else
row.displayName = 'empty'
end
row.index = slots[row.index]
return row
end,
},
accelerators = {
[ 'control-q' ] = 'quit',
},
detail = UI.SlideOut {
menuBar = UI.MenuBar {
buttons = {
{ text = 'Back', event = 'slide_hide' },
},
},
grid = UI.ScrollingGrid {
y = 2,
columns = {
{ heading = 'Name', key = 'name' },
{ heading = 'Value', key = 'value' },
},
sortColumn = 'name',
accelerators = {
grid_select = 'inspect',
},
},
show = function(self, slot)
local detail = equipment.getItemMeta(slot.index)
local t = { }
for k,v in pairs(detail) do
table.insert(t, {
name = k,
value = v,
})
end
self.grid:setValues(t)
self.grid:setIndex(1)
UI.SlideOut.show(self)
end,
},
enable = function(self)
self:refresh()
UI.Page.enable(self)
end,
refresh = function(self)
local t = { }
local list = equipment.list()
for i = 1, equipment.size() do
local v = list[i] or { }
v.index = i
table.insert(t, v)
end
self.grid:setValues(t)
self.grid:draw()
end,
eventHandler = function(self, event)
if event.type == 'quit' then
UI:quit()
elseif event.type == 'show_detail' then
if event.selected.name then
self.detail:show(event.selected)
end
elseif event.type == 'drop' then
local selected = self.grid:getSelected()
equipment.drop(selected.index)
self:refresh()
elseif event.type == 'suck' then
local selected = self.grid:getSelected()
equipment.suck(selected.index)
self:refresh()
end
UI.Page.eventHandler(self, event)
end,
}
Event.onInterval(1, function()
page:refresh()
page:sync()
end)
UI:setPage(page)
UI:start()
itemDB:flush()

View File

@@ -182,7 +182,7 @@ end
function page:eventHandler(event) function page:eventHandler(event)
if event.type == 'quit' then if event.type == 'quit' then
Event.exitPullEvents() UI:quit()
elseif event.type == 'scan' then elseif event.type == 'scan' then
self:scan() self:scan()
@@ -211,7 +211,7 @@ Event.onTimeout(0, function()
page:sync() page:sync()
end) end)
UI:pullEvents() UI:start()
if canvas then if canvas then
canvas:clear() canvas:clear()

View File

@@ -253,7 +253,7 @@ end
function page:eventHandler(event) function page:eventHandler(event)
if event.type == 'quit' then if event.type == 'quit' then
Event.exitPullEvents() UI:quit()
elseif event.type == 'tab_activate' then elseif event.type == 'tab_activate' then
config.activeTab = event.activated.tabTitle config.activeTab = event.activated.tabTitle
@@ -268,7 +268,7 @@ if config.activeTab then
end end
UI:setPage(page) UI:setPage(page)
UI:pullEvents() UI:start()
if canvas then if canvas then
canvas:clear() canvas:clear()

View File

@@ -29,4 +29,10 @@
run = "ores.lua", run = "ores.lua",
requires = "neuralInterface", requires = "neuralInterface",
}, },
[ "7f2465ac7cefab2766e6ee0714647089df9364b0ff09858c84b21b8a436a845d" ] = {
title = "Equipment",
category = "Neural",
run = "Equipment",
requires = "neuralInterface",
}
} }

View File

@@ -1,6 +1,15 @@
--[[ --[[
Breed either cows or sheep. Changed to use a 2-high mob (smaller mobs may work ?)
Must be run on a mob with the same height. Updated due to entity.look working correctly now.
The mob looks head-on to the lever. Make sure the
lever is accessible by the mob.
Laser is now optional - if no laser, the mobs will be
punched (or provide a stick). Best mob may be a
skeleton (unlimited ammo).
Feeding hand has been changed to off-hand.
]] ]]
local Array = require('opus.array') local Array = require('opus.array')
@@ -21,80 +30,100 @@ local WALK_SPEED = 1.5
neural.assertModules({ neural.assertModules({
'plethora:sensor', 'plethora:sensor',
'plethora:scanner', 'plethora:scanner',
'plethora:laser', --'plethora:laser',
'plethora:kinetic', 'plethora:kinetic',
'plethora:introspection', 'plethora:introspection',
}) })
local caninimals = config.animals or { [ config.animal ] = true }
local animals = { }
for k in pairs(caninimals) do
animals[k] = { }
end
local fed = { } local fed = { }
local function resupply() local function resupply()
local slot = neural.getEquipment().list()[1] local slot = neural.getEquipment().list()[2]
if slot and slot.count > 32 then if slot and slot.count > 32 then
return return
end end
print('resupplying') print('resupplying')
for _ = 1, 2 do for _ = 1, 2 do
local dispenser = Map.find(neural.scan(), 'name', 'minecraft:dispenser') local dispenser = Map.find(neural.scan(), 'name', 'minecraft:lever')
if not dispenser then if not dispenser then
print('dispenser not found') print('dispenser not found')
break break
end end
if math.abs(dispenser.x) <= 1 and math.abs(dispenser.z) <= 1 then if math.abs(dispenser.x) <= 1.2 and math.abs(dispenser.z) <= 1.2 then
neural.lookAt(dispenser) neural.lookAt({ x = dispenser.x, y = dispenser.y, z = dispenser.z })
for _ = 1, 8 do for _ = 1, 8 do
neural.use(0, 'off') if not neural.use(0, 'off') then
break
end
os.sleep(.2) os.sleep(.2)
neural.getEquipment().suck(1, 64) neural.getEquipment().suck(2, 64)
end end
break break
else else
neural.walkTo({ x = dispenser.x, y = 0, z = dispenser.z }, WALK_SPEED) neural.walkTo({ x = dispenser.x, y = 0, z = dispenser.z }, WALK_SPEED, .5)
end end
end end
end end
local function breed(entity) local function breed(entity)
print('breeding') print('breeding ' .. entity.name)
entity.lastFed = os.clock()
fed[entity.id] = entity
neural.walkTo(entity, WALK_SPEED, 1) neural.walkTo(entity, WALK_SPEED, 1)
entity = neural.getMetaByID(entity.id) entity = neural.getMetaByID(entity.id)
if entity then if entity then
neural.lookAt(entity) neural.lookAt(entity)
neural.use(1) if neural.use(1, 'off') then
entity.lastFed = os.clock()
fed[entity.id] = entity
end
os.sleep(.1) os.sleep(.1)
end end
end end
local function kill(entity) local function kill(entity)
print('killing') print('killing ' .. entity.name)
neural.walkTo(entity, WALK_SPEED, 2.5) neural.walkTo(entity, WALK_SPEED, (neural.fire or neural.shoot) and 2.5 or .5)
entity = neural.getMetaByID(entity.id) entity = neural.getMetaByID(entity.id)
if entity then if entity then
neural.lookAt(entity) neural.lookAt(entity)
neural.fireAt({ x = entity.x, y = 0, z = entity.z }) if neural.fire or neural.shoot then
neural.shootAt(entity)
else
neural.swing()
end
Sound.play('entity.firework.launch') Sound.play('entity.firework.launch')
os.sleep(.2) os.sleep(.2)
end end
end end
local function getEntities() local function shuffle(tbl)
local sheep = Array.filter(neural.sense(), function(entity) for i = #tbl, 2, -1 do
if entity.name == 'Sheep' and entity.y > -.5 then local j = math.random(i)
return true tbl[i], tbl[j] = tbl[j], tbl[i]
end
end)
if #sheep > config.maxAdults then
return sheep
end end
return tbl
end
return Map.filter(neural.sense(), function(entity) local function getEntities()
if entity.name == config.animal and entity.y > -.5 then return shuffle(Array.filter(neural.sense(), function(entity)
return true if animals[entity.name] then
if not animals[entity.name].height then
entity = neural.getMetaByID(entity.id)
if entity and not entity.isChild and entity.motionX == 0 and entity.motionZ == 0 then
animals[entity.name].height = entity.y
return true
end
elseif entity.y == animals[entity.name].height then
return true
end
end end
end) end))
end end
local function getHungry(entities) local function getHungry(entities)
@@ -105,13 +134,25 @@ local function getHungry(entities)
end end
end end
local function randomEntity(entities) local function getCount(entities, name)
local r = math.random(1, Map.size(entities)) local c = 0
local i = 1
for _, v in pairs(entities) do for _, v in pairs(entities) do
i = i + 1 if v.name == name then
if i > r then c = c + 1
return v end
end
print(name .. ' ' .. c)
return c
end
local function getKillable(entities)
print('map: ' .. Map.size(fed))
if Map.size(fed) > 1000 then
fed = { }
end
for name in pairs(animals) do
if getCount(entities, name) > config.maxAdults then
return Array.find(entities, 'name', name)
end end
end end
end end
@@ -120,9 +161,10 @@ while true do
resupply() resupply()
local entities = getEntities() local entities = getEntities()
local killable = getKillable(entities)
if Map.size(entities) > config.maxAdults then if killable then
kill(randomEntity(entities)) kill(killable)
else else
local entity = getHungry(entities) local entity = getHungry(entities)
if entity then if entity then

View File

@@ -61,12 +61,12 @@ local page = UI.Page {
autospace = true, autospace = true,
}, },
add = UI.SlideOut { add = UI.SlideOut {
backgroundColor = colors.cyan, height = 9, y = -9,
titleBar = UI.TitleBar { titleBar = UI.TitleBar {
title = 'Add a new book', title = 'Add a new book',
}, },
form = UI.Form { form = UI.Form {
x = 2, ex = -2, y = 2, ey = -1, y = 2,
[1] = UI.TextEntry { [1] = UI.TextEntry {
formLabel = 'Name', formKey = 'name', formLabel = 'Name', formKey = 'name',
shadowText = 'Friendly name', shadowText = 'Friendly name',
@@ -100,11 +100,10 @@ function page.info:draw()
self:clear() self:clear()
if book then if book then
self:setCursorPos(1, 1)
self:print( self:print(
string.format('Name: %s%s%s\n', Ansi.yellow, book.name, Ansi.reset)) string.format('Name: %s%s%s\nVersion: %s%s%s\n',
self:print( Ansi.yellow, book.name, Ansi.reset,
string.format('Version: %s%s%s\n', Ansi.yellow, book.version, Ansi.reset)) Ansi.yellow, book.version, Ansi.reset))
self.button.text = book.enabled and 'Disable' or 'Enable' self.button.text = book.enabled and 'Disable' or 'Enable'
self.button:draw() self.button:draw()
@@ -173,11 +172,11 @@ function page:eventHandler(event)
self.info:draw() self.info:draw()
elseif event.type == 'quit' then elseif event.type == 'quit' then
UI:exitPullEvents() UI:quit()
end end
UI.Page.eventHandler(self, event) UI.Page.eventHandler(self, event)
end end
UI:setPage(page) UI:setPage(page)
UI:pullEvents() UI:start()

View File

@@ -11,7 +11,7 @@ if not multishell then
end end
local config = Config.load('saver', { local config = Config.load('saver', {
enabled = true, enabled = false,
timeout = 60, timeout = 60,
random = true, random = true,
specific = nil, specific = nil,

View File

@@ -6,23 +6,26 @@ local config = Config.load('saver', {
timeout = 60, timeout = 60,
}) })
local tab = UI.Tab { return UI.Tab {
tabTitle = 'Screen Saver', tabTitle = 'Screen Saver',
description = 'Screen saver', description = 'Screen saver',
[1] = UI.Window {
x = 2, y = 2, ex = -2, ey = 5,
},
label1 = UI.Text { label1 = UI.Text {
x = 2, y = 3, x = 3, y = 3,
value = 'Enabled', value = 'Enabled',
}, },
checkbox = UI.Checkbox { checkbox = UI.Checkbox {
x = 20, y = 3, x = 21, y = 3,
value = config.enabled value = config.enabled
}, },
label2 = UI.Text { label2 = UI.Text {
x = 2, y = 4, x = 3, y = 4,
value = 'Timeout', value = 'Timeout',
}, },
timeout = UI.TextEntry { timeout = UI.TextEntry {
x = 20, y = 4, width = 6, x = 21, y = 4, width = 6,
limit = 4, limit = 4,
transform = 'number', transform = 'number',
value = config.timeout, value = config.timeout,
@@ -31,28 +34,25 @@ local tab = UI.Tab {
}, },
}, },
button = UI.Button { button = UI.Button {
x = 20, y = 6, x = -8, ex = -2, y = -2,
text = 'Update', text = 'Apply',
event = 'update', event = 'update',
}, },
} eventHandler = function(self, event)
if event.type =='checkbox_change' then
config.enabled = not not event.checked
function tab:eventHandler(event) elseif event.type == 'update' then
if event.type =='checkbox_change' then if self.timeout.value then
config.enabled = not not event.checked config.timeout = self.timeout.value
Config.update('saver', config)
elseif event.type == 'update' then self:emit({ type = 'success_message', message = 'Settings updated' })
if self.timeout.value then os.queueEvent('config_update', 'saver', config)
config.timeout = self.timeout.value else
Config.update('saver', config) self:emit({ type = 'error_message', message = 'Invalid timeout' })
end
self:emit({ type = 'success_message', message = 'Settings updated' })
os.queueEvent('config_update', 'saver', config)
else
self:emit({ type = 'error_message', message = 'Invalid timeout' })
end end
end return UI.Tab.eventHandler(self, event)
return UI.Tab.eventHandler(self, event) end,
end }
return tab

View File

@@ -49,7 +49,7 @@ local function buildLockScreen()
#self.pass.value > 0 and #self.pass.value > 0 and
Security.verifyPassword(SHA.compute(self.pass.value)) then Security.verifyPassword(SHA.compute(self.pass.value)) then
UI:exitPullEvents() -- valid UI:quit() -- valid
else else
self.notification:error('Invalid password', math.max(counter, 2)) self.notification:error('Invalid password', math.max(counter, 2))
self:sync() self:sync()
@@ -66,7 +66,7 @@ local function buildLockScreen()
Event.onTerminate(function() return false end) Event.onTerminate(function() return false end)
UI:setPage(page) UI:setPage(page)
UI:pullEvents() UI:start()
-- restart lock timer -- restart lock timer
timer = os.startTimer(config.timeout) timer = os.startTimer(config.timeout)

View File

@@ -9,20 +9,23 @@ local config = Config.load('secure', {
local tab = UI.Tab { local tab = UI.Tab {
tabTitle = 'Secure', tabTitle = 'Secure',
description = 'Secure options', description = 'Secure options',
[1] = UI.Window {
x = 2, y = 2, ex = -2, ey = 5,
},
label1 = UI.Text { label1 = UI.Text {
x = 2, y = 3, x = 3, y = 3,
value = 'Screen Locking', value = 'Screen Locking',
}, },
checkbox = UI.Checkbox { checkbox = UI.Checkbox {
x = 20, y = 3, x = 21, y = 3,
value = config.enabled value = config.enabled
}, },
label2 = UI.Text { label2 = UI.Text {
x = 2, y = 4, x = 3, y = 4,
value = 'Lock timeout', value = 'Lock timeout',
}, },
timeout = UI.TextEntry { timeout = UI.TextEntry {
x = 20, y = 4, width = 6, x = 21, y = 4, width = 6,
limit = 4, limit = 4,
transform = 'number', transform = 'number',
value = config.timeout, value = config.timeout,
@@ -31,8 +34,8 @@ local tab = UI.Tab {
}, },
}, },
button = UI.Button { button = UI.Button {
x = 20, y = 6, x = -8, ex = -2, y = -2,
text = 'Update', text = 'Apply',
event = 'update', event = 'update',
}, },
} }

View File

@@ -189,4 +189,4 @@ end)
page.grid:loadTransactions() page.grid:loadTransactions()
UI:setPage(page) UI:setPage(page)
UI:pullEvents() UI:start()

View File

@@ -9,7 +9,6 @@ local os = _G.os
local wizardPage = UI.WizardPage { local wizardPage = UI.WizardPage {
title = 'Store Front', title = 'Store Front',
index = 2, index = 2,
backgroundColor = colors.cyan,
form = UI.Form { form = UI.Form {
x = 2, ex = -2, y = 1, ey = -2, x = 2, ex = -2, y = 1, ey = -2,
manualControls = true, manualControls = true,
@@ -90,7 +89,6 @@ end
local passwordPage = UI.WizardPage { local passwordPage = UI.WizardPage {
title = 'Krist Settings', title = 'Krist Settings',
index = 3, index = 3,
backgroundColor = colors.cyan,
form = UI.Form { form = UI.Form {
x = 2, ex = -2, y = 1, ey = -2, x = 2, ex = -2, y = 1, ey = -2,
manualControls = true, manualControls = true,
@@ -112,7 +110,7 @@ local passwordPage = UI.WizardPage {
preview = UI.TextEntry { preview = UI.TextEntry {
formIndex = 4, formIndex = 4,
formLabel = 'Using address', formKey = 'address', formLabel = 'Using address', formKey = 'address',
backgroundColor = colors.cyan, backgroundColor = 'primary',
textColor = colors.yellow, textColor = colors.yellow,
inactive = true, inactive = true,
}, },

View File

@@ -10,7 +10,7 @@ local shopTab = UI.Tab {
tabTitle = 'Store', tabTitle = 'Store',
index = 2, index = 2,
form = UI.Form { form = UI.Form {
x = 2, ex = -2, y = 1, ey = -2, x = 2, ex = -2, y = 2, ey = -2,
manualControls = true, manualControls = true,
[1] = UI.TextEntry { [1] = UI.TextEntry {
formLabel = 'Name', formKey = 'name', formLabel = 'Name', formKey = 'name',