fix(canvas)!: use full block for Marker::Block (#133)

This commit is contained in:
Josh McKinney 2023-04-15 08:40:28 -07:00 committed by GitHub
parent b7bd3051b1
commit 5f1a37f0db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 126 additions and 2 deletions

View file

@ -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"

View file

@ -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);
}) })

View file

@ -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,
} }

View file

@ -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
"
),
);
}
}