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}