Copy link to clipboard
Copied
I am interested to find out how a preference file works with a custom script.
How is the preference file or settings file normally attached to the script?
Does this makes sense to attach the parent-settings.jsx to the parent .jsx script?
parent.jsx
parent-settings.jsx
Put your variables to 'parent-settings.jsx' and at beginning of 'parent.jsx' use evalFile() method with path to 'parent-settings.jsx' to collect its content for later use by 'parent.jsx'.
Ok, I revamped my script. It now allows for you to create a default preference, as well as saved preferences. You can save various preferences, using the Create New Preset Button. If you want to actually use that preset and set it as the default, you first select it in the dropdownlist then hit the Save as Default button.
To actually get the values to another script, copy the code for the UI to that script. You can omit all the onClick and onChange functions within the block to make the UI. In
...You still need all this code in the script that reads the XML
///////////Preference and XML vars YOU NEED ALL THIS CODE
var presetList = new Array( );//Blank array to be populated with the users preferences stored in an XML file
var xmlFile = new File('~/Desktop/XYZ/xmlTest.xml');
if(xmlFile.exists){
prefXML = new XML(readXMLFile(xmlFile))
};// see if a preference file exists and load it.
else {alert('There is no preset file')}
var dlg = new Window('dialog','XML Test
...
Copy link to clipboard
Copied
Probably only you understand what you are talking about.
Copy link to clipboard
Copied
How does a script call a preference/settings file?
Copy link to clipboard
Copied
First of all I don't know what you mean by parent.jsx & parent-settings.jsx.
Copy link to clipboard
Copied
Let’s say the parent.jsx script changes the text font family in the open document.
To assign a new font family change the font family variable in the paren-settings file.
Does this make sense?
Copy link to clipboard
Copied
Put your variables to 'parent-settings.jsx' and at beginning of 'parent.jsx' use evalFile() method with path to 'parent-settings.jsx' to collect its content for later use by 'parent.jsx'.
Copy link to clipboard
Copied
Thank you. I will give the evalFile() method a try.
Copy link to clipboard
Copied
Was my tip working that (I guess) you marked your reply as correct solution?
Copy link to clipboard
Copied
Absolutely! Thank you! I'll start by testing the evalFile () method, then add a UI. Next, add the UI and xml.
Before I asked the question, I did not know how to make sense of the preference file.
Now I have a good idea of what needs to happen.
Manay thanks to you all!
Copy link to clipboard
Copied
The eval method does work for getting a varaible from a separete script. Howwever when I add a simpe UI to the script the eval methis calls the UI and varaible instead of getting the varaible from the UI.
The other apporach is to write the UI input into a separete xml file and have the script read the values from the xml file. I am not familair with this alst apporach so I need to investigate it.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Not sure if this applies for what you want to do, but I use a recursive function to save all variables in a scripts UI to an XML file. The nice thing about the function that I created is that you can change the UI and you don't need to modify the save function. You can see an example of it in this thread on changing the arrowheads.
Copy link to clipboard
Copied
Absolutly, that applies! in the past, I have not used a preference file with a custom script. So I like to start with a super simple test and then move to more complex preference file concepts sucha as including an UI and saving settings to an xml file. Many thanks for providing the refrence link!
Copy link to clipboard
Copied
What about reading preferences from the other .jsx file, as you wanted. Does it work?
Copy link to clipboard
Copied
I have not try it yey, but I think it should work.
Copy link to clipboard
Copied
I know I posted an example with one script that I wrote, but here is a simplified version of just the UI and the code to save the UI variables to an XML file. Like I said before, the nice thing about this script is that you can change the UI at any time and the script will read the UI and store all the variables.
///////////Preference and XML vars
var startNodes = new XML('<root><presets/></root>');//creates a start for addin info to the XML preference file.
//var startNodes = new XML('<root><presets><preset presetName ="Current Default"/></presets></root>');//creates a start for addin info to the XML preference file.
var prefXML = new XML();// the actual XML file that holds the preferences until written to a file.
//var prefXML = new XML();// the actual XML file that holds the preferences until written to a file.
var presetList = new Array( );//Blank array to be populated with the users preferences stored in an XML file
var saveName;//Name for the saved preset
var xmlFile = new File('~/Desktop/XYZ/xmlTest.xml');
if(xmlFile.exists){
prefXML = new XML(readXMLFile(xmlFile))
};// see if a preference file exists and load it.
else {prefXML = startNodes}
var dlg = new Window('dialog','XML Test')
/////////All elements separated in a separate window
///////////////////////////////////////////////////////////////////////////////////////////
var dlg = new Window('dialog','XML Test')
var myCheckBox = dlg.add('checkbox',undefined,'Check Box'); myCheckBox.name='myCheckBox';
var myRadio1 = dlg.add('radiobutton',undefined,'Radio 1'); myRadio1.name='myRadio1';
var myRadio2 = dlg.add('radiobutton',undefined,'Radio 2'); myRadio2.name='myRadio2';
myRadio1.value = true;
var myEditT = dlg.add('edittext',undefined,'Edit Test '); myEditT.name='myEditT';
var myStaticT = dlg.add('statictext',undefined,'Static Test '); myStaticT.name='myStaticT';
var mySlider = dlg.add('slider',undefined,25,0,100); mySlider.name='mySlider';
var myDropList = dlg.add('dropdownlist',undefined,['one','two','three']); myDropList.name='myDropList';
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
/////////////////////////////////// This needs to be in any dialog box for the presets to work///////////////////////////////////////////////////////////
/////////////////////////////////// The name of the dialog has to match whatever is in the current UI///////////////////////////////////////////
dlg.gp = dlg.add('group');
dlg.gp.orientation = 'row';
var presetListDrop = dlg.gp.add('dropdownlist',undefined, ['No Presets']); //presetListDrop.name = 'presetListDrop';
presetListDrop.size = [200,16]
presetListDrop.selection = 0;
presetListDrop.onChange = function(){//updates UI when new preset is selected
if(prefXML.presets.children().length()>0){//loads presets into UI
setUIvar(prefXML,parseInt(presetListDrop.selection),dlg);
};
};
var saveP = dlg.gp.add('button',undefined,'Create New Preset')
var deleteP = dlg.gp.add('button',undefined,'Delete Current Preset')
saveP.onClick = function(){
var goodName = true;
saveName = prompt ('Enter a name for the preset', '', 'Preset Save');
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
for(var i=0;i<presetListDrop.items.length;i++){
if(presetListDrop.items[i].text==saveName){
goodName = false;
alert(saveName +' is already in use. Choose another name.')
}
}
if(saveName && goodName){
storePrefs()
presetListDrop.selection = presetListDrop.items.length -1
}
};
deleteP.onClick = function(){
if(isNaN(parseInt(presetListDrop.selection))){alert('You must select a preset to delete first')}
else{
var delPre = confirm ('Do you want to delete the preset "' + presetListDrop.selection.text +'"?', 'Yes', 'Delete Preset')
if(delPre){
delete prefXML.presets.preset[parseInt(presetListDrop.selection)];
setPresetList();
writeXMLFile(xmlFile,prefXML);
presetListDrop.selection = 0
}//end if
};//end else
};//end function
if(prefXML.presets.children().length()>0){//loads presets into UI
setPresetList()
setUIvar(prefXML,0,dlg)
//presetListDrop.selection = 0
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var myOkButton = dlg.add('button',undefined,'Close');
myOkButton.onClick = function(){dlg.close()};
dlg.show();
////////////////////////////////Presets//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//function to add a new preset
function storePrefs(){
var tempXML
tempXML = new XML('<root><presets><preset presetName ="' + saveName + '"/></presets></root>');
setXML(tempXML,0,dlg);
prefXML.presets.appendChild (XML(tempXML.presets.preset[0]))
setPresetList();
writeXMLFile(xmlFile,prefXML);
};//end function storePrefs
/////////////////////////////////////////////////////////////////////////////////////////////////////
//function loops through the ui object and if the control items have been assigned a name it stores the name and the value to an XML file.
function setXML(x,n,d){//x = xml file, n = starting node, d = dialog.
for(var i = 0;i<d.children.length;i++){
if(d.children[i].type == 'panel' || d.children[i].type == 'group' || d.children[i].type == 'tabbedpanel' || d.children[i].type == 'tab'){setXML(x,n,d.children[i])}//loops though UI and restarts function if it comes to a container that might have more children
else{
if(d.children[i].name){//check to make sure the control has a name assigned so that it only records those with name.
switch(d.children[i].type){
case 'radiobutton':
x.presets.child(n).appendChild(XML('<' + d.children[i].name +' type="' + d.children[i].type + '">' + d.children[i].value + '</' + d.children[i].name + '>'));
break;
case 'checkbox':
x.presets.child(n).appendChild(XML('<' + d.children[i].name +' type="' + d.children[i].type + '">' + d.children[i].value + '</' + d.children[i].name + '>'));
break;
case 'slider':
x.presets.child(n).appendChild(XML('<' + d.children[i].name +' type="' + d.children[i].type + '">' + d.children[i].value + '</' + d.children[i].name + '>'));
break;
case 'edittext':
x.presets.child(n).appendChild(XML('<' + d.children[i].name +' type="' + d.children[i].type + '"><![CDATA[' + d.children[i].text + ']]\></' + d.children[i].name + '>'));
break;
case 'dropdownlist':
if(d.children[i].selection){varHold = d.children[i].selection.text}
else{varHold = 'null'};
x.presets.child(n).appendChild(XML('<' + d.children[i].name +' selecIndex="' + d.children[i].selection + '" type="' + d.children[i].type + '"><![CDATA[' + varHold + ']]\></' + d.children[i].name + '>'));
break;
};//end switch
}//end if for child having name
};//end else
};//end for loop
}//end function setXML
////////////////////////////////////////////////////////////////////////////////////////////////
//function loops through the ui object and if a control item has been assigned a name uses that name to look up the preset value in the XML.
function setUIvar(x,n,d){//x= xml file; n = node number (0 is default node), d = UI dialog
var currentXMLVal;//used to store values from XML file. When this value is assigned, it checks to see if value from XML exist
var noMatch = false
for(var i = 0;i<d.children.length;i++){
noMatch = false;
if(d.children[i].type == 'panel' || d.children[i].type == 'group' || d.children[i].type == 'tab' || d.children[i].type == 'tabbedpanel'){setUIvar(x,n,d.children[i])};//reruns function if child is container and not control item.
else{
if(d.children[i].name){//Checks to see if child has a name assigned so only will reset those control items that have a name will be stored.
try{
//Assigns all variables from presets node. The "n" tells which preset to select.
currentXMLVal = x.presets.preset[n].child(d.children[i].name);
if(currentXMLVal == 'null'){currentXMLVal = null};
}//end try
//catch assigns 'no_good' to current XMLVal so that if there is no value in the XML file, it will not try to assign a bad value to the UI controls.
catch(e){currentXMLVal = 'no_good'};//end catch
//switch makes sure proper type of value is reassigned back to UI controls.
if(x.presets.preset[n].child(d.children[i].name).length() > 0 || d.children[i].type == 'button'){
switch(d.children[i].type){
case 'radiobutton':
d.children[i].value = returnBoolean(currentXMLVal);
break;
case 'checkbox':
d.children[i].value = returnBoolean(currentXMLVal);
break;
case 'edittext':
d.children[i].text = currentXMLVal;
break;
case 'slider':
d.children[i].value = parseFloat(currentXMLVal);
break;
case 'dropdownlist':
varHold = false;
if(x.presets.preset[n].child(d.children[i].name).@selecIndex.toString() == 'null'){d.children[i].selection = null}
else{d.children[i].selection = parseInt(x.presets.preset[n].child(d.children[i].name).@selecIndex)};
break;
};//end switch else
};//end if to see if there is a good value from the XML
};//end if for UI control having name
};//end else for if child is container or control
};//end for loop
};//end function setUIvar
//function returns a boolean value. Values stored in XML are returned as strings, so they need to be converted back to boolean values.
function returnBoolean(b){
if(b == 'true'){return true}
else{return false}
};
//Function resets the values of the preset list when items are added or deleted.
function setPresetList(){
presetList = new Array();
presetListDrop.removeAll();
for(var i=0;i<prefXML.presets.children().length();i++){presetListDrop.add('item',prefXML.presets.children()[i].@presetName)}
};//end function setPresetList
function readXMLFile(file) {
if (!file.exists) {
alert( "Cannot find file: " + deodeURI(file.absoluteURI));
}
else{
file.encoding = "UTF8";
file.lineFeed = "unix";
file.open("r", "TEXT", "????");
var str = file.read();
file.close();
return new XML(str);
};
};
function writeXMLFile(file, xml) {
file.encoding = "UTF8";
file.open("w", "TEXT", "????");
//unicode signature, this is UTF16 but will convert to UTF8 "EF BB BF"
file.write("\uFEFF");
file.lineFeed = "unix";
if (!(xml instanceof XML)) {
for(var g=0;g<scriptArray.length;g++){
try{
file.writeln (scriptArray[g].toString())
}
catch(e){}
};//end for loop
}
else{file.write(xml.toXMLString())};
file.close();
};
Copy link to clipboard
Copied
Hi Chusck, thanks for provising the simplifed script version. It is useful to see the UI, script together and xml file interacting. Somehow, the script is not generating the xmlTest file on the desktop.
I made a screen recording to show what happesn when the script runs.
Let me know if you have any ideas why the xml file is nt genrating on the desktop.
https://imageasel.com/wp-content/uploads/Screen-Recording-2022-02-26-at-5.23.10-PM.mp4
OSX Catalina
Copy link to clipboard
Copied
I guess I should have tried the script first. There were some issues, which should be fixed now. I replaced my previous script with the corrected one. Try that, now.
Copy link to clipboard
Copied
Thanks for making the changes. Can we walk through your example to understand how the preference file interacts with another script?
The script generated the following xml code on the desktop
<root>
<presets>
<preset presetName="Workstation">
<myCheckBox type="checkbox">false</myCheckBox>
<myRadio1 type="radiobutton">false</myRadio1>
<myRadio2 type="radiobutton">true</myRadio2>
<myEditT type="edittext"><![CDATA[OSX]]></myEditT>
<mySlider type="slider">25</mySlider>
<myDropList selecIndex="null" type="dropdownlist"><![CDATA[null]]></myDropList>
</preset>
</presets>
</root>
How do I read the myRadio1 xml node from another script?
var f = new File('~/Desktop/XYZ/xmlTest.xml');
f.open('r');
var xml = new XML( f.read() );
f.close();
//root node
//child node
//myRadio1 node
Copy link to clipboard
Copied
My s ript is really designed to be inserted into any script. The UI portion in the script, is just an example. It is replaced with whatever UI design, and it will record those values. Why do you want it read by a second script? It would be possible, but then, I think that you would have to set up an object with named nodes that match the original UI.
Copy link to clipboard
Copied
Let me try to clarify how I see the preference file working with an additional script.
The preference file UI allows the user to change the behavior of script1.
Script1 can run function A or function B and by default, runs function A.
To run function B set the preference file UI button to function B.
The preference file remembers the last setting.
Script1 reads the preference file to check which function to run and does not display the preference UI when checking.
To change the function in script1 open the separate preference file and choose function A or B
Do you think this approach makes sense?
Copy link to clipboard
Copied
That makes sense. So would you want to set up two different preferences with multiple variables, or just a select A or B option? And yes, that can be done, as I did that with a script that I used to use at work.
Copy link to clipboard
Copied
I apologize for my lack of understanding. What is the difference between two differnt preferences with multiple variables and the A or B option?
Copy link to clipboard
Copied
Ok, here are some options on how you can handle this:
A or B option: the ui comes up and you can select A or B (or whatever you want to call it) The code for thes two options are hard coded into you production script. The UI just stores which option you want - no other variables are stored. You really don't need an XML for this - just a CSV file will work.
Last saved default:
With this option, someone opens the UI makes changes to a variety of different controls (checkboxes, sliders, etc) and the values are stored in the XML. Then you run your production script. It reads the XML file and uses the last saved default values from the XML.
Saved preferences:
With this, you open the UI, make changes to the controls and then save those controls as difference preferences that you can then have your production script call. So say you have one preference file called routine A, which loads a set of values that you use often. Then you might have routine B that stores another set of values that you use at a different time. You can then either hard code your production script to only select one of the routines, or you can open the ui select one of the saved preferences and then store those as the default to be used by your production script.
Currently, the script that I posted, just stores preferences, and when you select a saved preference, it will change the values in the UI, in that script. To open those values from another script would require some modification.
Copy link to clipboard
Copied
Thanks for explaining the options. I think the Saved preferences option sounds the best but is probably the most complex approach. The Last saved default option sounds good and is probably easier. To be honest, I’m not sure how to code the last saved default option. A sample code would be very useful.