15

Perhaps it's not accessible from the front end, but what is this so-called attached cell?

In[91]:= Names["*`*AttachedCell*"]

Out[91]= {"FrontEndAttachedCellParent", \ "PredictiveInterfaceDump$UseAttachedCells",
"WebPredictionsPrivate$
UseAttachedCells"}

QuantumDot
  • 19,601
  • 7
  • 45
  • 121
M.R.
  • 31,425
  • 8
  • 90
  • 281
  • The title of your question does not seem to be related in any way to body of your question. The title is too broad to be a good question. The body is obscure; what motivated you to search on "*`*AttachedCell*"? – m_goldberg Nov 13 '15 at 04:15
  • Oh I was just guessing from some spelunking that attachedcells are the mechanism it uses. – M.R. Nov 13 '15 at 04:23
  • @m_goldberg fixed the title. – Kuba Nov 13 '15 at 09:10

2 Answers2

21

##Intro One day I was playing with Developer` package and found DateSetter which uses some kind of floating elements that I found useful.

enter image description here

After taking a look at a source code I found out it was FrontEnd`AttachCell. From the code one could learn enough to create something useful:

##Usage

FrontEnd`AttachCell[
   parentObject,             (*Box or Cell Object*)
   attachedCellBoxes,
   {Automatic, {Left, Bottom}}, (*1*)
   {Left, Top},                 (*2*)
   "ClosingActions" -> {...}    (*3*)
]
  1. I don't know what an Automatic is there for but the second part is setting alignment anchor point in the parentBoxObject
  2. alignment anchor point in the attached cell
  3. "The ClosingActions determines actions which automatically dismiss the attached cells". Available actions: "ParentChanged", "EvaluatorQuit", "OutsideMouseClick", "SelectionDeparture", "MouseExit".

I couldn't figure everything out by myself so let's quote John Fultz whom I've asked about details:

  • Kuba:

[...]

  1. I'm aware it is undocumented but I'm curious if it is stable. [...]
  1. Can you give me any insight in "ClosingActions"? [...]
  1. Can I AttachCell for DockedCells elements? [...]
  • John Fultz:
  1. Yes, this functionality is used all over the place. At some point, it'll graduate to a System` level function, but even when it does, we'll probably maintain backward compatibility with the current stuff.
  1. The "ClosingActions" determines actions which automatically dismiss the attached cells. You can manually dismiss a cell by doing NotebookDelete on the attached cell's CellObject. But there are some circumstances where it's much easier to let the system do it for you. It can be a list of any of the following:
  • "SelectionDeparture" -- if the selection leaves the parent, the attached cell, or any of the attached cell's children (the selection might be in the attached cell if the attached cell has InputFields).
  • "ParentChanged" -- if any change is made to the parent of the attached cell
  • "MouseExit" -- if the mouse leaves the region of the attached cell
  • "OutsideMouseClick" -- if a click happens anywhere outside of the attached cell. This includes clicks of the right and middle mouse buttons.
  1. Yes, that works, too. Except that the docked view will clip attached cells, so if the attached cell doesn't live fully within the docked view, it may not be very useful.

##My example:

attachTo[parentbox_] := MathLink`CallFrontEnd[
  FrontEnd`AttachCell[
    parentbox,
    ToBoxes[ExpressionCell[
      EventHandler[Panel["floating panel"], 
        "MouseExited" :> (NotebookDelete[ParentCell[EvaluationBox[]]];)
      ],
      StripOnInput -> True, Background -> White, 
      CellFrameColor -> LightBlue, CellFrameMargins -> 0, CellFrame -> 2
    ]],
    {Automatic, {Right, Bottom}},
    {Left, Top},
    "ClosingActions" -> {"ParentChanged", "EvaluatorQuit",  "OutsideMouseClick"}
]]

DynamicModule[{parentBox, attachedCell}, EventHandler[ Panel["test"], { "MouseEntered" :> ( NotebookDelete @ attachedCell; attachedCell = attachTo[parentBox]; )} ], Initialization :> ( parentBox = EvaluationBox[]; ) ]

enter image description here

Notice that I'm not using "MouseExit" closing action but an EventHandler + NotebookDelete. That's because if the initial position of the attached cell is away from cursor then it won't appear at all.

##Possible issues

  • the tricky thing is to get the parentBoxObject.
  • it's not the same as e.g. menu in PopupMenu since attached cell is restricted to notebook area only while the menu is able to be outside.
QuantumDot
  • 19,601
  • 7
  • 45
  • 121
Kuba
  • 136,707
  • 13
  • 279
  • 740
  • Thank you very much for the canonical answer (as always) :) – M.R. Nov 13 '15 at 21:34
  • @M.R. You are welcome, and thanks for another interesting question :) – Kuba Nov 13 '15 at 22:00
  • +1 Thanks for the digging Kuba! I was waiting for this kind of interactive floating element for years now. Didn't realize that DateSetter had it. – István Zachar Nov 14 '15 at 09:21
  • @IstvánZachar No problem, I have just recently found it too. I hope this post will generate many topics with nice GUI based on this. – Kuba Nov 14 '15 at 09:25
  • 1
    Aren't you missing an assignment as attachedCell = attachTo[parentBox] within the parent's `EventHandler? – István Zachar Dec 13 '15 at 16:25
  • @IstvánZachar good point, I was correcting it and missed that. – Kuba Dec 13 '15 at 17:49
  • I am trying to figure out how to do a nested menu structure with attached cells (a la ActionMenu, but with multiple levels) but it is not straightforward to call attached cells from attached cells and reliably destroy them when leaving the parent. Do you have any insight on this? – István Zachar Dec 13 '15 at 21:44
  • @IstvánZachar no haven't tested anything but this is the next thing I will take a look when I find time for this topic. – Kuba Dec 13 '15 at 21:50
  • @IstvánZachar I was playing with it today but I have to change approach because the current one is demolished by the fact that MouseEntered even is not reliable :/ – Kuba Dec 20 '15 at 05:47
  • Kuba, please see my application here. Any help is appreciated! – István Zachar Dec 21 '15 at 21:48
  • @IstvánZachar Yep, I;ve seen that, I willtry to post something tomorrow, probably won't be complete but something. Have to tidy the code a little bit. – Kuba Dec 21 '15 at 22:18
  • Ok, thanks! No need to hurry, I'll be away for a month. Have a nice Christmas! – István Zachar Dec 21 '15 at 22:30
  • @Kuba clearly the "Suggestions Bar" works via some attached cell mechanism. The "Show Suggestions Bar" arrow floats above my attached cells. – b3m2a1 Jan 04 '17 at 22:22
4

This is potentially useful info from a scrape I did building on this. The alignment position can be an Offset spec too, a la:

MathLink`CallFrontEnd[
  FrontEnd`AttachCell[EvaluationCell[],
   Cell["wheee"],
   {Offset[{10, -71}, 15], {Left, Bottom}},
   {Left, Top}, 
   "ClosingActions" -> {"SelectionDeparture", "ParentChanged", 
     "EvaluatorQuit"}]
  ];

Which gives better placement control


For the scrape I just found all the uses in my $InstallationDirectory:

{
 "/Applications/Mathematica.app/Contents/AddOns/Applications/\
DemoChannels/Oneliner.m" -> 
  HoldComplete[
   FrontEnd`AttachCell[SystemSearchDump`$tnb, ToBoxes[\!\(
PanelBox[
TagBox[GridBox[{
{
InterpretationBox[\!\(\*
StyleBox["\<\"Send to channel:\"\>",
StripOnInput->False,
FontSize->Medium]\),
Text[
Style["Send to channel:", Medium]]]},
{
TagBox[
InputFieldBox[Dynamic[SystemSearchDump`in$$], String,
ImageSize->{758., 20}],
EventHandlerTag[{"ReturnKeyDown" :> (ChannelSend["Demos:Oneliner", 
ToExpression[
                  SystemSearchDump`in$$, InputForm, 
                   Unevaluated]]; SystemSearchDump`in$$ = Null), 
               Method -> "Preemptive", PassEventsDown -> Automatic, 
               PassEventsUp -> True}]]}
},
DefaultBaseStyle->"Column",
GridBoxAlignment->{
           "Columns" -> {{Left}}, "ColumnsIndexed" -> {}, 
            "Rows" -> {}, "RowsIndexed" -> {}, "Items" -> {}, 
            "ItemsIndexed" -> {}},
GridBoxItemSize->{
           "Columns" -> {{Automatic}}, "ColumnsIndexed" -> {}, 
            "Rows" -> {{Automatic}}, "RowsIndexed" -> {}, 
            "Items" -> {}, "ItemsIndexed" -> {}}],
"Column"]]\)], {0, {Center, Bottom}}, {Center, Bottom}]],
 "/Applications/Mathematica.app/Contents/Documentation/English/\
Packages/Compatibility/Documentation/English/Tutorials/PlotLegends.\
nb" -> HoldComplete[
   FrontEnd`AttachCell[Typeset`box$, 
    FrontEndResource[
     "RGBColorValueSelector"], {0, {Left, Bottom}}, {Left, Top}, 
    "ClosingActions" -> {"SelectionDeparture", "ParentChanged", 
      "EvaluatorQuit"}]],
 "/Applications/Mathematica.app/Contents/Documentation/English/System/\
ExamplePages/CreateChartLegends.nb" -> 
  HoldComplete[
   FrontEnd`AttachCell[Typeset`box$, 
    FrontEndResource[
     "GrayLevelColorValueSelector"], {0, {Left, Bottom}}, {Left, Top},
     "ClosingActions" -> {"SelectionDeparture", "ParentChanged", 
      "EvaluatorQuit"}]],
 "/Applications/Mathematica.app/Contents/Documentation/English/System/\
ExamplePages/LegendPointMarkers.nb" -> 
  HoldComplete[
   FrontEnd`AttachCell[Typeset`box$, 
    FrontEndResource[
     "HueColorValueSelector"], {0, {Left, Bottom}}, {Left, Top}, 
    "ClosingActions" -> {"SelectionDeparture", "ParentChanged", 
      "EvaluatorQuit"}]],
 "/Applications/Mathematica.app/Contents/Documentation/English/System/\
ReferencePages/Interpreters/Color.nb" -> 
  HoldComplete[
   FrontEnd`AttachCell[Typeset`box$, 
    FrontEndResource[
     "CMYKColorValueSelector"], {0, {Left, Bottom}}, {Left, Top}, 
    "ClosingActions" -> {"SelectionDeparture", "ParentChanged", 
      "EvaluatorQuit"}]],
 "/Applications/Mathematica.app/Contents/Documentation/English/System/\
ReferencePages/Symbols/ClusterClassify.nb" -> 
  HoldComplete[
   FrontEnd`AttachCell[Typeset`box$, 
    FrontEndResource[
     "LABColorValueSelector"], {0, {Left, Bottom}}, {Left, Top}, 
    "ClosingActions" -> {"SelectionDeparture", "ParentChanged", 
      "EvaluatorQuit"}]],
 "/Applications/Mathematica.app/Contents/Documentation/English/System/\
ReferencePages/Symbols/ColorDistance.nb" -> 
  HoldComplete[
   FrontEnd`AttachCell[Typeset`box$, 
    FrontEndResource[
     "LCHColorValueSelector"], {0, {Left, Bottom}}, {Left, Top}, 
    "ClosingActions" -> {"SelectionDeparture", "ParentChanged", 
      "EvaluatorQuit"}]],
 "/Applications/Mathematica.app/Contents/Documentation/English/System/\
ReferencePages/Symbols/ColorNegate.nb" -> 
  HoldComplete[
   FrontEnd`AttachCell[Typeset`box$, 
    FrontEndResource[
     "LUVColorValueSelector"], {0, {Left, Bottom}}, {Left, Top}, 
    "ClosingActions" -> {"SelectionDeparture", "ParentChanged", 
      "EvaluatorQuit"}]],
 "/Applications/Mathematica.app/Contents/Documentation/English/System/\
ReferencePages/Symbols/ColorNegate.nb" -> 
  HoldComplete[
   FrontEnd`AttachCell[Typeset`box$, 
    FrontEndResource[
     "XYZColorValueSelector"], {0, {Left, Bottom}}, {Left, Top}, 
    "ClosingActions" -> {"SelectionDeparture", "ParentChanged", 
      "EvaluatorQuit"}]],
 "/Applications/Mathematica.app/Contents/Documentation/English/System/\
ReferencePages/Symbols/Graph.nb" -> 
  HoldComplete[
   FrontEnd`AttachCell[WSMLink`box$, 
    FrontEndResource[
     "GrayLevelColorValueSelector"], {0, {Left, Bottom}}, {Left, Top},
     "ClosingActions" -> {"SelectionDeparture", "ParentChanged", 
      "EvaluatorQuit"}]],
 "/Applications/Mathematica.app/Contents/Documentation/English/System/\
ReferencePages/Symbols/WhitePoint.nb" -> 
  HoldComplete[
   FrontEnd`AttachCell[WSMLink`box$, 
    FrontEndResource[
     "XYZColorValueSelector"], {0, {Left, Bottom}}, {Left, Top}, 
    "ClosingActions" -> {"SelectionDeparture", "ParentChanged", 
      "EvaluatorQuit"}]],
 "/Applications/Mathematica.app/Contents/SystemFiles/Components/MUnit/\
Kernel/Palette.m" -> 
  HoldComplete[
   FrontEnd`AttachCell[EvaluationCell[], SystemSearchDump`cell, 
    SystemSearchDump`pos, SystemSearchDump`opos]],
 "/Applications/Mathematica.app/Contents/SystemFiles/Components/\
WolframAlphaClient/Kernel/WolframAlphaClient.m" -> 
  HoldComplete[
   FrontEnd`AttachCell[SystemSearchDump`box, 
    SystemSearchDump`cell, {Offset[{7, 7}, 0], {SystemSearchDump`hpos,
       Bottom}}, {SystemSearchDump`hpos, Top}, 
    "ClosingActions" -> {"SelectionDeparture", "ParentChanged", 
      "EvaluatorQuit"}]],
 "/Applications/Mathematica.app/Contents/SystemFiles/Components/\
WolframAlphaClient/Kernel/WolframAlphaClient.m" -> 
  HoldComplete[
   FrontEnd`AttachCell[SystemSearchDump`box, 
    Cell[BoxData[ToBoxes[SystemSearchDump`b]]], {Offset[{2, 2}, 
      0], {Left, Bottom}}, {Right, Bottom}]],
 "/Applications/Mathematica.app/Contents/SystemFiles/Components/\
WolframAlphaClient/Kernel/WolframAlphaClient.m" -> 
  HoldComplete[
   FrontEnd`AttachCell[SystemSearchDump`cell, 
    Cell[BoxData[ToBoxes[\!\(\*
TagBox["SystemSearchDump`b",
EventHandlerTag[{
           "MouseExited" :> (
             NotebookDelete[SystemSearchDump`attached]; Unset[
              SystemSearchDump`attached]), Method -> "Preemptive", 
            PassEventsDown -> Automatic, PassEventsUp -> True}]]\)]], 
     Magnification -> 
      AbsoluteCurrentValue[SystemSearchDump`cell, 
       Magnification]], {Offset[{0, 0}, 0], {Center, 
      Center}}, {Center, Center}]],
 "/Applications/Mathematica.app/Contents/SystemFiles/Components/\
WolframAlphaClient/Kernel/WolframAlphaClient.m" -> 
  HoldComplete[
   FrontEnd`AttachCell[SystemSearchDump`box, 
    Cell[BoxData[ToBoxes[\!\(\*
TagBox["SystemSearchDump`b",
EventHandlerTag[{
           "MouseExited" :> (
             NotebookDelete[SystemSearchDump`attached]; Unset[
              SystemSearchDump`attached]), Method -> "Preemptive", 
            PassEventsDown -> Automatic, PassEventsUp -> True}]]\)]], 
     Magnification -> 
      AbsoluteCurrentValue[SystemSearchDump`box, 
       Magnification]], {Offset[{0, 0}, 0], {Center, 
      Center}}, {Center, Center}]],
 "/Applications/Mathematica.app/Contents/SystemFiles/Components/\
WolframAlphaClient/Kernel/WolframAlphaClient.m" -> 
  HoldComplete[
   FrontEnd`AttachCell[SystemSearchDump`box, 
    Cell[BoxData[ToBoxes[SystemSearchDump`b]], 
     Magnification -> 
      AbsoluteCurrentValue[SystemSearchDump`box, 
       Magnification]], {Offset[{0, 0}, 0], {Center, 
      Center}}, {Center, Center}, "ClosingActions" -> {"MouseExit"}]]
 }
b3m2a1
  • 46,870
  • 3
  • 92
  • 239