ming_wm_lib/components/
paragraph.rs

1use std::vec;
2use std::vec::Vec;
3
4use crate::framebuffer_types::{ Dimensions, Point };
5use crate::themes::ThemeInfo;
6use crate::messages::WindowMessage;
7use crate::window_manager_types::DrawInstructions;
8use crate::utils::calc_actual_lines;
9use crate::components::Component;
10
11const MONO_WIDTH: u8 = 10;
12const LINE_HEIGHT: usize = 18;
13
14pub struct Paragraph<T> {
15  name_: String,
16  actual_lines: Vec<(bool, usize, String)>, //first, line #, actual line
17  top_left: Point,
18  size: Dimensions,
19  line_pos: usize,
20  key_return: T,
21}
22
23impl<T: Copy> Component<T> for Paragraph<T> {
24  fn handle_message(&mut self, message: WindowMessage) -> Option<T> {
25    if let WindowMessage::KeyPress(key_press) = message {
26      if key_press.key == 'j' {
27        //down
28        if self.line_pos != self.actual_lines.len() - 1 {
29          self.line_pos += 1;
30        }
31        Some(self.key_return)
32      } else if key_press.key == 'k' {
33        //up
34        if self.line_pos != 0 {
35          self.line_pos -= 1;
36        }
37        Some(self.key_return)
38      } else {
39        None
40      }
41    } else {
42      None
43    }
44  }
45
46  fn draw(&self, theme_info: &ThemeInfo) -> Vec<DrawInstructions> {
47    let mut instructions = Vec::new();
48    let max_lines = self.size[1] / LINE_HEIGHT;
49    let mut start_y = self.top_left[1];
50    for line in self.actual_lines.iter().skip(self.line_pos).take(max_lines) {
51      instructions.push(DrawInstructions::Text([self.top_left[0], start_y], vec!["nimbus-romono".to_string()], line.2.clone(), theme_info.text, theme_info.background, Some(0), Some(MONO_WIDTH)));
52      start_y += LINE_HEIGHT;
53    }
54    instructions
55  }
56
57  //properties
58  fn focusable(&self) -> bool {
59    true
60  }
61
62  fn clickable(&self) -> bool {
63    false
64  }
65  
66  fn name(&self) -> &String {
67    &self.name_
68  }
69}
70
71impl<T> Paragraph<T> {
72  pub fn new(name_: String, top_left: Point, size: Dimensions, text: String, key_return: T) -> Self {
73    let mut s = Self {
74      name_,
75      actual_lines: Vec::new(),
76      top_left,
77      size,
78      line_pos: 0,
79      key_return,
80    };
81    s.new_text(text);
82    s
83  }
84
85  pub fn new_text(&mut self, text: String) {
86    let max_chars_per_line = self.size[0] / MONO_WIDTH as usize;
87    let lines: Vec<String> = text.split("\n").map(|s| s.to_string()).collect();
88    self.actual_lines = calc_actual_lines(lines.iter(), max_chars_per_line, true);
89  }
90}
91