Smarter Art

Create Custom SmartArt Graphics For Use In The 2007 Office System

Janet Schorr

This article discusses:

  • SmartArt graphic data model
  • Creating XML for custom SmartArt graphics
  • Algorithms, constraints, and rules
  • Testing and debugging custom SmartArt graphics
This article uses the following technologies:
The 2007 Microsoft Office System

Code download available at: Smart Art 2007_02.exe(152 KB)

Contents

Planning a Graphic Layout
Layout Nodes and Algorithms
Layout Tree and Data Model Mapping
Shape Properties
Constraints, Rules, and Text Properties
Packaging the Layout Definition File
Testing the Graphic Layout
Error Types and the Error Log
Valid File with Design Errors
Modifying Existing Graphic Layout Definitions
What's Next?

The 2007 Microsoft Office system offers a new way to quickly add polished graphics and diagrams to your Office files, including Word documents, Excel® spreadsheets, PowerPoint® presentations, and Outlook® e-mail messages. The new feature, called SmartArt™ graphics, incorporates a gallery (library) of templates and predefined shapes that can be quickly inserted and configured. It provides automatic sizing and alignment, while allowing you to edit objects and properties (see Figure 1 for several examples). But as you work with these graphics, experimenting with all the possibilities, it's easy to imagine additional graphics you'd like to see in the gallery. This isn't a problem-SmartArt graphics is completely extensible, allowing you to create your own layouts.

Each graphic layout in the SmartArt layout gallery has its own underlying XML file that defines how the SmartArt graphic will construct the object based on the dataset entered by the user (in the case of Figure 1, this dataset consisted of three text strings: "Design", "Create", and "Test"). SmartArt graphic layouts use a specific set of algorithms that provide different layout options, including a linear flow algorithm, a cycle algorithm, and two algorithms that work together to create a hierarchy diagram. It also supports a composite algorithm that lets you determine exactly where and how to size and position various shapes, giving you the flexibility to create a wide range of graphics. In this article, I'll go through the basics of creating your own SmartArt graphic layout.

Figure 1a Sample Diagrams Created with SmartArt Graphics

Figure 1a** Sample Diagrams Created with SmartArt Graphics **

Figure 1b

Figure 1b

Figure 1c

Figure 1c

Figure 1d

Figure 1d

Planning a Graphic Layout

The first step in creating a SmartArt graphic layout is deciding what the graphic should look like. Once that's settled, you can start to analyze the SmartArt graphic to figure out how to create it.

Let's say you want to create a graphic that looks like the one shown in Figure 2. It will take several steps to achieve this SmartArt graphic, and I'll walk through the details of each in this article. First, figure out the shapes you'll need to create the graphic-in this case, you'll need rounded rectangles for the blue shapes, rectangles for the white lines, and rectangles with no lines or fill for text areas.

Figure 2 Target Graphic Layout

Figure 2** Target Graphic Layout **(Click the image for a larger view)

Next, look at how the shapes are arranged. In this case, the blue rectangles are in a horizontal line, starting at the left side of the drawing area; the white boxes are combined with the blue boxes to create a single composite shape; and there is white space between each of the composite shapes. The arrangement of shapes is determined by one of SmartArt's algorithms for linear flows, bending linear flows, cycles, hierarchies, and composite (or fixed position) layouts.

Now look at how the text is displayed in the shapes. All SmartArt graphics map back to an underlying data model that can be visualized as a hierarchical list. For example, the text shown in the graphic in Figure 2 is based on the list shown in Figure 3.

Figure 3 Model

Design
Step One
Step Two
Step Three
Create
Step One
Step Two
Step Three
Test
Step One
Step Two
Step Three

In a SmartArt graphic, each shape can support multiple levels of text, which map back to this structure. In the sample in Figure 2, each composite shape contains two levels of text. The first level is sometimes called parent text or level-one items. The second level is sometimes called child text or level-two items. In general, child text has bullets in front to show that it's subordinate to the parent text.

The final step is to determine how you want it to display when it's abstracted away from a specific dataset. SmartArt graphic layouts provide a number of possibilities.

Static Graphic Layout If you always want to display the same number of shapes, you can create a static graphic layout. For our example, I can create a layout that always includes three shapes. The text from the users first three level-one items displays in the shapes, but any text added to subsequent level-one items won't display.

Semi-Dynamic Graphic Layout Using a semi-dynamic graphic layout, you can display only as many composite shapes as there are level-one items, up to a specified maximum number of shapes. For this example, I can create a graphic that includes from zero to three composite shapes. As users add subsequent lines of level-one text, new shapes are added. However, if they add more than three lines of level-one text, no new shapes are added.

Dynamic Graphic Layout A dynamic graphic layout isn't limited to a specific number of shapes. You can have as many composite shapes as there are lines of level-one text. As more shapes are added, the shapes get smaller as needed to fit inside the drawing area. For our sample graphic, a dynamic graphic layout is the best choice.

Layout Nodes and Algorithms

SmartArt graphic layouts are created in XML files that describe what shapes to create, how they map back to the data model, and which algorithms to use to lay out the shapes. (The XML files are part of an open document package, similar to the new file formats used for Word and PowerPoint.) One of these files, layout1.xml, provides the main layout definition.

The basic building block of a layout definition is the layout node. Each node in a layout has an associated algorithm that specifies either how to size and position its child layout nodes or how to size the text within its shape. Ultimately, all the nodes in a layout are nested together under a single layout node (see Figure 4).

Figure 4 Graphical Layout Definition

Figure 4** Graphical Layout Definition **(Click the image for a larger view)

The layout nodes in the layout definition form a hierarchical layout tree. In reality, the tree will have a composite layout node and a space layout node for every parent text item in the user's data model. However, the definition of this layout node and its descendants is the same for each one, so the layout definition file only needs to specify this set of layout nodes once, with some additional information that controls how many times to create this pattern of layout nodes for the graphic. Figure 5 shows the basic structure of the XML for this example.

Figure 5 XML Structure Defining the Sample Layout Tree

<?xml version="1.0" encoding="utf-8"?>
<layoutDef xmlns=
        "https://schemas.openxmlformats.org/drawingml/2006/diagram">
    <layoutNode name="diagram">
        <alg type="lin" />
        <presOf />
        <forEach axis="ch" ptType="node">
            <layoutNode name="composite">
                <alg type="composite" />
                <presOf />
                <layoutNode name="roundRect">
                    <alg type="sp" />
                    <presOf axis="self" />
                </layoutNode>
                <layoutNode name="parentText">
                    <alg type="tx" />
                    <presOf axis="self" />
                </layoutNode>
                <layoutNode name="whiteRect">
                    <alg type="sp" />
                    <presOf />
                </layoutNode>
                <layoutNode name="childText">
                    <alg type="tx" />
                    <presOf axis="des" ptType="node" />
                </layoutNode>
            </layoutNode>
            <forEach axis="followSib" ptType="sibTrans" cnt="1">
                <layoutNode name="space">
                    <alg type="sp" />
                    <presOf axis="self" />
                </layoutNode>
            </forEach>
        </forEach>
    </layoutNode>
</layoutDef>

Notice that in the XML, the layout nodes all have assigned names. These names are optional in this example, but may be required for reference in other parts of the definition. In addition, this naming can help you structure the XML and identify the various sections.

Layout Tree and Data Model Mapping

You'll notice that in addition to the layout node and algorithm tags, the XML sample also contains forEach and presOf tags. These indicate how to map the layout nodes to the user's data model.

The underlying data model in a SmartArt graphic is a collection of nodes and relationships. There are two kinds of relationships in SmartArt graphics: parent/child transitions and sibling transitions. Parent/child transitions construct the hierarchical relationship between nodes. Sibling transitions are relationships between adjacent nodes that have parent/child relationships to the same parent. Figure 6 illustrates these relationships.

Figure 6 Relationships in SmartArt Graphic

Sample Bulleted List


o Parent One
    o Child One
    o Child Two

o Parent Two
    o Child One

Corresponding Data Model

o Root Element
    o Parent/child transition: Root to "Parent One"
    o Node: "Parent One"
        o Parent/child transition: "Parent One" 
                  to "Child One"
        o Node: "Child One"
        o Sibling transition: "Child One" 
                  to "Child Two"
        o Parent/child transition: "Parent One" 
                  to "Child Two"
        o Node: "Child Two"
        o Sibling transition: "Child Two" 
                  to "Child One"
    o Sibling transition: "Parent One" to "Parent Two"
    o Parent/child transition: Root to "Parent Two"
    o Node: "Parent Two"
        o Parent/child transition: "Parent Two" to "Child One"
        o Node: "Child One"
    o Sibling transition: "Parent Two" to "Parent One"

The forEach elements in the layout definition XML move through the data model to select a set of nodes, and the presOf (presentation of) elements map the layout nodes to specific items in the data model. The attributes elements are outlined in Figure 7.

Figure 7 forEach and presOf Attributes

Attribute Description
axis This determines how to navigate through the data model, setting the context node as it moves. The context node always begins with the root element of the data model. Generally, the following axis values are used in SmartArt graphic layouts: self (returns the current context node), child (returns the immediate children of the current context node), des (returns all descendants of the current context node), desOrSelf (returns the current context node and all its descendants), and followingSib (returns the next item in the data model, regardless of whether it's a node or a transition).
ptType This determines the type of data model item to select and works as a filter against the items returned by the axis value. ptType can have one of three values: node (text items, which display as bullet points in the SmartArt graphic text area), parChTrans (parent-child transitions), or sibTrans (sibling transitions).
st For "start", this indicates which item in the returned set to select first. The default value for this attribute is 1, so it is often omitted.
cnt For "count", this indicates how many items in the returned set to select. The default value for this attribute is 0, which selects all items.
hideLastTrans This flag determines whether the last sibling transition in the returned set is filtered out of the set. The default value for this attribute is true, but in some cases, such as cycle diagrams, you may want to set it to false.

The XML for the sample graphic layout contains two forEach elements, as shown here:

<forEach axis="ch" ptType="node">
<forEach axis="followSib" ptType="sibTrans" cnt="1">

The first selects all nodes that are direct children of the root element, essentially selecting each level-one text item in the bulleted list. It then creates the layout nodes nested inside the forEach element for each selected data model item. As each item is acted on, the context item resets to the next node in the selected set.

The second forEach element selects the sibling transition item following the current context element. Because this forEach element is nested inside the preceding forEach element, it essentially selects the sibling transitions between each item in the bulleted list.

In the sample XML, each layoutNode has a presOf statement. For example:

<presOf />
<presOf axis="self" />
<presOf axis="des" ptType="node" />

An empty presOf element (<presOf />) indicates that the layoutNode does not map to anything in the data model. These tags are used for shapes without text, as well as for layout nodes without shapes that are used by algorithms to lay out the actual shapes.

A presOf with axis="self" associates the context item with the generated layout node. In the sample XML, this presOf puts the parent text into the parent text area shape.

A presOf with axis="des" and ptType="node" associates all of the descendants of the context item with the generated layout node. For the sample, this presOf puts all of the child text for a specific parent into the same text area shape.

Shape Properties

Now that the structure of the graphic is set up and the layout nodes are mapped to the data model, you can add information about the shapes being created. SmartArt graphic layouts can use any of the standard Office shapes.

Not all layout nodes need to display shapes; some are used to structure the graphic or provide additional space in the resulting graphic during layout. In the sample graphic, the layout nodes used for the linear flow and composite algorithms and for the white space between composite shapes do not display shapes. Each of these nodes is assigned an empty shape element, as shown in the XML in Figure 8.

Figure 8 Assigning an Empty Shape Element

<layoutNode name="diagram">
    <alg type="lin" />
    <presOf />
    <shape />
    <forEach axis="ch" ptType="node">
        ...
    </forEach>
</layoutNode>

<layoutNode name="composite">
    <alg type="composite" />
    <presOf />
    <shape />
    ...
</layoutNode>

<layoutNode name="space">
    <alg type="sp" />
    <presOf axis="self" />
    <shape />
</layoutNode>

The empty shape element isn't required and is usually the default value (the actual default is determined by the algorithm associated with a layout node). However, including the empty tag explicitly indicates that you are not assigning a shape to the layout node.

Now we can start adding shapes for the actual graphic. As I described, each composite shape is composed of two visible rectangles: the rounded blue rectangle and the regular white rectangle. The shape is identified by assigning the shape ID as the type in the shape tag. For the rounded rectangle, this value is roundRect.

The rounded rectangle is one of the Office shapes that has handles that let you adjust aspects of the shape appearance. For this graphic, we don't want the shape to be as rounded as it is by default. So we use the XML to set the adjust points as well as the shape type.

Finally, to make sure the graphic assigns an appropriate look to the rectangle (for example, blue when the default theme is used in PowerPoint), we use the XML to assign a style label to the layout node. The default style label for shapes associated with data model nodes is node1. However, that style generally uses a different colored line and won't align well with the white rectangle. So for this example I chose to use the style label alignNode1:

<layoutNode name="roundRect" styleLbl="alignNode1" >
    <alg type="sp" />
    <presOf axis="self" />
    <shape type="roundRect">
        <adjLst>
            <adj idx="1" val="0.1" />
        </adjLst>
    </shape>
</layoutNode>

Now, you might be wondering how you know what values to use for the adjust handles and how you can determine the shape types without looking up the values in reference material. Here's a little trick. The new PowerPoint file format, like the new Word and Excel file formats, is based on XML. You can add the shape you want to a blank slide, set the adjust handles, and then save the file. By looking at the resulting XML (first rename the resulting PowerPoint file to have a .zip extension and then open the ZIP package to access the XML data), you can deduce the appropriate shape name and adjust handle values. But keep in mind that PowerPoint shapes and SmartArt graphic layouts use different measurement scales, so you'll need to adjust the value. For example, here is the XML from the PowerPoint file for the rounded rectangle used in the sample graphic:

<a:prstGeom prst="roundRect">
    <a:avLst>
        <a:gd name="adj" fmla="val 10000" /> 
    </a:avLst>
</a:prstGeom>

The white rectangle is much easier. For this shape, all that's required is the shape type-in this case, rect. For the style label, you need to ensure that the box remains contrasted from the rounded rectangle and also stays in front when 3D properties are set. The style label fgAcc1 (foreground accent 1) defines the appropriate look:

<layoutNode name="whiteRect" styleLbl="fgAcc1" >
    <alg type="sp" />
    <presOf />
    <shape type="rect" />
</layoutNode>

Finally, our graphic contains two text area shapes, which are also simple rectangles. Since you don't want these shapes to be visible to the user, you can use the hideGeom (hide geometry) attribute to prevent line and fill values from displaying. And because you want the text to look as if it's part of the blue rectangle, use the same style label for these shapes as you used for the rounded rectangle:

<layoutNode name="parentText" styleLbl="alignNode1" >
    <alg type="tx" />
    <presOf axis="self" />
    <shape type="rect" hideGeom="true" />
</layoutNode>

<layoutNode name="childText" styleLbl="alignNode1" >
    <alg type="tx"/>
    <presOf axis="des" ptType="node" />
    <shape type="rect" hideGeom="true" />
</layoutNode>

Constraints, Rules, and Text Properties

The algorithms assigned to layout nodes determine how the subsequent layout nodes and their shapes are arranged on the canvas. While the algorithms support default shape sizes and fallback behavior, you'll almost always want to control some aspects of the shape sizing and text font behavior through a layout definition.

Constraints allow you to specify an ideal (or starting point) size for each shape, as well as for each shape's font size and margin values. Rules allow you to specify how these constraint values can be altered within a range, if more space is needed for additional shapes or text.

For example, in a linear flow of rectangles, the desired shape size may be 2 inches wide by 1 inch high, with a text font size of 65 points. However, if you add 10 shapes to a standard page, each with a paragraph of text, nothing will fit. You could scale everything proportionally, but this may not provide the look you want. As one alternative, you can add rules that allow the shape height to change up to a value of 5 inches, and font size to shrink to 10 points, but no smaller. These constraints and rules would use the following XML:

<constrLst>
    <constr type="w" val="50" />
    <constr type="h" val="25" />
    <constr type="primFontSz" val="65" />
</constrLst>
<ruleLst>
    <rule type="h" val="125" />
    <rule type="primFontSz" val="10" />
</ruleLst>

When creating rules and constraints, values are specified in millimeters and font sizes are specified in points. Rules are applied sequentially, so in the XML just shown, shapes would first grow up to 125 millimeters, and then the font size would shrink. The rule values are not absolute, meaning that if the text fits at 14 points, the font size will stop shrinking.

Constraints and rules can also be specified as reference values. For example, if you prefer that the height of the rectangles start as half of their width and then grow up to two times their width, the XML would look like this:

<constrLst>
    <constr type="w" val="50" />
    <constr type="h" refType="w" fact="0.5" />
    <constr type="primFontSz" val="65" />
</constrLst>
<ruleLst>
    <rule type="h" fact="2" />
    <rule type="primFontSz" val="10" />
</ruleLst>

Once you've added the constraints and rules, the layout definition file XML is complete. Now let's look at the constraints and rules in terms of the example layout.

Diagram Layout Node Constraints First, you need to determine where to place the various constraints and rules. These can be specified on either the parent layout node or the layout node itself. The location depends on several factors.

  • Convenience-storing the font size information for all layout nodes in one location makes it easier to change them at a later point.
  • Reference-when a constraint or rule refers to another constraint or rule, both generally need to be defined in the same location.
  • Algorithm-some algorithms require constraints to be in specific places. For example, with the composite algorithm, the size and position of the child layout nodes must be specified at the level of the composite layout node.

In the sample layout, the composite layout node's width and height should be as big as the layout area. The root layout node always inherits the canvas dimensions by default, so the first constraints in the list should set the composite node width and height equal to the width and height of the root layout node.

Next, the space between the composite nodes should scale with the graphic so that as more composite nodes are added, the space doesn't take over the graphic. To accomplish this, the space width is set to be 10 percent of the composite node width.

Finally, the font size for all layout nodes is set to 65 points and includes an equality value to ensure that they remain the same size across the graphic. The code in Figure 9 shows the completed XML with the new elements.

Figure 9 Diagram Layout Node with Constraints

<layoutNode name="diagram">
    <alg type="lin" />
    <presOf />
    <shape />
    <constrLst>
        <constr type="w" for="ch" forName="composite" 
                refType="w" fact="1" />
        <constr type="h" for="ch" forName="composite" 
                refType="h" fact="1" />
        <constr type="w" for="ch" forName="space" 
                refType="w" refFor="ch" refForName="composite" 
                fact=".1" />
        <constr op="equ" type="primFontSz" for="des" 
                ptType="node" val="65" />
    </constrLst>
    <ruleLst />
    <forEach axis="ch" ptType="node">
        ...
    </forEach>
</layoutNode>

Composite Layout Node Constraints The composite algorithm is unique among the SmartArt algorithms in that it doesn't actually control the size and position of the shapes. Instead, the size and position values are specified as constraints, and the composite algorithm uses these values to lay out the shapes. For this reason, any layout node that is positioned by the composite algorithm needs to have its constraints defined in the constraint block of the composite layout node.

When specifying the size and position for shapes, you need to determine the values along both the horizontal axis and the vertical axis. Both start in the upper-left corner of the layout area, with a value of 0. These constraint values are often expressed as a percentage of the composite layout node's width and height.

Along the horizontal axis, the composite algorithm determines the left, center, and right positions, as well as the overall width. Similarly, along the vertical axis, the composite algorithm determines the top, middle, and bottom positions, and the overall height. Any two of these values along either axis must be specified; the rest can then be calculated.

One other consideration when specifying composite constraints is that the constraints must be specified in the same order as the nested layout nodes. Stacking order of shapes is also determined, by default, by the order of the layout nodes, though you can specify stacking order overrides if necessary to achieve the correct look. The constraints for the example graphic layout are shown in Figure 10.

Figure 10 Composite Layout Node Constraints

<layoutNode name="composite">
    <alg type="composite" />
    <presOf />
    <shape />
    <constrLst>
        <!--constraints for roundRect -->
        <constr type="w" for="ch" forName="roundRect" 
                refType="w" fact="1" />
        <constr type="h" for="ch" forName="roundRect" 
                refType="h" fact="1" />
        <constr type="l" for="ch" forName="roundRect" val="0" />
        <constr type="t" for="ch" forName="roundRect" val="0" />

        <!--constraints for parentText -->
        <constr type="w" for="ch" forName="parentText" 
                refType="w" fact="1" />
        <constr type="h" for="ch" forName="parentText" 
                refType="h" fact=".175" />
        <constr type="l" for="ch" forName="parentText" val="0" />
        <constr type="t" for="ch" forName="parentText" val="0" />

        <!--constraints for whiteRect -->
        <constr type="w" for="ch" forName="whiteRect" 
                refType="w" fact="1" />
        <constr type="h" for="ch" forName="whiteRect" 
                refType="h" fact=".025" />
        <constr type="l" for="ch" forName="whiteRect" val="0" />
        <constr type="t" for="ch" forName="whiteRect" 
                refType="h" fact=".175" />

        <!--constraints for childText -->
        <constr type="w" for="ch" forName="childText" 
                refType="w" fact="1" />
        <constr type="h" for="ch" forName="childText" 
                refType="h" fact=".8" />
        <constr type="l" for="ch" forName="childText" val="0" />
        <constr type="t" for="ch" forName="childText" 
                refType="h" fact=".2" />
    </constrLst>
    <ruleLst />
    <layoutNode name="roundRect" styleLbl="node1" >
        ...
    </layoutNode>
    <layoutNode name="parentText" styleLbl="node1" >
        ...
    </layoutNode>
    <layoutNode name="whiteRect" styleLbl="fgAcc1" >
        ...
    </layoutNode>
    <layoutNode name="childText" styleLbl="node1" >
        ...
    </layoutNode>
</layoutNode>

Constraints on roundRect and whiteRect Layout Nodes The roundRect and whiteRect shapes do not contain text and do not have specific resizing behavior. Their width, height, and positions are specified in the composite node's constraint block, so no additional constraints or rules are needed. The empty constraint and rule list element tags are included here for completeness, but these are optional (see Figure 11).

Constraints on parentText and childText Layout Nodes The height, width, and position of the parentText shape are specified in the composite node's constraints, so the only additional constraints and rules for this layout node are those concerning text properties. For most text in SmartArt shapes, the font size is controlled by the primary font size (primFontSz) constraint. In our example, this constraint is specified at the root layout node to start at a value of 65 points.

For most graphics, 65 points will be too large. So you can add a rule that allows the font size to shrink to a minimum of 5 points:

<layoutNode name="parentText" styleLbl="node1" >
    <alg type="tx" />
    <presOf axis="self" />
    <shape type="rect" hideGeom="true" />
    <constrLst />
    <ruleLst>
        <rule type="primFontSz" val="5" />
    </ruleLst>
</layoutNode>

If the text still doesn't fit at 5 points, it will extend beyond outside of the shape.

The childText layout node also has constraints and rules related to font sizing. In addition, to get the text to align properly, text parameters are needed as elements nested inside the algorithm element, as shown in Figure 12.

Figure 12 Text Parameters Inside the Algorithm Element

<layoutNode name="childText" styleLbl="node1" >
    <alg type="tx">
        <param type="stBulletLvl" val="1" />
        <param type="parTxLTRAlign" val="l" />
        <param type="parTxRTLAlign" val="r" />
        <param type="txAnchorVert" val="t" />
    </alg>
    <presOf axis="des" ptType="node" />
    <shape type="rect" hideGeom="true" />
    <constrLst>
        <constr type="secFontSz" refType="primFontSz" />
    </constrLst>
    <ruleLst>
        <rule type="primFontSz" val="5" />
    </ruleLst>
</layoutNode>

In this layout node, the graphic displays a bulleted list of text, instead of a single text item. We want the bullets to start with the first level of text that displays in this layout node, but the default behavior is to start bullets at the second level inside a shape. The stBulletLvl (start bullet level) parameter controls this behavior. For the graphic here, the value should be 1 instead of the default value of 2. Note that these are the only two values supported for this parameter.

Because this text is a bulleted list, it should be left aligned and top aligned. For the first level of text within a shape, the default is to center the text vertically and horizontally, so these behaviors are changed using the parameters parTxLTRAlign (parent text LTR align) and txAnchorVert (text anchor vertical), setting them to l (left) and t (top), respectively.

Of course, if this graphic is used with language settings that display text from right to left, the text should align to the right. There are two parent text alignment parameters that determine the value to use according to system settings. So for this graphic, you should also include parTxRTLAlign (parent text right-to-left align) and set this value to r (right).

All shapes also support a secondary font size (secFontSz). These values correspond to where bullets begin in a shape. If a line has a bullet, it uses the secondary font size. If it doesn't have a bullet, it uses the primary font size. By default, the secondary font size is 78 percent of the primary font size.

Each shape also has margin values, and these values are, by default, proportional to the primary font size. If a shape only has secondary text in it, it makes more sense to have the margins reference the secondary font size. For the sample graphic, it's not necessary to have the secondary text smaller than the primary text, so you simply set the two values equal, which also ensures that the margins pick up the appropriate values.

Space Layout Node Constraints The space algorithm is used either as a placeholder to indicate that no sizing is needed or to preserve some minimum amount of space between other layout nodes. For this layout node, there should be a horizontal space between the composite shapes; therefore, you set a width constraint for the layout node. However, this value was defined on the diagram layout node, so the constraint and rule lists are empty for the actual space layout node as they are for the layout nodes shown in Figure 11. Now let's delve into packaging the layout file.

Figure 11 Empty Constraint and Rule List Element

<layoutNode name="roundRect" styleLbl="node1" >
    <alg type="sp" />
    <presOf axis="self" />
    <shape type="roundRect">
        <adjLst>
            <adj idx="1" val="0.1" />
        </adjLst>
    </shape>
    <constrLst />
    <ruleLst />
</layoutNode>

<layoutNode name="whiteRect" styleLbl="fgAcc1" >
    <alg type="sp" />
    <presOf />
    <shape type="rect" />
    <constrLst />
    <ruleLst />
</layoutNode>

Packaging the Layout Definition File

The XML I've discussed is part of an overall Open Document package. This is essentially a compressed ZIP file with the extension .glox and the following folder and file structure:

  • _rels
  • .rels
  • diagrams
  • layout1.xml
  • layout1header.xml
  • [Content_Types].xml

Let's take a closer look at what all these files and folders are.

The rels Folder and File The .rels file defines the relationships between the parts in the .glox file format. It is a text file that contains the following XML:

<?xml version="1.0" encoding="utf-8"?>
<Relationships xmlns=
        "https://schemas.openxmlformats.org/package/2006/relationships">
    <Relationship 
        Type="https://schemas.openxmlformats.org/officeDocument/2006/
             relationships/diagramLayoutHeader" 
        Target="/diagrams/layoutHeader1.xml" Id="rId1" />
    <Relationship 
        Type="https://schemas.openxmlformats.org/officeDocument/2006/
             relationships/diagramLayout" 
        Target="/diagrams/layout1.xml" Id="rId2" />
</Relationships>

The Diagrams Folder and Layout Definition Parts The diagrams folder contains the two XML layout definition files that comprise the SmartArt graphic layout. Layout1.xml is the main definition file, and contains the XML described in this article, which documents the layout and mapping for the graphic.

Layout1header.xml contains the header information for the layout definition, including the unique ID, title, and description:

<?xml version="1.0" encoding="utf-8"?>
<layoutDefHdr uniqueId="msdn/sampleGraphicLayout"
      xmlns="https://schemas.openxmlformats.org/drawingml/2006/diagram">
    <title val="MSDN Sample Graphic Layout" />
    <desc val=" " />
    <catLst>
        <cat type="list" pri="500" />
    </catLst>
</layoutDefHdr>

Each graphic layout requires a uniqueID. If another layout definition has the same uniqueID, the file will not load.

The title and description appear in the user interface. You can use this area to provide specific information about when and how to use the graphic layout.

The category and priority information determine where in the SmartArt layout gallery the graphic layout appears. SmartArt graphics supports the following category types: list, process, cycle, relationship, pyramid, matrix, and other. The built-in layout files begin with priority 1000 in each category and increment by 1000. You can use any positive integer as a priority.

The [Content_Types].xml File The content types file sets up the structure and namespace area for the entire package. It should be placed at the root level and contain the following XML:

<?xml version="1.0" encoding="utf-8"?>
<Types xmlns="https://schemas.openxmlformats.org/package/2006/
              content-types">
    <Default Extension="xml" ContentType="application/
        vnd.openxmlformats-officedocument.drawingml.
        diagramLayoutHeader+xml" />
    <Default Extension="rels" ContentType="application/
        vnd.openxmlformats-package.relationships+xml" />
    <Override PartName="/diagrams/layout1.xml" 
        ContentType="application/vnd.openxmlformats-
            officedocument.drawingml.diagramLayout+xml" />
</Types> 

Testing the Graphic Layout

Once your layout definition is packaged into a .glox file, it must be placed in the correct directory for it to be included in the SmartArt layout gallery. By default, SmartArt graphic layout files are stored in the local settings template directory, at the following location: %APPDATA%\Microsoft\templates\SmartArt Graphics.

You can also set a registry key to change the templates directory to another location. But keep in mind that the registry key applies to all Office templates, including the location of the normal.dotx file in Word. This registry key is stored under HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Common\General as UserTemplates as a string. As the value, specify a new path for the general templates folder and the SmartArt graphic feature will then look for a SmartArt graphics folder under the specified path.

After you've placed the graphic layout file in the templates directory, launch an application that supports SmartArt graphics and click the Insert SmartArt button. If there are no immediate errors, the graphic layout you created will be shown in the gallery under the category you specified.

If, by chance, you need to correct any errors in any of the XML files, you'll need to restart the Office application session for the modified XML file to be reloaded into the gallery.

Error Types and the Error Log

SmartArt graphics provide an XML log file that tracks errors and warnings associated with the layout definition files. You can use the log file to help determine what needs to be fixed in your graphic layout. Errors with layout files generally fall into three categories: non-unique uniqueID values, XML or schema errors, and layout validation errors.

When a uniqueID isn't actually unique, one of the layout files with the duplicate uniqueID will fail to load and an error message will display when the SmartArt layout gallery is opened. If this happens, an entry similar to the following will be added to the log file:

<entry>
    <time>2006-10-20T15:51:14.650</time>
    <sev>err</sev>
    <host>POWERPNT.EXE</host>
    <file>example.glox</file>
    <type>nonUniqueId</type>
    <desc>A user-defined or built-in definition with this 
          uniqueId was already loaded.</desc>
    <context>example</context>
</entry>

XML formatting or schema validation errors also prevent the layout definition from loading properly. If the error occurs in the layoutHeader1.xml file, no part of the file will load. However, if the error occurs in the layout1.xml file, the file will load, but a red X will be displayed in the gallery. And if you attempt to select this layout from the gallery, an error message will be displayed. The following log entry shows a typical XML formatting error:

<entry>
    <time>2006-10-20T15:53:39.619</time>
    <sev>err</sev>
    <host>POWERPNT.EXE</host>
    <file>example.glox</file>
    <type>xmlError</type>
    <desc>No error detail available</desc>
    <context></context>
    <line>58</line>
    <col>35</col>
</entry>

The most valuable piece of this error is the indication of the line and column where the error occurs.

Layout validation errors behave like XML errors, but they only occur when the SmartArt graphic attempts to run the layout. The following log entry shows an error that occurs when two layout nodes have the same name attribute:

<entry>
    <time>2006-10-20T15:59:25.650</time>
    <sev>err</sev>
    <host>POWERPNT.EXE</host>
    <file>example.glox</file>
    <type>invalidName</type>
    <desc>The name attribute must be unique.</desc>
    <context>&lt;layoutNode name='sibTrans'/&gt;</context>
    <line>131</line>
    <col>17</col>
</entry>

SmartArt graphics reference three registry keys (which are stored under HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Common\SmartArt Graphics) for controlling the log file: LogFileSeverityLevel, LogFileMaxSize, and LogFileNumEntriesToRemove.

LogFileSeverityLevel is a DWORD that sets the severity level of errors or warnings to report. 0 reports only errors, while levels 1 through 4 report different levels of warnings, with 1 being the most severe. LogFileMaxSize is a DWORD that sets the maximum number of bytes that can be stored in the log file. If this value is reached, a set of entries is removed from the log to provide additional space. And LogFileNumEntriesToRemove is a DWORD that specifies the number of entries to remove when the maximum log file size is exceeded.

Valid File with Design Errors

Once the graphic layout file loads successfully, you need to check for design errors. Some common errors are:

  • Text that appears in wrong shape.
  • Text that doesn't appear at all.
  • Shape size or font size that's not consistent across shapes.
  • Shapes that aren't positioned properly.
  • Graphics that don't react as you would expect when shapes are added.

Correcting these problems is really a matter of trial and error. As you gain more experience with creating definition files, you'll find the errors easier to identify and correct.

When testing your graphic layout, you should check the way it looks with various SmartArt graphic styles and colors and across different themes, to make sure it looks good in most scenarios. But keep in mind that not every graphic will look good with every style and color.

Modifying Existing Graphic Layout Definitions

Creating a graphic layout from scratch provides a good way to understand the structure and syntax for SmartArt graphic layout files. However, you may simply want to modify an existing graphic layout to get the look you want.

When you add a SmartArt graphic to a document and save it, a copy of the graphic layout file is stored with the other parts of the document as well. If you look inside the package and navigate to the diagrams directory, you can find layout and layout header XML files corresponding to each SmartArt graphic layout in the document. You can remove this file from the package, rename it layout1.xml, modify the appropriate sections, and then place the file into a new .glox.

If you're modifying an existing file, you may notice additional tags and attributes not discussed in this article or perhaps that other tags and attributes are missing. In general, the new attributes are optional or are attributes for which I've assumed default values. The missing attributes are those that use default values.

What's Next?

I've covered the basics of SmartArt graphic layout extensibility, but I've barely touched upon the many complexities of creating SmartArt graphic layout files. If you want to explore further, I'd recommend starting with the schema and looking through existing graphic layout definitions to see what's possible.n

Janet Schorr has been a program manager at Microsoft for six years and is currently a lead program manager on the Office Publisher team. She has been on a variety of product teams and recently worked with the Office Graphics team on the SmartArt layout architecture.