1use log::{error};
2use ratatui::{
3 layout::Rect,
4 widgets::{Paragraph, Wrap},
5};
6
7use crate::{
8 config::{PreviewConfig, PreviewLayoutSetting},
9 proc::Preview,
10};
11
12#[derive(Debug)]
13pub struct PreviewUI {
14 pub view: Preview,
15 config: PreviewConfig,
16 pub layout_idx: usize,
17 pub area: Rect,
18 pub offset: u16,
19}
20
21impl PreviewUI {
22 pub fn new(view: Preview, config: PreviewConfig) -> Self {
23 Self {
24 view,
25 config,
26 layout_idx: 0,
27 offset: 0,
28 area: Rect::default()
29 }
30 }
31
32 pub fn is_show(&self) -> bool {
33 self.config.show && self.layout().max != 0 }
36 pub fn show<const SHOW: bool>(&mut self) -> bool {
37 let previous = self.config.show;
38 self.config.show = SHOW;
39 previous != SHOW
40 }
41 pub fn toggle_show(&mut self) {
42 self.config.show = !self.config.show;
43 }
44
45 pub fn layout(&self) -> &PreviewLayoutSetting {
46 &self.config.layout[self.layout_idx].layout
47 }
48 pub fn command(&self) -> &String {
49 &self.config.layout[self.layout_idx].command
50 }
51
52 pub fn wrap(&mut self, wrap: bool) {
53 self.config.wrap = wrap;
54 }
55
56 pub fn is_wrap(&self) -> bool {
57 self.config.wrap
58 }
59
60 pub fn up(&mut self, n: u16) {
73 if self.offset >= n {
74 self.offset -= n;
75 } else if self.config.scroll_wrap {
76 let total_lines = self.view.len() as u16;
77 self.offset = total_lines.saturating_sub(n - self.offset);
78 } else {
79 self.offset = 0;
80 }
81 }
82
83 pub fn down(&mut self, n: u16) {
84 let total_lines = self.view.len() as u16;
85
86 if self.offset + n > total_lines {
87 if self.config.scroll_wrap {
88 self.offset = 0;
89 } else {
90 self.offset = total_lines;
91 }
92 } else {
93 self.offset += n;
94 }
95 }
96
97
98 pub fn update_dimensions(&mut self, area: &Rect) {
99 let mut height = area.height;
100 height -= self.config.border.height();
101 self.area.height = height;
102
103 let mut width = area.width;
104 width -= self.config.border.width();
105 self.area.width = width;
106 }
107
108 pub fn cycle_layout(&mut self) {
109 self.layout_idx = (self.layout_idx + 1) % self.config.layout.len()
110 }
111
112
113 pub fn set_idx(&mut self, idx: u8) -> bool {
114 let idx = idx as usize;
115 if idx <= self.config.layout.len() {
116 let changed = self.layout_idx != idx;
117 self.layout_idx = idx;
118 changed
119 } else {
120 error!("Layout idx {idx} out of bounds, ignoring.");
121 false
122 }
123 }
124
125 pub fn make_preview(&self) -> Paragraph<'_> {
126 let results = self.view.results();
127 let height = self.area.height as usize;
128 let offset = self.offset as usize;
129
130 let visible_lines: Vec<_> = results
132 .iter()
133 .skip(offset)
134 .take(height)
135 .cloned()
136 .collect();
137
138 let mut preview = Paragraph::new(visible_lines);
139 preview = preview.block(self.config.border.as_block());
140 if self.config.wrap {
141 preview = preview.wrap(Wrap { trim: true });
142 }
143 preview
144 }
145}