Commit e2443dec4dcd
tarball2 files changed+173-202
@@ -330,8 +330,7 @@ fn expand_skips_containers_of_hidden_windows() {
330330
assert_eq!(rect(b).w, AREA.w);331331
}332332
333
-/// Joining a stack hands the window's weight to it and leaving hands it back,334
-/// so going in and out repeatedly leaves every window the size it was.333
+/// Going in and out of a stack repeatedly leaves every window the size it was.335334
#[test]336335
fn stacking_in_and_out_does_not_drift() {337336
for out in [Dir::Up, Dir::Down, Dir::Right] {@@ -352,8 +351,8 @@ fn stacking_in_and_out_does_not_drift() {
352351
}353352
}354353
355
-/// Hidden windows in the rows around a window must not soak up its weight356
-/// as it passes through their lanes, or it shrinks on every round trip.354
+/// Windows of other tags in the rows around a window must not change what355
+/// the user sees as it moves through them, nor drift over round trips.357356
#[test]358357
fn moving_past_hidden_windows_does_not_drift() {359358
let (a, b, h, h2) = (1, 2, 3, 4);@@ -366,15 +365,17 @@ fn moving_past_hidden_windows_does_not_drift() {
366365
let once = t.arrange(AREA, 0.0, |_| true);367366
for _ in 0..4 {368367
for d in [Dir::Up, Dir::Up, Dir::Down] {369
- assert!(t.move_window(b, d, vis));368
+ t.move_window(b, d, vis);369
+ let shown = t.arrange(AREA, 0.0, vis);370
+ let r = shown.iter().find(|p| p.0 == b).unwrap().1;371
+ assert!(372
+ (r.w * r.h - AREA.w * AREA.h / 2.0).abs() < 1e-6,373
+ "{d:?} left {r:?}"374
+ );370375
}371376
t.check();372377
}373
- let after = t.arrange(AREA, 0.0, |_| true);374
- for ((w, r), (v, s)) in once.iter().zip(&after) {375
- assert_eq!(w, v);376
- assert!((r.y - s.y).abs() < 1e-6 && (r.h - s.h).abs() < 1e-6, "{w}: {r:?} became {s:?}");377
- }378
+ assert_eq!(t.arrange(AREA, 0.0, |_| true), once);378379
}379380
380381
/// Monitors sleeping together unplug one after another, so windows already@@ -20,6 +20,13 @@ impl Axis {
2020
Self::Vertical => Self::Horizontal,2121
}2222
}23
+24
+ fn index(self) -> usize {25
+ match self {26
+ Self::Horizontal => 0,27
+ Self::Vertical => 1,28
+ }29
+ }2330
}2431
2532
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]@@ -47,18 +54,15 @@ impl Dir {
4754
4855
const MIN_SHARE: f64 = 0.05;4956
50
-#[derive(Clone, Debug)]51
-struct Child {52
- node: NodeId,53
- weight: f64,54
-}57
+/// A window's width and height relative to its neighbours'.58
+type Size = [f64; 2];5559
5660
#[derive(Clone, Debug)]5761
enum Kind<W> {58
- Leaf(W),62
+ Leaf(W, Size),5963
Container {6064
axis: Axis,61
- children: Vec<Child>,65
+ children: Vec<NodeId>,6266
expanded: Option<NodeId>,6367
},6468
}@@ -118,43 +122,45 @@ impl<W: Copy + Eq + Hash> Tree<W> {
118122
let Some(&a) = self.leaves.get(&anchor) else {119123
return self.insert_row(w);120124
};121
- let n = self.new_leaf(w);122125
match self.position(a) {123126
Some((p, i)) if Some(p) == self.root && self.axis(p) == Some(self.stack) => {124
- let weight = self.unlink(p, i).weight;127
+ let n = self.new_leaf(w, self.size(a));128
+ self.unlink(p, i);125129
let c = self.new_container(self.stack.other());126
- self.attach(c, 0, a, 1.0);127
- self.attach(c, 1, n, 1.0);128
- self.attach(p, i, c, weight);130
+ self.attach(c, 0, a);131
+ self.attach(c, 1, n);132
+ self.attach(p, i, c);133
+ self.reveal(n, true);129134
}130135
Some((p, i)) => {131
- let weight = self.mean_weight(p);132
- self.attach(p, i + 1, n, weight);136
+ let n = self.new_leaf(w, self.size(p));137
+ self.attach(p, i + 1, n);138
+ self.reveal(n, true);133139
}134140
None => {141
+ let n = self.new_leaf(w, self.size(a));135142
let c = self.new_container(self.stack.other());136
- self.attach(c, 0, a, 1.0);137
- self.attach(c, 1, n, 1.0);143
+ self.attach(c, 0, a);144
+ self.attach(c, 1, n);138145
self.root = Some(c);139146
}140147
}141
- self.reveal(n, true);142148
}143149
144150
/// Appends `w` as a row of its own along the stacking axis.145151
pub fn insert_row(&mut self, w: W) {146
- let n = self.new_leaf(w);152
+ let size = self.root.map_or([1.0; 2], |r| self.size(r));153
+ let n = self.new_leaf(w, size);147154
match self.root {148155
None => self.root = Some(n),149156
Some(r) if self.axis(r) == Some(self.stack) => {150
- let weight = self.mean_weight(r);151157
let end = self.children(r).len();152
- self.attach(r, end, n, weight);158
+ self.attach(r, end, n);153159
}154160
Some(r) => {155161
let c = self.new_container(self.stack);156
- self.attach(c, 0, r, 1.0);157
- self.attach(c, 1, n, 1.0);162
+ self.attach(c, 0, r);163
+ self.attach(c, 1, n);158164
self.root = Some(c);159165
}160166
}@@ -257,7 +263,7 @@ impl<W: Copy + Eq + Hash> Tree<W> {
257263
let shared = self258264
.children(p)259265
.iter()260
- .any(|c| c.node != cur && self.visible(c.node, vis));266
+ .any(|&c| c != cur && self.visible(c, vis));261267
if shared {262268
path.push((p, cur));263269
}@@ -270,8 +276,9 @@ impl<W: Copy + Eq + Hash> Tree<W> {
270276
pub fn flip(&mut self) {271277
self.stack = self.stack.other();272278
for node in self.nodes.values_mut() {273
- if let Kind::Container { axis, .. } = &mut node.kind {274
- *axis = axis.other();279
+ match &mut node.kind {280
+ Kind::Container { axis, .. } => *axis = axis.other(),281
+ Kind::Leaf(_, size) => size.reverse(),275282
}276283
}277284
}@@ -306,30 +313,28 @@ impl<W: Copy + Eq + Hash> Tree<W> {
306313
307314
/// Grows `w` by `delta`, a fraction of the visible length of the nearest308315
/// container along `axis` where it has a visible sibling. Hidden siblings309
- /// keep their weights, and with them their share.316
+ /// keep their sizes, and with them their share.310317
pub fn resize(&mut self, w: W, axis: Axis, delta: f64, vis: impl Fn(W) -> bool) -> bool {311318
let Some(&leaf) = self.leaves.get(&w) else {312319
return false;313320
};314321
let mut cur = leaf;315
- while let Some((p, i)) = self.position(cur) {322
+ while let Some(p) = self.nodes[cur].parent {316323
if self.axis(p) == Some(axis) {317
- let shown: Vec<usize> = (0..self.children(p).len())318
- .filter(|&j| self.visible(self.children(p)[j].node, &vis))324
+ let shown: Vec<(NodeId, f64)> = self325
+ .children(p)326
+ .iter()327
+ .filter(|&&c| self.visible(c, &vis))328
+ .map(|&c| (c, self.extent(c, axis, &vis)))319329
.collect();320330
if shown.len() >= 2 {321
- let children = self.children_mut(p);322
- let sum: f64 = shown.iter().map(|&j| children[j].weight).sum();323
- let old = children[i].weight;331
+ let sum: f64 = shown.iter().map(|s| s.1).sum();332
+ let old = self.extent(cur, axis, &vis);324333
let max = 1.0 - MIN_SHARE * (shown.len() - 1) as f64;325334
let new = (old / sum + delta).clamp(MIN_SHARE, max) * sum;326335
let scale = (sum - new) / (sum - old);327
- for j in shown {328
- children[j].weight = if j == i {329
- new330
- } else {331
- children[j].weight * scale332
- };336
+ for (c, _) in shown {337
+ self.scale(c, axis, if c == cur { new / old } else { scale });333338
}334339
return true;335340
}@@ -339,6 +344,55 @@ impl<W: Copy + Eq + Hash> Tree<W> {
339344
false340345
}341346
347
+ /// Scales every window under `n` along `axis`, hidden ones too, so they348
+ /// keep their proportions for when they are shown again.349
+ fn scale(&mut self, n: NodeId, axis: Axis, by: f64) {350
+ match &mut self.nodes[n].kind {351
+ Kind::Leaf(_, size) => size[axis.index()] *= by,352
+ Kind::Container { children, .. } => {353
+ for c in children.clone() {354
+ self.scale(c, axis, by);355
+ }356
+ }357
+ }358
+ }359
+360
+ /// How much room `n` asks for along `axis` among its siblings. A361
+ /// container asks for the mean of what its visible children ask for, so362
+ /// windows of other tags sharing a lane change nothing on screen, and a363
+ /// window carries its own size wherever it moves.364
+ fn extent(&self, n: NodeId, axis: Axis, vis: &impl Fn(W) -> bool) -> f64 {365
+ match &self.nodes[n].kind {366
+ Kind::Leaf(_, size) => size[axis.index()],367
+ Kind::Container { children, .. } => {368
+ let shown: Vec<f64> = children369
+ .iter()370
+ .filter(|&&c| self.visible(c, vis))371
+ .map(|&c| self.extent(c, axis, vis))372
+ .collect();373
+ if shown.is_empty() {374
+ children375
+ .iter()376
+ .map(|&c| self.extent(c, axis, vis))377
+ .sum::<f64>()378
+ / children.len() as f64379
+ } else {380
+ shown.iter().sum::<f64>() / shown.len() as f64381
+ }382
+ }383
+ }384
+ }385
+386
+ /// The size a window placed in `n`'s stead would take, ignoring387
+ /// visibility since new windows land on any tag.388
+ fn size(&self, n: NodeId) -> Size {389
+ let all = |_: W| true;390
+ [391
+ self.extent(n, Axis::Horizontal, &all),392
+ self.extent(n, Axis::Vertical, &all),393
+ ]394
+ }395
+342396
/// Lays the tree out in `area`. Hidden windows come back as zero-size343397
/// rects on the boundary where they would reappear.344398
pub fn arrange(&self, area: Rect, gap: f64, vis: impl Fn(W) -> bool) -> Vec<(W, Rect)> {@@ -363,54 +417,54 @@ impl<W: Copy + Eq + Hash> Tree<W> {
363417
out: &mut Vec<(W, Rect)>,364418
) {365419
let (axis, children, expanded) = match &self.nodes[n].kind {366
- Kind::Leaf(w) => return out.push((*w, r)),420
+ Kind::Leaf(w, _) => return out.push((*w, r)),367421
Kind::Container {368422
axis,369423
children,370424
expanded,371425
} => (*axis, children, *expanded),372426
};373
- let shown: Vec<bool> = children.iter().map(|c| self.visible(c.node, vis)).collect();427
+ let shown: Vec<bool> = children.iter().map(|&c| self.visible(c, vis)).collect();374428
let (start, len) = span(r, axis);375
- if let Some(e) = expanded.and_then(|e| children.iter().position(|c| c.node == e))429
+ if let Some(e) = expanded.and_then(|e| children.iter().position(|&c| c == e))376430
&& shown[e]377431
{378
- for (i, c) in children.iter().enumerate() {432
+ for (i, &c) in children.iter().enumerate() {379433
let sub = match i.cmp(&e) {380434
std::cmp::Ordering::Equal => r,381435
std::cmp::Ordering::Less => with_span(r, axis, start, 0.0),382436
std::cmp::Ordering::Greater => with_span(r, axis, start + len, 0.0),383437
};384
- self.place(c.node, sub, gap, vis, out);438
+ self.place(c, sub, gap, vis, out);385439
}386440
return;387441
}388442
let count = shown.iter().filter(|s| **s).count();389
- let total: f64 = children443
+ let extents: Vec<f64> = children390444
.iter()391445
.zip(&shown)392
- .filter(|(_, s)| **s)393
- .map(|(c, _)| c.weight)394
- .sum();446
+ .map(|(&c, &s)| if s { self.extent(c, axis, vis) } else { 0.0 })447
+ .collect();448
+ let total: f64 = extents.iter().sum();395449
let gaps = count.saturating_sub(1) as f64;396450
let gap = if gaps > 0.0 { gap.min(len / gaps) } else { gap };397451
let avail = len - gap * gaps;398452
let last = shown.iter().rposition(|s| *s);399453
let mut pos = start;400454
let mut seen = false;401
- for (i, c) in children.iter().enumerate() {455
+ for (i, &c) in children.iter().enumerate() {402456
if shown[i] {403457
if seen {404458
pos += gap;405459
}406
- let l = avail * c.weight / total;407
- self.place(c.node, with_span(r, axis, pos, l), gap, vis, out);460
+ let l = avail * extents[i] / total;461
+ self.place(c, with_span(r, axis, pos, l), gap, vis, out);408462
pos += l;409463
seen = true;410464
} else {411465
let between = seen && last.is_some_and(|l| l > i);412466
let at = if between { pos + gap / 2.0 } else { pos };413
- self.place(c.node, with_span(r, axis, at, 0.0), gap, vis, out);467
+ self.place(c, with_span(r, axis, at, 0.0), gap, vis, out);414468
}415469
}416470
}@@ -421,24 +475,23 @@ impl<W: Copy + Eq + Hash> Tree<W> {
421475
if self.axis(p) == Some(dir.axis()) {422476
let hidden_lane = self423477
.adjacent(p, i, dir)424
- .filter(|&j| enter && !self.visible(self.children(p)[j].node, vis));478
+ .filter(|&j| enter && !self.visible(self.children(p)[j], vis));425479
if cur != n {426480
if let Some(j) = hidden_lane {427481
self.join_lane(n, p, j);428482
} else {429483
let at = if dir.forward() { i + 1 } else { i };430
- self.step_out(n, p, i, at);484
+ self.relocate(n, p, at);431485
}432486
return true;433487
}434488
if let Some(j) = self.next_shown(p, i, dir, vis) {435
- let sib = self.children(p)[j].node;489
+ let sib = self.children(p)[j];436490
if enter && self.axis(sib).is_some() {437491
self.join_lane(n, p, j);438492
} else {439493
let children = self.children_mut(p);440
- children[i].node = sib;441
- children[j].node = n;494
+ children.swap(i, j);442495
}443496
return true;444497
}@@ -453,27 +506,25 @@ impl<W: Copy + Eq + Hash> Tree<W> {
453506
return false;454507
}455508
let (old, i) = self.position(n).expect("n is below the root");456
- self.release_share(n);457509
self.unlink(old, i);458510
self.normalize(old);459511
let r = self.root.expect("the rest of the tree survives");460512
if self.axis(r) == Some(dir.axis()) {461
- let weight = self.mean_weight(r);462513
let at = if dir.forward() {463514
self.children(r).len()464515
} else {465516
0466517
};467
- self.attach(r, at, n, weight);518
+ self.attach(r, at, n);468519
} else {469520
let c = self.new_container(dir.axis());470
- self.attach(c, 0, r, 1.0);521
+ self.attach(c, 0, r);471522
let at = if dir.forward() {472523
self.children(c).len()473524
} else {474525
0475526
};476
- self.attach(c, at, n, 1.0);527
+ self.attach(c, at, n);477528
self.root = Some(c);478529
}479530
true@@ -482,9 +533,9 @@ impl<W: Copy + Eq + Hash> Tree<W> {
482533
fn next_shown(&self, p: NodeId, i: usize, dir: Dir, vis: &impl Fn(W) -> bool) -> Option<usize> {483534
let children = self.children(p);484535
if dir.forward() {485
- (i + 1..children.len()).find(|&j| self.visible(children[j].node, vis))536
+ (i + 1..children.len()).find(|&j| self.visible(children[j], vis))486537
} else {487
- (0..i).rev().find(|&j| self.visible(children[j].node, vis))538
+ (0..i).rev().find(|&j| self.visible(children[j], vis))488539
}489540
}490541
@@ -500,129 +551,52 @@ impl<W: Copy + Eq + Hash> Tree<W> {
500551
/// Moves `n` to the end of the lane at `p`'s child `j`. A lone window501552
/// there becomes a lane of its own, perpendicular to `p`.502553
fn join_lane(&mut self, n: NodeId, p: NodeId, j: usize) {503
- let lane = self.children(p)[j].node;554
+ let lane = self.children(p)[j];504555
let lane = if self.axis(lane).is_some() {505556
lane506557
} else {507558
let c = self.new_container(self.axis(p).expect("p is a container").other());508
- self.children_mut(p)[j].node = c;559
+ self.children_mut(p)[j] = c;509560
self.nodes[c].parent = Some(p);510561
if let Kind::Container { expanded, .. } = &mut self.nodes[p].kind511562
&& *expanded == Some(lane)512563
{513564
*expanded = Some(c);514565
}515
- self.attach(c, 0, lane, 1.0);566
+ self.attach(c, 0, lane);516567
c517568
};518569
let end = self.children(lane).len();519
- let (old, i) = self.position(n).expect("n is below p");520
- let weight = if old == p {521
- Some(self.children(p)[i].weight)522
- } else if self.position(old).is_some_and(|(q, _)| q == p) {523
- self.release_share(n)524
- } else {525
- None526
- };527
- let inner = match weight {528
- Some(weight) => {529
- let k = self.position(lane).expect("lanes sit in p").1;530
- let total: f64 = self.children(lane).iter().map(|c| c.weight).sum();531
- total * weight / self.children(p)[k].weight532
- }533
- None => self.mean_weight(lane),534
- };535
- self.relocate_weighted(n, lane, end, inner);536
- if let Some(weight) = weight537
- && self.nodes.contains_key(lane)538
- && let Some((q, k)) = self.position(lane)539
- && q == p540
- {541
- self.children_mut(p)[k].weight += weight;542
- }543
- }544
-545
- /// Moves `n` out of `p`'s child `i` to sit beside it at `at`, taking546
- /// along the share of that child's weight it had.547
- fn step_out(&mut self, n: NodeId, p: NodeId, i: usize, at: usize) {548
- let cur = self.children(p)[i].node;549
- let Some((parent, k)) = self.position(n).filter(|&(q, _)| q == cur) else {550
- self.relocate(n, p, at);551
- return;552
- };553
- let share = self.release_share(n).unwrap_or_else(|| self.mean_weight(p));554
- self.unlink(parent, k);555
- self.attach(p, at, n, share);556
- self.normalize(parent);557
- }558
-559
- /// Takes `n`'s share of its container's weight away from the container,560
- /// for `n` to carry out. Joining a lane hands a window's weight to the561
- /// lane, so leaving gives it back and windows going in and out of562
- /// stacks do not shrink their neighbours a little more each time.563
- fn release_share(&mut self, n: NodeId) -> Option<f64> {564
- let (old, i) = self.position(n)?;565
- let (q, k) = self.position(old)?;566
- let total: f64 = self.children(old).iter().map(|c| c.weight).sum();567
- let share = self.children(q)[k].weight * self.children(old)[i].weight / total;568
- self.children_mut(q)[k].weight -= share;569
- Some(share)570
+ self.relocate(n, lane, end);570571
}571572
572573
fn relocate(&mut self, n: NodeId, p: NodeId, at: usize) {573
- self.relocate_weighted(n, p, at, self.mean_weight(p));574
- }575
-576
- fn relocate_weighted(&mut self, n: NodeId, p: NodeId, at: usize, weight: f64) {577574
let (old, i) = self.position(n).expect("relocated nodes have a parent");578575
let at = if old == p && i < at { at - 1 } else { at };579576
self.unlink(old, i);580
- self.attach(p, at, n, weight);577
+ self.attach(p, at, n);581578
self.normalize(old);582579
}583580
584581
/// Places `node` among `p`'s children. A container running along `p`'s585582
/// axis is dissolved into `p` so axes keep alternating.586
- fn attach(&mut self, p: NodeId, at: usize, node: NodeId, weight: f64) {587
- if self.axis(node) == self.axis(p) {588
- let Some(Node {589
- kind: Kind::Container { children, .. },590
- ..591
- }) = self.nodes.remove(node)592
- else {593
- unreachable!("only containers have an axis");594
- };595
- let total: f64 = children.iter().map(|c| c.weight).sum();596
- for (k, c) in children.into_iter().enumerate() {597
- self.nodes[c.node].parent = Some(p);598
- let weight = weight * c.weight / total;599
- self.children_mut(p).insert(600
- at + k,601
- Child {602
- node: c.node,603
- weight,604
- },605
- );583
+ fn attach(&mut self, p: NodeId, at: usize, node: NodeId) {584
+ if self.axis(node).is_some() && self.axis(node) == self.axis(p) {585
+ let children = self.children(node).to_vec();586
+ self.nodes.remove(node);587
+ for (k, &c) in children.iter().enumerate() {588
+ self.nodes[c].parent = Some(p);589
+ self.children_mut(p).insert(at + k, c);606590
}607591
} else {608592
self.nodes[node].parent = Some(p);609
- self.children_mut(p).insert(at, Child { node, weight });593
+ self.children_mut(p).insert(at, node);610594
}611595
}612596
613
- fn unlink(&mut self, p: NodeId, i: usize) -> Child {614
- let Kind::Container {615
- children, expanded, ..616
- } = &mut self.nodes[p].kind617
- else {618
- unreachable!("parents are containers");619
- };620
- let child = children.remove(i);621
- if *expanded == Some(child.node) {622
- *expanded = None;623
- }624
- self.nodes[child.node].parent = None;625
- child597
+ fn unlink(&mut self, p: NodeId, i: usize) {598
+ let child = self.unlink_dead(p, i);599
+ self.nodes[child].parent = None;626600
}627601
628602
fn detach(&mut self, n: NodeId) {@@ -657,25 +631,25 @@ impl<W: Copy + Eq + Hash> Tree<W> {
657631
}658632
(None, None) => self.root = None,659633
(Some(only), Some((p, i))) => {660
- let weight = self.unlink_dead(p, i).weight;661
- let leaf_like = self.axis(only.node) != self.axis(p);662
- self.attach(p, i, only.node, weight);634
+ self.unlink_dead(p, i);635
+ let leaf_like = self.axis(only) != self.axis(p);636
+ self.attach(p, i, only);663637
if was_expanded664638
&& leaf_like665639
&& let Kind::Container { expanded, .. } = &mut self.nodes[p].kind666640
{667
- *expanded = Some(only.node);641
+ *expanded = Some(only);668642
}669643
}670644
(Some(only), None) => {671
- self.nodes[only.node].parent = None;672
- self.root = Some(only.node);645
+ self.nodes[only].parent = None;646
+ self.root = Some(only);673647
}674648
}675649
}676650
677651
/// Like `unlink`, for a child whose node is already gone.678
- fn unlink_dead(&mut self, p: NodeId, i: usize) -> Child {652
+ fn unlink_dead(&mut self, p: NodeId, i: usize) -> NodeId {679653
let Kind::Container {680654
children, expanded, ..681655
} = &mut self.nodes[p].kind@@ -683,16 +657,16 @@ impl<W: Copy + Eq + Hash> Tree<W> {
683657
unreachable!("parents are containers");684658
};685659
let child = children.remove(i);686
- if *expanded == Some(child.node) {660
+ if *expanded == Some(child) {687661
*expanded = None;688662
}689663
child690664
}691665
692
- fn new_leaf(&mut self, w: W) -> NodeId {666
+ fn new_leaf(&mut self, w: W, size: Size) -> NodeId {693667
let n = self.nodes.insert(Node {694668
parent: None,695
- kind: Kind::Leaf(w),669
+ kind: Kind::Leaf(w, size),696670
});697671
self.leaves.insert(w, n);698672
n@@ -711,51 +685,42 @@ impl<W: Copy + Eq + Hash> Tree<W> {
711685
712686
fn position(&self, n: NodeId) -> Option<(NodeId, usize)> {713687
let p = self.nodes[n].parent?;714
- let i = self.children(p).iter().position(|c| c.node == n)?;688
+ let i = self.children(p).iter().position(|&c| c == n)?;715689
Some((p, i))716690
}717691
718692
fn axis(&self, n: NodeId) -> Option<Axis> {719693
match &self.nodes[n].kind {720694
Kind::Container { axis, .. } => Some(*axis),721
- Kind::Leaf(_) => None,695
+ Kind::Leaf(..) => None,722696
}723697
}724698
725699
fn expanded(&self, n: NodeId) -> Option<NodeId> {726700
match &self.nodes[n].kind {727701
Kind::Container { expanded, .. } => *expanded,728
- Kind::Leaf(_) => None,702
+ Kind::Leaf(..) => None,729703
}730704
}731705
732
- fn children(&self, n: NodeId) -> &[Child] {706
+ fn children(&self, n: NodeId) -> &[NodeId] {733707
match &self.nodes[n].kind {734708
Kind::Container { children, .. } => children,735
- Kind::Leaf(_) => &[],709
+ Kind::Leaf(..) => &[],736710
}737711
}738712
739
- fn children_mut(&mut self, n: NodeId) -> &mut Vec<Child> {713
+ fn children_mut(&mut self, n: NodeId) -> &mut Vec<NodeId> {740714
match &mut self.nodes[n].kind {741715
Kind::Container { children, .. } => children,742
- Kind::Leaf(_) => unreachable!("leaves have no children"),743
- }744
- }745
-746
- fn mean_weight(&self, p: NodeId) -> f64 {747
- let children = self.children(p);748
- if children.is_empty() {749
- 1.0750
- } else {751
- children.iter().map(|c| c.weight).sum::<f64>() / children.len() as f64716
+ Kind::Leaf(..) => unreachable!("leaves have no children"),752717
}753718
}754719
755720
fn visible(&self, n: NodeId, vis: &impl Fn(W) -> bool) -> bool {756721
match &self.nodes[n].kind {757
- Kind::Leaf(w) => vis(*w),758
- Kind::Container { children, .. } => children.iter().any(|c| self.visible(c.node, vis)),722
+ Kind::Leaf(w, _) => vis(*w),723
+ Kind::Container { children, .. } => children.iter().any(|&c| self.visible(c, vis)),759724
}760725
}761726
@@ -770,14 +735,20 @@ impl<W: Copy + Eq + Hash> Tree<W> {
770735
};771736
assert_eq!(reachable, self.nodes.len(), "orphaned nodes");772737
for (&w, &n) in &self.leaves {773
- assert!(matches!(self.nodes[n].kind, Kind::Leaf(x) if x == w));738
+ assert!(matches!(self.nodes[n].kind, Kind::Leaf(x, _) if x == w));774739
}775740
}776741
777742
#[cfg(test)]778743
fn check_node(&self, n: NodeId) -> usize {779744
match &self.nodes[n].kind {780
- Kind::Leaf(_) => 1,745
+ Kind::Leaf(_, size) => {746
+ assert!(747
+ size.iter().all(|s| *s > 0.0 && s.is_finite()),748
+ "size {size:?}"749
+ );750
+ 1751
+ }781752
Kind::Container {782753
axis,783754
children,@@ -789,14 +760,13 @@ impl<W: Copy + Eq + Hash> Tree<W> {
789760
children.len()790761
);791762
if let Some(e) = expanded {792
- assert!(children.iter().any(|c| c.node == *e));763
+ assert!(children.contains(e));793764
}794765
let mut count = 1;795
- for c in children {796
- assert!(c.weight > 0.0 && c.weight.is_finite());797
- assert_eq!(self.nodes[c.node].parent, Some(n));798
- assert_ne!(self.axis(c.node), Some(*axis), "axes must alternate");799
- count += self.check_node(c.node);766
+ for &c in children {767
+ assert_eq!(self.nodes[c].parent, Some(n));768
+ assert_ne!(self.axis(c), Some(*axis), "axes must alternate");769
+ count += self.check_node(c);800770
}801771
count802772
}