Improvements in the bindings
This commit is contained in:
parent
3aed1c3075
commit
bd91097ecd
8 changed files with 152 additions and 90 deletions
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"lvgl",
|
||||
"lvgl-sys",
|
||||
"examples/demo",
|
||||
]
|
|
@ -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
|
||||
|
|
|
@ -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 { ¬o_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(¬o_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);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
6
lvgl-sys/include/lvgl_sys.c
Normal file
6
lvgl-sys/include/lvgl_sys.c
Normal 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);
|
||||
}
|
16
lvgl-sys/include/lvgl_sys.h
Normal file
16
lvgl-sys/include/lvgl_sys.h
Normal 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*/
|
|
@ -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 {
|
||||
|
|
141
lvgl/src/objx.rs
141
lvgl/src/objx.rs
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue