How to "SaveDefintions" without using the Manipulate structure?

544 Views Asked by At

I'm doing a CDF document where I'm placing Dynamic pieces in the middle of the text. This document is supposed to work in the Player.

What is the best way to register glogal values that should be accessed from all the dynamic pieces that are scattered around different cells?

For instance, I want to define g=9.8, and I want this value to be accessed by all the dynamics that are placed in the different cells. Since this should work on the player, this value should persist across sessions of Mathematica.

I could only think of 2 different ways:

  • an action button that has to be clicked by the user, when he opens the file, that launches all the needed = and := used around the notebook
  • create an empty manipulate, with a SaveDefinitions->True, and whose variable are not localized to the Manipulate

Both seem too artificial.

Having any other method that only sets the definitions once it is displayed is not good, since the person that accepts to display the dynamics may have already scrolled down, and passed by the dynamic that implements all the needed definitions.

So, how to "SaveDefintions" without using the Manipulate structure?

3

There are 3 best solutions below

0
Nasser On

I have not tried this in dynamics document like you have, but you can try this:

"Using initialization cells, you can specify that particular input cells of a notebook should be evaluated first. This ensures that your code is evaluated in the correct order, such as defining functions before evaluating cells that use those definitions."

http://reference.wolfram.com/mathematica/howto/WorkWithInitializationCells.html

5
Alexey Popkov On

One possibility is to define conditional Initialization for every Dynamic object in the document and place initialization expressions in an initialization cell (or in some other cell with a tag which allow easily identify it). For example, using initialization cell:

Manipulate[
 Plot[n f[x], {x, -3, 3}], {n, 1, 4}, 
 Initialization :> If[!TrueQ[$initialized],
                      FrontEndTokenExecute["EvaluateInitialization"]]]

In this way you need not to store initialization expressions in every Dynamic object and these expressions will not be evaluated repeatedly for every of them.


Update

It seems that NotebookDynamicExpression option of Notebook is what you want. John Fultz wrote about it:

"Dynamics can be stored in the front end options CellDynamicExpression, NotebookDynamicExpression, and FrontEndDynamicExpression. These Dynamics are not displayed, but are updated when the cell/notebook/frontend to which they are attached is displayed."

So the solution is:

SetOptions[EvaluationNotebook[], NotebookDynamicExpression :> (a = 1)]

Try to save and open again notebook after evaluating the above. And check definition for a.

0
Chris Degnen On

You can use something along these lines:

DynamicModule[{savetext = ""},
 Dynamic[If[StringQ[string], savetext = string, savetext],
  Initialization :> (string = savetext)]]

On first evaluation string does not exist, so StringQ results in the Dynamic showing "". Thereafter StringQ evaluates to True, and Dynamic shows the text in string. savetext is saved across sessions by being a DynamicModule local variable.

string can be updated directly, e.g. string = "new text"

However, if more than one copy of this construction is open at the same time, one string variable will update the other.

It would be interesting to see suggestions on how instances could be isolated, (without renaming 'string').