a-planet-alive/mods/gui/smart_inventory/libs/smartfs-elements.lua

288 lines
8.4 KiB
Lua

local smartfs = smart_inventory.smartfs
local elements = {}
-----------------------------------------------------
--- Crafting Preview applet
-----------------------------------------------------
-- enhanced / prepared container
-- Additional methods
-- craft_preview:setCraft(craft)
-- craft_preview:onButtonClicked(function(self, itemname, player))
-- if craft=nil, the view will be initialized
local craft_preview = table.copy(smartfs._edef.container)
function craft_preview:onCreate()
self.data.relative = true
smartfs._edef.container.onCreate(self)
for x = 1, 3 do
for y = 1, 3 do
local button = self._state:image_button(
(x-1)*self.data.zoom+self.data.pos.x,
(y-1)*self.data.zoom+self.data.pos.y,
self.data.zoom, self.data.zoom,
"craft:"..x..":"..y,"")
button:setVisible(false)
button:onClick(function(self, state, player)
local parent_element = state.location.containerElement
if parent_element._button_click then
parent_element._button_click(parent_element, self.data.item, player)
end
end)
end
end
if self.data.recipe then
self:setCraft(self.data.recipe)
end
end
function craft_preview:onButtonClicked(func)
self._button_click = func
end
-- Update fields
function craft_preview:setCraft(craft)
local width
if craft then -- adjust width to 1 if the recipe contains just 1 item
width = craft.width or 3
if width == 0 then
width = 3
end
if craft.items[1] and next(craft.items, 1) == nil then
width = 1
end
end
for x = 1, 3 do
for y = 1, 3 do
local item = nil
if craft then
if width <= 1 then
if x == 2 then
item = craft.items[y]
end
elseif x <= width then
item = craft.items[(y-1)*width+x]
end
end
local btn = self._state:get("craft:"..x..":"..y)
if item then
if type(item) == "string" then
btn:setItem(item)
btn:setTooltip()
btn:setText("")
else
btn:setItem(item.item)
btn:setTooltip(item.tooltip)
btn:setText(item.text)
end
btn:setVisible(true)
else
btn:setVisible(false)
end
end
end
end
-- get the preview as table
function craft_preview:getCraft()
local grid = {}
for x = 1, 3 do
grid[x] = {}
for y = 1, 3 do
local button = self._state:get("craft:"..x..":"..y)
if button:getVisible() then
grid[x][y] = button:getItem()
end
end
end
return grid
end
smartfs.element("craft_preview", craft_preview)
function elements:craft_preview(x, y, name, zoom, recipe)
return self:element("craft_preview", {
pos = {x=x, y=y},
name = name,
recipe = recipe,
zoom = zoom or 1
})
end
-----------------------------------------------------
--- Pagable grid buttons
-----------------------------------------------------
--[[ enhanced / prepared container
Additional methods
buttons_grid:setList(craft)
buttons_grid:onClick(function(state, index, player)...end)
buttons_grid:setList(iconlist)
buttons_grid:getFirstVisible()
buttons_grid:setFirstVisible(index)
iconslist is a list of next entries:
entry = {
image | item =
tooltip=
is_button = true,
size = {w=,h=}
}
]]
local buttons_grid = table.copy(smartfs._edef.container)
function buttons_grid:onCreate()
self.data.relative = true
assert(self.data.size and self.data.size.w and self.data.size.h, "button needs valid size")
smartfs._edef.container.onCreate(self)
if not self.data.cell_size or not self.data.cell_size.w or not self.data.cell_size.h then
self.data.cell_size = {w=1, h=1}
end
self:setSize(self.data.size.w, self.data.size.h) -- view size for background
self.data.grid_size = {w = math.floor(self.data.size.w/self.data.cell_size.w), h = math.floor(self.data.size.h/self.data.cell_size.h)}
self.data.list_start = self.data.list_start or 1
self.data.list = self.data.list or {}
for x = 1, self.data.grid_size.w do
for y=1, self.data.grid_size.h do
local button = self._state:button(
self.data.pos.x + (x-1)*self.data.cell_size.w,
self.data.pos.y + (y-1)*self.data.cell_size.h,
self.data.cell_size.w,
self.data.cell_size.h,
tostring((y-1)*self.data.grid_size.w+x),
"")
button:onClick(function(self, state, player)
local rel = tonumber(self.name)
local parent_element = state.location.containerElement
local idx = rel
if parent_element.data.list_start > 1 then
idx = parent_element.data.list_start + rel - 2
end
if rel == 1 and parent_element.data.list_start > 1 then
-- page back
local full_pagesize = parent_element.data.grid_size.w * parent_element.data.grid_size.h
if parent_element.data.list_start <= full_pagesize then
parent_element.data.list_start = 1
else
--prev page use allways 2x navigation buttons at list_start > 1 and the next page (we navigate from) exists
parent_element.data.list_start = parent_element.data.list_start - (full_pagesize-2)
end
parent_element:update()
elseif rel == (parent_element.data.grid_size.w * parent_element.data.grid_size.h) and
parent_element.data.list[parent_element.data.list_start+parent_element.data.pagesize] then
-- page forward
parent_element.data.list_start = parent_element.data.list_start+parent_element.data.pagesize
parent_element:update()
else
-- pass call to the button function
if parent_element._click then
parent_element:_click(parent_element.root, idx, player)
end
end
end)
button:setVisible(false)
end
end
end
function buttons_grid:reset(x, y, w, h, col_size, row_size)
self._state = nil
self.data.pos.x = x or self.data.pos.x
self.data.pos.y = y or self.data.pos.y
self.data.size.w = w or self.data.size.w
self.data.size.h = h or self.data.size.h
self.data.cell_size.w = col_size or self.data.cell_size.w
self.data.cell_size.h = row_size or self.data.cell_size.h
self:onCreate()
self:update()
end
function buttons_grid:onClick(func)
self._click = func
end
function buttons_grid:getFirstVisible()
return self.data.list_start
end
function buttons_grid:setFirstVisible(idx)
self.data.list_start = idx
end
function buttons_grid:setList(iconlist)
self.data.list = iconlist or {}
self:update()
end
function buttons_grid:update()
--init pagesize
self.data.pagesize = self.data.grid_size.w * self.data.grid_size.h
--adjust start position
if self.data.list_start > #self.data.list then
self.data.list_start = #self.data.list - self.data.pagesize
end
if self.data.list_start < 1 then
self.data.list_start = 1
end
local itemindex = self.data.list_start
for btnid = 1, self.data.grid_size.w * self.data.grid_size.h do
local button = self._state:get(tostring(btnid))
if btnid == 1 and self.data.list_start > 1 then
-- setup back button
button:setVisible(true)
button:setImage("smart_inventory_left_arrow.png")
button:setText(tostring(self.data.list_start-1))
button:setSize(self.data.cell_size.w, self.data.cell_size.h)
self.data.pagesize = self.data.pagesize - 1
elseif btnid == self.data.grid_size.w * self.data.grid_size.h and self.data.list[itemindex+1] then
-- setup next button
button:setVisible(true)
button:setImage("smart_inventory_right_arrow.png")
self.data.pagesize = self.data.pagesize - 1
button:setText(tostring(#self.data.list-self.data.list_start-self.data.pagesize+1))
button:setSize(self.data.cell_size.w, self.data.cell_size.h)
else
-- functional button
local entry = self.data.list[itemindex]
if entry then
if entry.size then
button:setSize(entry.size.w, entry.size.h)
else
button:setSize(self.data.cell_size.w, self.data.cell_size.h)
end
if entry.item and entry.is_button == true then
button:setVisible(true)
button:setItem(entry.item)
button:setText(entry.text or "")
button:setTooltip(nil)
elseif entry.image and entry.is_button == true then
button:setVisible(true)
button:setImage(entry.image)
button:setText(entry.text or "")
button:setTooltip(entry.tooltip)
-- TODO 1: entry.image to display *.png
-- TODO 2: entry.text to display label on button
-- TODO 3,4,5: is_button == false to get just pic or label without button
end
else
button:setVisible(false)
end
itemindex = itemindex + 1
end
end
end
smartfs.element("buttons_grid", buttons_grid)
function elements:buttons_grid(x, y, w, h, name, col_size, row_size)
return self:element("buttons_grid", {
pos = {x=x, y=y},
size = {w=w, h=h},
cell_size = {w=col_size, h=row_size},
name = name
})
end
-------------------------
return elements