The protocol split: `region` is the box a parent gives a widget -- what a fraction it declares or reports is a fraction of, and the coordinates every region it writes composes within -- and it is the same box on the ask that measures and the ask that places. `placement` is what of that region the drawing takes, chosen by the parent per axis or by the widget's own answer and alignment. That is what stops a fraction being resolved twice: the placing ask no longer hands the widget its own answer as its box, so nothing under it re-resolves against a box that came from its own report. `reports_of` and `decided` are gone, folded into the two regions; `box_of` is gone; `declared_box` becomes `ask_box`, which gives a rule the region's length and takes the position from the placement. 84 of 92 suite tests pass. Five text and region-node cases still diverge warm against cold, and three count a second widget draw where a span's measuring ask and its placing ask give different placements.
151 lines
3.2 KiB
Rust
151 lines
3.2 KiB
Rust
use super::*;
|
|
use crate::{Fixed, FixedVec2};
|
|
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
|
pub enum Axis {
|
|
X,
|
|
Y,
|
|
}
|
|
|
|
impl Axis {
|
|
/// A per-axis pair with `aligned` on this axis and `ortho` on the other,
|
|
/// which is what `from_axis` does for a vector.
|
|
pub fn pair<T>(self, aligned: T, ortho: T) -> [T; 2] {
|
|
match self {
|
|
Self::X => [aligned, ortho],
|
|
Self::Y => [ortho, aligned],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::ops::Not for Axis {
|
|
type Output = Self;
|
|
|
|
fn not(self) -> Self::Output {
|
|
match self {
|
|
Self::X => Self::Y,
|
|
Self::Y => Self::X,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
|
pub struct Dir {
|
|
pub axis: Axis,
|
|
pub sign: Sign,
|
|
}
|
|
|
|
impl Dir {
|
|
pub const fn new(axis: Axis, dir: Sign) -> Self {
|
|
Self { axis, sign: dir }
|
|
}
|
|
|
|
pub const LEFT: Self = Self::new(Axis::X, Sign::Neg);
|
|
pub const RIGHT: Self = Self::new(Axis::X, Sign::Pos);
|
|
pub const UP: Self = Self::new(Axis::Y, Sign::Neg);
|
|
pub const DOWN: Self = Self::new(Axis::Y, Sign::Pos);
|
|
}
|
|
|
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
|
pub enum Sign {
|
|
Neg,
|
|
Pos,
|
|
}
|
|
|
|
impl<const SHIFT: u32> FixedVec2<SHIFT> {
|
|
pub const fn axis(&self, axis: Axis) -> Fixed<SHIFT> {
|
|
match axis {
|
|
Axis::X => self.x,
|
|
Axis::Y => self.y,
|
|
}
|
|
}
|
|
|
|
pub const fn axis_mut(&mut self, axis: Axis) -> &mut Fixed<SHIFT> {
|
|
match axis {
|
|
Axis::X => &mut self.x,
|
|
Axis::Y => &mut self.y,
|
|
}
|
|
}
|
|
|
|
pub const fn from_axis(axis: Axis, aligned: Fixed<SHIFT>, ortho: Fixed<SHIFT>) -> Self {
|
|
match axis {
|
|
Axis::X => Self::new(aligned, ortho),
|
|
Axis::Y => Self::new(ortho, aligned),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Vec2 {
|
|
pub fn axis(&self, axis: Axis) -> f32 {
|
|
match axis {
|
|
Axis::X => self.x,
|
|
Axis::Y => self.y,
|
|
}
|
|
}
|
|
|
|
pub fn axis_mut(&mut self, axis: Axis) -> &mut f32 {
|
|
match axis {
|
|
Axis::X => &mut self.x,
|
|
Axis::Y => &mut self.y,
|
|
}
|
|
}
|
|
|
|
pub const fn from_axis(axis: Axis, aligned: f32, ortho: f32) -> Self {
|
|
Self {
|
|
x: match axis {
|
|
Axis::X => aligned,
|
|
Axis::Y => ortho,
|
|
},
|
|
y: match axis {
|
|
Axis::Y => aligned,
|
|
Axis::X => ortho,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
pub const trait AxisT {
|
|
fn get() -> Axis;
|
|
}
|
|
|
|
pub struct XAxis;
|
|
const impl AxisT for XAxis {
|
|
fn get() -> Axis {
|
|
Axis::X
|
|
}
|
|
}
|
|
|
|
pub struct YAxis;
|
|
const impl AxisT for YAxis {
|
|
fn get() -> Axis {
|
|
Axis::Y
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default)]
|
|
pub struct BothAxis<T> {
|
|
pub x: T,
|
|
pub y: T,
|
|
}
|
|
|
|
impl<T> BothAxis<T> {
|
|
pub const fn axis<A: const AxisT>(&mut self) -> &mut T {
|
|
match A::get() {
|
|
Axis::X => &mut self.x,
|
|
Axis::Y => &mut self.y,
|
|
}
|
|
}
|
|
pub fn take_axis<A: const AxisT>(self) -> T {
|
|
match A::get() {
|
|
Axis::X => self.x,
|
|
Axis::Y => self.y,
|
|
}
|
|
}
|
|
pub fn axis_dyn(&mut self, axis: Axis) -> &mut T {
|
|
match axis {
|
|
Axis::X => &mut self.x,
|
|
Axis::Y => &mut self.y,
|
|
}
|
|
}
|
|
}
|