1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use daggy::Walker;
use std;
use fnv;
use super::{Graph, Node};
use widget;
#[derive(Debug)]
pub struct DepthOrder {
pub indices: Vec<widget::Id>,
floating: Vec<widget::Id>,
}
impl DepthOrder {
pub fn new() -> DepthOrder {
DepthOrder {
indices: Vec::new(),
floating: Vec::new(),
}
}
pub fn with_node_capacity(n_nodes: usize) -> DepthOrder {
let n_indices = n_nodes * 2;
DepthOrder {
indices: Vec::with_capacity(n_indices),
floating: Vec::with_capacity(n_nodes),
}
}
pub fn update(&mut self,
graph: &Graph,
root: widget::Id,
updated_widgets: &fnv::FnvHashSet<widget::Id>)
{
let DepthOrder { ref mut indices, ref mut floating } = *self;
let num_nodes = graph.node_count();
indices.clear();
indices.reserve(num_nodes);
floating.clear();
floating.reserve(num_nodes);
visit_by_depth(graph, root, updated_widgets, indices, floating);
floating.sort_by(|&a, &b| match (&graph[a], &graph[b]) {
(&Node::Widget(ref a), &Node::Widget(ref b)) => {
let a_floating = a.maybe_floating.expect("Not floating");
let b_floating = b.maybe_floating.expect("Not floating");
a_floating.time_last_clicked.cmp(&b_floating.time_last_clicked)
},
_ => std::cmp::Ordering::Equal,
});
while !floating.is_empty() {
let idx = floating.remove(0);
visit_by_depth(graph, idx, updated_widgets, indices, floating);
}
}
}
fn visit_by_depth(graph: &Graph,
idx: widget::Id,
updated_widgets: &fnv::FnvHashSet<widget::Id>,
depth_order: &mut Vec<widget::Id>,
floating_deque: &mut Vec<widget::Id>)
{
match graph.widget(idx).is_some() && updated_widgets.contains(&idx) {
true => depth_order.push(idx),
false => return,
}
let mut child_sorter: Vec<widget::Id> = graph.depth_children(idx).iter(&graph).nodes().collect();
child_sorter.sort_by(|&a, &b| {
use std::cmp::Ordering;
if let (&Node::Widget(ref a), &Node::Widget(ref b)) = (&graph[a], &graph[b]) {
match b.depth.partial_cmp(&a.depth).expect("Depth was NaN!") {
Ordering::Equal => a.instantiation_order_idx.cmp(&b.instantiation_order_idx),
ordering => ordering,
}
} else {
Ordering::Equal
}
});
for child_idx in child_sorter.into_iter() {
let maybe_is_floating = graph.widget(child_idx).map(|w| w.maybe_floating.is_some());
match maybe_is_floating {
Some(true) => floating_deque.push(child_idx),
_ => visit_by_depth(graph, child_idx, updated_widgets, depth_order, floating_deque),
}
}
}