use teksilo_canvas::Size;
use teksilo_tokens::{InputTokens, TargetAxes, TargetRole};
pub fn dp(base: f32, role: TargetRole, tokens: &InputTokens) -> f32 {
match role {
TargetRole::Target => base.max(tokens.target_size),
TargetRole::Grab => base.max(tokens.grab_size),
TargetRole::Decoration => base,
}
}
pub fn spacing(base: f32, tokens: &InputTokens) -> f32 {
base * tokens.spacing_factor
}
pub fn density_min_size(base: Size, axes: TargetAxes, tokens: &InputTokens) -> Size {
Size {
width: if axes.has_width() {
base.width.max(tokens.target_size)
} else {
base.width
},
height: if axes.has_height() {
base.height.max(tokens.target_size)
} else {
base.height
},
}
}
#[cfg(test)]
mod tests {
use super::*;
use teksilo_tokens::TargetDensity;
fn compact() -> InputTokens {
InputTokens::for_density(TargetDensity::Compact)
}
#[test]
fn compact_is_the_identity_for_conforming_values() {
let t = compact();
for base in [24.0_f32, 28.0, 32.0, 40.0, 48.0, 100.0] {
assert_eq!(dp(base, TargetRole::Target, &t), base);
assert_eq!(dp(base, TargetRole::Grab, &t), base);
assert_eq!(dp(base, TargetRole::Decoration, &t), base);
assert_eq!(spacing(base, &t), base);
}
let s = Size {
width: 30.0,
height: 26.0,
};
assert_eq!(density_min_size(s, TargetAxes::BOTH, &t), s);
}
#[test]
fn decorations_are_never_scaled() {
for d in [
TargetDensity::Compact,
TargetDensity::Comfortable,
TargetDensity::Touch,
] {
let t = InputTokens::for_density(d);
assert_eq!(dp(1.0, TargetRole::Decoration, &t), 1.0);
assert_eq!(dp(0.0, TargetRole::Decoration, &t), 0.0);
}
}
#[test]
fn a_target_never_lands_below_the_conformance_floor() {
for d in [
TargetDensity::Compact,
TargetDensity::Comfortable,
TargetDensity::Touch,
] {
let t = InputTokens::for_density(d);
for base in [0.0_f32, 1.0, 12.0, 23.9, 24.0] {
assert!(dp(base, TargetRole::Target, &t) >= t.min_target_conformance);
}
}
}
#[test]
fn the_touch_ladder_raises_targets_and_grabs() {
let t = InputTokens::for_density(TargetDensity::Touch);
assert_eq!(dp(24.0, TargetRole::Target, &t), 44.0);
assert_eq!(dp(6.0, TargetRole::Grab, &t), 16.0);
assert_eq!(dp(60.0, TargetRole::Target, &t), 60.0);
assert_eq!(spacing(10.0, &t), 13.0);
}
#[test]
fn min_size_touches_only_the_named_axes() {
let t = InputTokens::for_density(TargetDensity::Touch);
let base = Size {
width: 10.0,
height: 10.0,
};
assert_eq!(
density_min_size(base, TargetAxes::HEIGHT, &t),
Size {
width: 10.0,
height: 44.0
}
);
assert_eq!(
density_min_size(base, TargetAxes::WIDTH, &t),
Size {
width: 44.0,
height: 10.0
}
);
assert_eq!(
density_min_size(base, TargetAxes::BOTH, &t),
Size {
width: 44.0,
height: 44.0
}
);
}
}