mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-10 07:04:17 +00:00
082cbcbc50
This change simplifys UI code that uses the Frame type. E.g.: ```rust fn draw<B: Backend>(frame: &mut Frame<B>) { // ... } ``` Frame was generic over Backend because it stored a reference to the terminal in the field. Instead it now directly stores the viewport area and current buffer. These are provided at creation time and are valid for the duration of the frame. BREAKING CHANGE: Frame is no longer generic over Backend. Code that accepted `Frame<Backend>` will now need to accept `Frame`. To migrate existing code, remove any generic parameters from code that uses an instance of a Frame. E.g. the above code becomes: ```rust fn draw(frame: &mut Frame) { // ... } ```
116 lines
3.6 KiB
Rust
116 lines
3.6 KiB
Rust
/// This example is useful for testing how your terminal emulator handles different modifiers.
|
|
/// It will render a grid of combinations of foreground and background colors with all
|
|
/// modifiers applied to them.
|
|
use std::{
|
|
error::Error,
|
|
io::{self, Stdout},
|
|
iter::once,
|
|
result,
|
|
time::Duration,
|
|
};
|
|
|
|
use crossterm::{
|
|
event::{self, Event, KeyCode},
|
|
execute,
|
|
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
|
};
|
|
use itertools::Itertools;
|
|
use ratatui::{prelude::*, widgets::*};
|
|
|
|
type Result<T> = result::Result<T, Box<dyn Error>>;
|
|
|
|
fn main() -> Result<()> {
|
|
let mut terminal = setup_terminal()?;
|
|
let res = run_app(&mut terminal);
|
|
restore_terminal(terminal)?;
|
|
if let Err(err) = res {
|
|
eprintln!("{err:?}");
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn run_app<B: Backend>(terminal: &mut Terminal<B>) -> io::Result<()> {
|
|
loop {
|
|
terminal.draw(ui)?;
|
|
|
|
if event::poll(Duration::from_millis(250))? {
|
|
if let Event::Key(key) = event::read()? {
|
|
if let KeyCode::Char('q') = key.code {
|
|
return Ok(());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn ui(frame: &mut Frame) {
|
|
let layout = Layout::default()
|
|
.direction(Direction::Vertical)
|
|
.constraints(vec![Constraint::Length(1), Constraint::Min(0)])
|
|
.split(frame.size());
|
|
frame.render_widget(
|
|
Paragraph::new("Note: not all terminals support all modifiers")
|
|
.style(Style::default().fg(Color::Red).add_modifier(Modifier::BOLD)),
|
|
layout[0],
|
|
);
|
|
let layout = Layout::default()
|
|
.direction(Direction::Vertical)
|
|
.constraints(vec![Constraint::Length(1); 50])
|
|
.split(layout[1])
|
|
.iter()
|
|
.flat_map(|area| {
|
|
Layout::default()
|
|
.direction(Direction::Horizontal)
|
|
.constraints(vec![Constraint::Percentage(20); 5])
|
|
.split(*area)
|
|
.to_vec()
|
|
})
|
|
.collect_vec();
|
|
|
|
let colors = [
|
|
Color::Black,
|
|
Color::DarkGray,
|
|
Color::Gray,
|
|
Color::White,
|
|
Color::Red,
|
|
];
|
|
let all_modifiers = once(Modifier::empty())
|
|
.chain(Modifier::all().iter())
|
|
.collect_vec();
|
|
let mut index = 0;
|
|
for bg in colors.iter() {
|
|
for fg in colors.iter() {
|
|
for modifier in &all_modifiers {
|
|
let modifier_name = format!("{modifier:11?}");
|
|
let padding = (" ").repeat(12 - modifier_name.len());
|
|
let paragraph = Paragraph::new(Line::from(vec![
|
|
modifier_name.fg(*fg).bg(*bg).add_modifier(*modifier),
|
|
padding.fg(*fg).bg(*bg).add_modifier(*modifier),
|
|
// This is a hack to work around a bug in VHS which is used for rendering the
|
|
// examples to gifs. The bug is that the background color of a paragraph seems
|
|
// to bleed into the next character.
|
|
".".black().on_black(),
|
|
]));
|
|
frame.render_widget(paragraph, layout[index]);
|
|
index += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn setup_terminal() -> Result<Terminal<CrosstermBackend<Stdout>>> {
|
|
enable_raw_mode()?;
|
|
let mut stdout = io::stdout();
|
|
execute!(stdout, EnterAlternateScreen)?;
|
|
let backend = CrosstermBackend::new(stdout);
|
|
let mut terminal = Terminal::new(backend)?;
|
|
terminal.hide_cursor()?;
|
|
Ok(terminal)
|
|
}
|
|
|
|
fn restore_terminal(mut terminal: Terminal<CrosstermBackend<Stdout>>) -> Result<()> {
|
|
disable_raw_mode()?;
|
|
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
|
|
terminal.show_cursor()?;
|
|
Ok(())
|
|
}
|