Ever since Version 3 of Mathematica, there has been rich support for arbitrary mathematical typesetting and layout. Underlying all that power was a so-called box language, which allowed notebooks themselves to be Mathematica expressions. This approach turned out to be very powerful, and has formed the basis of many unique features in Mathematica. However, despite the power of the box language, in practice it was awkward enough for users to access directly that few did.
Starting in Version 6, there is a higher-level interface to this box language which takes much of the pain out of using boxes directly, while still exposing all the same typesetting and layout power. Functions in this new layer are often referred to as box generators, but there is no need for you to be aware of the box language to use them effectively. In this tutorial, we will take a look at box generators that are relevant for displaying a wide variety of expressions, and we will show some ways in which they can be used to generate beautifully formatted output that goes beyond simple mathematical typesetting.
front end supports all the usual style mechanisms available in word processors, for example including menus for changing font characteristics. However, it used to be very difficult to access those styling mechanisms automatically in generated output. Output continued to be almost universally plain 12 point Courier (or Times for those people using TraditionalForm
). To address this, the function Style
was created. Whenever you evaluate a Style
expression, its output will be displayed with the given style attributes active.
You can wrap Style
around any sort of expression. Here is an example that displays prime and composite numbers using different font weights and colors via Style
There are hundreds of formatting options that you could apply with Style
—see the documentation for Style
for a more complete listing—but there are a handful that are by far the most common, listed here.
Note that Style
can be arbitrarily nested, with the innermost one taking precedence if there is a conflict. Here we wrap Style
around the entire list to apply a new font to all elements of the list.
Another common thing to want is to have a portion of the output styled like text. It can look quite strange to have text appear in a font which is intended for use by code. For that purpose, we have a function Text
which ensures that its argument will always be rendered in a text font. (Those of you familiar with Mathematica
graphics will recognize the Text
function as a graphics primitive, but that use does not conflict with this use outside of graphics.)
can be used to set up a region on the screen where any option is active, not just options related to fonts. Later in this tutorial, we will see how Style
can even affect the display characteristics of other formatting constructs, like Grid
Using two-dimensional layout structures can be just as useful as applying style directives to those structures. In Mathematica
, the primary function for such layout is Grid
has very flexible layout features, including the ability to arbitrarily adjust things like alignment, frame elements, and spanning elements. (Other tutorials go into Grid
features in greater detail, but we will cover the highlights here.)
Look again at the Style
example which displays prime and composite numbers differently.
To put this into a Grid
, we first use Partition
to turn this 100-element list into a 10×10 array. Although you can give Grid
a ragged array (a list whose elements are lists of different lengths), in this case we give Grid
a regular array, and the resulting display is a nicely formatted layout.
Notice that the columns are aligned on center, and there are no frame lines. It is an easy matter to change either of these using Grid
A complete description of all Grid
options and their syntax is beyond the scope of this document, but it is possible to do some remarkable things with them. See the complete Grid
documentation for complete details.
There are a few convenience constructs related to Grid
. One is Column
, which takes a flat list of elements and arranges them vertically. This would be slightly awkward to do with Grid
. Here is a simple example, viewing the options of column in, well, a column.
What about laying out a list of things horizontally? In that case, the main question you need to ask is whether you want the resulting display to line wrap like a line of math or text would, or whether you want the elements to remain on a single line. In the latter case, you would use Grid
applied to a 1×n
But notice in this example that the overall grid shrinks so that it fits in the available window width. As a result, there are elements of the grid which themselves wrap onto multiple lines. This is due to the default ItemSize
option of Grid
. If you want to allow the elements of a grid to be as wide as they would naturally be, set ItemSize
Of course, now the whole grid is too wide to fit on one line (unless you make this window very wide), and so there are elements in the grid which you cannot see. That brings us to the other horizontal layout function: Row
Given a list of elements, Row
will allow the overall result to word wrap in the natural way, just like a line of text or math would. This type of layout will be familiar to those of you who might have used the old (and now obsolete) SequenceForm
As you can see, Row
does not leave space between elements by default. But if you give a second argument, that expression is inserted between elements. Here we use a comma, but any expression can be used.
If you resize the notebook window, you will see that Grid
continues to behave differently than Row
, and each is useful in different circumstances.
Using Output as Input
This is a good time to point out that Style
, and all other box generators are persistent in output. If you were to take a piece of output that had some formatting created by Style
and reuse that as input, the literal Style
expressions would appear in the input expression. Those of you familiar with the old uses of StyleBox
and even functions like MatrixForm
will find this a change.
Consider taking the output of this Grid
command, which has lots of embedded styles, and using it in some input expression.
Notice that the grid is still a grid, it is still blue, and the elements are still bold or gray as before. Also notice that having literal Grid
in the expression interferes with what would have otherwise been adding a scalar to a matrix, and raising the result to a power. This distinction is very important, since you almost always want these composite structures to resist being interpreted automatically in some way. However, if you ever do want to get rid of these wrappers and get at your data, that is easy enough to do.
Special Grid Entries
To allow more flexible two-dimensional layout, Grid
accepts a few special symbols like SpanFromLeft
as entries. The entry SpanFromLeft
indicates that the grid entry immediately to the left should take up its own space and also the space of the spanning character. There are also SpanFromAbove
. See "Grids, Rows, and Columns"
for detailed information.
This approach can be used to create complicated spanning setups. Typing something like the following as an input would take a long time. Luckily you can create this table interactively by using and in the submenu. If you want to see what would be involved in typing this, evaluate the cell, which will show how it should be typed as input.
We have already seen how to apply things like alignment and background to a grid as a whole, or to individual columns or rows. What we have not seen though is how to override that for an individual element. Say you want your whole grid to have the same background, except for a few special elements. A convenient way to do that is to wrap each such element in Item
, and then specify options to Item
which override the corresponding option in Grid
You could override this option with Style
too, but the purpose of Item
is to override it in a way that knows about the two-dimensional layout of Grid
. Notice in the preceding output that whenever two of the yellow cells are next to each other, there is no blue space between them. That would be impossible to do with constructs other than Item
The same thing goes for all Item
options, not just Background
. Consider the Frame
option. If you want no frame elements except around certain specified elements, you might think that you have to wrap them in their own Grid
with the Frame->True
setting. (We will learn a much easier way to add a frame around an arbitrary expression in the next section
But notice that adjacent framed elements do not share their boundaries. Compare that with using Item
, below, which has enough information to not draw more frame elements than are necessary. Notice now the frames of 2 and 11 meet at a single point, and how the frames of 2 and 3 share a single-pixel line, which in turn is perfectly aligned with the left frame of 13 and 23. That is the power of Item
Frames and Labels
Adding a frame or a label to an expression can be done with Grid
, but conceptually these are much simpler operations than general two-dimensional layout, and so there are correspondingly simpler ways to get them. For instance, Framed
is a simple function for drawing a frame around an arbitrary expression. This can be useful to draw attention to parts of an expression, for instance.
is another such function, which allows labels to be placed at arbitrary locations around a given expression. Here we add a legend to the Grid
example from the last section. (Spacer
is just a function that is designed to leave empty space.)
is yet another framing construct, which uses the underlying operating system's panel frame. This is different from Frame
, as different operating systems might use a drop shadow, rounded corners, or fancier graphic design elements for a panel frame.
Note that Panel
has its own concept of font family and size as well, so the contents of Grid
change font family and size, and the Text
changes font size. (Text
has its own opinion about font family though, and so it remains in Mathematica
's text font.) We will talk about this in some detail below in the section on the BaseStyle
Finally, we should point out that Panel
itself has an optional second argument to specify one or more labels, which are automatically positioned outside the panel, and an optional third argument to give details of that position. See the documentation for Panel
for more detail.
The annotations mentioned so far have a very definite visual component. There are a number of annotations which are effectively invisible, until the user needs them. Tooltip
for example does not change the display of its first argument, and only when you move the mouse pointer over that display is the second argument shown, as a tooltip.
is another such function, but instead of displaying the result in a tooltip, it uses the same area of the screen that had been used for the display before you moved the mouse pointer over it. If the two displays are different sizes, then the effect can be jarring, so it is a good idea to use displays which are closer to the same size, or use the Mouseover ImageSize
option to leave space for the larger of the two displays, regardless of which is being displayed.
Also similar to Tooltip
displays the extra information in the notebook's status area, typically in the lower-left corner, while PopupWindow
will display extra information in a new window when clicked.
Finally, you can specify an arbitrary location for an annotation by using the pair Annotation
When using annotations that are triggered merely by moving the mouse pointer over a region of the screen, it is important to keep the user in mind. Moving the mouse is not something that should trigger a long evaluation or a lot of visual clutter. But used sparingly, annotations can be quite helpful to users.
Finally, note that all these annotations work perfectly well in graphics too. So you can provide tooltips or mouseovers to aid users in understanding a complicated graphic you have created. In fact, even visualization functions like ListPlot
. See the documentation for details.
As we saw in the section "Frames and Labels
", constructs like Panel
actually work much like Style
, in that they set up an environment in which a set of default styles is applied to their contents. This can be overridden by explicit Style
commands, but it can also be overridden for the Panel
itself, through the BaseStyle
can be set to a style or a list of style directives, just like you would use in Style
. And those directives then become the ambient default within the scope of that Panel
As we have already seen, Panel
by default uses the dialog font family and size. But that can be overridden by using this BaseStyle
Actually, almost all of these box generators have a BaseStyle
option. For instance, here is a grid in which the default font color is blue. Notice that the elements that were gray stay gray, since the inner Style
wrapper trumps the outer Grid BaseStyle
. (This is one of the principal characteristics of option inheritance
, which is beyond the scope of this document to discuss.)
Say you have an expression with multiple occurrences of the same box generator, like a Framed
or a Panel
, and you want to change all of them to have the same set of options. It might be cumbersome to go through and add the same set of options to every occurrence of that function. Thankfully, there is an easier way.
is an option to Style
which, when set to a list of elements of the form
. sets up an environment with the given options as the ambient default for the given box-generating head. Those options will be active throughout the Style
wrapper, but only in any instances of the associated box generator.
Suppose you had an expression that contained some Framed
items, and you wanted them all to be drawn with the same background and frame style.
Actually, that input is too short to see the advantage of this syntax. Say you had this same list, but specified manually.
Now inserting Background
options into every Framed
wrapper is prohibitively time consuming, although you certainly could do it (or you could write a program to do it for you). But using DefaultOptions
, you can effectively set up an environment in which all Framed
wrappers will use your settings for Background
This approach makes it easy to create structures that follow uniform style guidelines without having to specify those styles in more than one place, which makes for considerably cleaner code, smaller file sizes, and easier maintenance.
No discussion of formatted output would be complete without at least a nod toward the formatting constructs that are unique to mathematical syntaxes.
We will not discuss these at length, but we will point out that these constructs do not have any built-in mathematical meaning in the kernel. For example, Superscript
will not be interpreted as Power
, even though their displays are identical. So you can use these as structural elements in your formatted output without having to worry about their meaning affecting your display.
Using the Box Language
One final note. Those of you who are already familiar with the box language might occasionally find that these box generators get in the way of your constructing low level boxes yourselves, and inserting their display into a piece of output. That can be true for any layered technology where one abstraction layer attempts to hide the layers on which it sits. However, there is a simple loophole through which you can take boxes which you happen to know are valid, and display them directly in output: RawBoxes
As with all loopholes, RawBoxes
gives you added flexibility, but it also allows you to shoot yourself in the foot. Use with care. And if you are not yet familiar with the box language, perhaps you should not use it at all.