Tree.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. /**
  20. * AUTO-GENERATED FILE. DO NOT MODIFY.
  21. */
  22. /*
  23. * Licensed to the Apache Software Foundation (ASF) under one
  24. * or more contributor license agreements. See the NOTICE file
  25. * distributed with this work for additional information
  26. * regarding copyright ownership. The ASF licenses this file
  27. * to you under the Apache License, Version 2.0 (the
  28. * "License"); you may not use this file except in compliance
  29. * with the License. You may obtain a copy of the License at
  30. *
  31. * http://www.apache.org/licenses/LICENSE-2.0
  32. *
  33. * Unless required by applicable law or agreed to in writing,
  34. * software distributed under the License is distributed on an
  35. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  36. * KIND, either express or implied. See the License for the
  37. * specific language governing permissions and limitations
  38. * under the License.
  39. */
  40. /**
  41. * Tree data structure
  42. */
  43. import * as zrUtil from 'zrender/lib/core/util.js';
  44. import linkSeriesData from './helper/linkSeriesData.js';
  45. import SeriesData from './SeriesData.js';
  46. import prepareSeriesDataSchema from './helper/createDimensions.js';
  47. import { convertOptionIdName } from '../util/model.js';
  48. var TreeNode =
  49. /** @class */
  50. function () {
  51. function TreeNode(name, hostTree) {
  52. this.depth = 0;
  53. this.height = 0;
  54. /**
  55. * Reference to list item.
  56. * Do not persistent dataIndex outside,
  57. * besause it may be changed by list.
  58. * If dataIndex -1,
  59. * this node is logical deleted (filtered) in list.
  60. */
  61. this.dataIndex = -1;
  62. this.children = [];
  63. this.viewChildren = [];
  64. this.isExpand = false;
  65. this.name = name || '';
  66. this.hostTree = hostTree;
  67. }
  68. /**
  69. * The node is removed.
  70. */
  71. TreeNode.prototype.isRemoved = function () {
  72. return this.dataIndex < 0;
  73. };
  74. TreeNode.prototype.eachNode = function (options, cb, context) {
  75. if (zrUtil.isFunction(options)) {
  76. context = cb;
  77. cb = options;
  78. options = null;
  79. }
  80. options = options || {};
  81. if (zrUtil.isString(options)) {
  82. options = {
  83. order: options
  84. };
  85. }
  86. var order = options.order || 'preorder';
  87. var children = this[options.attr || 'children'];
  88. var suppressVisitSub;
  89. order === 'preorder' && (suppressVisitSub = cb.call(context, this));
  90. for (var i = 0; !suppressVisitSub && i < children.length; i++) {
  91. children[i].eachNode(options, cb, context);
  92. }
  93. order === 'postorder' && cb.call(context, this);
  94. };
  95. /**
  96. * Update depth and height of this subtree.
  97. */
  98. TreeNode.prototype.updateDepthAndHeight = function (depth) {
  99. var height = 0;
  100. this.depth = depth;
  101. for (var i = 0; i < this.children.length; i++) {
  102. var child = this.children[i];
  103. child.updateDepthAndHeight(depth + 1);
  104. if (child.height > height) {
  105. height = child.height;
  106. }
  107. }
  108. this.height = height + 1;
  109. };
  110. TreeNode.prototype.getNodeById = function (id) {
  111. if (this.getId() === id) {
  112. return this;
  113. }
  114. for (var i = 0, children = this.children, len = children.length; i < len; i++) {
  115. var res = children[i].getNodeById(id);
  116. if (res) {
  117. return res;
  118. }
  119. }
  120. };
  121. TreeNode.prototype.contains = function (node) {
  122. if (node === this) {
  123. return true;
  124. }
  125. for (var i = 0, children = this.children, len = children.length; i < len; i++) {
  126. var res = children[i].contains(node);
  127. if (res) {
  128. return res;
  129. }
  130. }
  131. };
  132. /**
  133. * @param includeSelf Default false.
  134. * @return order: [root, child, grandchild, ...]
  135. */
  136. TreeNode.prototype.getAncestors = function (includeSelf) {
  137. var ancestors = [];
  138. var node = includeSelf ? this : this.parentNode;
  139. while (node) {
  140. ancestors.push(node);
  141. node = node.parentNode;
  142. }
  143. ancestors.reverse();
  144. return ancestors;
  145. };
  146. TreeNode.prototype.getAncestorsIndices = function () {
  147. var indices = [];
  148. var currNode = this;
  149. while (currNode) {
  150. indices.push(currNode.dataIndex);
  151. currNode = currNode.parentNode;
  152. }
  153. indices.reverse();
  154. return indices;
  155. };
  156. TreeNode.prototype.getDescendantIndices = function () {
  157. var indices = [];
  158. this.eachNode(function (childNode) {
  159. indices.push(childNode.dataIndex);
  160. });
  161. return indices;
  162. };
  163. TreeNode.prototype.getValue = function (dimension) {
  164. var data = this.hostTree.data;
  165. return data.getStore().get(data.getDimensionIndex(dimension || 'value'), this.dataIndex);
  166. };
  167. TreeNode.prototype.setLayout = function (layout, merge) {
  168. this.dataIndex >= 0 && this.hostTree.data.setItemLayout(this.dataIndex, layout, merge);
  169. };
  170. /**
  171. * @return {Object} layout
  172. */
  173. TreeNode.prototype.getLayout = function () {
  174. return this.hostTree.data.getItemLayout(this.dataIndex);
  175. }; // @depcrecated
  176. // getModel<T = unknown, S extends keyof T = keyof T>(path: S): Model<T[S]>
  177. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  178. TreeNode.prototype.getModel = function (path) {
  179. if (this.dataIndex < 0) {
  180. return;
  181. }
  182. var hostTree = this.hostTree;
  183. var itemModel = hostTree.data.getItemModel(this.dataIndex);
  184. return itemModel.getModel(path);
  185. }; // TODO: TYPE More specific model
  186. TreeNode.prototype.getLevelModel = function () {
  187. return (this.hostTree.levelModels || [])[this.depth];
  188. };
  189. TreeNode.prototype.setVisual = function (key, value) {
  190. this.dataIndex >= 0 && this.hostTree.data.setItemVisual(this.dataIndex, key, value);
  191. };
  192. /**
  193. * Get item visual
  194. * FIXME: make return type better
  195. */
  196. TreeNode.prototype.getVisual = function (key) {
  197. return this.hostTree.data.getItemVisual(this.dataIndex, key);
  198. };
  199. TreeNode.prototype.getRawIndex = function () {
  200. return this.hostTree.data.getRawIndex(this.dataIndex);
  201. };
  202. TreeNode.prototype.getId = function () {
  203. return this.hostTree.data.getId(this.dataIndex);
  204. };
  205. /**
  206. * index in parent's children
  207. */
  208. TreeNode.prototype.getChildIndex = function () {
  209. if (this.parentNode) {
  210. var children = this.parentNode.children;
  211. for (var i = 0; i < children.length; ++i) {
  212. if (children[i] === this) {
  213. return i;
  214. }
  215. }
  216. return -1;
  217. }
  218. return -1;
  219. };
  220. /**
  221. * if this is an ancestor of another node
  222. *
  223. * @param node another node
  224. * @return if is ancestor
  225. */
  226. TreeNode.prototype.isAncestorOf = function (node) {
  227. var parent = node.parentNode;
  228. while (parent) {
  229. if (parent === this) {
  230. return true;
  231. }
  232. parent = parent.parentNode;
  233. }
  234. return false;
  235. };
  236. /**
  237. * if this is an descendant of another node
  238. *
  239. * @param node another node
  240. * @return if is descendant
  241. */
  242. TreeNode.prototype.isDescendantOf = function (node) {
  243. return node !== this && node.isAncestorOf(this);
  244. };
  245. return TreeNode;
  246. }();
  247. export { TreeNode };
  248. ;
  249. var Tree =
  250. /** @class */
  251. function () {
  252. function Tree(hostModel) {
  253. this.type = 'tree';
  254. this._nodes = [];
  255. this.hostModel = hostModel;
  256. }
  257. Tree.prototype.eachNode = function (options, cb, context) {
  258. this.root.eachNode(options, cb, context);
  259. };
  260. Tree.prototype.getNodeByDataIndex = function (dataIndex) {
  261. var rawIndex = this.data.getRawIndex(dataIndex);
  262. return this._nodes[rawIndex];
  263. };
  264. Tree.prototype.getNodeById = function (name) {
  265. return this.root.getNodeById(name);
  266. };
  267. /**
  268. * Update item available by list,
  269. * when list has been performed options like 'filterSelf' or 'map'.
  270. */
  271. Tree.prototype.update = function () {
  272. var data = this.data;
  273. var nodes = this._nodes;
  274. for (var i = 0, len = nodes.length; i < len; i++) {
  275. nodes[i].dataIndex = -1;
  276. }
  277. for (var i = 0, len = data.count(); i < len; i++) {
  278. nodes[data.getRawIndex(i)].dataIndex = i;
  279. }
  280. };
  281. /**
  282. * Clear all layouts
  283. */
  284. Tree.prototype.clearLayouts = function () {
  285. this.data.clearItemLayouts();
  286. };
  287. /**
  288. * data node format:
  289. * {
  290. * name: ...
  291. * value: ...
  292. * children: [
  293. * {
  294. * name: ...
  295. * value: ...
  296. * children: ...
  297. * },
  298. * ...
  299. * ]
  300. * }
  301. */
  302. Tree.createTree = function (dataRoot, hostModel, beforeLink) {
  303. var tree = new Tree(hostModel);
  304. var listData = [];
  305. var dimMax = 1;
  306. buildHierarchy(dataRoot);
  307. function buildHierarchy(dataNode, parentNode) {
  308. var value = dataNode.value;
  309. dimMax = Math.max(dimMax, zrUtil.isArray(value) ? value.length : 1);
  310. listData.push(dataNode);
  311. var node = new TreeNode(convertOptionIdName(dataNode.name, ''), tree);
  312. parentNode ? addChild(node, parentNode) : tree.root = node;
  313. tree._nodes.push(node);
  314. var children = dataNode.children;
  315. if (children) {
  316. for (var i = 0; i < children.length; i++) {
  317. buildHierarchy(children[i], node);
  318. }
  319. }
  320. }
  321. tree.root.updateDepthAndHeight(0);
  322. var dimensions = prepareSeriesDataSchema(listData, {
  323. coordDimensions: ['value'],
  324. dimensionsCount: dimMax
  325. }).dimensions;
  326. var list = new SeriesData(dimensions, hostModel);
  327. list.initData(listData);
  328. beforeLink && beforeLink(list);
  329. linkSeriesData({
  330. mainData: list,
  331. struct: tree,
  332. structAttr: 'tree'
  333. });
  334. tree.update();
  335. return tree;
  336. };
  337. return Tree;
  338. }();
  339. /**
  340. * It is needed to consider the mess of 'list', 'hostModel' when creating a TreeNote,
  341. * so this function is not ready and not necessary to be public.
  342. */
  343. function addChild(child, node) {
  344. var children = node.children;
  345. if (child.parentNode === node) {
  346. return;
  347. }
  348. children.push(child);
  349. child.parentNode = node;
  350. }
  351. export default Tree;