documentationfor yFiles for HTML 3.0.0.1

Reconnecting Edges

Edge reconnection involves moving an edge’s source or target endpoint to another port. In yFiles for HTML, this is accomplished by selecting an edge and dragging the handle that represents its source or target port. Edge reconnection is enabled by default, and edges can be reconnected to the port candidates provided for nodes.

The following steps occur when reconnecting edges:

  • When an edge is selected and an HandleInputMode is active, IHandle instances are calculated for the edge’s source and target ports:
  • HandleInputMode visualizes these handles and delegates drag gestures to the PortRelocationHandle instances.
  • When a drag gesture is initiated, PortRelocationHandle calculates the possible port candidates to which the edge may reconnect:

These steps can be adjusted for a customized reconnection behavior. The most common adjustments include Providing Port Candidates and Customizing the Reconnection Gesture.

Providing Port Candidates

Possible candidates for new source and target nodes are provided by implementations of IEdgeReconnectionPortCandidateProvider which are retrieved from the edge’s lookup. During reconnections, the following methods are called to return a list of port candidates:

Method Description
getSourcePortCandidates(IInputModeContext)Returns a list of possible candidates for an edge’s source port.
getTargetPortCandidates(IInputModeContext)Returns a list of possible candidates for target ports.

Implementers must implement the above methods to return an appropriate list of candidates. Note that this list may be empty (or contain only invalid candidates) if an edge cannot be reconnected. The concept of port candidates is explained above.

yFiles for HTML provides several IEdgeReconnectionPortCandidateProvider implementations for common use cases. These are available through factory methods or constants on the IEdgeReconnectionPortCandidateProvider interface:

Predefined edge reconnection port candidate providers
Constant / Factory Method Description
fromAllNodeCandidates(IEdge)Creates an IEdgeReconnectionPortCandidateProvider that queries all nodes for their IPortCandidateProvider implementation and returns a union of all port candidates returned by their getAllSourcePortCandidates or getAllTargetPortCandidates methods. This is the default implementation.
fromAllNodeAndEdgeCandidates(IEdge)Creates an IEdgeReconnectionPortCandidateProvider that queries all nodes and edges for their IPortCandidateProvider implementation and returns a union of all port candidates returned by their getAllSourcePortCandidates or getAllTargetPortCandidates methods.
fromSourceAndTarget(IEdge)Creates an IEdgeReconnectionPortCandidateProvider which queries the edge’s source and target port owner for an IPortCandidateProvider. The IPortCandidateProvider is then queried to return a list of port candidates. This allows edges to be reconnected only to other ports on the same node.

The edge’s lookup must be modified to return an instance of the new provider. You can do this using an EdgeDecorator:

graph.decorator.edges.reconnectionPortCandidateProvider.addFactory(
  IEdgeReconnectionPortCandidateProvider.fromSourceAndTarget
)

For folding-enabled graphs, you must decorate the master graph. Decorating the view graph may result in an exception during edge reconnection.

The tutorial demo application Edge Reconnection shows how to implement IEdgeReconnectionPortCandidateProvider for different purposes.

Customizing the Reconnection Gesture

The actual dragging is managed by IHandle implementations, and by default, a PortRelocationHandle is used. It provides a number of settings that control the behavior and appearance of the handle. The most common settings are listed below:

Property Description truefalse
showPortCandidatesWhether to show port candidates. The default is true.
showHitPortOwnerCandidatesOnlyWhether to show only the candidates of the IPortOwner that was hit. The default is true.
showTargetHighlightWhether the owner of the current port candidate should be highlighted. The default is true.

Additionally, the maximum distance the pointer can be from a candidate to snap to it can be set via maximumSnapDistance.

The appearance of the edge during the movement gesture can be determined with visualization. The effect is visualized below. The default is PLACEHOLDER:

Visualization modes during edge reconnection
NONEGHOSTPLACEHOLDERLIVE
Visualization.NONEVisualization.GHOSTVisualization.PLACEHOLDERVisualization.LIVE
Only the handle is visualized during movement; the original edge is not changed.A symbolic view of the edge is visualized during movement; the original edge is not changed. The edge ghost visualization provides the .yfiles-edge-relocation-ghost CSS class.A copy of the edge (a helper edge) is shown during movement; the original edge is hidden. Note that decorations like labels are not moved with the helper edge.The original edge, together with all its decorations, is moved.

The PortRelocationHandle cannot be directly associated with edges. Instead instances of this IHandle are provided by the PortRelocationHandleProvider. It can be associated using the edges's portHandleProvider. The most commonly used settings are also available on the PortRelocationHandleProvider:

graph.decorator.edges.portHandleProvider.addFactory((edge) => {
  const portRelocationHandleProvider = new PortRelocationHandleProvider(
    graph,
    edge
  )
  portRelocationHandleProvider.visualization = Visualization.LIVE
  portRelocationHandleProvider.showPortCandidates = false
  return portRelocationHandleProvider
})

For less frequently used settings, a custom PortRelocationHandleProvider has to be provided, and its createPortRelocationHandle method must be overridden to provide the configured PortRelocationHandle:

graph.decorator.edges.portHandleProvider.addFactory((edge) => {
  const portRelocationHandleProvider = new MyHandleProvider(graph, edge)
  portRelocationHandleProvider.visualization = Visualization.LIVE
  portRelocationHandleProvider.showPortCandidates = false
  return portRelocationHandleProvider
})

class MyHandleProvider extends PortRelocationHandleProvider {
  createPortRelocationHandle(graph, edge, sourceEnd) {
    const portRelocationHandle = new PortRelocationHandle(
      graph,
      edge,
      sourceEnd
    )
    portRelocationHandle.addExistingPort = true
    return portRelocationHandle
  }
}

graph.decorator.edges.portHandleProvider.addFactory((edge) => {
  const portRelocationHandleProvider = new MyHandleProvider(graph, edge)
  portRelocationHandleProvider.visualization = Visualization.LIVE
  portRelocationHandleProvider.showPortCandidates = false
  return portRelocationHandleProvider
})

class MyHandleProvider extends PortRelocationHandleProvider {
  createPortRelocationHandle(
    graph: IGraph,
    edge: IEdge,
    sourceEnd: boolean
  ): PortRelocationHandle {
    const portRelocationHandle = new PortRelocationHandle(
      graph,
      edge,
      sourceEnd
    )
    portRelocationHandle.addExistingPort = true
    return portRelocationHandle
  }
}