Skip to main content
deckarduk
Inspiring
June 5, 2023
Answered

Storing a palette location and size...

  • June 5, 2023
  • 11 replies
  • 1076 views

Hi Everyone,

I'm trying to store the size and location of a palette so when the user re-executes a script their preferences are used.

Please can someone point me in the right direction. I know how to get the palette size but how do you check if that info already exists when the user starts the script again?

Thanks in advance.

This topic is closed to new replies. Start a new post to keep the conversation going.
Correct answer Peter Kahrel

You can store data in an app label -- as Brian suggests -- but I prefer to write it to a file because I use scripts in three or more versions of InDesign. Using app. labels wouldn't work very well then. Another advantage of using a file is that the content is easier to inspect and easier to reset/delete/change manually.

 

I use this genelal schema for working with config files. The config file is names after the script (so abc.jsx creates a config file abc.txt) and is stored in the script's folder. You can use a separate Reseources folder, that's probably neater.

 

The below script stores the window's location, but also the content of the two text fields. You can store anything you like: location, size (in case of resizeable windows), selected items in lists, selected radiobuttons and checkboxes, etc. etc. And restore the window's slections.

 

The file that's created looks like this:

 

({location:[317, 385], first:"Piet", last:"Vlerk"})

 

Here's the script:

function scriptPath () {
  try {
    return app.activeScript;
  } catch (e) {
    return File (e.fileName);
  }
}

// Write the config file
function saveData (obj) {
  var f = File (scriptPath().fullName.replace (/\.jsx?(bin)?$/, '.txt'));
  f.open ('w');
  f.write (obj.toSource());
  f.close ();
}

// Read the config file
function getPrevious () {
  var f = File (scriptPath().fullName.replace (/\.jsx?(bin)?$/, '.txt'));
  try {
    return $.evalFile(f);
  } catch (_) {
    return null;
  }
}

var w = new Window ('dialog');
  w.firstName = w.add ('edittext {characters: 10}');
  w.lastName = w.add ('edittext {characters: 10}');
  w.add ('button {text: "OK"}');
  w.add ('button {text: "Cancel"}');
  
w.onShow = function () {
  // Look for the config file
  var previous = getPrevious();
  // It was there, populate window
  if (previous !== null) {
    w.location = previous.location,
    w.firstName.text = previous.first,
    w.lastName.text = previous.last
  }
  w.firstName.active = true;
}

// OK clicked: store the window data
if (w.show() === 1) {
  saveData ({
    location: [w.location.x, w.location.y],
    first: w.firstName.text,
    last: w.lastName.text
  });
}

 

11 replies

TᴀW
Legend
June 6, 2023

Just one caveat: With Hi DPI monitors, just storing the window location isn't sufficient. It will open in a slightly different place each time. I can't quite remember why, but I think it's because the read-location factors in the hi-DPI, and the write doesn't, or vice versa.

See: Indiscripts :: ScriptUI vs. UI Scaling

id-extras.com | InDesign tools & scripts for typesetters, form designers, and translators
Peter Kahrel
Community Expert
Peter KahrelCommunity ExpertCorrect answer
Community Expert
June 6, 2023

You can store data in an app label -- as Brian suggests -- but I prefer to write it to a file because I use scripts in three or more versions of InDesign. Using app. labels wouldn't work very well then. Another advantage of using a file is that the content is easier to inspect and easier to reset/delete/change manually.

 

I use this genelal schema for working with config files. The config file is names after the script (so abc.jsx creates a config file abc.txt) and is stored in the script's folder. You can use a separate Reseources folder, that's probably neater.

 

The below script stores the window's location, but also the content of the two text fields. You can store anything you like: location, size (in case of resizeable windows), selected items in lists, selected radiobuttons and checkboxes, etc. etc. And restore the window's slections.

 

The file that's created looks like this:

 

({location:[317, 385], first:"Piet", last:"Vlerk"})

 

Here's the script:

function scriptPath () {
  try {
    return app.activeScript;
  } catch (e) {
    return File (e.fileName);
  }
}

// Write the config file
function saveData (obj) {
  var f = File (scriptPath().fullName.replace (/\.jsx?(bin)?$/, '.txt'));
  f.open ('w');
  f.write (obj.toSource());
  f.close ();
}

// Read the config file
function getPrevious () {
  var f = File (scriptPath().fullName.replace (/\.jsx?(bin)?$/, '.txt'));
  try {
    return $.evalFile(f);
  } catch (_) {
    return null;
  }
}

var w = new Window ('dialog');
  w.firstName = w.add ('edittext {characters: 10}');
  w.lastName = w.add ('edittext {characters: 10}');
  w.add ('button {text: "OK"}');
  w.add ('button {text: "Cancel"}');
  
w.onShow = function () {
  // Look for the config file
  var previous = getPrevious();
  // It was there, populate window
  if (previous !== null) {
    w.location = previous.location,
    w.firstName.text = previous.first,
    w.lastName.text = previous.last
  }
  w.firstName.active = true;
}

// OK clicked: store the window data
if (w.show() === 1) {
  saveData ({
    location: [w.location.x, w.location.y],
    first: w.firstName.text,
    last: w.lastName.text
  });
}

 

deckarduk
deckardukAuthor
Inspiring
June 6, 2023

Wow! Thanks for the lovely explanation 👍🙂

Would there ever be an issue with permissions when you come to saving the config file?

Peter Kahrel
Community Expert
Community Expert
June 6, 2023

Maybe. I never had a problem, but it depends on the user/computer I guess.

Community Expert
June 6, 2023

Hi @deckarduk and @brian_p_dts,

Correct me if I am worng but can we set the location of the panel as well according to our needs? If not then @deckarduk, how do you intend to use this information.

-Manan

-Manan
brian_p_dts
Community Expert
Community Expert
June 5, 2023

You can use app.insertLabel and app.extractLabel to insert the label info and check it upon reruning. A general workflow is: 

var panelInfo = app.extractLabel( "panelInfo" );
if (panelInfo) { /*the info exists*/ }
//...
app.insertLabel( "panelInfo", /*your panel info*/ );
deckarduk
deckardukAuthor
Inspiring
June 5, 2023

Hi Peter,

Thank you for the help 👍🙂