Bind Parent Node Width to Width of All Child Nodes

I started with the static org chart and have tweaked some options, but ultimately have a tree layout. Is there a way to bind the width of parent nodes to have their left and right bounds match the outer bounds of their left and right most children? Right now I have code that finds the root, finds the first child and last child, and sets the width of the parent to the right bound of the right most child node minus the left bound of the left most child node. This works well, but I want every parent to effectively umbrella all of it’s children. If I recurse from the lower left most child node up to the root(s) with the code I have now, I’m sure that would accomplish what I want, but I was hoping there was a way to bind it at initial layout. Hopefully what I’m trying to do is clear enough without an example image, but I’m happy to provide one if necessary. Thanks!

That may require a customization of the layout.

Also, as a generalized principle, it might cause issues. If you have a tree that looks like

     A
   B   C
 D  E F  G

B and C would need to become as wide as their children, which means A would need to become as wide as the whole graph. Or is that what you intend?

 AAAAAAAAA
 BBBB CCCC
 D  E F  G

Ah. Should have thought of describing it that way on my train ride home. That’s actually exactly what I want! :-)

Is there documentation you can point me to on how to create a custom layout? I feel like it might just be easier to work my way from the bottom of the tree to the top resizing if a custom layout is the only other way. At least my function for doing this on the parent is already mostly done. Thanks for the quick reply!

I think we already have such an example. I’ll look for it tomorrow.

First, there already exists a more complicated version of this: Pipe Tree

But you can try this simpler customization of TreeLayout. Note that the constructor sets some properties that you should not modify.

  function CoveringTreeLayout() {
    go.TreeLayout.call(this);
    this.compaction = go.TreeLayout.CompactionNone;  // necessary to avoid potential overlapping nodes
    this.alignment = go.TreeLayout.AlignmentStart;
    this.alternateAlignment = go.TreeLayout.AlignmentStart;
  }
  go.Diagram.inherit(CoveringTreeLayout, go.TreeLayout);

  CoveringTreeLayout.prototype.assignTreeVertexValues = function(v) {
    if (v.childrenCount > 0) {
      if (this.angle === 0 || this.angle === 180) {
        v.height = 0;
      } else {
        v.width = 0;
      }
    }
  };

  CoveringTreeLayout.prototype.commitNodes = function() {
    var vit = this.network.vertexes.iterator;
    while (vit.next()) {
      var v = vit.value;
      var n = v.node;
      if (n === null) continue;
      n.position = new go.Point(v.x, v.y);
      if (v.childrenCount > 0) {
        if (this.angle === 0 || this.angle === 180) {
          n.height = v.subtreeSize.height;
        } else {
          n.width = v.subtreeSize.width;
        }
      }
    }
  };

This CoveringTreeLayout also assumes that in order for the node to be a particular width or height it is sufficient to just set those properties on the whole node. Depending on your node template, that might not be the case.

Thanks for the quick replies. I’ll give that code a shot once I get through an issue I’m having with a double tree at the moment (you may see a new ticket for that soon…). I was also able to play with some other TreeLayout settings to maybe no longer require a CoveringTreeLayout, but the org charts we’re attempting to produce have nodes with quite a few children and it might be nice to see the parent even as you scroll far to the left or right. Thanks again!