diff --git a/examples/button_click.rs b/examples/button_click.rs index f31c171..5575ff1 100644 --- a/examples/button_click.rs +++ b/examples/button_click.rs @@ -4,7 +4,7 @@ use embedded_graphics_simulator::{ OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window, }; use lvgl::style::Style; -use lvgl::widgets::{Btn, Label}; +use lvgl::widgets::{Btn, Label, Msgbox, Spinbox}; use lvgl::{self, Align, Color, DisplayDriver, Event, LvError, Part, State, Widget, UI}; use lvgl_sys; use std::sync::{mpsc, Arc, Mutex}; diff --git a/lvgl-codegen/src/lib.rs b/lvgl-codegen/src/lib.rs index 8bab7aa..43f5ed7 100644 --- a/lvgl-codegen/src/lib.rs +++ b/lvgl-codegen/src/lib.rs @@ -1,7 +1,7 @@ -use clang::{Clang, Entity, EntityKind, Index, Type}; +use clang::{Availability, Clang, Entity, EntityKind, Index, Linkage, Type}; use inflector::cases::pascalcase::to_pascal_case; use lazy_static::lazy_static; -use proc_macro2::TokenStream; +use proc_macro2::{Ident, TokenStream}; use quote::format_ident; use quote::quote; use regex::Regex; @@ -47,14 +47,13 @@ impl Rusty for LvWidget { type Parent = (); fn code(&self, _parent: &Self::Parent) -> WrapperResult { + // We don't generate for the generic Obj + if self.name.eq("obj") { + return Err(WrapperError::Skip); + } + let widget_name = format_ident!("{}", to_pascal_case(self.name.as_str())); - let methods: Vec = self - .methods - .iter() - .take(1) - .into_iter() - .flat_map(|m| m.code(self)) - .collect(); + let methods: Vec = self.methods.iter().flat_map(|m| m.code(self)).collect(); Ok(quote! { define_object!(#widget_name); @@ -76,6 +75,14 @@ impl LvFunc { pub fn new(name: String, args: Vec, ret: Option) -> Self { Self { name, args, ret } } + + pub fn is_method(&self) -> bool { + if self.args.len() > 0 { + let first_arg = &self.args[0]; + return first_arg.typ.typ.contains("lv_obj_t"); + } + false + } } impl Rusty for LvFunc { @@ -108,6 +115,10 @@ impl Rusty for LvFunc { for arg in self.args.iter().skip(1) { arg.code(self)?; } + // We don't deal with methods that return types yet + if self.ret.is_some() { + return Err(WrapperError::Skip); + } let args_decl = self .args @@ -144,7 +155,7 @@ impl Rusty for LvFunc { let next_arg = if i == 0 { quote!(self.core.raw()?.as_mut()) } else { - let var = format_ident!("{}", arg.name.as_str()); + let var = arg.get_name_ident(); quote!(#var) }; if args.is_empty() { @@ -160,7 +171,7 @@ impl Rusty for LvFunc { // TODO: Handle methods that return types Ok(quote! { - pub fn #func_name(#args_decl) -> LvResult<()> { + pub fn #func_name(#args_decl) -> crate::LvResult<()> { unsafe { lvgl_sys::#original_func_name(#args_call); } @@ -201,6 +212,10 @@ impl LvArg { Self { name, typ } } + pub fn get_name_ident(&self) -> Ident { + format_ident!("r#{}", self.name) + } + pub fn get_type(&self) -> &LvType { &self.typ } @@ -210,7 +225,7 @@ impl Rusty for LvArg { type Parent = LvFunc; fn code(&self, _parent: &Self::Parent) -> WrapperResult { - let name = format_ident!("{}", self.name.as_str()); + let name = self.get_name_ident(); let typ = self.typ.code(self)?; Ok(quote! { #name: #typ @@ -287,6 +302,7 @@ impl CodeGen { for widget_name in &widget_names { if f.name .starts_with(format!("{}{}", LIB_PREFIX, widget_name).as_str()) + && f.is_method() { ws.entry(widget_name.clone()) .or_insert_with(|| LvWidget { @@ -335,6 +351,7 @@ impl CodeGen { .into_iter() .filter(|e| e.get_kind() == EntityKind::FunctionDecl) .filter(|e| e.get_name().is_some()) + .filter(|e| e.get_linkage().unwrap() != Linkage::Internal) .map(|e| e.into()) .filter(|e: &LvFunc| e.name.starts_with(LIB_PREFIX)) .collect::>(); diff --git a/lvgl/build.rs b/lvgl/build.rs index cb054ae..17fa0f3 100644 --- a/lvgl/build.rs +++ b/lvgl/build.rs @@ -1,15 +1,17 @@ -use std::ffi::OsStr; -use std::path::{Path, PathBuf}; +use std::env; +use std::path::Path; use std::process::Command; -use std::{env, fs, path}; fn main() { let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); let widgets_rs_path = manifest_dir.join("src/widgets/generated.rs"); + let codegen_bin = manifest_dir.join("../target/debug/lvgl-codegen"); - if !widgets_rs_path.exists() { + println!("rerun-if-changed={}", codegen_bin.to_string_lossy()); + + if env::var("LVGL_FORCE_CODEGEN").is_ok() || !widgets_rs_path.exists() { println!("Generating `src/widgets/generated.rs`"); - let status = Command::new(manifest_dir.join("../target/debug/lvgl-codegen")) + let status = Command::new(codegen_bin) .spawn() .unwrap_or_else(|_| { panic!( diff --git a/lvgl/src/display.rs b/lvgl/src/display.rs index 0a7508e..3c8b4d3 100644 --- a/lvgl/src/display.rs +++ b/lvgl/src/display.rs @@ -1,7 +1,6 @@ use crate::Color; use alloc::boxed::Box; use core::mem::MaybeUninit; -use core::ptr; use embedded_graphics::prelude::*; use embedded_graphics::{drawable, DrawTarget}; diff --git a/lvgl/src/widgets/arc.rs b/lvgl/src/widgets/arc.rs index 515fe01..e168286 100644 --- a/lvgl/src/widgets/arc.rs +++ b/lvgl/src/widgets/arc.rs @@ -1,42 +1,41 @@ use crate::widgets::Arc; -use crate::{LvResult, NativeObject}; impl Arc { - /// Set the start angle, for the given arc part. - /// 0 degrees for the right, 90 degrees for the bottom, etc. - pub fn set_start_angle(&mut self, angle: u16, part: ArcPart) -> LvResult<()> { - match part { - ArcPart::Background => unsafe { - lvgl_sys::lv_arc_set_bg_start_angle(self.core.raw()?.as_mut(), angle) - }, - ArcPart::Indicator => unsafe { - lvgl_sys::lv_arc_set_start_angle(self.core.raw()?.as_mut(), angle) - }, - } - Ok(()) - } - - /// Set the end angle, for the given arc part. - /// 0 degrees for the right, 90 degrees for the bottom, etc. - pub fn set_end_angle(&self, angle: u16, part: ArcPart) -> LvResult<()> { - match part { - ArcPart::Background => unsafe { - lvgl_sys::lv_arc_set_bg_end_angle(self.core.raw()?.as_mut(), angle) - }, - ArcPart::Indicator => unsafe { - lvgl_sys::lv_arc_set_end_angle(self.core.raw()?.as_mut(), angle) - }, - } - Ok(()) - } - - /// Rotate the arc, `angle` degrees clockwise. - pub fn set_rotation(&mut self, angle: u16) -> LvResult<()> { - unsafe { - lvgl_sys::lv_arc_set_rotation(self.core.raw()?.as_mut(), angle); - } - Ok(()) - } + // /// Set the start angle, for the given arc part. + // /// 0 degrees for the right, 90 degrees for the bottom, etc. + // pub fn set_start_angle(&mut self, angle: u16, part: ArcPart) -> LvResult<()> { + // match part { + // ArcPart::Background => unsafe { + // lvgl_sys::lv_arc_set_bg_start_angle(self.core.raw()?.as_mut(), angle) + // }, + // ArcPart::Indicator => unsafe { + // lvgl_sys::lv_arc_set_start_angle(self.core.raw()?.as_mut(), angle) + // }, + // } + // Ok(()) + // } + // + // /// Set the end angle, for the given arc part. + // /// 0 degrees for the right, 90 degrees for the bottom, etc. + // pub fn set_end_angle(&self, angle: u16, part: ArcPart) -> LvResult<()> { + // match part { + // ArcPart::Background => unsafe { + // lvgl_sys::lv_arc_set_bg_end_angle(self.core.raw()?.as_mut(), angle) + // }, + // ArcPart::Indicator => unsafe { + // lvgl_sys::lv_arc_set_end_angle(self.core.raw()?.as_mut(), angle) + // }, + // } + // Ok(()) + // } + // + // /// Rotate the arc, `angle` degrees clockwise. + // pub fn set_rotation(&mut self, angle: u16) -> LvResult<()> { + // unsafe { + // lvgl_sys::lv_arc_set_rotation(self.core.raw()?.as_mut(), angle); + // } + // Ok(()) + // } } /// The different parts, of an arc object. diff --git a/lvgl/src/widgets/gauge.rs b/lvgl/src/widgets/gauge.rs index 6805eb0..4ba1ebf 100644 --- a/lvgl/src/widgets/gauge.rs +++ b/lvgl/src/widgets/gauge.rs @@ -1,5 +1,3 @@ -use crate::{LvResult, NativeObject}; - pub enum GaugePart { Main, Major, diff --git a/lvgl/src/widgets/mod.rs b/lvgl/src/widgets/mod.rs index 9abd935..d4845eb 100644 --- a/lvgl/src/widgets/mod.rs +++ b/lvgl/src/widgets/mod.rs @@ -5,7 +5,7 @@ mod label; include!("generated.rs"); -use crate::Widget; +use crate::{NativeObject, Widget}; pub use arc::*; pub use bar::*; pub use gauge::*;