Advertisement
Guest User

Ratatui scrollbar test/example

a guest
Feb 18th, 2024
43
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.71 KB | Source Code | 0 0
  1. use std::{
  2.     error::Error,
  3.     io,
  4.     time::{Duration, Instant},
  5. };
  6.  
  7. use crossterm::{
  8.     event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind},
  9.     execute,
  10.     terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
  11. };
  12. use ratatui::{prelude::*, symbols::scrollbar, widgets::*};
  13.  
  14. #[derive(Default)]
  15. struct App {
  16.     pub vertical_scroll_state: ScrollbarState,
  17.     pub horizontal_scroll_state: ScrollbarState,
  18.     pub vertical_scroll: usize,
  19.     pub horizontal_scroll: usize,
  20. }
  21.  
  22. fn main() -> Result<(), Box<dyn Error>> {
  23.     // setup terminal
  24.     enable_raw_mode()?;
  25.     let mut stdout = io::stdout();
  26.     execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
  27.     let backend = CrosstermBackend::new(stdout);
  28.     let mut terminal = Terminal::new(backend)?;
  29.  
  30.     // create app and run it
  31.     let tick_rate = Duration::from_millis(250);
  32.     let app = App::default();
  33.     let res = run_app(&mut terminal, app, tick_rate);
  34.  
  35.     // restore terminal
  36.     disable_raw_mode()?;
  37.     execute!(terminal.backend_mut(), LeaveAlternateScreen, DisableMouseCapture)?;
  38.     terminal.show_cursor()?;
  39.  
  40.     if let Err(err) = res {
  41.         println!("{err:?}");
  42.     }
  43.  
  44.     Ok(())
  45. }
  46.  
  47. fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App, tick_rate: Duration) -> io::Result<()> {
  48.     let mut last_tick = Instant::now();
  49.     loop {
  50.         terminal.draw(|f| ui(f, &mut app))?;
  51.  
  52.         let timeout = tick_rate.saturating_sub(last_tick.elapsed());
  53.         if crossterm::event::poll(timeout)? {
  54.             if let Event::Key(key) = event::read()? {
  55.                 if key.kind == KeyEventKind::Release {
  56.                     continue;
  57.                 }
  58.  
  59.                 match key.code {
  60.                     KeyCode::Char('q') => return Ok(()),
  61.                     KeyCode::Char('j') | KeyCode::Down => {
  62.                         app.vertical_scroll = app.vertical_scroll.saturating_add(1);
  63.                         app.vertical_scroll_state = app.vertical_scroll_state.position(app.vertical_scroll);
  64.                     }
  65.                     KeyCode::Char('k') | KeyCode::Up => {
  66.                         app.vertical_scroll = app.vertical_scroll.saturating_sub(1);
  67.                         app.vertical_scroll_state = app.vertical_scroll_state.position(app.vertical_scroll);
  68.                     }
  69.                     KeyCode::Char('h') | KeyCode::Left => {
  70.                         app.horizontal_scroll = app.horizontal_scroll.saturating_sub(1);
  71.                         app.horizontal_scroll_state = app.horizontal_scroll_state.position(app.horizontal_scroll);
  72.                     }
  73.                     KeyCode::Char('l') | KeyCode::Right => {
  74.                         app.horizontal_scroll = app.horizontal_scroll.saturating_add(1);
  75.                         app.horizontal_scroll_state = app.horizontal_scroll_state.position(app.horizontal_scroll);
  76.                     }
  77.                     _ => {}
  78.                 }
  79.             }
  80.         }
  81.         if last_tick.elapsed() >= tick_rate {
  82.             last_tick = Instant::now();
  83.         }
  84.     }
  85. }
  86.  
  87. fn ui(f: &mut Frame, app: &mut App) {
  88.     let size = f.size();
  89.  
  90.     let chunks = Layout::vertical([
  91.         Constraint::Min(1),
  92.         Constraint::Percentage(25),
  93.         Constraint::Percentage(25),
  94.         Constraint::Percentage(25),
  95.         Constraint::Percentage(25),
  96.     ])
  97.     .split(size);
  98.  
  99.     app.vertical_scroll_state = app.vertical_scroll_state.content_length(80);
  100.     app.horizontal_scroll_state = app.horizontal_scroll_state.content_length(7500);
  101.  
  102.     let create_block = |title: &'static str| Block::bordered().gray().title(title.bold());
  103.  
  104.    let title = Block::default()
  105.        .title(format!("The terminal's size is {size}").bold())
  106.        .title_alignment(Alignment::Center);
  107.    f.render_widget(title, chunks[0]);
  108.  
  109.    f.render_widget(create_block("Vertical scrollbar with arrows"), chunks[1]);
  110.    f.render_stateful_widget(
  111.        Scrollbar::default()
  112.            .orientation(ScrollbarOrientation::VerticalRight)
  113.            .begin_symbol(Some(""))
  114.            .end_symbol(Some("")),
  115.        chunks[1],
  116.        &mut app.vertical_scroll_state,
  117.    );
  118.  
  119.    f.render_widget(
  120.        create_block("Vertical scrollbar without arrows, without track symbol and mirrored"),
  121.        chunks[2],
  122.    );
  123.    f.render_stateful_widget(
  124.        Scrollbar::default()
  125.            .orientation(ScrollbarOrientation::VerticalLeft)
  126.            .symbols(scrollbar::VERTICAL)
  127.            .begin_symbol(None)
  128.            .track_symbol(None)
  129.            .end_symbol(None),
  130.        chunks[2].inner(&Margin {
  131.            vertical: 1,
  132.            horizontal: 0,
  133.        }),
  134.        &mut app.vertical_scroll_state,
  135.    );
  136.  
  137.    f.render_widget(
  138.        create_block("Horizontal scrollbar with only begin arrow & custom thumb symbol"),
  139.        chunks[3],
  140.    );
  141.    f.render_stateful_widget(
  142.        Scrollbar::default()
  143.            .orientation(ScrollbarOrientation::HorizontalBottom)
  144.            .thumb_symbol("")
  145.            .end_symbol(None),
  146.        chunks[3].inner(&Margin {
  147.            vertical: 0,
  148.            horizontal: 1,
  149.        }),
  150.        &mut app.horizontal_scroll_state,
  151.    );
  152.  
  153.    f.render_widget(
  154.        create_block("Horizontal scrollbar without arrows & custom thumb and track symbol"),
  155.        chunks[4],
  156.    );
  157.    f.render_stateful_widget(
  158.        Scrollbar::default()
  159.            .orientation(ScrollbarOrientation::HorizontalBottom)
  160.            .thumb_symbol("")
  161.            .track_symbol(Some("")),
  162.        chunks[4].inner(&Margin {
  163.            vertical: 0,
  164.            horizontal: 1,
  165.        }),
  166.        &mut app.horizontal_scroll_state,
  167.    );
  168. }
  169.  
Tags: ratatui
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement