Force consistent line endings.
I'd suggest enabling the EolExtension: this way we won't go back and forth here.
This commit is contained in:
@@ -1,119 +1,119 @@
|
||||
--[[
|
||||
IniFile: basically a Lua rewrite of SM's IniFile class that serves as the
|
||||
basis for the sm-ssc UserPrefs and ThemePrefs configuration systems.
|
||||
Note that this is a namespace, not a class per se.
|
||||
--]]
|
||||
|
||||
-- TODO: move this into a more general section
|
||||
-- func takes a key and a value
|
||||
function foreach_ordered( tbl, func )
|
||||
local keys = { }
|
||||
for k,_ in pairs(tbl) do keys[#keys+1] = k end
|
||||
|
||||
table.sort( keys )
|
||||
|
||||
-- iterate in sorted order
|
||||
for _,key in ipairs(keys) do func( key, tbl[key]) end
|
||||
end
|
||||
|
||||
-- redeclared here for my sanity's sake
|
||||
-- TODO: declare these as global variables
|
||||
local RageFile =
|
||||
{
|
||||
READ = 1,
|
||||
WRITE = 2,
|
||||
STREAMED = 4,
|
||||
SLOW_FLUSH = 8
|
||||
}
|
||||
|
||||
-- IniFile namespace
|
||||
IniFile =
|
||||
{
|
||||
StrToKeyVal = function( str )
|
||||
local _, _, key, value = str:find( "(.+)=(.*)" )
|
||||
|
||||
-- key is always a string, but value may be num, bool, or nil.
|
||||
-- do a few quick checks to see which one it is.
|
||||
|
||||
-- if it's a nil, convert it to an empty string and return
|
||||
if value == nil then value = ""; return key, value; end
|
||||
|
||||
-- if it's a number, convert it in place and return
|
||||
if tonumber(value) ~= nil then value = tonumber(value); return key, value; end
|
||||
|
||||
-- not a number, so let's try a boolean value
|
||||
if value == "true" then value = true;
|
||||
elseif value == "false" then value = false;
|
||||
end
|
||||
|
||||
return key, value
|
||||
end,
|
||||
|
||||
ReadFile = function( file_path )
|
||||
Trace( "IniFile.ReadFile( " .. file_path .. " )" )
|
||||
local file = RageFileUtil.CreateRageFile()
|
||||
|
||||
if not file:Open(file_path, RageFile.READ) then
|
||||
Warn( string.format("ReadFile(%s): %s",file_path,file:GetError()) )
|
||||
file:destroy()
|
||||
return { } -- return a blank table
|
||||
end
|
||||
|
||||
local tbl = { }
|
||||
local current = tbl
|
||||
|
||||
while not file:AtEOF() do
|
||||
local str = file:GetLine()
|
||||
|
||||
-- is this a section?
|
||||
local _, _, sec = str:find( "%[(.+)%]" )
|
||||
|
||||
-- if so, set focus there; otherwise, try to
|
||||
-- read a key/value pair (ignore blank lines)
|
||||
if sec then
|
||||
-- if this section doesn't exist, create it
|
||||
tbl[sec] = tbl[sec] and tbl[sec] or { }
|
||||
current = tbl[sec]
|
||||
Warn( "Switching section to " .. sec )
|
||||
else
|
||||
local k, v = IniFile.StrToKeyVal( str )
|
||||
if k and v then current[k] = v end
|
||||
end
|
||||
end
|
||||
|
||||
file:Close()
|
||||
file:destroy()
|
||||
|
||||
return tbl
|
||||
end,
|
||||
|
||||
WriteFile = function( file_path, tbl )
|
||||
Trace( "IniFile.WriteFile( " .. file_path .. " )" )
|
||||
local file = RageFileUtil.CreateRageFile()
|
||||
|
||||
if not file:Open(file_path, RageFile.WRITE) then
|
||||
Warn( string.format("WriteFile(%s): %s",file_path.file:GetError()) )
|
||||
file:destroy()
|
||||
return false
|
||||
end
|
||||
|
||||
-- declare functions so we can write with foreach_ordered
|
||||
local function put_pair( k, v )
|
||||
file:PutLine( string.format("%s=%s", k, tostring(v)) )
|
||||
end
|
||||
|
||||
local function put_section( section, pair )
|
||||
file:PutLine( "[" .. section .. "]" )
|
||||
foreach_ordered( pair, put_pair )
|
||||
file:PutLine("") -- put a blank line between sections
|
||||
end
|
||||
|
||||
-- each base key is a section and its value is a
|
||||
-- table of key-value pairs under that section.
|
||||
foreach_ordered( tbl, put_section )
|
||||
|
||||
file:Close()
|
||||
file:destroy()
|
||||
return true
|
||||
end
|
||||
};
|
||||
--[[
|
||||
IniFile: basically a Lua rewrite of SM's IniFile class that serves as the
|
||||
basis for the sm-ssc UserPrefs and ThemePrefs configuration systems.
|
||||
Note that this is a namespace, not a class per se.
|
||||
--]]
|
||||
|
||||
-- TODO: move this into a more general section
|
||||
-- func takes a key and a value
|
||||
function foreach_ordered( tbl, func )
|
||||
local keys = { }
|
||||
for k,_ in pairs(tbl) do keys[#keys+1] = k end
|
||||
|
||||
table.sort( keys )
|
||||
|
||||
-- iterate in sorted order
|
||||
for _,key in ipairs(keys) do func( key, tbl[key]) end
|
||||
end
|
||||
|
||||
-- redeclared here for my sanity's sake
|
||||
-- TODO: declare these as global variables
|
||||
local RageFile =
|
||||
{
|
||||
READ = 1,
|
||||
WRITE = 2,
|
||||
STREAMED = 4,
|
||||
SLOW_FLUSH = 8
|
||||
}
|
||||
|
||||
-- IniFile namespace
|
||||
IniFile =
|
||||
{
|
||||
StrToKeyVal = function( str )
|
||||
local _, _, key, value = str:find( "(.+)=(.*)" )
|
||||
|
||||
-- key is always a string, but value may be num, bool, or nil.
|
||||
-- do a few quick checks to see which one it is.
|
||||
|
||||
-- if it's a nil, convert it to an empty string and return
|
||||
if value == nil then value = ""; return key, value; end
|
||||
|
||||
-- if it's a number, convert it in place and return
|
||||
if tonumber(value) ~= nil then value = tonumber(value); return key, value; end
|
||||
|
||||
-- not a number, so let's try a boolean value
|
||||
if value == "true" then value = true;
|
||||
elseif value == "false" then value = false;
|
||||
end
|
||||
|
||||
return key, value
|
||||
end,
|
||||
|
||||
ReadFile = function( file_path )
|
||||
Trace( "IniFile.ReadFile( " .. file_path .. " )" )
|
||||
local file = RageFileUtil.CreateRageFile()
|
||||
|
||||
if not file:Open(file_path, RageFile.READ) then
|
||||
Warn( string.format("ReadFile(%s): %s",file_path,file:GetError()) )
|
||||
file:destroy()
|
||||
return { } -- return a blank table
|
||||
end
|
||||
|
||||
local tbl = { }
|
||||
local current = tbl
|
||||
|
||||
while not file:AtEOF() do
|
||||
local str = file:GetLine()
|
||||
|
||||
-- is this a section?
|
||||
local _, _, sec = str:find( "%[(.+)%]" )
|
||||
|
||||
-- if so, set focus there; otherwise, try to
|
||||
-- read a key/value pair (ignore blank lines)
|
||||
if sec then
|
||||
-- if this section doesn't exist, create it
|
||||
tbl[sec] = tbl[sec] and tbl[sec] or { }
|
||||
current = tbl[sec]
|
||||
Warn( "Switching section to " .. sec )
|
||||
else
|
||||
local k, v = IniFile.StrToKeyVal( str )
|
||||
if k and v then current[k] = v end
|
||||
end
|
||||
end
|
||||
|
||||
file:Close()
|
||||
file:destroy()
|
||||
|
||||
return tbl
|
||||
end,
|
||||
|
||||
WriteFile = function( file_path, tbl )
|
||||
Trace( "IniFile.WriteFile( " .. file_path .. " )" )
|
||||
local file = RageFileUtil.CreateRageFile()
|
||||
|
||||
if not file:Open(file_path, RageFile.WRITE) then
|
||||
Warn( string.format("WriteFile(%s): %s",file_path.file:GetError()) )
|
||||
file:destroy()
|
||||
return false
|
||||
end
|
||||
|
||||
-- declare functions so we can write with foreach_ordered
|
||||
local function put_pair( k, v )
|
||||
file:PutLine( string.format("%s=%s", k, tostring(v)) )
|
||||
end
|
||||
|
||||
local function put_section( section, pair )
|
||||
file:PutLine( "[" .. section .. "]" )
|
||||
foreach_ordered( pair, put_pair )
|
||||
file:PutLine("") -- put a blank line between sections
|
||||
end
|
||||
|
||||
-- each base key is a section and its value is a
|
||||
-- table of key-value pairs under that section.
|
||||
foreach_ordered( tbl, put_section )
|
||||
|
||||
file:Close()
|
||||
file:destroy()
|
||||
return true
|
||||
end
|
||||
};
|
||||
|
||||
@@ -1,141 +1,141 @@
|
||||
--[[
|
||||
ThemePrefs: handles the underlying structure for ThemePrefs, so any themes
|
||||
built off of this can simply declare their prefs and default values, and
|
||||
access them through this system.
|
||||
|
||||
v0.7.1: Dec. 28, 2010. Added language support.
|
||||
v0.7.0: Dec. 15, 2010. Initial version.
|
||||
|
||||
vyhd wrote this for sm-ssc. <3 you guys
|
||||
--]]
|
||||
|
||||
-- local function to handle themed error strings
|
||||
-- (and to ensure we're getting all of them from the same section)
|
||||
local function GetString( name )
|
||||
return THEME:GetString( "ThemePrefs", name )
|
||||
end
|
||||
|
||||
function PrintTable( tbl )
|
||||
Trace( "Printing table" )
|
||||
for k,v in pairs(tbl) do
|
||||
Trace( ("[%s] -> %s"):format(tostring(k),tostring(v)) )
|
||||
end
|
||||
end
|
||||
|
||||
local ThemePrefsPath = "Save/ThemePrefs.ini";
|
||||
local FallbackTheme = "_fallback";
|
||||
|
||||
-- This will be set on load.
|
||||
local PrefsTable = nil;
|
||||
|
||||
-- Gets the name of the current theme using themeInfo
|
||||
-- if available and the ThemeManager name otherwise.
|
||||
local function GetThemeName()
|
||||
return themeInfo and themeInfo.Name or THEME:GetThemeDisplayName()
|
||||
end
|
||||
|
||||
-- Given a preference name, returns the table it's in. Checks the current
|
||||
-- theme first, then _fallback, then all other sections, in that order.
|
||||
local function ResolveTable( pref )
|
||||
-- check the section for this theme
|
||||
local name = GetThemeName()
|
||||
local val = PrefsTable[name][pref]
|
||||
|
||||
if val ~= nil then
|
||||
Trace( ("ResolveTable(%s): found in %s"):format(pref,name) )
|
||||
return PrefsTable[name]
|
||||
end
|
||||
|
||||
-- not in the current theme; check the fallback if it exists
|
||||
if PrefsTable[FallbackTheme] then
|
||||
val = PrefsTable[FallbackTheme][pref]
|
||||
if val ~= nil then
|
||||
Trace( ("ResolveTable(%s): found in fallback"):format(pref) )
|
||||
return PrefsTable[FallbackTheme]
|
||||
end
|
||||
end
|
||||
|
||||
-- not there either. check every section.
|
||||
-- XXX: we should do this less redundantly.
|
||||
for section, _ in pairs(PrefsTable) do
|
||||
val = PrefsTable[section][pref]
|
||||
if val ~= nil then
|
||||
Trace( ("ResolveTable(%s): found in section %s"):format(pref,section) )
|
||||
return PrefsTable[section] end
|
||||
end
|
||||
|
||||
-- not found at all
|
||||
Trace( ("ResolveTable(%s): pref not found"):format(pref) )
|
||||
return nil
|
||||
end
|
||||
|
||||
ThemePrefs =
|
||||
{
|
||||
NeedsSaved = false,
|
||||
|
||||
-- Loads preferences from Save/ThemePrefs.ini, then adds theme
|
||||
-- preferences (and default values if applicable) to PrefsTable.
|
||||
-- Only read from disk once, when _fallback calls this; we just
|
||||
-- need the base set once to add prefs onto.
|
||||
Init = function( prefs, bLoadFromDisk )
|
||||
-- If we don't have IniFile, we can't read/write from/to disk
|
||||
if not IniFile then Warn( GetString("IniFileMissing") ) end
|
||||
|
||||
Trace( ("ThemePrefs.Init(prefs, %s)"):format(tostring(bLoadFromDisk)) )
|
||||
if bLoadFromDisk then
|
||||
Trace( "ThemePrefs.Init: loading from disk" )
|
||||
if not ThemePrefs.Load() then return false end
|
||||
end
|
||||
|
||||
Trace( "ThemePrefs.Init: not loading from disk" )
|
||||
|
||||
-- create the section if it doesn't exist
|
||||
local section = GetThemeName()
|
||||
PrefsTable[section] = PrefsTable[section] and PrefsTable[section] or { }
|
||||
|
||||
Trace( "Using section " .. section )
|
||||
|
||||
-- if the key doesn't exist, add it with our default value
|
||||
for k, tbl in pairs(prefs) do
|
||||
if not PrefsTable[section][k] then
|
||||
Trace( k .. " doesn't exist, creating" )
|
||||
PrefsTable[section][k] = tbl.Default
|
||||
end
|
||||
end
|
||||
|
||||
PrintTable( PrefsTable[section] )
|
||||
end,
|
||||
|
||||
Load = function()
|
||||
if not IniFile then return false end
|
||||
PrefsTable = IniFile.ReadFile( ThemePrefsPath )
|
||||
return true
|
||||
end,
|
||||
|
||||
Save = function()
|
||||
Trace( "ThemePrefs.Save" )
|
||||
if not IniFile then return false end
|
||||
if not NeedsSaved then return end
|
||||
NeedsSaved = false
|
||||
IniFile.WriteFile( ThemePrefsPath, PrefsTable )
|
||||
end,
|
||||
|
||||
Get = function( name )
|
||||
Trace( ("ThemePrefs.Get(%s)"):format(name) )
|
||||
local tbl = ResolveTable(name)
|
||||
if tbl then return tbl[name] end
|
||||
Warn( "Get: "..GetString("UnknownPreference"):format(name) )
|
||||
return nil
|
||||
end,
|
||||
|
||||
Set = function( name, value )
|
||||
Trace( ("ThemePrefs.Set(%s, %s)"):format(name, tostring(value)) )
|
||||
local tbl = ResolveTable(name)
|
||||
if tbl then tbl[name] = value; NeedsSaved = true; return end
|
||||
Warn( "Set: "..GetString("UnknownPreference"):format(name) )
|
||||
end,
|
||||
};
|
||||
|
||||
-- global aliases
|
||||
GetThemePref = ThemePrefs.Get
|
||||
SetThemePref = ThemePrefs.Set
|
||||
--[[
|
||||
ThemePrefs: handles the underlying structure for ThemePrefs, so any themes
|
||||
built off of this can simply declare their prefs and default values, and
|
||||
access them through this system.
|
||||
|
||||
v0.7.1: Dec. 28, 2010. Added language support.
|
||||
v0.7.0: Dec. 15, 2010. Initial version.
|
||||
|
||||
vyhd wrote this for sm-ssc. <3 you guys
|
||||
--]]
|
||||
|
||||
-- local function to handle themed error strings
|
||||
-- (and to ensure we're getting all of them from the same section)
|
||||
local function GetString( name )
|
||||
return THEME:GetString( "ThemePrefs", name )
|
||||
end
|
||||
|
||||
function PrintTable( tbl )
|
||||
Trace( "Printing table" )
|
||||
for k,v in pairs(tbl) do
|
||||
Trace( ("[%s] -> %s"):format(tostring(k),tostring(v)) )
|
||||
end
|
||||
end
|
||||
|
||||
local ThemePrefsPath = "Save/ThemePrefs.ini";
|
||||
local FallbackTheme = "_fallback";
|
||||
|
||||
-- This will be set on load.
|
||||
local PrefsTable = nil;
|
||||
|
||||
-- Gets the name of the current theme using themeInfo
|
||||
-- if available and the ThemeManager name otherwise.
|
||||
local function GetThemeName()
|
||||
return themeInfo and themeInfo.Name or THEME:GetThemeDisplayName()
|
||||
end
|
||||
|
||||
-- Given a preference name, returns the table it's in. Checks the current
|
||||
-- theme first, then _fallback, then all other sections, in that order.
|
||||
local function ResolveTable( pref )
|
||||
-- check the section for this theme
|
||||
local name = GetThemeName()
|
||||
local val = PrefsTable[name][pref]
|
||||
|
||||
if val ~= nil then
|
||||
Trace( ("ResolveTable(%s): found in %s"):format(pref,name) )
|
||||
return PrefsTable[name]
|
||||
end
|
||||
|
||||
-- not in the current theme; check the fallback if it exists
|
||||
if PrefsTable[FallbackTheme] then
|
||||
val = PrefsTable[FallbackTheme][pref]
|
||||
if val ~= nil then
|
||||
Trace( ("ResolveTable(%s): found in fallback"):format(pref) )
|
||||
return PrefsTable[FallbackTheme]
|
||||
end
|
||||
end
|
||||
|
||||
-- not there either. check every section.
|
||||
-- XXX: we should do this less redundantly.
|
||||
for section, _ in pairs(PrefsTable) do
|
||||
val = PrefsTable[section][pref]
|
||||
if val ~= nil then
|
||||
Trace( ("ResolveTable(%s): found in section %s"):format(pref,section) )
|
||||
return PrefsTable[section] end
|
||||
end
|
||||
|
||||
-- not found at all
|
||||
Trace( ("ResolveTable(%s): pref not found"):format(pref) )
|
||||
return nil
|
||||
end
|
||||
|
||||
ThemePrefs =
|
||||
{
|
||||
NeedsSaved = false,
|
||||
|
||||
-- Loads preferences from Save/ThemePrefs.ini, then adds theme
|
||||
-- preferences (and default values if applicable) to PrefsTable.
|
||||
-- Only read from disk once, when _fallback calls this; we just
|
||||
-- need the base set once to add prefs onto.
|
||||
Init = function( prefs, bLoadFromDisk )
|
||||
-- If we don't have IniFile, we can't read/write from/to disk
|
||||
if not IniFile then Warn( GetString("IniFileMissing") ) end
|
||||
|
||||
Trace( ("ThemePrefs.Init(prefs, %s)"):format(tostring(bLoadFromDisk)) )
|
||||
if bLoadFromDisk then
|
||||
Trace( "ThemePrefs.Init: loading from disk" )
|
||||
if not ThemePrefs.Load() then return false end
|
||||
end
|
||||
|
||||
Trace( "ThemePrefs.Init: not loading from disk" )
|
||||
|
||||
-- create the section if it doesn't exist
|
||||
local section = GetThemeName()
|
||||
PrefsTable[section] = PrefsTable[section] and PrefsTable[section] or { }
|
||||
|
||||
Trace( "Using section " .. section )
|
||||
|
||||
-- if the key doesn't exist, add it with our default value
|
||||
for k, tbl in pairs(prefs) do
|
||||
if not PrefsTable[section][k] then
|
||||
Trace( k .. " doesn't exist, creating" )
|
||||
PrefsTable[section][k] = tbl.Default
|
||||
end
|
||||
end
|
||||
|
||||
PrintTable( PrefsTable[section] )
|
||||
end,
|
||||
|
||||
Load = function()
|
||||
if not IniFile then return false end
|
||||
PrefsTable = IniFile.ReadFile( ThemePrefsPath )
|
||||
return true
|
||||
end,
|
||||
|
||||
Save = function()
|
||||
Trace( "ThemePrefs.Save" )
|
||||
if not IniFile then return false end
|
||||
if not NeedsSaved then return end
|
||||
NeedsSaved = false
|
||||
IniFile.WriteFile( ThemePrefsPath, PrefsTable )
|
||||
end,
|
||||
|
||||
Get = function( name )
|
||||
Trace( ("ThemePrefs.Get(%s)"):format(name) )
|
||||
local tbl = ResolveTable(name)
|
||||
if tbl then return tbl[name] end
|
||||
Warn( "Get: "..GetString("UnknownPreference"):format(name) )
|
||||
return nil
|
||||
end,
|
||||
|
||||
Set = function( name, value )
|
||||
Trace( ("ThemePrefs.Set(%s, %s)"):format(name, tostring(value)) )
|
||||
local tbl = ResolveTable(name)
|
||||
if tbl then tbl[name] = value; NeedsSaved = true; return end
|
||||
Warn( "Set: "..GetString("UnknownPreference"):format(name) )
|
||||
end,
|
||||
};
|
||||
|
||||
-- global aliases
|
||||
GetThemePref = ThemePrefs.Get
|
||||
SetThemePref = ThemePrefs.Set
|
||||
|
||||
@@ -1,164 +1,164 @@
|
||||
--[[
|
||||
ThemePrefsRows: you give it the choices, values, and params, and it'll
|
||||
generate the rest; quirky behavior to be outlined below. Documentation
|
||||
will be provided once this system is stabilized.
|
||||
|
||||
v0.5.2: Dec. 28, 2010. Throw an error for default/value type mismatches.
|
||||
v0.5.1: Dec. 27, 2010. Fix Choices not necessarily being strings.
|
||||
v0.5.0: Dec. 15, 2010. Initial version. Not very well tested.
|
||||
|
||||
vyhd wrote this for sm-ssc
|
||||
--]]
|
||||
|
||||
-- unless overridden, these parameters will be used for the OptionsRow
|
||||
local DefaultParams =
|
||||
{
|
||||
LayoutType = "ShowAllInRow",
|
||||
SelectType = "SelectOne",
|
||||
OneChoiceForAllPlayers = true,
|
||||
ExportOnChange = false,
|
||||
EnabledForPlayers = nil,
|
||||
ReloadRowMessages = nil,
|
||||
|
||||
-- takes a function(self, list, pn);
|
||||
-- if not used, we use the default
|
||||
LoadSelections = nil,
|
||||
SaveSelections = nil,
|
||||
}
|
||||
|
||||
-- local alias to simplify error reporting
|
||||
local function GetString( name )
|
||||
return THEME:GetString( "ThemePrefsRows", name )
|
||||
end
|
||||
|
||||
local function DefaultLoad( pref, default, choices, values )
|
||||
return function(self, list, pn)
|
||||
local val = ThemePrefs.Get( pref )
|
||||
|
||||
-- if our current value is here, set focus to that
|
||||
for i=1, #choices do
|
||||
if values[i] == val then list[i] = true return end
|
||||
end
|
||||
|
||||
-- try the default value
|
||||
for i=1, #choices do
|
||||
if values[i] == default then list[i] = true return end
|
||||
end
|
||||
|
||||
-- set to the first value and output a warning
|
||||
Warn( GetString("NoDefaultInValues"):format(pref) )
|
||||
list[1] = true
|
||||
end
|
||||
end
|
||||
|
||||
local function DefaultSave( pref, choices, values )
|
||||
local msg = "ThemePrefChanged"
|
||||
local params = { Name = pref }
|
||||
|
||||
return function(self, list, pn)
|
||||
for i=1, #choices do
|
||||
if list[i] then ThemePrefs.Set( pref, values[i] ) break end
|
||||
MESSAGEMAN:Broadcast( msg, params )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This function checks for mismatches between the default value and the
|
||||
-- values table passed to the ThemePrefRow, e.g. it will return false if
|
||||
-- you have a boolean default and an integer value. I'm somewhat stricter
|
||||
-- about types than Lua is because I don't like the unpredictability and
|
||||
-- complexity of coercing values transparently in a bunch of places.
|
||||
local function TypesMatch( Values, Default )
|
||||
local DefaultType = type(Default)
|
||||
|
||||
for i, value in ipairs(Values) do
|
||||
local ValueType = type(value)
|
||||
if ValueType ~= DefaultType then
|
||||
Warn( GetString("TypeMismatch"):format(DefaultType, i, ValueType) )
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function CreateThemePrefRow( pref, tbl )
|
||||
-- can't make an option handler without options
|
||||
if not tbl.Choices then return nil end
|
||||
|
||||
local Choices = tbl.Choices
|
||||
local Default = tbl.Default
|
||||
local Values = tbl.Values and tbl.Values or Choices
|
||||
local Params = tbl.Params and tbl.Params or { }
|
||||
|
||||
-- if the choices aren't strings, make them strings now
|
||||
for i, str in ipairs(Choices) do
|
||||
Choices[i] = tostring( Choices[i] )
|
||||
end
|
||||
|
||||
-- check to see that Values and Choices have the same length
|
||||
if #Choices ~= #Values then
|
||||
Warn( GetString("ChoicesSizeMismatch") )
|
||||
return nil
|
||||
end
|
||||
|
||||
-- check to see that everything in Values matches the type of Default
|
||||
if not TypesMatch( Values, Default ) then return nil end
|
||||
|
||||
-- set the name and choices here; we'll do the rest below
|
||||
local Handler = { Name = pref, Choices = Choices }
|
||||
|
||||
-- add all the keys in DefaultParams, get the value from
|
||||
-- Params if it exists and DefaultParams otherwise
|
||||
-- (note that we explicitly check for nil, due to bools.)
|
||||
for k, _ in pairs(DefaultParams) do
|
||||
Handler[k] = Params[k] ~= nil and Params[k] or DefaultParams[k]
|
||||
end
|
||||
|
||||
-- if we don't have LoadSelections and SaveSelections, make them
|
||||
if not Handler.LoadSelections then
|
||||
Handler.LoadSelections = DefaultLoad( pref, Default, Choices, Values )
|
||||
end
|
||||
|
||||
if not Handler.SaveSelections then
|
||||
Handler.SaveSelections = DefaultSave( pref, Choices, Values )
|
||||
end
|
||||
|
||||
return Handler
|
||||
end
|
||||
|
||||
-- All OptionsRows for preferences are stuck in this table, accessible
|
||||
-- through GetRow('name') in the namespace or ThemePrefRow('name') in
|
||||
-- the global namespace. (I like to keep pollution to a minimum.)
|
||||
local Rows = { }
|
||||
|
||||
ThemePrefsRows =
|
||||
{
|
||||
IsInitted = false,
|
||||
|
||||
Init = function( prefs )
|
||||
for pref, tbl in pairs(prefs) do
|
||||
Rows[pref] = CreateThemePrefRow( pref, tbl )
|
||||
end
|
||||
end,
|
||||
|
||||
GetRow = function( pref )
|
||||
Trace( ("GetRow(%s), type %s"):format(pref, type(Rows[pref])) )
|
||||
return Rows[pref]
|
||||
end,
|
||||
|
||||
}
|
||||
|
||||
-- Global namespace alias
|
||||
ThemePrefRow = ThemePrefsRows.GetRow
|
||||
|
||||
-- UGLY: declare this here, even though it's in the previous namespace,
|
||||
-- so we can have one call to initialize both systems (ThemePrefsRow is
|
||||
-- declared after ThemePrefs, so it can't actually be in that file...)
|
||||
|
||||
ThemePrefs.InitAll = function( prefs )
|
||||
Trace( "ThemePrefs.InitAll( prefs )" )
|
||||
|
||||
ThemePrefs.Init( prefs, true )
|
||||
ThemePrefsRows.Init( prefs )
|
||||
end
|
||||
--[[
|
||||
ThemePrefsRows: you give it the choices, values, and params, and it'll
|
||||
generate the rest; quirky behavior to be outlined below. Documentation
|
||||
will be provided once this system is stabilized.
|
||||
|
||||
v0.5.2: Dec. 28, 2010. Throw an error for default/value type mismatches.
|
||||
v0.5.1: Dec. 27, 2010. Fix Choices not necessarily being strings.
|
||||
v0.5.0: Dec. 15, 2010. Initial version. Not very well tested.
|
||||
|
||||
vyhd wrote this for sm-ssc
|
||||
--]]
|
||||
|
||||
-- unless overridden, these parameters will be used for the OptionsRow
|
||||
local DefaultParams =
|
||||
{
|
||||
LayoutType = "ShowAllInRow",
|
||||
SelectType = "SelectOne",
|
||||
OneChoiceForAllPlayers = true,
|
||||
ExportOnChange = false,
|
||||
EnabledForPlayers = nil,
|
||||
ReloadRowMessages = nil,
|
||||
|
||||
-- takes a function(self, list, pn);
|
||||
-- if not used, we use the default
|
||||
LoadSelections = nil,
|
||||
SaveSelections = nil,
|
||||
}
|
||||
|
||||
-- local alias to simplify error reporting
|
||||
local function GetString( name )
|
||||
return THEME:GetString( "ThemePrefsRows", name )
|
||||
end
|
||||
|
||||
local function DefaultLoad( pref, default, choices, values )
|
||||
return function(self, list, pn)
|
||||
local val = ThemePrefs.Get( pref )
|
||||
|
||||
-- if our current value is here, set focus to that
|
||||
for i=1, #choices do
|
||||
if values[i] == val then list[i] = true return end
|
||||
end
|
||||
|
||||
-- try the default value
|
||||
for i=1, #choices do
|
||||
if values[i] == default then list[i] = true return end
|
||||
end
|
||||
|
||||
-- set to the first value and output a warning
|
||||
Warn( GetString("NoDefaultInValues"):format(pref) )
|
||||
list[1] = true
|
||||
end
|
||||
end
|
||||
|
||||
local function DefaultSave( pref, choices, values )
|
||||
local msg = "ThemePrefChanged"
|
||||
local params = { Name = pref }
|
||||
|
||||
return function(self, list, pn)
|
||||
for i=1, #choices do
|
||||
if list[i] then ThemePrefs.Set( pref, values[i] ) break end
|
||||
MESSAGEMAN:Broadcast( msg, params )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This function checks for mismatches between the default value and the
|
||||
-- values table passed to the ThemePrefRow, e.g. it will return false if
|
||||
-- you have a boolean default and an integer value. I'm somewhat stricter
|
||||
-- about types than Lua is because I don't like the unpredictability and
|
||||
-- complexity of coercing values transparently in a bunch of places.
|
||||
local function TypesMatch( Values, Default )
|
||||
local DefaultType = type(Default)
|
||||
|
||||
for i, value in ipairs(Values) do
|
||||
local ValueType = type(value)
|
||||
if ValueType ~= DefaultType then
|
||||
Warn( GetString("TypeMismatch"):format(DefaultType, i, ValueType) )
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function CreateThemePrefRow( pref, tbl )
|
||||
-- can't make an option handler without options
|
||||
if not tbl.Choices then return nil end
|
||||
|
||||
local Choices = tbl.Choices
|
||||
local Default = tbl.Default
|
||||
local Values = tbl.Values and tbl.Values or Choices
|
||||
local Params = tbl.Params and tbl.Params or { }
|
||||
|
||||
-- if the choices aren't strings, make them strings now
|
||||
for i, str in ipairs(Choices) do
|
||||
Choices[i] = tostring( Choices[i] )
|
||||
end
|
||||
|
||||
-- check to see that Values and Choices have the same length
|
||||
if #Choices ~= #Values then
|
||||
Warn( GetString("ChoicesSizeMismatch") )
|
||||
return nil
|
||||
end
|
||||
|
||||
-- check to see that everything in Values matches the type of Default
|
||||
if not TypesMatch( Values, Default ) then return nil end
|
||||
|
||||
-- set the name and choices here; we'll do the rest below
|
||||
local Handler = { Name = pref, Choices = Choices }
|
||||
|
||||
-- add all the keys in DefaultParams, get the value from
|
||||
-- Params if it exists and DefaultParams otherwise
|
||||
-- (note that we explicitly check for nil, due to bools.)
|
||||
for k, _ in pairs(DefaultParams) do
|
||||
Handler[k] = Params[k] ~= nil and Params[k] or DefaultParams[k]
|
||||
end
|
||||
|
||||
-- if we don't have LoadSelections and SaveSelections, make them
|
||||
if not Handler.LoadSelections then
|
||||
Handler.LoadSelections = DefaultLoad( pref, Default, Choices, Values )
|
||||
end
|
||||
|
||||
if not Handler.SaveSelections then
|
||||
Handler.SaveSelections = DefaultSave( pref, Choices, Values )
|
||||
end
|
||||
|
||||
return Handler
|
||||
end
|
||||
|
||||
-- All OptionsRows for preferences are stuck in this table, accessible
|
||||
-- through GetRow('name') in the namespace or ThemePrefRow('name') in
|
||||
-- the global namespace. (I like to keep pollution to a minimum.)
|
||||
local Rows = { }
|
||||
|
||||
ThemePrefsRows =
|
||||
{
|
||||
IsInitted = false,
|
||||
|
||||
Init = function( prefs )
|
||||
for pref, tbl in pairs(prefs) do
|
||||
Rows[pref] = CreateThemePrefRow( pref, tbl )
|
||||
end
|
||||
end,
|
||||
|
||||
GetRow = function( pref )
|
||||
Trace( ("GetRow(%s), type %s"):format(pref, type(Rows[pref])) )
|
||||
return Rows[pref]
|
||||
end,
|
||||
|
||||
}
|
||||
|
||||
-- Global namespace alias
|
||||
ThemePrefRow = ThemePrefsRows.GetRow
|
||||
|
||||
-- UGLY: declare this here, even though it's in the previous namespace,
|
||||
-- so we can have one call to initialize both systems (ThemePrefsRow is
|
||||
-- declared after ThemePrefs, so it can't actually be in that file...)
|
||||
|
||||
ThemePrefs.InitAll = function( prefs )
|
||||
Trace( "ThemePrefs.InitAll( prefs )" )
|
||||
|
||||
ThemePrefs.Init( prefs, true )
|
||||
ThemePrefsRows.Init( prefs )
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user