gemini_engine/view/scale_to_fit.rs
1use crate::{core::Canvas, view::term_utils};
2
3use super::{ColChar, Vec2D, View};
4
5/// A wrapper around a [`View`] which auto resizes to fit the terminal window
6///
7/// `ScaleFitView`'s [`update()`](ScaleFitView::update()) function should be used in place of `View`'s `clear()` function to handle auto-resizing and clearing
8#[non_exhaustive]
9pub struct ScaleFitView {
10 /// The [`View`] that this struct wraps around
11 pub view: View,
12 /// How many rows to leave clear below the rendered view. You might want to set this if you have more than one line of text after rendered text
13 pub empty_row_count: i64,
14}
15
16impl ScaleFitView {
17 /// Create a new `ScaleFitView` with the given background `ColChar`
18 #[must_use]
19 pub fn new(background_char: ColChar) -> Self {
20 let mut tmp = Self {
21 view: View::new(0, 0, background_char),
22 empty_row_count: 1,
23 };
24 tmp.update();
25 tmp
26 }
27
28 /// Return the `ScaleFitView` with an updated `empty_row_count` property. Consumes the original `ScaleFitView`
29 #[must_use]
30 pub const fn with_empty_row_count(mut self, empty_row_count: i64) -> Self {
31 self.empty_row_count = empty_row_count;
32 self
33 }
34
35 /// Returns the size of the terminal, with the y adjusted as intended using the [`empty_row_count`](ScaleFitView::empty_row_count) property
36 ///
37 /// # Panics
38 /// Panics if there is no TTY to get the terminal size of, as per [`terminal_size::terminal_size()`]
39 #[must_use]
40 pub fn intended_size(&self) -> Vec2D {
41 let mut term_size =
42 term_utils::get_terminal_size_as_vec2d().expect("Failed to get terminal size");
43 term_size.y -= self.empty_row_count + 1;
44
45 term_size.max(Vec2D::ZERO)
46 }
47
48 /// Resize and clear the `View`
49 ///
50 /// # Panics
51 /// Panics if there is no TTY to get the terminal size of, as per [`terminal_size::terminal_size()`]
52 pub fn update(&mut self) {
53 let term_size = self.intended_size();
54 self.view.width = term_size.x as usize;
55 self.view.height = term_size.y as usize;
56
57 self.view.clear();
58 }
59}
60
61impl Canvas for ScaleFitView {
62 fn plot(&mut self, pos: Vec2D, c: ColChar) {
63 self.view.plot(pos, c);
64 }
65}