Front End Frontiers

MiER vol 9.1: Button Basics

Louis J. D’Andria

The focus of my column, which up until now has been based on joint work with Richard J. Gaylord [GD] concerning computer simulation of individual and group social and economic interactions, has changed. Starting with this issue, the topic will be something that I hope is also of widespread interest: using the Mathematica Front End to its full potential. This will include discussing some common uses — such as this inagural column covering basic button construction — as well as some more advanced ones. It will also include all the details behind some features, which is often necessary to get the most out of those features. As there are very few differences between the front ends on various platforms, the focus will be on universal features and concepts.

Feel free to contact me (lou@wolfram.com) about topics you would like to see covered in a future column. It is my hope people will find that this column fills the role of trail guide, and not view it as just another piece of the mountain.

Introduction

One of the most useful, but possibly least used, features of Mathematica is the ability to include active elements known as buttons in a notebook. Clicking on a button can initiate any action in Mathematica, such as pasting typesetting information, creating a cell, or beginning an evaluation. Effective use of buttons can greatly simplify how you work.

This column will examine most aspects of button construction and design.

Predefined Button Styles

Before creating a button, it’s useful to look at an existing palette. A palette is just a special kind of notebook that contains some buttons. When Mathematica first launches, it automatically opens the Basic Input palette. You can also open this palette manually from the Palettes submenu of the File menu.

({{(■^□), (■/□)}, {(Sqrt[■]), (■^(1/□))}, {∫■ d□, (∂_□) ■}, {(∫_□^□)■ d□, (∂_(□,□))■}, {(∑_(□=□)^□) ■, (∏_(□=□)^□) ■}, {(({{□, □}, {□, □}})), (Subscript[■, [[□]]])}})({{({{π, e, i, ∞, °}, {×, ÷, ×, ->, :>}, {==, ≠, ≤, ≥, ∈}, {¬, ∧, ∨, ⋃, ⋂}, {α, β, γ, δ, ϵ}, {ζ, η, θ, κ, λ}, {μ, ν, ξ, π, ρ}, {σ, τ, ϕ, φ, χ}})}})

Pieces of the BasicInput palette

The buttons in this particular palette are designed to paste information into your notebook — the contents of the button are pasted into the notebook at the insertion point. The empty squares in some of the buttons are called placeholders, and can be filled in after the expression is in your notebook. If the button has a blackened square, called a selection placeholder, and if you have some expression highlighted or selected when you click the button, the selected expression will replace the selection placeholder. If you have never used this palette before, you should probably take a few minutes now to become familiar with it.

Creating a button like those on this palette, also called paste buttons, is exceedingly easy:

1. Construct the expression you want the button to contain. You can insert a □ or a ■ by typing \[ Placeholder] or \[ SelectionPlaceholder] respectively. For example.

(Sqrt[Tr[(((\[SelectionPlaceholder]-\[Placeholder]))^2)]])

2. Make it into a button by highlighting the expression

(Sqrt[Tr[(((\[SelectionPlaceholder]-\[Placeholder]))^2)]])

and selecting Create Button ⊳ Paste from the Input menu. (The other styles in this menu are discussed below.)

(Sqrt[Tr[(((\[SelectionPlaceholder]-\[Placeholder]))^2)]])

3. Activate the button. The easiest way is to make the cell containing the button into a palette by selecting Generate Palette from Selection from the File menu.

You could also activate the button in your original notebook by hightlighting the cell’s bracket and selecting Cell ⊳ Cell Properties ⊳ Cell Active.

That’s it! Clicking on this active button will paste its contents, just as clicking on a button in the Basic Input palette would.

Palettes of Buttons

If you want to create a grid of buttons instead of just one, begin by using the menu command Create Table/Matrix/Palette in the Input menu, and choose the Palette option in the resulting dialog. This will automatically fill the grid with empty Paste style buttons, which you can then fill in (essentially doing step 2 before step 1).

Other Button Styles

In addition to pasting information, buttons can be used to initiate any action that Mathematica is capable of performing. There are some predefined buttons styles in the default style sheet, which are listed in the Input ⊳ Create Button submenu. The Hyperlink style is for creating hyperlinks to other notebooks or to the Web (the interface for building hyperlinks is the Create Hyperlink… item in the Input menu). The other button styles ending in "link" allow direct access to locations in the Help Browser, and will be discussed in detail some other time.

The remaining styles begin kernel evaluations when you click on such a button. The Evaluate style will perform a paste just as the buttons created above, after which the pasted information will evaluate in place, and be replaced by its result. These are the kind of buttons used in the AlgebraicManipulation palette, available in the File ⊳ Palettes submenu.

({{Expand[■]}, {Factor[■]}, {Together[■]}, {Apart[■]}, {Cancel[■]}, {Simplify[■]}, {FullSimplify[■]}, {TrigExpand[■]}, {TrigFactor[■]}, {TrigReduce[■]}, {ExpToTrig[■]}, {TrigToExp[■]}, {PowerExpand[■]}, {ComplexExpand[■]}})

The AlgebraicManipulation palette

The CopyEvaluate style pastes the button contents (and any selection that would affect the result of the paste, if your button has a ■) into a new cell, and evaluates the resulting expression in place as the Evaluate style does.

The EvaluateCell and CopyEvaluateCell styles do the same thing as Evaluate and CopyEvaluate, except that the cell is evaluateed normally, as if you had pressed ⇧[⏎].

Building Buttons from Scratch

The above button styles are defined in the default style sheet. However, they depend heavily on front end command constructs such as NotebookApply and FrontEndExecute. Rather than begin a discussion of such constructs here, we look instead at building buttons which perform arbitrary kernel action. Front end commands will be discussed next time.

Typesetting Background

Beginning in version 3.0 of Mathematica, notebook files and everything in them became Mathematica expressions. The notebook itself is an expression with head Notebook; every cell in a notebook is an expression with head Cell. Whenever you tweak some aspect of your notebook, from font size to background color, you are actually setting options (or instructing the front end to set options) for the Cell or Notebook expression they affect.

Graphics, typesetting structures, and buttons, are all stored as Mathematica expressions too. What you see on screen is the result of the front end interpreting and displaying the underlying expression. You can view the expression which underlies a particular cell by selecting that cell and choosing Show Expression from the Cell menu. (Select it again to toggle back to the formatted cell.) If you edit the underlying expression manually, the display will change accordingly.

For instance, if you view the cell expression corresponding to the button we created above

(Sqrt[Tr[(((\[SelectionPlaceholder]-\[Placeholder]))^2)]])

you would see a nested expression like this.

Cell[BoxData[
     ButtonBox[
       SqrtBox[(* deleted to save space *)],
       ButtonStyle->"Paste"]], "Input"]

The displayed button corresponds to the underlying ButtonBox expression, which takes one argument plus options.

ButtonBox[contents, opts]

The first argument, contents, is what gets displayed on the face of the button (in this case, a typesetting directive representing a square root); the options opts determine other aspects of the display and behavior of the button.

ButtonBox Options

In order to understand how to create a button which does what you want it to do, you should first understand the options to ButtonBox and how they interact with one another. If you lookup ButtonBoxOptions in the Option Inspector, you will find a dozen options:

({{ButtonStyle, ButtonData, ButtonMargins}, {ButtonFunction, ButtonNote, ButtonMinHeight}, {ButtonEvaluator, ButtonFrame, ButtonExpandable}, {ButtonSource, Background, Active}})

Half of these — those in italics — are just for display and have nothing to do with a button’s action. For information on those options, look them up in the Help Browser’s Master Index, and follow the links to Other Information. This information is also available online at <http://documents.wolfram.com/v4/index_0_4_5_8_2.html>.

The remaining options determine what happens when you click on the button. We look at these options one by one.

Active, ButtonStyle, and ButtonEvaluator

We’ve already seen how to activate a button by creating a palette or by making the cell containing the button an active cell. You can also activate a single button by setting Active->True in the ButtonBox. The default is typically Active->False, so that clicking on a button doesn’t perform the button’s action. Think of this as electricity: It doesn’t matter if the wiring is correctly connected — if there’s no electricity, the button won’t do a thing.

Paste and Evaluate in the previous section were examples of use of the ButtonStyle option. The default is ButtonStyle->Paste.

ButtonEvaluator is a somewhat more interesting option. Remember that the front end is an application which communicates with other applications — usually kernels — over MathLink. The ButtonEvaluator option specifies which of these kernels or other applications to use as the evaluation engine for the button’s action. You can set it to the name a kernel (the names of defined kernels are listed in the Kernel ⊳ Kernel Configuration Options… dialog), or to Automatic which will use your default kernel.

There is one other possible setting: ButtonEvaluator->None. The front end not only communicates with other programs over MathLink, but communicates with itself too. Most features of the front end, such as opening a notebook or creating a cell, have an associated command that one could use in a button. In fact, all the defalt button styles, including those that begin evaluations, use ButtonEvaluator->None because the actions can be performed entirely in the front end. More complicated actions or evaluations will of course require a kernel.

\[MathematicaIcon] (Underscript[↔,   ButtonEvaluator -> Automatic  ]) \[KernelIcon]

\[MathematicaIcon] (Underscript[↔,   ButtonEvaluator -> None  ]) \[MathematicaIcon]

For example, let’s use another method of creating buttons. Since buttons are just expressions, and the kernel is so good at handling expressions, it is possible to use the kernel to create buttons. The function DisplayForm comes in handy for this.

?DisplayForm

So to create a button, we need only construct the appropriate ButtonBox expression, and then evaluate DisplayForm[ButtonBox[...]]. This gives us another way to create the button from the previous section.

ButtonBox["\!\(\@Tr[\((\[SelectionPlaceholder]\\\\  - \\\\ \[Placeholder])\)\^2]\)",ButtonStyle->"Paste",Active->True]//DisplayForm

It happens that although paste buttons are designed to work entirely in the front end, the kernel knows how to deal with them too. So here is another button which does the same thing.

ButtonBox["\!\(\@Tr[\((\[SelectionPlaceholder]\\\\  - \\\\ \[Placeholder])\)\^2]\)",ButtonStyle->"Paste",Active->True,ButtonEvaluator->Automatic]//DisplayForm

ButtonFunction

The ButtonFunction option is the work-horse of the button. This option is set to the instructions for what the button is supposed to do. The setting gets sent directly to the kernel specified by ButtonEvaluator. You can put any Mathematica function you want in the setting for ButtonFunction, but keep the following two points in mind.

1. Although notebooks and cells are Mathematica expressions, the front end doesn’t understand special shorthand syntax such as + representing Plus, or ; representing CompoundExpression. The front end’s parser can recognize expressions in full form [Wol], plus the shorthand for List, Rule, and RuleDelayed ({}, ->, and :>).

This makes it difficult to edit the setting for ButtonFunction because programmers are not used to editing a function

Block[{c=10^6},While[!PrimeQ[++c]];Print[c]]

in full form

Block[{Set[c,Power[10,6]]},CompoundExpression[While[Not[PrimeQ[PreIncrement[c]]]],Print[c]]]

Again, the DisplayForm technique can help to keep readable code. Note the use of RuleDelayed to prevent the function from evaluating during the application of DisplayForm.

ButtonBox["Smallest Seven Digit Prime", ButtonFunction:>Block[{c=10^6},While[!PrimeQ[++c]];Print[c]],ButtonEvaluator->Automatic,Active->True]//DisplayForm

2. Since these button functions are not evaluated in the kernel as part of the main loop, there is no output in the conventional sense — you will not see an Out[n] prompt followed by the result of evaluating the function. For example, this cell contains a button whose function adds two and two.

Cell[BoxData[
     ButtonBox[
       "Add two and two",
       ButtonFunction:>Plus[2, 2],
       ButtonEvaluator->Automatic,
       Active->True]], "Input"]

Clicking on this button will have no visible effect, even though the function has evaluated. You can see the result by generating a side effect that will be visible, such as by using Print. In this case, it’s easy to edit the cell expression so that it contains the revised function using Format ⊳ Show Expression.

Cell[BoxData[
     ButtonBox[
       "Add two and two",
       ButtonFunction:>Print[Plus[2, 2]],
       ButtonEvaluator->Automatic,
       Active->True]], "Input"]

Example: Loading Packages

Button Example

Before delving into the final two options — ButtonSource and ButtonData — look at some examples. Consider a button that loads a package. It might do so by asking the kernel to evaluate the necessary Needs command directly:

Cell[BoxData[
     ButtonBox[
       RowBox[{"Load", " ", "Combinatorica"}],
       ButtonFunction:>Needs[ "DiscreteMath`Combinatorica`"],
       ButtonEvaluator->Automatic,
       Active->True]], "Input"]

Another way is to use the default button style EvaluateCell to paste the command into a cell and then evaluate that cell. This is useful if an evaluation history is desired, because the evaluated command is now in the notebook.

Cell[BoxData[
     ButtonBox[
       RowBox[{
       "Needs", "[", "\"\<DiscreteMath`Combinatorica`\>\"",
         "]"}],
       Active->True,
       ButtonStyle->"EvaluateCell"]], "Input"]

Palette Example

Now we look at one special consideration of creating a palette of buttons instead of a single button. Many times, all the buttons on the palette will have something in common, such as their settings for ButtonStyle or ButtonEvaluator. In such situations, it is possible (and preferable) to have a single setting which is inherited by all the buttons in the palette. This is done through the cell option ButtonBoxOptions. The setting for this option is a list of options for ButtonBox, and any buttons in the cell will inherit these option settings, unless those same options are explicitly set in the buttons already [GG]. So in this grid of buttons, every button will inherit the setting ButtonEvaluator->Automatic from the setting within ButtonBoxOptions.

Cell[BoxData[GridBox[{
         {ButtonBox["Combinatorica",
             ButtonFunction:>Needs[
               "DiscreteMath`Combinatorica`"]]},
         {ButtonBox["Notation",
             ButtonFunction:>Needs[ "Utilities`Notation`"]]},
         {ButtonBox["Graphics3D",
             ButtonFunction:>Needs[ "Graphics`Graphics3D`"]]}},
       RowSpacings->0,
       ColumnSpacings->0]], "Input",
   ButtonBoxOptions->{ButtonEvaluator->Automatic,
   Active->True}]

ButtonSource and ButtonData

Here is where things start getting more confusing, and more interesting.

?ButtonSource

?ButtonData

What does this mean? We’ve been using arbitrary settings for ButtonFunction, supplying all the arguments, and everything has been working just fine. Or has it?

ButtonSource and ButtonData are relevant when you supply a ButtonFunction setting that is a pure function [Wol], such as (Print[{#1, #2}]&). In that case, you can have the #1 and #2 filled in automatically when the button is clicked with some data either from the button or from the enclosing cell.

The setting for ButtonData can be any Mathematica expression, which is passed verbatim to the button function as its second argument.

The setting for ButtonSource "specifies the first argument" for the button’s function, but it does not give the argument itself; rather, it gives the location of the argument. The default setting of Automatic says to use the setting for ButtonData if there is one, and if not use the first argument of the ButtonBox. You could also set ButtonSource->ButtonData or ButtonSource->ButtonContents respectively.

Setting ButtonSource->Cell is a good way to create a self-replicating cell (recall that Paste is the default setting for ButtonStyle):

Cell[BoxData[
     ButtonBox["replicate",
       Active->True,
       ButtonSource->Cell]], "Input"]

In summary: clicking on an active button sends the ButtonFunction to the ButtonEvaluator, after having resolved the ButtonSource and ButtonData if necessary.

Example Revisited

Now we have enough information to create a package loading button in a number of ways.

Cell[BoxData[
     ButtonBox["Combinatorica",
       ButtonFunction:>(Needs[ #2]&),
       ButtonEvaluator->Automatic,
       ButtonData:>"DiscreteMath`Combinatorica`",
       Active->True]], "Input"]

Cell[BoxData[
     ButtonBox["Combinatorica",
       ButtonFunction:>(Needs[ #]&),
       ButtonEvaluator->Automatic,
       ButtonData:>"DiscreteMath`Combinatorica`",
       Active->True,
       ButtonSource->Automatic]], "Input"]

Cell[BoxData[
     ButtonBox["Combinatorica",
       ButtonData:>"DiscreteMath`Combinatorica`"]], "Input",
   ButtonBoxOptions->{ButtonFunction:>(Needs[ #2]&),
   ButtonEvaluator->Automatic,
   Active->True}]

The last of these is most useful when there are multiple cells which can have the same ButtonFunction with different arguments. The arguments are supplied by ButtonData, which is now the only option that needs to be set in the individual buttons.

Cell[BoxData[GridBox[{
         {
           ButtonBox["Combinatorica",
             ButtonData:>"DiscreteMath`Combinatorica`"]},
         {
           ButtonBox["Notation",
             ButtonData:>"Utilities`Notation`"]},
         {
           ButtonBox["Graphics3D",
             ButtonData:>"Graphics`Graphics3D`"]}
         },
       RowSpacings->0,
       ColumnSpacings->0]], "Input",
   ButtonBoxOptions->{ButtonFunction:>(Needs[ #2]&),
   ButtonEvaluator->Automatic,
   Active->True}]

Given this template, it is easy to write a function to produce a palette for loading packages of your choice. Use CellPrint instead of DisplayForm to display a complete Cell expression.

loadContexts[{contexts__String}] :=CellPrint[Cell[BoxData[GridBox[{ButtonBox[#,ButtonData->#]}&/@ {contexts},RowSpacings->0,ColumnSpacings->0]],"Input",ButtonBoxOptions->{ButtonFunction:>(Needs[#2]&),ButtonEvaluator->Automatic,Active->True}]]

loadContexts[{"Finance`InterestRates`","Parallel`Parallel`","Testing`TestMaster`"}]

Example: Colors

The task of designing web pages with usable colors can be difficult, especially if one does not uses a WYSIWYG editor which shows all aspects of the design, such as the color of various elements. This example builds a palette in Mathematica which looks like a grid of colored boxes. When you click a box, the hex representation of the color, suitable for embedding in web pages, is pasted into your notebook.

For this example, we need not start from scratch. There is a palette demo in the help browser which provides almost this functionality, except that it pastes the Mathematica representation of a color, an expression with head RGBColor or GrayLevel. Locate this palette by opening the Help Browser, selecting the Getting Started / Demos area, and looking in the Demos category for Palette Demos.

({{ ,  ,  ,  ,  ,  }, { ,  ,  ,  ,  ,  }, { ,  ,  ,  ,  ,  }, { ,  ,  ,  ,  ,  }, { ,  ,  ,  ,  ,  }, { ,  ,  ,  ,  ,  }})

A small piece of the demo Color Palette

Given a palette, how can one determine the Cell expression(s) contained in the palette? The front end provides a menu item that does this: File ⊳ Generate Notebook from Palette. This will open a copy of the palette notebook suitable for editing, although while in this form the palette buttons may be inactive. Use the Show Expression command as above to view the Cell expression behind this palette.

Cell[BoxData[GridBox[{
         {
           ButtonBox[" ",
             ButtonData:>"RGBColor[0, 0, 0]",
             Background->GrayLevel[0]],
           ButtonBox[" ",
             ButtonData:>"RGBColor[0.2, 0, 0]",
             Background->RGBColor[0.2, 0, 0]],
           ButtonBox[" ",
             ButtonData:>"RGBColor[0.4, 0, 0]",
             Background->RGBColor[0.4, 0, 0]],
           (* remainder of grid deleted to save space *)
       ]], "Text",
  (* options deleted *) ]

So how does this palette work? As no style or evaluator is specified for the buttons, they all inherit the default settings ButtonStyle->Paste and ButtonEvaluator->None. The only options which are set in each ButtonBox are ButtonData and Background. It’s easy to guess (correctly) that Background determines the color of the displayed button, and the setting for ButtonData will be used as the information to paste. (Why the latter is true is temporarily left unsubstantiated, but will be discussed next time). To change these buttons so that they paste hex values instead of rgb values, change the settings for ButtonData.

Cell[BoxData[GridBox[{
         {
           ButtonBox[" ",
             ButtonData:>"#000000",
             Background->GrayLevel[0]],
           ButtonBox[" ",
             ButtonData:>"#330000",
             Background->RGBColor[0.2, 0, 0]],
           ButtonBox[" ",
             ButtonData:>"#660000",
             Background->RGBColor[0.4, 0, 0]],
           (* remainder of grid deleted to save space *)
       ]], "Text",
  (* options deleted *) ]

It is left as an exercise to convert this palette in its entirety to hex color information.

As is usually the case with buttons, there is another way to design this palette. Using the kernel to do the conversion to a different color scheme has the benefit of not needing to generate the values beforehand, but it also allows more flexibility in design. In this palette,

({{RGBColor}, {CMYKColor}, {GrayLevel}, {({{ ,  ,  ,  ,  ,  }, { ,  ,  ,  ,  ,  }, { ,  ,  ,  ,  ,  }, { ,  ,  ,  ,  ,  }, { ,  ,  ,  ,  ,  }, { ,  ,  ,  ,  ,  }})}})

the user clicks on one of the top buttons to change the color format used for data from this palette. This is implemented in each of the top buttons by setting a new kernel variable, $myColorFunction, to RGBColor, CMYKColor, or GrayLevel respectively. After that, the colored buttons paste the color value in the user’s chosen format. Here is an excerpt of the Cell expression, including the all important ButtonFunction within ButtonBoxOptions towards the bottom.

Cell[BoxData[GridBox[{
         {
           ButtonBox["RGBColor",
             ButtonFunction:>Set[ $myColorFunction, RGBColor]]},
         {
           ButtonBox["CMYKColor",
             ButtonFunction:>Set[ $myColorFunction, CMYKColor]]},
         {
           ButtonBox["GrayLevel",
             ButtonFunction:>Set[ $myColorFunction, GrayLevel]]},
         {GridBox[{
               {
                 ButtonBox[" ",
                   ButtonData:>"RGBColor[0, 0, 0]",
                   Background->GrayLevel[0]],
                 ButtonBox[" ",
                   ButtonData:>"RGBColor[0.2, 0, 0]",
                   Background->RGBColor[0.2, 0, 0]],
                 ButtonBox[" ",
                   ButtonData:>"RGBColor[0.4, 0, 0]",
                   Background->RGBColor[0.4, 0, 0]],
               (* etc *)
               ]}
         }]], "Text",
   ButtonBoxOptions->{ButtonFunction:>(CompoundExpression[
       If[
         Not[
           ValueQ[ $myColorFunction]],
         Set[ $myColorFunction, RGBColor]],
       NotebookApply[
         InputNotebook[ ],
         ToString[
           ToColor[
             ToExpression[ #2], $myColorFunction], InputForm]]]&),
   ButtonEvaluator->Automatic,
   Active->True},
   GridBoxOptions->{RowSpacings->0,
   ColumnSpacings->0}]

This example contains a new concept: overriding option inheritance. Notice that there is an explicit setting for ButtonFunction in the top three buttons, and also a setting within ButtonBoxOptions. The latter is used for those buttons which don’t have an explicit setting.

A discussion of NotebookApply and InputNotebook — important front end commands — is deferred until next time.

Summary

Even without knowing any front end commands, creating and editing buttons can simplify your daily work and improve the usability of your notebooks by others. Buttons can simplify many common tasks, from constructing and pasting commonly entered data to evaluating arbitrary expressions in any kernel or other MathLink program. The focus of this column next time will be the pervasive front end commands, tokens, and packets. You use them every time you use Mathematica, whether you know it or not.

References

[GD] Gaylord, Richard J. and Louis J. D’Andria. Simulating Society: A Mathematica Toolkit for Modeling Socioeconomic Behavior. TELOS/Springer-Verlag, New York, 1998.

[GG] Glynn, Jerry and Theodore Gray. The Beginner’s Guide to Mathematica Version 3. Cambridge University Press, 1997.

[Hin] Hinton, Paul J. Button Box How-To: Making a Graphics Generator. MathSource Item 0209-809, http://www.mathsource.com/.

[Mae] Maeder, Roman. Programming in Mathematica, Third Edition. Addison-Wesley, 1996.

[Wol] Wolfram, Stephen. The Mathematica Book, Fourth Edition. Wolfram Media, Cambridge University Press, 1999.

About the Author

Comp: I assume you still have my "about the author" blurb from the "old" column. I’ll review it at proof time, to make sure it’s still valid.