lv_tui_code_highlight/
view.rs1use lv_tui::component::{Component, EventCx, LayoutCx, MeasureCx};
2use lv_tui::event::Event;
3use lv_tui::geom::{Pos, Rect, Size};
4use lv_tui::layout::Constraint;
5use lv_tui::render::RenderCx;
6use lv_tui::style::Style;
7
8use crate::highlight::CodeHighlight;
9
10pub struct CodeView {
12 hl: CodeHighlight,
13 scroll: u16,
14 rect: Rect,
15}
16
17impl CodeView {
18 pub fn new(code: &str, language: &str) -> Self {
19 Self { hl: CodeHighlight::new(code, language), scroll: 0, rect: Rect::default() }
20 }
21}
22
23impl Component for CodeView {
24 fn render(&self, cx: &mut RenderCx) {
25 let vp = self.rect;
26 let visible = vp.height.max(1) as usize;
27 let start = (self.scroll as usize).min(self.hl.line_count().saturating_sub(visible));
28 let end = (start + visible).min(self.hl.line_count());
29
30 for i in start..end {
31 let y = vp.y.saturating_add((i - start) as u16);
32 self.hl.render_line(i, cx.buffer, Pos { x: vp.x, y }, vp);
33 }
34 }
35
36 fn measure(&self, _c: Constraint, _cx: &mut MeasureCx) -> Size {
37 Size { width: 80, height: self.hl.line_count().max(1) as u16 }
38 }
39
40 fn event(&mut self, event: &Event, cx: &mut EventCx) {
41 if let Event::Key(key) = event {
42 let visible = self.rect.height.max(1) as u16;
43 let total = self.hl.line_count().max(1) as u16;
44 match &key.key {
45 lv_tui::event::Key::Up => { self.scroll = self.scroll.saturating_sub(1); cx.invalidate_paint(); }
46 lv_tui::event::Key::Down => { self.scroll = (self.scroll + 1).min(total.saturating_sub(visible)); cx.invalidate_paint(); }
47 lv_tui::event::Key::PageUp => { self.scroll = self.scroll.saturating_sub(visible); cx.invalidate_paint(); }
48 lv_tui::event::Key::PageDown => { self.scroll = (self.scroll + visible).min(total.saturating_sub(visible)); cx.invalidate_paint(); }
49 _ => {}
50 }
51 }
52 }
53
54 fn layout(&mut self, rect: Rect, _cx: &mut LayoutCx) { self.rect = rect; }
55 fn focusable(&self) -> bool { false }
56 fn style(&self) -> Style { Style::default() }
57}