How to have a port connection from entire node and still move the node as well?


#1

I have a dilemma; I can link two nodes but can’t move the nodes on the diagram, or I can move the nodes on the diagram but can’t link two nodes. Is it possible to be able to do both? I found something that works somewhat, but to link nodes I need to click a one pixel border of the node and drag which is nearly impossible. Here is my code:

// creates the node template for each entity
fileDiagram.nodeTemplate =
$(go.Node, "Auto",
	{
		defaultStretch: go.GraphObject.Horizontal,
		selectionAdorned: true,
		layoutConditions: go.Part.LayoutStandard & ~go.Part.LayoutNodeSized
	},

	// binds the location of the node
	new go.Binding("location", "location").makeTwoWay(),

	// creates the entity
	 $(go.Panel, "Auto",
		$(go.Shape, "Rectangle",
			{
				fill: "#eaeffd",
				stroke: "#3c599b",
				strokeWidth: 2,

				portId: "",
				background: "transparent",
				
				// allows links to/from all sides
				fromSpot: go.Spot.AllSides,
				toSpot: go.Spot.AllSides,
				
				// allows drawing links from or to this port
				fromLinkable: true,
				toLinkable: true,
				
				// allows drawing links within the same node
				fromLinkableSelfNode: true,
				toLinkableSelfNode: true,
				
				// allows duplicate linking
				fromLinkableDuplicates: true,
				toLinkableDuplicates: true,
				cursor: "pointer"
			},
			// sets the port for binding between two nodes
			new go.Binding("portId", "name"),
			new go.Binding("figure", "figure").makeTwoWay()
		)
	),

	// creates the node table
	$(go.Panel, "Vertical",
		
		$(go.Panel, "Auto",

			// stretches the header of the table to fill the node
			{
				stretch: go.GraphObject.Horizontal
			},
			
			// sets the fill and stroke of the header of the node
			$(go.Shape, "RoundedTopRectangle",
				{
					fill: "#3c599b",
					stroke: null
				}
			),
			// $(go.RowColumnDefinition, { row: 1, separatorStroke: "#3c599b" }),
			// sets the header text style and grabs the text from the binding
			$(go.TextBlock,
				{
					name: "ENTITY",
					row: 0,
					alignment: go.Spot.Center,
					margin: 3,
					stroke: "white",
					textAlign: "center",
					font: "bold 12pt sans-serif",
					cursor: "text",
					editable: true
				},
				new go.Binding("text", "key", function(key) { return key.toUpperCase() }).makeTwoWay()
			)
		),
		
		// sets the attributes row
		$(go.Panel, "Table",
			new go.Binding("itemArray", "attributes"),
			{ 
				name: "ATTRIBUTES",
				row: 1,
				minSize: new go.Size(100, 10),
				stretch: go.GraphObject.Horizontal,
				defaultAlignment: go.Spot.Left,
				defaultColumnSeparatorStroke: "#3c599b",
				cursor: "pointer",
				itemTemplateMap: itemTemplateMap
			}
		)
	)
); 

Here is an image:


#2

Yes, you need to decide where a mouse-down-and-move should start the LinkingTool and where it should start the DraggingTool.

It is easiest to control by having distinct GraphObjects within the port element (the element that has a string value for GraphObject.portId) have different values for GraphObject.fromLinkable (and perhaps GraphObject.toLinkable).

So you if you have set portId and fromLinkable on a Shape, I suppose you could make that shape easier to “pick” with the mouse. In this case you could increase the Shape.strokeWidth.

If you don’t want to do that, you could move setting portId and all of the other port-related properties up to a Panel. That Panel could be the whole Node. Then all elements in that Panel would be part of that port. And all those elements will be “linkable” except for those that you have set GraphObject.fromLinkable (and toLinkable?) to false.

Those objects that are not linkable can then be “grabbed” for dragging.

Unrelated comment: are you using go-debug.js? If not, you are not seeing warnings such as the wastefulness of having an “Auto” Panel that only has one element in it.


#3

Thank you so much! This solved my problem. I put the one element in the Auto panel because that seemed to be the only way to get that rectangle shape to fill the Node. Otherwise, it looked like this:
image
Instead of this:
image


#4

On the border Shape that is the main element of an “Auto” Panel, if it’s a “RoundedRectangle” but you want the body elements to completely fill the area of the “RoundedRectangle” Shape because you don’t mind the corners of the body being cut off by the rounded curves of the shape, then you can set Shape.spot1 to go.Spot.TopLeft and Shape.spot2 to go.Spot.BottomRight.


#5

Thank you! Problem solved.