ratatui_toolkit/widgets/code_diff/widget/traits/
widget.rs

1use ratatui::buffer::Buffer;
2use ratatui::layout::Rect;
3use ratatui::widgets::Widget;
4
5use crate::widgets::code_diff::code_diff::methods::helpers::{
6    render_diff_content, render_header, render_side_by_side, render_sidebar,
7};
8use crate::widgets::code_diff::code_diff::CodeDiff;
9use crate::widgets::code_diff::enums::DiffStyle;
10
11impl Widget for CodeDiff {
12    /// Renders the diff widget to the given buffer.
13    ///
14    /// The widget renders:
15    /// 1. If sidebar enabled and visible: file tree on left, diff on right
16    /// 2. Otherwise: just the diff content
17    ///
18    /// Each panel includes:
19    /// - A header bar with file path and stats (if file path is set)
20    /// - Diff hunks in the configured style (side-by-side or unified)
21    ///
22    /// # Arguments
23    ///
24    /// * `area` - The area to render the widget in
25    /// * `buf` - The buffer to render to
26    fn render(self, area: Rect, buf: &mut Buffer) {
27        (&self).render(area, buf);
28    }
29}
30
31impl Widget for &CodeDiff {
32    /// Renders the diff widget from a reference.
33    fn render(self, area: Rect, buf: &mut Buffer) {
34        if area.width == 0 || area.height == 0 {
35            return;
36        }
37
38        // Check if we should show sidebar
39        if self.show_sidebar && self.config.sidebar_enabled {
40            // Calculate split areas using ResizableSplit's percentage
41            let sidebar_width =
42                (area.width as u32 * self.sidebar_split.split_percent as u32 / 100) as u16;
43            let sidebar_width = sidebar_width.max(1).min(area.width.saturating_sub(10));
44
45            let sidebar_area = Rect {
46                x: area.x,
47                y: area.y,
48                width: sidebar_width,
49                height: area.height,
50            };
51
52            let diff_area = Rect {
53                x: area.x + sidebar_width,
54                y: area.y,
55                width: area.width.saturating_sub(sidebar_width),
56                height: area.height,
57            };
58
59            // Render sidebar
60            render_sidebar(self, sidebar_area, buf);
61
62            // Render diff content with border
63            render_diff_content(self, diff_area, buf, true);
64        } else {
65            // Just render diff without sidebar
66            // Use the old direct rendering for backwards compatibility
67            let header_height = render_header(self, area, buf);
68
69            let content_area = Rect {
70                x: area.x,
71                y: area.y + header_height,
72                width: area.width,
73                height: area.height.saturating_sub(header_height),
74            };
75
76            if content_area.height == 0 {
77                return;
78            }
79
80            match self.config.style {
81                DiffStyle::SideBySide => {
82                    render_side_by_side(self, content_area, buf);
83                }
84                DiffStyle::Unified | DiffStyle::Inline => {
85                    render_side_by_side(self, content_area, buf);
86                }
87            }
88        }
89    }
90}