File: mouse.rs

package info (click to toggle)
rust-tui-widget-list 0.15.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,776 kB
  • sloc: makefile: 2
file content (102 lines) | stat: -rw-r--r-- 3,312 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#[path = "common/lib.rs"]
mod common;

use common::{Colors, Result, Terminal};
use ratatui::crossterm::event::{
    self, Event, KeyCode, KeyEventKind, MouseButton, MouseEvent, MouseEventKind,
};
use ratatui::{
    prelude::*,
    widgets::{Block, Borders, Paragraph, Scrollbar, ScrollbarOrientation},
};
use tui_widget_list::hit_test::Hit;
use tui_widget_list::{ListBuilder, ListState, ListView};

fn main() -> Result<()> {
    let mut terminal = Terminal::init()?;
    App::default().run(&mut terminal)?;
    Terminal::reset()?;
    terminal.show_cursor()?;
    Ok(())
}

#[derive(Default)]
pub struct App;

impl App {
    pub fn run(&self, terminal: &mut Terminal) -> Result<()> {
        let mut state = ListState::default();

        loop {
            terminal.draw_app(self, &mut state)?;

            match event::read()? {
                Event::Key(key) if key.kind == KeyEventKind::Press => match key.code {
                    KeyCode::Char('q') => return Ok(()),
                    KeyCode::Up | KeyCode::Char('k') => state.previous(),
                    KeyCode::Down | KeyCode::Char('j') => state.next(),
                    _ => {}
                },
                Event::Mouse(MouseEvent {
                    kind: MouseEventKind::Down(MouseButton::Left),
                    column,
                    row,
                    ..
                }) => match state.hit_test(column, row) {
                    Some(Hit::Item(index)) => state.select(Some(index)),
                    Some(Hit::Area) | None => {}
                },
                Event::Mouse(MouseEvent {
                    kind: MouseEventKind::ScrollUp,
                    ..
                }) => {
                    state.previous();
                }
                Event::Mouse(MouseEvent {
                    kind: MouseEventKind::ScrollDown,
                    ..
                }) => {
                    state.next();
                }
                _ => {}
            }
        }
    }
}

impl StatefulWidget for &App {
    type State = ListState;
    fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
        let builder = ListBuilder::new(|context| {
            let text = format!("Item {0}", context.index);
            let mut item = Line::from(text);

            if context.index % 2 == 0 {
                item.style = Style::default().bg(Colors::CHARCOAL)
            } else {
                item.style = Style::default().bg(Colors::BLACK)
            };

            if context.is_selected {
                let mut spans = item.spans;
                spans.insert(0, Span::from(">>"));
                item = Line::from(spans);
                item.style = Style::default().bg(Colors::ORANGE).fg(Colors::CHARCOAL);
            };

            let style = item.style;
            let lines = vec![item, Line::from("")];
            let paragraph = Paragraph::new(lines).style(style);
            (paragraph, 2)
        });

        let scrollbar = Scrollbar::new(ScrollbarOrientation::VerticalRight)
            .begin_symbol(Some("┐"))
            .end_symbol(Some("┘"));
        let list = ListView::new(builder, 50)
            .block(Block::default().borders(Borders::ALL))
            .scrollbar(scrollbar);

        list.render(area, buf, state);
    }
}