mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-22 12:43:16 +00:00
fix(canvas)!: use full block for Marker::Block (#133)
This commit is contained in:
parent
b7bd3051b1
commit
5f1a37f0db
4 changed files with 126 additions and 2 deletions
|
@ -35,6 +35,7 @@ serde = { version = "1", optional = true, features = ["derive"]}
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
argh = "0.1"
|
argh = "0.1"
|
||||||
|
indoc = "2.0"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "barchart"
|
name = "barchart"
|
||||||
|
|
|
@ -7,6 +7,7 @@ use ratatui::{
|
||||||
backend::{Backend, CrosstermBackend},
|
backend::{Backend, CrosstermBackend},
|
||||||
layout::{Constraint, Direction, Layout, Rect},
|
layout::{Constraint, Direction, Layout, Rect},
|
||||||
style::{Color, Style},
|
style::{Color, Style},
|
||||||
|
symbols::Marker,
|
||||||
text::Span,
|
text::Span,
|
||||||
widgets::{
|
widgets::{
|
||||||
canvas::{Canvas, Map, MapResolution, Rectangle},
|
canvas::{Canvas, Map, MapResolution, Rectangle},
|
||||||
|
@ -29,6 +30,8 @@ struct App {
|
||||||
vy: f64,
|
vy: f64,
|
||||||
dir_x: bool,
|
dir_x: bool,
|
||||||
dir_y: bool,
|
dir_y: bool,
|
||||||
|
tick_count: u64,
|
||||||
|
marker: Marker,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
@ -48,10 +51,22 @@ impl App {
|
||||||
vy: 1.0,
|
vy: 1.0,
|
||||||
dir_x: true,
|
dir_x: true,
|
||||||
dir_y: true,
|
dir_y: true,
|
||||||
|
tick_count: 0,
|
||||||
|
marker: Marker::Dot,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_tick(&mut self) {
|
fn on_tick(&mut self) {
|
||||||
|
self.tick_count += 1;
|
||||||
|
// only change marker every 4 ticks (1s) to avoid stroboscopic effect
|
||||||
|
if (self.tick_count % 4) == 0 {
|
||||||
|
self.marker = match self.marker {
|
||||||
|
Marker::Dot => Marker::Block,
|
||||||
|
Marker::Block => Marker::Bar,
|
||||||
|
Marker::Bar => Marker::Braille,
|
||||||
|
Marker::Braille => Marker::Dot,
|
||||||
|
};
|
||||||
|
}
|
||||||
if self.ball.x < self.playground.left() as f64
|
if self.ball.x < self.playground.left() as f64
|
||||||
|| self.ball.x + self.ball.width > self.playground.right() as f64
|
|| self.ball.x + self.ball.width > self.playground.right() as f64
|
||||||
{
|
{
|
||||||
|
@ -155,6 +170,7 @@ fn ui<B: Backend>(f: &mut Frame<B>, app: &App) {
|
||||||
.split(f.size());
|
.split(f.size());
|
||||||
let canvas = Canvas::default()
|
let canvas = Canvas::default()
|
||||||
.block(Block::default().borders(Borders::ALL).title("World"))
|
.block(Block::default().borders(Borders::ALL).title("World"))
|
||||||
|
.marker(app.marker)
|
||||||
.paint(|ctx| {
|
.paint(|ctx| {
|
||||||
ctx.draw(&Map {
|
ctx.draw(&Map {
|
||||||
color: Color::White,
|
color: Color::White,
|
||||||
|
@ -171,6 +187,7 @@ fn ui<B: Backend>(f: &mut Frame<B>, app: &App) {
|
||||||
f.render_widget(canvas, chunks[0]);
|
f.render_widget(canvas, chunks[0]);
|
||||||
let canvas = Canvas::default()
|
let canvas = Canvas::default()
|
||||||
.block(Block::default().borders(Borders::ALL).title("Pong"))
|
.block(Block::default().borders(Borders::ALL).title("Pong"))
|
||||||
|
.marker(app.marker)
|
||||||
.paint(|ctx| {
|
.paint(|ctx| {
|
||||||
ctx.draw(&app.ball);
|
ctx.draw(&app.ball);
|
||||||
})
|
})
|
||||||
|
|
|
@ -228,6 +228,8 @@ pub enum Marker {
|
||||||
Dot,
|
Dot,
|
||||||
/// One point per cell in shape of a block
|
/// One point per cell in shape of a block
|
||||||
Block,
|
Block,
|
||||||
|
/// One point per cell in the shape of a bar
|
||||||
|
Bar,
|
||||||
/// Up to 8 points per cell
|
/// Up to 8 points per cell
|
||||||
Braille,
|
Braille,
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,9 +260,13 @@ impl<'a> Context<'a> {
|
||||||
y_bounds: [f64; 2],
|
y_bounds: [f64; 2],
|
||||||
marker: symbols::Marker,
|
marker: symbols::Marker,
|
||||||
) -> Context<'a> {
|
) -> Context<'a> {
|
||||||
|
let dot = symbols::DOT.chars().next().unwrap();
|
||||||
|
let block = symbols::block::FULL.chars().next().unwrap();
|
||||||
|
let bar = symbols::bar::HALF.chars().next().unwrap();
|
||||||
let grid: Box<dyn Grid> = match marker {
|
let grid: Box<dyn Grid> = match marker {
|
||||||
symbols::Marker::Dot => Box::new(CharGrid::new(width, height, '•')),
|
symbols::Marker::Dot => Box::new(CharGrid::new(width, height, dot)),
|
||||||
symbols::Marker::Block => Box::new(CharGrid::new(width, height, '▄')),
|
symbols::Marker::Block => Box::new(CharGrid::new(width, height, block)),
|
||||||
|
symbols::Marker::Bar => Box::new(CharGrid::new(width, height, bar)),
|
||||||
symbols::Marker::Braille => Box::new(BrailleGrid::new(width, height)),
|
symbols::Marker::Braille => Box::new(BrailleGrid::new(width, height)),
|
||||||
};
|
};
|
||||||
Context {
|
Context {
|
||||||
|
@ -508,3 +512,103 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::{buffer::Cell, symbols::Marker};
|
||||||
|
use indoc::indoc;
|
||||||
|
|
||||||
|
// helper to test the canvas checks that drawing a vertical and horizontal line
|
||||||
|
// results in the expected output
|
||||||
|
fn test_marker(marker: Marker, expected: &str) {
|
||||||
|
let area = Rect::new(0, 0, 5, 5);
|
||||||
|
let mut cell = Cell::default();
|
||||||
|
cell.set_char('x');
|
||||||
|
let mut buf = Buffer::filled(area, &cell);
|
||||||
|
let horizontal_line = Line {
|
||||||
|
x1: 0.0,
|
||||||
|
y1: 0.0,
|
||||||
|
x2: 10.0,
|
||||||
|
y2: 0.0,
|
||||||
|
color: Color::Reset,
|
||||||
|
};
|
||||||
|
let vertical_line = Line {
|
||||||
|
x1: 0.0,
|
||||||
|
y1: 0.0,
|
||||||
|
x2: 0.0,
|
||||||
|
y2: 10.0,
|
||||||
|
color: Color::Reset,
|
||||||
|
};
|
||||||
|
Canvas::default()
|
||||||
|
.marker(marker)
|
||||||
|
.paint(|ctx| {
|
||||||
|
ctx.draw(&vertical_line);
|
||||||
|
ctx.draw(&horizontal_line);
|
||||||
|
})
|
||||||
|
.x_bounds([0.0, 10.0])
|
||||||
|
.y_bounds([0.0, 10.0])
|
||||||
|
.render(area, &mut buf);
|
||||||
|
assert_eq!(buf, Buffer::with_lines(expected.lines().collect()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bar_marker() {
|
||||||
|
test_marker(
|
||||||
|
Marker::Bar,
|
||||||
|
indoc!(
|
||||||
|
"
|
||||||
|
▄xxxx
|
||||||
|
▄xxxx
|
||||||
|
▄xxxx
|
||||||
|
▄xxxx
|
||||||
|
▄▄▄▄▄"
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_block_marker() {
|
||||||
|
test_marker(
|
||||||
|
Marker::Block,
|
||||||
|
indoc!(
|
||||||
|
"
|
||||||
|
█xxxx
|
||||||
|
█xxxx
|
||||||
|
█xxxx
|
||||||
|
█xxxx
|
||||||
|
█████"
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_braille_marker() {
|
||||||
|
test_marker(
|
||||||
|
Marker::Braille,
|
||||||
|
indoc!(
|
||||||
|
"
|
||||||
|
⡇xxxx
|
||||||
|
⡇xxxx
|
||||||
|
⡇xxxx
|
||||||
|
⡇xxxx
|
||||||
|
⣇⣀⣀⣀⣀"
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_dot_marker() {
|
||||||
|
test_marker(
|
||||||
|
Marker::Dot,
|
||||||
|
indoc!(
|
||||||
|
"
|
||||||
|
•xxxx
|
||||||
|
•xxxx
|
||||||
|
•xxxx
|
||||||
|
•xxxx
|
||||||
|
•••••"
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue