FrontEnd Programming

The Mathematica notebook front is itself represented through Mathematica expressions, i.e. a notebook corresponds to some expression and all the individual cells in the notebook correspond to expressions. As we have already seen previously, also the cell content, i.e. the box expressions, is represented by Mathematica expressions and is therefore accessible for the Mathematica kernel. This allows to manipulate the front end from the Mathematica kernel.

The Structure of Cells

Die interne Struktur jeder Zelle kann durch den Menü-Befehl "Format -> Show Expression" gezeigt werden, z.B. die Input Zelle

The internal structure of a cell can be displayed by marking the cell and then choosing the menu item "Format -> Show Expression", e.g. the internal form of the input cell

a = 10 + (5^2) + (Overscript[7, b])

is

a = 10 + (5^2) + (Overscript[7, b])

In general, the expression representing a cell in a notebook has the form

Cell[ contents,  typ_String,  opts___]

where content is usually represented as boxes. Content in form of boxes is represented as BoxData[boxes]. This allows the two–dimensional display of expressions, as we have already seen in the chapter on formatted input and output. Formatted content (e.g. special fonts, colors, etc.) or nested cells are represented using TextData instead of BoxData. For details, we refer to the manual.

Manipulating Notebooks

The function CellPrint writes a cell into the current notebook at the current cursor position.

CellPrint[
      Cell[BoxData[
          RowBox[{"a", "+", 
              RowBox[{"(", 
                  GridBox[
                    Table[i + j, {i, 5}, {j, 5}]], ")"}]}]], "Text", 
        TextAlignment -> "Center"]]

Notebooks are again Mathematica expressions. The kernel provides several functions to access notebooks like creating new notebooks, opening existing notebooks, moving the cursor, saving, writing data to notebooks, etc. We can view notebooks as "windows on the screen" into which we can write data. In particular, also programs can write data into notebooks simulating that they write into a separate window.

nb = NotebookCreate[Background -> GrayLevel[0.8]]

SetOptions[nb, WindowElements -> {"MenuBar"}]

NotebookWrite[nb, 
      Cell[BoxData[
          RowBox[{"a", "+", 
              RowBox[{"(", 
                  GridBox[
                    Table[i + j, {i, 5}, {j, 5}]], ")"}]}]], "Text", 
        TextAlignment -> "Center"]]

We can even specify the cursor position after data has been written into the notebook. The cursor position is referred to in Mathematica terminology as the current selection.

NotebookWrite[nb, 
      Cell[BoxData[
          RowBox[{"a", " ", 
              RowBox[{"(", 
                  GridBox[
                    Table[i + j, {i, 5}, {j, 
                        5}]], ")"}]}]], "Input"], All]

There are several operations that refer to the current selection.

SelectionEvaluate[nb]

The Structure of Notebooks

We get the Mathematica expression corresponding to a notebook by NotebookGet.

nbexpr = NotebookGet[nb]

Thus, we see that a notebook is represented as an expression of the form Notebook[{cells___Cell},opts___]. We can manipulate the expression just like all other expressions in the Mathematica kernel.

nbexpr[[1, 1]]

A notebook expression in the kernel is turned back into a notebook by NotebookPut.

NotebookPut[
      Notebook[Reverse[
          nbexpr[[1]]]]]

There are several operations referring to the current selection in a notebook.

SelectionMove[nb, Previous, Cell]

SelectionMove[nb, Previous, Cell]

SelectionMove[nb, Before, Cell]

NotebookFind[nb, "5", Next]

(Now, the (4^th) element in the first row of the matrix in the input cell should be selected!)

The current selection can modified from within the kernel. There are several operations, in which we can refer to the current selection as "■" , which is called the SelectionPlaceholder. This is what is actually used in the input palettes also.

SelectionMove[nb, All, Expression]

SelectionMove[nb, All, Expression]

NotebookApply[nb, "Det[\[SelectionPlaceholder]]", All]

The role of "■" in NotebookApply is somewhat similar to the role of "#" in pure functions!!!

SelectionEvaluateCreateCell[nb]

SelectionMove[nb, Previous, CellContents]

We can read the content of the current selection as an expression into the kernel using NotebookRead.

NotebookRead[nb]

SelectionMove[nb, All, Cell]

NotebookRead[nb]

NotebookClose[nb]

For more details, we refer again to the manual.

Active Elements in Notebooks: Buttons, Palettes

Buttons

Buttons are active elements in a notebook that can trigger some action as soon as they are clicked with the mouse. In order to create a button, use the menu item "Input -> Create Button (Evaluate)".

\[Placeholder]

This is an empty button, and in place of "□" we can now write some expression. Now we must activate the button, which we do again via a menu item "Input -> Edit Button". Before pressing the button, place the curser after the cell containing the button.

Expand[(((x + 2))^3)]

It may be interesting to inspect the whole cell expression representing the button.

Expand[(((x + 2))^3)]

This explains everything, right? The actual action that is performed is hidden here in the ButtonStyle "Evaluate", which must be defined in the notebook's style sheet. Interestingly, we can use again "■" and "□" in the expression in the button so that the action of the button refers to the current selection in the notebook. This is so, because the action of the button uses NotebookApply.

Expand[(\[SelectionPlaceholder]^3)]

(The ButtonStyle is now "CopyEvaluate". Select 34s-5 in the input cell below and then click the button. Compare to before!)

34  s - 5

(Now change ButtonStyle to "CopyEvaluateCell" and try again.)

Expand[(\[SelectionPlaceholder]^3)]

34  s - 5

Try also "EvaluateCell"!

Expand[(\[SelectionPlaceholder]^3)]

34  s - 5

OK, so far for pre–defined button actions. The action to be performed on button–click is given by the ButtonFunction option in the button. The button function should be a function depending on two parameters, the first one being specified by the  ButtonSource option and the second one being specified by the ButtonData option. There are default values for these options in case they are not specified in the button. This allows to define buttons whose action need not depend on what is written on the button.

Überraschung!

Die Expression sieht so aus:

\(Überraschung!\)

More on all that to be found in the manual.

Buttons are FrontEnd elements, therefore the button action is executed by the front end (remember: kernel and front end are separate processes). NotebookWrite, NotebookApply, EvaluateCell, etc. are functions that are available in both the  Mathematica kernel and the Mathematica front end. By default, a button uses the "front end version" of these operations. Sometimes, however, one might need the kernel to execute some more elaborate button action. In particular, this is the case when a button should execute user–defined functions! This is what the ButtonEvaluator option in a button is made for.

PlotSomeFun[] := 
      With[{f = Input["Geben Sie den Funktionsterm ein:"], 
          rg = Input["In welchem Bereich soll die Funktion dargestellt \
werden?"]}, 
Plot[f, rg]]

Überraschung!

The corresponding Button expression is

\(Überraschung!\)

Palettes

A palette is just a collection of buttons, which is usually put as a separate notebook (window). Palette notebooks are normal Mathematica notebooks, that have certain notebooks options set to special values (e.g. a palette notebook does not automatically become the selected notebook by clicking into it, etc.).
The easiest way to create a palette is the following:

Choose menu item "Input -> Create Table/Matrix/Palette". Choose "Palette" and a palette skeleton will be put into the current notebook:

({{\[Placeholder], \[Placeholder], \[Placeholder]}, {\[Placeholder], \[Placeholder], \[Placeholder]}})

Edit the buttons as desired.

Select the palette, then choose menu item "File -> Generate Palette from Selection". The palette will appear in a separate notebook, which you can save if needed to have it available later.

Exercise: Differentiation Trainer

Start from the programs for symbolic differentiation prepared for an earlier exercise and extend each differentiation rule that has been implemented by capabilities for explaining the computation of the derivative. All explanations should be displayed in a separate window, and each line of explanation should tell the actual rule that is applied and it should explain, how the general rule needs to be applied in the concrete case. Example: When computing the derivative of (t^2) Sin[t] w.r.t. t we first have to use the product rule (f*g)' = f'*g + g' f. In the explanation of the computation, do not explain the abstract product rule as written above but explain the rule for the concrete case, i.e. substitute concrete expressions for f and g in the abstract product rule. Write something like

Product Rule: (∂_t)((t^2) 
              Sin[t]) = ((∂_t) (t^2)) 
            Sin[t] + ((∂_t) Sin[t]) (t^2).

This explanation is only a proposal, try to explain the computation as you would explain differentiation to somebody who is in the process of learning how to differentiate functions "by hand". As a consequence, arrange the rules for computation in such a way that the computation not only produces a correct result but also reflects how you would teach the rules for differentiation to a student. Use formatting (colors, fonts, etc.) to your personal taste. Using an optional parameter, the user should have the possibility to turn the feature of explanation on or off.

Differentiate[(t^2) Sin[t], t, Explain -> True]

should explain the computation in a separate window and return the final result as a return value, whereas

Differentiate[(t^2) Sin[t], t, Explain -> False]

should "quietly" compute and return the result. If the third parameter is missing the default behavior should be to explain the computation.

Solution: see separate notebook.