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.

I use Grid to align controls in Manipulate. Here is a simple example

Grid[{
     {name1,Control2,value1},
     {name2,Control1,value2}
    }]

The 3 fields above come out aligned automatically, even when one field, such as name, is longer than another, and Spacing can be used to control field width for all controls at once.

A problem shows up when I need to use an If statement to build controls based on selection used in previous control:

Grid[{
     {name1,Control2,value1},

     (*now make a control based on above value*)

     {Dynamic[If[name1==1,
                 {name2,Control1,value2},
                 {name3,Control3,value3}
                ]
             ]
     }
    }]

This works well, and allows me to change the controls that appear on the UI based on a selection that was made in another control but the problem with the above is that it gives an extra set of {} coming out from inside the If needed grouping which ends up messing up the alignment.

I think I need to use Sequence or some other function to remove the inner {} but can't figure the syntax.

I made below a simple working code to illustrate

Manipulate[
 eq,

 Grid[{

   {"eq", SetterBar[Dynamic[eq], {1, 2}], Dynamic[eq]},

   {Dynamic[If[eq == 1,

      {"v1",
       Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}],
       Dynamic[v1]
       },

      {"v2",
       Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}],
       Dynamic[v2]
       }
      ]], SpanFromLeft
    }}
  ],

 {{eq, 1}, None},
 {{v1, 1}, None},
 {{v2, 1}, None}
 ]

which gives

enter image description here

You can see that the whole expression was treated as if I wrote

Grid[{
     {name1,Control2,value1},
     {{name2,Control1,value2}}
    }]

I tried using First, Sequence but can't get it to come out correct.

Again, I need to keep the 3 fields in each Row separate and in a List. I can't just use Row since it means each row will collapse to become one field, not three fields, and I lost the alignment I needed, i.e. I can't just write

Manipulate[
 eq,

 Grid[{

   {"eq", SetterBar[Dynamic[eq], {1, 2}], Dynamic[eq]},

   {
    Dynamic[If[eq == 1,

      Row[{"v1",
        Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}],
        Dynamic[v1]
        }],

      Row[{"v2",
        Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}],
        Dynamic[v2]
        }]
      ]], SpanFromLeft
    }
   }

  ],

 {{eq, 1}, None},
 {{v1, 1}, None},
 {{v2, 1}, None}
 ]

enter image description here

Any idea how to make the above work and remove those extra {}?

edit

Let me just clarify why using Row as a solution does not work.

Compare the following 2 examples

Manipulate[eq,

 Grid[{
   {"eq", SetterBar[Dynamic[eq], {1, 2}], Dynamic[eq]},

   {Dynamic[If[eq == 1,

     Row[{"v1", Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}],Dynamic[v1]}],

     Row[{"v2", Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}], Dynamic[v2]}]
    ]]
   }

   }],

 {{eq, 1}, None},
 {{v1, 1}, None},
 {{v2, 1}, None}
 ]

enter image description here

We can see that the whole Row was treated as one field. I want to the above to come out as if I have written this

Manipulate[eq,

 Grid[{
   {"eq", SetterBar[Dynamic[eq], {1, 2}], Dynamic[eq]},

   {"v1", Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}],Dynamic[v1]}

   }],

 {{eq, 1}, None},
 {{v1, 1}, None},
 {{v2, 1}, None}
 ]

enter image description here

You see the difference? This is the important part. thanks.

share|improve this question
    
Related, possibly duplicate?: mathematica.stackexchange.com/q/1864/121 –  Mr.Wizard Dec 9 '12 at 14:03
add comment

2 Answers

up vote 4 down vote accepted

Does this work as you need?

  Manipulate[eq, Dynamic@Grid[{{"eq", SetterBar[Dynamic[eq], {1, 2}], 
  Dynamic[eq]}, {If[eq == 1,
    {"v1", Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}], Dynamic[v1]}, 
    {"v2", Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}], 
       Dynamic[v2]}], SpanFromLeft} /. 
      (lst : {x_String, _, _}) :>  Sequence @@ lst}], 
   {{eq, 1}, None}, {{v1, 1}, None}, {{v2, 1},  None}]

enter image description here

Alternatively, instead of post-processing, you can define a custom if that "holds" sequence arguments as follows:

 ifSeqHold = Function[{test, arg1, arg2}, 
    If[test, Sequence @@ arg1, Sequence @@ arg2], HoldAllComplete];

 Manipulate[eq,  Dynamic@Grid[{{"eq", SetterBar[Dynamic[eq], {1, 2}], 
 Dynamic[eq]}, {ifSeqHold[ eq == 1, 
   {"v1", Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}], Dynamic[v1]}, 
   {"v2", Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}], 
   Dynamic[v2]}], SpanFromLeft}}], 
   {{eq, 1}, None}, {{v1, 1}, None}, {{v2, 1}, None}]

which gives the same result.

Update: Hold[Sequence@@{...}] followed by ReleaseHold also works:

  Manipulate[eq, Dynamic@Grid[{{"eq", SetterBar[Dynamic[eq], {1, 2}], 
    Dynamic[eq]}, {If[eq == 1, 
     Hold[Sequence @@ {"v1", Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}], 
      Dynamic[v1]}], 
     Hold[Sequence @@ {"v2",  Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}], 
      Dynamic[v2]}]]// ReleaseHold, SpanFromLeft} }], 
   {{eq, 1},  None}, {{v1, 1}, None}, {{v2, 1}, None}]
share|improve this answer
    
@Nasser, my pleasure - glad it worked. –  kguler Dec 9 '12 at 14:33
    
Nasser, right -- the only way i could get it to work was by putting Dynamic outside Grid. –  kguler Dec 9 '12 at 15:07
add comment

Let's use a Column of Rows rather than a Grid.

Manipulate[eq,
 Column[{
   Row[{"eq", SetterBar[Dynamic[eq], {1, 2}], Dynamic[eq]},
    StringJoin@@Table[" ",{52}]],    
   Dynamic[If[eq == 1,
      Row[{"v1", Manipulator[Dynamic[v1, {v1 = #} &], {0, 2, .1}], 
        Dynamic[v1]}, "   "],
      Row[{"v2", Manipulator[Dynamic[v2, {v2 = #} &], {0, 2, .1}], 
        Dynamic[v2]}, "   "]
      ]
     ]   
   }],
 {{eq, 1}, None},
 {{v1, 1}, None},
 {{v2, 1}, None}
]

enter image description here

I do think that the use of spaces to format is a bit hacky; I'm not certain how it will look across platforms. There might be a better way to do it - perhaps use of Pane or Panel or Spacings or Margins or I don't know what. I think the basic idea is there, though.

share|improve this answer
add comment

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.