diff --git a/assets/indic-falling.bmp b/assets/indic-falling.bmp index c56a035..859d6ad 100644 Binary files a/assets/indic-falling.bmp and b/assets/indic-falling.bmp differ diff --git a/assets/indic-falling.svg b/assets/indic-falling.svg index ef69cb6..8d10fc3 100644 --- a/assets/indic-falling.svg +++ b/assets/indic-falling.svg @@ -28,8 +28,8 @@ inkscape:document-units="mm" inkscape:export-bgcolor="#080808ff" inkscape:zoom="32" - inkscape:cx="3.46875" - inkscape:cy="9.140625" + inkscape:cx="3.640625" + inkscape:cy="8.328125" inkscape:window-width="1916" inkscape:window-height="1032" inkscape:window-x="0" @@ -50,18 +50,9 @@ height="197.24825" x="-44.312061" y="-1.4580333" /> - + diff --git a/assets/indic-rising.bmp b/assets/indic-rising.bmp index 0fb32f0..bc67411 100644 Binary files a/assets/indic-rising.bmp and b/assets/indic-rising.bmp differ diff --git a/assets/indic-rising.svg b/assets/indic-rising.svg index 2507ddb..6a6818a 100644 --- a/assets/indic-rising.svg +++ b/assets/indic-rising.svg @@ -28,8 +28,8 @@ inkscape:document-units="mm" inkscape:export-bgcolor="#080808ff" inkscape:zoom="32" - inkscape:cx="3.46875" - inkscape:cy="9.140625" + inkscape:cx="3.640625" + inkscape:cy="8.328125" inkscape:window-width="1916" inkscape:window-height="1032" inkscape:window-x="0" @@ -50,18 +50,9 @@ height="197.24825" x="-44.312061" y="-1.4580333" /> - + diff --git a/assets/indic-steady.bmp b/assets/indic-steady.bmp index af79bb9..9f35aee 100644 Binary files a/assets/indic-steady.bmp and b/assets/indic-steady.bmp differ diff --git a/assets/indic-steady.svg b/assets/indic-steady.svg index a5e3a98..4ac30f3 100644 --- a/assets/indic-steady.svg +++ b/assets/indic-steady.svg @@ -28,8 +28,8 @@ inkscape:document-units="mm" inkscape:export-bgcolor="#080808ff" inkscape:zoom="32" - inkscape:cx="3.46875" - inkscape:cy="9.140625" + inkscape:cx="3.640625" + inkscape:cy="8.328125" inkscape:window-width="1916" inkscape:window-height="1032" inkscape:window-x="0" @@ -50,18 +50,9 @@ height="197.24825" x="-44.312061" y="-1.4580333" /> - + diff --git a/src/colors.rs b/src/colors.rs new file mode 100644 index 0000000..03d9bc8 --- /dev/null +++ b/src/colors.rs @@ -0,0 +1,12 @@ +use embedded_graphics::pixelcolor::Rgb565; +use embedded_graphics::prelude::RgbColor; +use embedded_graphics::prelude::WebColors; + +pub const BACKGROUND_COLOR: Rgb565 = Rgb565::BLACK; +pub const FRAME_BACKGROUD_COLOR: Rgb565 = Rgb565::new(1, 2, 1); +pub const FRAME_STROKE_COLOR: Rgb565 = Rgb565::new(4, 9, 4); + +pub const MAIN_TEXT_COLOR: Rgb565 = Rgb565::WHITE; +pub const SUB_TEXT_COLOR: Rgb565 = Rgb565::CSS_DARK_GRAY; + +pub const FRAME_STROKE: u32 = 3; diff --git a/src/images.rs b/src/images.rs index a8b4a9f..e698aa3 100644 --- a/src/images.rs +++ b/src/images.rs @@ -1,4 +1,5 @@ -use std::{cell::UnsafeCell, mem::MaybeUninit}; +use std::cell::UnsafeCell; +use std::mem::MaybeUninit; use embedded_graphics::pixelcolor::Rgb565; use tinybmp::Bmp; @@ -15,6 +16,8 @@ thread_local! { pub static TENDENCY_FALLING: UnsafeCell>> = const { UnsafeCell::new(MaybeUninit::zeroed()) }; } +pub type StaticImage = std::thread::LocalKey>>>; + macro_rules! load_image { ($stat:expr, $path:expr) => { $stat @@ -26,6 +29,8 @@ macro_rules! load_image { macro_rules! get_image { ($image:expr) => { unsafe { + use std::mem::MaybeUninit; + use tinybmp::Bmp; &*std::mem::transmute::<*mut MaybeUninit>, *mut Bmp>( $image.with(|g| g.get()), ) diff --git a/src/main.rs b/src/main.rs index 0672883..6833498 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,27 +1,19 @@ //#![feature(unsafe_cell_access)] +mod colors; mod images; +mod views; -use core::fmt::Write; use std::cell::UnsafeCell; use std::mem::MaybeUninit; -use buoyant::primitives::Point; -use buoyant::render::StrokedShape; use buoyant::view::prelude::*; use embedded_graphics::pixelcolor::Rgb565; -use embedded_graphics::pixelcolor::Rgb888; use embedded_graphics::prelude::*; use embedded_graphics_simulator::OutputSettings; use embedded_graphics_simulator::SimulatorDisplay; use embedded_graphics_simulator::Window; -use embedded_sprites::include_image; -use embedded_sprites::sprite::Sprite; use heapless::format; -use profont::PROFONT_12_POINT; -use profont::PROFONT_14_POINT; -use profont::PROFONT_18_POINT; -use profont::PROFONT_24_POINT; use tinybmp::Bmp; const BACKGROUND_COLOR: Rgb565 = Rgb565::BLACK; @@ -34,7 +26,12 @@ fn main() { let mut display: SimulatorDisplay = SimulatorDisplay::new(Size::new(320, 240)); display.clear(BACKGROUND_COLOR); - hello_view() + // views::menu::menu_view() + // .as_drawable(display.size(), DEFAULT_COLOR) + // .draw(&mut display) + // .unwrap(); + + views::detail::detailed_view(MenuIndicatorType::Temperature(38.3), Tendency::Steady) .as_drawable(display.size(), DEFAULT_COLOR) .draw(&mut display) .unwrap(); @@ -42,25 +39,6 @@ fn main() { window.show_static(&display); } -fn hello_view() -> impl View { - VStack::new(( - HStack::new(( - main_menu_indicator(MenuIndicatorType::Temperature(31.5), Tendency::Falling), - main_menu_indicator(MenuIndicatorType::Humidity(36.2), Tendency::Steady), - )) - .with_spacing(5), - HStack::new(( - main_menu_indicator(MenuIndicatorType::Co2(1329), Tendency::Rising), - main_menu_indicator(MenuIndicatorType::Voc(29), Tendency::Falling), - )) - .with_spacing(5), - )) - .with_spacing(5) -} - -const FRAME_STROKE: u32 = 2; -const FRAME_COLOR: Rgb565 = Rgb565::new(5, 9, 5); - pub enum MenuIndicatorType { Temperature(f32), Humidity(f32), @@ -99,55 +77,6 @@ impl MenuIndicatorType { } } -fn main_menu_indicator(indicator_type: MenuIndicatorType, tendency: Tendency) -> impl View { - Rectangle - .corner_radius(10) - .stroked(FRAME_STROKE) - .foreground_color(FRAME_COLOR) - .background(Alignment::Center, || { - ZStack::new(( - Rectangle - .corner_radius(15) - .foreground_color(Rgb565::new(1, 2, 1)), - VStack::new(( - HStack::new(( - Spacer::default(), - ZStack::new(( - Rectangle - .corner_radius(10) - //.stroked_offset(5, StrokeOffset::Outer) - .foreground_color(Rgb565::new(4, 9, 4)), - buoyant::view::Image::new(get_image!( - indicator_type.get_corresponding_icon() - )), - )) - .flex_frame() - .with_max_size(53, 53) - .with_min_size(53, 53), - Spacer::default(), - )), - HStack::new(( - Spacer::default(), - tendency_indicator(tendency), - Text::new(indicator_type.get_value_str(), &PROFONT_24_POINT), - Text::new( - indicator_type.get_corresponding_unit_string(), - &PROFONT_18_POINT, - ) - .foreground_color(Rgb565::CSS_DARK_GRAY) - .flex_frame() - .with_infinite_max_height() - .with_vertical_alignment(VerticalAlignment::Bottom) - .with_max_height(25), - Spacer::default(), - )), - )) - .with_alignment(HorizontalAlignment::Center) - .flex_frame(), - )) - }) -} - pub enum Tendency { Rising, Steady, diff --git a/src/views.rs b/src/views.rs new file mode 100644 index 0000000..38dde75 --- /dev/null +++ b/src/views.rs @@ -0,0 +1,3 @@ +pub mod detail; +pub mod icon; +pub mod menu; diff --git a/src/views/detail.rs b/src/views/detail.rs new file mode 100644 index 0000000..0bcf0ff --- /dev/null +++ b/src/views/detail.rs @@ -0,0 +1,52 @@ +use buoyant::layout::HorizontalAlignment; +use buoyant::layout::VerticalAlignment; +use buoyant::view::HStack; +use buoyant::view::Spacer; +use buoyant::view::Text; +use buoyant::view::VStack; +use buoyant::view::View; +use buoyant::view::ViewExt; +use embedded_graphics::pixelcolor::Rgb565; +use profont::PROFONT_18_POINT; +use profont::PROFONT_24_POINT; + +use crate::MenuIndicatorType; +use crate::Tendency; +use crate::colors::FRAME_STROKE_COLOR; +use crate::colors::MAIN_TEXT_COLOR; +use crate::colors::SUB_TEXT_COLOR; +use crate::tendency_indicator; +use crate::views::icon::icon_box_view; + +pub fn detailed_view(indicator: MenuIndicatorType, tendency: Tendency) -> impl View { + VStack::new(( + // Header + HStack::new(( + icon_box_view(FRAME_STROKE_COLOR, indicator.get_corresponding_icon()), + Spacer::default().flex_frame().with_max_width(10), + tendency_indicator(tendency), + Text::new(indicator.get_value_str(), &PROFONT_24_POINT) + .foreground_color(MAIN_TEXT_COLOR), + Text::new(indicator.get_corresponding_unit_string(), &PROFONT_18_POINT) + .foreground_color(SUB_TEXT_COLOR) + .flex_frame() + .with_infinite_max_height() + .with_vertical_alignment(VerticalAlignment::Bottom) + .with_max_height(25), + Spacer::default(), + Text::new("Temperature", &PROFONT_18_POINT) + .foreground_color(SUB_TEXT_COLOR) + .flex_frame() + .with_infinite_max_height() + .with_vertical_alignment(VerticalAlignment::Bottom) + .with_max_height(25), + Spacer::default().flex_frame().with_max_width(10), + )), + // Window + Spacer::default() + .flex_frame() + .with_infinite_max_width() + .with_infinite_max_height(), + )) + .with_alignment(HorizontalAlignment::Leading) +} diff --git a/src/views/icon.rs b/src/views/icon.rs new file mode 100644 index 0000000..8d0f5c1 --- /dev/null +++ b/src/views/icon.rs @@ -0,0 +1,18 @@ +use buoyant::view::View; +use buoyant::view::ViewExt; +use buoyant::view::ZStack; +use buoyant::view::shape::Rectangle; +use embedded_graphics::pixelcolor::Rgb565; + +use crate::get_image; +use crate::images::StaticImage; + +pub fn icon_box_view(box_color: Rgb565, icon: &'static StaticImage) -> impl View { + ZStack::new(( + Rectangle.corner_radius(10).foreground_color(box_color), + buoyant::view::Image::new(get_image!(icon)), + )) + .flex_frame() + .with_max_size(53, 53) + .with_min_size(53, 53) +} diff --git a/src/views/menu.rs b/src/views/menu.rs new file mode 100644 index 0000000..23d7a7a --- /dev/null +++ b/src/views/menu.rs @@ -0,0 +1,85 @@ +use buoyant::view::VStack; +use buoyant::view::View; + +use buoyant::view::prelude::*; +use embedded_graphics::pixelcolor::Rgb565; +use embedded_graphics::prelude::*; +use profont::PROFONT_18_POINT; +use profont::PROFONT_24_POINT; + +use crate::MenuIndicatorType; +use crate::Tendency; +use crate::colors::FRAME_BACKGROUD_COLOR; +use crate::colors::FRAME_STROKE; +use crate::colors::FRAME_STROKE_COLOR; +use crate::colors::MAIN_TEXT_COLOR; +use crate::colors::SUB_TEXT_COLOR; +use crate::get_image; +use crate::views::icon::icon_box_view; + +pub fn menu_view() -> impl View { + VStack::new(( + HStack::new(( + main_menu_indicator(MenuIndicatorType::Temperature(31.5), Tendency::Falling), + main_menu_indicator(MenuIndicatorType::Humidity(36.2), Tendency::Steady), + )) + .with_spacing(5), + HStack::new(( + main_menu_indicator(MenuIndicatorType::Co2(1329), Tendency::Rising), + main_menu_indicator(MenuIndicatorType::Voc(29), Tendency::Falling), + )) + .with_spacing(5), + )) + .with_spacing(5) +} + +fn main_menu_indicator(indicator_type: MenuIndicatorType, tendency: Tendency) -> impl View { + Rectangle + .corner_radius(10) + .stroked(FRAME_STROKE) + .foreground_color(FRAME_STROKE_COLOR) + .background(Alignment::Center, || { + ZStack::new(( + Rectangle + .corner_radius(15) + .foreground_color(FRAME_BACKGROUD_COLOR), + VStack::new(( + HStack::new(( + Spacer::default(), + icon_box_view(FRAME_STROKE_COLOR, indicator_type.get_corresponding_icon()), + Spacer::default(), + )), + HStack::new(( + Spacer::default(), + tendency_indicator(tendency), + Text::new(indicator_type.get_value_str(), &PROFONT_24_POINT) + .foreground_color(MAIN_TEXT_COLOR), + Text::new( + indicator_type.get_corresponding_unit_string(), + &PROFONT_18_POINT, + ) + .foreground_color(SUB_TEXT_COLOR) + .flex_frame() + .with_infinite_max_height() + .with_vertical_alignment(VerticalAlignment::Bottom) + .with_max_height(25), + Spacer::default(), + )), + )) + .with_alignment(HorizontalAlignment::Center) + .flex_frame(), + )) + }) +} + +fn tendency_indicator(tendency: Tendency) -> impl View { + HStack::new(( + Image::new(get_image!(tendency.get_corresponding_icon())) + .flex_frame() + .with_min_size(10, 20) + .with_max_size(10, 20), + Spacer::default(), + )) + .flex_frame() + .with_max_width(15) +}