Compare commits
5 Commits
05c4dbdbcb
...
f06a979536
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f06a979536 | ||
![]() |
3bb7a69577 | ||
![]() |
a96102dc48 | ||
![]() |
bbc528988f | ||
![]() |
4721410240 |
19
gfx/container.lua
Normal file
19
gfx/container.lua
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
local Prop = require("gfx.prop")
|
||||||
|
local Children = require("gfx.prop.children")
|
||||||
|
local Element = require("gfx.element")
|
||||||
|
|
||||||
|
local Container = Prop.attach(Element:new(), Children)
|
||||||
|
|
||||||
|
function Container:_reload()
|
||||||
|
Element._reload(self)
|
||||||
|
|
||||||
|
-- Reload child windows
|
||||||
|
local win = self:_getWindow()
|
||||||
|
for _,child in self:_iterateChildren() do
|
||||||
|
if child:_getWindow() ~= win then
|
||||||
|
child:setParent(win)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Container
|
171
gfx/list.lua
171
gfx/list.lua
@ -1,102 +1,44 @@
|
|||||||
local Event = require("gfx.event")
|
local Event = require("gfx.event")
|
||||||
local Element = require("gfx.element")
|
local Element = require("gfx.element")
|
||||||
local List = Element:new{
|
local Prop = require("gfx.prop")
|
||||||
children = {},
|
local Orientation = require("gfx.prop.orientation")
|
||||||
vertical = false
|
local Children = require("gfx.prop.children")
|
||||||
}
|
local List = Prop.attach(Prop.attach(Element:new(), Orientation), Children)
|
||||||
|
|
||||||
local function adjustPositions(elements, vertical, from)
|
function List:adjustPositions(from)
|
||||||
local newDims = 1
|
from = from or 1
|
||||||
local getDim = vertical and function(e) return e:getHeight() end or function(e) return e:getWidth() end
|
local vertical = self:isVertical()
|
||||||
for i=1,from-1 do
|
local newDims = 1
|
||||||
newDims = newDims + getDim(elements[i])
|
local getDim = vertical and function(e) return e:getHeight() end or function(e) return e:getWidth() end
|
||||||
end
|
for _,element in self:_iterateChildren{ to = from } do
|
||||||
|
newDims = newDims + getDim(element)
|
||||||
local setDim = vertical and function(e, dim) e:setY(dim) end or function(e, dim) e:setX(dim) end
|
end
|
||||||
for i=from,#elements do
|
|
||||||
setDim(elements[i], newDims)
|
local setDim = vertical and function(e, dim) e:setY(dim) end or function(e, dim) e:setX(dim) end
|
||||||
newDims = newDims + getDim(elements[i])
|
for _, element in self:_iterateChildren{ from = from } do
|
||||||
end
|
setDim(element, newDims)
|
||||||
|
newDims = newDims + getDim(element)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function List:insertChild(child, atIndex)
|
function List:insertChild(child, atIndex)
|
||||||
local index = math.min(math.max(1, atIndex or #self.children), #self.children)
|
self:_addChild(child, atIndex)
|
||||||
table.insert(self.children, index, child)
|
|
||||||
|
|
||||||
-- Update window references
|
|
||||||
self:_reload()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function List:removeChild(child)
|
function List:removeChild(child)
|
||||||
local index
|
return self:_removeChild(child)
|
||||||
local searchType = type(child)
|
|
||||||
if searchType == "string" then
|
|
||||||
for i,v in ipairs(self.children) do
|
|
||||||
if v:getId() == child then
|
|
||||||
index = i
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false, nil
|
|
||||||
elseif searchType == "table" then
|
|
||||||
for i,v in ipairs(self.children) do
|
|
||||||
if v == child then
|
|
||||||
index = i
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false, nil
|
|
||||||
else
|
|
||||||
index = child
|
|
||||||
end
|
|
||||||
|
|
||||||
if index <= 0 or index > #self.children then
|
|
||||||
return false, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local removed = table.remove(self.children, index)
|
|
||||||
self:_reload()
|
|
||||||
|
|
||||||
return true, removed
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function List:isVertical()
|
local function maxOrSum(shouldSum, iter, getValue)
|
||||||
return self.vertical
|
|
||||||
end
|
|
||||||
|
|
||||||
function List:isHorizontal()
|
|
||||||
return not self:isVertical()
|
|
||||||
end
|
|
||||||
|
|
||||||
function List:setDirty(fullInvalidate)
|
|
||||||
Element.setDirty(self, fullInvalidate)
|
|
||||||
if fullInvalidate then
|
|
||||||
for _,child in self.children do
|
|
||||||
child:setDirty(fullInvalidate)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function List:draw()
|
|
||||||
local dirty = Element.draw(self)
|
|
||||||
if dirty then
|
|
||||||
self:_getWindow().clear()
|
|
||||||
for _,child in ipairs(self.children) do
|
|
||||||
child:draw()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return dirty
|
|
||||||
end
|
|
||||||
|
|
||||||
local function maxOrSum(shouldSum, values, getValue)
|
|
||||||
if shouldSum then
|
if shouldSum then
|
||||||
local sum = 0
|
local sum = 0
|
||||||
for _,v in ipairs(values) do
|
for _,v in iter() do
|
||||||
sum = sum + getValue(v)
|
sum = sum + getValue(v)
|
||||||
end
|
end
|
||||||
return sum
|
return sum
|
||||||
else
|
else
|
||||||
local max = 0
|
local max = 0
|
||||||
for _,v in ipairs(values) do
|
for _,v in iter() do
|
||||||
max = math.max(max, getValue(v))
|
max = math.max(max, getValue(v))
|
||||||
end
|
end
|
||||||
return max
|
return max
|
||||||
@ -104,68 +46,13 @@ local function maxOrSum(shouldSum, values, getValue)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function List:getHeight()
|
function List:getHeight()
|
||||||
return maxOrSum(self:isVertical(), self.children, function(e) return e:getHeight() end)
|
local lSelf = self
|
||||||
|
return maxOrSum(self:isVertical(), function() return lSelf:_iterateChildren() end, function(e) return e:getHeight() end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function List:getWidth()
|
function List:getWidth()
|
||||||
return maxOrSum(self:isHorizontal(), self.children, function(e) return e:getWidth() end)
|
local lSelf = self
|
||||||
end
|
return maxOrSum(self:isHorizontal(), function() return lSelf:_iterateChildren() end, function(e) return e:getWidth() end)
|
||||||
|
|
||||||
function List:findById(id)
|
|
||||||
local find = Element.findById(self, id)
|
|
||||||
if find then
|
|
||||||
return find
|
|
||||||
end
|
|
||||||
|
|
||||||
for _,v in ipairs(self.children) do
|
|
||||||
local result = v:findById(id)
|
|
||||||
if result then
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function List:handleEvent(evt)
|
|
||||||
if Element.handleEvent(self, evt) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
local evtLocalCoords = Event.toElementLocalPosition(evt, self)
|
|
||||||
|
|
||||||
if Event.isClickEvent(evt) then
|
|
||||||
-- If click is not inside list bounds, we can safely ignore it
|
|
||||||
if not Event.containsClick(self, evt) then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
for _,child in ipairs(self.children) do
|
|
||||||
if child:handleEvent(evtLocalCoords) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
else
|
|
||||||
for _,child in ipairs(self.children) do
|
|
||||||
if child:handleEvent(evtLocalCoords) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function List:_isDirty()
|
|
||||||
if Element._isDirty(self) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
for _,child in ipairs(self.children) do
|
|
||||||
if child:_isDirty() then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function List:_reload()
|
function List:_reload()
|
||||||
@ -173,13 +60,13 @@ function List:_reload()
|
|||||||
|
|
||||||
-- Reload child windows
|
-- Reload child windows
|
||||||
local win = self:_getWindow()
|
local win = self:_getWindow()
|
||||||
for _,child in ipairs(self.children) do
|
for _,child in self:_iterateChildren() do
|
||||||
if child:_getWindow() ~= win then
|
if child:_getWindow() ~= win then
|
||||||
child:setParent(win)
|
child:setParent(win)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
adjustPositions(self.children, self:isVertical(), 1)
|
self:adjustPositions()
|
||||||
end
|
end
|
||||||
|
|
||||||
return List
|
return List
|
77
gfx/progress.lua
Normal file
77
gfx/progress.lua
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
local Element = require("gfx.element")
|
||||||
|
local Orientation = require("gfx.prop.orientation")
|
||||||
|
|
||||||
|
local BlankElement = Element:new()
|
||||||
|
|
||||||
|
function BlankElement:draw()
|
||||||
|
local dirty = Element.draw(self)
|
||||||
|
if dirty then
|
||||||
|
self:_getWindow().clear()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function round(value, biasDown)
|
||||||
|
local decimal = value % 1
|
||||||
|
return (((not biasDown) and decimal < 0.5) or ((not not biasDown) and decimal <= 0.5)) and math.floor(value) or math.ceil(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
local Progress = Orientation.with(Element:new{
|
||||||
|
progress = 0.0,
|
||||||
|
active = nil,
|
||||||
|
inactive = nil
|
||||||
|
})
|
||||||
|
|
||||||
|
function Progress:new(o)
|
||||||
|
local obj = o or {}
|
||||||
|
obj.active = BlankElement:new()
|
||||||
|
obj.inactive = BlankElement:new()
|
||||||
|
return Element.new(self, obj)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Progress:_updateProgress()
|
||||||
|
local width, height = self:getWidth(), self:getHeight()
|
||||||
|
if self:isVertical() then
|
||||||
|
self.active:resize(width, round(self:getProgress() * height))
|
||||||
|
self.inactive:resize(width, round((1 - self:getProgress()) * height, true))
|
||||||
|
self.inactive:setY(self.active:getY() + self.active:getHeight())
|
||||||
|
else
|
||||||
|
self.active:resize(round(self:getProgress() * width), height)
|
||||||
|
self.active:resize(round((1 - self:getProgress()) * width, true), height)
|
||||||
|
self.inactive:setX(self.active:setX() + self.active:getWidth())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Progress:setProgress(progress)
|
||||||
|
self:setDirty()
|
||||||
|
self.progress = math.min(1, math.max(0, progress))
|
||||||
|
self:_updateProgress()
|
||||||
|
end
|
||||||
|
|
||||||
|
function Progress:getProgress()
|
||||||
|
return self.progress
|
||||||
|
end
|
||||||
|
|
||||||
|
function Progress:draw()
|
||||||
|
local dirty = Element.draw(self)
|
||||||
|
if dirty then
|
||||||
|
self.inactive:draw()
|
||||||
|
self.active:draw()
|
||||||
|
end
|
||||||
|
return dirty
|
||||||
|
end
|
||||||
|
|
||||||
|
function Progress:_isDirty()
|
||||||
|
return Element._isDirty(self) or self.active:_isDirty() or self.inactive:_isDirty()
|
||||||
|
end
|
||||||
|
|
||||||
|
function Progress:_reload()
|
||||||
|
Element._reload(self)
|
||||||
|
|
||||||
|
-- Reload child windows
|
||||||
|
local win = self:_getWindow()
|
||||||
|
self.active:setParent(win)
|
||||||
|
self.inactive:setParent(win)
|
||||||
|
self:_updateProgress()
|
||||||
|
end
|
||||||
|
|
||||||
|
return Progress
|
158
gfx/prop/children.lua
Normal file
158
gfx/prop/children.lua
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
local Prop = require("gfx.prop")
|
||||||
|
local Element = require("gfx.element")
|
||||||
|
local Event = require("gfx.event")
|
||||||
|
local Children = Prop:new{ defaultState = {} }
|
||||||
|
|
||||||
|
function Children:with(elementType)
|
||||||
|
local propSelf = self
|
||||||
|
function elementType:_iterateChildren(opts)
|
||||||
|
local func, tbl, start = ipairs(propSelf:getState(self))
|
||||||
|
return function(t, i)
|
||||||
|
if i == opts.to then
|
||||||
|
return nil, nil
|
||||||
|
end
|
||||||
|
return func(t, i)
|
||||||
|
end, tbl, (opts and opts.from) or start
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:childCount()
|
||||||
|
return #propSelf:getState(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:_childAt(index)
|
||||||
|
return propSelf:getState()[elementType:_validChildIndex(index)]
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:_validChildIndex(from)
|
||||||
|
return math.max(1, math.min((from or self:childCount()) + 1, self:childCount() + 1))
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:_triggerChildChanged(index)
|
||||||
|
if type(self.onChildrenChanged) == "function" then
|
||||||
|
self:onChildrenChanged(index)
|
||||||
|
end
|
||||||
|
self:_reload()
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:_addChild(child, index)
|
||||||
|
index = self:_validChildIndex(index)
|
||||||
|
table.insert(propSelf:getState(self), index, child)
|
||||||
|
self:_triggerChildChanged(index)
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:_removeChild(locator)
|
||||||
|
local index = nil
|
||||||
|
local locatorType = type(locator)
|
||||||
|
if locatorType == "table" then
|
||||||
|
for i,v in self:_iterateChildren() do
|
||||||
|
if v == locator then
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif locatorType == "string" then
|
||||||
|
for i,v in self:_iterateChildren() do
|
||||||
|
if v:getId() == locator then
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else--if locatorType == "number" then
|
||||||
|
index = self:_validChildIndex(locator)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Child not found
|
||||||
|
if index == nil then
|
||||||
|
return false, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local result = table.remove(propSelf:getState(self), index)
|
||||||
|
self:_triggerChildChanged(index)
|
||||||
|
return true, result
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:setDirty(fullInvalidate)
|
||||||
|
Element.setDirty(self, fullInvalidate)
|
||||||
|
if fullInvalidate then
|
||||||
|
for _,child in self:_iterateChildren() do
|
||||||
|
child:setDirty(fullInvalidate)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:_isDirty()
|
||||||
|
if Element._isDirty(self) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
for _,child in self:_iterateChildren() do
|
||||||
|
if child:_isDirty() then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:draw()
|
||||||
|
local dirty = Element.draw(self)
|
||||||
|
if dirty then
|
||||||
|
self:_getWindow().clear()
|
||||||
|
for _,child in self:_iterateChildren() do
|
||||||
|
child:draw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return dirty
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:findById(id)
|
||||||
|
local find = Element.findById(self, id)
|
||||||
|
if find then
|
||||||
|
return find
|
||||||
|
end
|
||||||
|
|
||||||
|
return self:findChildById(id)
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:findChildById(id)
|
||||||
|
for _,child in self:_iterateChildren() do
|
||||||
|
local result = child:findById(id)
|
||||||
|
if result then
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:handleEvent(evt)
|
||||||
|
if Element.handleEvent(self, evt) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local evtLocalCoords = Event.toElementLocalPosition(evt, self)
|
||||||
|
|
||||||
|
if Event.isClickEvent(evt) then
|
||||||
|
-- If click is not inside list bounds, we can safely ignore it
|
||||||
|
if not Event.containsClick(self, evt) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
for _,child in self:_iterateChildren() do
|
||||||
|
if child:handleEvent(evtLocalCoords) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
for _,child in self:_iterateChildren() do
|
||||||
|
if child:handleEvent(evtLocalCoords) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return elementType
|
||||||
|
end
|
||||||
|
|
||||||
|
return Children
|
24
gfx/prop/init.lua
Normal file
24
gfx/prop/init.lua
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
local Prop = {}
|
||||||
|
Prop.__index = Prop
|
||||||
|
|
||||||
|
function Prop:getState(element)
|
||||||
|
return element[self]
|
||||||
|
end
|
||||||
|
|
||||||
|
function Prop:setState(element, state)
|
||||||
|
element[self] = state
|
||||||
|
end
|
||||||
|
|
||||||
|
function Prop.attach(elementType, prop, defaultState)
|
||||||
|
prop:setState(elementType, defaultState or prop.defaultState)
|
||||||
|
return prop:with(elementType)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Prop:new(o)
|
||||||
|
local obj = o or {}
|
||||||
|
setmetatable(obj, Prop)
|
||||||
|
obj.__index = obj
|
||||||
|
return obj
|
||||||
|
end
|
||||||
|
|
||||||
|
return Prop
|
25
gfx/prop/orientation.lua
Normal file
25
gfx/prop/orientation.lua
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
local Prop = require("gfx.prop")
|
||||||
|
local Orientation = Prop:new{ defaultState = false }
|
||||||
|
|
||||||
|
function Orientation:with(elementType)
|
||||||
|
local propSelf = self
|
||||||
|
function elementType:setVertical(vertical)
|
||||||
|
local state = self:isVertical()
|
||||||
|
if state ~= vertical then
|
||||||
|
self:setDirty()
|
||||||
|
propSelf:setState(self, vertical)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:isVertical()
|
||||||
|
return propSelf:getState(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
function elementType:isHorizontal()
|
||||||
|
return not self:isVertical()
|
||||||
|
end
|
||||||
|
|
||||||
|
return elementType
|
||||||
|
end
|
||||||
|
|
||||||
|
return Orientation
|
@ -5,6 +5,7 @@ local Text = require("gfx.text")
|
|||||||
local List = require("gfx.list")
|
local List = require("gfx.list")
|
||||||
local Event = require("gfx.event")
|
local Event = require("gfx.event")
|
||||||
local Padding = require("gfx.padding")
|
local Padding = require("gfx.padding")
|
||||||
|
local Container = require("gfx.container")
|
||||||
|
|
||||||
|
|
||||||
local CACHE_FILE = "/.storage.cache"
|
local CACHE_FILE = "/.storage.cache"
|
||||||
@ -245,7 +246,7 @@ local PAGES = {
|
|||||||
pageState.stacks = ItemGroup.collectStacks(state.controller:find(function(stack)
|
pageState.stacks = ItemGroup.collectStacks(state.controller:find(function(stack)
|
||||||
return not stack:isEmpty()
|
return not stack:isEmpty()
|
||||||
end))
|
end))
|
||||||
|
|
||||||
table.sort(pageState.stacks, function(a, b) return a:getItemCount() > b:getItemCount() end)
|
table.sort(pageState.stacks, function(a, b) return a:getItemCount() > b:getItemCount() end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -307,8 +308,17 @@ local PAGES = {
|
|||||||
bottom = 1,
|
bottom = 1,
|
||||||
element = title
|
element = title
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local stuffContainer = Container:new{
|
||||||
|
children = {
|
||||||
|
paddedTitle
|
||||||
|
},
|
||||||
|
width = state.width,
|
||||||
|
height = state.height,
|
||||||
|
parent = state.monitor
|
||||||
|
}
|
||||||
|
|
||||||
return renderDefault(state, paddedTitle)
|
return renderDefault(state, stuffContainer)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
REQUEST = function(state, newPage)
|
REQUEST = function(state, newPage)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user