# How can I create a custom control which evaluates to a list of values or replacements?

I have a set of variables which are used in various places in my calculations (solving a system, initial conditions, etc.). In order to make this easier to deal with, I want to make a control-like thing which makes them easier to manipulate, rather than just using long lists of unlabeled values such as

calculateValues[{0, 0, π, 0.5, 3}]


So far I have something like this:

This clearly doesn't work, and I expect in order to get it working properly I'll need to use Interpretation or more Dynamic incantations, but I can't figure out exactly what needs to happen. Any advice would be appreciated. Thanks in advance!

-

You could do

myControl[varNames_List, start_: 0] :=
myControl[varNames, ConstantArray[start, Length@varNames]]

myControl[varNames_List, start_List] :=
Interpretation[{vars = start},
Panel[Grid[{varNames,
Array[InputField[Dynamic@vars[[#]],
FieldSize -> {{0, Infinity}, 1}] &, Length@vars]}]], vars]


Now you can run that function to create a control myControl["a"~CharacterRange~"g"]. Each instance will have its own values and they all evaluate to their values when supplied as input

-
This works great, thanks! But what is the purpose of the DynamicSetting and Evaluate? It seems that if I remove them, it works just the same way. Also, I would expect to need Dynamic[vars] instead of vars at the end... – jtbandes Nov 23 '12 at 20:10
@jtbandes, without the DynamicSetting it shouldn't work as I thought you wanted. Try running myControl["a"~CharacterRange~"g"] and then adding +3 to the output in the output cell with and without the DynamicSetting – Rojolalalalalalalalalalalalala Nov 23 '12 at 21:14
The Evaluate is probably useless, but since Interpretation has attribute HoldAll and I don't know why it's not simply HoldRest, I wanted to make sure it evaluated the first argument. However, it seems to evaluate it anyway – Rojolalalalalalalalalalalalala Nov 23 '12 at 21:21
The second argument of Interpretation needs to be what you want the kernel to receive when you use that control as input. You want the values of vars, and not a visual GUI that shows the dynamically updated value of vars. Always remember that Dynamic is only for SHOWING updated output (or in a control such as Slider[Dynamic@..] "as a notation" for input in controls). – Rojolalalalalalalalalalalalala Nov 23 '12 at 21:25
@jtbandes, I just passed through the docs of Interpretation and saw that it can take an extra argument, specifying the local variables, and using it expands to the same code that I had used before: DynamicSetting@DynamicModule[..., but is way neater. Edited – Rojolalalalalalalalalalalalala Nov 25 '12 at 5:17

I would suggest using another list (vals) to store values for the variables vars. To set up a list of controllers (InputFields here) programmatically, some clever construct is required. Here I used an explicit Function call to save the changed value of the $i^{th}$ element of vals inside the Dynamic (as the # stands for the index of the list element, not the actual controller value, which is denoted as $x), but this can also be achieved using With. calculateValues[v_List] := Plus @@ (v^Range@Length@v); vars = {a, b, c, d, e}; vals = {1, 2, 3, 4, 5}; Panel[ Grid[{ Text /@ vars, InputField[Dynamic[vals[[#]], Function[{$x}, vals[[#]] = \$x]],
FieldSize -> {{0, Infinity}, 1}] & /@ Range@Length@vals
}]]


Dynamic@vals

{1, 2, 3, 4, 5}

calculateValues@vars

a + b^2 + c^3 + d^4 + e^5

Dynamic[calculateValues@vars /. Thread[vars -> vals]]

3413

-

You could use interpretation.

Here's the idea.

SetAttributes[makeDynamicPanel, HoldFirst]
makeDynamicPanel[x_, defaultValue_] :=
Module[{y},
y =
Interpretation[
Panel@InputField[Dynamic[x]]
,
x
];
x = defaultValue;
y
]


Then you do for example

makeDynamicPanel[z, {0, 0, π, 0.5, 3}]


and you get a panel that allows to edit the value of z and can be used as argument to your function, you can even do for example panel + 2 and get a valid value, it's quite practical.

-