Okay the pointer on bindings is slick! What bindings are doing here is actually writing a automatically file in ~/Library/Preferrence/ for any variable in the NIB wondow you specifiy You never even have to ask for this write to disk. You just get it once you click on bindings. THe second thing these things do is they become global variables in your applescript program.
So in a nutshell they replace traditional applescript properties for persistent variables and at the same time get their values right off the interface without one having to ask.
However It does seem sub optimal that you can’t separate that functionality. For example suppose you wanted to have a variable tied to an inteface builder value but you did not want it to be persistent (and therefore written to disk). Looks like you are stuck with the disk write to get that tie.
anyhow back to implmenting this.
So far I’m having three different sorts of problems with this binding.
-
for some reason I dont understand yet, not all of my bound values are acting peristent. I suspect I must have to do some sort of NSObject synchonization call to force that. But have not figured out the inconsistency.
-
all copies of an application will use the exact same preferences file!!! this means that if the user makes a new copy of the application, sets the preferences in that copy to some value, then this globally changes the preference in all other copies fo the application. THis is a much different behaviour than persistent properties in regular (non-ASS) applescript. There different copies of apps had separate preference.
THe reason this is undesirable is that for a Dropplet applescript one is often configuring multiple instances of the application to do different things. e.g. put all the files dropped on this dropplet in a particualr folder, and all the files droped on a different dropplet in another folder. One might do this by having the same applescript dropplet be user configurable about the destinastion folder. Can’t do that if all copies of an application share the same properties.
- since this is a preferences panel, I want to offer the user a cancel button in case they dont want to save any changes to the preferences they just made. If the interface fields are bound directly to the preference properties then al changes the user makes are committed to the disk as they are made. I don’t see any way around that when using bindings.
To get around that there are two possible ways to go that I can see. The horrid method is the one I started with. Dont use bindings: instead create defaults using the user-defaults class then laboriously copy all of those into the form fields when the panel awakens, then when the window closes laboriously copy all those form fields back out into the user-defaults.
A better method that requires less knowledge about the view one is using to present the text fields is to use bindings as above. But when the window awakes, store a temproary copy of all the bound variables. If the window closes with a “cancel”, you copy back the stored values, otherwise do nothing. THis still requires some laborious copies to specific bound variables but does not require any knowledge of the interface, so it’s much better design.
However implementing this in a nice way is driving me batty.
What I’m trying to do to keep this clean, is rather than hard-code every single copy-out then have a matching hard coded copy-in, is I want to have a list of all the bound variables and then process that list. THis would be a re-usable general purpose “undo” functionality for any bound interface you built. Just supply the list of variables to allow the undo on.
Now to do that one has to have a list of reference to the variable, not their contents. And there is the problem I’m having. I get errors when I try to take reference to bound variables. The message refers to some problem with taking a reference to an NSDictionary type (which I assume is the bound variable’s underlying ccocoa object class)
Here is a snippet of the code where I try to do this:
global orig_property_list -- I'm going to store the cached values in here
global property_list -- global variable to simplfy passing this around
-- my bound variables are called "scriptText" and "hideOutput"
on will finish launching theObject
-- here is key step, a list of names and references to my bound variables
-- it's this list that I will say which bound variables do I want to keep copies of
set property_list to {{theName:"scriptText", theValue:a reference to the scriptText}, {theName:"hideOutput", theValue:hideOutput} }
stashDefaultProperties()
end will finish launching
on stashDefaultProperties() -- make copies of the current values of all the bound variables in the property_list
set orig_property_list to {} -- start with empty set and accumulate into it
repeat with theSet in property_list
set thisName to the theName of theSet
set theOrigValue to theValue of theSet -- get the bound variable's value
set the end of orig_property_list to {theName:thisName, theValue:theOrigValue}
end repeat
-- no value is returned but the results have gone into the global variable orig_property_list
end stashDefaultProperties
THe errors I are like the above. if you look at what is in the property list it’s missing the “theValue” entries:
{{theName:"scriptText"}, {theName:"hideOutput"}}
So is there a way to do this? or is one forced to use non-reusable hard coded copies?