Improvements in the bindings

This commit is contained in:
Rafael Caricio 2020-04-18 19:20:38 +02:00
parent 3aed1c3075
commit bd91097ecd
8 changed files with 152 additions and 90 deletions

6
Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[workspace]
members = [
"lvgl",
"lvgl-sys",
"examples/demo",
]

View file

@ -51,7 +51,7 @@
/* Default display refresh period.
* Can be changed in the display driver (`lv_disp_drv_t`).*/
#define LV_DISP_DEF_REFR_PERIOD 100 /*[ms]*/
#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/
/* Dot Per Inch: used to initialize default sizes.
* E.g. a button with width = LV_DPI / 2 -> half inch wide

View file

@ -1,6 +1,6 @@
use lvgl_sys;
use lvgl;
use lvgl::{Object, Style};
use lvgl::Object;
use lvgl_sys;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
@ -13,10 +13,8 @@ use std::time::Duration;
fn main() -> Result<(), String> {
let sdl_context = sdl2::init()?;
let video_subsystem = sdl_context.video()?;
let mut framebuffer = [
[Color::from((0, 0, 0)); lvgl_sys::LV_VER_RES_MAX as usize];
lvgl_sys::LV_HOR_RES_MAX as usize
];
let mut framebuffer = [[Color::from((0, 0, 0)); lvgl_sys::LV_VER_RES_MAX as usize];
lvgl_sys::LV_HOR_RES_MAX as usize];
let window = video_subsystem
.window(
@ -65,11 +63,18 @@ fn main() -> Result<(), String> {
// let mut label = lvgl::Label::new(&mut button);
// label.set_text("Hello Mundo!\0");
let font_roboto_28 = unsafe { &lvgl_sys::lv_font_roboto_28 };
let font_noto_sans_numeric_28 = unsafe { &noto_sans_numeric_80 };
let mut screen_style = lvgl::Style::new();
screen_style.set_body_main_color(lvgl::Color::from_rgb((0, 0, 0)));
screen_style.set_body_grad_color(lvgl::Color::from_rgb((0, 0, 0)));
screen.set_style(&mut screen_style);
let mut time = lvgl::Label::new(&mut screen);
let mut style_time = Style::default();
style_time.text.font = unsafe {
Some(&noto_sans_numeric_80)
};
let mut style_time = lvgl::Style::new();
style_time.set_text_font(font_noto_sans_numeric_28);
style_time.set_text_color(lvgl::Color::from_rgb((255, 255, 255)));
time.set_style(&mut style_time);
time.set_align(&mut screen, lvgl::Align::InLeftMid, 20, 0);
time.set_text("20:46\0");
@ -77,10 +82,8 @@ fn main() -> Result<(), String> {
time.set_height(240);
let mut bt = lvgl::Label::new(&mut screen);
let mut style_bt = Style::default();
style_bt.text.font = unsafe {
Some(&lvgl_sys::lv_font_roboto_28)
};
let mut style_bt = lvgl::Style::new();
style_bt.set_text_font(font_roboto_28);
let mut style_power = style_bt.clone();
bt.set_style(&mut style_bt);
bt.set_width(50);
@ -114,7 +117,9 @@ fn main() -> Result<(), String> {
}
}
::std::thread::sleep(Duration::from_millis(lvgl_sys::LV_DISP_DEF_REFR_PERIOD as u64));
::std::thread::sleep(Duration::from_millis(
lvgl_sys::LV_DISP_DEF_REFR_PERIOD as u64,
));
unsafe {
lvgl_sys::lv_task_handler();
@ -124,6 +129,7 @@ fn main() -> Result<(), String> {
Ok(())
}
// Reference to native font for LittlevGL, defined in the file: "fonts_noto_sans_numeric_80.c"
extern "C" {
pub static mut noto_sans_numeric_80: lvgl_sys::lv_font_t;
}
@ -146,7 +152,8 @@ where
fn new(mut callback: F) -> Self {
// Create a display buffer for LittlevGL
let mut display_buffer = MaybeUninit::<lvgl_sys::lv_disp_buf_t>::uninit();
let mut refresh_buffer: [MaybeUninit<lvgl_sys::lv_color_t>; lvgl_sys::LV_HOR_RES_MAX as usize * 10] =
let mut refresh_buffer: [MaybeUninit<lvgl_sys::lv_color_t>;
lvgl_sys::LV_HOR_RES_MAX as usize * 10] =
unsafe { MaybeUninit::uninit().assume_init() }; /*Declare a buffer for 10 lines*/
unsafe {
// Initialize the display buffer
@ -188,17 +195,23 @@ unsafe extern "C" fn display_callback_wrapper<F>(
) where
F: FnMut(Vec<Point>, Vec<Color>),
{
// we need to make sure panics can't escape across the FFI boundary.
// We need to make sure panics can't escape across the FFI boundary.
let _ = panic::catch_unwind(|| {
let mut i = 0;
let disp = *disp_drv;
// Rust code closure reference
let closure = &mut *(disp.user_data as *mut F);
let mut points = vec![];
let mut colors = vec![];
for y in (*area).y1..=(*area).y2 {
for x in (*area).x1..=(*area).x2 {
// Convert point to paint to a high-level Rust repr
points.push(Point::new(x as i32, y as i32));
// Convert C color representation to high-level Rust
let raw_color = *color_p.add(i);
let color = Color::from((
raw_color.ch.red,
@ -207,10 +220,15 @@ unsafe extern "C" fn display_callback_wrapper<F>(
raw_color.ch.alpha,
));
colors.push(color);
i = i + 1;
}
}
// Callback the Rust closure to flush the new points to the screen
closure(points, colors);
lvgl_sys::lv_disp_flush_ready(disp_drv); // Indicate you are ready with the flushing
// Indicate to LittlevGL that you are ready with the flushing
lvgl_sys::lv_disp_flush_ready(disp_drv);
});
}

View file

@ -8,6 +8,7 @@ fn main() {
let project_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
.canonicalize()
.unwrap();
let include_dir = project_dir.join("include");
let vendor = project_dir.join("vendor");
let vendor_src = vendor.join("lvgl").join("src");
@ -52,7 +53,9 @@ fn main() {
add_c_files(&mut cfg, vendor_src.join("lv_misc"));
add_c_files(&mut cfg, vendor_src.join("lv_objx"));
add_c_files(&mut cfg, vendor_src.join("lv_themes"));
add_c_files(&mut cfg, vendor_src.join("lv_themes"));
add_c_files(&mut cfg, &lv_config_dir);
add_c_files(&mut cfg, &include_dir);
cfg.define("LV_CONF_INCLUDE_SIMPLE", Some("1"))
.include(&vendor_src)
@ -69,14 +72,7 @@ fn main() {
vendor.to_str().unwrap(),
];
bindgen::Builder::default()
.header(
vendor_src
.parent()
.unwrap()
.join("lvgl.h")
.to_str()
.unwrap(),
)
.header(include_dir.join("lvgl_sys.h").to_str().unwrap())
.layout_tests(false)
.use_core()
.ctypes_prefix("cty")

View file

@ -0,0 +1,6 @@
#include "lvgl_sys.h"
lv_color_t lvsys_color_make(uint8_t r, uint8_t g, uint8_t b)
{
return LV_COLOR_MAKE(r, g, b);
}

View file

@ -0,0 +1,16 @@
#ifndef LVGL_API_H
#define LVGL_API_H
#ifdef __cplusplus
extern "C" {
#endif
#include "lvgl/lvgl.h"
lv_color_t lvsys_color_make(uint8_t r, uint8_t g, uint8_t b);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LVGL_API*/

View file

@ -178,7 +178,7 @@ pub const LV_COLOR_16_SWAP: u32 = 0;
pub const LV_COLOR_SCREEN_TRANSP: u32 = 0;
pub const LV_INDEXED_CHROMA: u32 = 1;
pub const LV_ANTIALIAS: u32 = 1;
pub const LV_DISP_DEF_REFR_PERIOD: u32 = 100;
pub const LV_DISP_DEF_REFR_PERIOD: u32 = 30;
pub const LV_DPI: u32 = 100;
pub const LV_MEM_CUSTOM: u32 = 0;
pub const LV_MEM_SIZE: u32 = 131072;
@ -11788,6 +11788,9 @@ extern "C" {
#[doc = " @param src an image source path to a file or pointer to an `lv_img_dsc_t` variable."]
pub fn lv_img_cache_invalidate_src(src: *const cty::c_void);
}
extern "C" {
pub fn lvsys_color_make(r: u8, g: u8, b: u8) -> lv_color_t;
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct __locale_data {

View file

@ -1,7 +1,7 @@
use core::mem;
use core::ptr;
use cty;
use lvgl_sys;
use core::mem;
pub trait NativeObject {
fn raw(&self) -> ptr::NonNull<lvgl_sys::lv_obj_t>;
@ -9,7 +9,7 @@ pub trait NativeObject {
pub struct ObjectX<'a> {
raw: ptr::NonNull<lvgl_sys::lv_obj_t>,
style: Option<&'a mut Style<'a>>,
style: Option<&'a mut Style>,
}
impl<'a> ObjectX<'a> {
@ -57,13 +57,10 @@ pub trait Object<'a>: NativeObject {
}
}
fn set_align<C>(
&mut self,
base: &mut C,
align: Align,
x_mod: i32,
y_mod: i32,
) where C: NativeObject {
fn set_align<C>(&mut self, base: &mut C, align: Align, x_mod: i32, y_mod: i32)
where
C: NativeObject,
{
let align = match align {
Align::Center => lvgl_sys::LV_ALIGN_CENTER,
Align::InTopLeft => lvgl_sys::LV_ALIGN_IN_TOP_LEFT,
@ -98,7 +95,16 @@ pub trait Object<'a>: NativeObject {
}
}
fn set_style(&mut self, style: &'a mut Style<'a>);
fn set_style(&mut self, style: &'a mut Style);
}
impl<'a> Object<'a> for ObjectX<'a> {
fn set_style(&mut self, style: &'a mut Style) {
unsafe {
lvgl_sys::lv_obj_set_style(self.raw().as_mut(), style.raw());
};
self.style = Some(style);
}
}
macro_rules! define_object {
@ -114,20 +120,23 @@ macro_rules! define_object {
}
impl<'a> Object<'a> for $item<'a> {
fn set_style(&mut self, style: &'a mut Style<'a>) {
fn set_style(&mut self, style: &'a mut Style) {
unsafe {
lvgl_sys::lv_obj_set_style(self.raw().as_mut(), style.raw());
};
self.core.style = Some(style);
}
}
}
};
}
define_object!(Button);
impl<'a> Button<'a> {
pub fn new<C>(parent: &mut C) -> Self where C: NativeObject {
pub fn new<C>(parent: &mut C) -> Self
where
C: NativeObject,
{
let raw = unsafe {
let ptr = lvgl_sys::lv_btn_create(parent.raw().as_mut(), ptr::null_mut());
ptr::NonNull::new_unchecked(ptr)
@ -147,7 +156,10 @@ pub enum LabelAlign {
define_object!(Label);
impl<'a> Label<'a> {
pub fn new<C>(parent: &mut C) -> Self where C: NativeObject {
pub fn new<C>(parent: &mut C) -> Self
where
C: NativeObject,
{
let raw = unsafe {
let ptr = lvgl_sys::lv_label_create(parent.raw().as_mut(), ptr::null_mut());
ptr::NonNull::new_unchecked(ptr)
@ -188,64 +200,69 @@ pub enum Themes {
Pretty,
}
#[derive(Default)]
pub struct Style<'a> {
raw: Option<lvgl_sys::lv_style_t>,
pub text: TextStyle<'a>,
pub struct Style {
raw: lvgl_sys::lv_style_t,
}
impl<'a> Style<'a> {
impl Style {
pub fn new() -> Self {
let raw = unsafe {
let mut native_style = mem::MaybeUninit::<lvgl_sys::lv_style_t>::uninit();
lvgl_sys::lv_style_copy(native_style.as_mut_ptr(), &lvgl_sys::lv_style_pretty);
native_style.assume_init()
};
Self { raw }
}
/// Object's main background color.
pub fn set_body_main_color(&mut self, color: Color) {
self.raw.body.main_color = color.raw;
}
/// Second color. If not equal to `set_body_main_color` a gradient will be drawn for the background.
pub fn set_body_grad_color(&mut self, color: Color) {
self.raw.body.grad_color = color.raw;
}
/// Text color.
pub fn set_text_color(&mut self, color: Color) {
self.raw.text.color = color.raw;
}
/// Font used for displaying the text.
pub fn set_text_font(&mut self, font: &lvgl_sys::lv_font_t) {
self.raw.text.font = font;
}
fn raw(&mut self) -> *const lvgl_sys::lv_style_t {
match self.raw {
Some(mut native_pointer) => {
&mut native_pointer
},
None => unsafe {
let mut native_style = mem::MaybeUninit::<lvgl_sys::lv_style_t>::uninit();
lvgl_sys::lv_style_copy(native_style.as_mut_ptr(), &lvgl_sys::lv_style_pretty);
self.raw = Some(native_style.assume_init());
if let Some(text_font) = self.text.font {
self.raw.as_mut().unwrap().text.font = text_font as *const lvgl_sys::lv_font_t;
}
self.raw.as_mut().unwrap()
&mut self.raw
}
}
impl Clone for Style {
fn clone(&self) -> Self {
let mut native_style = mem::MaybeUninit::<lvgl_sys::lv_style_t>::uninit();
unsafe {
lvgl_sys::lv_style_copy(
native_style.as_mut_ptr(),
&self.raw as *const lvgl_sys::lv_style_t,
);
Self {
raw: native_style.assume_init(),
}
}
}
}
impl<'a> Clone for Style<'a> {
fn clone(&self) -> Self {
match self.raw {
Some(_) => {
let mut native_style = mem::MaybeUninit::<lvgl_sys::lv_style_t>::uninit();
unsafe {
lvgl_sys::lv_style_copy(native_style.as_mut_ptr(), self.raw.as_ref().unwrap());
Self{
raw: Some(native_style.assume_init()),
text: self.text.clone()
}
}
},
None => {
Self{
raw: None,
text: self.text.clone()
}
}
}
}
#[derive(Clone)]
pub struct Color {
raw: lvgl_sys::lv_color_t,
}
#[derive(Default)]
pub struct TextStyle<'a> {
pub font: Option<&'a lvgl_sys::lv_font_t>,
}
impl<'a> Clone for TextStyle<'a> {
fn clone(&self) -> Self {
Self {
font: self.font.clone()
}
impl Color {
pub fn from_rgb((r, g, b): (u8, u8, u8)) -> Self {
let raw = unsafe { lvgl_sys::lvsys_color_make(r, g, b) };
Self { raw }
}
}