Skip to content

UML Activity Diagram

To create a UML activity diagram, one uses the activityDiagram diagram function:

HyLiMo
activityDiagram {
    // define elements
}

Every node of an activity diagram is a regular element, positioned like a class in a class diagram, and every flow is a regular connection. There is no separate control flow syntax: what you write is what is placed on the canvas, so nodes can be moved and connections rerouted in the graphical editor just like in the other diagram types. All elements described below are also available in the general UML diagram.

Elements

In contrast to classifiers like classes and components, activity nodes have no compartments: each node is a single shape with its label centered inside. All nodes share the activity-node-element class and additionally carry a class named after their type, e.g. action-element or decision-element, while the shape inside a node carries the activity-node class and its type name.

Nodes which render a text register themselves in the diagram scope under that text, exactly like a class does:

Nodes which render no text at all - start, stop, end, fork and join - instead take an optional name as their first argument, which is only used to register them:

The nodes which have no content of their own get their default size from a style variable. Each of them can be resized individually, either by dragging it in the graphical editor or by setting width and height in its layout block:

action

Creates an action, the rounded rectangle which is the primary node of an activity diagram:

Keywords

The keywords named argument adds keywords or stereotypes in guillemets (« and ») above the name:

Pins

Actions can have pins, the small squares representing their input and output parameters. A pin is placed completely outside of the outline of the action, at a relative position on it: 0 is the right, 0.25 the bottom, 0.5 the left and 0.75 the top of the node.

Pins can be defined inside the action block, or using dot notation outside of it:

If a name is provided, it is rendered as a label next to the pin, and the pin is registered in the diagram scope under that name, so a flow can be connected directly to it. The position of the label can be adjusted with the namePos named argument, which takes the x and y offset relative to its default position:

object

Creates an object node, a rectangle holding the name of the object which flows between two actions:

The optional state named argument adds the state of the object in brackets, and keywords works just like for actions, which is how data stores and central buffers are expressed:

signalObject

Creates a signal object node: an object node for tokens whose type is a signal. It takes the same arguments as object, but is rendered with a point on the right and a matching notch on the left, so it interlocks with the signal nodes it sits between:

decision and merge

Both are rendered as a diamond. If a text is given, it is rendered inside the diamond, otherwise the plain diamond is drawn:

The guards of the outgoing flows of a decision node are usually written as labels on the connections, see Guards.

fork and join

Both are rendered as a filled bar, fork splitting one flow into several concurrent ones, and join synchronizing them again. By default the bar is horizontal, meaning it splits a flow running from top to bottom. With the vertical named argument, the bar is rotated for a flow running from left to right:

start, stop and end

The nodes at which a flow begins and terminates:

  • start is the initial node, the filled circle a flow starts at
  • stop is the activity final node, which terminates the whole activity
  • end is the flow final node, which terminates only the flow reaching it

sendSignal and acceptEvent

The signal nodes: sendSignal is drawn with a point on the right, acceptEvent with a matching notch on the left, so that a send/accept pair interlocks:

The signal travelling between such a pair is an object node carrying both the point and the notch.

connector

Creates a connector, a small circle holding a label. Connectors are used in pairs to split a long flow into multiple parts: the flow entering the first one continues at the second one carrying the same label.

comment

Comments work just like in class diagrams:

Connections / Flows

Control flows and object flows are created with the same operator syntax as the associations of a class diagram, using --> for a flow:

All connection operators are available, so ..> can for example be used for a dependency to a comment.

Guards

A guard is a regular connection label, created with the label function of the with operator, which takes the text, the relative position on the connection and the distance to it:

Flow direction

By default a connection starts at the right (0) of its source and ends at the left (0.5) of its target, which fits an activity flowing from left to right. For the more common top to bottom flow, route the connection from the bottom (0.25) of the source to the top (0.75) of the target:

To route around other nodes, use axisAligned instead of line, where a negative position starts the segment horizontally and a positive one vertically:

The two flows leave the bar at different points instead of both starting in its middle. On a bar, 0.25 is the middle of its bottom edge and 0.75 the middle of its top edge, and 0.125 more or less walks from there all the way to a corner, so 0.2 and 0.3 are 40% of the way to the right and to the left end.

Swimlanes

Activity partitions, better known as swimlanes, divide a diagram into lanes, each holding what one participant is responsible for. They are created with the swimlanes function, and the lanes inside it with lane:

Every lane is a canvas of its own, but all lanes share one coordinate system along the direction the flow runs in: a position means the same place in every lane, and a lane holding less than the others still spans the whole diagram. Both actions above are placed at the same position within their lane and line up accordingly, even though the first lane also contains the start node. Across the flow a lane sizes itself to its content, so lanes grow as nodes are added to them.

Lanes appear in the order they are declared, and cannot be nested. A node belongs to the lane it is written in: dragging it past a border in the graphical editor moves it visually, but does not move it into the other lane.

Orientation

By default lanes are rows: they are stacked from top to bottom, the flow runs from left to right, and the lane names are turned to read from bottom to top. The orientation named argument switches to columns, where the lanes are placed side by side, the flow runs from top to bottom, and the names are upright above their lane:

The default for a whole diagram can be changed with the swimlanesOrientation config property.

Flows between lanes

A flow is placed on the nearest canvas containing both of its ends, so one that crosses a lane border can be written inside a lane just as well as next to the lanes, whichever reads better. Flows crossing a border are usually routed from one side of a node to the other, as described under flow direction:

Nodes on a lane border

A lane exposes the separator drawn after it as separator. A separator is a connection, so it can be used as the target of lpos, which is how a node belonging to two lanes is placed on the border between them. An object handed from one partition to the next is the usual case:

The node is centered on the separator, and 0.5 places it halfway along it. A fork or join bar belonging to two lanes is placed the same way, though its length is not derived from the lanes it covers: set width or height in its layout block to size it.

Nodes on a border are written next to the lanes rather than inside one, which is also where they belong: they are part of no single lane.

Config properties

The following config properties are available for activity diagrams:

VariableMeaningDefault value
swimlanesOrientationWhether lanes default to "rows", with the flow running left to right, or "columns", with the flow running top to bottom"rows"

Styling

The following style variables are used by the activity diagram elements:

VariableMeaningDefault value (in pixels)
barLengthLength of a fork / join bar200
barThicknessThickness of a fork / join bar10
terminalNodeSizeDiameter of the start, stop and end nodes30
pinSizeEdge length of a pin20
pinLabelDistanceDistance of a pin label to the pin8

Example

The following example shows the handling of an order, using most of the elements described above: