Shapes in TextBlock

Hello!
My node represents a message that contains variables represented by different shapes.
I want my node to look like this:

What is the easiest way to do this?

You’ll need to break it up into separate TextBlocks and Panels.

Here’s a simple FlowPanelLayout:

  function FlowPanelLayout() {
    go.PanelLayout.call(this);
    this.spacing = new go.Size(2, 2);
  }
  go.Diagram.inherit(FlowPanelLayout, go.PanelLayout);

  FlowPanelLayout.prototype.measure = function(panel, width, height, elements, union, minw, minh) {
    var x = 0;
    var y = 0;
    var maxx = 0;
    var rowh = 0;
    for (var i = 0; i < elements.length; i++) {
      var elem = elements[i];
      this.measureElement(elem, width, height, minw, minh);
      var mb = elem.measuredBounds;
      if (x + this.spacing.width + mb.width > width) {
        y += rowh + this.spacing.height;
        x = this.spacing.width + mb.width;
        rowh = mb.height;
      } else {
        x += this.spacing.width + mb.width;
        rowh = Math.max(rowh, mb.height);
      }
      maxx = Math.max(maxx, x);
    }
    union.width = maxx;
    union.height = y + rowh;
  }

  FlowPanelLayout.prototype.arrange = function(panel, elements, union) {
    var x = 0;
    var y = 0;
    var rowh = 0;
    for (var i = 0; i < elements.length; i++) {
      var elem = elements[i];
      var mb = elem.measuredBounds;
      if (x + this.spacing.width + mb.width > union.width) {
        x = 0;
        y += rowh + this.spacing.height;
        this.arrangeElement(elem, x, y, mb.width, mb.height);
        x = this.spacing.width + mb.width;
        rowh = mb.height;
      } else {
        this.arrangeElement(elem, x, y, mb.width, mb.height);
        x += this.spacing.width + mb.width;
        rowh = Math.max(rowh, mb.height);
      }
    }
  }

  go.Panel.definePanelLayout('Flow', new FlowPanelLayout())

Example use:

  function init() {
    var $ = go.GraphObject.make;

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
        { "undoManager.isEnabled": true });

    var templMap = new go.Map();
    templMap.add("",
      $(go.Panel,
        $(go.TextBlock,
          new go.Binding("text", ""))
      ));
    templMap.add("Shape",
      $(go.Panel,
        $(go.Shape, 
          { width: 16, height: 16, strokeWidth: 0 },
          new go.Binding("figure", "fig"),
          new go.Binding("fill", "color"))
      ));
    templMap.add("Capsule",
      $(go.Panel, "Auto",
        $(go.Shape, "RoundedRectangle",
          { fill: "white", strokeWidth: 0, spot1: go.Spot.TopLeft, spot2: go.Spot.BottomRight }),
        $(go.Panel, "Flow",
          new go.Binding("itemArray", "content"),
          { itemTemplateMap: templMap }
        )
      ));

    myDiagram.nodeTemplate =
      $(go.Node, "Vertical",
        $(go.TextBlock, new go.Binding("text")),
        $(go.Panel, "Auto",
          { portId: "" },
          $(go.Shape, { fill: "lightgray" }),
          $(go.Panel, "Flow",
            {
              margin: new go.Margin(4, 4, 3, 4),
              maxSize: new go.Size(160, NaN),
              itemTemplateMap: templMap
            },
            new go.Binding("itemArray", "items"))
        )
      );

    myDiagram.model = new go.GraphLinksModel([
      {
        key: 1, text: "Alpha", items: [
          "A1",
          { category: "Shape", fig: "Diamond", color: "red"},
          "C1"
          ]
      },
      {
        key: 2, text: "Beta", items: [
          "some",
          {
            category: "Capsule", content: [
              { category: "Shape", fig: "Circle", color: "green" },
              "inside",
              { category: "Shape", fig: "TriangleRight", color: "green" },
              "text"
            ]
          },
          "more",
          { category: "Shape", fig: "TriangleUp", color: "orange" },
          "stuff"
        ]
      }
    ],
    [
      { from: 1, to: 2 }
    ]);
  }

produces:
image

The main thing lacking now is support for text baselines. And right-to-left text.