6
$\begingroup$

Let's say I have a column to display and each of its items can be hidden separately.

Question: Is there a way to make it work without re-rendering whole column whenever a particular item is hidden? What is the idiomatic approach to this problem?

To be clear, once an item is hidden the column should not have any weird gaps.

An item means whatever, I'm not talking about strings only.

Obstacles: One can use Dynamic@If[... or PaneSelector for each item but what to 'show' as a hidden item? I have failed to create an item/placeholder with no size.

Code to play with:

Without loss of generality we can play with one item being toggled:

DynamicModule[{x4 = True},
 Column[{
   1,
   2,
   3,
   PaneSelector[{
     True -> Grid[{{4, Checkbox@Dynamic@x4}}, Alignment -> {Center, Center}],
     False -> Spacer[{0, 0}]
     }, Dynamic@x4, ImageSize -> Automatic],
   5
   }, Spacings -> 0]]

enter image description here

As you can see, there is clearly something there.

An example of a correct behavior but not desired internals:

At the end I will probably use something like:

DynamicModule[{x1 = True, x2 = True, x3 = True, x4 = True, x5 = True},
 Dynamic@Column[
   Pick @@ Transpose[{
      {{1, Checkbox@Dynamic@x1}, x1},
      {{2, Checkbox@Dynamic@x2}, x2},
      {{3, Checkbox@Dynamic@x3}, x3},
      {{4, Checkbox@Dynamic@x4}, x4},
      {{5, Checkbox@Dynamic@x5}, x5}
      }]
   ]
 ]

But I don't like it because the whole column is re-rendered, so every item is being typeset again, which enforces constraints on how you write Dynamics inside items.

$\endgroup$
3
$\begingroup$

The following seems to meet your requirements for a single row:

DynamicModule[{flag=True},
    Column[
        {
            1,
            2,
            3,
            PaneSelector[
                {
                True -> Grid[{{4, Checkbox[Dynamic[flag]]}}],
                False->Spacer[{0,0}]
                },
                Dynamic@flag,
                FrameMargins->0,
                ImageSize->Automatic
            ],
            5
        },
        ItemSize->{Automatic,{Automatic,Automatic,Automatic,-1,Automatic}},
        Spacings->{1,{.2,.2,.2,-.1,.2,.2}}
    ]
]

A short animation (the ContentPadding option is a remnant from trying to shrink the Checkbox):

enter image description here

The extra space around the 4 is because of the size of the checkbox. Extending this to have multiple dynamically hidden rows is harder, but should be possible.

Addendum

Here is a version that works for multiple dynamic rows. The trick is to take over control of all spacing related functionality with a Pane:

pane[e_] := Pane[e, ContentPadding->False, FrameMargins->{{0,0},{4,2}}];
DynamicModule[{flag=Range[5]},
    Column[{
        CheckboxBar[Dynamic[flag], Range[5]],
        {
            Column[
                PaneSelector[
                    {True -> pane[#], False -> Spacer[{0,0}]},
                    Dynamic @ MemberQ[flag, #],
                    ContentPadding->False,
                    FrameMargins->0,
                    ImageSize->Automatic
                ]& /@ Range[5],
                ItemSize->{Automatic,-1},
                Spacings->{1,-.1}
            ],
            Column[
                pane /@ Range[5], 
                ItemSize->{Automatic,-1},
                Spacings->{1,-.1}
            ]
        }
    }]
]

enter image description here

$\endgroup$
  • $\begingroup$ Yes, getting those frames/margins/padding right is a pain. Will try to test it in action to see how robust it is. Thanks. $\endgroup$ – Kuba Sep 20 '18 at 7:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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