Limiting textblock size to its containing group node

We are using parallel layout, in which we have a group node which can contain many nodes, this group node has a panel which has a text-block, text-block shows description about this group node, currently when a large text comes in this text-block dynamically, the group-node also expands automatically, we want group node to have a width which is determined by its containing nodes, and text block just limits itself to whatever area is available to it, if text is large we can show ellipses. Problem is how to make group-node to take the size of children nodes and ignore size of text-block, and then text-block should just fit in whatever size is available.

Use a “Table” Panel.

In the simplest case, say you have a TextBlock in row 0 and the Group’s Placeholder in row 1. If you set the TextBlock’s GraphObject.stretch to go.GraphObject.Horizontal, its width will follow whatever width the Placeholder gets.

Read more at GoJS Table Panels -- Northwoods Software and GoJS Sizing of GraphObjects -- Northwoods Software.

Thanks Walter, our textblock is inside group node alongside SubGraphExpanderButton, so how should we introduce table panel inside the group node.

myDiagram.groupTemplate =
$(go.Group, “Auto”,
{
selectable: false,
layout: $(ParallelLayout,
{ layerSpacing: 20, nodeSpacing: 10 })
},
$(go.Shape, { fill: “transparent”, stroke: “darkgoldenrod” }),
$(go.Placeholder, { padding: 10, row:1 }),
$(go.Panel, “Auto”,

					$("SubGraphExpanderButton" , {margin: new go.Margin(2,0,0,5)}),
					$(go.TextBlock, 
					new go.Binding("text", "changep", function(a){
							// long text which will come dynamically
							return "abcd abcd abcd abcd abcd abcd abcd abcd abcd xyz xyz xyz";
						}), 
					{margin: new go.Margin(2,10,0,5),  overflow:go.TextBlock.OverflowEllipsis, wrap: go.TextBlock.None, stretch: go.GraphObject.Horizontal}),
					{alignment: go.Spot.TopLeft, defaultStretch: go.GraphObject.Horizontal}
				)
  );

Here’s an example:

    myDiagram.groupTemplate =
      $(go.Group, "Auto",
        $(go.Shape, { fill: "transparent", strokeWidth: 2 },
          new go.Binding("stroke", "color")),
        $(go.Panel, "Table",
          $(go.TextBlock,
            {
              row: 0,
              stretch: go.GraphObject.Horizontal, margin: 4,
              maxLines: 3, overflow: go.TextBlock.OverflowEllipsis,
              font: "bold 12pt sans-serif", editable: true
            },
            new go.Binding("text").makeTwoWay()),
          $(go.Placeholder, { row: 1, padding: 4 })
        )
      );

Here’s my test model:

    myDiagram.model = new go.GraphLinksModel(
    [
      { key: 3, text: "Gamma", color: "lightgreen", group: 5 },
      { key: 4, text: "Delta", color: "#00ff0080", group: 5 },
      { key: 5, text: "this text wraps because the TextBlock stretches to the width of the column holding the Placeholder", color: "purple", isGroup: true }
    ]);

The results, with two copies of the same Group, but one after dragging the Delta node towards the right:

Thanks Walter, Your example helped me to get some success in doing what I wanted to do, although still there is a minor technical niggle but from user point of view it is important, Please see below the graph which i am getting:

As you can see that I am getting text correctly “abc…” by clipping it to size of containing group, but as you see my links from start to ‘mno’ and from ‘mno’ to end are not straight, they are being bend, I think that is because my placeholder is in second row, How do I get past it, so that I get my links as straight lines instead of bended ones. Here is my group code

myDiagram.groupTemplate =
(go.Group, "Auto", { selectable: false, layout: (ParallelLayout,
{ layerSpacing: 20, nodeSpacing: 10 })
},
(go.Shape, { fill: "transparent", stroke: "darkgoldenrod" }), (go.Panel, “Table”,
("SubGraphExpanderButton" , {margin: new go.Margin(2,0,0,5), row:0, column:0}), (go.TextBlock, new go.Binding(“text”, “text”),
{margin: new go.Margin(2,10,0,5), overflow:go.TextBlock.OverflowEllipsis, wrap: go.TextBlock.None,
stretch: go.GraphObject.Horizontal,row:0, column:1}),
$(go.Placeholder, { padding: 10, row:1, column:1 })
)
);

and here is my data
model.nodeDataArray = [
{key:0, text: “abcd xyz”, isGroup:true, changep:false},
{ key: 1, text: “S”, category: “Split” },
{ key: 2, text: “mno”, group: 0 },
{ key: 100, text: “*”, category: “Merge” }
];
model.linkDataArray = [
{ from: 1, to: 2 },
{ from: 2, to: 100 }
];

we are using parallel layout. Thanks for your help and support.

Ah, well, that requires changing where it thinks it should focus on a group, which is normally just the center of the group. But now your group is asymmetrical, since you have added stuff at the top of the group. So you need to adjust each LayoutVertex that corresponds to a Group.

Fortunately, you already have a custom Layout that has an override of Layout,makeNetwork, so you just have to insert a little bit of code:

ParallelLayout.prototype.makeNetwork = function(coll) {
  var net = go.TreeLayout.prototype.makeNetwork.call(this, coll);
  // look for and remember the one "Split" node and the one "Merge" node
  for (var it = net.vertexes.iterator; it.next(); ) {
    var v = it.value;
    // add this here to focus on Groups differently:
    if (v.node instanceof go.Group) {
      v.focus = v.node.placeholder.getDocumentPoint(go.Spot.Center).subtract(v.node.position);
    }
    . . .

If you don’t mind my fiddling with your template, I think this looks better:

    myDiagram.groupTemplate =
      $(go.Group, "Auto",
        { layout: $(ParallelLayout, { layerSpacing: 20, nodeSpacing: 10 }) },
        $(go.Shape, { fill: "transparent", stroke: "darkgoldenrod" }),
        $(go.Panel, "Table",
          $(go.Panel, "Table",
            { stretch: go.GraphObject.Horizontal },
            $("SubGraphExpanderButton", { margin: new go.Margin(2, 0, 0, 2), column: 0 }),
            $(go.TextBlock, new go.Binding("text", "text"),
            {
              margin: new go.Margin(2, 10, 0, 5), overflow: go.TextBlock.OverflowEllipsis, wrap: go.TextBlock.None,
              stretch: go.GraphObject.Horizontal, column: 1
            })
          ),
          $(go.Placeholder, { padding: 10, row: 1 })
        )
      );

Hi Walter,

Thanks for your prompt suggestions, I think you have made a very good suggestion of shifting the focus, I tried it, I can see execution going through that line of code using debugger, but unfortunately it still shows those bended links, I wonder what could be the reason, I also used your modified template, which is obviously better :-) as it is helping my nodes to be more centrally aligned, aaah… but what to do with these bended links. Could it be GOJS version ? we are using 1.4.1 GOJS version. Did you tried my example ? Do you get straight links after these changes ?

Oh, I didn’t try it when Groups were collapsed.

Add this condition to the code that I added:

    // add this here to focus on Groups differently:
    if (v.node instanceof go.Group && v.node.isSubGraphExpanded) {
      v.focus = v.node.placeholder.getDocumentPoint(go.Spot.Center).subtract(v.node.position);
    }

I do recommend upgrading to version 1.7, but I think that’s independent of this issue.

My group is expanded and there is a node with text ‘mno’ inside as the image i posted, I still see no difference, links have not changed any bit, but that if condition is getting satisfied and you position subtraction line is getting executed. I think if you use my example probably you will be able to reproduce it.

ParallelLayout expects to find a single “Split” Node and a single “Merge” Node. That’s not the case for your Group’s members.

It worked as you would expect on the original extensions/Parallel.html sample model.

I added single split and merge in the group, its similar to the example just simplified, it looks like:

My data is:
model.nodeDataArray = [
{key:0, text: “abcd xyz”, isGroup:true, changep:false},
{ key: 1, text: “S”, category: “Split” },
{ key: 11, text: “S”, category: “Split” , group:0},
{ key: 2, text: “mno”, group: 0 },
{ key: 22, text: “", group: 0,category: “Merge” },
{ key: 100, text: "
”, category: “Merge” }
];
model.linkDataArray = [
{ from: 1, to: 11 },
{ from: 11, to: 2 },
{ from: 2, to: 22 },
{ from: 22, to: 100 }
];

Its very strange that it is not working, as I think your suggestion is good…

That’s because the ParallelLayout, a TreeLayout, is trying to center nodes according to the overall center of their complete subtrees, rather than centering relative to only their immediate children.

Try setting TreeLayout.alignment and TreeLayout.alternateAlignment to go.TreeLayout.AlignmentCenterChildren. You can do that either on individual ParallelLayouts or make that the default in the ParallelLayout constructor.