This post examines the programmability features for Containers, Lists and Callouts in Visio 2010. It supplements an earlier post that describes how these special shapes are constructed and how they can be customized. Collectively these shapes are known as Structured Diagram elements, and the part of the Visio API that manages these elements is known as the Structured Diagram API. This API enables developers to use Structured Diagram elements in their solutions. Developers can identify the relationships between these elements and other shapes, they can add or change the relationships with other shapes, and they can detect when the user makes changes to the relationships with other shapes.
Structured Diagram API Overview
Here are the key objects, properties and methods in the Structured Diagrams API:
There are two new objects in the API. ContainerProperties is an extension of the Shape object. It encapsulates the special properties and behaviors of containers and lists. RelatedShapePairEvent is an object used with the Structured Diagram API events, where Visio can describe a relationship being formed or broken between two shapes. The remaining parts of the API are additions to existing Visio objects.
Note that lists are just another type of container as far as the API is concerned. Therefore, lists use all the same objects, properties and methods as containers; and lists have a few additional properties and methods as well (those with “List” in their name).
Enabling Structured Diagram Behaviors in Solutions
Visio 2010 introduces a new feature called Diagram Services that manages what diagramming behaviors are enabled in the document. There are diagram services that control the behavior of Auto Size Page and diagram services that control the behaviors of Containers, Lists and Callouts. These services are turned on and off at the document level. When a service is off, changes made in the diagram through automation will not trigger the diagramming behaviors related to that service. (Changes made through the user interface are not subject to the diagram service state.)
For example, the Auto Size Page feature will normally grow the page size if a shape is placed outside the page boundary. However, when a shape is placed outside the page via automation, the Auto Size Page feature will only respond if the Auto Size Page diagram service is enabled. Similarly, dropping a shape on top of a container will normally make it a member of the container and cause the container to resize to fit it. However, when the shape is dropped via automation, the Containers feature will only respond if the Structured Diagram service is enabled.
The reason Visio 2010 includes this capability is that solutions may not always want these diagramming behaviors to get triggered while they are manipulating shapes in the diagram. This may especially be true for existing solutions that have no knowledge of the new Visio 2010 behaviors and have expectations that shapes respond in ways consistent with Visio 2007. In order for existing solutions to work as originally designed, all diagram services in Visio 2010 are disabled by default. Solutions must opt the document in to the new diagramming behaviors. Note that diagram service states apply to automation properties and methods that existed in Visio 2007. When a new Visio 2010 automation method is explicitly invoked by a solution - such as any of the examples below – the service state is ignored. The presumption is that the solution wants the Visio 2010 behavior associated with that method.
Diagram service states are checked or changed using the Document.DiagramServicesEnabled property. The value of this property is a mask of all the services currently enabled. Available services and values are listed in the table below. It is possible for a solution to opt into just one service, all the services supported in Visio 2010, or even all existing and future services.
VisDiagramServices values:
Enum | Value | Description |
visServiceAll | -1 | All diagram services |
visServiceVersion140 | 7 | Diagram services that exist in Visio 2010 |
visServiceNone | 0 | No diagram services (default) |
visServiceAutoSizePage | 1 | AutoSize page behaviors |
visServiceStructureBasic | 2 | Behaviors that maintain existing Structured Diagram relationships but do not create new relationships |
visServiceStructureFull | 4 | Structured Diagram behaviors that match the behaviors in the user interface |
There are two services for Structured Diagram behaviors. The StructureBasic service maintains relationships but will not form new ones. This might be appropriate for a solution that wants to respect the user’s usage of Containers, Lists and Callouts but does not want the solution itself to inadvertently form relationships when shapes are moved around the page. The StructureFull service maintains relationships and will form new relationships as well. This matches the behaviors that are triggered in the user interface. If both services are enabled, then Visio uses the StructureFull set of behaviors.
Common Tasks with the Structured Diagram API
Let’s look at some typical Structured Diagram tasks to explore the API in greater detail. For a complete list of the special flags that can be passed into the methods, look at the Object Browser within the VBA editor in Visio.
Add a container to the page
Containers can be added to a page by calling the traditional Page.Drop method, which will add the shape at coordinates you specify without affecting the membership of existing shapes on the page. However, there is a new Page method – Page.DropContainer - that will not only drop the container but will also size it around a set of shapes and make those shapes members of the container. This is the behavior in the UI when using Insert > Container when a selection exists. DropContainer needs an object for the container shape. If you want to use one of the shapes in the Insert Container gallery, you can use the GetBuiltInStencilFile method to retrieve the hidden stencil where these containers are stored.
Dim vsoDoc1 As Visio.Document
Set vsoDoc1 = Application.Documents.OpenEx(Application.GetBuiltInStencilFile(visBuiltInStencilContainers, visMSUS), visOpenHidden)
Application.ActivePage.DropContainer vsoDoc1.Masters.ItemU("Container 1"), Application.ActiveWindow.Selection
vsoDoc1.Close
Add a shape to a container
Shapes are added to a container by moving or dropping them onto the container (if the StructureFull diagram service is enabled). Shapes can be explicitly added to a container using the AddMember method. This is useful when the shape already overlaps the container and is not yet a member. It is also helpful if you want to force the container to expand to encompass the new member.
vsoContainerShape.ContainerProperties.AddMember vsoShape, visMemberAddExpandContainer
Find the containers on a page
To discover what containers exist in a document, Visio provides a direct way to get the set of containers in a selection or on a page. The GetContainers method returns an array of Shape IDs for the containers. Containers nested within other containers can be included or excluded using flags.
For Each containerID In vsoPage.GetContainers(visContainerIncludeNested)
Set vsoContainerShape = vsoPage.Shapes.ItemFromID(containerID)
'...
Next
Get the shapes in a container
Solutions can identify the members of a container using the GetMemberShapes method, which returns an array of Shape IDs for the member shapes. The flags allow certain kinds of member shapes to be filtered out of the array returned.
For Each memberID In vsoContainerShape.ContainerProperties.GetMemberShapes(visContainerFlagsDefault)
Set vsoShape = vsoPage.Shapes.ItemFromID(memberID)
'...
Next
Reorder a list
Every member of a list is placed in a specific position, and that ordinal value can be retrieved with the ContainerProperties.GetListMemberPosition method. To reorder a member, you can call the ContainerProperties.ReorderListMember method. Both methods use 1 to indicate the first position in the list.
vsoListShape.ContainerProperties.ReorderListMember vsoShape, 2
Add a callout to the page
Callouts can be added to a page by calling the traditional Page.Drop method, which will add the shape at coordinates you specify. However, there is a new Page method – Page.DropCallout - that will not only drop the callout but will associate it with a target shape and position it near the target shape. This is the behavior in the UI when using Insert > Callout when a selection exists. As with DropContainer, DropCallout needs an object for the callout shape. If you want to use one of the shapes in the Insert Callout gallery, you can use the GetBuiltInStencilFile method to retrieve the hidden stencil where these containers are stored.
Dim vsoDoc1 As Visio.Document
Set vsoDoc1 = Application.Documents.OpenEx(Application.GetBuiltInStencilFile(visBuiltInStencilCallouts, visMSUS), visOpenHidden)
Application.ActivePage.DropCallout vsoDoc1.Masters.ItemU("Callout 1"), vsoTargetShape
vsoDoc1.Close
Get the target shape for a callout
A shape can have multiple callouts, but a callout can have only one target shape at a time. The Shape.CalloutsAssociated property returns an array of callout shape IDs. You can get or set the target shape of a callout using the Shape.CalloutTarget property.
Set vsoShape = vsoCalloutShape.CalloutTarget
Structured Diagram Events
In addition to manipulating the containers, lists and callouts in a document, you can also respond to user actions that relate to these shapes. Containers, lists and callouts work by establishing relationships with other shapes. Visio fires an event whenever one of these relationships is formed or broken. For example, adding a shape to a container forms a new relationship between the shape and the container.
When a relationship event fires, Visio specifies the details in a RelatedShapePairEvent object. The FromShapeID property of this object indicates the container, list or callout involved in the relationship. The ToShapeID property indicates the other shape involved in the relationship. Thus when adding a shape to a container, the ToShapeID would refer to the new member shape, and when associating a callout with a target shape, the ToShapeID would refer to the target shape.
The following events are available for Application, Documents, Pages and Page event lists:
ContainerRelationshipAdded
ContainerRelationshipDeleted
CalloutRelationshipAdded
CalloutRelationshipDeleted
Also the ShapeChanged event will now fire when members of a list shape are reordered. The event passes the list shape as an argument and includes the string “/ListReorder” in the EventInfo argument.
Feedback
The Structured Diagrams feature set – Containers, Lists and Callouts – offers both end users and developers significant new diagramming capabilities in Visio 2010. We’re interested to hear what developers think of this API functionality, so please use the Send a Smile feedback tool or leave a comment below.