--@ Version: 2.0.2 --@ Author Luke Wigley --@ Description -- This script allows several objects to read and write their prefs (property/value pairs) to a -- single pref file. To save prefs, an object needs to call the SaveObjectPrefs method, specifying -- an id and a property list of property/value pairs to save. For example, if you had a script called -- 'FileBrowser' and you want to save the last Directory the user selected, you could do this: -- -- Prefs = script("PrefMgr") -- Prefs.SaveObjectPrefs("FileBrowser", [#LastPath: myLastPath]) -- -- To get prefs, an object calls the GetObjectPrefs() method, passing the id and a reference to itself. -- The values are set directly into the object. For example, the 'FileBrowser' script could read (and -- set) its prefs like this: -- -- Prefs = script("PrefMgr") -- Prefs.GetObjectPrefs("FileBrowser", me) -- -- Note. You need to call the "WritePrefsFile" method to actually save the prefs to disk. For example: -- -- on stopMovie -- script("PrefMgr").WritePrefsFile() -- end -- --@ History -- v.2.02 Added GetPrefs to return the prefs rather than apply them -- v.2.01 Updated examples to reflect new script name -- v.2.00 -- All strings are now quoted when they are saved. A quote character is added the start and end of a string -- when it is written to the pref file, and removed when read back in. This means it is possible to distinguish -- between "1.0" as a string and 1.0 as a floating number. Also, this means that VOID values will be read -- from the pref string as VOID, and empty strings will be read back as empty strings (this is different to -- version 1 of this script that would write VOID as an empty string, and return it as an empty string). -- -- Also improved the evaluation of strings - now will convert 6-character hex strings to colour objects. -- v.1.02 -- Added fix where saving a symbol would be restored as a string (by manually inserting the "#" character -- before the symbol name. -- -- -- v.1.01 -- Changed the way the script tests whether it can evaluate a string into a different type -- It tests (1) whether the string starts with a quote (always treats this as a string; and -- (2) whether the string version of an evaluation is the same as the original string. -- -- v.1.00 -- First version. ----------------------------------------- property myGlobalPrefList, myPrefFile on GetObjectPrefs (me, id, obj) -- Applies values extracted from the pref file to the specified object. -- --* id is the id used to save the prefs {String} --* obj is the object to apply the values to {instance} --* return TRUE is some pref values were found {instance} if voidP(myPrefFile) then me.Init() pList = myGlobalPrefList.getAProp(id) if voidP(pList) then put "Prefs not set for " & id return 0 else repeat with i = 1 to pList.count p = symbol(pList.getPropAt(i)) v = pList[i] obj[p] = v end repeat return 1 end if end on GetPrefs (me, id) if voidP(myPrefFile) then me.Init() pList = myGlobalPrefList.getAProp(id) if voidP(pList) then put "Prefs not set for " & id return [:] else return pList end if end on SaveObjectPrefs (me, id, inList) -- Stores the values in the specified list. The property names should -- match the property name in the object saving the prefs -- --* id is the id used to save the prefs {String} --* inList is a property list {instance} if voidP(myPrefFile) then me.Init() pList = myGlobalPrefList.getAProp(id) if voidP(pList) then pList = [:] end if repeat with i = 1 to inList.count p = inList.getPropAt(i) v = inList[i] pList[p] = v end repeat myGlobalPrefList.setAProp(id, pList) end on WritePrefsFile (me) -- Call this method on stopMovie (etc) to actually write the -- the prefs to disk if voidP(myPrefFile) then me.Init() ps = "" repeat with i = 1 to myGlobalPrefList.count ps = ps & "$"&myGlobalPrefList.getPropAt(i) & return pList = myGlobalPrefList[i] repeat with j = 1 to pList.count p = pList.getPropAt(j) v = me._ValToString(pList[j]) ps = ps & p & "=" & v & return end repeat end repeat -- put "Writing Prefs -->" & return & ps setPref (myPrefFile, ps) end ----------------------------------------- on new (me) -- Note - this is a 'single instance' script (the script object -- is returned if you try to make a new instance) return me.script end on PrefsExist (me, id) -- A Method for checking whether of not some prefs exist for -- the specified ID. --* id which pref to check {String} --* return true if there is some data for specified id {instance} if voidP(myPrefFile) then me.Init() pList = myGlobalPrefList.getAProp(id) return NOT(voidP(pList)) end on Init (me, PrefFile) -- Manually load the prefs from disk and initialise the object. -- (If you do not do this, this script will automatically load the -- prefs from disk the first time you call any of its methods) --* PrefFile name of the prefile (otherwise, movie name is used) {string, optional} if voidP(PrefFile) then me._SetDefaultPrefFile() else myPrefFile = PrefFile myGlobalPrefList = [:] me._LoadPrefs() end -- PRIVATE on _LoadPrefs(me) -- Load the prefs from disk. if voidP(myPrefFile) then me.Init() ps = getPref(myPrefFile) -- put "Reading prefs ->" & return & ps if (ps.ilk = #String) then mx = ps.line.count currentid = "" currentCollection = [:] repeat with i = 1 to mx thisline = ps.line[i] if thisline starts "$" then -- new collection if currentid <> "" then -- save the old myGlobalPrefList.addProp(currentid, currentCollection) end if currentid = thisline.char[2..thisline.length] currentCollection = [:] else if currentid <> "" then slen = length(thisline) p = offset("=", thisline) if p > 1 AND p< slen then toSet = symbol(thisline.char[1..p-1]) theVal = me._evalString(thisline.char[p+1..slen]) currentCollection[toSet] = theVal end if end if end repeat if currentid <> "" then myGlobalPrefList.addProp(currentid, currentCollection) end if else myGlobalPrefList = [:] end if end on _SetDefaultPrefFile (me) m = the movieName the itemDelimiter = "." mx = m.item.count myPrefFile = (m.item[1..(mx-1)] & ".txt") end on _ValToString (me, v) i = v.ilk case (i) of #Symbol: v = "#" & (v) #Color: v = v.hexString() #string: v = QUOTE & v & QUOTE end case return string(v) end on _evalString(me, aStr) mx = aStr.length if mx = 0 then return VOID -- if ((aStr.char[1]=QUOTE) AND (aStr.char[mx] = QUOTE)) then return aStr.char[2..mx-1] else -- see if its a colour if aStr.length = 7 then if aStr.char[1] = "#" AND me._isHex(aStr.char[2..7]) then return rgb(aStr) end if -- otherwise, try value() test1 = value(aStr) if not voidP(test1) then if symbolP(test1) then test2 = "#"&test1 if test2 = aStr then return test1 end if else test2 = string(test1) if test2 = test1 then return test1 end if end if end if end if return aStr end on _isHex (me, aStr) mx = aStr.length vChars = "0123456789abcdef" repeat with i = 1 to mx if NOT(vChars contains aStr.char[i]) then return 0 end repeat return 1 end