Stack data i/o question

Anything beyond the basics in using the LiveCode language. Share your handlers, functions and magic here.

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

mbossiere
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 47
Joined: Wed Aug 01, 2007 2:15 am

Stack data i/o question

Post by mbossiere » Mon Dec 15, 2014 5:50 pm

I have some limited experience with building standalones from my stacks on the Mac OS and none building mobile apps out of them. My question is about input/output of the data written to objects in my stack by the user, as well as properties set by the user when the stack is frozen as a standalone. My understanding is that as a standalone or a mobile app the stack cannot contain user input or changes except when actually running. At quit time, all data added by the user is lost unless it is saved to external files via some elaborate i/o library of my own devising. My question is, is there some sort of built in LC mechanism which I'm overlooking for keeping added user data across launch-quit cycles? Any help is appreciated, before I hunker down and write my own i/o routines. I'm hoping some genius here will casually point out the existence of some LC property I can set to automagically solve this problem!
“You do what you do out of your own private passion for the thing itself”
A Dillard (source: https://educheer.com/essays/annie-dillard-s-handed-my-own-life/)

Klaus
Posts: 14208
Joined: Sat Apr 08, 2006 8:41 am
Contact:

Re: Stack data i/o question

Post by Klaus » Mon Dec 15, 2014 6:01 pm

Bonjour mbossiere,

I just answered another posting which might shed some light on your problem :D
Check this: http://forums.livecode.com/viewtopic.ph ... 54#p114942


Best

Klaus

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10354
Joined: Wed May 06, 2009 2:28 pm

Re: Stack data i/o question

Post by dunbarx » Mon Dec 15, 2014 6:14 pm

This is a common question. The executable cannot save changes to itself. So any stack file attached to the executable similarly cannot be changed.

But that is not a problem at all. This will take just a few minutes to learn. Make a stack with a button. Name the stack "Splash". Save it. Put a handler in the button script that opens another stack named "test". Make a new stack with a field in it. Name that new stack "test". Put a closeStack handler in the stack script that saves the stack. Save the stack. In the standalone settings, in the "stacks" pane, attach the "test" stack file to the "splash" stack file. Make the standalone.

I am saying this from memory, but it should be most of what you need to do. Open the standalone, click the button, and write into the field on the other stack. Quit the standalone. When you re-open, the text should be there. Do you see, (even if a few tweaks are needed to make all this work)? The "splash" stack can be hidden if you want to, need do very little or nothing at all, and the "working" stack(s) are where the, er, work happens.

Craig Newman

sturgis
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 1685
Joined: Sat Feb 28, 2009 11:49 pm

Re: Stack data i/o question

Post by sturgis » Tue Dec 16, 2014 4:12 am

Yeah, what dunbarx and Klaus said. The only provision is, you need to make sure your "splashstack" loads all the libraries that will be needed by your other stack. For example, I don't know if its still required, but to use the splashstack method with a datagrid, you needed to have a substack of your splashstack named something like (from long ago memory) "datagrid stub" or something of that nature. I can find a link to it if you need.

Since the engine is very smart, and can look at your code and do a pretty good job of guessing, what libraries you need, if most of your code will NOT be in the stack you're building as a splash, you'll have to manually include the libraries.

When i'm doing this, I tend to put as much code as I can in a substack of the splashstack and use it as a library stack "start using stack..." That way the standalone gets built properly, and other than the datagrid thing I mentioned earlier, should be quick and easy. Then, as dunbarx said, add a stack as part of the files of your splash stack. Heck, I think it can even be a substack that is saved as part of the standalone, and on first launch, a) see if there is already a stack saved into a writable location. if not, set the name and filename of the substack you are using as a template and save it to a writable location (like documents or wherever).Then simply open the saved stack file. (go stack stackname) On exit, save it again and the changes will stick. If the file is already there, just "go stack <whatevername>" to open the last saved version.

Not sure how much you have poked around with lc yet, but you'll probably need to look at "if there is a file..." and of course specialfolderpath in the dictionary.

Edit: Heres a link to information about using splashstacks. http://lessons.runrev.com/m/4071/l/1737 ... pplication

Here is a link to a place that mentions how to deal with a datagrid and splashstack (launcher). http://lessons.runrev.com/m/datagrid/l/ ... -data-grid

mbossiere
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 47
Joined: Wed Aug 01, 2007 2:15 am

Re: Stack data i/o question

Post by mbossiere » Tue Dec 16, 2014 5:07 am

Thank you, dunbarx, Klaus, and sturgis. I am very much intrigued by the ideas set forth. I have enough LC background to know "if there is a file" and "specialfolder" but I admit I am still a little baffled by the description laid out here of using another stack as the repository (and I thank sturgis for fleshing this out further). I have not tied what you suggest, but I will. Datagrids are not something I have any familiarity with, so you thoroughly lost me there. But the basic idea of a stack as a repository for user data makes good sense EXCEPT does that not prevent distributing the standalone to non-LC users? And it rules out mobile apps too, as it is not possible to run an uncompiled stack there either.
Still, I want to understand your concept as it sounds very useful (and simple). My (untested) ideas for an I/O library have revolved around a library stack (start using...) which I can attach to any existing stack I have in order to identify all the controls I want access to (maybe a grouped set of controls) and then send every change in them (via closeField or textChanged handlers) to disk a based text file or files.
(btw, Klaus' script, "put fld "user_data" of cd 1 into url("file:" & tFile)" fascinates me too as I am not familiar with the url() structure as an alternative to write/read operations -- would like to know more)
So my questions are about what more specifically dunbarx and sturgis have in mind... it seems remarkably free of custom scripting! If I go with inserting my own I/O library stack i hope to make it very much applicable to any old Hypercard stack I choose to convert and ultimately rework as standalone. I'd like to take an existing stack with 1000 plus cards (and myriad flds and btns, etc) and export each of those cards initially to text file/s. Then, with a single-card version of that stack (and I/O library attached) I'd like to re-import that data and, from that point on, have it written dynamically to disk by the app as the app is used. At this point, I'd be happy just to have the text contents of flds and btns written, but was hoping later to build a way to save control property settings (to be save then reloaded at runtime).
Incidentally, I'm curious why dunbarx and sturgis use the names "Splash" and "test"? Maybe if I understood the significance of these names I would understand better the concept they are trying to convey to me. I will explore what I can do with this concept (using a non-compiled stack as a data repository) when I have a few hours free later this week.
Thanks. Any other input is appreciated!
“You do what you do out of your own private passion for the thing itself”
A Dillard (source: https://educheer.com/essays/annie-dillard-s-handed-my-own-life/)

sturgis
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 1685
Joined: Sat Feb 28, 2009 11:49 pm

Re: Stack data i/o question

Post by sturgis » Tue Dec 16, 2014 5:25 am

Ah k, I see where part of the confusion lies. You aren't distributing an uncompiled stack. You're distributing a compiled stack, that contains all the drivers/libraries needed for your app to function.
Then, you are going to have a separate stack file that is used by your application.

TO see what I mean, try this. Create a simple stack that has a button that lets you choose a file. Once the file is chosen use that information to "go stack <path/to/the/file/you/chose"

Build the standalone, click the button, and choose a stack file. Viola. A stack that is NOT part of your standalone executable pops up and is usable. Assuming all the required libraries are included of course.

Now. IF the stack file that you chose has the line "save this stack" in its preclosestack handler (or even closestack).. any changes you've made to the stack will be reflected the next time you choose to open that particular stack file with your application. Many people make "stackrunner" stacks that do this. I have one somewhere that lets you drag stackfiles into a list so that you end up with an app that acts as a kind of menu. In this case, the list itself is stored in an sqlite database, but all the other stacks are external and can save themselves. (This type of thing is very handy for little tools and whatnot when you just want to use them and not be in the IDE)

There are several ways to include stacks in your application so that when they're deployed, you can create savable stack files. One way, is to put the stack file into a property, and then create it on the drive in a writable location on first run. Another is to have it is a substack, and again, on first run 1) name the substack as you would like, set its mainstack property to point to itself. (so that its its own mainstack) set the filename of the stack to a writable location, and save it. (if it already exists, load it from disk and you're ready to go.)

In both of the previous methods, since you're creating a new stackfile that is not part of the executable, you aren't modifying the executable. Its just treated as a regular old file, and you can do what you want with it. go stack <stackfilename> works dandy. Having said all the previous, I'm not sure how apple views this. I know on android (self publishing) it works like a champ. Apple is a bit odd though.

The links I sent (especially the second one) would be a good read.

EDIT: Actually its the first one you should read. 2nd is datagrid specific.




mbossiere wrote:Thank you, dunbarx, Klaus, and sturgis. I am very much intrigued by the ideas set forth. I have enough LC background to know "if there is a file" and "specialfolder" but I admit I am still a little baffled by the description laid out here of using another stack as the repository (and I thank sturgis for fleshing this out further). I have not tied what you suggest, but I will. Datagrids are not something I have any familiarity with, so you thoroughly lost me there. But the basic idea of a stack as a repository for user data makes good sense EXCEPT does that not prevent distributing the standalone to non-LC users? And it rules out mobile apps too, as it is not possible to run an uncompiled stack there either.
Still, I want to understand your concept as it sounds very useful (and simple). My (untested) ideas for an I/O library have revolved around a library stack (start using...) which I can attach to any existing stack I have in order to identify all the controls I want access to (maybe a grouped set of controls) and then send every change in them (via closeField or textChanged handlers) to disk a based text file or files.
(btw, Klaus' script, "put fld "user_data" of cd 1 into url("file:" & tFile)" fascinates me too as I am not familiar with the url() structure as an alternative to write/read operations -- would like to know more)
So my questions are about what more specifically dunbarx and sturgis have in mind... it seems remarkably free of custom scripting! If I go with inserting my own I/O library stack i hope to make it very much applicable to any old Hypercard stack I choose to convert and ultimately rework as standalone. I'd like to take an existing stack with 1000 plus cards (and myriad flds and btns, etc) and export each of those cards initially to text file/s. Then, with a single-card version of that stack (and I/O library attached) I'd like to re-import that data and, from that point on, have it written dynamically to disk by the app as the app is used. At this point, I'd be happy just to have the text contents of flds and btns written, but was hoping later to build a way to save control property settings (to be save then reloaded at runtime).
Incidentally, I'm curious why dunbarx and sturgis use the names "Splash" and "test"? Maybe if I understood the significance of these names I would understand better the concept they are trying to convey to me. I will explore what I can do with this concept (using a non-compiled stack as a data repository) when I have a few hours free later this week.
Thanks. Any other input is appreciated!

Klaus
Posts: 14208
Joined: Sat Apr 08, 2006 8:41 am
Contact:

Re: Stack data i/o question

Post by Klaus » Tue Dec 16, 2014 6:12 pm

Hi mbossiere,
mbossiere wrote:...btw, Klaus' script, "put fld "user_data" of cd 1 into url("file:" & tFile)" fascinates me too as I am not familiar with the url() structure as an alternative to write/read operations -- would like to know more...
this is quite simple! :D

Instead of using the long and verbose form:
...
open file xxx for read/write
write xyz to file xxx
close file xxx
...
you can have a ONE liner when accessing files using the URL syntax.
Basically we have 2 modes FILE and BINFILE, where FILE is merely for simple TXT/ASCII files and BINFILE for the rest.

You can use the syntax just like any chunk expression like this:
...
put fld "some text field" into tText
put specialfolderpath("desktop") & "/a text file.txt" into tFile

## Replace complete content of file if present or create a new file:
put tText into url("file:" & tFile)

## Append at end of file:
put tText AFTER url("file:" & tFile)

## Append at beginning of file:
put tText BEFORE url("file:" & tFile)

## And even:
put "new_word" into word 1 of url("file:" & tFile)
put line 3 of fld "a field" into line 3 of url("file:" & tFile)

## Read complete file into field or variable:
put url("file:" & tFile) into tText
put url("file:" & tFile) into fld "a text field
put line 3 of url("file:" & tFile) into line 3 of fld "a text field"

## Using a BINFILE, example which will read a PDF file into a custom property of a stack:
put specialfolderpath("desktop") & "/Your PDF here.pdf" into tFile
set the cStoredPDFFIle of this stack to url("binfile:" & tFile)

## Spit it out again later:
put the cStoredPDFFIle of this stack into url("binfile:" & tFile)
## etc., you get the picture :D
...

Best

Klaus

mbossiere
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 47
Joined: Wed Aug 01, 2007 2:15 am

Re: Stack data i/o question

Post by mbossiere » Tue Dec 16, 2014 7:02 pm

Awesome, Klaus! You've made my day! How did I never know about that??
I am excited also to try your suggestions at my next opportunity, sturgis. What I understand is, a stack compiled as executable has the capacity to act as an "engine" of sorts for an un-compiled stack attached to it?? This too is very exciting, as it could solve a problem I've been chewing on for the better part of two years -- never thought to just post my questions here! Thanks guys. Will report back here later.
“You do what you do out of your own private passion for the thing itself”
A Dillard (source: https://educheer.com/essays/annie-dillard-s-handed-my-own-life/)

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10057
Joined: Sat Apr 08, 2006 7:05 am
Contact:

Re: Stack data i/o question

Post by FourthWorld » Tue Dec 16, 2014 7:37 pm

mbossiere wrote:What I understand is, a stack compiled as executable has the capacity to act as an "engine" of sorts for an un-compiled stack attached to it?? This too is very exciting....
There are many useful implication for this which may make it even more exciting:
- your app can use any number of external stack files, a suite of mini-apps if you like
- stack files are very small
- because they're small they're easily updated
- they can even be downloaded over the internet and run in one command, e.g.:
go url "http://fourthworld.net/channels/lc/IdleHour.rev"
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

mbossiere
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 47
Joined: Wed Aug 01, 2007 2:15 am

Re: Stack data i/o question

Post by mbossiere » Wed Dec 17, 2014 5:42 am

Richard, I am experimenting with this now. Very cool. Is this a standard way people use to implement read-write apps to iOS and Android? I heard someone express some doubt that iOS cooperated with this kind of structure.
“You do what you do out of your own private passion for the thing itself”
A Dillard (source: https://educheer.com/essays/annie-dillard-s-handed-my-own-life/)

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7394
Joined: Sat Apr 08, 2006 8:31 pm
Contact:

Re: Stack data i/o question

Post by jacque » Wed Dec 17, 2014 8:15 pm

iOS works fine with that construct, but Apple doesn't allow apps to download files that contain executable code. That's where the doubt is. Stacks containing scripts are "executable" and may fail Apple's verification checks, but I haven't heard whether that's happened to anyone yet or not.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

mbossiere
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 47
Joined: Wed Aug 01, 2007 2:15 am

Re: Stack data i/o question

Post by mbossiere » Thu Dec 18, 2014 12:54 am

I've tried following the tutorial suggested by sturgis, "How do I save custom properties in a standalone application", and I'm running into some problems already. After constructing the "Launcher" and "Main Application" stacks and saving the Launcher as a standalone (pasting the scripts verbatim), I did as instructed:

"Now run the launcher, you should see the Main Application window, put into your name and check it displays. Now close the application, run the launcher and try Display Name again. The custom property storing your name should have been saved from the previous run."

... and all goes well except that my "Display Name" button does not work when running from the standalone (it works well in the LC dev environment -- answering my name or whatever -- so it's done right I think). From Main Application file (when run by the standalone), it simply doesn't respond. I can't figure out why.

Btw, I'm very excited to begin to comprehend two significant new (to me) concepts since starting this thread a couple days ago: (1) the (apparent) ability to use a Launcher to run a dynamic stack; and (2) Custom Properties.
Weak grasp of both so far, but both have my head crowded with possibilities!! Thx
“You do what you do out of your own private passion for the thing itself”
A Dillard (source: https://educheer.com/essays/annie-dillard-s-handed-my-own-life/)

sturgis
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 1685
Joined: Sat Feb 28, 2009 11:49 pm

Re: Stack data i/o question

Post by sturgis » Thu Dec 18, 2014 3:02 am

Would you mind zipping and posting your two stacks? Not the exe, but the stack you used to build the launcher.

My guess would be that in the standalone settings, "ask dialog" and "answer dialog" might not be getting included. You might check the standalone settings and "select inclusions manually" then make sure those 2 boxes are checked, as well as any other support libraries you might need. Another method to do this is put a dummy handler in the stack script that never gets called, that includes an "answer.." and "ask" (and you can do this with all kinds of other calls to trick the standalone builder into including the things you need)

Thats my guess, though seeing your stacks and building the launcher myself would help figure things out.

mbossiere
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 47
Joined: Wed Aug 01, 2007 2:15 am

Re: Stack data i/o question

Post by mbossiere » Thu Dec 18, 2014 6:54 am

Thanks. In my haste I didn't even look at the standalone settings or think much of them. You are exactly correct. Now I'm curious to know, why are Custom Properties suggested for keeping data? I find that data "put" normally in a fld will be saved just as readily. Is it just as good?
“You do what you do out of your own private passion for the thing itself”
A Dillard (source: https://educheer.com/essays/annie-dillard-s-handed-my-own-life/)

sturgis
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 1685
Joined: Sat Feb 28, 2009 11:49 pm

Re: Stack data i/o question

Post by sturgis » Thu Dec 18, 2014 5:34 pm

It all depends on your need. With the exception of variables of course, the state of the stack that is saved, will pop back up the same. Unless of course there are pre-open and open handlers that change things on startup.
Properties are nice because they're a way to store data in a stackfile that doesn't require other objects. So, if all you are doing is storing data, it leaves you with a tiny, efficient data store, that is object free, and you can even get and set the properties without specifically loading the stack. (get the whateverproperty of stack "path/to/the/stackfile.livecode" to... ) Admittedly, you can also set the text of a field, etc.
Propreties are just another convenient way to store information as part of your stack file. Once nice thing you can do with a property that I don't believe you can do with a field is, store an array.
set the mystoredarray of stack "whateverstack" to tDataArray.

Save the stack, next time you need that array, just
put the mystoredarray of stack "whateverstack" into myArray

I guess what i'm saying is that it pretty much boils down to what you need to do, and how you prefer to do it. Using fields as storage units works fine. So does using properties. Or regular old files, or a database. It all depends on what you want to accomplish.

EDIT: You might look at setprop and getprop in your property explorations. Handy things that allow for input to be pre-processed before being shoved into a property (or processed as data is pulled OUT of a property) In fact, you can even use them to manage virtual properties. (for example, you could have a getprop handler that looks at another property containing numbers, and return the sum... Silly example, but hopefully you get the idea)

Post Reply