Skip to main content

stynx_code_tui/widgets/
model_picker.rs

1use ratatui::{
2    buffer::Buffer,
3    layout::{Constraint, Layout, Rect},
4    style::{Modifier, Style},
5    text::{Line, Span},
6    widgets::{Block, Borders, Clear, List, ListItem, Widget},
7};
8
9use crate::theme;
10
11pub struct ModelPicker<'a> {
12    pub options: &'a [String],
13    pub selected: usize,
14}
15
16impl<'a> ModelPicker<'a> {
17    pub fn new(options: &'a [String], selected: usize) -> Self {
18        Self { options, selected }
19    }
20}
21
22fn centered_rect(pct_x: u16, pct_y: u16, area: Rect) -> Rect {
23    let v = Layout::vertical([
24        Constraint::Percentage((100 - pct_y) / 2),
25        Constraint::Percentage(pct_y),
26        Constraint::Percentage((100 - pct_y) / 2),
27    ]).split(area);
28    Layout::horizontal([
29        Constraint::Percentage((100 - pct_x) / 2),
30        Constraint::Percentage(pct_x),
31        Constraint::Percentage((100 - pct_x) / 2),
32    ]).split(v[1])[1]
33}
34
35impl<'a> Widget for ModelPicker<'a> {
36    fn render(self, area: Rect, buf: &mut Buffer) {
37        let dialog = centered_rect(40, 50, area);
38        Clear.render(dialog, buf);
39
40        let block = Block::default()
41            .title(Span::styled(" Select Model ", Style::default().fg(theme::IRIS()).add_modifier(Modifier::BOLD)))
42            .borders(Borders::ALL)
43            .border_style(Style::default().fg(theme::IRIS()))
44            .style(Style::default().bg(theme::SURFACE()));
45
46        let items: Vec<ListItem<'_>> = self.options.iter().enumerate().map(|(i, opt)| {
47            let (prefix, style) = if i == self.selected {
48                ("› ", Style::default().fg(theme::BASE()).bg(theme::IRIS()).add_modifier(Modifier::BOLD))
49            } else {
50                ("  ", Style::default().fg(theme::TEXT()))
51            };
52            ListItem::new(Line::from(Span::styled(format!("{prefix}{opt}"), style)))
53        }).collect();
54
55        List::new(items).block(block).render(dialog, buf);
56    }
57}