summaryrefslogtreecommitdiff
path: root/streetsmod/libs/smartfs
diff options
context:
space:
mode:
authorVanessa Ezekowitz <vanessaezekowitz@gmail.com>2016-04-01 21:00:20 -0400
committerVanessa Ezekowitz <vanessaezekowitz@gmail.com>2016-04-01 21:10:04 -0400
commit888b0ebfec8c2eff9015163549a7e47443cb8665 (patch)
tree915080159bfaa6ba6e226087c7ce0e8d5464b518 /streetsmod/libs/smartfs
parentda66780a569712c23ae4f2996cfb4608a9f9d69d (diff)
downloaddreambuilder_modpack-888b0ebfec8c2eff9015163549a7e47443cb8665.tar
dreambuilder_modpack-888b0ebfec8c2eff9015163549a7e47443cb8665.tar.gz
dreambuilder_modpack-888b0ebfec8c2eff9015163549a7e47443cb8665.tar.bz2
dreambuilder_modpack-888b0ebfec8c2eff9015163549a7e47443cb8665.tar.xz
dreambuilder_modpack-888b0ebfec8c2eff9015163549a7e47443cb8665.zip
"explode" all modpacks into their individual components
(you can't have a modpack buried inside a modpack)
Diffstat (limited to 'streetsmod/libs/smartfs')
-rw-r--r--streetsmod/libs/smartfs/README.md88
-rw-r--r--streetsmod/libs/smartfs/api.md107
-rw-r--r--streetsmod/libs/smartfs/depends.txt2
-rw-r--r--streetsmod/libs/smartfs/example.lua66
-rw-r--r--streetsmod/libs/smartfs/example.smartfs1
-rw-r--r--streetsmod/libs/smartfs/init.lua2
-rw-r--r--streetsmod/libs/smartfs/smartfs.lua760
7 files changed, 1026 insertions, 0 deletions
diff --git a/streetsmod/libs/smartfs/README.md b/streetsmod/libs/smartfs/README.md
new file mode 100644
index 0000000..df0e166
--- /dev/null
+++ b/streetsmod/libs/smartfs/README.md
@@ -0,0 +1,88 @@
+smartfs
+=======
+
+This mod provides a 2nd generation way of creating forms - this means that the modder does not need to worry about complex formspec strings
+
+* Expandable: you can register your own elements to use on the form.
+* Easy event handling: use binding to handle events.
+* New elements: Includes a toggle button
+
+License: WTFPL
+To install this library, place the smartfs.lua file in your mod and then include it (dofile).
+There is an init.lua file in the download that shows you how to do this.
+
+#Using Smart Formspec
+Smartfs provides 2nd generation Minetest forms to replace clunky formspec strings. Each smartfs form is a container filled with GUI elements. A number of default elements are included with smartfs, but modders can also define their own custom elements. This document describes the basic usage of the smartfs API.
+
+##Installation
+Smartfs can be used as a library or a mod.
+
+To use smartfs as a library, copy the smartfs.lua file to your mod folder and add
+ dofile(minetest.get\_modpath(minetest.get\_current\_modname()).."/smartfs.lua")
+to the top of any files that use it.
+
+To use smartfs as a mod, add it to your game's mods folder or to the user mods folder and enable it.
+
+## Creating and showing forms
+A form is a rectangular area of the screen upon which all elements are placed. Use the smartfs.create() function to create a new form. This function takes two arguments and returns a form object.
+
+The first argument is a unique string that identifies the form. The second argument is a function that should take a single argument called state which is used to set form properties like size and background color. State also has constructors for all form elements and can be used with state:element_name. Below is a quick example.
+
+ myform = smartfs.create("My Form",function(state)
+ --sets the form's size
+ -- (width, hieght)
+ state:size(5,5)
+
+ --creates a label and places it on the form
+ --(x-pos, y-pos, name, text)
+ state:label(3,3,"label1", "A label!")
+ end)
+
+Forms can be shown to the player by using the show(target) function. The target argument is the name of the player that will see the form.
+
+ myform:show("singleplayer")
+
+Here is a list of steps the library takes.
+* You create a new form using smartfs.create().
+* The form is registered and stored for later use.
+* You show a form to a player using the myform:show()
+* The state is created and stored.
+* The function in smartfs.create runs and creates the elements.
+* The form is displayed to the player.
+
+## Modifying Elements
+Elements have functions of the form element:function(args) where you need to have access to the element object.
+
+You can get the element object by assigning a variable to its creation function like so:
+
+ local button1 = state:button(0,0, 1,4, "btn1", "A button")
+ --button1 is now a table representing the button
+
+You can also get the element by using state:get(name). The example below will retrieve a button with the name "btn1":
+
+ button1 = state:get("btn1")
+ --or
+ state:get("btn1"):onClick(your\_onclick\_function
+
+Both of these methods should be used inside the form creation callback function, the function you pass to smartfs.create, or in event callbacks.
+
+Now that you have located your element you can modify it.
+
+ button1:setPos(4,0)
+
+## Inventory Support
+Smartfs supports adding a button to Inventory+ or Unified Inventory which will open one of your own custom forms. Use the smartfs.add\_to\_inventory(form, icon, title) function where form is the smartfs form linked to by the button, icon is the button image (only for unified inventory), and title is the button text (only for inventory+).
+
+ smartfs.add_to_inventory(form, icon, title)
+
+## Dynamic forms
+Dynamic forms allow you to make a form without having to register it before the game finished loading.
+
+ local state = smartfs.dynamic("smartfs:dyn_form", name)
+ state:load(minetest.get_modpath("smartfs").."/example.smartfs")
+ state:get("btn"):click(function(self,state)
+ print("Button clicked!")
+ end)
+ state:show()
+
+Make sure you call state:show()
diff --git a/streetsmod/libs/smartfs/api.md b/streetsmod/libs/smartfs/api.md
new file mode 100644
index 0000000..69e3f47
--- /dev/null
+++ b/streetsmod/libs/smartfs/api.md
@@ -0,0 +1,107 @@
+#Full API
+##Smartfs
+* smartfs( name ) - returns the form regisered with the name 'name'
+* smartfs.create( name,function ) - creates a new form and adds elements to it by running the function. Use before Minetest loads. (like minetest.register_node)
+* smartfs.element( name, data ) - creates a new element type.
+* smartfs.dynamic( formname, playername ) - creates a dynamic form. Returns state. See example.lua for example. Remember to call state:show()
+* smartfs.add\_to\_inventory(form, icon, title) - Adds a form to an installed advanced inventory. Returns true on success.
+* smartfs.inventory_mod() - Returns the name of an installed and supported inventory mod that will be used above, or null.
+* smartfs.override\_load\_checks() - Allows you to use smartfs.create after the game loads. Not recommended!
+
+##Form
+* form:show( playername [, parameters] ) - shows the form to a player. See state.param.
+* form.name - the name of the form.
+
+##State
+
+### Methods
+* state:size( width,height ) - sets the forms width and height.
+* state:get( name ) - gets an element by name.
+* state:show() - reshows the form to the player.
+* state:close() - closes the form (does not work yet, due to no MT api support).
+* state:load( filepath ) - Loads elements from a file.
+* state:save( filepath ) - Saves elements to a file.
+* state:button( x,y,w,h,name,text [, exit_on_click] ) - create a new button at x,y with name and caption (text)
+ * ^ optional: exit_on_click - set to true to exit the form when the button is clicked. ( Also see button.setClose() )
+* state:toggle( x,y,w,h,name,list ) - create a new toggle button at x,y with name and possible list of values
+* state:label( x,y,name,text ) - create a new label at x,y with name and caption (text)
+* state:field( x,y,w,h,name,label ) - create a new field at x,y with label
+ * state:pwdfield( x,y,w,h,name,label ) - create a password field
+ * state:textarea( x,y,w,h,name,label ) - create a new textarea
+* state:image( x,y,w,h,name,imagepath ) - create an image box.
+* state:inventory( x,y,w,h,name ) - create an inventory listing (use 'main' as name for the main player inventory)
+* state:checkbox( x,y,name,label,selected ) - create a check box.
+* state:element( element_type, data ) - Semi-private, create an element with type and data.
+
+### Variables
+* state.player - The name of the player.
+* state.param - The parameters supplied by form:show.
+* state.def - The form definition.
+* state.is_inv - Boolean which is true if this form is being shown as an inventory.
+
+##Button
+* element:setPosition( x,y ) - change the position
+* element:getPosition() - get the current position
+* element:setSize( w,h ) - set the size
+* element:getSize() - get the size
+* element:setText( text ) - set the caption of the button
+* element:getText() - get the caption of the button
+* element:setImage( filename ) - sets the background of the button
+* element:getImage() - get the background filename of the button
+* element:click( func(self,state) ) - specify a function to run when the button is clicked
+
+##Toggle Button
+* element:setPosition( x,y ) - change the position
+* element:getPosition() - get the current position
+* element:setSize( w,h ) - set the size
+* element:getSize() - get the size
+* element:getText() - get the text of the toggle option
+* element:setId( filename ) - sets the selected id
+* element:getId() - get the selected id
+* element:onToggle( func(self,state) ) - specify a function to run when the value if toggled
+
+##Label
+* element:setPosition( x,y ) - change the position
+* element:getPosition() - get the current position
+* element:setText( text ) - set the caption of the label
+* element:getText() - get the caption of the label
+
+##Field and Text Area
+* element:setPosition( x,y ) - change the position
+* element:getPosition() - get the current position
+* element:setSize( w,h ) - set the size
+* element:getSize() - get the size
+* element:setText( text ) - set the caption of the button
+* element:getText() - get the caption of the field
+* element:setImage( filename ) - sets the background of the field
+* element:getImage() - get the background filename of the field
+
+##List box
+* element:onClick( func(self,state,idx) ) - function to run when listbox item idx is clicked
+* element:onDoubleClick( func(self,state,idx) ) - function to run when listbox item idx is double clicked
+* element:setPosition( x,y ) - set the position
+* element:getPosition() - returns {x=x, y=y}
+* element:setSize( w,h ) - set the size
+* element:getSize() - gets the size {w=w, h=h}
+* element:addItem( item ) - appends and item
+* element:removeItem( idx ) - remove item
+* element:popItem() - removes last item and returns
+
+##Inventory listing
+* element:setPosition( x,y ) - set the position
+* element:getPosition() - returns {x=x, y=y}
+* element:setSize( w,h ) - set the size
+* element:getSize() - gets the size {w=w, h=h}
+* element:setLocation( location ) - set a custom inventory location or nil for the default (current_player)
+ * element:usePosition( position ) - use a node metadata attached inventory of the node at the given positon
+ * element:useDetached( name ) - use a detached inventory with the given name
+ * element:usePlayer( name ) - use a player inventory other than the current player
+* element:getLocation() - returns the inventory location (default: current_player)
+* element:setIndex( index ) - set the inventory starting index
+* element:getIndex() - returns the inventory starting index
+
+##Custom Code
+* element:onSubmit( func(self) ) - on form submit
+* element:onBuild( func(self) ) - run every time form is shown. You can set code from here
+* element:setCode( code ) - set the formspec code
+* element:getCode( code ) - get the formspec code
diff --git a/streetsmod/libs/smartfs/depends.txt b/streetsmod/libs/smartfs/depends.txt
new file mode 100644
index 0000000..4893cdc
--- /dev/null
+++ b/streetsmod/libs/smartfs/depends.txt
@@ -0,0 +1,2 @@
+unified_inventory?
+inventory_plus?
diff --git a/streetsmod/libs/smartfs/example.lua b/streetsmod/libs/smartfs/example.lua
new file mode 100644
index 0000000..935dd70
--- /dev/null
+++ b/streetsmod/libs/smartfs/example.lua
@@ -0,0 +1,66 @@
+dofile(minetest.get_modpath("smartfs").."/smartfs.lua")
+
+s = smartfs.create("smartfs:form",function(state)
+ state:size(10,7)
+ state:label(2,0,"lbl","SmartFS example formspec!")
+ state:field(7,1,3,1,"txt","Textbox")
+ state:image(0,0,2,2,"img","default_stone.png")
+ state:toggle(0,2,3,1,"tg",{"plenty..","of..","custom..","elements"})
+ state:checkbox(2,1,"c","Easy code",true)
+ local res = "smartfs.create(\"smartfs:form\",function(state)\n"
+ res = res .. "\tstate:size(10,7)\n"
+ res = res .. "\tstate:label(2,0,\"lbl\",\"SmartFS example formspec!\")\n"
+ res = res .. "\tstate:field(7,1,3,1,\"txt\",\"Textbox\")\n"
+ res = res .. "\tstate:image(0,0,2,2,\"img\",\"default_stone.png\")\n"
+ res = res .. "\tstate:toggle(0,2,3,1,\"tg\",{\"plenty..\",\"of..\",\"custom..\",\"elements\"})\n"
+ res = res .. "\tstate:checkbox(2,1,\"c\",\"Easy code\",true)\n"
+ res = res .. "end)"
+ state:textarea(1,3.5,9,4,"ta","Code:"):setText(res)
+ return true
+end)
+
+l = smartfs.create("smartfs:load",function(state)
+ state:load(minetest.get_modpath("smartfs").."/example.smartfs")
+ state:get("btn"):click(function(self,state)
+ print("Button clicked!")
+ end)
+ return true
+end)
+
+smartfs.add_to_inventory(l,"icon.png","SmartFS")
+
+minetest.register_chatcommand("sfs_s", {
+ params = "",
+ description = "SmartFS test formspec 1: basics",
+ func = function(name, param)
+ s:show(name)
+ end,
+})
+minetest.register_chatcommand("sfs_l", {
+ params = "",
+ description = "SmartFS test formspec 2: loading",
+ func = function(name, param)
+ l:show(name)
+ end,
+})
+
+minetest.register_chatcommand("sfs_d", {
+ params = "",
+ description = "SmartFS test formspec 3: dynamic",
+ func = function(name, param)
+ local state = smartfs.dynamic("smartfs:dyn_form", name)
+ state:load(minetest.get_modpath("smartfs").."/example.smartfs")
+ state:get("btn"):click(function(self,state)
+ print("Button clicked!")
+ end)
+ state:show()
+ end,
+})
+
+minetest.register_chatcommand("sfs_lc", {
+ params = "",
+ description = "SmartFS test formspec 4: smartfs.create error catching",
+ func = function(name, param)
+ smartfs.create("asdinas",function() end)
+ end
+})
diff --git a/streetsmod/libs/smartfs/example.smartfs b/streetsmod/libs/smartfs/example.smartfs
new file mode 100644
index 0000000..cbbaabf
--- /dev/null
+++ b/streetsmod/libs/smartfs/example.smartfs
@@ -0,0 +1 @@
+return { ["ele"] = { ["c"] = { ["pos"] = { ["y"] = 1, ["x"] = 1 }, ["label"] = "Check", ["value"] = true, ["type"] = "checkbox", ["name"] = "c" }, ["btn"] = { ["pos"] = { ["y"] = 2, ["x"] = 1 }, ["size"] = { ["h"] = 1, ["w"] = 1 }, ["value"] = "Button", ["type"] = "button", ["name"] = "btn" } }, ["size"] = { ["h"] = 3, ["w"] = 5 } } \ No newline at end of file
diff --git a/streetsmod/libs/smartfs/init.lua b/streetsmod/libs/smartfs/init.lua
new file mode 100644
index 0000000..b2aaa29
--- /dev/null
+++ b/streetsmod/libs/smartfs/init.lua
@@ -0,0 +1,2 @@
+dofile(minetest.get_modpath("smartfs").."/smartfs.lua")
+--dofile(minetest.get_modpath("smartfs").."/example.lua")
diff --git a/streetsmod/libs/smartfs/smartfs.lua b/streetsmod/libs/smartfs/smartfs.lua
new file mode 100644
index 0000000..dfa0819
--- /dev/null
+++ b/streetsmod/libs/smartfs/smartfs.lua
@@ -0,0 +1,760 @@
+---------------------------
+-- SmartFS: Smart Formspecs
+-- by Rubenwardy
+---------------------------
+
+smartfs = {
+ _fdef = {},
+ _edef = {},
+ opened = {},
+ inv = {}
+}
+
+-- the smartfs() function
+function smartfs.__call(self, name)
+ return smartfs._fdef[name]
+end
+
+-- Register forms and elements
+function smartfs.create(name,onload)
+ if smartfs._fdef[name] then
+ error("SmartFS - (Error) Form "..name.." already exists!")
+ end
+ if smartfs.loaded and not smartfs._loaded_override then
+ error("SmartFS - (Error) Forms should be declared while the game loads.")
+ end
+
+ smartfs._fdef[name] = {
+ _reg = onload,
+ name = name,
+ show = smartfs._show_
+ }
+
+ return smartfs._fdef[name]
+end
+function smartfs.override_load_checks()
+ smartfs._loaded_override = true
+end
+
+minetest.after(0, function()
+ smartfs.loaded = true
+end)
+function smartfs.dynamic(name,player)
+ if not smartfs._dynamic_warned then
+ smartfs._dynamic_warned = true
+ print("SmartFS - (Warning) On the fly forms are being used. May cause bad things to happen")
+ end
+ local state = smartfs._makeState_({name=name},player,nil,false)
+ state.show = state._show_
+ smartfs.opened[player] = state
+ return state
+end
+function smartfs.element(name,data)
+ if smartfs._edef[name] then
+ error("SmartFS - (Error) Element type "..name.." already exists!")
+ end
+ smartfs._edef[name] = data
+ return smartfs._edef[name]
+end
+
+function smartfs.inventory_mod()
+ if unified_inventory then
+ return "unified_inventory"
+ elseif inventory_plus then
+ return "inventory_plus"
+ else
+ return nil
+ end
+end
+
+function smartfs.add_to_inventory(form,icon,title)
+ if unified_inventory then
+ unified_inventory.register_button(form.name, {
+ type = "image",
+ image = icon,
+ })
+ unified_inventory.register_page(form.name, {
+ get_formspec = function(player, formspec)
+ local name = player:get_player_name()
+ local opened = smartfs._show_(form, name, nil, true)
+ return {formspec = opened:_getFS_(false)}
+ end
+ })
+ return true
+ elseif inventory_plus then
+ minetest.register_on_joinplayer(function(player)
+ inventory_plus.register_button(player, form.name, title)
+ end)
+ minetest.register_on_player_receive_fields(function(player, formname, fields)
+ if formname == "" and fields[form.name] then
+ local name = player:get_player_name()
+ local opened = smartfs._show_(form, name, nil, true)
+ inventory_plus.set_inventory_formspec(player, opened:_getFS_(true))
+ end
+ end)
+ return true
+ else
+ return false
+ end
+end
+
+function smartfs._makeState_(form,player,params,is_inv)
+ return {
+ _ele = {},
+ def = form,
+ player = player,
+ param = params,
+ is_inv = is_inv,
+ get = function(self,name)
+ return self._ele[name]
+ end,
+ close = function(self)
+ self.closed = true
+ end,
+ size = function(self,w,h)
+ self._size = {w=w,h=h}
+ end,
+ _getFS_ = function(self,size)
+ local res = ""
+ if self._size and size then
+ res = "size["..self._size.w..","..self._size.h.."]"
+ end
+ for key,val in pairs(self._ele) do
+ res = res .. val:build()
+ end
+ return res
+ end,
+ _show_ = function(self)
+ if self.is_inv then
+ if unified_inventory then
+ unified_inventory.set_inventory_formspec(minetest.get_player_by_name(self.player), self.def.name)
+ elseif inventory_plus then
+ inventory_plus.set_inventory_formspec(minetest.get_player_by_name(self.player), self:_getFS_(true))
+ end
+ else
+ local res = self:_getFS_(true)
+ minetest.show_formspec(player,form.name,res)
+ end
+ end,
+ load = function(self,file)
+ local file = io.open(file, "r")
+ if file then
+ local table = minetest.deserialize(file:read("*all"))
+ if type(table) == "table" then
+ if table.size then
+ self._size = table.size
+ end
+ for key,val in pairs(table.ele) do
+ self:element(val.type,val)
+ end
+ return true
+ end
+ end
+ return false
+ end,
+ save = function(self,file)
+ local res = {ele={}}
+
+ if self._size then
+ res.size = self._size
+ end
+
+ for key,val in pairs(self._ele) do
+ res.ele[key] = val.data
+ end
+
+ local file = io.open(file, "w")
+ if file then
+ file:write(minetest.serialize(res))
+ file:close()
+ return true
+ end
+ return false
+ end,
+ button = function(self,x,y,w,h,name,text,exitf)
+ if exitf == nil then exitf = false end
+ return self:element("button",{pos={x=x,y=y},size={w=w,h=h},name=name,value=text,closes=exitf})
+ end,
+ label = function(self,x,y,name,text)
+ return self:element("label",{pos={x=x,y=y},name=name,value=text})
+ end,
+ toggle = function(self,x,y,w,h,name,list)
+ return self:element("toggle",{pos={x=x,y=y},size={w=w,h=h},name=name,id=1,list=list})
+ end,
+ field = function(self,x,y,w,h,name,label)
+ return self:element("field",{pos={x=x,y=y},size={w=w,h=h},name=name,value="",label=label})
+ end,
+ pwdfield = function(self,x,y,w,h,name,label)
+ local res = self:element("field",{pos={x=x,y=y},size={w=w,h=h},name=name,value="",label=label})
+ res:isPassword(true)
+ return res
+ end,
+ textarea = function(self,x,y,w,h,name,label)
+ local res = self:element("field",{pos={x=x,y=y},size={w=w,h=h},name=name,value="",label=label})
+ res:isMultiline(true)
+ return res
+ end,
+ image = function(self,x,y,w,h,name,img)
+ return self:element("image",{pos={x=x,y=y},size={w=w,h=h},name=name,value=img})
+ end,
+ checkbox = function(self,x,y,name,label,selected)
+ return self:element("checkbox",{pos={x=x,y=y},name=name,value=selected,label=label})
+ end,
+ listbox = function(self,x,y,w,h,name)
+ return self:element("list", { pos={x=x,y=y}, size={w=w,h=h}, name=name })
+ end,
+ inventory = function(self,x,y,w,h,name)
+ return self:element("inventory", { pos={x=x,y=y}, size={w=w,h=h}, name=name })
+ end,
+ element = function(self,typen,data)
+ local type = smartfs._edef[typen]
+
+ if not type then
+ error("Element type "..typen.." does not exist!")
+ end
+
+ if self._ele[data.name] then
+ error("Element "..data.name.." already exists")
+ end
+ data.type = typen
+
+ local ele = {
+ name = data.name,
+ root = self,
+ data = data,
+ remove = function(self)
+ self.root._ele[self.name] = nil
+ end
+ }
+
+ for key,val in pairs(type) do
+ ele[key] = val
+ end
+
+ self._ele[data.name] = ele
+
+ return self._ele[data.name]
+ end
+ }
+end
+
+-- Show a formspec to a user
+function smartfs._show_(form, player, params, is_inv)
+ local state = smartfs._makeState_(form, player, params, is_inv)
+ state.show = state._show_
+ if form._reg(state)~=false then
+ if not is_inv then
+ smartfs.opened[player] = state
+ state:_show_()
+ else
+ smartfs.inv[player] = state
+ end
+ end
+ return state
+end
+
+-- Receive fields from formspec
+local function _sfs_recieve_(state,name,fields)
+ if (fields.quit == "true") then
+ if not state.is_inv then
+ smartfs.opened[name] = nil
+ end
+ return true
+ end
+
+ for key,val in pairs(fields) do
+ if state._ele[key] then
+ state._ele[key].data.value = val
+ end
+ end
+ for key,val in pairs(state._ele) do
+ if val.submit then
+ if (val:submit(fields)==true) then
+ return true
+ end
+ end
+ end
+ if state.closed ~= true then
+ state:_show_()
+ else
+ minetest.show_formspec(name,"","size[5,1]label[0,0;Formspec closing not yet created!]")
+ if not state.is_inv then
+ smartfs.opened[name] = nil
+ end
+ end
+ return true
+end
+
+minetest.register_on_player_receive_fields(function(player, formname, fields)
+ local name = player:get_player_name()
+ if smartfs.opened[name] and not smartfs.opened[name].is_inv then
+ if smartfs.opened[name].def.name == formname then
+ local state = smartfs.opened[name]
+ return _sfs_recieve_(state,name,fields)
+ else
+ smartfs.opened[name] = nil
+ end
+ elseif smartfs.inv[name] and smartfs.inv[name].is_inv then
+ local state = smartfs.inv[name]
+ _sfs_recieve_(state,name,fields)
+ end
+ return false
+end)
+
+
+-----------------------------------------------------------------
+------------------------- ELEMENTS ----------------------------
+-----------------------------------------------------------------
+
+smartfs.element("button",{
+ build = function(self)
+ if self.data.img then
+ return "image_button["..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.data.size.w..","..self.data.size.h..
+ ";"..
+ self.data.img..
+ ";"..
+ self.name..
+ ";"..
+ self.data.value..
+ "]"
+ else
+ if self.data.closes then
+ return "button_exit["..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.data.size.w..","..self.data.size.h..
+ ";"..
+ self.name..
+ ";"..
+ self.data.value..
+ "]"
+ else
+ return "button["..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.data.size.w..","..self.data.size.h..
+ ";"..
+ self.name..
+ ";"..
+ self.data.value..
+ "]"
+ end
+ end
+ end,
+ submit = function(self,fields,state)
+ if fields[self.name] and self._click then
+ self:_click(self.root)
+ end
+
+ if self.data.closes then
+ return true
+ end
+ end,
+ setPosition = function(self,x,y)
+ self.data.pos = {x=x,y=y}
+ end,
+ getPosition = function(self,x,y)
+ return self.data.pos
+ end,
+ setSize = function(self,w,h)
+ self.data.size = {w=w,h=h}
+ end,
+ getSize = function(self,x,y)
+ return self.data.size
+ end,
+ onClick = function(self,func)
+ self._click = func
+ end,
+ click = function(self,func)
+ self._click = func
+ end,
+ setText = function(self,text)
+ self.data.value = text
+ end,
+ getText = function(self)
+ return self.data.value
+ end,
+ setImage = function(self,image)
+ self.data.img = image
+ end,
+ getImage = function(self)
+ return self.data.img
+ end,
+ setClose = function(self,bool)
+ self.data.closes = bool
+ end
+})
+
+smartfs.element("toggle",{
+ build = function(self)
+ return "button["..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.data.size.w..","..self.data.size.h..
+ ";"..
+ self.name..
+ ";"..
+ self.data.list[self.data.id]..
+ "]"
+ end,
+ submit = function(self,fields)
+ if fields[self.name] then
+ self.data.id = self.data.id + 1
+ if self.data.id > #self.data.list then
+ self.data.id = 1
+ end
+ if self._tog then
+ self:_tog(self.root)
+ end
+ end
+ end,
+ onToggle = function(self,func)
+ self._tog = func
+ end,
+ setPosition = function(self,x,y)
+ self.data.pos = {x=x,y=y}
+ end,
+ getPosition = function(self,x,y)
+ return self.data.pos
+ end,
+ setSize = function(self,w,h)
+ self.data.size = {w=w,h=h}
+ end,
+ getSize = function(self,x,y)
+ return self.data.size
+ end,
+ setId = function(self,id)
+ self.data.id = id
+ end,
+ getId = function(self)
+ return self.data.id
+ end,
+ getText = function(self)
+ return self.data.list[self.data.id]
+ end
+})
+
+smartfs.element("label",{
+ build = function(self)
+ return "label["..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.data.value..
+ "]"
+ end,
+ setPosition = function(self,x,y)
+ self.data.pos = {x=x,y=y}
+ end,
+ getPosition = function(self,x,y)
+ return self.data.pos
+ end,
+ setText = function(self,text)
+ self.data.value = text
+ end,
+ getText = function(self)
+ return self.data.value
+ end
+})
+
+smartfs.element("field",{
+ build = function(self)
+ if self.data.ml then
+ return "textarea["..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.data.size.w..","..self.data.size.h..
+ ";"..
+ self.name..
+ ";"..
+ self.data.label..
+ ";"..
+ self.data.value..
+ "]"
+ elseif self.data.pwd then
+ return "pwdfield["..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.data.size.w..","..self.data.size.h..
+ ";"..
+ self.name..
+ ";"..
+ self.data.label..
+ "]"
+ else
+ return "field["..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.data.size.w..","..self.data.size.h..
+ ";"..
+ self.name..
+ ";"..
+ self.data.label..
+ ";"..
+ self.data.value..
+ "]"
+ end
+ end,
+ setPosition = function(self,x,y)
+ self.data.pos = {x=x,y=y}
+ end,
+ getPosition = function(self,x,y)
+ return self.data.pos
+ end,
+ setSize = function(self,w,h)
+ self.data.size = {w=w,h=h}
+ end,
+ getSize = function(self,x,y)
+ return self.data.size
+ end,
+ setText = function(self,text)
+ self.data.value = text
+ end,
+ getText = function(self)
+ return self.data.value
+ end,
+ isPassword = function(self,bool)
+ self.data.pwd = bool
+ end,
+ isMultiline = function(self,bool)
+ self.data.ml = bool
+ end
+})
+
+smartfs.element("image",{
+ build = function(self)
+ return "image["..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.data.size.w..","..self.data.size.h..
+ ";"..
+ self.data.value..
+ "]"
+ end,
+ setPosition = function(self,x,y)
+ self.data.pos = {x=x,y=y}
+ end,
+ getPosition = function(self,x,y)
+ return self.data.pos
+ end,
+ setSize = function(self,w,h)
+ self.data.size = {w=w,h=h}
+ end,
+ getSize = function(self,x,y)
+ return self.data.size
+ end,
+ setImage = function(self,text)
+ self.data.value = text
+ end,
+ getImage = function(self)
+ return self.data.value
+ end
+})
+
+smartfs.element("checkbox",{
+ build = function(self)
+ if self.data.value then
+ return "checkbox["..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.name..
+ ";"..
+ self.data.label..
+ ";true]"
+ else
+ return "checkbox["..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.name..
+ ";"..
+ self.data.label..
+ ";false]"
+ end
+ end,
+ setPosition = function(self,x,y)
+ self.data.pos = {x=x,y=y}
+ end,
+ getPosition = function(self,x,y)
+ return self.data.pos
+ end,
+ setSize = function(self,w,h)
+ self.data.size = {w=w,h=h}
+ end,
+ getSize = function(self,x,y)
+ return self.data.size
+ end,
+ setText = function(self,text)
+ self.data.value = text
+ end,
+ getText = function(self)
+ return self.data.value
+ end
+})
+
+smartfs.element("list",{
+ build = function(self)
+ local listformspec = "textlist["..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.data.size.w..","..self.data.size.h..
+ ";"..
+ self.data.name..
+ ";"
+
+ --loop through the list's items and add them to the formspec
+ if not self.data.items then
+ self.data.items = {" "}
+ end
+ for i,value in ipairs(self.data.items) do
+ listformspec = listformspec..value..","
+ end
+ listformspec = string.sub(listformspec, 0, -2) --removes extra ,
+ --close out the list items section
+ listformspec = listformspec..";"
+
+ --TODO support selected idx and transparency
+
+ --close formspec definition and return formspec
+ listformspec = listformspec.."]"
+ return listformspec
+ end,
+ submit = function(self,fields)
+ if fields[self.name] then
+ local _type = string.sub(fields[self.data.name],1,3)
+ local index = string.sub(fields[self.data.name],5)
+ if _type == "CHG" and self._click then
+ self:_click(self.root, index)
+ elseif _type == "DCL" and self._doubleClick then
+ self:_doubleClick(self.root, index)
+ end
+ end
+ end,
+ onClick = function(self, func)
+ self._click = func
+ end,
+ click = function(self, func)
+ self._click = func
+ end,
+ onDoubleClick = function(self, func)
+ self._doubleClick = func
+ end,
+ doubleclick = function(self, func)
+ self._doubleClick = func
+ end,
+ setPosition = function(self,x,y)
+ self.data.pos = {x=x,y=y}
+ end,
+ getPosition = function(self,x,y)
+ return self.data.pos
+ end,
+ setSize = function(self,w,h)
+ self.data.size = {w=w,h=h}
+ end,
+ getSize = function(self,x,y)
+ return self.data.size
+ end,
+ addItem = function(self, item)
+ if not self.data.items then
+ self.data.items = {" "}
+ end
+ table.insert(self.data.items, item)
+ end,
+ removeItem = function(self,idx)
+ if not self.data.items then
+ self.data.items = {" "}
+ end
+ table.remove(self.data.items,idx)
+ end,
+ popItem = function(self)
+ if not self.data.items then
+ self.data.items = {" "}
+ end
+ local item = self.data.items[#self.data.items]
+ table.remove(self.data.items)
+ return item
+ end
+})
+
+smartfs.element("inventory",{
+ build = function(self)
+ return "list["..
+ (self.data.location or "current_player") ..
+ ";"..
+ self.name..
+ ";"..
+ self.data.pos.x..","..self.data.pos.y..
+ ";"..
+ self.data.size.w..","..self.data.size.h..
+ ";"..
+ (self.data.index or "") ..
+ "]"
+ end,
+ setPosition = function(self,x,y)
+ self.data.pos = {x=x,y=y}
+ end,
+ getPosition = function(self,x,y)
+ return self.data.pos
+ end,
+ setSize = function(self,w,h)
+ self.data.size = {w=w,h=h}
+ end,
+ getSize = function(self,x,y)
+ return self.data.size
+ end,
+ -- available inventory locations
+ -- "current_player": Player to whom the menu is shown
+ -- "player:<name>": Any player
+ -- "nodemeta:<X>,<Y>,<Z>": Any node metadata
+ -- "detached:<name>": A detached inventory
+ -- "context" does not apply to smartfs, since there is no node-metadata as context available
+ setLocation = function(self,location)
+ self.data.location = location
+ end,
+ getLocation = function(self)
+ return self.data.location or "current_player"
+ end,
+ usePosition = function(self, pos)
+ self.data.location = string.format("nodemeta:%d,%d,%d", pos.x, pos.y, pos.z)
+ end,
+ usePlayer = function(self, name)
+ self.data.location = "player:" .. name
+ end,
+ useDetached = function(self, name)
+ self.data.location = "detached:" .. name
+ end,
+ setIndex = function(self,index)
+ self.data.index = index
+ end,
+ getIndex = function(self)
+ return self.data.index
+ end
+})
+
+smartfs.element("code",{
+ build = function(self)
+ if self._build then
+ self:_build()
+ end
+
+ return self.data.code
+ end,
+ submit = function(self,fields)
+ if self._sub then
+ self:_sub(fields)
+ end
+ end,
+ onSubmit = function(self,func)
+ self._sub = func
+ end,
+ onBuild = function(self,func)
+ self._build = func
+ end,
+ setCode = function(self,code)
+ self.data.code = code
+ end,
+ getCode = function(self)
+ return self.data.code
+ end
+})