forked from minetest-mods/global_exchange
Expand formlib & distinguish items by wear in market summary.
This commit is contained in:
parent
2a5a726cc0
commit
808b3cbf04
19
atm.lua
19
atm.lua
@ -33,7 +33,7 @@ local function wire_fs(fs, p_name)
|
||||
fs:size(4,5)
|
||||
|
||||
if balance then
|
||||
-- To prevent duplicates
|
||||
-- To detect duplicate/stale form submission
|
||||
fs:field(-100, -100, 0,0, "trans_id", "", unique())
|
||||
|
||||
fs:label(0.50,0.325, "Balance: " .. balance)
|
||||
@ -79,13 +79,12 @@ local function log_fs(fs, p_name)
|
||||
|
||||
fs:label(0,0, "Transaction Log")
|
||||
|
||||
fs("tablecolumns[text;text]")
|
||||
fs:element("tablecolumns", "text", "text")
|
||||
|
||||
fs("table[0,0.75;13.75,6.75;log_table;Time,Message")
|
||||
|
||||
for _, entry in ipairs(exchange:player_log(p_name)) do
|
||||
fs(",", formlib.escape(entry.Time), ",", formlib.escape(entry.Message))
|
||||
fs(","):escape_list(entry.Time, entry.Message)
|
||||
end
|
||||
|
||||
fs("]")
|
||||
|
||||
fs:button(6,7.5, 2,1, "logout", "Log Out")
|
||||
@ -100,9 +99,6 @@ local function main_menu_fs(fs, p_name)
|
||||
end
|
||||
|
||||
|
||||
local trans_ids = {}
|
||||
|
||||
|
||||
local function show_atm_form(fs_fn, p_name, ...)
|
||||
local fs = formlib.Builder()
|
||||
fs_fn(fs, p_name, ...)
|
||||
@ -110,15 +106,18 @@ local function show_atm_form(fs_fn, p_name, ...)
|
||||
end
|
||||
|
||||
|
||||
local trans_ids = {}
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= atm_form then return end
|
||||
if fields.quit then return true end
|
||||
|
||||
local p_name = player:get_player_name()
|
||||
|
||||
local this_id = fields.trans_id
|
||||
local this_id = tonumber(fields.trans_id)
|
||||
|
||||
if this_id and this_id == trans_ids[p_name] then
|
||||
if this_id and trans_ids[p_name] and this_id <= trans_ids[p_name] then
|
||||
-- Ignore duplicate/stale form submittal
|
||||
return true
|
||||
end
|
||||
|
||||
|
@ -26,19 +26,15 @@ end
|
||||
|
||||
|
||||
local function mk_inbox_list(fs, results, x, y, w, h)
|
||||
fs("textlist[", x, ",", y, ";", w, ",", h, ";result_list;")
|
||||
|
||||
local sep = nil
|
||||
for i, row in ipairs(results) do
|
||||
fs(sep)
|
||||
fs:escape(row.Amount, " ", row.Item)
|
||||
if row.Wear > 0 then
|
||||
fs:escape(" (", wear_string(row.Wear), ")")
|
||||
fs:textlist(x,y, w,h, "result_list", function(add_row)
|
||||
for i, row in ipairs(results) do
|
||||
local wear_suffix = nil
|
||||
if row.Wear > 0 then
|
||||
wear_suffix = " (" .. wear_string(row.Wear) .. ")"
|
||||
end
|
||||
add_row(row.Amount, " ", row.Item, wear_suffix)
|
||||
end
|
||||
sep = ","
|
||||
end
|
||||
|
||||
fs("]")
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
|
55
exchange.lua
55
exchange.lua
@ -16,13 +16,13 @@ end)({})
|
||||
|
||||
local init_query = [=[
|
||||
BEGIN TRANSACTION;
|
||||
CREATE TABLE if not exists Credit
|
||||
CREATE TABLE IF NOT EXISTS Credit
|
||||
(
|
||||
Owner TEXT PRIMARY KEY NOT NULL,
|
||||
Balance INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE if not exists Log
|
||||
CREATE TABLE IF NOT EXISTS Log
|
||||
(
|
||||
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
Recipient TEXT NOT NULL,
|
||||
@ -30,7 +30,7 @@ CREATE TABLE if not exists Log
|
||||
Message TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE if not exists Orders
|
||||
CREATE TABLE IF NOT EXISTS Orders
|
||||
(
|
||||
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
Poster TEXT NOT NULL,
|
||||
@ -43,7 +43,7 @@ CREATE TABLE if not exists Orders
|
||||
Rate INTEGER NOT NULL CHECK(Rate > 0)
|
||||
);
|
||||
|
||||
CREATE TABLE if not exists Inbox
|
||||
CREATE TABLE IF NOT EXISTS Inbox
|
||||
(
|
||||
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
Recipient TEXT NOT NULL,
|
||||
@ -52,44 +52,49 @@ CREATE TABLE if not exists Inbox
|
||||
Amount INTEGER NOT NULL CHECK(Amount > 0)
|
||||
);
|
||||
|
||||
CREATE INDEX if not exists index_log
|
||||
CREATE INDEX IF NOT EXISTS index_log
|
||||
ON Log (Recipient, Time);
|
||||
|
||||
CREATE INDEX if not exists index_orders
|
||||
CREATE INDEX IF NOT EXISTS index_orders
|
||||
ON Orders (Exchange, Type, Item, Rate, Wear, Time);
|
||||
|
||||
CREATE INDEX if not exists index_own_orders
|
||||
CREATE INDEX IF NOT EXISTS index_own_orders
|
||||
ON Orders (Poster, Time);
|
||||
|
||||
CREATE INDEX if not exists index_inbox
|
||||
CREATE INDEX IF NOT EXISTS index_inbox
|
||||
ON Inbox (Recipient, Item, Wear);
|
||||
|
||||
CREATE VIEW if not exists distinct_items AS
|
||||
SELECT DISTINCT Item FROM Orders;
|
||||
CREATE VIEW IF NOT EXISTS distinct_items AS
|
||||
SELECT DISTINCT Item, Wear FROM Orders;
|
||||
|
||||
CREATE VIEW if not exists market_summary AS
|
||||
CREATE VIEW IF NOT EXISTS market_summary AS
|
||||
SELECT
|
||||
distinct_items.Item,
|
||||
distinct_items.Item AS Item,
|
||||
distinct_items.Wear AS Wear,
|
||||
(
|
||||
SELECT sum(Orders.Amount) FROM Orders
|
||||
SELECT SUM(Orders.Amount) FROM Orders
|
||||
WHERE Orders.Item = distinct_items.Item
|
||||
AND Orders.Wear >= distinct_items.Wear
|
||||
AND Orders.Type = "buy"
|
||||
),
|
||||
) AS Buy_Volume,
|
||||
(
|
||||
SELECT max(Orders.Rate) FROM Orders
|
||||
SELECT MAX(Orders.Rate) FROM Orders
|
||||
WHERE Orders.Item = distinct_items.Item
|
||||
AND Orders.Wear >= distinct_items.Wear
|
||||
AND Orders.Type = "buy"
|
||||
),
|
||||
) AS Buy_Max,
|
||||
(
|
||||
SELECT sum(Orders.Amount) FROM Orders
|
||||
SELECT SUM(Orders.Amount) FROM Orders
|
||||
WHERE Orders.Item = distinct_items.Item
|
||||
AND Orders.Wear <= distinct_items.Wear
|
||||
AND Orders.Type = "sell"
|
||||
),
|
||||
) AS Sell_Volume,
|
||||
(
|
||||
SELECT min(Orders.Rate) FROM Orders
|
||||
SELECT MIN(Orders.Rate) FROM Orders
|
||||
WHERE Orders.Item = distinct_items.Item
|
||||
AND Orders.Wear <= distinct_items.Wear
|
||||
AND Orders.Type = "sell"
|
||||
)
|
||||
) AS Sell_Min
|
||||
FROM distinct_items;
|
||||
|
||||
|
||||
@ -1241,14 +1246,8 @@ function ex_methods.market_summary(self)
|
||||
local stmt = self.stmts.summary_stmt
|
||||
|
||||
local res = {}
|
||||
for a in stmt:rows() do
|
||||
table.insert(res, {
|
||||
item_name = a[1],
|
||||
buy_volume = a[2],
|
||||
buy_max = a[3],
|
||||
sell_volume = a[4],
|
||||
sell_min = a[5],
|
||||
})
|
||||
for a in stmt:nrows() do
|
||||
table.insert(res, a)
|
||||
end
|
||||
stmt:reset()
|
||||
|
||||
|
@ -9,26 +9,40 @@ local function is_integer(x)
|
||||
return math.floor(x) == x
|
||||
end
|
||||
|
||||
local function wear_string(wear)
|
||||
if wear > 0 then
|
||||
return "-" .. math.ceil(100 * wear / 65535) .. "%"
|
||||
else
|
||||
return "----"
|
||||
end
|
||||
end
|
||||
|
||||
local summary_fs = ""
|
||||
local function mk_summary_fs()
|
||||
local fs = formlib.Builder()
|
||||
|
||||
fs("tablecolumns[text;text;text;text;text;text]")
|
||||
fs("table[0,0;11.75,9;summary_table;")
|
||||
fs("Item,Description,Buy Vol,Buy Max,Sell Vol,Sell Min")
|
||||
fs:tablecolumns("text", "text", "text", "text", "text", "text", "text")
|
||||
fs:table(0,0, 11.75,9, "summary_table", function(add_row)
|
||||
add_row("Item",
|
||||
"Description",
|
||||
"Wear",
|
||||
"Buy Vol",
|
||||
"Buy Max",
|
||||
"Sell Vol",
|
||||
"Sell Min")
|
||||
|
||||
local all_items = minetest.registered_items
|
||||
for i, row in ipairs(exchange:market_summary()) do
|
||||
local def = all_items[row.item_name] or {}
|
||||
fs(",", formlib.escape(row.item_name))
|
||||
fs(",", formlib.escape(def.description or "Unknown Item"))
|
||||
fs(",", formlib.escape(row.buy_volume or 0))
|
||||
fs(",", formlib.escape(row.buy_max or "N/A"))
|
||||
fs(",", formlib.escape(row.sell_volume or 0))
|
||||
fs(",", formlib.escape(row.sell_min or "N/A"))
|
||||
end
|
||||
|
||||
fs("]")
|
||||
local all_items = minetest.registered_items
|
||||
for i, row in ipairs(exchange:market_summary()) do
|
||||
local def = all_items[row.Item] or {}
|
||||
add_row(row.Item,
|
||||
def.description or "Unknown Item",
|
||||
wear_string(row.Wear),
|
||||
row.Buy_Volume or 0,
|
||||
row.Buy_Max or "N/A",
|
||||
row.Sell_Volume or 0,
|
||||
row.Sell_Min or "N/A")
|
||||
end
|
||||
end)
|
||||
|
||||
summary_fs = tostring(fs)
|
||||
end
|
||||
@ -58,10 +72,6 @@ for _,v in ipairs(wear_levels) do
|
||||
wear_levels[tostring(v.text)] = v
|
||||
end
|
||||
|
||||
local function wear_string(wear)
|
||||
return "-" .. math.ceil(100 * wear / 65535) .. "%"
|
||||
end
|
||||
|
||||
|
||||
local main_state = {}
|
||||
-- ^ A per-player state for the main form.
|
||||
@ -108,30 +118,20 @@ end)
|
||||
local main_form = "global_exchange:exchange_main"
|
||||
|
||||
local function table_from_results(fs, results, name, x, y, w, h, selected)
|
||||
fs("tablecolumns[text;text;text;text;text;text;text]")
|
||||
fs("table[", x, ",", y, ";", w, ",", h, ";")
|
||||
fs(formlib.escape(name), ";")
|
||||
fs("Poster,Type,Item,Description,Wear,Amount,Rate")
|
||||
fs:tablecolumns("text", "text", "text", "text", "text", "text", "text")
|
||||
fs:table(x,y, w,h, name, function(add_row)
|
||||
add_row("Poster", "Type", "Item",
|
||||
"Description",
|
||||
"Wear", "Amount", "Rate")
|
||||
|
||||
local all_items = minetest.registered_items
|
||||
|
||||
for i, row in ipairs(results) do
|
||||
local def = all_items[row.Item] or {}
|
||||
fs(",", formlib.escape(row.Poster))
|
||||
fs(",", formlib.escape(row.Type))
|
||||
fs(",", formlib.escape(row.Item))
|
||||
fs(",", formlib.escape(def.description or "Unknown Item"))
|
||||
if row.Wear > 0 then
|
||||
fs(",", formlib.escape("-" .. math.ceil(100 * row.Wear / 65535) .. "%"))
|
||||
else
|
||||
fs(",---")
|
||||
local all_items = minetest.registered_items
|
||||
for i, row in ipairs(results) do
|
||||
local def = all_items[row.Item] or {}
|
||||
add_row(row.Poster, row.Type, row.Item,
|
||||
def.description or "Unknown Item",
|
||||
wear_string(row.Wear), row.Amount, row.Rate)
|
||||
end
|
||||
fs(",", formlib.escape(row.Amount))
|
||||
fs(",", formlib.escape(row.Rate))
|
||||
end
|
||||
|
||||
local sel_num = math.max(0, tonumber(selected) or 0)
|
||||
fs(";", sel_num + 1, "]")
|
||||
end, math.max(0, tonumber(selected) or 0) + 1)
|
||||
end
|
||||
|
||||
local function mk_main_market_fs(fs, p_name, state)
|
||||
@ -141,22 +141,13 @@ end
|
||||
local function mk_main_order_book_fs(fs, p_name, x, y, w, h, item_name)
|
||||
local order_book = exchange:order_book("", item_name)
|
||||
|
||||
fs("tablecolumns[text;text;text;text]")
|
||||
fs("table[", x, ",", y, ";", w, ",", h, ";", "order_book;")
|
||||
fs("Type,Rate,Wear,Amount")
|
||||
|
||||
for _,row in ipairs(order_book) do
|
||||
fs(",", formlib.escape(row.Type))
|
||||
fs(",", formlib.escape(row.Rate))
|
||||
if row.Wear > 0 then
|
||||
fs(",", formlib.escape(wear_string(row.Wear)))
|
||||
else
|
||||
fs(",---")
|
||||
fs:tablecolumns("text", "text", "text", "text")
|
||||
fs:table(x,y, w,h, "order_book", function(add_row)
|
||||
add_row("Type", "Rate", "Wear", "Amount")
|
||||
for _,row in ipairs(order_book) do
|
||||
add_row(row.Type, row.Rate, wear_string(row.Wear), row.Amount)
|
||||
end
|
||||
fs(",", formlib.escape(row.Amount))
|
||||
end
|
||||
|
||||
fs(";1]")
|
||||
end, 1)
|
||||
end
|
||||
|
||||
local function mk_main_buy_fs(fs, p_name, state)
|
||||
@ -167,14 +158,11 @@ local function mk_main_buy_fs(fs, p_name, state)
|
||||
fs:field(10.25,0.40, 2,1, "buy_amount", "Quantity", state.buy_amount, false)
|
||||
|
||||
local wear = wear_levels[state.buy_wear] or wear_levels[1]
|
||||
fs("dropdown[9,1;3;buy_wear;")
|
||||
local sep = nil
|
||||
for _,v in ipairs(wear_levels) do
|
||||
if sep then fs(sep) end
|
||||
fs:escape(v.text)
|
||||
sep = ","
|
||||
end
|
||||
fs(";", wear.index, "]")
|
||||
fs:dropdown(9,1, 3, "buy_wear", function(add_item)
|
||||
for _,v in ipairs(wear_levels) do
|
||||
add_item(v.text)
|
||||
end
|
||||
end, wear.index)
|
||||
|
||||
fs:field(9.35,2.40, 2.9,1, "buy_price", "Bid (ea.)", state.buy_price, false)
|
||||
|
||||
@ -241,14 +229,11 @@ local function mk_main_fs(fs, p_name, err_str, success)
|
||||
fs:size(12,10)
|
||||
fs:bgcolor("#606060", false)
|
||||
|
||||
fs("tabheader[0,0.65;tab;")
|
||||
local sep = nil
|
||||
for _,tab in ipairs(main_tabs) do
|
||||
if sep then fs(sep) end
|
||||
fs:escape(tab.text)
|
||||
sep = ","
|
||||
end
|
||||
fs(";", state.tab or 1, ";false;true]")
|
||||
fs:tabheader(0,0.65, "tab", function(add_tab)
|
||||
for _,tab in ipairs(main_tabs) do
|
||||
add_tab(tab.text)
|
||||
end
|
||||
end, state.tab or 1, false, true)
|
||||
|
||||
local bal = exchange:get_balance(p_name)
|
||||
fs:label(0,0.37, "Balance: " .. bal)
|
||||
|
158
formlib.lua
158
formlib.lua
@ -2,83 +2,163 @@ local formlib = {}
|
||||
local builder_methods = {}
|
||||
|
||||
function formlib.escape(x)
|
||||
return minetest.formspec_escape(tostring(x or ""))
|
||||
if x == nil then return "" end
|
||||
return minetest.formspec_escape(tostring(x))
|
||||
end
|
||||
|
||||
function formlib.bool(x)
|
||||
-- nil and false are returned as-is, everything else maps to true
|
||||
return x and true
|
||||
end
|
||||
|
||||
function builder_methods.append(fs, ...)
|
||||
for i=1,select("#", ...) do
|
||||
local x = select(i, ...)
|
||||
if x ~= nil then table.insert(fs, tostring(x)) end
|
||||
end
|
||||
return fs
|
||||
end
|
||||
|
||||
function builder_methods.escape(fs, ...)
|
||||
for _,x in ipairs({...}) do
|
||||
if x then fs(formlib.escape(x)) end
|
||||
for i=1,select("#", ...) do
|
||||
local x = select(i, ...)
|
||||
if x ~= nil then table.insert(fs, formlib.escape(x)) end
|
||||
end
|
||||
return fs
|
||||
end
|
||||
|
||||
function builder_methods.escape_list(fs, ...)
|
||||
for i=1,select("#", ...) do
|
||||
local x = select(i, ...)
|
||||
if i > 1 then fs(",") end
|
||||
fs:escape(x)
|
||||
end
|
||||
return fs
|
||||
end
|
||||
|
||||
function builder_methods.escape_groups(fs, ...)
|
||||
for i=1,select("#", ...) do
|
||||
local group = select(i, ...)
|
||||
if i > 1 then fs(";") end
|
||||
if type(group) == "table" then
|
||||
fs:escape_list(unpack(group))
|
||||
else
|
||||
fs:escape(group)
|
||||
end
|
||||
end
|
||||
return fs
|
||||
end
|
||||
|
||||
function builder_methods.element(fs, name, ...)
|
||||
return fs(name, "["):escape_groups(...):append("]")
|
||||
end
|
||||
|
||||
function builder_methods.size(fs, w,h, fixed)
|
||||
if fixed == false then
|
||||
fs("size[", w, ",", h, ",false]")
|
||||
elseif fixed then
|
||||
fs("size[", w, ",", h, ",true]")
|
||||
if fixed == nil then
|
||||
return fs:element("size", {w,h})
|
||||
else
|
||||
fs("size[", w, ",", h, "]")
|
||||
return fs:element("size", {w,h, formlib.bool(fixed)})
|
||||
end
|
||||
end
|
||||
|
||||
function builder_methods.bgcolor(fs, color, fullscreen)
|
||||
if fullscreen == false then
|
||||
fs("bgcolor[", formlib.escape(color), ";false]")
|
||||
elseif fullscreen then
|
||||
fs("bgcolor[", formlib.escape(color), ";true]")
|
||||
if fullscreen == nil then
|
||||
return fs:element("bgcolor", {color})
|
||||
else
|
||||
fs("bgcolor[", formlib.escape(color), "]")
|
||||
return fs:element("bgcolor", {color}, {formlib.bool(fullscreen)})
|
||||
end
|
||||
end
|
||||
|
||||
function builder_methods.list(fs, x,y, w,h, inv_loc, inv_list, start_idx)
|
||||
fs("list[", formlib.escape(inv_loc), ";", formlib.escape(inv_list), ";",
|
||||
x, ",", y, ";", w, ",", h, ";", formlib.escape(start_idx), "]")
|
||||
return fs:element("list", {inv_loc}, {inv_list}, {x,y}, {w,h}, {start_idx})
|
||||
end
|
||||
|
||||
function builder_methods.button(fs, x,y, w,h, name, text)
|
||||
fs("button[", x, ",", y, ";", w, ",", h, ";",
|
||||
formlib.escape(name), ";", formlib.escape(text), "]")
|
||||
return fs:element("button", {x,y}, {w,h}, {name}, {text})
|
||||
end
|
||||
|
||||
function builder_methods.item_image_button(fs, x,y, w,h, name, item, text)
|
||||
fs("item_image_button[", x, ",", y, ";", w, ",", h, ";",
|
||||
formlib.escape(item), ";", formlib.escape(name), ";",
|
||||
formlib.escape(text), "]")
|
||||
return fs:element("item_image_button", {x,y}, {w,h}, {item}, {name}, {text})
|
||||
end
|
||||
|
||||
function builder_methods.label(fs, x,y, text)
|
||||
fs("label[", x, ",", y, ";", formlib.escape(text), "]")
|
||||
return fs:element("label", {x,y}, {text})
|
||||
end
|
||||
|
||||
function builder_methods.field(fs, x,y, w,h, name, label, default, close_on_enter)
|
||||
fs("field[", x, ",", y, ";", w, ",", h, ";",
|
||||
formlib.escape(name), ";", formlib.escape(label), ";",
|
||||
formlib.escape(default), "]")
|
||||
|
||||
if close_on_enter == false then
|
||||
fs("field_close_on_enter[", formlib.escape(name), ";false]")
|
||||
fs:element("field", {x,y}, {w,h}, {name}, {label}, {default})
|
||||
if close_on_enter ~= nil then
|
||||
fs:element("field_close_on_enter", {name}, {formlib.bool(close_on_enter)})
|
||||
end
|
||||
end
|
||||
|
||||
function builder_methods.container(fs, x,y, sub_fn, ...)
|
||||
fs("container[", x, ",", y, "]")
|
||||
sub_fn(fs, ...)
|
||||
fs("container_end[]")
|
||||
return fs
|
||||
end
|
||||
|
||||
function builder_methods.box(fs, x,y, w,h, color)
|
||||
fs("box[", x, ",", y, ";", w, ",", h, ";", formlib.escape(color), "]")
|
||||
return fs:element("box", {x,y}, {w,h}, {color})
|
||||
end
|
||||
|
||||
function builder_methods.dropdown(fs, x,y, w, name, body_fn, selected_idx)
|
||||
fs("dropdown["):escape_groups({x,y}, {w}, {name}):append(";")
|
||||
local first = true
|
||||
local results = { body_fn(function(...)
|
||||
if first then first = false else fs(",") end
|
||||
fs:escape(...)
|
||||
end) }
|
||||
if selected_idx ~= nil then fs(";"):escape(selected_idx) end
|
||||
return fs("]"), unpack(results)
|
||||
end
|
||||
|
||||
function builder_methods.tabheader(fs, x,y, name, body_fn, current_tab, transparent, draw_border)
|
||||
fs("tabheader["):escape_groups({x,y}, {name}):append(";")
|
||||
local first = true
|
||||
local results = { body_fn(function(...)
|
||||
if first then first = false else fs(",") end
|
||||
fs:escape(...)
|
||||
end) }
|
||||
fs(";"):escape_groups({current_tab}, {formlib.bool(transparent)}, {formlib.bool(draw_border)})
|
||||
return fs("]"), unpack(results)
|
||||
end
|
||||
|
||||
function builder_methods.textlist(fs, x,y, w,h, name, body_fn, selected_idx, transparent)
|
||||
fs("textlist["):escape_groups({x,y}, {w,h}, {name}):append(";")
|
||||
local first = true
|
||||
local results = { body_fn(function(...)
|
||||
if first then first = false else fs(",") end
|
||||
fs:escape(...)
|
||||
end) }
|
||||
fs(";"):escape_groups({selected_idx}, {formlib.bool(transparent)})
|
||||
return fs("]"), unpack(results)
|
||||
end
|
||||
|
||||
function builder_methods.tableoptions(fs, ...)
|
||||
return fs:element("tableoptions", ...)
|
||||
end
|
||||
|
||||
function builder_methods.tablecolumns(fs, ...)
|
||||
return fs:element("tablecolumns", ...)
|
||||
end
|
||||
|
||||
function builder_methods.table(fs, x,y, w,h, name, body_fn, selected_idx)
|
||||
fs("table["):escape_groups({x,y}, {w,h}, {name}):append(";")
|
||||
local first = true
|
||||
local results = { body_fn(function(...)
|
||||
if first then first = false else fs(",") end
|
||||
fs:escape_list(...)
|
||||
end) }
|
||||
if selected_idx ~= nil then fs(";"):escape(selected_idx) end
|
||||
return fs("]"), unpack(results)
|
||||
end
|
||||
|
||||
function builder_methods.container(fs, x,y, sub_fn, ...)
|
||||
fs:element("container", {x,y})
|
||||
local results = { sub_fn(fs, ...) }
|
||||
return fs("container_end[]"), unpack(results)
|
||||
end
|
||||
|
||||
local builder_meta = {
|
||||
__metatable = "protected",
|
||||
__index = builder_methods,
|
||||
__call = function(fs, ...)
|
||||
for _,x in ipairs({...}) do
|
||||
if x then table.insert(fs, tostring(x)) end
|
||||
end
|
||||
end,
|
||||
__call = builder_methods.append,
|
||||
__tostring = table.concat,
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user