From 818b14200feefd422b1b7d79d53f3d1ddb3be92c Mon Sep 17 00:00:00 2001 From: Ilya Date: Fri, 15 Apr 2022 23:45:35 +0200 Subject: [PATCH] Add component trait and vsplit --- examples/test.rs | 15 +++++----- src/calendar.rs | 30 ++++++++++++++------ src/frame.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ src/list_item.rs | 34 ++++++++++++++++++----- 5 files changed, 129 insertions(+), 23 deletions(-) create mode 100644 src/frame.rs diff --git a/examples/test.rs b/examples/test.rs index 3e4d8ac..f1ebcf6 100644 --- a/examples/test.rs +++ b/examples/test.rs @@ -1,5 +1,5 @@ use embedded_components::{ - Calendar, ComponentStyle, Gauge, List, ListItem, ListItemData, ScrollingCalendar, + Calendar, ComponentStyle, Gauge, List, ListItem, ListItemData, ScrollingCalendar, VSplit, }; use embedded_graphics::{ pixelcolor::{raw::RawU2, BinaryColor, Rgb888}, @@ -85,8 +85,6 @@ fn main() -> Result<(), core::convert::Infallible> { //calendar.draw(&mut display)?; let list = List { - top_left: Point::new(320, 0), - size: Size::new(280, 448), style: calendar_style.clone(), items_shown: 10, list_items: vec![ @@ -94,18 +92,19 @@ fn main() -> Result<(), core::convert::Infallible> { ListItemData::new("O", "Other test task"), ], }; - list.draw(&mut display)?; + //list.draw(&mut display)?; let calendar_week = ScrollingCalendar { - top_left: Point::new(0, 0), - size: Size::new(320, 448), style: calendar_style, day: chrono::Local::now().naive_local().date(), //.checked_add_signed(chrono::Duration::days(28 * 4 * 0 - 14)) //.unwrap(), - weeks: 5, + prev_weeks: 2, + next_weeks: 5, }; - calendar_week.draw(&mut display)?; + //calendar_week.draw(&mut display)?; + + VSplit::new(calendar_week, list).draw(&mut display)?; let output_settings = OutputSettingsBuilder::new() .theme(BinaryColorTheme::Default) diff --git a/src/calendar.rs b/src/calendar.rs index 8a702ef..3ebad71 100644 --- a/src/calendar.rs +++ b/src/calendar.rs @@ -311,11 +311,21 @@ impl ScrollingWeek { } pub struct ScrollingCalendar { - pub top_left: Point, - pub size: Size, pub style: ComponentStyle, pub day: chrono::NaiveDate, - pub weeks: u32, + pub prev_weeks: u32, + pub next_weeks: u32, +} + +impl ScrollingCalendar { + pub fn new(style: ComponentStyle, prev_weeks: u32, next_weeks: u32) -> Self { + Self { + style, + day: chrono::Local::now().naive_local().date(), + prev_weeks, + next_weeks, + } + } } impl Drawable for ScrollingCalendar @@ -329,20 +339,24 @@ where where D: DrawTarget, { - let height = self.size.height / (1 + self.weeks * 2); + let top_left = target.bounding_box().top_left; + let size = target.bounding_box().size; + + let total_weeks = self.prev_weeks + 1 + self.next_weeks; + let height = size.height / total_weeks; let mut week = ScrollingWeek::from_date( self .day - .checked_sub_signed(chrono::Duration::days(self.weeks as i64 * 7)) + .checked_sub_signed(chrono::Duration::days(self.prev_weeks as i64 * 7)) .unwrap(), ); - for i in 0..(1 + self.weeks * 2) { + for i in 0..total_weeks { week = week.succ(); let calendar_week = CalendarWeek { - top_left: Point::new(self.top_left.x, self.top_left.y + (height * i) as i32), - size: Size::new(self.size.width, height), + top_left: Point::new(top_left.x, top_left.y + (height * i) as i32), + size: Size::new(size.width, height), style: self.style.clone(), year: week.year(), month: week.month(), diff --git a/src/frame.rs b/src/frame.rs new file mode 100644 index 0000000..34b735d --- /dev/null +++ b/src/frame.rs @@ -0,0 +1,71 @@ +use embedded_graphics::{pixelcolor::BinaryColor, prelude::*, primitives::Rectangle}; +use embedded_layout::View; + +pub trait Component { + fn set_top_left(&mut self, top_left: Point); + fn set_size(&mut self, size: Size); +} + +pub struct Frame { + drawtarget: D, + pub weight: f32, +} + +pub struct VSplit { + pub left: T, + pub right: U, + pub ratio: f32, +} + +impl VSplit { + pub fn new(left: T, right: U) -> Self { + VSplit { + left, + right, + ratio: 0.5, + } + } +} + +impl VSplit { + pub fn with_ratio(self, ratio: f32) -> Self { + VSplit { ratio, ..self } + } +} + +impl Drawable for VSplit +where + C: PixelColor + From, + T: Drawable, + U: Drawable, +{ + type Color = C; + type Output = (); + + fn draw(&self, target: &mut D) -> Result + where + D: DrawTarget, + { + let size = target.bounding_box().size; + let left_width = (size.width as f32 * self.ratio) as u32; + + self.left.draw(&mut target.clipped(&Rectangle::new( + Point::default(), + Size::new(left_width, size.height), + )))?; + + self.right.draw(&mut target.clipped(&Rectangle::new( + Point::new(left_width as i32, 0), + Size::new(size.width - left_width, size.height), + )))?; + + Ok(()) + } +} + +pub struct HSplit { + pub top_left: Point, + pub size: Size, + pub top: T, + pub bottom: T, +} diff --git a/src/lib.rs b/src/lib.rs index e08a390..dad8d84 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,13 @@ mod bullet_counter; mod calendar; +mod frame; mod gauge; mod list_item; mod style; pub use bullet_counter::BulletCounter; pub use calendar::{Calendar, ScrollingCalendar}; +pub use frame::{Component, HSplit, VSplit}; pub use gauge::Gauge; pub use list_item::{List, ListItem, ListItemData}; pub use style::ComponentStyle; diff --git a/src/list_item.rs b/src/list_item.rs index 8c796d2..9573c64 100644 --- a/src/list_item.rs +++ b/src/list_item.rs @@ -33,12 +33,20 @@ impl<'a> ListItemData { pub struct List { pub style: ComponentStyle, - pub top_left: Point, - pub size: Size, pub items_shown: usize, pub list_items: Vec, } +impl List { + pub fn new(style: ComponentStyle, list_items: Vec, items_shown: usize) -> Self { + Self { + style, + items_shown, + list_items, + } + } +} + impl Drawable for List where C: PixelColor + From, @@ -50,7 +58,10 @@ where where D: DrawTarget, { - let rect = Rectangle::new(self.top_left, self.size); + let top_left = target.bounding_box().top_left; + let size = target.bounding_box().size; + + let rect = Rectangle::new(top_left, size); rect .into_styled(PrimitiveStyle::with_stroke( self.style.bg_color, @@ -61,13 +72,22 @@ where .into_styled(PrimitiveStyle::with_fill(self.style.bg_color)) .draw(target)?; - let height = self.size.height / self.items_shown as u32; + let height = size.height / self.items_shown as u32; for (i, item) in self.list_items.iter().enumerate().take(self.items_shown) { + let (fg_color, bg_color) = match item.progress >= 100f32 { + true => (self.style.fg_color, self.style.hi_color), + _ => (self.style.fg_color, self.style.bg_color), + }; + let item_style = ComponentStyle { + fg_color, + bg_color, + ..self.style.clone() + }; let list_item = ListItem { - style: self.style.clone(), - top_left: self.top_left + Point::new(0, (height as usize * i) as i32), - size: Size::new(self.size.width, height), + style: item_style, + top_left: top_left + Point::new(0, (height as usize * i) as i32), + size: Size::new(size.width, height), text: &item.text, icon: &item.icon, progress: item.progress,