NorthwoodsSoftware / GoJS

JavaScript diagramming library for interactive flowcharts, org charts, design tools, planning tools, visual languages.
http://gojs.net
Other
7.7k stars 2.86k forks source link

Bug in LinkShiftingTool.ts #154

Closed Darma1106 closed 3 years ago

Darma1106 commented 3 years ago

If a link data without 'to' like:

{
  "points": [
    123.77770660034568, -295.0003859604378, 123.77770660034568, -285.0003859604378, 124.2689901376375,
    -254.99886393596353
  ],
  "from": "6f12aa8f-54f2-46bd-b888-113c86ada914",
  "fromSpot": { "class": "go.Spot", "x": 0.5196570246207027, "y": 0.9999940621471104, "offsetX": 0, "offsetY": 0 }
}

example

This link can't shift thier fromSpot.

The reason is that the function 《doReshape》 in LinkShiftingTool.ts (line 248 and line 263) because link.toPort is null && fromend === 'LinkShiftingTo'

public doReshape(pt: go.Point): void {
    if (this._handle === null) return;
    const ad = this._handle.part as go.Adornment;
    if (ad.adornedObject === null) return;
    const link = ad.adornedObject.part as go.Link;
    const fromend = ad.category === 'LinkShiftingFrom';
    let port = null;
    if (fromend) {
      port = link.fromPort;
    } else {
      port = link.toPort;  // =>  port = link.toPort ?? link.fromPort
    }
    if (port === null) return;
    // support rotated ports
    const portang = port.getDocumentAngle();
    const center = port.getDocumentPoint(go.Spot.Center);
    const portb = new go.Rect(port.getDocumentPoint(go.Spot.TopLeft).subtract(center).rotate(-portang).add(center),
                              port.getDocumentPoint(go.Spot.BottomRight).subtract(center).rotate(-portang).add(center));
    let lp = link.getLinkPointFromPoint(port.part as go.Node, port, center, pt, fromend);
    lp = lp.copy().subtract(center).rotate(-portang).add(center);
    const spot = new go.Spot(Math.max(0, Math.min(1, (lp.x - portb.x) / (portb.width || 1))),
                             Math.max(0, Math.min(1, (lp.y - portb.y) / (portb.height || 1))));
    if (fromend) {  //// => if (fromend || link.toPort === null)
      link.fromSpot = spot;
    } else {
      link.toSpot = spot;
    }
  }
WalterNorthwoods commented 3 years ago

Are you asking for the tool to be able to handle Links that are only half connected?

Darma1106 commented 3 years ago

Are you asking for the tool to be able to handle Links that are only half connected?

yes,

Darma1106 commented 3 years ago

Are you asking for the tool to be able to handle Links that are only half connected?

I modified these two line to support this but I don't know if there are any side effects

Ernest1984 commented 3 years ago

If a link data without 'to' like:


{

  "points": [

    123.77770660034568, -295.0003859604378, 123.77770660034568, -285.0003859604378, 124.2689901376375,

    -254.99886393596353

  ],

  "from": "6f12aa8f-54f2-46bd-b888-113c86ada914",

  "fromSpot": { "class": "go.Spot", "x": 0.5196570246207027, "y": 0.9999940621471104, "offsetX": 0, "offsetY": 0 }

}

example

This link can't shift thier fromSpot.

The reason is that the function 《doReshape》 in LinkShiftingTool.ts (line 248 and line 263)

because link.toPort is null && fromend === 'LinkShiftingTo'


public doReshape(pt: go.Point): void {

    if (this._handle === null) return;

    const ad = this._handle.part as go.Adornment;

    if (ad.adornedObject === null) return;

    const link = ad.adornedObject.part as go.Link;

    const fromend = ad.category === 'LinkShiftingFrom';

    let port = null;

    if (fromend) {

      port = link.fromPort;

    } else {

      port = link.toPort;  // =>  port = link.toPort ?? link.fromPort

    }

    if (port === null) return;

    // support rotated ports

    const portang = port.getDocumentAngle();

    const center = port.getDocumentPoint(go.Spot.Center);

    const portb = new go.Rect(port.getDocumentPoint(go.Spot.TopLeft).subtract(center).rotate(-portang).add(center),

                              port.getDocumentPoint(go.Spot.BottomRight).subtract(center).rotate(-portang).add(center));

    let lp = link.getLinkPointFromPoint(port.part as go.Node, port, center, pt, fromend);

    lp = lp.copy().subtract(center).rotate(-portang).add(center);

    const spot = new go.Spot(Math.max(0, Math.min(1, (lp.x - portb.x) / (portb.width || 1))),

                             Math.max(0, Math.min(1, (lp.y - portb.y) / (portb.height || 1))));

    if (fromend) {  //// => if (fromend || link.toPort === null)

      link.fromSpot = spot;

    } else {

      link.toSpot = spot;

    }

  }
WalterNorthwoods commented 3 years ago

Thank you both for your contributions. I think the best solution is to change the LinkShiftingTool.updateAdornments method so that it doesn't create an adornment for an end of the link where there's no connected node/port.

That can be accomplished by adding these two checks:

  if (link.isSelected && !this.diagram.isReadOnly && link.fromPort) {
  if (link.isSelected && !this.diagram.isReadOnly && link.toPort) {

These are at lines:

These changes will be in the next release.