From 2fae95bdfb2e766ac2820ab1520ef3cdaed24ad0 Mon Sep 17 00:00:00 2001 From: Kuba Clark Date: Sun, 31 May 2020 09:12:37 +0200 Subject: [PATCH] Bar widget (#12) * Implement simple bar widget * Make it easier to create new examples * Add bar example * Add README to examples * Remove unnecessary imports --- Cargo.toml | 2 +- README.md | 8 +- examples/Cargo.toml | 20 +++++ examples/README.md | 8 ++ examples/bar.rs | 82 +++++++++++++++++++ examples/{demo/src/main.rs => demo.rs} | 0 examples/demo/README.md | 12 --- .../include/fonts_noto_sans_numeric_80.c | 0 examples/{demo => }/include/lv_conf.h | 0 .../{demo => }/include/noto_sans_numeric_80.h | 0 lvgl/src/lib.rs | 7 +- lvgl/src/support.rs | 19 +++-- lvgl/src/widgets.rs | 0 lvgl/src/widgets/bar.rs | 33 ++++++++ lvgl/src/widgets/mod.rs | 3 + 15 files changed, 169 insertions(+), 25 deletions(-) create mode 100644 examples/Cargo.toml create mode 100644 examples/README.md create mode 100644 examples/bar.rs rename examples/{demo/src/main.rs => demo.rs} (100%) delete mode 100644 examples/demo/README.md rename examples/{demo => }/include/fonts_noto_sans_numeric_80.c (100%) rename examples/{demo => }/include/lv_conf.h (100%) rename examples/{demo => }/include/noto_sans_numeric_80.h (100%) delete mode 100644 lvgl/src/widgets.rs create mode 100644 lvgl/src/widgets/bar.rs create mode 100644 lvgl/src/widgets/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 57a7ed7..491624a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,5 +2,5 @@ members = [ "lvgl", "lvgl-sys", - "examples/demo", + "examples" ] diff --git a/README.md b/README.md index 865520e..97d7255 100644 --- a/README.md +++ b/README.md @@ -54,4 +54,10 @@ That is required, so we can safely provide Rust pointers through FFI. For that r ## Running the demo -[This project contains an example that can run in a desktop simulator.](./examples/demo) +[This project contains examples that can run in a desktop simulator.](./examples) + +To run the `demo` example: + +```shell +$ DEP_LV_CONFIG_PATH=`pwd`/examples/include cargo run --example demo +``` diff --git a/examples/Cargo.toml b/examples/Cargo.toml new file mode 100644 index 0000000..6338aa7 --- /dev/null +++ b/examples/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "demo" +version = "0.1.0" +authors = ["Rafael Caricio "] +edition = "2018" +publish = false + +[dev-dependencies] +lvgl = { path = "../lvgl" } +lvgl-sys = { path = "../lvgl-sys" } +embedded-graphics = "0.6" +embedded-graphics-simulator = "0.2.0" + +[[example]] +name = "demo" +path = "demo.rs" + +[[example]] +name = "bar" +path = "bar.rs" diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..395437b --- /dev/null +++ b/examples/README.md @@ -0,0 +1,8 @@ +## Examples of how to use various `lvgl-rs` widgets/components + +All examples can be executed using: +```shell +cargo run --example +``` + +The `DEP_LV_CONFIG_PATH` environment variable is necessary, as explained in the [README](../README.md). diff --git a/examples/bar.rs b/examples/bar.rs new file mode 100644 index 0000000..2b16608 --- /dev/null +++ b/examples/bar.rs @@ -0,0 +1,82 @@ +use embedded_graphics::pixelcolor::Rgb565; +use embedded_graphics::prelude::*; +use embedded_graphics_simulator::{ + OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window, +}; +use lvgl::{self, widgets::Bar, Align, Color, DisplayDriver, Object, Style, UI}; +use lvgl_sys; +use std::sync::{mpsc, Arc, Mutex}; +use std::thread::sleep; +use std::time::Duration; + +fn main() -> Result<(), String> { + let mut display: SimulatorDisplay = SimulatorDisplay::new(Size::new( + lvgl_sys::LV_HOR_RES_MAX, + lvgl_sys::LV_VER_RES_MAX, + )); + + let output_settings = OutputSettingsBuilder::new().scale(2).build(); + let mut window = Window::new("Bar Example", &output_settings); + + let mut ui = UI::init().unwrap(); + + // Implement and register your display: + let display_driver = DisplayDriver::new(&mut display); + ui.disp_drv_register(display_driver); + + // Create screen and widgets + let mut screen = ui.scr_act(); + + let mut screen_style = Style::new(); + screen_style.set_body_main_color(Color::from_rgb((0, 0, 0))); + screen_style.set_body_grad_color(Color::from_rgb((0, 0, 0))); + screen.set_style(screen_style); + + // Create the bar object + let mut bar = Bar::new(&mut screen); + bar.set_size(50, 175); + bar.set_align(&mut screen, Align::Center, 0, 0); + bar.set_range(0, 100); + bar.set_value(0); + + let threaded_ui = Arc::new(Mutex::new(ui)); + + let (stop_ch, read_ch) = mpsc::channel(); + let closure_ui = threaded_ui.clone(); + let tick_thr = std::thread::spawn(move || loop { + let period = Duration::from_millis(5); + closure_ui.lock().unwrap().tick_inc(period); + + sleep(period); + if read_ch.try_recv().is_ok() { + break; + } + }); + + let mut i = 0; + 'running: loop { + if i > 100 { + i = 0; + } + bar.set_value(i); + i += 1; + + sleep(Duration::from_millis(25)); + + threaded_ui.lock().unwrap().task_handler(); + + window.update(&display); + + for event in window.events() { + match event { + SimulatorEvent::Quit => break 'running, + _ => {} + } + } + } + + stop_ch.send(true).unwrap(); + tick_thr.join().unwrap(); + + Ok(()) +} diff --git a/examples/demo/src/main.rs b/examples/demo.rs similarity index 100% rename from examples/demo/src/main.rs rename to examples/demo.rs diff --git a/examples/demo/README.md b/examples/demo/README.md deleted file mode 100644 index 0ce3e64..0000000 --- a/examples/demo/README.md +++ /dev/null @@ -1,12 +0,0 @@ -From base of the repository, install LVGL git submodule. - -``` -git submodule update --init -``` - -Run this demo: - -``` -cd examples/demo/ -DEP_LV_CONFIG_PATH=./include cargo run -``` diff --git a/examples/demo/include/fonts_noto_sans_numeric_80.c b/examples/include/fonts_noto_sans_numeric_80.c similarity index 100% rename from examples/demo/include/fonts_noto_sans_numeric_80.c rename to examples/include/fonts_noto_sans_numeric_80.c diff --git a/examples/demo/include/lv_conf.h b/examples/include/lv_conf.h similarity index 100% rename from examples/demo/include/lv_conf.h rename to examples/include/lv_conf.h diff --git a/examples/demo/include/noto_sans_numeric_80.h b/examples/include/noto_sans_numeric_80.h similarity index 100% rename from examples/demo/include/noto_sans_numeric_80.h rename to examples/include/noto_sans_numeric_80.h diff --git a/lvgl/src/lib.rs b/lvgl/src/lib.rs index 56268a8..d010efd 100644 --- a/lvgl/src/lib.rs +++ b/lvgl/src/lib.rs @@ -2,11 +2,12 @@ extern crate alloc; -mod global; mod display; +mod global; +#[macro_use] mod support; -mod widgets; +pub mod widgets; -pub use global::{UI, LvError}; pub use display::DisplayDriver; +pub use global::{LvError, UI}; pub use support::*; diff --git a/lvgl/src/support.rs b/lvgl/src/support.rs index 480ecfe..5d38236 100644 --- a/lvgl/src/support.rs +++ b/lvgl/src/support.rs @@ -111,20 +111,23 @@ impl Object for ObjectX { macro_rules! define_object { ($item:ident) => { pub struct $item { - core: ObjectX, + core: $crate::support::ObjectX, } - impl NativeObject for $item { - fn raw(&self) -> ptr::NonNull { + impl $crate::support::NativeObject for $item { + fn raw(&self) -> core::ptr::NonNull { self.core.raw() } } - impl Object for $item { - fn set_style(&mut self, style: Style) { + impl $crate::support::Object for $item { + fn set_style(&mut self, style: $crate::support::Style) { unsafe { - let boxed = Box::new(style.raw); - lvgl_sys::lv_obj_set_style(self.raw().as_mut(), Box::into_raw(boxed)); + let boxed = alloc::boxed::Box::new(style.raw); + lvgl_sys::lv_obj_set_style( + self.raw().as_mut(), + alloc::boxed::Box::into_raw(boxed), + ); }; } } @@ -200,7 +203,7 @@ pub enum Themes { } pub struct Style { - raw: lvgl_sys::lv_style_t, + pub(crate) raw: lvgl_sys::lv_style_t, } impl Style { diff --git a/lvgl/src/widgets.rs b/lvgl/src/widgets.rs deleted file mode 100644 index e69de29..0000000 diff --git a/lvgl/src/widgets/bar.rs b/lvgl/src/widgets/bar.rs new file mode 100644 index 0000000..17a1be6 --- /dev/null +++ b/lvgl/src/widgets/bar.rs @@ -0,0 +1,33 @@ +use crate::support::{NativeObject, ObjectX}; +use core::ptr; +use lvgl_sys; + +define_object!(Bar); + +impl Bar { + pub fn new(parent: &mut C) -> Self + where + C: NativeObject, + { + let raw = unsafe { + let ptr = lvgl_sys::lv_bar_create(parent.raw().as_mut(), ptr::null_mut()); + ptr::NonNull::new_unchecked(ptr) + }; + let core = ObjectX::from_raw(raw); + Self { core } + } + + /// Set minimum and the maximum values of the bar + pub fn set_range(&mut self, min: i16, max: i16) { + unsafe { + lvgl_sys::lv_bar_set_range(self.core.raw().as_mut(), min, max); + } + } + + /// Set the value of the bar + pub fn set_value(&mut self, value: i16) { + unsafe { + lvgl_sys::lv_bar_set_value(self.core.raw().as_mut(), value, 0); + } + } +} diff --git a/lvgl/src/widgets/mod.rs b/lvgl/src/widgets/mod.rs new file mode 100644 index 0000000..af83335 --- /dev/null +++ b/lvgl/src/widgets/mod.rs @@ -0,0 +1,3 @@ +mod bar; + +pub use self::bar::Bar;