Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dia.Graph): add transferCellEmbeds() and transferCellConnectedLinks() #2752

Merged
merged 10 commits into from
Oct 23, 2024
35 changes: 35 additions & 0 deletions packages/joint-core/src/dia/Graph.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,41 @@ export const Graph = Model.extend({
this.get('cells').remove(cell, { silent: true });
},

transferCellHierarchy: function(sourceCell, targetCell) {

// Embed children of the source cell in the target cell.
const children = sourceCell.getEmbeddedCells();
if (children.length > 0) {
sourceCell.unembed(children);
targetCell.embed(children);
}

// Embed the target cell in the parent of the source cell, if any.
const parent = sourceCell.getParentCell();
if (parent) {
parent.unembed(sourceCell);
parent.embed(targetCell);
}

return this;
},

transferCellLinks: function(sourceCell, targetCell) {

// Reconnect all the links connected to the old cell to the new cell.
const connectedLinks = this.getConnectedLinks(sourceCell);
connectedLinks.forEach((link) => {

if (link.getSourceCell() === sourceCell) {
MartinKanera marked this conversation as resolved.
Show resolved Hide resolved
link.prop(['source', 'id'], targetCell.id);
} else {
link.prop(['target', 'id'], targetCell.id);
}
});

return this;
},

// Get a cell by `id`.
getCell: function(id) {

Expand Down
124 changes: 124 additions & 0 deletions packages/joint-core/test/jointjs/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -1546,4 +1546,128 @@ QUnit.module('graph', function(hooks) {
assert.notOk(graph.hasActiveBatch());
});
});

QUnit.module('graph.transferCellHierarchy()', function() {

QUnit.test('should transfer hierarchy of elements', function(assert) {

const topLevelElement = new joint.shapes.standard.Rectangle();
const originalElement = new joint.shapes.standard.Rectangle();
const child = new joint.shapes.standard.Rectangle();
const replacementElement = new joint.shapes.standard.Rectangle();

topLevelElement.embed(originalElement);
originalElement.embed(child);

this.graph.addCells([topLevelElement, originalElement, child, replacementElement]);
this.graph.transferCellHierarchy(originalElement, replacementElement);

assert.equal(replacementElement.getParentCell(), topLevelElement);
assert.equal(replacementElement.getEmbeddedCells()[0], child);
});

QUnit.test('should transfer hierarchy of links', function(assert) {

const parent = new joint.shapes.standard.Rectangle();
const originalLink = new joint.shapes.standard.Link();
const replacementLink = new joint.shapes.standard.Link();

parent.embed(originalLink);

this.graph.addCells([parent, originalLink, replacementLink]);
this.graph.transferCellHierarchy(originalLink, replacementLink);

assert.equal(replacementLink.getParentCell(), parent);
});

QUnit.test('should work when transferring hierarchy from a link to an element', function(assert) {

const parent = new joint.shapes.standard.Rectangle();
const link = new joint.shapes.standard.Link();
const element = new joint.shapes.standard.Rectangle();

parent.embed(link);

this.graph.addCells([parent, link, element]);
this.graph.transferCellHierarchy(link, element);

assert.equal(element.getParentCell(), parent);
});

QUnit.test('should work when transferring hierarchy from an element to a link', function(assert) {

const parent = new joint.shapes.standard.Rectangle();
const link = new joint.shapes.standard.Link();
const child = new joint.shapes.standard.Rectangle();
const element = new joint.shapes.standard.Rectangle();

element.embed(child);
parent.embed(element);

this.graph.addCells([parent, link, child, element]);
this.graph.transferCellHierarchy(element, link);

assert.equal(link.getParentCell(), parent);
assert.equal(link.getEmbeddedCells()[0], child);
});
});

QUnit.module('graph.transferCellLinks()', function() {

QUnit.test('should transfer links of an element', function(assert) {

const originalElement = new joint.shapes.standard.Rectangle();
const link1 = new joint.shapes.standard.Link({ source: { id: originalElement.id }});
const link2 = new joint.shapes.standard.Link({ target: { id: originalElement.id }});
const replacementElement = new joint.shapes.standard.Rectangle();

this.graph.addCells([originalElement, link1, link2]);
this.graph.transferCellLinks(originalElement, replacementElement);

assert.equal(link1.source().id, replacementElement.id);
assert.equal(link2.target().id, replacementElement.id);
});

QUnit.test('should transfer links of a link', function(assert) {

const originalLink = new joint.shapes.standard.Link();
const link1 = new joint.shapes.standard.Link({ source: { id: originalLink.id }});
const link2 = new joint.shapes.standard.Link({ target: { id: originalLink.id }});
const replacementLink = new joint.shapes.standard.Link();

this.graph.addCells([originalLink, link1, link2]);
this.graph.transferCellLinks(originalLink, replacementLink);

assert.equal(link1.source().id, replacementLink.id);
assert.equal(link2.target().id, replacementLink.id);
});

QUnit.test('should work when transferring links from a link to an element', function(assert) {

const originalLink = new joint.shapes.standard.Link();
const link1 = new joint.shapes.standard.Link({ source: { id: originalLink.id }});
const link2 = new joint.shapes.standard.Link({ target: { id: originalLink.id }});
const element = new joint.shapes.standard.Rectangle();

this.graph.addCells([originalLink, link1, link2, element]);
this.graph.transferCellLinks(originalLink, element);

assert.equal(link1.source().id, element.id);
assert.equal(link2.target().id, element.id);
});

QUnit.test('should work when transferring links from an element to a link', function(assert) {

const originalElement = new joint.shapes.standard.Rectangle();
const link1 = new joint.shapes.standard.Link({ source: { id: originalElement.id }});
const link2 = new joint.shapes.standard.Link({ target: { id: originalElement.id }});
const replacementLink = new joint.shapes.standard.Link();

this.graph.addCells([originalElement, link1, link2, replacementLink]);
this.graph.transferCellLinks(originalElement, replacementLink);

assert.equal(link1.source().id, replacementLink.id);
assert.equal(link2.target().id, replacementLink.id);
});
});
});
4 changes: 4 additions & 0 deletions packages/joint-core/types/joint.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,10 @@ export namespace dia {

removeCells(cells: Cell[], opt?: Cell.DisconnectableOptions): this;

transferCellHierarchy(sourceCell: Cell, targetCell: Cell): this;

transferCellLinks(sourceCell: Cell, targetCell: Cell): this;

resize(width: number, height: number, opt?: S): this;

resizeCells(width: number, height: number, cells: Cell[], opt?: S): this;
Expand Down
Loading