chevron_right Demos chevron_right Tutorial: Port Style Implementation chevron_right 06 Edge Cropping
05 Hit-Testing

Customizing edge-cropping

In this tutorial step, we will add support for edge cropping at the port. Since in this example, the ports protrude from their owner node’s bounds, the edge’s arrow can be hidden behind the port.

To define the port shape, we first define an IShapeGeometry for the style. This interface is later used by the IEdgePathCropper to crop the edge at the port outline.

We override the lookup method to return the IShapeGeometry to the port style. The IShapeGeometry gets the port’s bounds and uses the convenience class GeometryUtilities to consider the elliptic port shape.

protected lookup(port: IPort, type: Constructor<any>): any {
  if (type === IShapeGeometry) {
    // calculate the port bounds for edge cropping
    const bounds = this.getPortBounds(port)
    // the IShapeGeometry implementation for this style
    const PortShapeGeometry = class extends BaseClass(IShapeGeometry) {
      getIntersection(inner: Point, outer: Point): Point | null {
        return GeometryUtilities.getEllipseLineIntersection(
          bounds,
          inner,
          outer
        )
      }

      getOutline(): GeneralPath | null {
        const path = new GeneralPath()
        path.appendEllipse(bounds, false)
        return path
      }

      isInside(location: Point): boolean {
        return GeometryUtilities.ellipseContains(bounds, location, 0)
      }
    }
    return new PortShapeGeometry()
  }

Now, we have to provide an IEdgePathCropper instance in the lookup method that yFiles for HTML can use it for edge cropping. We subclass EdgePathCropper and override getPortGeometry. In this method, we use the port’s lookup to get the IShapeGeometry we defined above. We enable cropAtPort in the constructor.

if (type === IEdgePathCropper) {
  // a custom IEdgePathCropped implementation that uses the IShapeGeometry defined above
  const CustomEdgePathCropper = class extends EdgePathCropper {
    protected getPortGeometry(port: IPort): IShapeGeometry | null {
      return port.lookup(IShapeGeometry)
    }
  }
  return new CustomEdgePathCropper({ cropAtPort: true })
}