Help with Group Subprocess

I am trying to implement a group template similar to the Subprocess node available in the BPMN example with some custom behavior. I have a few issues that I need help with.

  1. Is there a way to set the padding in the Placeholder to provide a larger drop space when the group is expanded and less padding when the group is collapsed? For example I was trying to bind the placeholder padding property dynamically with a function instead of statically.

$(go.Placeholder,
// { padding: new go.Margin(25, 25)},
new go.Binding(“padding”, “isSubGraphExpanded”, function (s) {
if(s) {
return new go.Margin(100, 100);
} else {
return new go.Margin(10, 10);
}
})
)

  1. I took code from the Regrouping example to handle drag and resize of the group and the highlight is a good cue for the user to resize, but the resize with that code demands the user hang near the border of the group to get the group to slowly resize. It’s pretty touchy and not nearly as flexible as resizing the group without computesBoundsAfterDrag set to true. With computesBoundsAfterDrag set to false, the container moves really fluidly, but you can’t drag a node out. I tried the drag with the shift key code, but that was not working for me and in addition that would not be desirable for my users. I would like a better fluidity of resize of the container near the border. Is there a way to achieve that?

  2. I was trying to add ports for creating links on dragEnter and dragLeave on the group, but the port always shows at center as if it has no knowledge of its bounds. For example, the ports would be added like:
    makeSubProcPort(“T”, go.Spot.Top, true, true),
    makeSubProcPort(“L”, go.Spot.Left, true, true),
    makeSubProcPort(“R”, go.Spot.Right, true, true),
    makeSubProcPort(“B”, go.Spot.Bottom, true, true)
    function makeSubProcPort(name, spot, output, input) {
    // the port is basically just a small transparent square
    return $(go.Shape, “Circle”,
    {
    fill: null, // not seen, by default; set to a translucent gray by showSmallPorts, defined below
    stroke: null,
    desiredSize: new go.Size(10, 10),
    alignment: spot, // align the port on the main Shape
    alignmentFocus: spot, // just inside the Shape
    portId: name, // declare this object to be a “port”
    fromSpot: spot, toSpot: spot, // declare where links may connect at this port
    fromLinkable: output, toLinkable: input, // declare whether the user may draw links to/from here
    cursor: “pointer” // show a different cursor to indicate potential link point
    });
    }

Thanks a lot for the help!!

Andrea

    
var subProcessGroupTemplate =
      $(go.Group, "Spot",
        {
          copyable: false,
          locationSpot: go.Spot.Center,
          locationObjectName: "PH",
          fromSpot: go.Spot.AllSides, toSpot: go.Spot.AllSides, portId: "",
          isSubGraphExpanded: true,
          memberValidation: function (group, part) {
            return !(part instanceof go.Group) ||
              (part.category !== "Pool" && part.category !== "Lane");
          },
          mouseDragEnter: function(e, grp, prev) { highlightGroup(e, grp, true); },
          mouseDragLeave: function(e, grp, next) { highlightGroup(e, grp, false); },
          computesBoundsAfterDrag: true,
          // when the selection is dropped into a Group, add the selected Parts into that Group;
          // if it fails, cancel the tool, rolling back any changes
          mouseDrop: finishDrop,
          handlesDragDropForMembers: true,  // don't need to define handlers on member Nodes and Links
          // Groups containing Groups lay out their members horizontally
          contextMenu: activityNodeMenu,
          itemTemplate: boundaryEventItemTemplate,
          selectionAdornmentTemplate:
        $(go.Adornment, "Auto",
          $(go.Shape, "RoundedRectangle",
          { fill: null, stroke: "#296796", strokeWidth: 1.5,
          strokeDashArray: [3,2] }),
          $(go.Placeholder)
        )
        },
       
        new go.Binding("background", "isHighlighted", function(h) {
          if(h) return "rgba(41,103,150)"; else return "transparent";}).ofObject(),
        new go.Binding("itemArray", "boundaryEventArray"),
        makeSubProcPort("T", go.Spot.Top, true, true),
        makeSubProcPort("L", go.Spot.Left, true, true),
        makeSubProcPort("R", go.Spot.Right, true, true),
        makeSubProcPort("B", go.Spot.Bottom, true, true),
        { // handle mouse enter/leave events to show/hide the ports
          mouseEnter: function (e, node) { showSmallPorts(node, true); },
          mouseLeave: function (e, node) { showSmallPorts(node, false); }
        },
      $(go.Panel, "Auto",
          $(go.Shape, "RoundedRectangle",
            {
              name: "PH", fill: "rgba(255,255,255, 0.8)", stroke: SubprocessNodeStroke,
              minSize: new go.Size(ActivityNodeWidth, ActivityNodeHeight),
              portId: "", fromLinkable: true, toLinkable: true, cursor: "pointer",
              fromSpot: go.Spot.RightSide, toSpot: go.Spot.LeftSide
            },
            new go.Binding("strokeWidth", "isCall", function (s) { return s ? ActivityNodeStrokeWidthIsCall : ActivityNodeStrokeWidth; })
          ),
          $(go.Panel, "Vertical",
            { defaultAlignment: go.Spot.Left },
            $(go.TextBlock,  // label
              { margin: 3, editable: true },
              new go.Binding("text", "label").makeTwoWay(),
              new go.Binding("alignment", "isSubGraphExpanded", function (s) { return s ? go.Spot.TopLeft : go.Spot.Center; })),
            // create a placeholder to represent the area where the contents of the group are
            $(go.Placeholder,
             // { padding: new go.Margin(25, 25)},
                new go.Binding("padding", "isSubGraphExpanded", function (s) {
                 if(s) {
                   return new go.Margin(100, 100);
                  } else {
                    return new go.Margin(10, 10);
                  }
                })
            ),
            makeMarkerPanel(true, 1)  // sub-process,  loop, parallel, sequential, ad doc and compensation markers
          )  // end Vertical Panel
        )
      );  // end Group
  1. That’s right – but you forgot to make sure the Binding uses the Group itself as the source rather than the Group.data. So you need to say new go.Binding(. . .).ofObject().

  2. I don’t know what you mean. Could you describe it better in a separate forum topic?

  3. Those ports need to be laid out by the appropriate kind of Panel. Could you open a separate topic for this, including a small screenshot showing what’s happening and what you want instead?

Hi Walter,

Thanks a lot for the help. ofObject is very handy – thanks so much for that tip. I will reopen another topic for the drag issue. We have decided to use a line drawing tool instead of showing ports on the templates so that will alleviate the other question I had.

Thanks a lot for your help!!

Andrea