Bar widget (#12)

* Implement simple bar widget

* Make it easier to create new examples

* Add bar example

* Add README to examples

* Remove unnecessary imports
This commit is contained in:
Kuba Clark 2020-05-31 09:12:37 +02:00 committed by GitHub
parent 81d924e854
commit 2fae95bdfb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 169 additions and 25 deletions

View file

@ -2,5 +2,5 @@
members = [
"lvgl",
"lvgl-sys",
"examples/demo",
"examples"
]

View file

@ -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
```

20
examples/Cargo.toml Normal file
View file

@ -0,0 +1,20 @@
[package]
name = "demo"
version = "0.1.0"
authors = ["Rafael Caricio <crates@caric.io>"]
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"

8
examples/README.md Normal file
View file

@ -0,0 +1,8 @@
## Examples of how to use various `lvgl-rs` widgets/components
All examples can be executed using:
```shell
cargo run --example <name>
```
The `DEP_LV_CONFIG_PATH` environment variable is necessary, as explained in the [README](../README.md).

82
examples/bar.rs Normal file
View file

@ -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<Rgb565> = 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(())
}

View file

@ -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
```

View file

@ -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::*;

View file

@ -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<lvgl_sys::lv_obj_t> {
impl $crate::support::NativeObject for $item {
fn raw(&self) -> core::ptr::NonNull<lvgl_sys::lv_obj_t> {
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 {

View file

33
lvgl/src/widgets/bar.rs Normal file
View file

@ -0,0 +1,33 @@
use crate::support::{NativeObject, ObjectX};
use core::ptr;
use lvgl_sys;
define_object!(Bar);
impl Bar {
pub fn new<C>(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);
}
}
}

3
lvgl/src/widgets/mod.rs Normal file
View file

@ -0,0 +1,3 @@
mod bar;
pub use self::bar::Bar;