leetcode_tui_rs/widgets/
popup.rs

1use crate::ctx::Ctx;
2use leetcode_tui_config::CONFIG;
3use leetcode_tui_shared::layout::GetWindowStats;
4use ratatui::prelude::*;
5use ratatui::widgets::{
6    Block, Borders, Clear, List, ListItem, Paragraph, Scrollbar, StatefulWidget, Widget, Wrap,
7};
8
9pub struct SelectPopup<'a> {
10    ctx: &'a mut Ctx,
11}
12
13impl<'a> SelectPopup<'a> {
14    pub fn new(ctx: &'a mut Ctx) -> Self {
15        Self { ctx }
16    }
17}
18
19impl<'a> Widget for SelectPopup<'a> {
20    fn render(self, _area: Rect, buf: &mut Buffer) {
21        let c_def = &CONFIG.as_ref().theme.defaults;
22        let mut block: Block<'_> = Block::default();
23        if let Some(title) = self.ctx.select_popup.get_title() {
24            block = Block::default().title(title);
25        }
26        let block = block
27            .borders(Borders::ALL)
28            .border_style(Style::default().fg(c_def.info.into()));
29        Clear.render(self.get_window().root.popup.outer, buf);
30        block.render(self.get_window().root.popup.outer, buf);
31        let chunks = Layout::default()
32            .direction(Direction::Horizontal)
33            .constraints(vec![Constraint::Percentage(100), Constraint::Min(1)])
34            .split(self.get_window().root.popup.inner);
35        let content_area = chunks[0];
36        let lines = self.ctx.select_popup.get_lines().clone();
37
38        let list = List::new(
39            lines
40                .iter()
41                .map(|l| ListItem::new(vec![Line::from(l.as_ref())]).fg(c_def.fg_dark))
42                .collect::<Vec<_>>(),
43        )
44        .highlight_style(
45            Style::default()
46                .bg(c_def.bg_highlight.into())
47                .fg(c_def.fg.into())
48                .add_modifier(Modifier::BOLD),
49        );
50        StatefulWidget::render(list, content_area, buf, &mut self.ctx.select_popup.state);
51        // Scrollbar::default()
52        //     .orientation(ratatui::widgets::ScrollbarOrientation::VerticalRight)
53        //     .begin_symbol(Some("↑"))
54        //     .end_symbol(Some("↓"))
55        //     .render(scrollbar_area, buf, &mut self.ctx.popup.v_scroll_state)
56    }
57}
58
59pub struct Popup<'a> {
60    ctx: &'a mut Ctx,
61}
62
63impl<'a> Popup<'a> {
64    pub fn new(ctx: &'a mut Ctx) -> Self {
65        Self { ctx }
66    }
67}
68
69impl<'a> Widget for Popup<'a> {
70    fn render(self, _area: ratatui::prelude::Rect, buf: &mut ratatui::prelude::Buffer) {
71        let c_def = &CONFIG.as_ref().theme.defaults;
72        let mut block: Block<'_> = Block::default();
73        if let Some(title) = self.ctx.popup.get_title() {
74            block = Block::default().title(title);
75        }
76        let block = block
77            .borders(Borders::ALL)
78            .border_style(Style::default().fg(c_def.info.into()));
79        Clear.render(self.get_window().root.popup.outer, buf);
80        block.render(self.get_window().root.popup.outer, buf);
81        let chunks = Layout::default()
82            .direction(Direction::Horizontal)
83            .constraints(vec![Constraint::Percentage(100), Constraint::Min(1)])
84            .split(self.get_window().root.popup.inner);
85        let content_area = chunks[0];
86        let scrollbar_area = chunks[1];
87
88        let content = self.ctx.popup.get_lines().join("\n");
89        let text = tui_markdown::from_str(content.as_str());
90
91        Paragraph::new(text)
92            .scroll((self.ctx.popup.v_scroll as u16, 0))
93            .wrap(Wrap { trim: true })
94            .style(Style::default().fg(CONFIG.as_ref().theme.defaults.fg.into()))
95            .render(content_area, buf);
96
97        Scrollbar::default()
98            .orientation(ratatui::widgets::ScrollbarOrientation::VerticalRight)
99            .begin_symbol(Some("↑"))
100            .end_symbol(Some("↓"))
101            .render(scrollbar_area, buf, &mut self.ctx.popup.v_scroll_state)
102    }
103}