Standalone: Saving prefs
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller
Standalone: Saving prefs
Hi all,
I'm lost on where in the forum to find an answer for this question: If my standalone requires that a user modify settings in my app (for example they may change the bg color of the UI) then this needs to be saved externally to a custom plist/JSON/XML etc.
What is the current best practice for this? I was thinking I'd just write any customizations made by the user to a plist file. The issue is where this file goes, I see that the build process allows us to copy files with the build. So if I include a userprefs.plist then would I be able to still write to it? Or is it better to save those prefs to the user's Documents folder?
Any help to posts here that cover this is appreciated.
I'm lost on where in the forum to find an answer for this question: If my standalone requires that a user modify settings in my app (for example they may change the bg color of the UI) then this needs to be saved externally to a custom plist/JSON/XML etc.
What is the current best practice for this? I was thinking I'd just write any customizations made by the user to a plist file. The issue is where this file goes, I see that the build process allows us to copy files with the build. So if I include a userprefs.plist then would I be able to still write to it? Or is it better to save those prefs to the user's Documents folder?
Any help to posts here that cover this is appreciated.
-
- VIP Livecode Opensource Backer
- Posts: 9709
- Joined: Wed May 06, 2009 2:28 pm
- Location: New York, NY
Re: Standalone: Saving prefs
Hi.
A common question.
The trick is to NOT have the "app" be the executable. No OS will save the executable. Once you grok that, just save away, as you might an ordinary stack in the IDE, and the "app" is, er, saved.
Now then, look up "splash" on this forum. Read a bit; there is a lot there.
If you still want a simple recipe, just come back.
Craig
A common question.
The trick is to NOT have the "app" be the executable. No OS will save the executable. Once you grok that, just save away, as you might an ordinary stack in the IDE, and the "app" is, er, saved.
Now then, look up "splash" on this forum. Read a bit; there is a lot there.
If you still want a simple recipe, just come back.
Craig
Re: Standalone: Saving prefs
Hi Simon,
on Windows use -> specialfolderpath("support")
on a Mac use -> specialfolderpath("preferences")
to store your prefs.
Best
Klaus
on Windows use -> specialfolderpath("support")
on a Mac use -> specialfolderpath("preferences")
to store your prefs.
Best
Klaus
-
- VIP Livecode Opensource Backer
- Posts: 9709
- Joined: Wed May 06, 2009 2:28 pm
- Location: New York, NY
Re: Standalone: Saving prefs
Simon.
You now have the other way to save information in a standalone app, an external file. Which to use is up to you. I always use the "Splash Stack" method.
Craig
You now have the other way to save information in a standalone app, an external file. Which to use is up to you. I always use the "Splash Stack" method.
Craig
Re: Standalone: Saving prefs
I'm absorbing the replies and continue to read what I can find — here's my current understanding:
[1] specialfolderpath()
I can store basic preferences such as window size, colors and fonts, preferred "save path" directory etc to an xml or json file. I don't really see any benefit to saving 4KB of string-based data to a new stack.
[2] create/clone stack "NewStack"
In the past I recall doing this from a standalone to create a new stack that the user can work in. I think the preferred method would be to clone a substack currently within my standalone (essentially a "template" stack) which has my custom layouts etc and let the user modify that clone and save it.
[3] Splash stack
I'm still unclear on the use case here. Conceptually I understand that you need the executable "Splash" to edit and work on data it can save to "the stack". However, as a practical matter, I can't seem to wrap my head on what's happening or what this solution looks like.
Can I assume that any solution using this method would be delivered as a runtime which has an accompanying stack sidekick?
For example, if the purpose of your standalone was to act as a plain text editor then is "the stack" your text editor which generates txt files or does the "Splash" contain the editor which saves data to "the stack"? Are you then constantly forking/cloning "the stack"?
Sorry for being dense, there are so many results when searching "Splash stack" that I have yet to find a practical example I can open to see how it's being applied in practice. On the surface it seems functionally similar to cloning a substack but "with extra steps" as the memes say.
[1] specialfolderpath()
I can store basic preferences such as window size, colors and fonts, preferred "save path" directory etc to an xml or json file. I don't really see any benefit to saving 4KB of string-based data to a new stack.
[2] create/clone stack "NewStack"
In the past I recall doing this from a standalone to create a new stack that the user can work in. I think the preferred method would be to clone a substack currently within my standalone (essentially a "template" stack) which has my custom layouts etc and let the user modify that clone and save it.
[3] Splash stack
I'm still unclear on the use case here. Conceptually I understand that you need the executable "Splash" to edit and work on data it can save to "the stack". However, as a practical matter, I can't seem to wrap my head on what's happening or what this solution looks like.
Can I assume that any solution using this method would be delivered as a runtime which has an accompanying stack sidekick?
For example, if the purpose of your standalone was to act as a plain text editor then is "the stack" your text editor which generates txt files or does the "Splash" contain the editor which saves data to "the stack"? Are you then constantly forking/cloning "the stack"?
Sorry for being dense, there are so many results when searching "Splash stack" that I have yet to find a practical example I can open to see how it's being applied in practice. On the surface it seems functionally similar to cloning a substack but "with extra steps" as the memes say.
-
- VIP Livecode Opensource Backer
- Posts: 7255
- Joined: Sat Apr 08, 2006 8:31 pm
- Location: Minneapolis MN
- Contact:
Re: Standalone: Saving prefs
For something like a prefs file I always just write a file to one of the folders Klaus suggested. The file can be in any format, it doesn't have to be a plist or JSON. If the data isn't critical, a plain text file is fine. If you need to store info securely you can encrypt it and then decrypt when you read it in. The file can be created on the fly as needed.
If you need to store images or LC controls then creating a prefs stack is a similar way to do the same thing.
If you need to store images or LC controls then creating a prefs stack is a similar way to do the same thing.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com
HyperActive Software | http://www.hyperactivesw.com
Re: Standalone: Saving prefs
I came here for a different purpose, however, the question posed was interesting to me, so I thought I would input my .02 (worth less due to inflation).
On the general question, Klaus (and Jacque's follow up) nail most situations, but Craig's answer deserves a little more explanation.
Since the main program is a non-compiled stack, as long as you have ...
Then the actual application closes with all changes made being saved directly therein, so a preference file becomes redundant. Jacque mentions this obliquely in her reply about a pref's stack, however, you don't need the pref's stack at all in the above situation (other than to set the background color or whatever).
You will notice this behavior when editing stacks in the IDE, for instance, when you save a stack in work. The only difference here is that you are automating the stack saving in the stacks close request.
I hope that was of some help, if a bit late. If you would like to see a good demonstration of it, making one will be very easy.
On the general question, Klaus (and Jacque's follow up) nail most situations, but Craig's answer deserves a little more explanation.
It can be like you see in the bold/italic/underlined above, however it usually is even simpler than that. You don't use the 'splash stack' as the main program, but merely as a way to launch the main program.[3] Splash stack
I'm still unclear on the use case here. Conceptually I understand that you need the executable "Splash" to edit and work on data it can save to "the stack". However, as a practical matter, I can't seem to wrap my head on what's happening or what this solution looks like.
Since the main program is a non-compiled stack, as long as you have ...
Code: Select all
on closeStack -- automatically save changes
save this stack
pass closeStack
end closeStack
You will notice this behavior when editing stacks in the IDE, for instance, when you save a stack in work. The only difference here is that you are automating the stack saving in the stacks close request.
I hope that was of some help, if a bit late. If you would like to see a good demonstration of it, making one will be very easy.
Last edited by bogs on Wed Aug 16, 2023 7:59 am, edited 1 time in total.
-
- Livecode Opensource Backer
- Posts: 9444
- Joined: Fri Feb 19, 2010 10:17 am
- Location: Bulgaria
Re: Standalone: Saving prefs
Personally I store prefs in my 'Home' folder as a simple comma delimited text file.
Re: Standalone: Saving prefs
I must say that’s one of my big bears as a user. I detest it when apps clutter my home folder with random files, it’s just rude…. There are dedicated locations for preferences and really these should be used.
-
- Livecode Opensource Backer
- Posts: 9444
- Joined: Fri Feb 19, 2010 10:17 am
- Location: Bulgaria
Re: Standalone: Saving prefs
As Macintosh apps are disguised folders it is perfectly possible to save preferences inside them.
Last edited by richmond62 on Sat Aug 26, 2023 12:32 pm, edited 1 time in total.
-
- VIP Livecode Opensource Backer
- Posts: 7255
- Joined: Sat Apr 08, 2006 8:31 pm
- Location: Minneapolis MN
- Contact:
Re: Standalone: Saving prefs
Well look who's back. Nice to see you, Bogs.I came here for a different purpose, however, the question posed was interesting to me, so I thought I would input my .02 (worth less due to inflation).
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com
HyperActive Software | http://www.hyperactivesw.com
Re: Standalone: Saving prefs
You'd think so wouldn't you? But no........richmond62 wrote: ↑Wed Aug 16, 2023 1:58 amAs Macintosh apps are disguised folders it is perfecyly possible yo save preferences inside them.
Apps are immutable (even if it's a folder pretending to be an App bundle). You would break the codesigning if you edited the app bundle.
There is good reason you haven't seen any Mac apps do this!
The correct place to put preferences on MacOS is in the Preferences folder of the user's library: ~/Library/Preferences
This is where specialFolderPath("preferences") points to on Mac
As far as I can tell, there is no direct equivalent on Windows (I guess usually stored in the registry, if that's still a thing?). But I guess you could store a prefs file in the user's AppData folder - specialFolderPath("support") or Documents - specialFolderPath("documents")
-
- Livecode Opensource Backer
- Posts: 9444
- Joined: Fri Feb 19, 2010 10:17 am
- Location: Bulgaria
Re: Standalone: Saving prefs
Aha . . .
That is because I have only saved prefs files inwith Mac app 'folders' with standalones deployed on my own machines.
That is because I have only saved prefs files inwith Mac app 'folders' with standalones deployed on my own machines.
Re: Standalone: Saving prefs
I think the most reliable and easiest way is to store the preferences in an array, and use the arrayEncode() and arrayDecode() functions.
Here is a shortened example of what I always use:
Here is a shortened example of what I always use:
Code: Select all
local gArrPrefs // preferences array
local gPrefsFileName // your preferences file name
on openStack
prefsDefaults // initialize default prefs
put "MyAppPrefs.bin" into gPrefsFileName // define your preferences file name
prefsFileRead // read previous prefs file (if exists)
end openStack
on closeStack
// eventually update prefs here...
prefsFileWrite
end closeStack
on prefsDefaults
put "YourData1" into gArrPrefs["data1"]
put "YourData2" into gArrPrefs["data2"]
put "YourSubData1" into gArrPrefs["data3"]["subData"]
// ...
end prefsDefaults
on prefsFileRead
put getPrefsFolder() & gPrefsFileName into prefsFile
if (there is a file prefsFile) then
put URL ("binfile:" & fichierPrefs) into encodedArr
put arrayDecode(encodedArr) into gArrPrefs // defaults prefs are overriden by existing prefs file
end if
end prefsFileRead
on prefsFileWrite
put getPrefsFolder() & gPrefsFileName into prefsFile
put arrayEncode(gArrPrefs, 7.0) into URL ("binfile:" & prefsFile)
if (the result <> "") then answer error "ERROR : Unable to save preferences file." with "Continue"
end prefsFileWrite
function getPrefsFolder
if the PlatForm = "MacOS" then
return specialFolderPath("preferences") & slash
else return specialFolderPath("documents") & slash
end getPrefsFolder
-
- Livecode Opensource Backer
- Posts: 9444
- Joined: Fri Feb 19, 2010 10:17 am
- Location: Bulgaria
Re: Standalone: Saving prefs
Why not store preferences as a comma-delimited text file?
Here's some code I nicked from some of my own work [Devawriter Pro] just for saving a textField . . . which can, quite obviously be used to export the contents on a tableField:
As long as you are confident about the file structure of your clients' computers [risky, very risky] you can set the
automatically, rather than let a client choose their own location; thereby making it easy for your standalone to 'know' where to look for a prefs file.
Here's some code I nicked from some of my own work [Devawriter Pro] just for saving a textField . . . which can, quite obviously be used to export the contents on a tableField:
Code: Select all
ask file "Choose where you wish to export your text"
if the result = "cancel"
then exit mouseUp
else
put the RTFtext of fld "fRESULT" into url("file:" & it & ".rtf")
get the longFilePath of it
set the itemDelimiter to slash
set the defaultFolder to item 1 to -2 of the longFilePath of it
end if
Code: Select all
url("file:" & it & ".rtf")