Inactivate Controls within Manipulate

2

1

Given a certain Control object (checkbox, for example) within a Manipulate environment, my goal is to define another control which is inactivated if the first control is active (or satisfies some condition). How do I do this efficiently? Are there built in functions to help me do this?

A first idea was to simply create an If condition within a Dynamic@Grid in the Control panel, as follows

Manipulate[b,
 Dynamic@Grid[{
    {"a", Control[{{a, 0, ""}, {1, 0}}]},
    If[a == 0,
     {"b", Control[{{b, 0, ""}, {1, 0}}]},
     b = 0;
     {Style["b", Gray], Control[{{b0, 0, ""}, {1, 0}}]}
     ]},
 Alignment -> {{Right, Left}, Automatic}], 
 ControlPlacement -> Left]

which gives

enter image description here

enter image description here

Here I'm creating a null control b0 to replace b and setting b = 0 for convenience.

This not bad, but I would like to check if any of the following are possible:

  1. Add a Gray tone to checkbox b whenever it's inactive;
  2. Make it impossible to interact with checkbox b if inactive, that is, lock the dependent control in a specific state;
  3. Find an efficient way to do this for multiple controls and dependencies, and avoid creating null controls as mentioned (for example, maybe I could simply define a function that toggles st in Style["b",st], for st = Black or st = Gray, and force b = False when a = 1).

Any ideas?

sam wolfe

Posted 2020-02-20T14:01:30.980

Reputation: 2 357

Answers

4

Use Dynamic[a == 0] as the option setting for Enabled in the second control:

Manipulate[b, 
 {{a, 0, "a"}, {1, 0}},
 {{b, 0, "b"}, {1, 0}, Enabled -> Dynamic[a == 0]}, 
 ControlPlacement -> Left]

enter image description here

If you need to fade the label when the control is not enabled:

Manipulate[b, 
  {{a, 0, "a"}, {1, 0}}, 
  {{b, 0, Dynamic[If[a == 0, "b", Style["b", GrayLevel[.7]]]]}, {1, 0}, 
     Enabled -> Dynamic[a == 0]}, 
  ControlPlacement -> Left]

enter image description here

If the second control is a slider, that is, if you use

 {b, 0, Dynamic[If[a == 0, "b", Style["b", GrayLevel[.7]]]]}, 0, 1, 
    Enabled -> Dynamic[a == 0]}

for the second control, you get

enter image description here

Update: An alternative approach is to use the option TrackingFunction in the first control to update all dynamic variables that depend on a:

Manipulate[b, 
 {{a, 0, "a"}, {1, 0}, TrackingFunction -> 
    (a = #; b = (1 - a) b; benabled = a == 0; 
     sty = (a /. {0 -> Black, 1 -> GrayLevel[.8]}); &)}, 
 {{b, 0, Dynamic@Style["b", sty]}, {1, 0}, Enabled -> Dynamic[benabled]}, 
 {{benabled, True}, None}, 
 {{sty, Black}, None}, 
 ControlPlacement -> Left]

enter image description here

kglr

Posted 2020-02-20T14:01:30.980

Reputation: 302 076

Can I set b = 0 when a = 1 in your first solution? – sam wolfe – 2020-02-20T15:20:33.310

@sam, maybe replace b in the first argument of Manipulate with Dynamic[b = (1 - a) b]? – kglr – 2020-02-20T15:36:28.277

1I can incorporate it in the If you have on your second code, and that's actually even better. Didn't know about the Enabled option. This is great, thanks! – sam wolfe – 2020-02-20T15:38:19.403

1It's even better if I define If[a == 1, b = 0; sty = Gray, sty = Black]; right after Dynamic@Grid[{, and simply have Style["b",sty] in the control. This helps me to change a lot of widget dependencies easier. – sam wolfe – 2020-02-20T15:53:45.617