Constrain Width of Document Bounds

I’ve been searching a lot to try and find the answer to this so I apologize if it’s been answered before. I’m hoping there’s a way to constrain the width of the document bounds and allow the diagram to expand vertically while still retaining the ArrangementHorizontal style. Currently, each top level node expands horizontally across the screen until it reaches the end regardless of the width of the containing div. I prefer the line style of the horizontal alignment, but I’d like to cause a “break” if you will at a specified width. Thanks!

First, are you talking about TreeLayout?

Second, assuming that the TreeLayout.angle is 90, did you want to limit the width of each tree? If so, set TreeLayout.breadthLimit.

Third, if you want to limit the total width occupied by the laid-out diagram, why do you want to set TreeLayout.arrangement to go.TreeLayout.ArrangementHorizontal, which would just put separate trees into one row? Setting it to go.TreeLayout.ArrangementVertical will use less horizontal space.

Yes, it is a TreeLayout and the angle is 90. The diagram lives in a div that can be resized to three different widths. The way nodes are originally brought in is all as top level parents so there isn’t much of a tree yet. Eventually the users will be dragging nodes onto each other and making their diagram. Unfortunately, when they first open up the diagram; if they have a lot of items it can reach far off to the right and take a bit of scrolling to get to. I was hoping there’d be a way to have the diagram see the containing div’s width and begin drawing another row if the nodes were going to exceed that width. If it were up to me, I’d be fine with ArrangementVertical, but the request I’m working on is for a layout like ArrangementHorizontal.

Try this custom TreeLayout:

    function ArrangingTreeLayout() {
      go.TreeLayout.call(this);
      this.isViewportSized = true;
      this.individuals = null;  // Nodes in layout whose LayoutVertexes did not have any connected LayoutEdges
    }
    go.Diagram.inherit(ArrangingTreeLayout, go.TreeLayout);

    ArrangingTreeLayout.prototype.makeNetwork = function(coll) {
      var net = go.TreeLayout.prototype.makeNetwork.call(this, coll);
      var singletons = new go.Set();
      net.vertexes.each(function(v) { if (v.edgesCount === 0) singletons.add(v); });
      singletons.each(function(v) { net.deleteVertex(v); });
      this.individuals = new go.Set().addAll(singletons.map(function(v) { return v.node; }));
      if (net.vertexes.count === 0) this.layoutIndividuals(net);
      return net;
    };

    ArrangingTreeLayout.prototype.layoutIndividuals = function(net) {
      if (this.individuals !== null) {
        var parts = net.findAllParts();
        var bounds = this.diagram.computePartsBounds(parts);
        if (!bounds.isReal()) bounds = new go.Rect(this.arrangementOrigin, new go.Size(0, 0));

        // arrange singleton nodes in rows below or to the right of the trees
        var horiz = (this.angle === 0);
        var x = horiz ? bounds.right + 20 : bounds.x;
        var max = horiz ? Math.max(bounds.bottom, this.diagram.viewportBounds.height-50) : Math.max(bounds.right, this.diagram.viewportBounds.width-50);
        var y = horiz ? bounds.y : bounds.bottom + 20;  // some vertical space between the main graph and the individual nodes
        var breadth = 0;
        var it = this.individuals.iterator;
        while (it.next()) {
          var node = it.value;
          node.moveTo(x, y);
          if (horiz) {
            breadth = Math.max(breadth, node.actualBounds.width);
            y += node.actualBounds.height + 20;  // some horizontal space between individual nodes
            if (y > max) {
              y = bounds.y;
              x += breadth + 20;  // increment Y by the node's height plus some space
              breadth = 0;
            }
          } else {
            breadth = Math.max(breadth, node.actualBounds.height);
            x += node.actualBounds.width + 20;  // some horizontal space between individual nodes
            if (x > max) {
              x = bounds.x;
              y += breadth + 20;  // increment Y by the node's height plus some space
              breadth = 0;
            }
          }
        }
        this.individuals = null;
      }
    }

    ArrangingTreeLayout.prototype.commitLayout = function() {
      go.TreeLayout.prototype.commitLayout.call(this);  // call base method first
      this.layoutIndividuals(this.network);
    };
    // end ArrangingTreeLayout

Example use:

        $(go.Diagram, . . .,
          {
            layout:
              $(ArrangingTreeLayout,
                { angle: 90 }),
            . . .
1 Like

Thanks! I’ll give it a shot.

After a little massaging I think this is going to do the trick. Thank you so much!