use crate::geom::LogicalPosition;
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct ScrollOffset(pub LogicalPosition);
impl ScrollOffset {
#[inline]
#[must_use]
pub const fn zero() -> Self {
Self(LogicalPosition::zero())
}
#[inline]
#[must_use]
pub const fn new(x: f32, y: f32) -> Self {
Self(LogicalPosition { x, y })
}
#[inline]
#[must_use]
pub const fn get(self) -> LogicalPosition {
self.0
}
#[inline]
#[must_use]
pub const fn plus(self, other: Self) -> Self {
Self(LogicalPosition {
x: self.0.x + other.0.x,
y: self.0.y + other.0.y,
})
}
}
#[derive(Debug, Copy, Clone, Default, PartialEq)]
#[repr(C)]
pub struct ContentInset {
pub left: f32,
pub top: f32,
}
impl ContentInset {
pub const ZERO: Self = Self {
left: 0.0,
top: 0.0,
};
#[inline]
#[must_use]
pub const fn new(left: f32, top: f32) -> Self {
Self { left, top }
}
}
macro_rules! point_space {
($(#[$meta:meta])* $name:ident) => {
$(#[$meta])*
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct $name(LogicalPosition);
impl $name {
#[inline]
#[must_use]
pub const fn new(p: LogicalPosition) -> Self {
Self(p)
}
#[inline]
#[must_use]
pub const fn zero() -> Self {
Self(LogicalPosition::zero())
}
#[inline]
#[must_use]
pub const fn get(self) -> LogicalPosition {
self.0
}
#[inline]
#[must_use]
pub const fn x(self) -> f32 {
self.0.x
}
#[inline]
#[must_use]
pub const fn y(self) -> f32 {
self.0.y
}
}
};
}
point_space! {
WindowPoint
}
point_space! {
StaticLayoutPoint
}
point_space! {
BorderBoxLocal
}
point_space! {
ContentBoxLocal
}
point_space! {
ScrolledContentPoint
}
impl WindowPoint {
#[inline]
#[must_use]
pub const fn to_static_layout(self, ancestor_scroll: ScrollOffset) -> StaticLayoutPoint {
StaticLayoutPoint(LogicalPosition {
x: self.0.x + ancestor_scroll.0.x,
y: self.0.y + ancestor_scroll.0.y,
})
}
}
impl StaticLayoutPoint {
#[inline]
#[must_use]
pub const fn to_window(self, ancestor_scroll: ScrollOffset) -> WindowPoint {
WindowPoint(LogicalPosition {
x: self.0.x - ancestor_scroll.0.x,
y: self.0.y - ancestor_scroll.0.y,
})
}
#[inline]
#[must_use]
pub const fn to_border_box_local(self, border_box_origin: LogicalPosition) -> BorderBoxLocal {
BorderBoxLocal(LogicalPosition {
x: self.0.x - border_box_origin.x,
y: self.0.y - border_box_origin.y,
})
}
}
impl BorderBoxLocal {
#[inline]
#[must_use]
pub const fn to_static_layout(self, border_box_origin: LogicalPosition) -> StaticLayoutPoint {
StaticLayoutPoint(LogicalPosition {
x: self.0.x + border_box_origin.x,
y: self.0.y + border_box_origin.y,
})
}
#[inline]
#[must_use]
pub const fn to_content_box_local(self, inset: ContentInset) -> ContentBoxLocal {
ContentBoxLocal(LogicalPosition {
x: self.0.x - inset.left,
y: self.0.y - inset.top,
})
}
}
impl ContentBoxLocal {
#[inline]
#[must_use]
pub const fn to_border_box_local(self, inset: ContentInset) -> BorderBoxLocal {
BorderBoxLocal(LogicalPosition {
x: self.0.x + inset.left,
y: self.0.y + inset.top,
})
}
#[inline]
#[must_use]
pub const fn scrolled_by(self, own_scroll: ScrollOffset) -> ScrolledContentPoint {
ScrolledContentPoint(LogicalPosition {
x: self.0.x + own_scroll.0.x,
y: self.0.y + own_scroll.0.y,
})
}
}
impl ScrolledContentPoint {
#[inline]
#[must_use]
pub const fn unscrolled_by(self, own_scroll: ScrollOffset) -> ContentBoxLocal {
ContentBoxLocal(LogicalPosition {
x: self.0.x - own_scroll.0.x,
y: self.0.y - own_scroll.0.y,
})
}
#[inline]
#[must_use]
pub const fn clamp_to(self, width: f32, height: f32) -> Self {
Self(LogicalPosition {
x: self.0.x.clamp(0.0, width.max(0.0)),
y: self.0.y.clamp(0.0, height.max(0.0)),
})
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Inclusivity {
SelfAndAncestors,
AncestorsOnly,
}
impl Inclusivity {
#[inline]
#[must_use]
pub const fn includes_self(self) -> bool {
matches!(self, Self::SelfAndAncestors)
}
}
#[cfg(test)]
#[path = "spaces_test.rs"]
mod spaces_test;