Copying Elements of a Graph
This section describes how graph elements can be copied at a low level. For clipboard operations, see the sections Clipboard and Customizing the Clipboard.
A graph or part of a graph can be copied using the GraphCopier class. Its copy method provides a means to finely control the copied elements.
- copy(sourceGraph: IGraph, targetGraph: IGraph, itemsToCopy: IEnumerable<IModelItem>, targetRootNode: INode, itemOffset: Point, itemCopiedCallback: ItemCopiedCallback)
- Copies the
itemsToCopy
from thesourceGraph
into thetargetGraph
, using the providedtargetRootNode
as the parent (see Grouping Nodes) for the copied elements. After the elements are copied, theoffset
is applied to their position, and theitemCopiedCallback
is applied to the copied item.
Note that the source and target graph can be the same graph.
// copy the elements of 'sourceGraph' to 'targetGraph'
const copier = new GraphCopier()
copier.copy(sourceGraph, targetGraph)
// copy some elements (on the same graph)
const copier = new GraphCopier()
copier.copy(graph, graph, (item) => 'copy me' === item.tag)
Copying Styles, Tags, and Model Parameters
By default, when GraphCopier copies items, the associated styles are cloned. However, tags are not cloned. Instead, the original and the copy share a reference to the same tag. This behavior can be adjusted using the property cloneTypes. For model parameters, only the references are copied as well. Since model parameters are immutable, this does not cause any unintended side effects.
// clone node styles and tags but nothing else
const copier = new GraphCopier()
copier.cloneTypes = CloneTypes.NODE_STYLE | CloneTypes.TAGS
Only styles and tag objects which implement ICloneable can be cloned. For all other elements, the same reference is shared. Note that all built-in styles of yFiles for HTML are cloneable.
The GraphCopier can be configured to ensure that items sharing the same instance of a
style or tag will also share an instance in their copies. However, the shared instance in the
copies is a clone of the original. For example, if nodes n1
and n2
share the same style instance
s1
, their copies will share a new style instance s2
. While s2
is shared between the copies, it
is a separate reference from the original s1
. This behavior is controlled by
referentialIdentityTypes, which is enabled by default for all
element types.
Grouping and Folding
The GraphCopier supports both grouping and folding.
When using a GraphCopier with a folding-enabled graph, it is mandatory to use folding-enabled master graphs as both source and target graphs.
- copyGrouping
- Whether to copy grouping information. When set to
false
, a grouped graph loses its grouping hierarchy upon copying. This can be used to "flatten" a grouped graph. - copyFoldingStates
- Whether to copy the folding states together with the copied items.
const copier = new GraphCopier()
// the copier works on the master graph
const sourceView = sourceGraph.foldingView
const sourceMaster = sourceView.manager.masterGraph
const targetView = targetGraph.foldingView
const targetMaster = targetView.manager.masterGraph
// we want the folding states
// to be copied with the master items
copier.copyFoldingStates = true
// we only copy items with "copy me" as tag
const itemsToCopy = graph.nodes.filter((node) => node.tag === 'copy me')
itemsToCopy.concat(graph.edges)
// after a node is copied we collapse it
// if its original is a collapsed group node
const callback = (original, copy) => {
if (
original instanceof INode &&
copy instanceof INode &&
!sourceView.isExpanded(original)
) {
targetView.collapse(copy)
}
}
// we don't move items after copying
const offset = Point.ORIGIN
copier.copy({
sourceGraph: sourceMaster,
targetGraph: targetMaster,
itemsToCopy: itemsToCopy,
itemOffset: offset,
itemCopiedCallback: callback
})
const copier = new GraphCopier()
// the copier works on the master graph
const sourceView = sourceGraph.foldingView!
const sourceMaster = sourceView.manager.masterGraph
const targetView = targetGraph.foldingView!
const targetMaster = targetView.manager.masterGraph
// we want the folding states
// to be copied with the master items
copier.copyFoldingStates = true
// we only copy items with "copy me" as tag
const itemsToCopy = graph.nodes.filter((node) => node.tag === 'copy me')
itemsToCopy.concat(graph.edges)
// after a node is copied we collapse it
// if its original is a collapsed group node
const callback = (original: IModelItem, copy: IModelItem): void => {
if (
original instanceof INode &&
copy instanceof INode &&
!sourceView.isExpanded(original)
) {
targetView.collapse(copy)
}
}
// we don't move items after copying
const offset = Point.ORIGIN
copier.copy({
sourceGraph: sourceMaster,
targetGraph: targetMaster,
itemsToCopy: itemsToCopy,
itemOffset: offset,
itemCopiedCallback: callback
})