3
$\begingroup$

I'm creating an application with Dynamics for calculating and plotting circular orbits.

It allows the user to set a custom radius, giving them an option to either use an InputField as well as a Slider to emulate the Slider ability from the Manipulate but as part of the User Interface. The application also includes a selection of preset orbits with fixed values accessible via a Popup menu.

I'm currently having an issue setting up the 3 Control objects (Popup menu, InputField, Slider) such that they reflect the set value but are also able to be independently edited in order to override the other selections.

Control object setup

For example, when I select Geostationary in the Popup menu, I want to set the radius variable to the preset value for the Geostationary orbit and I want this value to be updated and shown both on the Slider and the InputField. However, I also want to be able to either alter the value on the Slider or the InputField (thus setting the radius to a custom user-defined variable) and I want the Popup menu's selection to update to show the Custom option. The overriding process would occur in a "first come" basis as in the last Control object to be edited is the one which overrides all the others.

As of right now I only have the Popup menu and the InputField included - when I include the Slider this locks both the InputField and the Slider to the preset value from the Popup selection and I can't alter the values through them, only with the Popup menu. Even then, I can select the Custom option in the Popup and set the value through the InputField successfully, but I haven't been able to do the reverse, that is, alter the Popup menu selection from a non-Custom option to the Custom option by changing the value in the InputField. When I select a preset option on the Popup menu it also doesn't update the value in the input field - despite it overriding the variable itself used for the calculations so the results are correct.

Does anyone have any suggestions? I apologize for the long post and for these being relatively simple concepts and when I apply each one individually (looking at the tutorials) they work, but it's combining them altogether which is causing issues.

$\endgroup$

2 Answers 2

4
$\begingroup$

Note: See also my other answer for a different approach and a discussion of the differences between the two.

You can achieve what you want by introducing a helper variable (custom in the code below) that tracks whether a custom value is used. This allows you to easily control the state of the PopupMenu. The rest can be done using the second argument of Dynamic to make the necessary changes:

radiusInput[Dynamic[r_], gs_, range_: {100, 2000}] := DynamicModule[
  {custom = False},
  r = gs;
  Row@{
    PopupMenu[
     Dynamic[
      custom,
      custom = #; If[! custom, r = gs]; &
      ],
     {False -> "Geostationary", True -> "Custom"}
     ],
    Slider[
     Dynamic[r, {custom = True; &, Automatic, Automatic}],
     range
     ],
    InputField[
     Dynamic[r, {custom = True; &, Automatic, Automatic}],
     Number,
     ContinuousAction -> True
     ]
    }
  ]

radiusInput[Dynamic[r], 200]

enter image description here

Note how both the Slider and InputField set custom=True when the user starts editing. For the InputField, we need to set the type to Number and ContinuousAction->True, as shown by @rm-rf in this answer.

$\endgroup$
1
  • $\begingroup$ Thank you very much! That second answer is indeed much more elegant in its looks but I did end up going for an iteration on the first one :) $\endgroup$
    – Donalf
    Commented Sep 4, 2019 at 17:57
2
$\begingroup$

In my other answer, I show how to achieve the desired effect using the second argument of Dynamic to manually do the necessary changes to the PopupMenu. Here is a significantly simpler approach that uses the default label of PopupMenu to get the desired effect:

radiusInput2[r_, gs_, range_: {100, 2000}] :=
 Row@{
   PopupMenu[
    r,
    {gs -> "Geostationary"},
    "Custom"
    ],
   Slider[
    r,
    range
    ],
   InputField[
    r,
    Number,
    ContinuousAction -> True
    ]
   }

radiusInput2[Dynamic[r2], 200]

enter image description here

As can be seen, the behavior is quite similar to the other one. Some notable differences:

  • You can't manually set the PopupMenu to "Custom" (which is not necessarily a bad thing)
  • When you enter the exact value of the "Geostationary" setting, the PopupMenu will change to "Geostationary". Again, might even be desirable
  • You can supply a custom second argument to the Dynamic passed to the function, which could allow for more customization. (In the other example, this would only be possible with way more effort, since we're already using custom functions there)
  • The other approach allows for more customization of the behavior (by adding more stuff to the functions handling the value changes), which might be hard to implement with this approach
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.