mirror of
https://github.com/ricoriedel/wipe.git
synced 2024-11-26 01:46:36 +00:00
Adhere to RAII
This commit is contained in:
parent
1eddc2e3a2
commit
edb429ed43
@ -264,7 +264,7 @@ fn main() -> Result<(), Error> {
|
|||||||
let converter = ConverterImpl::new(char_converter, color_converter);
|
let converter = ConverterImpl::new(char_converter, color_converter);
|
||||||
let term = TerminalImpl::new(stdout());
|
let term = TerminalImpl::new(stdout());
|
||||||
let printer = PrinterImpl::new(term)?;
|
let printer = PrinterImpl::new(term)?;
|
||||||
let renderer = RendererImpl::new(sampler, converter, printer);
|
let renderer = RendererImpl::new(sampler, converter, printer)?;
|
||||||
|
|
||||||
let clock = ClockImpl::new();
|
let clock = ClockImpl::new();
|
||||||
let timer = Timer::new(clock, duration, delay);
|
let timer = Timer::new(clock, duration, delay);
|
||||||
|
121
src/renderer.rs
121
src/renderer.rs
@ -3,33 +3,35 @@ use crate::pattern::*;
|
|||||||
use crate::Error;
|
use crate::Error;
|
||||||
use crate::Printer;
|
use crate::Printer;
|
||||||
use crate::Vector;
|
use crate::Vector;
|
||||||
|
use crossterm::style::Color;
|
||||||
|
|
||||||
/// A renderer for an animation.
|
/// A renderer for an animation.
|
||||||
#[cfg_attr(test, mockall::automock)]
|
#[cfg_attr(test, mockall::automock)]
|
||||||
pub trait Renderer {
|
pub trait Renderer {
|
||||||
/// Prepares the terminal for the animation.
|
|
||||||
/// Call once before rendering frames.
|
|
||||||
fn begin(&mut self) -> Result<(), Error>;
|
|
||||||
/// Renders the current frame and flushes.
|
/// Renders the current frame and flushes.
|
||||||
fn render(&mut self, step: f32) -> Result<(), Error>;
|
fn render(&mut self, step: f32) -> Result<(), Error>;
|
||||||
/// Cleans up and resets the terminal.
|
|
||||||
/// Call once after rendering frames.
|
|
||||||
fn end(&mut self) -> Result<(), Error>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The implementation of [Renderer].
|
/// The implementation of [Renderer].
|
||||||
#[derive(derive_more::Constructor)]
|
pub struct RendererImpl<T1, T2, T3: Printer> {
|
||||||
pub struct RendererImpl<T1, T2, T3> {
|
|
||||||
sampler: T1,
|
sampler: T1,
|
||||||
converter: T2,
|
converter: T2,
|
||||||
printer: T3,
|
printer: T3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T1: SamplerFactory, T2: Converter, T3: Printer> Renderer for RendererImpl<T1, T2, T3> {
|
impl<T1, T2, T3: Printer> RendererImpl<T1, T2, T3> {
|
||||||
fn begin(&mut self) -> Result<(), Error> {
|
pub fn new(sampler: T1, converter: T2, mut printer: T3) -> Result<Self, Error> {
|
||||||
self.printer.hide_cursor()
|
printer.hide_cursor()?;
|
||||||
}
|
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
sampler,
|
||||||
|
converter,
|
||||||
|
printer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T1: SamplerFactory, T2: Converter, T3: Printer> Renderer for RendererImpl<T1, T2, T3> {
|
||||||
fn render(&mut self, step: f32) -> Result<(), Error> {
|
fn render(&mut self, step: f32) -> Result<(), Error> {
|
||||||
let (width, height) = self.printer.size()?;
|
let (width, height) = self.printer.size()?;
|
||||||
let config = Config {
|
let config = Config {
|
||||||
@ -60,12 +62,16 @@ impl<T1: SamplerFactory, T2: Converter, T3: Printer> Renderer for RendererImpl<T
|
|||||||
}
|
}
|
||||||
self.printer.flush()
|
self.printer.flush()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn end(&mut self) -> Result<(), Error> {
|
impl<T1, T2, T3: Printer> Drop for RendererImpl<T1, T2, T3> {
|
||||||
self.printer.move_to(0, 0)?;
|
fn drop(&mut self) {
|
||||||
self.printer.clear()?;
|
// Errors while dropping the renderer can be safely ignored.
|
||||||
self.printer.show_cursor()?;
|
self.printer.move_to(0, 0).ok();
|
||||||
self.printer.flush()
|
self.printer.set_foreground(Color::Reset).ok();
|
||||||
|
self.printer.show_cursor().ok();
|
||||||
|
self.printer.clear().ok();
|
||||||
|
self.printer.flush().ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,16 +87,22 @@ mod test {
|
|||||||
use mockall::Sequence;
|
use mockall::Sequence;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn begin() {
|
fn new() {
|
||||||
let factory = MockSamplerFactory::new();
|
let factory = MockSamplerFactory::new();
|
||||||
let converter = MockConverter::new();
|
let converter = MockConverter::new();
|
||||||
let mut printer = MockPrinter::new();
|
let mut printer = MockPrinter::new();
|
||||||
|
|
||||||
|
// Constructor
|
||||||
printer.expect_hide_cursor().once().returning(|| Ok(()));
|
printer.expect_hide_cursor().once().returning(|| Ok(()));
|
||||||
|
|
||||||
let mut renderer = RendererImpl::new(factory, converter, printer);
|
// Drop
|
||||||
|
printer.expect_move_to().returning(|_, _| Ok(()));
|
||||||
|
printer.expect_set_foreground().returning(|_| Ok(()));
|
||||||
|
printer.expect_show_cursor().returning(|| Ok(()));
|
||||||
|
printer.expect_clear().returning(|| Ok(()));
|
||||||
|
printer.expect_flush().returning(|| Ok(()));
|
||||||
|
|
||||||
renderer.begin().unwrap();
|
drop(RendererImpl::new(factory, converter, printer));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -163,6 +175,14 @@ mod test {
|
|||||||
|
|
||||||
let seq = &mut Sequence::new();
|
let seq = &mut Sequence::new();
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
printer
|
||||||
|
.expect_hide_cursor()
|
||||||
|
.once()
|
||||||
|
.returning(|| Ok(()))
|
||||||
|
.in_sequence(seq);
|
||||||
|
|
||||||
|
// Rendering
|
||||||
printer
|
printer
|
||||||
.expect_move_to()
|
.expect_move_to()
|
||||||
.once()
|
.once()
|
||||||
@ -217,7 +237,35 @@ mod test {
|
|||||||
.returning(|| Ok(()))
|
.returning(|| Ok(()))
|
||||||
.in_sequence(seq);
|
.in_sequence(seq);
|
||||||
|
|
||||||
let mut renderer = RendererImpl::new(sampler, converter, printer);
|
// Drop
|
||||||
|
printer
|
||||||
|
.expect_move_to()
|
||||||
|
.once()
|
||||||
|
.returning(|_, _| Ok(()))
|
||||||
|
.in_sequence(seq);
|
||||||
|
printer
|
||||||
|
.expect_set_foreground()
|
||||||
|
.with(eq(Color::Reset))
|
||||||
|
.once()
|
||||||
|
.returning(|_| Ok(()))
|
||||||
|
.in_sequence(seq);
|
||||||
|
printer
|
||||||
|
.expect_show_cursor()
|
||||||
|
.once()
|
||||||
|
.returning(|| Ok(()))
|
||||||
|
.in_sequence(seq);
|
||||||
|
printer
|
||||||
|
.expect_clear()
|
||||||
|
.once()
|
||||||
|
.returning(|| Ok(()))
|
||||||
|
.in_sequence(seq);
|
||||||
|
printer
|
||||||
|
.expect_flush()
|
||||||
|
.once()
|
||||||
|
.returning(|| Ok(()))
|
||||||
|
.in_sequence(seq);
|
||||||
|
|
||||||
|
let mut renderer = RendererImpl::new(sampler, converter, printer).unwrap();
|
||||||
|
|
||||||
renderer.render(0.0).unwrap();
|
renderer.render(0.0).unwrap();
|
||||||
}
|
}
|
||||||
@ -237,7 +285,17 @@ mod test {
|
|||||||
printer.expect_size().returning(|| Ok((3, 2)));
|
printer.expect_size().returning(|| Ok((3, 2)));
|
||||||
printer.expect_flush().returning(|| Ok(()));
|
printer.expect_flush().returning(|| Ok(()));
|
||||||
|
|
||||||
let mut renderer = RendererImpl::new(sampler, converter, printer);
|
// Constructor
|
||||||
|
printer.expect_hide_cursor().returning(|| Ok(()));
|
||||||
|
|
||||||
|
// Drop
|
||||||
|
printer.expect_move_to().returning(|_, _| Ok(()));
|
||||||
|
printer.expect_set_foreground().returning(|_| Ok(()));
|
||||||
|
printer.expect_show_cursor().returning(|| Ok(()));
|
||||||
|
printer.expect_clear().returning(|| Ok(()));
|
||||||
|
printer.expect_flush().returning(|| Ok(()));
|
||||||
|
|
||||||
|
let mut renderer = RendererImpl::new(sampler, converter, printer).unwrap();
|
||||||
|
|
||||||
renderer.render(0.8).unwrap();
|
renderer.render(0.8).unwrap();
|
||||||
}
|
}
|
||||||
@ -249,6 +307,11 @@ mod test {
|
|||||||
let mut printer = MockPrinter::new();
|
let mut printer = MockPrinter::new();
|
||||||
|
|
||||||
let seq = &mut Sequence::new();
|
let seq = &mut Sequence::new();
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
printer.expect_hide_cursor().returning(|| Ok(()));
|
||||||
|
|
||||||
|
// Drop
|
||||||
printer
|
printer
|
||||||
.expect_move_to()
|
.expect_move_to()
|
||||||
.with(eq(0), eq(0))
|
.with(eq(0), eq(0))
|
||||||
@ -256,12 +319,18 @@ mod test {
|
|||||||
.returning(|_, _| Ok(()))
|
.returning(|_, _| Ok(()))
|
||||||
.in_sequence(seq);
|
.in_sequence(seq);
|
||||||
printer
|
printer
|
||||||
.expect_clear()
|
.expect_set_foreground()
|
||||||
|
.with(eq(Color::Reset))
|
||||||
|
.once()
|
||||||
|
.returning(|_| Ok(()))
|
||||||
|
.in_sequence(seq);
|
||||||
|
printer
|
||||||
|
.expect_show_cursor()
|
||||||
.once()
|
.once()
|
||||||
.returning(|| Ok(()))
|
.returning(|| Ok(()))
|
||||||
.in_sequence(seq);
|
.in_sequence(seq);
|
||||||
printer
|
printer
|
||||||
.expect_show_cursor()
|
.expect_clear()
|
||||||
.once()
|
.once()
|
||||||
.returning(|| Ok(()))
|
.returning(|| Ok(()))
|
||||||
.in_sequence(seq);
|
.in_sequence(seq);
|
||||||
@ -271,8 +340,6 @@ mod test {
|
|||||||
.returning(|| Ok(()))
|
.returning(|| Ok(()))
|
||||||
.in_sequence(seq);
|
.in_sequence(seq);
|
||||||
|
|
||||||
let mut renderer = RendererImpl::new(factory, converter, printer);
|
drop(RendererImpl::new(factory, converter, printer));
|
||||||
|
|
||||||
renderer.end().unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
src/timer.rs
18
src/timer.rs
@ -41,15 +41,13 @@ impl<T: Clock> Timer<T> {
|
|||||||
let start = self.clock.now();
|
let start = self.clock.now();
|
||||||
let mut now = start;
|
let mut now = start;
|
||||||
|
|
||||||
renderer.begin()?;
|
|
||||||
|
|
||||||
while now.duration_since(start) < self.duration {
|
while now.duration_since(start) < self.duration {
|
||||||
let step = now.duration_since(start).as_secs_f32() / self.duration.as_secs_f32();
|
let step = now.duration_since(start).as_secs_f32() / self.duration.as_secs_f32();
|
||||||
|
|
||||||
renderer.render(step)?;
|
renderer.render(step)?;
|
||||||
now = self.delay(now);
|
now = self.delay(now);
|
||||||
}
|
}
|
||||||
renderer.end()
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sleeps until the next frame starts.
|
/// Sleeps until the next frame starts.
|
||||||
@ -98,11 +96,6 @@ mod test {
|
|||||||
let mut renderer = MockRenderer::new();
|
let mut renderer = MockRenderer::new();
|
||||||
let renderer_seq = &mut Sequence::new();
|
let renderer_seq = &mut Sequence::new();
|
||||||
|
|
||||||
renderer
|
|
||||||
.expect_begin()
|
|
||||||
.once()
|
|
||||||
.returning(|| Ok(()))
|
|
||||||
.in_sequence(renderer_seq);
|
|
||||||
renderer
|
renderer
|
||||||
.expect_render()
|
.expect_render()
|
||||||
.with(eq(0.0))
|
.with(eq(0.0))
|
||||||
@ -115,11 +108,6 @@ mod test {
|
|||||||
.once()
|
.once()
|
||||||
.returning(|_| Ok(()))
|
.returning(|_| Ok(()))
|
||||||
.in_sequence(renderer_seq);
|
.in_sequence(renderer_seq);
|
||||||
renderer
|
|
||||||
.expect_end()
|
|
||||||
.once()
|
|
||||||
.returning(|| Ok(()))
|
|
||||||
.in_sequence(renderer_seq);
|
|
||||||
|
|
||||||
timer.run(renderer).unwrap();
|
timer.run(renderer).unwrap();
|
||||||
}
|
}
|
||||||
@ -155,9 +143,7 @@ mod test {
|
|||||||
let timer = Timer::new(clock, Duration::from_secs(10), Duration::from_secs(10));
|
let timer = Timer::new(clock, Duration::from_secs(10), Duration::from_secs(10));
|
||||||
|
|
||||||
let mut renderer = MockRenderer::new();
|
let mut renderer = MockRenderer::new();
|
||||||
renderer.expect_begin().returning(|| Ok(()));
|
|
||||||
renderer.expect_render().returning(|_| Ok(()));
|
renderer.expect_render().returning(|_| Ok(()));
|
||||||
renderer.expect_end().returning(|| Ok(()));
|
|
||||||
|
|
||||||
timer.run(renderer).unwrap();
|
timer.run(renderer).unwrap();
|
||||||
}
|
}
|
||||||
@ -182,9 +168,7 @@ mod test {
|
|||||||
let timer = Timer::new(clock, Duration::from_secs(10), Duration::from_secs(10));
|
let timer = Timer::new(clock, Duration::from_secs(10), Duration::from_secs(10));
|
||||||
|
|
||||||
let mut renderer = MockRenderer::new();
|
let mut renderer = MockRenderer::new();
|
||||||
renderer.expect_begin().returning(|| Ok(()));
|
|
||||||
renderer.expect_render().returning(|_| Ok(()));
|
renderer.expect_render().returning(|_| Ok(()));
|
||||||
renderer.expect_end().returning(|| Ok(()));
|
|
||||||
|
|
||||||
timer.run(renderer).unwrap();
|
timer.run(renderer).unwrap();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user