Szabolcs
Szabolcs

Reputation: 25703

How to run initialization code for a palette?

Occasionally it would be preferable to have some initialization code for palettes (of buttons). For example, it could define some functions that are used by palette buttons.

What is the easiest and preferable way to define/run initialization code for a palette?

Upvotes: 8

Views: 741

Answers (2)

John Fultz
John Fultz

Reputation: 766

You're right to be concerned about the visibility of the Dynamic being an issue. The way to absolutely guarantee a Dynamic expression to be evaluated regardless of the visibility of any of the individual cells is to use NotebookDynamicExpression. Here's an example that illustrates NotebookDynamicExpression working while a Dynamic fails because it's hidden within a closed cell group:

cell1 = First @ MakeBoxes[
    TextCell["Click to open", "Title", 
        CellMargins -> 0, System`WholeCellGroupOpener -> True],
    StandardForm];
cell2 = First @ MakeBoxes[
    ExpressionCell[DynamicWrapper["hidden cell", Print["DynamicWrapper"]]], 
    StandardForm];
CreatePalette[
    Notebook[{Cell[CellGroupData[{cell1, cell2}, Closed]]}, 
        NotebookDynamicExpression :>
            Dynamic[Refresh[Print["NotebookDynamicExpression"], None]]]]

When you evaluate this, note that the Dynamic in NotebookDynamicExpression evaluates immediately. The DynamicWrapper never evaluates until you open the cell group, which you can do by clicking on the "Click to open" text.

In this example, incidentally, notice that I wrapped the NotebookDynamicExpression with Refresh. The function Refresh[#, None]& will make sure that the code evaluates only once -- when the notebook is first opened. Otherwise, the code would obey the standard properties of Dynamic and evaluate whenever any of the dependencies change.

NotebookDynamicExpression has been around since v6, but was only documented in v8. Also documented are its related cousins, CellDynamicExpression and FrontEndDynamicExpression.

Upvotes: 10

Mr.Wizard
Mr.Wizard

Reputation: 24336

A DynamicBox with Initialization is capable of the basic function. You can size the palette such that the object is not visible, and it will still operate.

Here is code for a small sample palette. It sets a value for var. The active code is offset with whitespace.

(* Beginning of Notebook Content *)
Notebook[{
Cell[BoxData[{
 TagBox[GridBox[{
    {
     ButtonBox["\<\"TSV\"\>",
      Appearance->Automatic,
      ButtonFunction:>None,
      Evaluator->Automatic,
      Method->"Preemptive"]},
    {
     ButtonBox["\<\"CSV\"\>",
      Appearance->Automatic,
      ButtonFunction:>None,
      Evaluator->Automatic,
      Method->"Preemptive"]},
    {
     ButtonBox["\<\"Table\"\>",
      Appearance->Automatic,
      ButtonFunction:>None,
      Evaluator->Automatic,
      Method->"Preemptive"]}
   },
   GridBoxAlignment->{"Columns" -> {{Left}}},
   GridBoxItemSize->{"Columns" -> {{Automatic}}, "Rows" -> {{Automatic}}}],
  "Column"], "\[IndentingNewLine]", 

DynamicBox[Null,
   Initialization :> ($CellContext`var = "It is done, Master.")
]

}], NotebookDefault,
 CellMargins->{{0, 0}, {0, 0}},
 CellBracketOptions->{"Color"->RGBColor[0.269993, 0.308507, 0.6]},
 CellHorizontalScrolling->True,
 PageBreakAbove->True,
 PageBreakWithin->False,
 ShowAutoStyles->True,
 LineSpacing->{1.25, 0},
 AutoItalicWords->{},
 ScriptMinSize->9,
 ShowStringCharacters->False,
 FontFamily:>CurrentValue["PanelFontFamily"],
 FontSize:>CurrentValue["PanelFontSize"]]
},
WindowSize->{55, 105},
WindowMargins->{{Automatic, 583}, {Automatic, 292}},
WindowFrame->"Palette",
WindowElements->{},
WindowFrameElements->{"CloseBox", "MinimizeBox"},
StyleDefinitions->"Palette.nb"
]
(* End of Notebook Content *)

Upvotes: 4

Related Questions