3

There is a "OpenCloseGroup" in FrontEndTokenExecute. It act like toggle. If the selected cell group is open, FrontEndTokenExecute["OpenCloseGroup"] will close cell group. If the selected cell group is closed, FrontEndTokenExecute["OpenCloseGroup"] will open cell group.

But I want a way to explicitly open or close cell group. It is not like FrontEndTokenExecute["SelectionOpenAllGroups"] or FrontEndTokenExecute["SelectionCloseAllGroups"] which will open or close all sub cell groups in any level. I want open and close one level like the FrontEndTokenExecute["OpenCloseGroup"] does.

Update

The problem is actually equivalent to seeking an efficient way to get the open status of a cell group, then we can use FrontEndTokenExecute["OpenCloseGroup"]. Thanks to Alexey Popkov for many information. I found currently the most reliable way is to NotebookRead cell data to check if it is closed or not. Here is a way

ClearAll[openSelectedCellGroup];
openSelectedCellGroup[nb_NotebookObject]:=Module[{},
If[MatchQ[NotebookRead[nb],Cell[CellGroupData[_,Closed]]],
FrontEndTokenExecute[nb,"OpenCloseGroup"]];

Though NotebookRead seems to be inefficient if the cell group contains large data. However, my experience is that it is still workable. But again, there should better be a more efficient way to check the open-close state of cell group. Hope anyone knows.

Update 2

Alexey Popkov found a way using CurrentValue[cellObj, "CellGroupOpen"]. Now we finally have an efficient tool for explicitly open and close cell groups! Like this function:

ClearAll[openSelectedCellGroup];
openSelectedCellGroup[nb_NotebookObject]:=Module[{},
If[CurrentValue[First@Cells[NotebookSelection[nb]],"CellGroupOpen"]===Closed,
FrontEndTokenExecute[nb,"OpenCloseGroup"]];

See my real applications here

matheorem
  • 17,132
  • 8
  • 45
  • 115
  • perhaps the tokens "SelectionOpenAllGroups" and "SelectionCloseAllGroups"? – kglr Jan 03 '22 at 02:46
  • @kglr Well, "SelectionOpenAllGroups" will open all descendant subgroups in any level, it is not the same as Open or close group which just open one level – matheorem Jan 03 '22 at 02:56
  • Probably the only way is to check preliminarily whether the CellGroup is open or not. Here is one way that doesn't take into account that the second argument of CellGroupData can be a Dynamic expression. – Alexey Popkov Jan 03 '22 at 09:38
  • Unfortunately Developer`CellInformation provides information about every cell in the selected CellGroup, but no information on whether the group is open or closed. – Alexey Popkov Jan 03 '22 at 10:02
  • There is an undocumented Symbol CellBoundingBox which theoretically can be used to determine whether CellGroup is closed or not. But I know nothing about how to work with it. – Alexey Popkov Jan 03 '22 at 10:09
  • Another idea is to turn on ShowGroupOpener for the Notebook, and determine the current state of the Opener (but I don't know how). – Alexey Popkov Jan 03 '22 at 10:19
  • Related consideration: NotebookLocate automatically opens all groups containing located cell. – Alexey Popkov Jan 03 '22 at 10:27
  • 1
    @AlexeyPopkov Thank you so much for so many suggestions. I tried NotebookLocate, it is great. But it is also bugged. It only works in the same notebook. I found if I use NotebookLocate to locate inner folding cells in another notebook, it can not automatically open cell group – matheorem Jan 03 '22 at 14:21

1 Answers1

2

In this answer b3m2a1 demonstrated how to attach a GroupOpener to a CellGroup using FrontEndResource["FEExpressions", "cellGroupOpenerInline"]. Evaluating the latter, we can find that it is based upon CurrentValue[cellObj, "CellGroupOpen"] which can be used as follows:

Dynamic@CurrentValue[cellObj, "CellGroupOpen"]

CellPrint@Cell[ CellGroupData[{Cell["Close me", "Subsubsection"], Cell["goodbye cruel notebook", "Text"], Cell["I'll disappear too!", "Text"]}]]; cellObj = NextCell[];

screenshot

Now collapse the CellGroup by hand:

screenshot2

We see that CurrentValue[cellObj, "CellGroupOpen"] allows determining the current state of the CellGroup.

Unfortunately, it doesn't allow to set the state directly: CurrentValue[cellObj, "CellGroupOpen"] = Closed doesn't work.

But there is an undocumented way to do this, which was uncovered by b3m2a1 in this answer:

MathLink`CallFrontEnd@FrontEnd`Value@FEPrivate`SetCellGroupOpen[cellObj, Closed]
Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
  • CurrentValue[cellObj, "CellGroupOpen"] works like a magic. This is exactly what I am looking for. Thank you so much! – matheorem Jan 04 '22 at 15:01