Shape max size relative to another shape

Hi all.

I have two rectangles (with text blocks) as seen below, however I would like to have the size of the orange rectangle grow with the text to a maximum width of half of the white one (like an Auto panel, but with a max width specified). If the text would exceed the max dimensions, have it cut off as Ellypsis (which AFAIK can be done with TextBlock.OverflowEllipsis)

There is no built-in way to have a Binding where the dimensions of one GraphObject are determined by the actualBounds (or measuredBounds) of another (or the same) GraphObject.

The reason is to avoid bad feedback loops, particularly ones where the measurements do not stabilize! It also guarantees that measuring and arranging panels is fast, or at least bounded.

Note that there would be no problem with having two Bindings to a source data property where there’s a conversion function that causes one GraphObject’s width to be half the width of a different GraphObject. It’s the Binding.ofObject that could cause panel layout problems.

Here’s a node template that I think does what you want:

    myDiagram.nodeTemplate =
      $(go.Node, "Spot",
        $(go.Panel, "Auto",
          { name: "BODY", portId: "" },
          $(go.Shape,
            new go.Binding("fill", "color")),
          $(go.TextBlock,
            { margin: 8, editable: true },
            new go.Binding("text").makeTwoWay())
        ),
        $(go.TextBlock, "abcdefghijklmnopqrstuvwxyz",
          {
            alignment: go.Spot.TopRight,
            background: "orange",
            wrap: go.TextBlock.None,
            overflow: go.TextBlock.OverflowEllipsis
          },
          new go.Binding("width", "actualBounds", function(b) { return b.width/2; }).ofObject("BODY"))
      );

Note the Binding on GraphObject.actualBounds. That property is not settable, so the Binding does not “work”.

But you can make it work by explicitly asking for the Binding to be evaluated, by calling Panel.updateTargetBindings. This is somewhat inefficient, but I think it accomplishes what you want:

  $(go.Diagram, . . . ,
      {
          "LayoutCompleted": function(e) {
              e.diagram.nodes.each(n => n.updateTargetBindings("actualBounds"));
          },
      })