TransWikia.com

Removing an extra curly braces when using Grid with an If statment

Mathematica Asked on February 9, 2021

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.

2 Answers

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.

Answered by Mark McClure on February 9, 2021

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}]

Answered by kglr on February 9, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP