1
$\begingroup$

This question is related to a previous question of mine, Expand and collapse rows in a grid

I'm trying to have nested OpenerViews similarly to the answer of kguler, but they are not aligned. The problem is compounded if I add more nesting. How can I have aligned rows across levels, as in the end I want to add the rows by group, and not have to zigzag when reading?

A basic example of my problem is :

OpenerView[
    {
        Grid[
            {{1}}
            ,
            Dividers->All,ItemSize->3
        ]
        ,
        Grid[
            {{
                OpenerView[
                    {
                        Grid[
                            {{2}}
                            ,
                            Dividers->All,ItemSize->3
                        ]
                        ,
                        Grid[
                            {{3}}
                            ,
                            Dividers->All,ItemSize->3
                        ]
                    }
                ]   
            }}
        ]
    }
]

Mathematica graphics

$\endgroup$
2
$\begingroup$

You can roll you own to get things as you prefer. Bare bones toy code:

opener[Dynamic[open_]] := 
 EventHandler[Dynamic[If[TrueQ[open], "[-]", "[+]"]], 
  "MouseClicked" :> (open = ! open)]

open = {False, False}

Dynamic[
 Grid@Join[{
    {opener[Dynamic[open[[1]]]], 1},
    If[TrueQ[open[[1]]], {opener[Dynamic[open[[2]]]], 2}, {}],
    If[TrueQ[open[[1]]] && TrueQ[open[[2]]], {"[  ]", 3}, {}]
    }],
 TrackedSymbols :> {open}]

enter image description here

This gives you more flexibility in the sort of things you can make. For example.

$\endgroup$
1
$\begingroup$

Using the interesting answer of Mike, I managed to do the following which is quite easy to use. I use the vanishing sequence ##&[] instead of {}.

I didn't think I would spend so much time on this display issue, but it was nonetheless quite interesting.

ReleaseAllHold[expr_,firstLevel_:0,lastLevel_:Infinity] := Replace[expr, (Hold|HoldForm|HoldPattern|HoldComplete)[e___] :> e, {firstLevel, lastLevel}, Heads -> True];

emptyElement="  ";
customOpener[Dynamic[open_]]:=EventHandler[Dynamic[If[TrueQ[open],Opener[True],Opener[False]]],"MouseClicked":>(open=!open)];

expandOpener[openList_,element_,{},newLevel_]:=Hold[{myOpener[dynamic[openList[[newLevel]]]],element}];
expandOpener[openList_,element_,levels_,newLevel_]:=Hold[If[TrueQ[And@@openList[[levels]]],{myOpener[dynamic[openList[[newLevel]]]],element},##&[]]];

expandLine[openList_,openerView[head_,rest_],levels_]:=
    Module[{newLevels=levels,newLevel},
        newLevel=++$nOpeners;
        AppendTo[newLevels,newLevel];

        Sequence@@{
            expandOpener[openList,head,levels,newLevel]
            ,
            Sequence@@(expandLine[openList,#,newLevels]&/@rest)
        }
    ];

expandLine[openList_,element_,{}]:=Hold[{emptyElement,element}];
expandLine[openList_,element_,levels_]:=Hold[If[TrueQ[And@@openList[[levels]]],{emptyElement,element},##&[]]];

OpenerTree[tree_,firstLine_,defaultTreeOpenValue:(True|False):False]:=
    Module[{linesHeld},
        $nOpeners=0;

        DynamicModule[{openList},
            linesHeld=expandLine[openList,#,{}]&/@Prepend[tree,firstLine]//Hold@dynamic@Grid@#&;
            openList=ConstantArray[defaultTreeOpenValue,{$nOpeners}];
            linesHeld/.{dynamic->Dynamic,myOpener->customOpener}//ReleaseAllHold
        ]
    ];

grid[x_]:=Grid[{{x}},Dividers->All,ItemSize->3];
l={grid[1],openerView[grid[2],{openerView[grid[3],{grid[4],grid[5]}],grid[6]}],grid[7],openerView[grid[8],{grid[9],grid[10],grid[11]}]};

OpenerTree[l,grid["head"],False]
$\endgroup$

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.