From 950a0eb1322f15e5d1083f4793b55d52061718de Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Thu, 1 Aug 2024 13:01:12 +1200 Subject: [PATCH] Add is_table for block items (#701) --- src/compute/block.rs | 33 ++++++++++++++++++++------------- src/style/block.rs | 11 ++++++++++- src/style/mod.rs | 23 ++++++++++++++++++++++- src/tree/traits.rs | 4 ++-- 4 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/compute/block.rs b/src/compute/block.rs index 02f5d14a7..eeb2aa009 100644 --- a/src/compute/block.rs +++ b/src/compute/block.rs @@ -9,7 +9,7 @@ use crate::util::sys::f32_max; use crate::util::sys::Vec; use crate::util::MaybeMath; use crate::util::{MaybeResolve, ResolveOrZero}; -use crate::{BlockContainerStyle, BoxGenerationMode, BoxSizing, LayoutBlockContainer, TextAlign}; +use crate::{BlockContainerStyle, BlockItemStyle, BoxGenerationMode, BoxSizing, LayoutBlockContainer, TextAlign}; #[cfg(feature = "content_size")] use super::common::content_size::compute_content_size_contribution; @@ -23,6 +23,9 @@ struct BlockItem { /// and controls the order in which the nodes are placed order: u32, + /// Items that are tables don't have stretch sizing applied to them + is_table: bool, + /// The base size of this item size: Size>, /// The minimum allowable size of this item @@ -310,6 +313,7 @@ fn generate_item_list( BlockItem { node_id: child_node_id, order: order as u32, + is_table: child_style.is_table(), size: child_style .size() .maybe_resolve(node_inner_size) @@ -408,18 +412,21 @@ fn perform_final_layout_on_in_flow_children( let item_margin = item.margin.map(|margin| margin.resolve_to_option(container_outer_width)); let item_non_auto_margin = item_margin.map(|m| m.unwrap_or(0.0)); let item_non_auto_x_margin_sum = item_non_auto_margin.horizontal_axis_sum(); - let known_dimensions = item - .size - .map_width(|width| { - // TODO: Allow stretch-sizing to be conditional, as there are exceptions. - // e.g. Table children of blocks do not stretch fit - Some( - width - .unwrap_or(container_inner_width - item_non_auto_x_margin_sum) - .maybe_clamp(item.min_size.width, item.max_size.width), - ) - }) - .maybe_clamp(item.min_size, item.max_size); + let known_dimensions = if item.is_table { + Size::NONE + } else { + item.size + .map_width(|width| { + // TODO: Allow stretch-sizing to be conditional, as there are exceptions. + // e.g. Table children of blocks do not stretch fit + Some( + width + .unwrap_or(container_inner_width - item_non_auto_x_margin_sum) + .maybe_clamp(item.min_size.width, item.max_size.width), + ) + }) + .maybe_clamp(item.min_size, item.max_size) + }; let item_layout = tree.perform_child_layout( item.node_id, diff --git a/src/style/block.rs b/src/style/block.rs index 04b758336..7cea35eda 100644 --- a/src/style/block.rs +++ b/src/style/block.rs @@ -1,7 +1,7 @@ //! Style types for Block layout use crate::{CoreStyle, Style}; -/// The set of styles required for a CSS Grid item (child of a CSS Grid container) +/// The set of styles required for a Block layout container pub trait BlockContainerStyle: CoreStyle { /// Defines which row in the grid the item should start and end at #[inline(always)] @@ -10,6 +10,15 @@ pub trait BlockContainerStyle: CoreStyle { } } +/// The set of styles required for a Block layout item (child of a Block container) +pub trait BlockItemStyle: CoreStyle { + /// Whether the item is a table. Table children are handled specially in block layout. + #[inline(always)] + fn is_table(&self) -> bool { + false + } +} + /// Used by block layout to implement the legacy behaviour of `
` and `
` #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] diff --git a/src/style/mod.rs b/src/style/mod.rs index 71a6f608e..9c35d202b 100644 --- a/src/style/mod.rs +++ b/src/style/mod.rs @@ -13,7 +13,7 @@ pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, J pub use self::dimension::{AvailableSpace, Dimension, LengthPercentage, LengthPercentageAuto}; #[cfg(feature = "block_layout")] -pub use self::block::{BlockContainerStyle, TextAlign}; +pub use self::block::{BlockContainerStyle, BlockItemStyle, TextAlign}; #[cfg(feature = "flexbox")] pub use self::flex::{FlexDirection, FlexWrap, FlexboxContainerStyle, FlexboxItemStyle}; #[cfg(feature = "grid")] @@ -330,6 +330,9 @@ impl Overflow { pub struct Style { /// What layout strategy should be used? pub display: Display, + /// Whether a child is display:table or not. This affects children of block layouts. + /// This should really be part of `Display`, but it is currently seperate because table layout isn't implemented + pub item_is_table: bool, /// Should size styles apply to the content box or the border box of the node pub box_sizing: BoxSizing, @@ -456,6 +459,7 @@ impl Style { /// The [`Default`] layout, in a form that can be used in const functions pub const DEFAULT: Style = Style { display: Display::DEFAULT, + item_is_table: false, box_sizing: BoxSizing::BorderBox, overflow: Point { x: Overflow::Visible, y: Overflow::Visible }, scrollbar_width: 0.0, @@ -659,6 +663,22 @@ impl BlockContainerStyle for &'_ T { } } +#[cfg(feature = "block_layout")] +impl BlockItemStyle for Style { + #[inline(always)] + fn is_table(&self) -> bool { + self.item_is_table + } +} + +#[cfg(feature = "block_layout")] +impl BlockItemStyle for &'_ T { + #[inline(always)] + fn is_table(&self) -> bool { + (*self).is_table() + } +} + #[cfg(feature = "flexbox")] impl FlexboxContainerStyle for Style { #[inline(always)] @@ -895,6 +915,7 @@ mod tests { let old_defaults = Style { display: Default::default(), + item_is_table: false, box_sizing: Default::default(), overflow: Default::default(), scrollbar_width: 0.0, diff --git a/src/tree/traits.rs b/src/tree/traits.rs index e9382ae95..7c5a9ab35 100644 --- a/src/tree/traits.rs +++ b/src/tree/traits.rs @@ -134,7 +134,7 @@ use crate::style::{FlexboxContainerStyle, FlexboxItemStyle}; #[cfg(feature = "grid")] use crate::style::{GridContainerStyle, GridItemStyle}; #[cfg(feature = "block_layout")] -use crate::BlockContainerStyle; +use crate::{BlockContainerStyle, BlockItemStyle}; use core::ops::{Deref, DerefMut}; /// This trait is Taffy's abstraction for downward tree traversal. @@ -257,7 +257,7 @@ pub trait LayoutBlockContainer: LayoutPartialTree { where Self: 'a; /// The style type representing each CSS Block item's styles - type BlockItemStyle<'a>: CoreStyle + type BlockItemStyle<'a>: BlockItemStyle where Self: 'a;