Author Topic: Using the Settings JavaScript object [Updated 2007 OCT 01]  (Read 7663 times)

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Using the Settings JavaScript object [Updated 2007 OCT 01]
« on: 2007 September 17 11:49:36 »
[Note: Updated to reflect changes in build 329 (2007 OCT 01)]

The latest build 325 of the core PixInsight application comes with a new Settings object that we have added to the JavaScript runtime.

Settings allows you to save and restore values that can be remembered across sessions. In this way, your script can store working information, as parameters or user selections, which can later be restored, for example the next time it is executed. JavaScript's Settings provides similar functionality to the Settings PCL class (see pcl/Settings.h).

The Settings object provides only static functions. Like its PCL counterpart, It does not represent an instantiable object, so there are no dynamic properties or methods of the Settings object.

Static Methods

Object Settings.read( String key, int dataType )

    Retrieves a value that has been previously stored associated to the specified settings
key. The dataType argument specifies a data type to which the existing settings object will be converted.

This method returns the retrieved value, or null if no value has been stored associated to the specified key, or if the existing value cannot be converted to the requested data type. In the event of read error, an exception is thrown.

For valid data types, see the <pjsr/DataType.jsh> standard header file.[/list]

void Settings.write( String key, int dataType, Object x )

    Writes the specified value
x associated to key, previously converted to the specified dataType.

In the event of write error, or if the specified value cannot be legally converted to the requested data type, this method throws an exception.

If a settings value has already been stored associated to the specified key, the previous value is replaced, even if the old data type doesn't match the new one.[/list]

Boolean Settings.remove( String key )

    Removes an existing settings
key and its associated settings value. Returns true if the specified key existed, and hence if it was removed.[/list]

Static Properties

Boolean Settings.lastReadOK (read-only)

    This property is true if the last call to Settings.read() has retrieved an existing settings key; false if the specified settings key didn't exist.

    Use this property to check if a previous settings read operation has retrieved an existing key. Note that Settings.read() will return null if an existing key cannot be legally converted to a requested data type, so testing for null return values is unsafe as an existence test. For example:

Code: [Select]

/* *** WRONG way of testing for settings key existence *** */
var foo = Settings.read( "MyScript/FooKey", DataType_Float );
if ( !foo ) // may fail
   console.writeln( "The key does not exist." );


Code: [Select]

/* *** CORRECT way of testing for settings key existence *** */
var foo = Settings.read( "MyScript/FooKey", DataType_Float );
if ( !Settings.lastReadOK )
   console.writeln( "The key does not exist." );
[/list]

Usage

A script must always use a private key prefix to store its own settings. This requirement is particularly important because the PixInsight core application has no way to associate a given set of settings keys with a particular script. All script settings are internally stored under the /ScriptData global settings key.

Other than that, using the Settings object is pretty straightforward. You typically will write three global functions: one to retrieve previously stored settings, another one to store new settings values, and possibly a third one to reset all settings stored by your script. The secret to write good code around the Settings object is simply to keep all the data well organized, preferably using object-oriented techniques.

here is an example of the correct way to use Settings from a JavaScript script in Pixinsight:

Code: [Select]
#include <pjsr/DataType.jsh>

#define KEYPREFIX    "MyScript"

// Define an object to store and manage all working parameters as properties.
// Note that the constructor function initializes all properties with
// appropriate default values.
function MyScriptData()
{
   this.parameter1 = 0;
   this.parameter2 = "Hello";
   // ... and so on for all working parameters
}

// Keep all working parameters into a global object.
myData = new MyScriptData;

// A function to restore all script parameters from settings keys.
function RestoreSettings()
{
   var keyValue;
   keyValue = Settings.read( KEYPREFIX+"/parameter1", DataType_Float );
   if ( Settings.lastReadOK )
      myData.parameter1 = keyValue;
   keyValue = Settings.read( KEYPREFIX+"/parameter2", DataType_String );
   if ( Settings.lastReadOK )
      myData.parameter2 = keyValue;
   // ... and so on for all script parameters
}

// A function to save all script parameters as settings keys.
function SaveSettings()
{
   Settings.write( KEYPREFIX+"/parameter1", DataType_Float, myData.parameter1 );
   Settings.write( KEYPREFIX+"/parameter2", DataType_String, myData.parameter2 );
   // ... and so on for all script parameters
}

// A function to delete all previously stored settings keys for this script.
function ResetSettings()
{
   Settings.remove( KEYPREFIX );
}

/*
 * Script entry point
 */
main()
{
   // Restore things as they were the last time this script was executed.
   // Or, if this is the first time, keep the default values set by the
   // MyScriptData() constructor.
   RestoreSettings();

   // ... do your stuff here ...
   // ... possibly, the user will change some working parameters ...
   // ... or perhaps, some working parameters will change automatically ...

   // Anyway, you want your script to remember all current values the next time
   // it gets executed.
   SaveSettings();
}


The KEYPREFIX macro is used to identify all settings pertaining to this particular script and, more importantly, to store all of them under a unique settings root key ("MyScript" in the example).

Don't forget to include a separator slash character ('/') between the key prefix and the actual key identifiers, as in:

Code: [Select]
  Settings.write( KEYPREFIX+"/parameter1", DataType_Float, myData.parameter1 );

Otherwise, you would generate a good mess if your script writes wrong keys like "MyScriptparameter1", and so on.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/