interface_builder/builder/components/
page.rs

1use std::{io::{stdout, Stdout}, fmt::Display};
2
3use crossterm::{execute, cursor, style::Print};
4
5use crate::builder::tools::{clear_terminal, move_cursor_to};
6
7use super::tools;
8
9pub enum Line<'a> {
10  String(String),
11  Str(&'a str),
12}
13impl<'a> Display for Line<'a> {
14  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
15    match self {
16      Line::String(value) => write!(f, "{}", value),
17      Line::Str(value) => write!(f, "{}", value),
18    }
19  }
20}
21
22pub struct Page<'a> {
23  stdout: Stdout,
24  width: u16,
25  height: Option<u16>,
26  title: Option<&'a str>,
27  content: Vec<Line<'a>>,
28  footer: Vec<Line<'a>>
29}
30impl<'a> Page<'a> {
31  pub fn new(width: u16, height: Option<u16>) -> Page<'a> {
32    Page {
33      stdout: stdout(),
34      width, height,
35      title: None,
36      content: Vec::new(),
37      footer: Vec::new()
38    }
39  }
40  pub fn title(&mut self, title: &'a str) {
41    self.title = Some(title);
42  }
43  pub fn content(&mut self, content: Vec<Line<'a>>){
44    self.content = content
45  }
46  pub fn footer(&mut self, footer: Vec<Line<'a>>) {
47    self.footer = footer
48  }
49
50  fn print_box(&self) {
51    match self.height {
52      Some(height) => tools::bordered_box::print(self.width, height),
53      None => tools::bordered_box::print(self.width, self.content.len() as u16 + 4)
54    }
55  }
56  fn print_title(&mut self) {
57    match &self.title {
58      Some(title) => {
59        execute!(
60          self.stdout,
61          cursor::MoveTo(5, 1),
62          Print(format!(" {} ", &title))
63        ).expect("Print title failed");
64      },
65      None => ()
66    }
67  }
68  fn print_content(&mut self) {
69    for (i, line) in self.content.iter().enumerate() {
70      execute!(
71        self.stdout,
72        cursor::MoveTo(5, i as u16 + 3),
73        Print(line)
74      ).expect("Failed on print content");
75    }
76  }
77  fn print_footer(&mut self) {
78    for (i, line) in self.footer.iter().enumerate() {
79      let y = match self.height {
80        Some(height) => height + i as u16 + 1,
81        None => i as u16 + self.content.len() as u16 + 5
82      };
83      execute!(
84        self.stdout,
85        cursor::MoveTo(5, y),
86        Print(line)
87      ).expect("Failed on print content");
88    }
89  }
90  pub fn print(&mut self) {
91    clear_terminal();
92    self.print_box();
93    self.print_title();
94    self.print_content();
95    self.print_footer();
96    let y = match self.height {
97      Some(height) => height + self.footer.len() as u16 + 2,
98      None => self.content.len() as u16 + self.footer.len() as u16 + 6
99    };
100    move_cursor_to(0, y)
101  }
102}