Skip to main content

azul_core/
dom_table.rs

1// Table layout support for generating anonymous table elements
2// Based on CSS 2.1 Section 17.2.1: Anonymous table objects
3
4use alloc::vec::Vec;
5
6use azul_css::props::layout::LayoutDisplay;
7
8use crate::{
9    dom::{NodeData, NodeType},
10    id::NodeId,
11    styled_dom::StyledDom,
12};
13
14/// Error type for table anonymous element generation
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum TableAnonymousError {
17    /// Invalid node ID provided
18    InvalidNodeId,
19    /// No display property found for node
20    NoDisplayProperty,
21}
22
23/// Generates anonymous table elements according to CSS table layout rules.
24///
25/// This function works on StyledDom (not Dom) because it needs access to computed
26/// CSS display property values to determine which elements need wrapping.
27///
28/// This function ensures that:
29/// - Table elements have proper table-row and table-cell children
30/// - Non-table children of tables are wrapped in anonymous table-row and table-cell boxes
31/// - The resulting DOM tree is suitable for table layout algorithms
32/// - All generated anonymous nodes are marked with is_anonymous=true
33///
34/// Must be called after CSS cascade but before layout calculation.
35///
36/// Implementation follows CSS 2.2 Section 17.2.1:
37/// - Stage 1: Remove irrelevant whitespace
38/// - Stage 2: Generate missing child wrappers
39/// - Stage 3: Generate missing parents
40pub fn generate_anonymous_table_elements(
41    styled_dom: &mut StyledDom,
42) -> Result<(), TableAnonymousError> {
43    // TODO: Implement the full 3-stage algorithm
44    // This is a complex task that requires:
45    // 1. Traversing the entire tree
46    // 2. Identifying nodes with table display values
47    // 3. Checking if their children have correct display values
48    // 4. Inserting anonymous wrapper nodes where needed
49    // 5. Marking all generated nodes with is_anonymous=true
50    //
51    // For now, this is a placeholder that returns Ok(())
52    // The actual implementation will need to:
53    // - Access styled_dom.node_hierarchy for tree structure
54    // - Access styled_dom.node_data for node information
55    // - Access styled_dom.css_property_cache for display properties
56    // - Insert new nodes into both hierarchy and data containers
57    // - Update parent-child-sibling relationships
58    //
59    // This is left for future implementation as it requires careful
60    // manipulation of the arena-based data structures.
61
62    Ok(())
63}
64
65/// Helper function to check if a display value represents a proper table child
66fn is_proper_table_child(display: &LayoutDisplay) -> bool {
67    matches!(
68        display,
69        LayoutDisplay::TableRowGroup
70            | LayoutDisplay::TableHeaderGroup
71            | LayoutDisplay::TableFooterGroup
72            | LayoutDisplay::TableRow
73            | LayoutDisplay::TableCaption
74            | LayoutDisplay::TableColumn
75            | LayoutDisplay::TableColumnGroup
76    )
77}
78
79/// Helper function to check if a display value represents a table row
80fn is_table_row(display: &LayoutDisplay) -> bool {
81    matches!(display, LayoutDisplay::TableRow)
82}
83
84/// Helper function to check if a display value represents a table cell
85fn is_table_cell(display: &LayoutDisplay) -> bool {
86    matches!(display, LayoutDisplay::TableCell)
87}
88
89/// Helper function to check if a display value represents a table or inline-table
90fn is_table_element(display: &LayoutDisplay) -> bool {
91    matches!(display, LayoutDisplay::Table | LayoutDisplay::InlineTable)
92}
93
94/// Helper function to get the computed display property for a node
95fn get_node_display(styled_dom: &StyledDom, node_id: NodeId) -> Option<LayoutDisplay> {
96    // Get display property from CSS property cache
97    let cache = styled_dom.get_css_property_cache();
98    let node_data = &styled_dom.node_data.as_ref()[node_id.index()];
99    let node_state = &styled_dom.styled_nodes.as_container()[node_id].styled_node_state;
100
101    cache
102        .get_display(node_data, &node_id, node_state)
103        .and_then(|value| value.get_property().cloned())
104}