Browse Source

Add item list

master
Ilya 4 years ago
parent
commit
5562b57ea5
  1. 45
      examples/test.rs
  2. 68
      src/calendar.rs
  3. 2
      src/lib.rs
  4. 116
      src/list_item.rs
  5. 14
      src/style.rs

45
examples/test.rs

@ -1,4 +1,6 @@
use embedded_components::{Calendar, ComponentStyle, Gauge, ScrollingCalendar};
use embedded_components::{
Calendar, ComponentStyle, Gauge, List, ListItem, ListItemData, ScrollingCalendar,
};
use embedded_graphics::{
pixelcolor::{raw::RawU2, BinaryColor, Rgb888},
prelude::*,
@ -48,12 +50,21 @@ impl From<Rgb888> for TriColor {
fn main() -> Result<(), core::convert::Infallible> {
//let mut display = SimulatorDisplay::<BinaryColor>::new(Size::new(212, 104));
//let mut display = SimulatorDisplay::<BinaryColor>::new(Size::new(800, 480));
let mut display = SimulatorDisplay::<TriColor>::new(Size::new(800, 480));
let mut display = SimulatorDisplay::<TriColor>::new(Size::new(600, 448));
let fg_color = TriColor::Black;
let bg_color = TriColor::White;
let hi_color = Some(TriColor::Red);
let calendar_style = ComponentStyle {
border: 1,
bezel: 1,
fg_color,
bg_color,
hi_color: TriColor::Red,
border_color: TriColor::Black,
};
let gauge = Gauge {
top_left: Point::new(300, 300),
bezel: 1,
@ -64,30 +75,30 @@ fn main() -> Result<(), core::convert::Infallible> {
bg_color,
text: "test test test test test",
};
gauge.draw(&mut display)?;
//gauge.draw(&mut display)?;
let calendar = Calendar {
top_left: Point::new(10, 10),
size: Size::new(196, 196),
border: 1,
fg_color,
bg_color,
hi_color,
style: calendar_style.clone(),
};
calendar.draw(&mut display)?;
//calendar.draw(&mut display)?;
let calendar_style = ComponentStyle {
border: 1,
bezel: 1,
fg_color,
bg_color,
hi_color: TriColor::Red,
border_color: TriColor::Black,
let list = List {
top_left: Point::new(320, 0),
size: Size::new(280, 448),
style: calendar_style.clone(),
items_shown: 10,
list_items: vec![
ListItemData::new("I", "Test task").with_progress(100f32),
ListItemData::new("O", "Other test task"),
],
};
list.draw(&mut display)?;
let calendar_week = ScrollingCalendar {
top_left: Point::new(400, 0),
size: Size::new(396, 480),
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))

68
src/calendar.rs

@ -88,9 +88,7 @@ where
pub struct CalendarMonth<C> {
pub top_left: Point,
pub size: Size,
pub border: u32,
pub fg_color: C,
pub bg_color: C,
pub style: ComponentStyle<C>,
pub month: chrono::Month,
}
@ -107,14 +105,17 @@ where
{
let rect = Rectangle::new(
self.top_left,
self.size + Size::new(self.border / 2 + 1, self.border / 2 + 1),
self.size + Size::new(self.style.border / 2 + 1, self.style.border / 2 + 1),
);
rect
.into_styled(PrimitiveStyle::with_stroke(self.fg_color, self.border))
.into_styled(PrimitiveStyle::with_stroke(
self.style.fg_color,
self.style.border,
))
.draw(target)?;
let month_font = font((self.size.height as f32 * 0.8 - 2.) as u32);
let text_style = MonoTextStyle::new(&month_font, self.fg_color);
let text_style = MonoTextStyle::new(&month_font, self.style.fg_color);
Text::new(self.month.name(), self.top_left, text_style)
.align_to(&rect, horizontal::Center, vertical::Center)
.draw(target)?;
@ -126,11 +127,7 @@ where
pub struct Calendar<C> {
pub top_left: Point,
pub size: Size,
pub border: u32,
pub fg_color: C,
pub bg_color: C,
// If hi_color is None, the fg and bg colors are inverted instead.
pub hi_color: Option<C>,
pub style: ComponentStyle<C>,
}
impl<C> Drawable for Calendar<C>
@ -144,7 +141,7 @@ where
where
D: DrawTarget<Color = C>,
{
let border = self.border;
let border = self.style.border;
let date_now = chrono::offset::Local::now().date();
let first_day = date_now.with_day(1).unwrap();
@ -171,12 +168,11 @@ where
} else {
width * empty_squares
};
let calendar_month = CalendarMonth {
border,
style: self.style.clone(),
top_left: self.top_left,
size: Size::new(month_width, height),
fg_color: self.fg_color,
bg_color: self.bg_color,
month: Month::from_u32(date_now.month()).unwrap(),
};
calendar_month.draw(target)?;
@ -196,22 +192,19 @@ where
>= 5;
let is_today = day_of_month == date_now.day();
let (mut fg_color, mut bg_color, mut border) = match is_weekend ^ is_today {
false => (self.fg_color, self.bg_color, border),
true => (self.bg_color, self.fg_color, 0),
};
if is_today && self.hi_color.is_some() {
(fg_color, bg_color, border) = (self.bg_color, self.hi_color.unwrap(), 0);
}
let style = self.style.clone();
let style = ComponentStyle {
fg_color,
bg_color,
hi_color: fg_color,
border_color: fg_color,
border,
bezel: border,
let mut style = match is_weekend ^ is_today {
false => style.with_border(border),
true => style.invert().with_border(0),
};
if is_today && self.style.hi_color != self.style.bg_color {
style = ComponentStyle {
fg_color: style.hi_color,
bg_color: style.fg_color,
..style
}
}
let calendar_day = CalendarDay {
style,
@ -262,13 +255,6 @@ impl ScrollingWeek {
.succ()
.first_day_of_week()?
.checked_sub_signed(chrono::Duration::days(1));
match self.succ().first_day_of_week() {
None => self
.first_day_of_week()?
.checked_add_signed(chrono::Duration::days(6)),
Some(date) => date.checked_sub_signed(chrono::Duration::days(1)),
}
}
pub fn from_date(date: chrono::NaiveDate) -> ScrollingWeek {
@ -419,28 +405,24 @@ where
if first_day.weekday().number_from_monday() > 4 {
let month = CalendarMonth {
style: self.style.clone(),
top_left: self.top_left,
size: Size::new(
width * first_day.weekday().number_from_monday(),
width * (first_day.weekday().number_from_monday() - 1),
self.size.height,
),
border: self.style.border,
fg_color: self.style.fg_color,
bg_color: self.style.bg_color,
month: chrono::Month::from_u32(first_day.month()).unwrap(),
};
month.draw(target)?;
} else if last_day.weekday().number_from_monday() < 4 {
let month = CalendarMonth {
style: self.style.clone(),
top_left: self.top_left
+ Point::new((width * last_day.weekday().number_from_monday()) as i32, 0),
size: Size::new(
width * (7 - last_day.weekday().number_from_monday()),
self.size.height,
),
border: self.style.border,
fg_color: self.style.fg_color,
bg_color: self.style.bg_color,
month: chrono::Month::from_u32(
last_day
.checked_add_signed(chrono::Duration::days(1))

2
src/lib.rs

@ -1,9 +1,11 @@
mod bullet_counter;
mod calendar;
mod gauge;
mod list_item;
mod style;
pub use bullet_counter::BulletCounter;
pub use calendar::{Calendar, ScrollingCalendar};
pub use gauge::Gauge;
pub use list_item::{List, ListItem, ListItemData};
pub use style::ComponentStyle;

116
src/list_item.rs

@ -1,26 +1,45 @@
use crate::ComponentStyle;
use embedded_graphics::{
mono_font::{
ascii::{FONT_10X20, FONT_7X14},
MonoTextStyle,
},
pixelcolor::{BinaryColor, PixelColor},
prelude::*,
primitives::{Line, PrimitiveStyle, Rectangle},
text::Text,
text::{Baseline, Text},
};
use embedded_layout::prelude::*;
pub struct ListItemData {
pub text: &'a str,
pub icon: &'a str,
pub text: String,
pub icon: String,
pub progress: f32,
}
impl<'a> ListItemData {
pub fn new(icon: &'a str, text: &'a str) -> Self {
Self {
icon: String::from(icon),
text: String::from(text),
progress: 0f32,
}
}
pub fn with_progress(self, progress: f32) -> Self {
Self { progress, ..self }
}
}
pub struct List<'a, C> {
pub struct List<C> {
pub style: ComponentStyle<C>,
pub top_left: Point,
pub border: u32,
pub size: Size,
pub fg_color: C,
pub bg_color: C,
pub items_shown: usize,
pub list_items: Vec<ListItemData>,
}
impl<C> Drawable for ListItem<'_, C>
impl<C> Drawable for List<C>
where
C: PixelColor + From<BinaryColor>,
{
@ -33,25 +52,40 @@ where
{
let rect = Rectangle::new(self.top_left, self.size);
rect
.into_styled(PrimitiveStyle::with_stroke(self.fg_color, self.border))
.into_styled(PrimitiveStyle::with_stroke(
self.style.bg_color,
self.style.border,
))
.draw(target)?;
rect
.into_styled(PrimitiveStyle::with_fill(self.fg_color))
.into_styled(PrimitiveStyle::with_fill(self.style.bg_color))
.draw(target)?;
// TODO: draw list items
let height = self.size.height / self.items_shown as u32;
for (i, item) in self.list_items.iter().enumerate().take(self.items_shown) {
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),
text: &item.text,
icon: &item.icon,
progress: item.progress,
};
list_item.draw(target)?;
}
Ok(())
}
}
pub struct ListItem<'a, C> {
pub style: ComponentStyle<C>,
pub top_left: Point,
pub border: u32,
pub size: Size,
pub fg_color: C,
pub bg_color: C,
pub text: &'a str,
pub icon: &'a str,
pub progress: f32,
}
impl<C> Drawable for ListItem<'_, C>
@ -65,14 +99,62 @@ where
where
D: DrawTarget<Color = C>,
{
let rect = Rectangle::new(self.top_left, self.size);
let rect = Rectangle::new(
self.top_left,
self.size + Size::new(self.style.border / 2 + 1, self.style.border / 2 + 1),
);
rect
.into_styled(PrimitiveStyle::with_stroke(self.fg_color, self.border))
.into_styled(PrimitiveStyle::with_fill(self.style.bg_color))
.draw(target)?;
rect
.into_styled(PrimitiveStyle::with_fill(self.fg_color))
.into_styled(PrimitiveStyle::with_stroke(
self.style.border_color,
self.style.border,
))
.draw(target)?;
let icon_square = Rectangle::new(self.top_left, Size::new(rect.size.height, rect.size.height));
icon_square
.into_styled(PrimitiveStyle::with_stroke(
self.style.border_color,
self.style.border,
))
.draw(target)?;
let icon_style = MonoTextStyle::new(&FONT_10X20, self.style.hi_color);
let mut icon = Text::with_baseline(self.icon, self.top_left, icon_style, Baseline::Middle);
let icon_box = icon.bounding_box();
icon.position = self.top_left
+ Point::new(
(self.size.height / 2 - icon_box.size.width / 2) as i32,
(self.size.height / 2) as i32,
);
icon.draw(&mut target.clipped(&rect))?;
let text_style = MonoTextStyle::new(&FONT_10X20, self.style.fg_color);
let mut text = Text::with_baseline(self.text, self.top_left, text_style, Baseline::Middle);
let text_box = text.bounding_box();
text.position = self.top_left
+ Point::new(
(self.size.height as f32 * 1.2) as i32,
self.size.height as i32 / 2,
);
text.draw(&mut target.clipped(&rect))?;
if self.progress >= 100f32 {
let strikethrough = Line::new(
text.position + Point::new(0, 1),
text.position + Point::new(text_box.size.width as i32, 1),
);
strikethrough
.into_styled(PrimitiveStyle::with_stroke(self.style.fg_color, 2))
.draw(target)?;
}
Ok(())
}
}

14
src/style.rs

@ -7,3 +7,17 @@ pub struct ComponentStyle<C> {
pub border: u32,
pub bezel: u32,
}
impl<C> ComponentStyle<C> {
pub fn invert(self) -> Self {
ComponentStyle {
fg_color: self.bg_color,
bg_color: self.fg_color,
..self
}
}
pub fn with_border(self, border: u32) -> Self {
ComponentStyle { border, ..self }
}
}

Loading…
Cancel
Save