Skip to content

Commit 68d0632

Browse files
committed
Revise poor node sorting algorithm with a more accurate version.
1 parent 6789c25 commit 68d0632

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

lib/src/api/node_processor.dart

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,60 @@ class NodeProcessor {
231231
}
232232
}
233233

234+
/// [Returns] all of the parents of [node]. [node] is not included in the
235+
/// final result.
236+
static List<String> _allParentsOfNode(BaseNode node) {
237+
final List<String> parents = [];
238+
239+
String currentId = node.parentID;
240+
while (currentId != kRootNode) {
241+
final BaseNode currentNode = getNode(currentId);
242+
parents.add(currentNode.id);
243+
currentId = currentNode.parentID;
244+
}
245+
246+
return parents;
247+
}
248+
249+
/// Sorted nodes is a list of nodes that go from parent -> child.
250+
static void sortNodes(List<BaseNode> nodes) {
251+
// Optimization: We can cache the parent chains for each node to avoid
252+
// computing them multiple times.
253+
final Map<BaseNode, List<String>> parentChains = {};
254+
255+
nodes.sort((a, b) {
256+
if (a.id == kRootNode) return -1;
257+
if (b.id == kRootNode) return 1;
258+
259+
final BaseNode aParent = getNode(a.parentID);
260+
final BaseNode bParent = getNode(b.parentID);
261+
262+
if (aParent.id == bParent.id) {
263+
return aParent.childrenOrEmpty.indexOf(a.id) -
264+
bParent.childrenOrEmpty.indexOf(b.id);
265+
}
266+
267+
parentChains.putIfAbsent(a, () => _allParentsOfNode(a));
268+
parentChains.putIfAbsent(b, () => _allParentsOfNode(b));
269+
270+
final List<String> aParents = parentChains[a] ?? const [];
271+
final List<String> bParents = parentChains[b] ?? const [];
272+
273+
final int aIndex = bParents.indexOf(a.id);
274+
final int bIndex = aParents.indexOf(b.id);
275+
276+
if (aIndex == -1 && bIndex == -1) {
277+
return bParents.indexOf(kRootNode) - aParents.indexOf(kRootNode);
278+
} else if (bIndex == -1) {
279+
return -1;
280+
} else if (aIndex == -1) {
281+
return 1;
282+
} else {
283+
return bIndex - aIndex;
284+
}
285+
});
286+
}
287+
234288
/// [updateNode] is responsible for updating the node and its children when
235289
/// one or more of its properties change. Ex. if [margin] is changed, all the
236290
/// node boxes and node's children are updated accordingly.

0 commit comments

Comments
 (0)