use crate::geometry::{AbsoluteAxis, Line, Point, Rect, Size};
use crate::style::AvailableSpace;
use crate::style_helpers::TaffyMaxContent;
use crate::util::sys::{f32_max, f32_min};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum RunMode {
PerformLayout,
ComputeSize,
PerformHiddenLayout,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum SizingMode {
ContentSize,
InherentSize,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct CollapsibleMarginSet {
positive: f32,
negative: f32,
}
impl CollapsibleMarginSet {
pub const ZERO: Self = Self { positive: 0.0, negative: 0.0 };
pub fn from_margin(margin: f32) -> Self {
if margin >= 0.0 {
Self { positive: margin, negative: 0.0 }
} else {
Self { positive: 0.0, negative: margin }
}
}
pub fn collapse_with_margin(mut self, margin: f32) -> Self {
if margin >= 0.0 {
self.positive = f32_max(self.positive, margin);
} else {
self.negative = f32_min(self.negative, margin);
}
self
}
pub fn collapse_with_set(mut self, other: CollapsibleMarginSet) -> Self {
self.positive = f32_max(self.positive, other.positive);
self.negative = f32_min(self.negative, other.negative);
self
}
pub fn resolve(&self) -> f32 {
self.positive + self.negative
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum RequestedAxis {
Horizontal,
Vertical,
Both,
}
impl From<AbsoluteAxis> for RequestedAxis {
fn from(value: AbsoluteAxis) -> Self {
match value {
AbsoluteAxis::Horizontal => RequestedAxis::Horizontal,
AbsoluteAxis::Vertical => RequestedAxis::Vertical,
}
}
}
impl TryFrom<RequestedAxis> for AbsoluteAxis {
type Error = ();
fn try_from(value: RequestedAxis) -> Result<Self, Self::Error> {
match value {
RequestedAxis::Horizontal => Ok(AbsoluteAxis::Horizontal),
RequestedAxis::Vertical => Ok(AbsoluteAxis::Vertical),
RequestedAxis::Both => Err(()),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct LayoutInput {
pub run_mode: RunMode,
pub sizing_mode: SizingMode,
pub axis: RequestedAxis,
pub known_dimensions: Size<Option<f32>>,
pub parent_size: Size<Option<f32>>,
pub available_space: Size<AvailableSpace>,
pub vertical_margins_are_collapsible: Line<bool>,
}
impl LayoutInput {
pub const HIDDEN: LayoutInput = LayoutInput {
run_mode: RunMode::PerformHiddenLayout,
known_dimensions: Size::NONE,
parent_size: Size::NONE,
available_space: Size::MAX_CONTENT,
sizing_mode: SizingMode::InherentSize,
axis: RequestedAxis::Both,
vertical_margins_are_collapsible: Line::FALSE,
};
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct LayoutOutput {
pub size: Size<f32>,
#[cfg(feature = "content_size")]
pub content_size: Size<f32>,
pub first_baselines: Point<Option<f32>>,
pub top_margin: CollapsibleMarginSet,
pub bottom_margin: CollapsibleMarginSet,
pub margins_can_collapse_through: bool,
}
impl LayoutOutput {
pub const HIDDEN: Self = Self {
size: Size::ZERO,
#[cfg(feature = "content_size")]
content_size: Size::ZERO,
first_baselines: Point::NONE,
top_margin: CollapsibleMarginSet::ZERO,
bottom_margin: CollapsibleMarginSet::ZERO,
margins_can_collapse_through: false,
};
pub const DEFAULT: Self = Self::HIDDEN;
pub fn from_sizes_and_baselines(
size: Size<f32>,
#[cfg_attr(not(feature = "content_size"), allow(unused_variables))] content_size: Size<f32>,
first_baselines: Point<Option<f32>>,
) -> Self {
Self {
size,
#[cfg(feature = "content_size")]
content_size,
first_baselines,
top_margin: CollapsibleMarginSet::ZERO,
bottom_margin: CollapsibleMarginSet::ZERO,
margins_can_collapse_through: false,
}
}
pub fn from_sizes(size: Size<f32>, content_size: Size<f32>) -> Self {
Self::from_sizes_and_baselines(size, content_size, Point::NONE)
}
pub fn from_outer_size(size: Size<f32>) -> Self {
Self::from_sizes(size, Size::zero())
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct Layout {
pub order: u32,
pub location: Point<f32>,
pub size: Size<f32>,
#[cfg(feature = "content_size")]
pub content_size: Size<f32>,
pub scrollbar_size: Size<f32>,
pub border: Rect<f32>,
pub padding: Rect<f32>,
pub margin: Rect<f32>,
}
impl Default for Layout {
fn default() -> Self {
Self::new()
}
}
impl Layout {
#[must_use]
pub const fn new() -> Self {
Self {
order: 0,
location: Point::ZERO,
size: Size::zero(),
#[cfg(feature = "content_size")]
content_size: Size::zero(),
scrollbar_size: Size::zero(),
border: Rect::zero(),
padding: Rect::zero(),
margin: Rect::zero(),
}
}
#[must_use]
pub const fn with_order(order: u32) -> Self {
Self {
order,
size: Size::zero(),
location: Point::ZERO,
#[cfg(feature = "content_size")]
content_size: Size::zero(),
scrollbar_size: Size::zero(),
border: Rect::zero(),
padding: Rect::zero(),
margin: Rect::zero(),
}
}
#[inline]
pub fn content_box_width(&self) -> f32 {
self.size.width - self.padding.left - self.padding.right - self.border.left - self.border.right
}
#[inline]
pub fn content_box_height(&self) -> f32 {
self.size.height - self.padding.top - self.padding.bottom - self.border.top - self.border.bottom
}
#[inline]
pub fn content_box_size(&self) -> Size<f32> {
Size { width: self.content_box_width(), height: self.content_box_height() }
}
pub fn content_box_x(&self) -> f32 {
self.location.x + self.border.left + self.padding.left
}
pub fn content_box_y(&self) -> f32 {
self.location.y + self.border.top + self.padding.top
}
}
#[cfg(feature = "content_size")]
impl Layout {
pub fn scroll_width(&self) -> f32 {
f32_max(
0.0,
self.content_size.width + f32_min(self.scrollbar_size.width, self.size.width) - self.size.width
+ self.border.right,
)
}
pub fn scroll_height(&self) -> f32 {
f32_max(
0.0,
self.content_size.height + f32_min(self.scrollbar_size.height, self.size.height) - self.size.height
+ self.border.bottom,
)
}
}
#[cfg(feature = "detailed_layout_info")]
#[derive(Debug, Clone, PartialEq)]
pub enum DetailedLayoutInfo {
#[cfg(feature = "grid")]
Grid(Box<crate::compute::grid::DetailedGridInfo>),
None,
}