use std::cell::Cell;
use teksilo_canvas::geometry::{Size, SizeProposal};
pub(crate) fn viewport_size(
proposal: SizeProposal,
viewport_height: &Cell<f32>,
fallback: Size,
) -> Size {
let size = proposal.resolve(fallback.width, fallback.height);
if proposal.height.is_some() {
viewport_height.set(size.height);
}
size
}
pub(crate) fn record_viewport_height(viewport_height: &Cell<f32>, height: f32) {
viewport_height.set(height);
}
#[cfg(test)]
mod tests {
use super::*;
const FALLBACK: Size = Size {
width: 300.0,
height: 200.0,
};
#[test]
fn an_allocation_updates_the_cache() {
let cache = Cell::new(600.0);
let size = viewport_size(SizeProposal::exact(400.0, 654.0), &cache, FALLBACK);
assert_eq!(size, Size::new(400.0, 654.0));
assert_eq!(cache.get(), 654.0);
}
#[test]
fn a_measurement_leaves_the_cache_alone() {
let cache = Cell::new(654.0);
let size = viewport_size(SizeProposal::with_width(400.0), &cache, FALLBACK);
assert_eq!(size, Size::new(400.0, FALLBACK.height));
assert_eq!(cache.get(), 654.0, "measurement must not touch the cache");
}
#[test]
fn a_fully_unspecified_proposal_leaves_the_cache_alone() {
let cache = Cell::new(654.0);
let size = viewport_size(SizeProposal::unspecified(), &cache, FALLBACK);
assert_eq!(size, Size::new(FALLBACK.width, FALLBACK.height));
assert_eq!(cache.get(), 654.0);
}
#[test]
fn a_height_only_proposal_updates_the_cache() {
let cache = Cell::new(600.0);
let size = viewport_size(SizeProposal::with_height(120.0), &cache, FALLBACK);
assert_eq!(size, Size::new(FALLBACK.width, 120.0));
assert_eq!(cache.get(), 120.0);
}
#[test]
fn placement_is_authoritative_over_any_earlier_proposal() {
let cache = Cell::new(0.0);
viewport_size(SizeProposal::exact(400.0, 200.0), &cache, FALLBACK);
record_viewport_height(&cache, 654.0);
assert_eq!(cache.get(), 654.0);
}
}