jsplumb / community-edition

The community edition of jsPlumb, versions 1.x - 6.x
https://jsplumbtoolkit.com
Other
225 stars 18 forks source link

Cannot access internalSegments in FlowchartConnector. Any other alternative? #280

Closed vanessadnguyen closed 1 year ago

vanessadnguyen commented 1 year ago

Hi, I tried to migrate our code from jsplumb 2.5.12 https://www.npmjs.com/package/jsplumb) to @jsplumb/browser-ui": "~5.13.2 Related thread in the past: https://github.com/jsplumb/community-edition/issues/296

let gridGraph = function(segments: any[]) {
    let abstractConnector = jsPlumb.Connectors.AbstractConnector.apply(this, arguments);
    this.type = 'GridGraph';
this._compute = (paintInfo, paintParam) => {
let currentPoint = [paintInfo.sx, paintInfo.sy];
let nextPoint;
// draw the path according to the segments
segments.forEach((segment) => {
nextPoint = [segment.end[0] - segment.start[0] + currentPoint[0],
segment.end[1] - segment.start[1] + currentPoint[1]
];
abstractConnector.addSegment(this, 'Straight', {
x1: currentPoint[0],
y1: currentPoint[1],
x2: nextPoint[0],
y2: nextPoint[1]
});
currentPoint = nextPoint;
});
};
};
// jsPlumb already initialized, so we have to set connectorsInitialized to false for the connector
jsPlumb.registerConnectorType(gridGraph, 'GridGraph');
jsPlumb.connectorsInitialized = false;
jsPlumb.init();

For my case, I think my GridGraphConnector should extend FlowchartConnector as below:

export class GridGraphConnector extends FlowchartConnector {
  static override type = "GridGraph";
  override type = GridGraphConnector.type;

  override _compute (paintInfo:PaintGeometry, params:ConnectorComputeParams):void {
    let currentPoint = [paintInfo.sx, paintInfo.sy];
    let nextPoint;
    // draw the path according to the segments
    this.internalSegments.forEach(segment => {
      nextPoint = [segment.end[0] - segment.start[0] + currentPoint[0], segment.end[1] - segment.start[1] + currentPoint[1]];
      this._addSegment(StraightSegment, {
        x1: currentPoint[0],
        y1: currentPoint[1],
        x2: nextPoint[0],
        y2: nextPoint[1]
      });
      currentPoint = nextPoint;
    });
  }
}

However, this.internalSegments is private and it is not accessible from within GridGraphConnector. How do I work around this issue? Since I cannot test this due to compilation issue with inaccessible private member, I am not sure whether internalSegments is the right choice. Any suggestion is greatly appreciated. Thanks. Vanessa

sporritt commented 1 year ago

internalSegments is not something a custom connector should need to access. The _compute method is where you do your calculations, and then you call this._addSegment for every segment you wish to add, which results in changes to the internal segments. There's a guide to creating a custom connector for 5.x here:

https://blog.jsplumbtoolkit.com/2022/05/20/custom-connectors

vanessadnguyen commented 1 year ago

Thanks for pointing out that guide. It is very helpful. With old JsPlumb, our code tried to call JsPlumbConnection.setConnector('GridGraph', pathData) //pathData is an array of {start: number[], end: number[]} setConnector calls makeConnector which calls _jp.Connectors[connectorName].apply(this, arguments); //connectorName is "GriidGraph" and arguments contains the above pathData and JsPlumbInstance. This actually invoked our let gridGraph = function(segments: any[]) {} where the segments contains pathData above with JsPlumbInstance. I think our GridGraphConnector tried to look at all segments at once. I will need to think more about this and figure out how to do it similarly with the new JsPlumb 5.x. The following is the code of the makeConnector in JsPlumb version 2.5.12.

var makeConnector = function (_jsPlumb, renderMode, connectorName, connectorArgs, forComponent) {
            // first make sure we have a cache for the specified renderer
            _jp.Connectors[renderMode] = _jp.Connectors[renderMode] || {};

            // now see if the one we want exists; if not we will try to make it
            if (_jp.Connectors[renderMode][connectorName] == null) {

                if (_jp.Connectors[connectorName] == null) {
                    if (!_jsPlumb.Defaults.DoNotThrowErrors) {
                        throw new TypeError("jsPlumb: unknown connector type '" + connectorName + "'");
                    } else {
                        return null;
                    }
                }

                _jp.Connectors[renderMode][connectorName] = function() {
                    _jp.Connectors[connectorName].apply(this, arguments);
                    _jp.ConnectorRenderers[renderMode].apply(this, arguments);
                };

                _ju.extend(_jp.Connectors[renderMode][connectorName], [ _jp.Connectors[connectorName], _jp.ConnectorRenderers[renderMode]]);

            }

            return new _jp.Connectors[renderMode][connectorName](connectorArgs, forComponent);
        },
vanessadnguyen commented 1 year ago

Screen Shot 2023-03-29 at 3 28 22 PM Screen Shot 2023-03-29 at 3 51 22 PM Screen Shot 2023-03-29 at 3 52 27 PM

vanessadnguyen commented 1 year ago

Screen Shot 2023-03-29 at 3 56 05 PM

vanessadnguyen commented 1 year ago

Screen Shot 2023-03-29 at 4 06 02 PM

sporritt commented 1 year ago

closing this out. I think the question was answered.