Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Background: I want to develop a custom control, based on a 2D slider. I currently have this ( working ) example.

  Manipulate[
   If[(iOld != i || jOld != j),
    lata[[1]] = i; lata[[2]] = j];
    i = lata[[1]];
    j = lata[[2]];
    iOld = i;
    jOld = j;
    lata,
    Row[{
       Column[{
       Control[{{i, i, "i"}, -5, 5, 0.25}],
       Control[{{j, j, "j"}, -5, 5, 0.25}]}]
       ,
       Control[{{lata, lata, "lata"}, {-5, -5}, {5, 5}, {0.25, 0.25}}]
    }],
    Initialization -> {
      lata = {1, 0},
      i = lata[[1]],
      j = lata[[2]],
      jOld = j,
      iOld = i
    }]

This control is a 2D Slider and two normal sliders in sync. Clearly the two sliders are not necessary but I like the built-in functionality of the slider's drop down precision- entry ( and auto play ).

Question: Is there an easy way to build a 2D Slider with the drop down precision provided for a normal slider, thus in x and y direction? Or do I have to build it from scratch? ( Update: Basically remove the two sliders =itself= but remain all other functionality in the example. )

share|improve this question
    
@IstvánZachar There are two answers now :) –  belisarius May 7 '12 at 14:56

3 Answers 3

up vote 5 down vote accepted

Something like the following?

 Manipulate[If[(iOld != i || jOld != j), lata[[1]] = i; lata[[2]] = j];
 i = lata[[1]];
 j = lata[[2]];
 iOld = i;
 jOld = j;
 lata, 
 Column[{Row[{Opener[Dynamic[zz]], " lata"}], 
 PaneSelector[{True -> 
 Row[{Column[{Row[
  {Control[{{i, 0, ""}, {-5, -5}, {5, 5}, {0.25, 0.25}, Animator[#, {-5, 5, 0.25}, 
     AnimationRunning -> False, AnimationRate -> 4/5, Appearance -> Small, 
     AppearanceElements -> {"ResetButton","PlayPauseButton", "StepLeftButton", 
              "StepRightButton", "FasterSlowerButtons", "DirectionButton"}] &}], 
   Spacer[5], 
   Control[{{i, 0, ""}, {-5, -5}, {5, 5}, {0.25, 0.25}, 
          InputField[#, FieldSize -> {4, 1}] &}]}] , 
   Row[{Control[{{j, 0, ""}, {-5, -5}, {5, 5}, {0.25, 0.25}, 
        Animator[#, {-5, 5, 0.25}, AnimationRunning -> False, 
        AnimationRate -> 4/5, Appearance -> Small, 
        AppearanceElements -> {"ResetButton","PlayPauseButton", "StepLeftButton", 
           "StepRightButton", "FasterSlowerButtons","DirectionButton"}] &}], 
   Spacer[5],             
   Control[{{j, 0, ""}, {-5, -5}, {5, 5}, {0.25, 0.25}, 
          InputField[#, FieldSize -> {4, 1}] &}]}]}], Spacer[15], 
   Control[{{lata, lata, ""}, {-5, -5}, {5, 5}, {0.25, 0.25}}]}],
  False -> 
  Control[{{lata, lata, ""}, {-5, -5}, {5, 5}, {0.25, 0.25}}]}, 
  Dynamic[zz]]}], 
  Initialization -> {lata = {0, 0}, i = lata[[1]], j = lata[[2]], jOld = j, iOld = i}]

screenshots:

enter image description here

enter image description here

share|improve this answer
    
EXCELLENT. Code is somewhat verbose but that is to be expected of such a cool solution. Thank you very much. - Make sure this control is included in the forthcoming custom control collection or whatever. –  ndroock1 May 7 '12 at 15:38
    
@ndroock1, thank you for the accept; perhaps you should have waited a while for a more complete answer. Both the code and the appearance/functionality can be made much cooler... and Slider2D does need quite a few enhancements. –  kguler May 7 '12 at 15:50
    
@kguler and @ndroock1 nice design, but if you will share this with someone you should be careful. They can access option "Autorun" from the little cross in the top right corner which will fail in this case. It happens when dynamic things become too complex. Two choices here: you can fix the problem adjusting the code or simply set AppearanceElements -> None as an option for Manipulate to remove little cross (if you are satisfied with current code). –  Vitaliy Kaurov May 7 '12 at 16:54
    
@Vitaliy, you are right; I was struggling with the Autorun behavior and the only "solution" (short of suppressing all that comes with the top-right cross button) that i could find was to set the AutorunSequencing so that all controls except the Slider2D are inactive under Autorun. –  kguler May 7 '12 at 17:27

This is basically the same concept as belisarius's and kguler's answers but I've put the definition of the controller in a function to make things a bit more portable.

Options[contr] = {"Trigger" -> {}, "InputField" -> {}, "Slider2D" -> {}};
SetAttributes[contr, HoldAll];

contr[Dynamic[a_], range_, opt : OptionsPattern[contr]] :=
 Dynamic[
  Labeled[
   Slider2D[Dynamic[a], range, OptionValue["Slider2D"]],
   OpenerView[{"",
     Grid[Join[{{"\[LeftRightArrow]"}, {"\[UpDownArrow]"}},
       {InputField[#, Number, OptionValue["InputField"], FieldSize -> {6, 1}],
        Trigger[#, range[[All, 1]],
           OptionValue["Trigger"], 
           AppearanceElements -> {"StepLeftButton", "StepRightButton",
              "PlayPauseButton", "FasterSlowerButtons"}]} & /@ 
             {Dynamic[a[[1]]], Dynamic[a[[2]]]}, 2]]}], 
     {{Right, Top}}]]

Example

Manipulate[a,
 {{a, {1, 0}, "Lata"}, (contr[Dynamic[a], {{-5, -5}, {5, 5}, {.25, .25}}] &)}]

screenshot

I'm using a Slider2D, two InputFields and two Triggers to create the control. You can set the options of these elements by setting the options "Slider2D" -> opt, "InputField" -> opt and/or "Trigger" -> opt. For example, to set the width of the input fields to 10 and the animation rate of the trigger to 3 you could do

Manipulate[a,
 {{a, {1, 0}, 
   "Lata"}, (contr[Dynamic[a], {{-5, -5}, {5, 5}, {.25, .25}}, 
     "InputField" -> {FieldSize -> 10}, 
     "Trigger" -> {AnimationRate -> 3}] &)}]
share|improve this answer

Perhaps something like this (the interface display needs some polishing):

appEl = {"StepRightButton", "PlayPauseButton", "FasterSlowerButtons"}
Manipulate[If[(iOld != i || jOld != j), lata[[1]] = i; lata[[2]] = j];
 i = lata[[1]];
 j = lata[[2]];
 iOld = i;
 jOld = j;
 Row[{
   Column[{
     {Animator[Dynamic[i], {-5, 5, .25}, AnimationRunning -> False, 
       AppearanceElements -> appEl], InputField[ Dynamic[i]]}, 
     {Animator[Dynamic[j], {-5, 5, .25}, AnimationRunning -> False, 
       AppearanceElements -> appEl], InputField[ Dynamic[j]]}
     }],
   Control[{{lata, lata, "lata"}, {-5, -5}, {5, 5}, {0.25, 0.25}}]
   }],
 Initialization -> {lata = {1, 0}, i = lata[[1]], j = lata[[2]], jOld = j, iOld = i}, 
 AppearanceElements -> All]

enter image description here

share|improve this answer
    
just got the "new answer posted" notice with a 40 minutes delay just before I posted an answer also based on animator:) –  kguler May 7 '12 at 14:16
    
@kguler I think you could undelete your answer. Your interface is nicer than mine –  belisarius May 7 '12 at 14:20
    
i should work on it a little more; perhaps to align the animator controls around the sides of Slider2D. –  kguler May 7 '12 at 14:26
    
Yes, and isn't this how the Slider2D should have been by default in Mma? Anyway, as you said a tiny bit of customization is still required. - Is there a particular reason why you left the minus button out of this version? –  ndroock1 May 7 '12 at 14:49
1  
@ndroock1 I only focused on the barebone requirements, and did not worked out the presentation details. –  belisarius May 7 '12 at 14:53

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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