From 45a9b0e0d75a2442715ff3fc7e335d7648a2c4b1 Mon Sep 17 00:00:00 2001 From: Parth Date: Mon, 31 Mar 2025 15:08:41 +0100 Subject: [PATCH 01/10] add logic to have custom label on vedge --- packages/core/src/graph/graph.ts | 166 ++++++++++++++++++++++++++++--- 1 file changed, 151 insertions(+), 15 deletions(-) diff --git a/packages/core/src/graph/graph.ts b/packages/core/src/graph/graph.ts index c0b835cf57c..de2ced76979 100644 --- a/packages/core/src/graph/graph.ts +++ b/packages/core/src/graph/graph.ts @@ -2747,6 +2747,40 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs } } + private getEdgeDirection(style): 'start' | 'end' | 'both' | 'none' { + const startArrowPath = style?.keyshape?.startArrow?.path; + const endArrowPath = style?.keyshape?.endArrow?.path; + const hasStart = !!startArrowPath && startArrowPath !== ''; + const hasEnd = !!endArrowPath && endArrowPath !== ''; + return hasStart && hasEnd ? 'both' : hasStart ? 'start' : hasEnd ? 'end' : 'none'; + } + + private processEdgeLabels(edgeInfo) { + const labelEntries = Object.entries(edgeInfo.labelCounts.labels); + const totalCount = edgeInfo.labelCounts.total; + const uniqueLabels = labelEntries.filter(([label]) => label !== ''); + const allSameLabel = uniqueLabels.length === 1 && uniqueLabels[0][1] === totalCount; + + edgeInfo.style.label.value = allSameLabel + ? `${uniqueLabels[0][0]} (${totalCount})` + : `(${totalCount})`; + } + + private setArrowDirections(edgeInfo) { + if (!edgeInfo.consistentDirection) { + edgeInfo.style.keyshape.startArrow = null; + edgeInfo.style.keyshape.endArrow = null; + } else { + const { direction } = edgeInfo; + edgeInfo.style.keyshape.startArrow = (direction === 'start' || direction === 'both') + ? edgeInfo.startArrow + : null; + edgeInfo.style.keyshape.endArrow = (direction === 'end' || direction === 'both') + ? edgeInfo.endArrow + : null; + } + } + /** * 收起指定的 combo * @param {string | ICombo} combo combo ID 或 combo item @@ -2821,6 +2855,11 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs return; } let otherEndModel = otherEnd.getModel(); + const edgeModel = edge.getModel(); + const edgeLabel = edgeModel.label || edgeModel.style?.label?.value || ''; + const { style } = edgeModel; + const edgeDirection = this.getEdgeDirection(style); + while (!otherEnd.isVisible()) { const { parentId: otherEndPId, comboId: otherEndCId } = otherEndModel; const otherEndParentId = otherEndPId || otherEndCId; @@ -2843,20 +2882,62 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs isVEdge: true, }; const key = `${vEdgeInfo.source}-${vEdgeInfo.target}`; - if (addedVEdgeMap[key]) { - addedVEdgeMap[key].size += size; - return; - } else { - const inverseKey = `${vEdgeInfo.target}-${vEdgeInfo.source}`; - if (addedVEdgeMap[inverseKey]) { - addedVEdgeMap[inverseKey].size += size; - return; + const inverseKey = `${vEdgeInfo.target}-${vEdgeInfo.source}`; + let currentKey = key; + let adjustedDirection = edgeDirection; + + if (!addedVEdgeMap[key] && addedVEdgeMap[inverseKey]) { + currentKey = inverseKey; + adjustedDirection = edgeDirection === 'start' ? 'end' : + edgeDirection === 'end' ? 'start' : edgeDirection; + } + + const startArrow = edgeModel.style?.keyshape?.endArrow + const endArrow = edgeModel.style?.keyshape?.startArrow + + if (addedVEdgeMap[currentKey]) { + const existing = addedVEdgeMap[currentKey]; + existing.size += size; + existing.labelCounts.total += 1; + existing.labelCounts.labels[edgeLabel] = (existing.labelCounts.labels[edgeLabel] || 0) + 1; + + if (existing.consistentDirection && existing.direction !== adjustedDirection) { + existing.consistentDirection = false; } + } else if (addedVEdgeMap[inverseKey]) { + const existing = addedVEdgeMap[inverseKey]; + existing.size += size; + existing.labelCounts.total += 1; + existing.labelCounts.labels[edgeLabel] = (existing.labelCounts.labels[edgeLabel] || 0) + 1; + + const adjustedInverseDirection = adjustedDirection === 'start' ? 'end' : adjustedDirection === 'end' ? 'start' : adjustedDirection; + if (existing.consistentDirection && existing.direction !== adjustedInverseDirection) { + existing.consistentDirection = false; + } + } else { + addedVEdgeMap[currentKey] = { + ...vEdgeInfo, + labelCounts: { + total: 1, + labels: { [edgeLabel]: 1 } + }, + direction: adjustedDirection, + consistentDirection: true, + startArrow, + endArrow, + style: { + label: { value: '' }, + keyshape: { startArrow, endArrow } + } + }; } - addedVEdgeMap[key] = vEdgeInfo; } }); + Object.values(addedVEdgeMap).forEach(edgeInfo => { + this.processEdgeLabels(edgeInfo); + this.setArrowDirections(edgeInfo); + }); // update the width of the virtual edges, which is the sum of merged actual edges // be attention that the actual edges with same endpoints but different directions will be represented by two different virtual edges this.addItems( @@ -2945,6 +3026,10 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs this.removeItem(edge, false); return; } + const edgeModel = edge.getModel(); + const edgeLabel = edgeModel.label || edgeModel.style?.label?.value || ''; + const { style } = edgeModel; + const edgeDirection = this.getEdgeDirection(style); let otherEndModel = otherEnd.getModel(); // find the nearest visible ancestor @@ -2989,16 +3074,67 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs size } const vedgeId = `${vEdgeInfo.source}-${vEdgeInfo.target}`; - // update the width of the virtual edges, which is the sum of merged actual edges - // be attention that the actual edges with same endpoints but different directions will be represented by two different virtual edges - if (addedVEdgeMap[vedgeId]) { - addedVEdgeMap[vedgeId].size += size; - return; + const inverseVedgeId = `${vEdgeInfo.target}-${vEdgeInfo.source}`; + + let currentKey = vedgeId; + let adjustedDirection = edgeDirection; + + if (!addedVEdgeMap[vedgeId] && addedVEdgeMap[inverseVedgeId]) { + currentKey = inverseVedgeId; + adjustedDirection = edgeDirection === 'start' ? 'end' : + edgeDirection === 'end' ? 'start' : edgeDirection; + } + + const startArrow = edgeModel.style?.keyshape?.endArrow + const endArrow = edgeModel.style?.keyshape?.startArrow + + if (addedVEdgeMap[currentKey]) { + const existing = addedVEdgeMap[currentKey]; + // update the width of the virtual edges, which is the sum of merged actual edges + // be attention that the actual edges with same endpoints but different directions will be represented by two different virtual edges + existing.size += size; + existing.labelCounts.total += 1; + existing.labelCounts.labels[edgeLabel] = (existing.labelCounts.labels[edgeLabel] || 0) + 1; + + if (existing.consistentDirection && existing.direction !== adjustedDirection) { + existing.consistentDirection = false; + } + } else if (addedVEdgeMap[inverseVedgeId]) { + const existing = addedVEdgeMap[inverseVedgeId]; + existing.size += size; + existing.labelCounts.total += 1; + existing.labelCounts.labels[edgeLabel] = (existing.labelCounts.labels[edgeLabel] || 0) + 1; + + const adjustedInverseDirection = adjustedDirection === 'start' ? 'end' : adjustedDirection === 'end' ? 'start' : adjustedDirection; + if (existing.consistentDirection && existing.direction !== adjustedInverseDirection) { + existing.consistentDirection = false; + } + } else { + addedVEdgeMap[currentKey] = { + ...vEdgeInfo, + labelCounts: { + total: 1, + labels: { [edgeLabel]: 1 } + }, + direction: adjustedDirection, + consistentDirection: true, + startArrow, + endArrow, + style: { + label: { value: '' }, + keyshape: { startArrow, endArrow } + } + }; } - addedVEdgeMap[vedgeId] = vEdgeInfo; } } }); + + Object.values(addedVEdgeMap).forEach(edgeInfo => { + this.processEdgeLabels(edgeInfo); + this.setArrowDirections(edgeInfo); + }); + this.addItems( Object.values(addedVEdgeMap).map(edgeInfo => ({ type: 'vedge', model: edgeInfo as EdgeConfig })), false From b8c8554d0ae8e81c5a6702268ef151c27127b552 Mon Sep 17 00:00:00 2001 From: Parth Date: Tue, 1 Apr 2025 00:42:12 +0100 Subject: [PATCH 02/10] move duplicate code to function --- packages/core/src/graph/graph.ts | 162 +++++++++++++------------------ 1 file changed, 65 insertions(+), 97 deletions(-) diff --git a/packages/core/src/graph/graph.ts b/packages/core/src/graph/graph.ts index de2ced76979..1c30de409dd 100644 --- a/packages/core/src/graph/graph.ts +++ b/packages/core/src/graph/graph.ts @@ -2781,6 +2781,65 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs } } + private updateVEdgeMap( addedVEdgeMap, key, inverseKey, vEdgeInfo, + edgeLabel, edgeDirection, size, edgeModel + ) { + let currentKey = key; + let adjustedDirection = edgeDirection; + + if (!addedVEdgeMap[key] && addedVEdgeMap[inverseKey]) { + currentKey = inverseKey; + adjustedDirection = edgeDirection === 'start' ? 'end' : + edgeDirection === 'end' ? 'start' : edgeDirection; + } + + const isInverse = currentKey === inverseKey; + const startArrow = isInverse ? edgeModel.style?.keyshape?.endArrow : edgeModel.style?.keyshape?.startArrow; + const endArrow = isInverse ? edgeModel.style?.keyshape?.startArrow : edgeModel.style?.keyshape?.endArrow; + + if (addedVEdgeMap[currentKey]) { + const existing = addedVEdgeMap[currentKey]; + // update the width of the virtual edges, which is the sum of merged actual edges + // be attention that the actual edges with same endpoints but different directions will be represented by two different virtual edges + existing.size += size; + existing.labelCounts.total += 1; + existing.labelCounts.labels[edgeLabel] = (existing.labelCounts.labels[edgeLabel] || 0) + 1; + + if (existing.consistentDirection && existing.direction !== adjustedDirection) { + existing.consistentDirection = false; + } + } else if (addedVEdgeMap[inverseKey]) { + const existing = addedVEdgeMap[inverseKey]; + // update the width of the virtual edges, which is the sum of merged actual edges + // be attention that the actual edges with same endpoints but different directions will be represented by two different virtual edges + existing.size += size; + existing.labelCounts.total += 1; + existing.labelCounts.labels[edgeLabel] = (existing.labelCounts.labels[edgeLabel] || 0) + 1; + + const adjustedInverseDirection = adjustedDirection === 'start' ? 'end' : adjustedDirection === 'end' ? 'start' : adjustedDirection; + if (existing.consistentDirection && existing.direction !== adjustedInverseDirection) { + existing.consistentDirection = false; + } + } else { + addedVEdgeMap[currentKey] = { + ...vEdgeInfo, + size, + labelCounts: { + total: 1, + labels: { [edgeLabel]: 1 } + }, + direction: adjustedDirection, + consistentDirection: true, + startArrow, + endArrow, + style: { + label: { value: '' }, + keyshape: { startArrow, endArrow } + } + }; + } + } + /** * 收起指定的 combo * @param {string | ICombo} combo combo ID 或 combo item @@ -2883,54 +2942,10 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs }; const key = `${vEdgeInfo.source}-${vEdgeInfo.target}`; const inverseKey = `${vEdgeInfo.target}-${vEdgeInfo.source}`; - let currentKey = key; - let adjustedDirection = edgeDirection; - - if (!addedVEdgeMap[key] && addedVEdgeMap[inverseKey]) { - currentKey = inverseKey; - adjustedDirection = edgeDirection === 'start' ? 'end' : - edgeDirection === 'end' ? 'start' : edgeDirection; - } - const startArrow = edgeModel.style?.keyshape?.endArrow - const endArrow = edgeModel.style?.keyshape?.startArrow - - if (addedVEdgeMap[currentKey]) { - const existing = addedVEdgeMap[currentKey]; - existing.size += size; - existing.labelCounts.total += 1; - existing.labelCounts.labels[edgeLabel] = (existing.labelCounts.labels[edgeLabel] || 0) + 1; - - if (existing.consistentDirection && existing.direction !== adjustedDirection) { - existing.consistentDirection = false; - } - } else if (addedVEdgeMap[inverseKey]) { - const existing = addedVEdgeMap[inverseKey]; - existing.size += size; - existing.labelCounts.total += 1; - existing.labelCounts.labels[edgeLabel] = (existing.labelCounts.labels[edgeLabel] || 0) + 1; - - const adjustedInverseDirection = adjustedDirection === 'start' ? 'end' : adjustedDirection === 'end' ? 'start' : adjustedDirection; - if (existing.consistentDirection && existing.direction !== adjustedInverseDirection) { - existing.consistentDirection = false; - } - } else { - addedVEdgeMap[currentKey] = { - ...vEdgeInfo, - labelCounts: { - total: 1, - labels: { [edgeLabel]: 1 } - }, - direction: adjustedDirection, - consistentDirection: true, - startArrow, - endArrow, - style: { - label: { value: '' }, - keyshape: { startArrow, endArrow } - } - }; - } + this.updateVEdgeMap(addedVEdgeMap, key, inverseKey, vEdgeInfo, + edgeLabel,edgeDirection, size, edgeModel + ); } }); @@ -3076,56 +3091,9 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs const vedgeId = `${vEdgeInfo.source}-${vEdgeInfo.target}`; const inverseVedgeId = `${vEdgeInfo.target}-${vEdgeInfo.source}`; - let currentKey = vedgeId; - let adjustedDirection = edgeDirection; - - if (!addedVEdgeMap[vedgeId] && addedVEdgeMap[inverseVedgeId]) { - currentKey = inverseVedgeId; - adjustedDirection = edgeDirection === 'start' ? 'end' : - edgeDirection === 'end' ? 'start' : edgeDirection; - } - - const startArrow = edgeModel.style?.keyshape?.endArrow - const endArrow = edgeModel.style?.keyshape?.startArrow - - if (addedVEdgeMap[currentKey]) { - const existing = addedVEdgeMap[currentKey]; - // update the width of the virtual edges, which is the sum of merged actual edges - // be attention that the actual edges with same endpoints but different directions will be represented by two different virtual edges - existing.size += size; - existing.labelCounts.total += 1; - existing.labelCounts.labels[edgeLabel] = (existing.labelCounts.labels[edgeLabel] || 0) + 1; - - if (existing.consistentDirection && existing.direction !== adjustedDirection) { - existing.consistentDirection = false; - } - } else if (addedVEdgeMap[inverseVedgeId]) { - const existing = addedVEdgeMap[inverseVedgeId]; - existing.size += size; - existing.labelCounts.total += 1; - existing.labelCounts.labels[edgeLabel] = (existing.labelCounts.labels[edgeLabel] || 0) + 1; - - const adjustedInverseDirection = adjustedDirection === 'start' ? 'end' : adjustedDirection === 'end' ? 'start' : adjustedDirection; - if (existing.consistentDirection && existing.direction !== adjustedInverseDirection) { - existing.consistentDirection = false; - } - } else { - addedVEdgeMap[currentKey] = { - ...vEdgeInfo, - labelCounts: { - total: 1, - labels: { [edgeLabel]: 1 } - }, - direction: adjustedDirection, - consistentDirection: true, - startArrow, - endArrow, - style: { - label: { value: '' }, - keyshape: { startArrow, endArrow } - } - }; - } + this.updateVEdgeMap(addedVEdgeMap, vedgeId, inverseVedgeId, vEdgeInfo, + edgeLabel,edgeDirection, size, edgeModel + ); } } }); From 7397f4682f89ec80f4ce4a71306085ab9d7b60d4 Mon Sep 17 00:00:00 2001 From: Parth Date: Tue, 1 Apr 2025 01:47:55 +0100 Subject: [PATCH 03/10] feedback use only first label --- packages/core/src/graph/graph.ts | 34 +++++++++++++++++++------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/core/src/graph/graph.ts b/packages/core/src/graph/graph.ts index 1c30de409dd..78fcb84b6e8 100644 --- a/packages/core/src/graph/graph.ts +++ b/packages/core/src/graph/graph.ts @@ -2756,13 +2756,11 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs } private processEdgeLabels(edgeInfo) { - const labelEntries = Object.entries(edgeInfo.labelCounts.labels); - const totalCount = edgeInfo.labelCounts.total; - const uniqueLabels = labelEntries.filter(([label]) => label !== ''); - const allSameLabel = uniqueLabels.length === 1 && uniqueLabels[0][1] === totalCount; + const totalCount = edgeInfo.count; + const { allSameLabel, firstLabel } = edgeInfo; - edgeInfo.style.label.value = allSameLabel - ? `${uniqueLabels[0][0]} (${totalCount})` + edgeInfo.style.label.value = allSameLabel && firstLabel !== '' + ? `${firstLabel} (${totalCount})` : `(${totalCount})`; } @@ -2797,13 +2795,22 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs const startArrow = isInverse ? edgeModel.style?.keyshape?.endArrow : edgeModel.style?.keyshape?.startArrow; const endArrow = isInverse ? edgeModel.style?.keyshape?.startArrow : edgeModel.style?.keyshape?.endArrow; + const _processLabel = (existing, label) => { + if (existing.firstLabel === undefined) { + existing.firstLabel = label; + existing.allSameLabel = true; + } else if (existing.allSameLabel && existing.firstLabel !== label) { + existing.allSameLabel = false; + } + }; + if (addedVEdgeMap[currentKey]) { const existing = addedVEdgeMap[currentKey]; // update the width of the virtual edges, which is the sum of merged actual edges // be attention that the actual edges with same endpoints but different directions will be represented by two different virtual edges existing.size += size; - existing.labelCounts.total += 1; - existing.labelCounts.labels[edgeLabel] = (existing.labelCounts.labels[edgeLabel] || 0) + 1; + existing.count += 1; + _processLabel(existing, edgeLabel); if (existing.consistentDirection && existing.direction !== adjustedDirection) { existing.consistentDirection = false; @@ -2813,8 +2820,8 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs // update the width of the virtual edges, which is the sum of merged actual edges // be attention that the actual edges with same endpoints but different directions will be represented by two different virtual edges existing.size += size; - existing.labelCounts.total += 1; - existing.labelCounts.labels[edgeLabel] = (existing.labelCounts.labels[edgeLabel] || 0) + 1; + existing.count += 1; + _processLabel(existing, edgeLabel); const adjustedInverseDirection = adjustedDirection === 'start' ? 'end' : adjustedDirection === 'end' ? 'start' : adjustedDirection; if (existing.consistentDirection && existing.direction !== adjustedInverseDirection) { @@ -2824,10 +2831,9 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs addedVEdgeMap[currentKey] = { ...vEdgeInfo, size, - labelCounts: { - total: 1, - labels: { [edgeLabel]: 1 } - }, + count: 1, + firstLabel: edgeLabel, + allSameLabel: true, direction: adjustedDirection, consistentDirection: true, startArrow, From c48ccf611e8551be77a9ee0966af56f50aed4269 Mon Sep 17 00:00:00 2001 From: Parth Date: Tue, 1 Apr 2025 17:11:16 +0100 Subject: [PATCH 04/10] feedback add feature flag and add test --- packages/core/src/graph/graph.ts | 77 +++++++++--- packages/core/src/interface/graph.ts | 6 +- packages/core/tests/unit/graph/graph-spec.ts | 122 +++++++++++++++++++ 3 files changed, 185 insertions(+), 20 deletions(-) diff --git a/packages/core/src/graph/graph.ts b/packages/core/src/graph/graph.ts index 78fcb84b6e8..1ebf58e7580 100644 --- a/packages/core/src/graph/graph.ts +++ b/packages/core/src/graph/graph.ts @@ -2810,8 +2810,8 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs // be attention that the actual edges with same endpoints but different directions will be represented by two different virtual edges existing.size += size; existing.count += 1; - _processLabel(existing, edgeLabel); - + _processLabel(existing, edgeLabel); + if (existing.consistentDirection && existing.direction !== adjustedDirection) { existing.consistentDirection = false; } @@ -2850,7 +2850,13 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs * 收起指定的 combo * @param {string | ICombo} combo combo ID 或 combo item */ - public collapseCombo(combo: string | ICombo, stack: boolean = true): void { + public collapseCombo(combo: string | ICombo, stack: boolean = true, opts: { + inheritLabelWithDir: boolean, + showCount: boolean + } = { + inheritLabelWithDir: true, + showCount: true + }): void { if (this.destroyed) return; if (isString(combo)) { combo = this.findById(combo) as ICombo; @@ -2949,16 +2955,32 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs const key = `${vEdgeInfo.source}-${vEdgeInfo.target}`; const inverseKey = `${vEdgeInfo.target}-${vEdgeInfo.source}`; - this.updateVEdgeMap(addedVEdgeMap, key, inverseKey, vEdgeInfo, - edgeLabel,edgeDirection, size, edgeModel - ); + if (opts.inheritLabelWithDir && opts.showCount) { + this.updateVEdgeMap(addedVEdgeMap, key, inverseKey, vEdgeInfo, + edgeLabel,edgeDirection, size, edgeModel + ); + } + else { + if (addedVEdgeMap[key]) { + addedVEdgeMap[key].size += size; + return; + } else { + if (addedVEdgeMap[inverseKey]) { + addedVEdgeMap[inverseKey].size += size; + return; + } + } + addedVEdgeMap[key] = vEdgeInfo; + } } }); - Object.values(addedVEdgeMap).forEach(edgeInfo => { - this.processEdgeLabels(edgeInfo); - this.setArrowDirections(edgeInfo); - }); + if (opts.inheritLabelWithDir && opts.showCount) { + Object.values(addedVEdgeMap).forEach(edgeInfo => { + this.processEdgeLabels(edgeInfo); + this.setArrowDirections(edgeInfo); + }); + } // update the width of the virtual edges, which is the sum of merged actual edges // be attention that the actual edges with same endpoints but different directions will be represented by two different virtual edges this.addItems( @@ -2972,7 +2994,13 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs * 展开指定的 combo * @param {string | ICombo} combo combo ID 或 combo item */ - public expandCombo(combo: string | ICombo, stack: boolean = true): void { + public expandCombo(combo: string | ICombo, stack: boolean = true, opts: { + inheritLabelWithDir: boolean, + showCount: boolean + } = { + inheritLabelWithDir: true, + showCount: true + }): void { if (isString(combo)) { combo = this.findById(combo) as ICombo; } @@ -3097,17 +3125,30 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs const vedgeId = `${vEdgeInfo.source}-${vEdgeInfo.target}`; const inverseVedgeId = `${vEdgeInfo.target}-${vEdgeInfo.source}`; - this.updateVEdgeMap(addedVEdgeMap, vedgeId, inverseVedgeId, vEdgeInfo, - edgeLabel,edgeDirection, size, edgeModel - ); + if (opts.inheritLabelWithDir && opts.showCount) { + this.updateVEdgeMap(addedVEdgeMap, vedgeId, inverseVedgeId, vEdgeInfo, + edgeLabel,edgeDirection, size, edgeModel + ); + } + else { + // update the width of the virtual edges, which is the sum of merged actual edges + // be attention that the actual edges with same endpoints but different directions will be represented by two different virtual edges + if (addedVEdgeMap[vedgeId]) { + addedVEdgeMap[vedgeId].size += size; + return; + } + addedVEdgeMap[vedgeId] = vEdgeInfo; + } } } }); - Object.values(addedVEdgeMap).forEach(edgeInfo => { - this.processEdgeLabels(edgeInfo); - this.setArrowDirections(edgeInfo); - }); + if (opts.inheritLabelWithDir && opts.showCount) { + Object.values(addedVEdgeMap).forEach(edgeInfo => { + this.processEdgeLabels(edgeInfo); + this.setArrowDirections(edgeInfo); + }); + } this.addItems( Object.values(addedVEdgeMap).map(edgeInfo => ({ type: 'vedge', model: edgeInfo as EdgeConfig })), diff --git a/packages/core/src/interface/graph.ts b/packages/core/src/interface/graph.ts index 76c8528a80b..c9c89504ca7 100644 --- a/packages/core/src/interface/graph.ts +++ b/packages/core/src/interface/graph.ts @@ -528,13 +528,15 @@ export interface IAbstractGraph extends EventEmitter { * 收起指定的 Combo * @param comboId combo ID 或 combo 实例 */ - collapseCombo: (combo: string | ICombo, stack?: boolean) => void; + // collapseCombo: (combo: string | ICombo, stack?: boolean) => void; + collapseCombo: (combo: string | ICombo, stack?: boolean, opts?: {inheritLabelWithDir: boolean, showCount: boolean}) => void; /** * 展开指定的 Combo * @param combo combo ID 或 combo 实例 */ - expandCombo: (combo: string | ICombo, stack?: boolean) => void; + // expandCombo: (combo: string | ICombo, stack?: boolean) => void; + expandCombo: (combo: string | ICombo, stack?: boolean, opts?: { inheritLabelWithDir: boolean, showCount: boolean }) => void; /** * 展开或收缩指定的 Combo diff --git a/packages/core/tests/unit/graph/graph-spec.ts b/packages/core/tests/unit/graph/graph-spec.ts index 5a181f0233e..44ab5867077 100644 --- a/packages/core/tests/unit/graph/graph-spec.ts +++ b/packages/core/tests/unit/graph/graph-spec.ts @@ -1770,3 +1770,125 @@ describe('states', () => { expect(savedGraph.combos[1].states).toEqual({}); }); }); + +describe.only('Custom label and direction on VEdge', () => { + let graph: Graph; + let combo: ICombo; + + beforeEach(() => { + graph = new Graph({ + container: div, + height: 500, + width: 500, + }); + + const comboId = 'testCombo'; + graph.addItem('combo', { id: comboId }); + combo = graph.findById(comboId) as ICombo; + graph.addItem('node', { id: 'node1', comboId, x: 50, y: 50 }); + graph.addItem('node', { id: 'node2', comboId, x: 150, y: 150 }); + graph.addItem('node', { id: 'externalNode', x: 250, y: 50 }); + }); + + afterEach(() => { + if (!graph.destroyed) graph.destroy(); + }); + + it('should display combined label with count and direction for edges having identical label and direction', () => { + graph.addItem('edge', { + source: 'node1', + target: 'externalNode', + label: 'A', + style: { keyshape: { startArrow: true }} + }); + graph.addItem('edge', { + source: 'node2', + target: 'externalNode', + label: 'A', + style: { keyshape: { startArrow: true }} + }); + + graph.collapseCombo(combo); + + const vEdges = graph.get('vedges'); + expect(vEdges.length).toBe(1); + const vEdge = vEdges[0].getModel(); + + expect(vEdge.style.label.value).toBe('A (2)'); + + expect(vEdge.startArrow).toBe(true); + expect(vEdge.endArrow).toBeUndefined; + }); + + it('should display only count and direction on VEdge when combining edges having mixed labels and identical direction', () => { + graph.addItem('edge', { + source: 'node1', + target: 'externalNode', + label: 'A', + style: { keyshape: { endArrow: true }} + }); + graph.addItem('edge', { + source: 'node2', + target: 'externalNode', + label: 'B', + style: { keyshape: { endArrow: true }} + }); + + graph.collapseCombo(combo); + + const vEdges = graph.get('vedges'); + expect(vEdges.length).toBe(1); + const vEdge = vEdges[0].getModel(); + expect(vEdge.style.label.value).toBe('(2)'); + expect(vEdge.endArrow).toBe(true); + expect(vEdge.startArrow).toBeUndefined; + }); + + it('should display combined label with count and no direction for edges having identical label but mix in direction', () => { + graph.addItem('edge', { + source: 'node1', + target: 'externalNode', + label: 'A', + style: { keyshape: { endArrow: true }} + }); + graph.addItem('edge', { + source: 'externalNode', + target: 'node2', + label: 'A', + style: { keyshape: { startArrow: true }} + }); + + graph.collapseCombo(combo); + + const vEdges = graph.get('vedges'); + expect(vEdges.length).toBe(1); + const vEdge = vEdges[0].getModel(); + expect(vEdge.style.label.value).toBe('A (2)'); + expect(vEdge.startArrow).toBeUndefined; + expect(vEdge.endArrow).toBeUndefined; + }); + + it('should display only count and no direction for edges having mix label and mix direction', () => { + graph.addItem('edge', { + source: 'node1', + target: 'externalNode', + label: 'A', + style: { keyshape: { endArrow: true }} + }); + graph.addItem('edge', { + source: 'externalNode', + target: 'node2', + label: 'B', + style: { keyshape: { startArrow: true }} + }); + + graph.collapseCombo(combo); + + const vEdges = graph.get('vedges'); + expect(vEdges.length).toBe(1); + const vEdge = vEdges[0].getModel(); + expect(vEdge.style.label.value).toBe('(2)'); + expect(vEdge.startArrow).toBeUndefined; + expect(vEdge.endArrow).toBeUndefined; + }); +}); \ No newline at end of file From 8407752447199866afdf3c4783ac737ee1c3359a Mon Sep 17 00:00:00 2001 From: Parth Date: Tue, 1 Apr 2025 21:39:24 +0100 Subject: [PATCH 05/10] clean up --- packages/core/tests/unit/graph/graph-spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/tests/unit/graph/graph-spec.ts b/packages/core/tests/unit/graph/graph-spec.ts index 44ab5867077..6e715fa28a1 100644 --- a/packages/core/tests/unit/graph/graph-spec.ts +++ b/packages/core/tests/unit/graph/graph-spec.ts @@ -1771,7 +1771,7 @@ describe('states', () => { }); }); -describe.only('Custom label and direction on VEdge', () => { +describe('Custom label and direction on VEdge', () => { let graph: Graph; let combo: ICombo; From 5a831f3bf1b0125c431b8d4d0c86ffbc29da2d68 Mon Sep 17 00:00:00 2001 From: Parth Date: Fri, 4 Apr 2025 00:11:32 +0100 Subject: [PATCH 06/10] feedback change obj property name --- packages/core/src/graph/graph.ts | 40 +++++++++++++++++----------- packages/core/src/interface/graph.ts | 4 +-- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/packages/core/src/graph/graph.ts b/packages/core/src/graph/graph.ts index 1ebf58e7580..f70b08b188e 100644 --- a/packages/core/src/graph/graph.ts +++ b/packages/core/src/graph/graph.ts @@ -2755,13 +2755,13 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs return hasStart && hasEnd ? 'both' : hasStart ? 'start' : hasEnd ? 'end' : 'none'; } - private processEdgeLabels(edgeInfo) { - const totalCount = edgeInfo.count; - const { allSameLabel, firstLabel } = edgeInfo; + private processEdgeLabels(edgeInfo, opts) { + const { showCount, inheritLabel } = opts; + const { count, allSameLabel, firstLabel } = edgeInfo; - edgeInfo.style.label.value = allSameLabel && firstLabel !== '' - ? `${firstLabel} (${totalCount})` - : `(${totalCount})`; + edgeInfo.style.label.value = (inheritLabel && allSameLabel && firstLabel !== '') + ? `${firstLabel}${showCount ? ` (${count})` : ''}` + : (showCount ? `(${count})` : ''); } private setArrowDirections(edgeInfo) { @@ -2849,12 +2849,16 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs /** * 收起指定的 combo * @param {string | ICombo} combo combo ID 或 combo item + * @param {object} [opts] - Optional parameter for the collapse operation. + * @param {boolean} [opts.inheritLabel=true] - If true, the virtual edge inherits the label from connected edges + * only if all connected edges have identical labels. Otherwise, the vedge will have a blank label. + * @param {boolean} [opts.showCount=true] - If true, displays the count of edges merged to form a virtual edge. */ public collapseCombo(combo: string | ICombo, stack: boolean = true, opts: { - inheritLabelWithDir: boolean, + inheritLabel: boolean, showCount: boolean } = { - inheritLabelWithDir: true, + inheritLabel: true, showCount: true }): void { if (this.destroyed) return; @@ -2955,7 +2959,7 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs const key = `${vEdgeInfo.source}-${vEdgeInfo.target}`; const inverseKey = `${vEdgeInfo.target}-${vEdgeInfo.source}`; - if (opts.inheritLabelWithDir && opts.showCount) { + if (opts.inheritLabel || opts.showCount) { this.updateVEdgeMap(addedVEdgeMap, key, inverseKey, vEdgeInfo, edgeLabel,edgeDirection, size, edgeModel ); @@ -2975,9 +2979,9 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs } }); - if (opts.inheritLabelWithDir && opts.showCount) { + if (opts.inheritLabel || opts.showCount) { Object.values(addedVEdgeMap).forEach(edgeInfo => { - this.processEdgeLabels(edgeInfo); + this.processEdgeLabels(edgeInfo, opts); this.setArrowDirections(edgeInfo); }); } @@ -2993,12 +2997,16 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs /** * 展开指定的 combo * @param {string | ICombo} combo combo ID 或 combo item + * @param {object} [opts] - Optional parameter for the collapse operation. + * @param {boolean} [opts.inheritLabel=true] - If true, the virtual edge inherits the label from connected edges + * only if all connected edges have identical labels. Otherwise, the vedge will have a blank label. + * @param {boolean} [opts.showCount=true] - If true, displays the count of edges merged to form a virtual edge. */ public expandCombo(combo: string | ICombo, stack: boolean = true, opts: { - inheritLabelWithDir: boolean, + inheritLabel: boolean, showCount: boolean } = { - inheritLabelWithDir: true, + inheritLabel: true, showCount: true }): void { if (isString(combo)) { @@ -3125,7 +3133,7 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs const vedgeId = `${vEdgeInfo.source}-${vEdgeInfo.target}`; const inverseVedgeId = `${vEdgeInfo.target}-${vEdgeInfo.source}`; - if (opts.inheritLabelWithDir && opts.showCount) { + if (opts.inheritLabel || opts.showCount) { this.updateVEdgeMap(addedVEdgeMap, vedgeId, inverseVedgeId, vEdgeInfo, edgeLabel,edgeDirection, size, edgeModel ); @@ -3143,9 +3151,9 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs } }); - if (opts.inheritLabelWithDir && opts.showCount) { + if (opts.inheritLabel || opts.showCount) { Object.values(addedVEdgeMap).forEach(edgeInfo => { - this.processEdgeLabels(edgeInfo); + this.processEdgeLabels(edgeInfo, opts); this.setArrowDirections(edgeInfo); }); } diff --git a/packages/core/src/interface/graph.ts b/packages/core/src/interface/graph.ts index c9c89504ca7..d56aa6fca55 100644 --- a/packages/core/src/interface/graph.ts +++ b/packages/core/src/interface/graph.ts @@ -529,14 +529,14 @@ export interface IAbstractGraph extends EventEmitter { * @param comboId combo ID 或 combo 实例 */ // collapseCombo: (combo: string | ICombo, stack?: boolean) => void; - collapseCombo: (combo: string | ICombo, stack?: boolean, opts?: {inheritLabelWithDir: boolean, showCount: boolean}) => void; + collapseCombo: (combo: string | ICombo, stack?: boolean, opts?: {inheritLabel: boolean, showCount: boolean}) => void; /** * 展开指定的 Combo * @param combo combo ID 或 combo 实例 */ // expandCombo: (combo: string | ICombo, stack?: boolean) => void; - expandCombo: (combo: string | ICombo, stack?: boolean, opts?: { inheritLabelWithDir: boolean, showCount: boolean }) => void; + expandCombo: (combo: string | ICombo, stack?: boolean, opts?: { inheritLabel: boolean, showCount: boolean }) => void; /** * 展开或收缩指定的 Combo From 37ba42f8e5a7fcc1b3915ce164848642d91d5a6f Mon Sep 17 00:00:00 2001 From: Parth Date: Fri, 4 Apr 2025 09:35:59 +0100 Subject: [PATCH 07/10] feedback cosmetic changes --- packages/core/src/graph/graph.ts | 30 +++++++++----------- packages/core/tests/unit/graph/graph-spec.ts | 8 +++--- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/packages/core/src/graph/graph.ts b/packages/core/src/graph/graph.ts index f70b08b188e..d2afde84996 100644 --- a/packages/core/src/graph/graph.ts +++ b/packages/core/src/graph/graph.ts @@ -2858,8 +2858,8 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs inheritLabel: boolean, showCount: boolean } = { - inheritLabel: true, - showCount: true + inheritLabel: false, + showCount: false }): void { if (this.destroyed) return; if (isString(combo)) { @@ -2930,10 +2930,6 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs return; } let otherEndModel = otherEnd.getModel(); - const edgeModel = edge.getModel(); - const edgeLabel = edgeModel.label || edgeModel.style?.label?.value || ''; - const { style } = edgeModel; - const edgeDirection = this.getEdgeDirection(style); while (!otherEnd.isVisible()) { const { parentId: otherEndPId, comboId: otherEndCId } = otherEndModel; @@ -2960,11 +2956,14 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs const inverseKey = `${vEdgeInfo.target}-${vEdgeInfo.source}`; if (opts.inheritLabel || opts.showCount) { + const edgeModel = edge.getModel(); + const edgeLabel = edgeModel.label || edgeModel.style?.label?.value || ''; + const { style } = edgeModel; + const edgeDirection = this.getEdgeDirection(style); this.updateVEdgeMap(addedVEdgeMap, key, inverseKey, vEdgeInfo, edgeLabel,edgeDirection, size, edgeModel ); - } - else { + } else { if (addedVEdgeMap[key]) { addedVEdgeMap[key].size += size; return; @@ -3006,8 +3005,8 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs inheritLabel: boolean, showCount: boolean } = { - inheritLabel: true, - showCount: true + inheritLabel: false, + showCount: false }): void { if (isString(combo)) { combo = this.findById(combo) as ICombo; @@ -3083,10 +3082,6 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs this.removeItem(edge, false); return; } - const edgeModel = edge.getModel(); - const edgeLabel = edgeModel.label || edgeModel.style?.label?.value || ''; - const { style } = edgeModel; - const edgeDirection = this.getEdgeDirection(style); let otherEndModel = otherEnd.getModel(); // find the nearest visible ancestor @@ -3134,11 +3129,14 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs const inverseVedgeId = `${vEdgeInfo.target}-${vEdgeInfo.source}`; if (opts.inheritLabel || opts.showCount) { + const edgeModel = edge.getModel(); + const edgeLabel = edgeModel.label || edgeModel.style?.label?.value || ''; + const { style } = edgeModel; + const edgeDirection = this.getEdgeDirection(style); this.updateVEdgeMap(addedVEdgeMap, vedgeId, inverseVedgeId, vEdgeInfo, edgeLabel,edgeDirection, size, edgeModel ); - } - else { + } else { // update the width of the virtual edges, which is the sum of merged actual edges // be attention that the actual edges with same endpoints but different directions will be represented by two different virtual edges if (addedVEdgeMap[vedgeId]) { diff --git a/packages/core/tests/unit/graph/graph-spec.ts b/packages/core/tests/unit/graph/graph-spec.ts index 6e715fa28a1..af9b40ce240 100644 --- a/packages/core/tests/unit/graph/graph-spec.ts +++ b/packages/core/tests/unit/graph/graph-spec.ts @@ -1808,7 +1808,7 @@ describe('Custom label and direction on VEdge', () => { style: { keyshape: { startArrow: true }} }); - graph.collapseCombo(combo); + graph.collapseCombo(combo, undefined, {inheritLabel:true, showCount:true},); const vEdges = graph.get('vedges'); expect(vEdges.length).toBe(1); @@ -1834,7 +1834,7 @@ describe('Custom label and direction on VEdge', () => { style: { keyshape: { endArrow: true }} }); - graph.collapseCombo(combo); + graph.collapseCombo(combo, undefined, {inheritLabel:true, showCount:true},); const vEdges = graph.get('vedges'); expect(vEdges.length).toBe(1); @@ -1858,7 +1858,7 @@ describe('Custom label and direction on VEdge', () => { style: { keyshape: { startArrow: true }} }); - graph.collapseCombo(combo); + graph.collapseCombo(combo, undefined, {inheritLabel:true, showCount:true},); const vEdges = graph.get('vedges'); expect(vEdges.length).toBe(1); @@ -1882,7 +1882,7 @@ describe('Custom label and direction on VEdge', () => { style: { keyshape: { startArrow: true }} }); - graph.collapseCombo(combo); + graph.collapseCombo(combo, undefined, {inheritLabel:true, showCount:true},); const vEdges = graph.get('vedges'); expect(vEdges.length).toBe(1); From bf006e445fa0b494ebe820f525f5a9a2e1e1d1c4 Mon Sep 17 00:00:00 2001 From: Parth Date: Fri, 4 Apr 2025 11:53:01 +0100 Subject: [PATCH 08/10] update jsdocs --- packages/core/src/graph/graph.ts | 14 ++++++++------ packages/core/src/interface/graph.ts | 10 ++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/core/src/graph/graph.ts b/packages/core/src/graph/graph.ts index d2afde84996..529a7b17cfe 100644 --- a/packages/core/src/graph/graph.ts +++ b/packages/core/src/graph/graph.ts @@ -2849,10 +2849,11 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs /** * 收起指定的 combo * @param {string | ICombo} combo combo ID 或 combo item - * @param {object} [opts] - Optional parameter for the collapse operation. - * @param {boolean} [opts.inheritLabel=true] - If true, the virtual edge inherits the label from connected edges + * @param {boolean} [stack] Default is true. If true, the collase operation is recorded in the stack. + * @param {object} [opts] Optional parameter for the collapse operation. + * @param {boolean} [opts.inheritLabel=false] Default is false. If true, the virtual edge inherits the label from connected edges * only if all connected edges have identical labels. Otherwise, the vedge will have a blank label. - * @param {boolean} [opts.showCount=true] - If true, displays the count of edges merged to form a virtual edge. + * @param {boolean} [opts.showCount=false] Default is false. If true, displays the count of edges merged to form a virtual edge. */ public collapseCombo(combo: string | ICombo, stack: boolean = true, opts: { inheritLabel: boolean, @@ -2996,10 +2997,11 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs /** * 展开指定的 combo * @param {string | ICombo} combo combo ID 或 combo item - * @param {object} [opts] - Optional parameter for the collapse operation. - * @param {boolean} [opts.inheritLabel=true] - If true, the virtual edge inherits the label from connected edges + * @param {boolean} [stack] Default is true. If true, the expand operation is recorded in the stack. + * @param {object} [opts] Optional parameter for the collapse operation. + * @param {boolean} [opts.inheritLabel=false] Default is false. If true, the virtual edge inherits the label from connected edges * only if all connected edges have identical labels. Otherwise, the vedge will have a blank label. - * @param {boolean} [opts.showCount=true] - If true, displays the count of edges merged to form a virtual edge. + * @param {boolean} [opts.showCount=false] Default is false. If true, displays the count of edges merged to form a virtual edge. */ public expandCombo(combo: string | ICombo, stack: boolean = true, opts: { inheritLabel: boolean, diff --git a/packages/core/src/interface/graph.ts b/packages/core/src/interface/graph.ts index d56aa6fca55..d15893fcf62 100644 --- a/packages/core/src/interface/graph.ts +++ b/packages/core/src/interface/graph.ts @@ -527,6 +527,11 @@ export interface IAbstractGraph extends EventEmitter { /** * 收起指定的 Combo * @param comboId combo ID 或 combo 实例 + * @param {boolean} [stack] Default is true. If true, the collase operation is recorded in the stack. + * @param {object} [opts] Optional parameter for the collapse operation. + * @param {boolean} [opts.inheritLabel=false] Default is false. If true, the virtual edge inherits the label from connected edges + * only if all connected edges have identical labels. Otherwise, the vedge will have a blank label. + * @param {boolean} [opts.showCount=false] Default is false. If true, displays the count of edges merged to form a virtual edge. */ // collapseCombo: (combo: string | ICombo, stack?: boolean) => void; collapseCombo: (combo: string | ICombo, stack?: boolean, opts?: {inheritLabel: boolean, showCount: boolean}) => void; @@ -534,6 +539,11 @@ export interface IAbstractGraph extends EventEmitter { /** * 展开指定的 Combo * @param combo combo ID 或 combo 实例 + * @param {boolean} [stack] Default is true. If true, the expand operation is recorded in the stack. + * @param {object} [opts] Optional parameter for the collapse operation. + * @param {boolean} [opts.inheritLabel=false] Default is false. If true, the virtual edge inherits the label from connected edges + * only if all connected edges have identical labels. Otherwise, the vedge will have a blank label. + * @param {boolean} [opts.showCount=false] Default is false. If true, displays the count of edges merged to form a virtual edge. */ // expandCombo: (combo: string | ICombo, stack?: boolean) => void; expandCombo: (combo: string | ICombo, stack?: boolean, opts?: { inheritLabel: boolean, showCount: boolean }) => void; From a510e06b888949158dd63a4707205958ed4fc8c8 Mon Sep 17 00:00:00 2001 From: Parth Date: Mon, 7 Apr 2025 09:57:07 +0100 Subject: [PATCH 09/10] Update docs and add support in few other places --- packages/core/src/graph/graph.ts | 12 +++++++++--- packages/core/src/interface/graph.ts | 4 +--- packages/site/docs/api/graphFunc/combo.en.md | 6 ++++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/core/src/graph/graph.ts b/packages/core/src/graph/graph.ts index 529a7b17cfe..89fdbc98239 100644 --- a/packages/core/src/graph/graph.ts +++ b/packages/core/src/graph/graph.ts @@ -3165,7 +3165,13 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs this.emit('aftercollapseexpandcombo', { action: 'expand', item: combo }); } - public collapseExpandCombo(combo: string | ICombo, stack: boolean = true) { + public collapseExpandCombo(combo: string | ICombo, stack: boolean = true, opts: { + inheritLabel: boolean, + showCount: boolean + } = { + inheritLabel: true, + showCount: true + }) { if (isString(combo)) { combo = this.findById(combo) as ICombo; } @@ -3187,9 +3193,9 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs const collapsed = comboModel.collapsed; // 该群组已经处于收起状态,需要展开 if (collapsed) { - this.expandCombo(combo, stack); + this.expandCombo(combo, stack, opts); } else { - this.collapseCombo(combo, stack); + this.collapseCombo(combo, stack, opts); } this.updateCombo(combo); } diff --git a/packages/core/src/interface/graph.ts b/packages/core/src/interface/graph.ts index d15893fcf62..c1441c037d1 100644 --- a/packages/core/src/interface/graph.ts +++ b/packages/core/src/interface/graph.ts @@ -533,7 +533,6 @@ export interface IAbstractGraph extends EventEmitter { * only if all connected edges have identical labels. Otherwise, the vedge will have a blank label. * @param {boolean} [opts.showCount=false] Default is false. If true, displays the count of edges merged to form a virtual edge. */ - // collapseCombo: (combo: string | ICombo, stack?: boolean) => void; collapseCombo: (combo: string | ICombo, stack?: boolean, opts?: {inheritLabel: boolean, showCount: boolean}) => void; /** @@ -545,14 +544,13 @@ export interface IAbstractGraph extends EventEmitter { * only if all connected edges have identical labels. Otherwise, the vedge will have a blank label. * @param {boolean} [opts.showCount=false] Default is false. If true, displays the count of edges merged to form a virtual edge. */ - // expandCombo: (combo: string | ICombo, stack?: boolean) => void; expandCombo: (combo: string | ICombo, stack?: boolean, opts?: { inheritLabel: boolean, showCount: boolean }) => void; /** * 展开或收缩指定的 Combo * @param comboId combo ID 或 combo 实例 */ - collapseExpandCombo: (combo: string | ICombo, stack?: boolean) => void; + collapseExpandCombo: (combo: string | ICombo, stack?: boolean, opts?: { inheritLabel: boolean, showCount: boolean }) => void; /** * 根据节点的 bbox 更新所有 combos 的绘制,包括 combos 的位置和范围 diff --git a/packages/site/docs/api/graphFunc/combo.en.md b/packages/site/docs/api/graphFunc/combo.en.md index 8bd153ce13c..9180bde11b3 100644 --- a/packages/site/docs/api/graphFunc/combo.en.md +++ b/packages/site/docs/api/graphFunc/combo.en.md @@ -99,6 +99,8 @@ Collapse a Combo. | Name | Type | Required | Description | | ----- | --------------- | -------- | ----------------------------------------------------- | | combo | string / ICombo | true | The ID of the combo or the combo item to be collapsed | +| stack | boolean | false | Whether to push this operation in the undo & redo stack. | +| opts | object | false | Customize VEdge: `{ inheritLabel: boolean, showCount: boolean }`. If `inheritLabel` is `true` and all edges forming a VEdge have identical labels/directions, the same label/direction is inherited; otherwise, a blank label and no direction appear. If `showCount` is `true`, displays the count of edges merged into the VEdge as a label. | **Usage** @@ -115,6 +117,8 @@ Expand a Combo. | Name | Type | Required | Description | | ----- | --------------- | -------- | ---------------------------------------------------- | | combo | string / ICombo | true | The ID of the combo or the combo item to be expanded | +| stack | boolean | false | Whether to push this operation in the undo & redo stack. | +| opts | object | false | Customize VEdge: `{ inheritLabel: boolean, showCount: boolean }`. If `inheritLabel` is `true` and all edges forming a VEdge have identical labels/directions, the same label/direction is inherited; otherwise, a blank label and no direction appear. If `showCount` is `true`, displays the count of edges merged into the VEdge as a label. | **Usage** @@ -131,6 +135,8 @@ Expand the `combo` if it is collapsed. Collapse the `combo` if it is expanded. | Name | Type | Required | Description | | --- | --- | --- | --- | | combo | string / ICombo | true | The ID of the combo or the combo item to be collapsed or expanded | +| stack | boolean | false | Whether to push this operation in the undo & redo stack. | +| opts | object | false | Customize VEdge: `{ inheritLabel: boolean, showCount: boolean }`. If `inheritLabel` is `true` and all edges forming a VEdge have identical labels/directions, the same label/direction is inherited; otherwise, a blank label and no direction appear. If `showCount` is `true`, displays the count of edges merged into the VEdge as a label. | **Usage** From b191207f80ce04202c33c34dd8e98dca15081adb Mon Sep 17 00:00:00 2001 From: Parth Date: Mon, 7 Apr 2025 13:05:05 +0100 Subject: [PATCH 10/10] typo --- packages/core/src/graph/graph.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/graph/graph.ts b/packages/core/src/graph/graph.ts index 89fdbc98239..3331032fc87 100644 --- a/packages/core/src/graph/graph.ts +++ b/packages/core/src/graph/graph.ts @@ -3169,8 +3169,8 @@ export default abstract class AbstractGraph extends EventEmitter implements IAbs inheritLabel: boolean, showCount: boolean } = { - inheritLabel: true, - showCount: true + inheritLabel: false, + showCount: false }) { if (isString(combo)) { combo = this.findById(combo) as ICombo;