From 26e56014514a2870e20e8f66881359d21407dc4b Mon Sep 17 00:00:00 2001 From: Yanyan-Wang Date: Thu, 9 Apr 2020 10:49:55 +0800 Subject: [PATCH] feat: update combo tree structure for moving subtree. --- src/graph/graph.ts | 15 +++++++++----- src/interface/item.ts | 3 ++- src/item/item.ts | 4 ++-- src/item/node.ts | 9 ++++---- src/util/graphic.ts | 25 +++++++++++++++++++++-- stories/Combo/component/default-combo.tsx | 16 ++++++++------- 6 files changed, 50 insertions(+), 22 deletions(-) diff --git a/src/graph/graph.ts b/src/graph/graph.ts index c0f02185bb..937b543cd8 100644 --- a/src/graph/graph.ts +++ b/src/graph/graph.ts @@ -864,8 +864,7 @@ export default class Graph extends EventEmitter implements IGraph { }); // const comboGroup = this.get('comboGroup') // comboGroup && comboGroup.sort(); - } - else if (type === 'node' && isString(model.comboId) && comboTrees) { + } else if (type === 'node' && isString(model.comboId) && comboTrees) { const parentCombo = this.findById(model.comboId as string); if (!parentCombo || parentCombo.getType() !== 'combo') { console.warn(`The combo ${model.comboId} for the node ${model.id} does not exist, please add the combo first.`); @@ -1243,15 +1242,21 @@ export default class Graph extends EventEmitter implements IGraph { /** * 更新树结构,例如移动子树等 - * @param {String | Item} item 需要被更新的 Combo 或 节点 id + * @param {String | INode | ICombo} item 需要被更新的 Combo 或 节点 id * @param {string | undefined} parentId 新的父 combo id,undefined 代表没有父 combo */ public updateComboTree(item: String | INode | ICombo, parentId: String | undefined) { const self = this; + let uItem: INode | ICombo; if (isString(item)) { - item = self.findById(item) as INode | ICombo; + uItem = self.findById(item) as INode | ICombo; + } else { + uItem = item as INode | ICombo; } - self.removeItem(item as INode | ICombo); + + const newComboTrees = reconstructTree(this.get('comboTrees'), uItem.getModel().id, parentId); + this.set('comboTrees', newComboTrees); + this.updateCombos(); } /** diff --git a/src/interface/item.ts b/src/interface/item.ts index 07548f692f..042e8b3325 100644 --- a/src/interface/item.ts +++ b/src/interface/item.ts @@ -13,6 +13,7 @@ import { ShapeStyle, Indexable, ComboConfig, + ITEM_TYPE, } from '../types'; // item 的配置项 @@ -137,7 +138,7 @@ export interface IItemBase { * 节点类型 * @return {string} 节点的类型 */ - getType(): string; + getType(): ITEM_TYPE; getShapeCfg(model: ModelConfig): ModelConfig; diff --git a/src/item/item.ts b/src/item/item.ts index 43e99ba180..8943fbf9f4 100644 --- a/src/item/item.ts +++ b/src/item/item.ts @@ -3,7 +3,7 @@ import { each, isNil, isPlainObject, isString, isBoolean, uniqueId, mix } from '@antv/util' import { IItemBase, IItemBaseConfig } from '../interface/item'; import Shape from '../shape/shape'; -import { IBBox, IPoint, IShapeBase, ModelConfig, ShapeStyle, Indexable, NodeConfig, EdgeConfig, ComboConfig } from '../types'; +import { IBBox, IPoint, IShapeBase, ModelConfig, ShapeStyle, Indexable, NodeConfig, EdgeConfig, ComboConfig, ITEM_TYPE } from '../types'; import { getBBox } from '../util/graphic'; import { translate } from '../util/math'; @@ -465,7 +465,7 @@ export default class ItemBase implements IItemBase { * 节点类型 * @return {string} 节点的类型 */ - public getType(): string { + public getType(): ITEM_TYPE { return this.get('type'); } diff --git a/src/item/node.ts b/src/item/node.ts index 09e7b8ce1e..3a467ee7d2 100644 --- a/src/item/node.ts +++ b/src/item/node.ts @@ -9,7 +9,6 @@ import { getEllipseIntersectByPoint, getRectIntersectByPoint, } from '../util/math'; -import Edge from './edge'; import Item from './item'; const CACHE_ANCHOR_POINTS = 'anchorPointsCache'; @@ -50,17 +49,17 @@ export default class Node extends Item implements INode { /** * 获取所有的入边 */ - public getInEdges(): Edge[] { + public getInEdges(): IEdge[] { const self = this; - return this.get('edges').filter((edge: Edge) => edge.get('target') === self); + return this.get('edges').filter((edge: IEdge) => edge.get('target') === self); } /** * 获取所有的出边 */ - public getOutEdges(): Edge[] { + public getOutEdges(): IEdge[] { const self = this; - return this.get('edges').filter((edge: Edge) => edge.get('source') === self); + return this.get('edges').filter((edge: IEdge) => edge.get('source') === self); } /** diff --git a/src/util/graphic.ts b/src/util/graphic.ts index 5e10d00a81..7342f2153c 100644 --- a/src/util/graphic.ts +++ b/src/util/graphic.ts @@ -525,11 +525,13 @@ export const plainCombosToTrees = (array: ComboConfig[], nodes?: INode[]) => { return result; } -export const reconstructTree = (trees: ComboTree[]): ComboTree[] => { +export const reconstructTree = (trees: ComboTree[], subtreeId?: String, newParentId?: String | undefined): ComboTree[] => { let brothers = trees; + let subtree; trees.forEach(tree => { traverseTree(tree, child => { - if (child && child.removed && brothers) { + if (child && (child.removed || subtreeId === child.id) && brothers) { + subtree = child; const index = brothers.indexOf(child); brothers.splice(index, 1); } @@ -537,6 +539,25 @@ export const reconstructTree = (trees: ComboTree[]): ComboTree[] => { return true; }); }); + // append to new parent + if (subtreeId) { + let found = false; + // newParentId is undefined means the subtree will have no parent + if (newParentId) { + trees.forEach(tree => { + traverseTree(tree, child => { + if (newParentId === child.id) { + found = true; + if (child.children) child.children.push(subtree); + else child.children = [ subtree ]; + } + return true; + }); + }); + } else if (!newParentId || !found) { + trees.push(subtree); + } + } return trees; } diff --git a/stories/Combo/component/default-combo.tsx b/stories/Combo/component/default-combo.tsx index d10be29fea..29f3240704 100644 --- a/stories/Combo/component/default-combo.tsx +++ b/stories/Combo/component/default-combo.tsx @@ -237,13 +237,13 @@ const DefaultCombo = () => { graph.on('canvas:click', e => { // graph.setItemState(graph.findById('A'), 'selected', true); // console.log( graph.findAllByState('combo', 'selected')) - const hidedCombos = graph.findAll('combo', combo => { - if (!combo.isVisible()) return true; - return false; - }); - hidedCombos.forEach(combo => { - graph.showItem(combo); - }) + // const hidedCombos = graph.findAll('combo', combo => { + // if (!combo.isVisible()) return true; + // return false; + // }); + // hidedCombos.forEach(combo => { + // graph.showItem(combo); + // }) // console.log(graph.getCombos()[0]); // console.log(graph.getComboChildren(graph.getCombos()[0])); //graph.focusItem(graph.getCombos()[0]); @@ -269,6 +269,8 @@ const DefaultCombo = () => { // }); // console.log(graph.save()); + + graph.updateComboTree('A', 'M'); }); } });