OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2015 Google Inc. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style | |
5 * license that can be found in the LICENSE file or at | |
6 * https://developers.google.com/open-source/licenses/bsd | |
7 */ | |
8 part of charted.layout; | |
9 | |
10 typedef int SortFunction(HierarchyNode a, HierarchyNode b); | |
11 typedef List ChildrenAccessor(HierarchyNode node); | |
12 typedef num ValueAccessor(HierarchyNode node); | |
13 | |
14 /** | |
15 * The hierarchy layout is an abstract layout that is not used directly, but | |
16 * instead allows code sharing between multiple hierarchical layouts such as: | |
17 * Cluster, Pack, Partition, Tree, and Treemap layout. | |
18 */ | |
19 abstract class HierarchyLayout<T extends HierarchyNode> { | |
20 static const ROOT_ROW_INDEX = -1; | |
21 SortFunction sortFunction = hierarchySort; | |
22 ChildrenAccessor childrenAccessor = hierarchyChildren; | |
23 ValueAccessor valueAccessor = hierarchyValue; | |
24 | |
25 /// Returns the list of HierarchyNode constructed from the given data and | |
26 /// parentColumn and valueColumn which is used to construct the hierarchy. | |
27 /// The returned list of nodes contains the hierarchy with root being the | |
28 /// first element its children in depth first order. | |
29 List<T> layout(List rows, int parentColumn, int labelColumn, | |
30 int valueColumn) { | |
31 List<HierarchyNode> nodeList = []; | |
32 for (var row in rows) { | |
33 nodeList.add(createNode(row[labelColumn], row[valueColumn], 0)); | |
34 } | |
35 | |
36 for (var i = 0; i < rows.length; i++) { | |
37 int parentRow = rows[i][parentColumn]; | |
38 if (parentRow == ROOT_ROW_INDEX) continue; | |
39 var currentNode = nodeList[i]; | |
40 var parentNode = nodeList[parentRow]; | |
41 (parentNode.children.isEmpty) ? parentNode.children = [currentNode] : | |
42 parentNode.children.add(currentNode); | |
43 currentNode.parent = parentNode; | |
44 currentNode.depth = parentNode.depth + 1; | |
45 for (var child in currentNode.children) { | |
46 child.depth += 1; | |
47 } | |
48 } | |
49 | |
50 // Reorder the list so that root is the first element and the list contains | |
51 // the hierarchy of nodes in depth first order. | |
52 var hierarchyNodeList = []; | |
53 var root = nodeList.where((e) => e.depth == 0).elementAt(0); | |
54 var children = [root]; | |
55 while (children.length > 0) { | |
56 var node = children.removeLast(); | |
57 children.addAll(node.children); | |
58 hierarchyNodeList.add(node); | |
59 } | |
60 | |
61 return hierarchyNodeList; | |
62 } | |
63 | |
64 T createNode(label, value, depth); | |
65 | |
66 /// Default accessor method for getting the list of children of the node. | |
67 static List hierarchyChildren(HierarchyNode node) => node.children; | |
68 | |
69 /// Default accessor method for getting the value of the node. | |
70 static num hierarchyValue(HierarchyNode node) => node.value; | |
71 | |
72 /// Default sorting method for comparing node a and b. | |
73 static int hierarchySort(HierarchyNode a, HierarchyNode b) => | |
74 b.value - a.value; | |
75 | |
76 } | |
77 | |
78 abstract class HierarchyNode { | |
79 /// The parent node, or null for the root. | |
80 HierarchyNode parent = null; | |
81 | |
82 /// The list of children nodes, or null for leaf nodes. | |
83 List children = []; | |
84 | |
85 /// The label to show for each block of hierarchy | |
86 String label = ''; | |
87 | |
88 /// The node value, as returned by the value accessor. | |
89 dynamic value; | |
90 | |
91 /// The depth of the node, starting at 0 for the root. | |
92 int depth = 0; | |
93 } | |
OLD | NEW |