@antv/g6
Version:
graph visualization frame work
396 lines (353 loc) • 10.9 kB
JavaScript
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/**
* @fileOverview tree
* @author huangtonger@aliyun.com
*/
var Util = require('./util/');
var Graph = require('./graph');
var Layouts = require('./layouts/');
var Tree = function (_Graph) {
_inherits(Tree, _Graph);
function Tree(inputCfg) {
_classCallCheck(this, Tree);
var cfg = Util.mix({
layout: new Layouts.CompactBoxTree({
getHGap: function getHGap() {
return 10;
},
getVGap: function getVGap() {
return 10;
}
})
}, inputCfg);
return _possibleConstructorReturn(this, _Graph.call(this, cfg));
}
Tree.prototype.initEvent = function initEvent() {
var _this2 = this;
this.on('afterdrawinner', function () {
var source = _this2.get('_sourceData');
source.roots.forEach(function (root) {
var rootItem = _this2.find(root.id);
_this2._setVisibleByCollapsed(rootItem);
});
});
// this.on('afterchange', () => {
// const roots = this.getRoots();
// roots.forEach(root => {
// root.hierarchy = 1;
// root.deepEach(child => {
// const parent = child.getParent();
// child.hierarchy = parent.hierarchy + 1;
// });
// });
// });
};
Tree.prototype._executeLayout = function _executeLayout(processer) {
var source = this.get('_sourceData');
if (Util.isFunction(processer)) {
processer(source.roots, this);
} else if (Util.isObject(processer)) {
processer.roots = source.roots;
processer.graph = this;
processer.execute();
}
};
Tree.prototype.getHierarchy = function getHierarchy(item) {
item = this.getItem(item);
var dataMap = this.get('_dataMap');
var model = item.getModel();
var parent = model.parent;
var hierarchy = 1;
while (parent) {
parent = dataMap[parent].parent;
hierarchy++;
}
return hierarchy;
};
Tree.prototype.parseSource = function parseSource(data) {
var roots = data.roots;
var dataMap = this.get('_dataMap');
var nodes = [];
var edges = [];
roots.forEach(function (root) {
Util.traverseTree(root, function (child, parent) {
if (!child.id) {
child.id = Util.guid();
}
if (!parent) {
parent = dataMap[child.parent];
}
if (parent) {
child.parent = parent.id;
if (!parent.id) {
parent.id = Util.guid();
}
edges.push({
source: parent.id,
target: child.id,
id: parent.id + '-' + child.id
});
}
nodes.push(child);
}, function (parent) {
return parent.children;
}, true);
});
return {
nodes: nodes,
edges: edges
};
};
// input an item set it's children visiable
Tree.prototype._setVisibleByCollapsed = function _setVisibleByCollapsed(item) {
var model = item.getModel();
if (model.collapsed) {
item.deepEach(function (node) {
node.hide();
node.getEdges().forEach(function (edge) {
edge.hide();
});
});
} else {
item.deepEach(function (node) {
if (node.collapsedParent) {
node.hide();
node.getEdges().forEach(function (edge) {
edge.hide();
});
}
});
}
};
/**
* @param {object} data tree data
*/
Tree.prototype.source = function source(data) {
var _data = this.parseSource(data);
this.emit('beforesource');
this.set('_sourceData', data);
this.set('_data', _data);
this.emit('aftersource');
};
/**
* @param {object} node item node
* @param {object} nth nth
*/
Tree.prototype.setNodeNth = function setNodeNth(node, nth) {
var model = node.getModel();
var parent = node.getParent();
var parentModel = parent.getModel();
var children = parentModel.children;
Util.Array.remove(children, model);
children.splice(nth, 0, model);
};
/**
* @param {object} node item node
* @return {number} nth
*/
Tree.prototype.getNth = function getNth(node) {
var model = node.getModel();
var parent = node.getParent();
var parentModel = parent.getModel();
return parentModel.children.indexOf(model);
};
/**
* @param {string} type item type
* @param {object} model data model
* @return {Graph} this
*/
Tree.prototype.add = function add(type, model) {
var dataMap = this.get('_dataMap');
var parent = dataMap[model.parent];
var ev = {
action: 'add',
model: model
};
var item = void 0;
if (type !== 'node' && type !== 'guide') {
console.warn('Tree do not support add type ' + type + '!');
return;
}
this.emit('beforechange', ev);
if (type === 'node') {
if (!parent) {
throw new Error('please set available parent Id !');
}
if (Util.isArray(parent.children)) {
parent.children.push(model);
} else {
parent.children = [model];
}
var data = this.parseSource({
roots: [model]
});
this.addItems('node', data.nodes);
this.addItems('edge', data.edges);
item = this.find(model.id);
this._setVisibleByCollapsed(item);
// set node nth
if (!Util.isNil(model.nth)) {
this.setNodeNth(item, model.nth);
}
this.find(parent.id).forceUpdate();
} else {
this.addItems(type, [model]);
item = this.find(model.id);
}
ev.item = item;
this.emit('afterchange', ev);
this.draw();
return item;
};
/**
* @param {String|Item} item target item
* @param {object} model data model
* @return {Graph} this
*/
Tree.prototype.update = function update(item, model) {
var _this3 = this;
if (!model) {
return;
}
item = this.getItem(item);
var itemModel = item.getModel();
var originModel = Util.mix({}, itemModel);
var ev = {
action: 'update',
item: item,
originModel: originModel,
updateModel: model
};
model && this.emit('beforechange', ev);
this.updateItem(item, model);
if (item.isNode) {
// deal collapsed
if ('collapsed' in model) {
if (model.collapsed) {
item.deepEach(function (child) {
child.hide();
child.getEdges().forEach(function (edge) {
edge.hide();
});
});
} else {
item.deepEach(function (child) {
child.show();
child.getEdges(function (edge) {
var model = edge.getModel();
return model.target === child.id;
}).forEach(function (edge) {
edge.show();
});
}, function (parent) {
if (!parent.model.collapsed) {
return parent.getChildren();
}
return null;
});
}
}
// exchange parent
if (model.parent) {
var originParent = this.find(originModel.id);
var originParentModel = originParent.getModel();
var newParent = this.find(model.parent);
var newParentModel = newParent.getModel();
Util.Array.remove(originParentModel.children, itemModel);
if (newParentModel.children) {
newParentModel.children.push(itemModel);
} else {
newParentModel.children = [itemModel];
}
this.find(newParentModel.id).forceUpdate();
}
// update children
if (Util.isArray(model.children)) {
if (originModel.children) {
Util.each(originModel.children, function (child) {
var removeItems = [_this3.find(child)];
child.getEdges().forEach(function (edge) {
removeItems.push(edge);
});
_this3.removeItems(removeItems);
});
}
Util.each(model.children, function (child) {
var data = _this3.parseSource({
roots: [child]
});
_this3.addItems('node', data.nodes);
_this3.addItems('edge', data.edges);
});
}
// set node nth
if (!Util.isNil(model.nth)) {
this.setNodeNth(item, model.nth);
}
var parentItem = this.find(itemModel.parent);
parentItem && parentItem.forceUpdate();
}
this.emit('afterchange', ev);
this.draw();
return this;
};
/**
* @param {String|Item} item target item
* @return {Graph} this
*/
Tree.prototype.remove = function remove(item) {
var dataMap = this.get('_dataMap');
var items = [];
item = this.getItem(item);
if (!item || item.destroyed) {
return;
}
var ev = {
action: 'remove',
item: item
};
this.emit('beforechange', ev);
items.push(item);
item.getEdges().forEach(function (edge) {
items.push(edge);
});
if (item.type === 'node') {
var model = item.getModel();
var parent = dataMap[model.parent];
item.deepEach(function (child) {
items.push(child);
child.getEdges().forEach(function (edge) {
items.push(edge);
});
});
Util.Array.remove(parent.children, model);
this.find(parent.id).forceUpdate();
}
this.removeItems(Util.uniq(items));
this.emit('afterchange', ev);
this.draw();
return this;
};
Tree.prototype.getRoots = function getRoots() {
var _this4 = this;
var source = this.getSource();
return source.roots.map(function (root) {
return _this4.find(root.id);
});
};
Tree.prototype.save = function save() {
var rst = {
roots: Util.cloneDeep(this.getSource().roots),
guides: this.getGuides().map(function (guide) {
return guide.getModel();
})
};
rst.roots.length === 0 && delete rst.roots;
rst.guides.length === 0 && delete rst.guides;
return rst;
};
return Tree;
}(Graph);
module.exports = Tree;