This is a little related to this question
Define control as variable in Mathematica
But the above question did not answer my problem, as it talks about the f
I was going to give a solution almost the same as Leonid's and use With
to insert the code, but he beat me to it, so here's an alternative way. Define a dynamic local function using ControlType -> None
that does your styling:
Manipulate[Plot[{f, g + 1}, {x, -1, 1}],
Dynamic[Grid[{{Style["f(x)="], pu[f]},
{Style["g(x)="], pu[g]}}]],
{{pu, Function[{f}, PopupMenu[Dynamic[f], {x, x^2, x^3}, ImageSize -> Tiny],
HoldFirst]}, None}]
By the way, the Style[]
in Style["f(x)="]
is redundant, as you are not actually setting any styles...
What about this
Manipulate[Plot[f*g, {x, -1, 1}],
Evaluate@
With[{styleAndpopup =
Function[{st, fun},
{
Style[st],
PopupMenu[Dynamic[fun], {x, x^2, x^3}, ImageSize -> Tiny]
},
HoldAll]},
Grid[{styleAndpopup["f(x)=", f], styleAndpopup["g(x)=", g]}]]]
This is actually a tiny example of the code-generation at work, since if you look at the FullForm
of the resulting Manipulate
, you will see the same expression you originally started with. The styleAndpopup
is actually not a function here, but a macro, locally defined using With
.
EDIT
Per request of the OP - generalizing to many controls. The easiest fix is to insert Sequence@@...
as Sequence @@ {First@control1[...
. However, there is some extraneous stuff that can be removed as well:
Manipulate[{x, y},
Evaluate@With[{control1 =
Function[{var, initialValue, str, from, to, incr},
Unevaluated@{{var, initialValue, str}, from, to, incr, ImageSize -> Tiny},
HoldAll]},
Sequence @@ {
control1[x, 0, "x=", 0, 1, .1],
control1[y, 0, "y=", 0, 2, .1],
control1[z, 0, "z=", 0, 10, .1]}]]
One could do this:
Manipulate[
Plot[f*g, {x, -1, 1}]
, Grid[
{ {Style["f(x)="], PopupMenu[Dynamic[f], opts]}
, {Style["g(x)="], PopupMenu[Dynamic[g], opts]}
}
]
] /. opts -> Sequence[{x, x^2, x^3}, ImageSize -> Tiny]
If one is in the habit of assigning down-values to symbols whose names do not begin with $
, then it would be prudent to wrap the whole thing in Block[{x, opts}, ...]
in case x
and opts
have globally-defined values.
A similar technique is possible for the case of multiple controls:
Manipulate[
{x, y, z}
, Grid[
{ {control1[x, 0, "x=", 0, 1, .1]}
, {control1[y, 0, "y=", 0, 2, .1]}
, {control1[z, 0, "z=", 0, 10, .1]}
}
]
] /. control1[var_, initialValue_, str_, from_, to_, incr_] :>
Control[{{var, initialValue, str}, from, to, incr, ImageSize -> Tiny}]