Hi!
I’m looking for a solution which makes it possible for the user to save the current selections of the ComboBoxes in a named file and load them again if the user needs exactly these settings again.
All I found was this: http://macscripter.net/viewtopic.php?id=24606
But as I’m new to scripting at all I’m not sure if
“this is what I have to search for
“this is what I need
“it’s possible at all
I’m using Xcode 5.1.1 on OS X 10.9
Thanks for your help!
That posting was for AppleScript Studio, which is no longer supported. The easiest way to do what you want is to use bindings, and bind the value of each combo box to the Shared User Defaults Controller.
Thanks a lot! I bought your e-book and can now understand much more. Great work!
But I think in this case the User Defaults is not the solutions for me because I want the different combinations of many ComboBoxes’ values to save in different files and load them at a later point.
I managed to write the values of the ComboBox to a .plist. I didn’t use bindings as you suggested because I think they would collide with the Referencing Outlets I use for the same ComboBox in another part of the script. But nevertheless it works out for me so far.
Now I want to load them from the .plist back into the ComboBox respectively set the value of the ComboBox. I expected a line like
set ComboBox1's stringValue() to loadedChoiceComboBox1
could do that. But it seems much more difficult. This is the save/load part of my code (I deleted the many other ComboBoxes):
on saveSettings_(sender)
tell application "System Events"
-- create an empty property list dictionary item
set the parent_dictionary to make new property list item with properties {kind:record}
-- create new property list file using the empty dictionary list item as contents
set the plistfile_path to "~/Desktop/example.plist"
set this_plistfile to ¬
make new property list file with properties {contents:parent_dictionary, name:plistfile_path}
-- add new property list items of each of the supported types
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:boolean, name:"ChoiceComboBox1", value: ComboBox1's stringValue() as text}
end tell
end saveSettings_
on loadSettings_(sender)
set the plistfile_path to "~/Desktop/example.plist"
tell application "System Events"
tell property list file plistfile_path
tell contents
set loadedChoiceComboBox1 to value of property list item "ChoiceComboBox1" as text
set ComboBox1's stringValue() to loadedChoiceComboBox1
end tell
end tell
end tell
end loadSettings_
Also I’m not sure if a boolean kind is the write way to store the data.
Any suggestions, solutions, comments?
Thanks!
You don’t need to use System Events: use ASObjC. Just build your list of records, convert it to an NSArray, then save that using -writeToFile:atomically:, and read it in again using -arrayWithContentsOfFile:.
Sorry I don’t get it but maybe I’m getting nearer. I managed to build the ComboBox’s values via bindings to an Array Controller which has a binding to a list as you describe it in your book.
What doesn’t work is writing the .plist with writeToFile (it still works with System Events).
The problem:
Unrecognized function writeToFile_atomically_
Unrecognized function arrayWithArray_
why do these functions not work?
property theValues: {"apple", "banana", "orange"}
on saveSettings_(sender)
theValues's writeToFile:"/desktop/xxx.plist" atomically:true
end saveSettings_
You need to make an NSArray first:
property theValues: {"apple", "banana", "orange"}
on saveSettings_(sender)
set anNSArray to current application's NSArray's arrayWithArray:theValues
anNSArray's writeToFile:"/desktop/xxx.plist" atomically:true
end saveSettings_
Hi!
I finally managed saving a ComboBox’s value into a .plist file and updateing it by loading the value from the .plist again. Heres the code:
on saveSettings_(sender)-- save settings to .plist file
tell application "System Events"
-- create an empty property list dictionary item
set the parent_dictionary to make new property list item with properties {kind:record}
-- create new property list file using the empty dictionary list item as contents
set the plistfile_path to "~/Desktop/myes_settings.plist"
set this_plistfile to ¬
make new property list file with properties {contents:parent_dictionary, name:plistfile_path}
-- add new property list items of each of the supported types
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:boolean, name:"ChoiceComboBox1", value: ComboBox1's stringValue() as text}
end tell
end saveSettings_
on loadSettings_(sender)--loading .plist
set theOutputFolder to path to desktop folder as string
set thePListPath to POSIX path of (theOutputFolder & "myes_settings.plist")
tell application "System Events"
tell property list file thePListPath
tell contents
ComboBox1's selectItemWithObjectValue_(value of property list item "ChoiceComboBox1")
end tell
end tell
end tell
end loadSettings_
To make it more comfortable I’d like to give the user the chance to have a modal dialog where he can define filename and directory. I started with chapter 17 in your book and used
tell current application's NSSavePanel to set thePanel to makeSaveAt_types_name_prompt_title_(path to home folder, {"plist"}, "Project_Font", "Save the file", "Save As")
tell thePanel to set thePath to showModal()
if thePath = missing value then
log "Cancel pressed"
else
log thePath
end if
to have a modal dialog.
What I don’t understand is how to combine the two things. Can’t I just pass the variable thePath to the ºtell application "System Events"¹?
Go back and read message #4. You don’t need to use System Events at all to read in the property list – it’s just slowing things down.
Again thanks for your respond!
Okay, but this gives me only a .plist with the content of theValues. Am I doing something wrong?
on saveSettings_(sender)
set theOutputFolder to path to desktop folder as string
set thePListPath to POSIX path of (theOutputFolder & "Settings2.plist")
set anNSArray to current application's NSArray's arrayWithArray:theValues
anNSArray's writeToFile: thePListPath atomically:true
end saveSettings_
this leads to a .plist like:
fixed no-break space
no-break space
1 em
1/2 em
1/3 em
1/4 em
1/6 em
1/8 em
1/24 em
I want the users choice of the 9 possibilities above of more than 40 ComboBoxes in a .plist like:
ChoiceComboBox1
1/2 em
ChoiceComboBox2
1/8 em
ChoiceComboBox3
1/24 em
ChoiceComboBox4
1 em
ChoiceComboBox5
1/24 em
ChoiceComboBox6
1/8 em
...
Would your proposal make it also easier to have a modal save/load dialog?
You want to save a dictionary (ie, record) of the values, not an array/list. The saving method is the same. How you build the dictionary is up to you.
But if the choices are a fixed list, you should probably be using menus or matrixes rather than comboboxes.
Getting closer! I think ComboBoxes are the right choice for my intention.
The code for storing the choice of a ComboBox into a file combined with a modal save dialog:
set thePanel to current application's NSSavePanel's savePanel()
tell thePanel
its setMessage:"Save the data:"
its setAllowedFileTypes:{"plist"}
its setNameFieldStringValue:"Project_Fontname"
its setShowsHiddenFiles:false
its setTreatsFilePackagesAsDirectories:false
set returnCode to its runModal() as integer
end tell
if returnCode = (current application's NSFileHandlingPanelOKButton) as integer then
set thePosixPath to thePanel's |URL|()'s |path|()
set ChoiceComboBox1 to objectValueOfSelectedItem of ComboBox1
ChoiceComboBox1's writeToFile: thePosixPath atomically:true
else
-- cancel button
log "Cancel pressed"
end if
First thing is that I’m not sure how to put all values of the ComboBoxes in one file, the second thing is that it’s actually not a real .plist with and . Not sure if I can access them properly via e.g. “line 3” or something.
To me it would be easier if I could figure out why this doesn’t work:
on saveSettings_(sender)-- save settings to .plist file
set thePanel to current application's NSSavePanel's savePanel()
tell thePanel
its setMessage:"Save the data:"
its setAllowedFileTypes:{"plist"}
its setNameFieldStringValue:"Project_Fontname"
its setShowsHiddenFiles:false
its setTreatsFilePackagesAsDirectories:false
set returnCode to its runModal() as integer
end tell
if returnCode = (current application's NSFileHandlingPanelOKButton) as integer then
tell application "System Events"
-- create an empty property list dictionary item
set the parent_dictionary to make new property list item with properties {kind:record}
-- create new property list file using the empty dictionary list item as contents
set the plistfile_path to thePanel's |URL|()'s |path|()
set this_plistfile to ¬
make new property list file with properties {contents:parent_dictionary, name:plistfile_path}
-- add new property list items of each of the supported types
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:boolean, name:"ChoiceComboBox1", value: ComboBox1's stringValue() as text}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:boolean, name:"ChoiceComboBox2", value: ComboBox2's stringValue() as text}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:boolean, name:"ChoiceComboBox3", value: ComboBox3's stringValue() as text}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:boolean, name:"ChoiceComboBox4", value: ComboBox4's stringValue() as text}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:boolean, name:"ChoiceComboBox5", value: ComboBox5's stringValue() as text}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:boolean, name:"ChoiceComboBox6", value: ComboBox6's stringValue() as text}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:boolean, name:"ChoiceComboBox7", value: ComboBox7's stringValue() as text}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:boolean, name:"ChoiceComboBox8", value: ComboBox8's stringValue() as text}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:boolean, name:"ChoiceComboBox9", value: ComboBox9's stringValue() as text}
make new property list item at end of property list items of contents of this_plistfile ¬
with properties {kind:boolean, name:"ChoiceComboBox10", value: ComboBox10's stringValue() as text}
...
end tell
else
-- cancel button
log "Cancel pressed"
end if
end saveSettings_
Is it because of the limited scope of the variable?
No, it would be easier if you did as I suggested:
set theDict to current application's NSDictionary's dictionaryWithObjects:{ComboBox1's stringValue(), ComboBox2's stringValue(), ...} forKeys:{"ChoiceComboBox1", "ChoiceComboBox2", ...}
theDict's writeToURL:(thePanel's URL {}) atomically:true
Yes, you’re right! That would be much easier. Sorry, as you see Im not deep into it. :rolleyes:
Now I get this message, which confuses me:
2014-07-21 13:33:23.273 Myes 2.1[608:303] -[NSAppleEventDescriptor isFileURL]: unrecognized selector sent to instance 0x618000030de0
2014-07-21 13:33:23.277 Myes 2.1[608:303] *** -[AppDelegate saveSettings:]: -[NSAppleEventDescriptor isFileURL]: unrecognized selector sent to instance 0x618000030de0 (error -10000)
on saveSettings_(sender)
set thePanel to current application's NSSavePanel's savePanel()
tell thePanel
its setMessage:"Save the data:"
its setAllowedFileTypes:{"plist"}
its setNameFieldStringValue:"Project_Fontname"
its setShowsHiddenFiles:false
its setTreatsFilePackagesAsDirectories:false
set returnCode to its runModal() as integer
end tell
if returnCode = (current application's NSFileHandlingPanelOKButton) as integer then
set theDict to current application's NSDictionary's dictionaryWithObjects:{ComboBox1's stringValue(), ComboBox2's stringValue()} forKeys:{"ChoiceComboBox1", "ChoiceComboBox2"}
theDict's writeToURL:(thePanel's URL {}) atomically:true
end if
end saveSettings_
There’s a terminology conflict – it should be: |URL|(), not URL {}.
It works perfectly! Thank u so much!
One last thing. Do I have to use “objectForKey_(“ChoiceComboBox1”)” to call it again? Or “ComboBox1’s selectItemWithObjectValue_(value of property list item “ChoiceComboBox1”)”
I suppose its no longer -arrayWithContentsOfFile: as you suggested it in post #4.
on loadSettings_()
-- set up open panel
set thePanel to current application's NSOpenPanel's openPanel()
tell thePanel
its setMessage:"Choose an .plist:"
its setExtensionHidden:false
its setShowsHiddenFiles:false
its setTreatsFilePackagesAsDirectories:false
its setCanChooseFiles:true
its setCanChooseDirectories:false
its setAllowsMultipleSelection:false
its setResolvesAliases:true
set theResult to its runModal() -- show as a modal dialog
end tell
if theResult = current application's NSFileHandlingPanelOKButton then
set theURLs to thePanel's |URLs|() as list
return item 1 of theURLs
ComboBox1's objectForKey_("ChoiceComboBox1")--????
else -- user hit Cancel
return missing value
end if
end loadSettings_
You’d read it like this:
set theNSDictionary to current application's NSDictionary's dictionaryWithContentsOfURL:(thePanel's |URLs|()'s objectAtIndex:0)