From a78fa73b345cd156563592233b3f8367aa1c28fb Mon Sep 17 00:00:00 2001 From: Sven-Hendrik Haase Date: Mon, 14 Jan 2019 21:14:57 +0100 Subject: [PATCH] Add new shape: Rectangle --- CHANGELOG.md | 3 +- examples/canvas.rs | 30 ++---------------- examples/demo.rs | 11 ++++++- src/widgets/canvas/line.rs | 3 ++ src/widgets/canvas/mod.rs | 21 ++++++++----- src/widgets/canvas/rectangle.rs | 54 +++++++++++++++++++++++++++++++++ 6 files changed, 85 insertions(+), 37 deletions(-) create mode 100644 src/widgets/canvas/rectangle.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 307ddb3..1f2817f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Changelog -## v0.3.1 - To be released +## To be released +* Added a new shape: Rectangle * Upgraded to Rust 2018 edition ## v0.3.0 - 2018-11-04 diff --git a/examples/canvas.rs b/examples/canvas.rs index 0a525be..db845d4 100644 --- a/examples/canvas.rs +++ b/examples/canvas.rs @@ -11,7 +11,7 @@ use termion::screen::AlternateScreen; use tui::backend::TermionBackend; use tui::layout::{Constraint, Direction, Layout, Rect}; use tui::style::Color; -use tui::widgets::canvas::{Canvas, Line, Map, MapResolution}; +use tui::widgets::canvas::{Canvas, Line, Map, MapResolution, Rectangle}; use tui::widgets::{Block, Borders, Widget}; use tui::Terminal; @@ -106,32 +106,8 @@ fn main() -> Result<(), failure::Error> { Canvas::default() .block(Block::default().borders(Borders::ALL).title("Pong")) .paint(|ctx| { - ctx.draw(&Line { - x1: f64::from(app.ball.left()), - y1: f64::from(app.ball.top()), - x2: f64::from(app.ball.right()), - y2: f64::from(app.ball.top()), - color: Color::Yellow, - }); - ctx.draw(&Line { - x1: f64::from(app.ball.right()), - y1: f64::from(app.ball.top()), - x2: f64::from(app.ball.right()), - y2: f64::from(app.ball.bottom()), - color: Color::Yellow, - }); - ctx.draw(&Line { - x1: f64::from(app.ball.right()), - y1: f64::from(app.ball.bottom()), - x2: f64::from(app.ball.left()), - y2: f64::from(app.ball.bottom()), - color: Color::Yellow, - }); - ctx.draw(&Line { - x1: f64::from(app.ball.left()), - y1: f64::from(app.ball.bottom()), - x2: f64::from(app.ball.left()), - y2: f64::from(app.ball.top()), + ctx.draw(&Rectangle { + rect: app.ball, color: Color::Yellow, }); }) diff --git a/examples/demo.rs b/examples/demo.rs index 2bda2e5..592ae8f 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -10,7 +10,7 @@ use termion::screen::AlternateScreen; use tui::backend::{Backend, TermionBackend}; use tui::layout::{Constraint, Direction, Layout, Rect}; use tui::style::{Color, Modifier, Style}; -use tui::widgets::canvas::{Canvas, Line, Map, MapResolution}; +use tui::widgets::canvas::{Canvas, Line, Map, MapResolution, Rectangle}; use tui::widgets::{ Axis, BarChart, Block, Borders, Chart, Dataset, Gauge, List, Marker, Paragraph, Row, SelectableList, Sparkline, Table, Tabs, Text, Widget, @@ -459,6 +459,15 @@ where resolution: MapResolution::High, }); ctx.layer(); + ctx.draw(&Rectangle { + rect: Rect { + x: 0, + y: 30, + width: 10, + height: 10, + }, + color: Color::Yellow, + }); for (i, s1) in app.servers.iter().enumerate() { for s2 in &app.servers[i + 1..] { ctx.draw(&Line { diff --git a/src/widgets/canvas/line.rs b/src/widgets/canvas/line.rs index 4265524..cec9f4e 100644 --- a/src/widgets/canvas/line.rs +++ b/src/widgets/canvas/line.rs @@ -23,6 +23,7 @@ pub struct LineIterator { impl Iterator for LineIterator { type Item = (f64, f64); + fn next(&mut self) -> Option { if self.current < self.end { let pos = ( @@ -40,6 +41,7 @@ impl Iterator for LineIterator { impl<'a> IntoIterator for &'a Line { type Item = (f64, f64); type IntoIter = LineIterator; + fn into_iter(self) -> Self::IntoIter { let dx = self.x1.max(self.x2) - self.x1.min(self.x2); let dy = self.y1.max(self.y2) - self.y1.min(self.y2); @@ -63,6 +65,7 @@ impl<'a> Shape<'a> for Line { fn color(&self) -> Color { self.color } + fn points(&'a self) -> Box + 'a> { Box::new(self.into_iter()) } diff --git a/src/widgets/canvas/mod.rs b/src/widgets/canvas/mod.rs index 8d048b9..f5edf1b 100644 --- a/src/widgets/canvas/mod.rs +++ b/src/widgets/canvas/mod.rs @@ -1,11 +1,13 @@ mod line; mod map; mod points; +mod rectangle; mod world; pub use self::line::Line; pub use self::map::{Map, MapResolution}; pub use self::points::Points; +pub use self::rectangle::Rectangle; use crate::buffer::Buffer; use crate::layout::Rect; @@ -133,7 +135,8 @@ impl<'a> Context<'a> { /// /// ``` /// # use tui::widgets::{Block, Borders}; -/// # use tui::widgets::canvas::{Canvas, Shape, Line, Map, MapResolution}; +/// # use tui::layout::Rect; +/// # use tui::widgets::canvas::{Canvas, Shape, Line, Rectangle, Map, MapResolution}; /// # use tui::style::Color; /// # fn main() { /// Canvas::default() @@ -141,23 +144,25 @@ impl<'a> Context<'a> { /// .x_bounds([-180.0, 180.0]) /// .y_bounds([-90.0, 90.0]) /// .paint(|ctx| { -/// ctx.draw(&Map{ +/// ctx.draw(&Map { /// resolution: MapResolution::High, /// color: Color::White /// }); /// ctx.layer(); -/// ctx.draw(&Line{ +/// ctx.draw(&Line { /// x1: 0.0, /// y1: 10.0, /// x2: 10.0, /// y2: 10.0, /// color: Color::White, /// }); -/// ctx.draw(&Line{ -/// x1: 10.0, -/// y1: 10.0, -/// x2: 20.0, -/// y2: 20.0, +/// ctx.draw(&Rectangle { +/// rect: Rect { +/// x: 10, +/// y: 20, +/// width: 10, +/// height: 10, +/// }, /// color: Color::Red /// }); /// }); diff --git a/src/widgets/canvas/rectangle.rs b/src/widgets/canvas/rectangle.rs new file mode 100644 index 0000000..91a2e2b --- /dev/null +++ b/src/widgets/canvas/rectangle.rs @@ -0,0 +1,54 @@ +use crate::layout::Rect; +use crate::style::Color; +use crate::widgets::canvas::{Line, Shape}; +use itertools::Itertools; + +/// Shape to draw a rectangle from a `Rect` with the given color +pub struct Rectangle { + pub rect: Rect, + pub color: Color, +} + +impl<'a> Shape<'a> for Rectangle { + fn color(&self) -> Color { + self.color + } + + fn points(&'a self) -> Box + 'a> { + let left_line = Line { + x1: f64::from(self.rect.x), + y1: f64::from(self.rect.y), + x2: f64::from(self.rect.x), + y2: f64::from(self.rect.y + self.rect.height), + color: self.color, + }; + let top_line = Line { + x1: f64::from(self.rect.x), + y1: f64::from(self.rect.y + self.rect.height), + x2: f64::from(self.rect.x + self.rect.width), + y2: f64::from(self.rect.y + self.rect.height), + color: self.color, + }; + let right_line = Line { + x1: f64::from(self.rect.x + self.rect.width), + y1: f64::from(self.rect.y), + x2: f64::from(self.rect.x + self.rect.width), + y2: f64::from(self.rect.y + self.rect.height), + color: self.color, + }; + let bottom_line = Line { + x1: f64::from(self.rect.x), + y1: f64::from(self.rect.y), + x2: f64::from(self.rect.x + self.rect.width), + y2: f64::from(self.rect.y), + color: self.color, + }; + Box::new( + left_line.into_iter().merge( + top_line + .into_iter() + .merge(right_line.into_iter().merge(bottom_line.into_iter())), + ), + ) + } +}