Skip to main content

par_term_render/renderer/
types.rs

1// Render-input data types: the per-pane, divider, and title descriptions the
2// frontend hands to `Renderer`, plus the viewport mapping for separator marks.
3// These are plain data with no dependency on `Renderer` itself.
4
5use crate::cell_renderer::{Cell, PaneViewport};
6use par_term_config::SeparatorMark;
7
8/// Compute which separator marks are visible in the current viewport.
9///
10/// Maps absolute scrollback line numbers to screen rows for the current view.
11/// Returns only the marks whose absolute line index falls within the visible
12/// window `[viewport_start, viewport_start + visible_lines)`, converting each
13/// to a zero-based screen row. No deduplication or merging is performed; marks
14/// are returned in the same order they appear in `marks`.
15pub fn compute_visible_separator_marks(
16    marks: &[par_term_config::ScrollbackMark],
17    scrollback_len: usize,
18    scroll_offset: usize,
19    visible_lines: usize,
20) -> Vec<SeparatorMark> {
21    let mut out = Vec::new();
22    fill_visible_separator_marks(
23        &mut out,
24        marks,
25        scrollback_len,
26        scroll_offset,
27        visible_lines,
28    );
29    out
30}
31
32/// Fill `out` with the separator marks visible in the current viewport, reusing
33/// the provided allocation to avoid a per-call heap allocation on the render hot path.
34///
35/// The buffer is cleared on entry. Semantics are identical to
36/// [`compute_visible_separator_marks`].
37pub(crate) fn fill_visible_separator_marks(
38    out: &mut Vec<SeparatorMark>,
39    marks: &[par_term_config::ScrollbackMark],
40    scrollback_len: usize,
41    scroll_offset: usize,
42    visible_lines: usize,
43) {
44    out.clear();
45    let viewport_start = scrollback_len.saturating_sub(scroll_offset);
46    let viewport_end = viewport_start + visible_lines;
47    for mark in marks {
48        if mark.line >= viewport_start && mark.line < viewport_end {
49            let screen_row = mark.line - viewport_start;
50            out.push((screen_row, mark.exit_code, mark.color));
51        }
52    }
53}
54
55/// Information needed to render a single pane
56pub struct PaneRenderInfo<'a> {
57    /// Viewport bounds and state for this pane
58    pub viewport: PaneViewport,
59    /// Cells to render (should match viewport grid size)
60    pub cells: &'a [Cell],
61    /// Grid dimensions (cols, rows)
62    pub grid_size: (usize, usize),
63    /// Cursor position within this pane (col, row), or None if no cursor visible
64    pub cursor_pos: Option<(usize, usize)>,
65    /// Cursor opacity (0.0 = hidden, 1.0 = fully visible)
66    pub cursor_opacity: f32,
67    /// Whether this pane has a scrollbar visible
68    pub show_scrollbar: bool,
69    /// Scrollback marks for this pane
70    pub marks: Vec<par_term_config::ScrollbackMark>,
71    /// Scrollback length for this pane (needed for separator mark mapping)
72    pub scrollback_len: usize,
73    /// Current scroll offset for this pane (needed for separator mark mapping)
74    pub scroll_offset: usize,
75    /// Per-pane background image override (None = use global background)
76    pub background: Option<par_term_config::PaneBackground>,
77    /// Inline graphics (Sixel/iTerm2/Kitty) to render for this pane
78    pub graphics: Vec<par_term_emu_core_rust::graphics::TerminalGraphic>,
79    /// Kitty virtual placements (U=1) used as prototypes for Unicode placeholder
80    /// rendering. The actual on-screen position is taken from the placeholder
81    /// cells in `cells`, not from each graphic's `position` field.
82    pub virtual_placements: Vec<par_term_emu_core_rust::graphics::TerminalGraphic>,
83}
84
85/// Information needed to render a pane divider
86#[derive(Clone, Copy, Debug)]
87pub struct DividerRenderInfo {
88    /// X position in pixels
89    pub x: f32,
90    /// Y position in pixels
91    pub y: f32,
92    /// Width in pixels
93    pub width: f32,
94    /// Height in pixels
95    pub height: f32,
96    /// Whether this divider is currently being hovered
97    pub hovered: bool,
98}
99
100impl DividerRenderInfo {
101    /// Create from a DividerRect
102    pub fn from_rect(rect: &par_term_config::DividerRect, hovered: bool) -> Self {
103        Self {
104            x: rect.x,
105            y: rect.y,
106            width: rect.width,
107            height: rect.height,
108            hovered,
109        }
110    }
111}
112
113/// Information needed to render a pane title bar
114#[derive(Clone, Debug)]
115pub struct PaneTitleInfo {
116    /// X position of the title bar in pixels
117    pub x: f32,
118    /// Y position of the title bar in pixels
119    pub y: f32,
120    /// Width of the title bar in pixels
121    pub width: f32,
122    /// Height of the title bar in pixels
123    pub height: f32,
124    /// Title text to display
125    pub title: String,
126    /// Whether this pane is focused
127    pub focused: bool,
128    /// Text color [R, G, B] as floats (0.0-1.0)
129    pub text_color: [f32; 3],
130    /// Background color [R, G, B] as floats (0.0-1.0)
131    pub bg_color: [f32; 3],
132}
133
134/// Settings for rendering pane dividers and focus indicators
135#[derive(Clone, Copy, Debug)]
136pub struct PaneDividerSettings {
137    /// Color for dividers [R, G, B] as floats (0.0-1.0)
138    pub divider_color: [f32; 3],
139    /// Color when hovering over dividers [R, G, B] as floats (0.0-1.0)
140    pub hover_color: [f32; 3],
141    /// Whether to show focus indicator around focused pane
142    pub show_focus_indicator: bool,
143    /// Color for focus indicator [R, G, B] as floats (0.0-1.0)
144    pub focus_color: [f32; 3],
145    /// Width of focus indicator border in pixels
146    pub focus_width: f32,
147    /// Style of dividers (solid, double, dashed, shadow)
148    pub divider_style: par_term_config::DividerStyle,
149}
150
151impl Default for PaneDividerSettings {
152    fn default() -> Self {
153        Self {
154            divider_color: [0.3, 0.3, 0.3],
155            hover_color: [0.5, 0.6, 0.8],
156            show_focus_indicator: true,
157            focus_color: [0.4, 0.6, 1.0],
158            focus_width: 1.0,
159            divider_style: par_term_config::DividerStyle::default(),
160        }
161    }
162}