Code
--[[
===================================
* Option Dialogs
* Original Author: Brow42
* Version 1.0 Jan. 6 2012
* This allows you to define a dialog with a table instead of
* explicit function calls, set its values with another table,
* and read its values into yet a third table.
* A self-contained function for text-only message dialogs is
* included. This is good for help and error messages.
* New functions:
* dialog.AddFromTable(dialog,field table, data table)
* dialog.ReadFields(dialog,field table, data table)
* dialog.MessageBox(text or text table,title text,okay button text, cancel button text)
--]]
-- =================================== Begin Defaults
option={}
option.fuze = true
option.bandstr = 3.0
option.range = {} -- only segments in this range will be banded { low, high }
-- ================================== End Defaults
-- ================================== Begin New Dialog Library Functions
--[[
Throws up a dialog containing just text, provided as a string or table
of strings in the first argument. Title and buttons are optional. Return
value is 1 if the first button is clicked and 0 if the second button is clicked
or the window is closed.
--]]
function dialog.MessageBox(msg,title,buttontext1, buttontext0)
title = title or ''
local d = dialog.CreateDialog(title)
if type(msg) == 'string' then d['1'] = dialog.AddLabel(msg)
else for i = 1,#msg do
d[tostring(i)] = dialog.AddLabel(msg[i])
end
end
buttontext1 = buttontext1 or 'Ok'
d.button = dialog.AddButton(buttontext1,1)
if buttontext0 then d.button0 = dialog.AddButton(buttontext0,0) end
return dialog.Show(d)
end
--[[
Add items to the dialog from a table in the order given. The each table entry
is the dialog control function, the control label, the data key name, and the control options.
If this function fails, it gives an error saying which table item it failed on.
d = a created dialog, fields = table of dialog controls as described, object = data table
--]]
function dialog.AddFromTable(d,fields,object)
local func, label, id, value -- renamed field parameters for clarity
-- function wrappers to catch errors, explicitly named for clarity
function _AddLabel(args) d[id] = dialog.AddLabel(label) end
function _AddCheckbox(args) d[id] = dialog.AddCheckbox(label,value) end
function _AddSlider(args) d[id] = dialog.AddSlider(label,value,args[4],args[5],args[6]) end
function _AddTextbox(args) d[id] = dialog.AddTextbox(label,value) end
for i = 1, #fields do
local rc = true
local err
rc,err = pcall( function() func,label,id = fields[i][1],fields[i][2],fields[i][3] end)
value = object[id]
if func == dialog.AddLabel then id='_AL'..tostring(i) rc,err = pcall(_AddLabel,fields[i])
else
-- this is a crasher for AddTextbox but not an error for AddLabel!
if value == nil then error('Missing data field for field #'..tostring(i)..
'\n(Did you forget to pass a string?)') end
if func == dialog.AddCheckbox then rc,err = pcall(_AddCheckbox,fields[i])
elseif func == dialog.AddSlider then rc,err = pcall(_AddSlider,fields[i])
elseif func == dialog.AddTextbox then rc,err = pcall(_AddTextbox,fields[i])
else error('Unknown control in dialog field #'..tostring(i)) end
end -- if AddLabel
if rc == false then
error('Error setting dialog field #'..tostring(i)..(err and ('\n'..err) or ''))
end
end
end
--[[
This just copies the data from the dialog to the data table.
--]]
function dialog.ReadFields(d,fields,object)
for i = 1,#fields do
if fields[i][1]~= dialog.AddLabel then
object[fields[i][3]] = d[fields[i][3]].value
end
end
end
-- ================================== End New Dialog Library Functions
-- ================================== Begin Demo
-- This function defines an optional help screen
function DoInfoDialog()
local msg = {
' This allows you to define a dialog with a table instead of',
'explicit function calls, set its values with another table,',
'and read its values into yet a third table.',
' A self-contained function for text-only message',
'dialogs is included.',
' Options:',
' * Fuze -- Do a Fuze Y/N',
' * Band Strength -- 0.1 to 10.0',
' * Range -- two numbers, e.g. 10 20',
'Range segment numbers must be > 0 and increasing,',
'otherwise it is an error.'
}
dialog.MessageBox(msg,'About Dialog Options Demo','Back')
end
-- This function defines our dialog and calls the functions to set and read values
-- First arg is the current option state and optional second arg is a remembered
-- default.
function DoOptionsDialog(options,defaults)
-- Short names for the dialog controls
-- this is not an invitation to override, they are not used as functions
local label = dialog.AddLabel -- no data member for this
local box = dialog.AddCheckbox
local slider = dialog.AddSlider -- 4 control options for this
local text = dialog.AddTextbox
-- Lay out the dialog here
-- { { dialog control, textlabel, data member name, control options }, ... }
-- all data member names must be unique
local fields ={
{label,'Pick one or more options:'},
{box, 'Do a Fuze', 'fuze'},
{label,''},
{slider,'Band Strength:','bandstr',0.1,10.0,1},
{text,'Range (inclusive):','range'}
}
local d = dialog.CreateDialog('Dialog Options Demo')
-- Make sure your text fields are text!
if #options.range == 2 then
options.range = tostring(options.range[1])..' '..tostring(options.range[2])
else
options.range=''
end
-- Generate the dialog in order of the table
-- You can still do this by hand for a custom layout if you wish
dialog.AddFromTable(d,fields,options) -- last arg = table to read from
-- You can add more items from a different table here as long
-- as there is no name conflict in the two tables
-- Add the button now
d.ok = dialog.AddButton('Start!',1) -- 1 = okay
d.cancel = dialog.AddButton('Cancel',0) -- 0 = quit
d.help = dialog.AddButton('About',-1) -- < 0 = show options again, optional button
if defaults then d.reset = dialog.AddButton('Reset',-2) end -- if defaults provided, allow reset
local button = dialog.Show(d)
-- Check for reset first...if you have multiple option tables you have to reset them all
if button == -2 then for i,v in pairs(defaults) do options[i]=v end return -1 end -- < 0 = redraw
-- Check for cancel to skip the error checking
if button == 0 then return 0 end -- 0 = cancel
-- Otherwise read in the values to update with the user's entry in case we have to redraw
-- Read the fields into (a possibly different or empty table) table
dialog.ReadFields(d,fields,options) -- last arg = table to save to
-- Read in your other fields/tables here
-- Convert your text fields
-- For this text field, we want to pull out the numbers into a table
range={}
for num in string.gfind(options.range,'%d+') do
table.insert(range,tonumber(num))
end
options.range = range
-- Check user input here
if #options.range > 0 and (#options.range ~= 2 or options.range[1] < 1 or options.range[1] > options.range[2]) then
-- error dialog and signal an error (which will cause options dialog to be redisplayed)
dialog.MessageBox({'Range must be two numbers > 1 in ascending order','separated by non-numeric characters'},'Input Error','Oops!')
return -1
end
if button == -1 then DoInfoDialog() end
return button
end
-- Recursive table printer
function PrintTable(tab,indent)
indent = indent or ''
for i,v in pairs(tab) do
if type(v) == 'table' then do print(indent,i) PrintTable(v,indent..' ') end
else print(indent,i,v) end
end
end
defaults={}
for i,v in pairs(option) do defaults[i]=v end -- save the initial options as defaults, deep copy
repeat -- Loop if something other than okay or cancel
local rc = DoOptionsDialog(option,defaults)
if rc == 0 then print('Canceled') return end -- cancel
until rc == 1 -- okay
print('Printing Option Table')
PrintTable(option)
dialog.MessageBox('Options have been written to program output','Script Completed')