Skip to content

7. Layer 4 — Toolbox, context tools and forms

Contents of DISL 0.1

This layer defines how users create and edit elements: the palette (toolbox), tools that appear next to a selection, reusable templates, and forms — both property inspectors and widgets embedded directly in nodes.

7.1 Toolbox

{
  "toolbox": {
    "layout": "list",
    "searchable": true,
    "showRecent": 5,
    "groups": [
      { "id": "states", "label": "States", "icon": "square-rounded",
        "doc": "Elements that describe where the system can be.",
        "tools": [
          { "id": "state",   "creates": "State",        "shortcut": "S" },
          { "id": "initial", "creates": "InitialState", "shortcut": "I" },
          { "id": "final",   "creates": "FinalState" }
        ] },
      { "id": "connections", "label": "Connections",
        "tools": [ { "id": "transition", "creates": "Transition", "mode": "drag", "shortcut": "T" } ] }
    ]
  }
}
Property Type Description
groups ToolGroup[] Ordered groups.
tools map → Tool Library of tools referenced from groups by id (a group entry may be a string id).
layout "list", "grid", "icons", "compact" Presentation. Default "list".
position "left", "right", "top", "floating" Suggested placement; runtimes MAY ignore it.
searchable bool Offer a search box (matches labels, doc.summary, doc.tags). Default true.
showRecent int Show a group with the n most recently used tools.
generic {select, pan, lasso, text, note, image, freehand} of bool Which generic tools are offered. Defaults: select and pan true, others false.
doc Doc

If toolbox is absent, the runtime generates one group per 10 concrete types, alphabetically, with one creation tool per concrete node and relation type.

ToolGroup: id, label, doc, icon, collapsed (bool), visible (Expression in the diagram context), viewpoints (string[]), tools (Tool or tool id)[], and nested groups for sub-groups.

7.2 Tools

Property Type Description
id identifier Required.
kind ToolKind Default: "create-node" or "create-edge" depending on creates; otherwise required.
label, doc, icon Default: from the created type. doc.summary is the tooltip.
creates TypeRef Type to create.
initial map attribute → value or {cel} Initial attribute values, overriding metamodel defaults. CEL values use the create context (12.3).
size Size Initial size overriding the notation default.
variantOf tool id Presents this tool as a variant (dropdown) of another.
mode see below Interaction mode.
sticky bool Tool stays active after use until Escape. Default false; shift-click MAY toggle.
shortcut string Keyboard shortcut ("S", "Ctrl+Shift+E"). Conflicts are a validator warning.
enabled, visible Expression Context diagram.
preview {style, shape} Ghost appearance while placing.
after "select", "editLabel", "openForm", "none" What happens after creation. Default "editLabel" when the type has an editable label.
template template id For kind: "template".
operation operation id For kind: "operation".
plugin {name, args} For kind: "plugin".

ToolKind: create-node, create-edge, template (inserts a fragment), operation (runs an operation on the selection or diagram), select, pan, lasso, text, note, image, freehand, plugin.

Modes. For node tools: "click" (place at default size), "drag" (drag out the size; default), "stamp" (click repeatedly, implies sticky). For edge tools: "drag" (drag from source to target; default), "click-click" (click source, then target, with intermediate clicks adding bendpoints), "chain" (each click continues from the last target), "auto" (drag between nodes or start from a port). When a node tool is dragged on a coordinate system with bound placement, the dragged extent is written to the bound attributes: dragging across five days of a time axis creates a task with start and end set to those days, dropped into a lane it sets the lane attribute. Edge tools that start on empty canvas may create the source node when createSource: TypeRef is set; ending on empty canvas may create the target when createTarget: TypeRef is set (or offer a context menu of valid targets when createTarget: "ask").

7.3 Context tools

Context tools appear next to the selected element (a "quick bar" or radial menu) and are the fastest way to grow a diagram. They are declared in toolbox.contextTools.

{
  "contextTools": [
    {
      "for": ["State"],
      "placement": "around",
      "tools": [
        { "kind": "create-connected", "creates": "State", "via": "Transition", "direction": "outgoing",
          "label": "Add next state", "icon": "arrow-right", "position": "right" },
        { "kind": "connect", "via": "Transition", "icon": "link", "position": "bottom" },
        { "kind": "operation", "operation": "makeFinal", "icon": "flag", "position": "top-right" },
        { "kind": "delete", "position": "top-right" }
      ]
    }
  ]
}
Property Type Description
for TypeRef[] Element types the context tools apply to.
when Expression Additional condition (element context).
placement "around", "toolbar", "menu", "radial" Presentation.
tools ContextTool[] Items.

ContextTool kinds: create-connected (create a node of type creates connected via relation via, placed at position using the layout's spacing; direction outgoing or incoming), connect (start an edge of type via from this element), create-child (create a child of creates in slot), operation, delete, duplicate, editLabel, openForm, plugin. All kinds accept label, doc, icon, shortcut, enabled, position.

Right-click context menus are defined the same way under toolbox.contextMenus with placement: "menu"; runtimes add standard entries (cut, copy, paste, delete, arrange) unless standardEntries: false.

7.4 Templates

Templates insert pre-built fragments — patterns, starter structures, snippets. They are declared in toolbox.templates:

{
  "templates": {
    "retryLoop": {
      "label": "Retry loop",
      "doc": "A state that retries up to three times before failing.",
      "params": { "attempts": { "type": "int", "default": 3, "label": "Attempts" } },
      "fragment": {
        "nodes": [
          { "ref": "try",  "type": "State", "attributes": { "name": "'Trying'" }, "at": [0, 0] },
          { "ref": "fail", "type": "FinalState", "attributes": { "name": "'Failed'" }, "at": [200, 0] }
        ],
        "relations": [
          { "type": "Transition", "source": "try", "target": "try",  "attributes": { "guard": "'retries < ' + string(p.attempts)" } },
          { "type": "Transition", "source": "try", "target": "fail", "attributes": { "guard": "'retries >= ' + string(p.attempts)" } }
        ]
      },
      "preview": "templates/retry.svg"
    }
  }
}

fragment uses local ref names instead of ids; attribute values are Expressions (strings are CEL) evaluated with template parameters as p. at positions are relative to the insertion point, in the coordinate system of the target container (time values are durations relative to the drop time on time axes). Templates are placed with a kind: "template" tool or dragged from a template gallery. Templates MAY also be offered on the creation of a new diagram (language-level starter templates: toolbox.starters: ["retryLoop", …]).

7.5 Forms

A form is a declarative description of editable fields for one element type. Forms are used as property inspectors (side panel or popover), as creation dialogs, and — embedded — inside nodes on the canvas.

If no form is defined for a type, runtimes generate one: one field per non-derived attribute, grouped by the attribute group, ordered by order then declaration order, with widgets chosen by type (Appendix B.7).

{
  "forms": {
    "taskInspector": {
      "for": "Task",
      "usage": ["inspector", "create"],
      "layout": { "columns": 2 },
      "items": [
        { "kind": "section", "title": "General", "items": [
          { "attribute": "title", "colSpan": 2, "widget": "text" },
          { "attribute": "assignee", "widget": "reference",
            "options": { "cel": "diagram.nodesOfType('Resource')" } },
          { "attribute": "priority", "widget": "segmented" }
        ] },
        { "kind": "section", "title": "Schedule", "items": [
          { "attribute": "start", "widget": "date" },
          { "attribute": "end",   "widget": "date",
            "validate": [ { "rule": "value >= self.start", "message": "End must not be before start." } ] },
          { "kind": "computed", "label": "Duration",
            "value": { "cel": "string(workingDays(self.start, self.end, 'project')) + ' working days'" } }
        ] },
        { "kind": "section", "title": "Notes", "collapsed": true, "items": [
          { "attribute": "notes", "widget": "markdown", "rows": 6 }
        ] },
        { "kind": "button", "label": "Split task", "operation": "splitTask", "icon": "scissors" }
      ]
    }
  }
}

Form

Property Type Description
for TypeRef or TypeRef[] Types edited. For relations, the relation type. "diagram" edits the diagram root.
usage ("inspector", "create", "embedded", "popover", "bulk")[] Where the form is used. create shows it as a dialog before creation; bulk supports editing several selected elements (fields show "mixed" values). Default ["inspector"].
layout "vertical", "horizontal", {columns, labelPosition, density} labelPosition: "top", "left", "inline", "none"; density: "comfortable", "compact".
items FormItem[] Fields and containers.
commit "immediate", "onBlur", "explicit" When edits become model changes (each commit is one undoable transaction). Default "immediate" for inspectors, "explicit" for create dialogs.
label, doc, icon Title and help of the form.

Field (an item with attribute, or kind: "field"):

Property Type Description
attribute path Attribute edited (dotted path into structs). Required for fields.
widget Widget Default by type (Appendix B.7).
label LocalizedText Default: attribute label.
doc Doc Field help. Default: attribute doc. Shown below the field (summary) and via an info icon (description, rationale).
placeholder LocalizedText Hint text inside empty inputs.
visible, enabled Expression Context form (12.3): self, value, diagram.
required bool Visual required marker; may tighten but not loosen the attribute.
validate {rule, message, severity}[] Field-local validation shown immediately; does not replace constraints.
options {cel} or {enum} or literal list Choices for select-like widgets: values or {value, label, icon, doc} maps, or elements for reference.
widgetOptions object Widget-specific settings (below).
colSpan, width int, length Grid layout.
prefix, suffix, unit LocalizedText Adornments.
format string Display format for numbers and dates.
rows int For multi-line widgets.
readOnly Bindable bool
onChange Action[] Actions run after the value is committed (9.4).

Widgets: text, textarea, markdown, code (with widgetOptions.language: "cel", "json", "sql", …; the cel language is type-checked in the attribute's context), number, slider (min, max, step, marks), spinner, rating (max, icon), checkbox, switch, select, combobox (free entry allowed), radio, segmented (button group), multiselect, tags, date, datetime, time, duration, daterange (edits two attributes: attribute and widgetOptions.endAttribute), color (palette, alpha), icon (icon picker), reference (element picker, with widgetOptions.pickOnCanvas: true to select by clicking), references (for many references), list (editable list of primitives), table (list of structs, with widgetOptions.columns), struct (nested sub-form), file (binary or URI, mediaTypes), image, link, progress (read-only bar), readonly (plain text), plugin.

Containers and other items (by kind): section (title, collapsible, collapsed, items), row (horizontal group), tabs (tabs: [{title, icon, items}]), group (a bordered box with title), text (static help text, Markdown), divider, computed (read-only value Bindable), button (label, icon, operation or actions, enabled, confirm), problems (list of the element's current constraint problems with quick fixes), plugin.

7.6 Embedded forms (widgets inside nodes)

Nodes MAY display live form widgets on the canvas — checkboxes in a to-do card, a slider on a parameter block, a dropdown on a gateway, a table inside an entity — via NodeNotation.form:

{
  "form": {
    "form": "taskCard",
    "region": { "x": 8, "y": 30, "w": "w - 16", "h": "h - 38" },
    "interaction": "always",
    "minZoom": 0.6,
    "fallback": "labels",
    "autoSize": true
  }
}
Property Type Description
form form id or inline Form The form (its usage SHOULD include "embedded").
region Box of GeomExpr Area inside the node, in shape coordinates. Default: the shape's text area.
interaction "always", "onSelect", "onDoubleClick", "readOnly" When the widgets accept input. readOnly renders values only. Default "onSelect".
minZoom number Below this zoom, the form is not rendered; fallback decides what is shown instead ("labels", "none", "summary").
autoSize bool The node grows to fit the form.
style StyleRef Styling of embedded widgets (font, density). Runtimes SHOULD render embedded widgets in the node's style, not the platform style.

Embedded forms MUST NOT capture canvas gestures outside their widgets: dragging on a non-interactive area moves the node. Every widget change is an undoable model transaction, exactly as in the inspector.

Illustrated by

Referenced from