7. Add a custom review node
Now give our flowchart a reusable review node with left and right ports. Add this top-level definition below the app classes:
dart
ShapeDefinition reviewNode() => ShapeDefinition(
type: 'tutorial.review',
outline: const ShapeOutlineDefinition.rectangle(),
textBounds: const ShapeBoundsDefinition.inset(16),
minimumSize: const DiagramSize(140, 80),
defaultSize: const DiagramSize(220, 120),
defaultStyle: const ShapeStyle(cornerRadius: 12),
capabilities: ShapeCapabilities(
rotatable: false,
cornerRadiusEditable: true,
textSizing: ShapeTextSizing.growHeight,
),
connection: ShapeConnectionDefinition.fixedPorts([
PortDefinition.onSide(id: 'input', side: PortSide.left),
PortDefinition.onSide(id: 'output', side: PortSide.right),
]),
);Replace the session initializer:
dart
late final session = DrawingSession(
shapeRegistry: ShapeRegistry.withStandard([reviewNode()]),
);In both the initial process creation and addProcess, replace Shapes.rectangle with 'tutorial.review'. Hot restart because the session is created once. Existing saved rectangles do not automatically become the new type.
Before restarting, also replace the two connection calls in initState. A ports-only review node requires an explicit port ID on its endpoint:
dart
session.connect(startId, processId, targetPortId: 'input');
session.connect(processId, decisionId, sourcePortId: 'output');The other endpoints still bind to the standard shapes' outlines. Omitting a review port is invalid; the SDK does not silently choose an outline attachment for a ports-only shape.
The definition owns shape geometry and behavior. The instance owns its ID, position and text. Shared code handles text editing, hit testing, movement, port placement, routing, saving and history. You do not implement a second painter/drag pipeline.
Capabilities, locks and host permissions
| Mechanism | Question it answers | Example |
|---|---|---|
| Definition capabilities | What edits does this type support? | Review nodes cannot rotate. |
| Instance locks | Is this object currently locked? | A finalized node cannot move. |
| Host admission | Is this candidate edit permitted now? | The current user has read-only access. |
Unlocking a node does not grant a capability its definition lacks. All three can affect the decision returned by an edit. This is why handling allowed belongs in custom controls too.
Add a DrawingHooks.beforeChange callback in configuration when you need host-wide admission; return DiagramPolicyDecision.deny('This drawing is read-only.') or allow(). It is synchronous and read-only. Server authorization remains your backend's responsibility. Fixed domain invariants belong in documentValidator; see hooks.
Checkpoint: add a review node, edit its text, connect through its ports and save/load it. It has no rotation interaction. For richer compositions and native controls, continue later with Build a library.