cursive_logger_view/
view.rs1use crate::{
2 log_buffer::{self, GET_LOCK_ERR_MSG},
3 FlexiLoggerView,
4};
5use cursive_core::{
6 view::{ScrollStrategy, Scrollable, View},
7 views::ScrollView,
8 Printer, Vec2,
9};
10use tap::Pipe;
11use unicode_width::UnicodeWidthStr;
12
13impl FlexiLoggerView {
14 pub fn wrap_scroll_view(self) -> ScrollView<Self> {
26 self.scrollable()
27 .scroll_x(true)
28 .scroll_y(true)
29 .scroll_strategy(ScrollStrategy::StickToBottom)
30 }
31
32 pub fn new() -> Self {
34 FlexiLoggerView { indent: true }
35 }
36}
37
38impl View for FlexiLoggerView {
39 fn draw(&self, printer: &Printer<'_, '_>) {
40 let logs = log_buffer::static_logs()
41 .lock()
42 .expect(GET_LOCK_ERR_MSG);
43
44 let skipped = logs
46 .len()
47 .saturating_sub(printer.size.y);
48
49 logs.iter()
50 .skip(skipped)
51 .fold(0, |y, msg| {
52 let log_msg_index = msg.spans_raw().len() - 1;
53
54 let x = msg
55 .spans()
56 .take(log_msg_index)
57 .fold(0, |x, span| {
58 printer.with_style(*span.attr, |p| {
59 p.print((x, y), span.content)
60 });
61 x + span.width
62 });
63
64 msg.spans()
65 .nth(log_msg_index)
66 .map(|log_msg| {
67 log_msg
68 .content
69 .split('\n')
70 .enumerate()
71 .fold(y, |current_y, (i, part)| {
72 let x_pos =
73 if !self.indent && i > 0 { 0 } else { x };
74 printer.with_style(*log_msg.attr, |p| {
75 p.print((x_pos, current_y), part)
76 });
77 current_y + 1
78 })
79 })
80 .unwrap_or(y)
81 });
82 }
83
84 fn required_size(&mut self, constraint: Vec2) -> Vec2 {
85 let logs = log_buffer::static_logs()
86 .lock()
87 .expect(GET_LOCK_ERR_MSG);
88
89 let width = logs
91 .iter()
92 .map(|msg| {
93 msg.spans()
94 .map(|x|
95 x.content.split('\n').map(|x| x.width()).max().expect("ERR: required_size(), failed to get width"))
99 .sum::<usize>()
100 })
101 .max()
102 .unwrap_or(1)
103 .pipe(|w|core::cmp::max(w, constraint.x));
104
105 let height = logs
106 .iter()
107 .map(|msg| {
108 msg.spans()
109 .last()
110 .map(|x| x.content.split('\n').count())
111 .expect("ERR: required_size(), the last span message is invalid, and failed to get height.")
112 })
113 .sum::<usize>()
114 .pipe(|h| core::cmp::max(h, constraint.y));
115
116 Vec2::new(width, height)
117 }
118}