ratatui_toolkit/primitives/split_layout/methods/
layout_dividers.rs

1use crate::primitives::split_layout::enums::layout_node::LayoutNode;
2use crate::primitives::split_layout::SplitAxis;
3use crate::primitives::split_layout::SplitDividerLayout;
4use crate::primitives::split_layout::SplitLayout;
5use ratatui::layout::Rect;
6
7impl SplitLayout {
8    /// Calculates divider metadata for the current split tree.
9    pub fn layout_dividers(&self, area: Rect) -> Vec<SplitDividerLayout> {
10        let mut dividers = Vec::new();
11        let mut stack = vec![(self.root_index, area)];
12
13        while let Some((node_index, node_area)) = stack.pop() {
14            let Some(node) = self.nodes.get(node_index) else {
15                continue;
16            };
17
18            if let LayoutNode::Split {
19                axis,
20                ratio,
21                first,
22                second,
23            } = node
24            {
25                dividers.push(SplitDividerLayout {
26                    split_index: node_index,
27                    axis: *axis,
28                    area: node_area,
29                    ratio: *ratio,
30                });
31
32                match axis {
33                    SplitAxis::Vertical => {
34                        let first_width = ((node_area.width as u32 * *ratio as u32) / 100) as u16;
35                        let second_width = node_area.width.saturating_sub(first_width);
36                        let first_area = Rect {
37                            x: node_area.x,
38                            y: node_area.y,
39                            width: first_width,
40                            height: node_area.height,
41                        };
42                        let second_area = Rect {
43                            x: node_area.x.saturating_add(first_width),
44                            y: node_area.y,
45                            width: second_width,
46                            height: node_area.height,
47                        };
48                        stack.push((*second, second_area));
49                        stack.push((*first, first_area));
50                    }
51                    SplitAxis::Horizontal => {
52                        let first_height = ((node_area.height as u32 * *ratio as u32) / 100) as u16;
53                        let second_height = node_area.height.saturating_sub(first_height);
54                        let first_area = Rect {
55                            x: node_area.x,
56                            y: node_area.y,
57                            width: node_area.width,
58                            height: first_height,
59                        };
60                        let second_area = Rect {
61                            x: node_area.x,
62                            y: node_area.y.saturating_add(first_height),
63                            width: node_area.width,
64                            height: second_height,
65                        };
66                        stack.push((*second, second_area));
67                        stack.push((*first, first_area));
68                    }
69                }
70            }
71        }
72
73        dividers
74    }
75}