Generate all widgets

This commit is contained in:
Rafael Caricio 2020-06-12 18:20:02 +02:00 committed by Rafael Carício
parent d970deaa9d
commit de9b6512a7
7 changed files with 73 additions and 58 deletions

View file

@ -4,7 +4,7 @@ use embedded_graphics_simulator::{
OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window, OutputSettingsBuilder, SimulatorDisplay, SimulatorEvent, Window,
}; };
use lvgl::style::Style; 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::{self, Align, Color, DisplayDriver, Event, LvError, Part, State, Widget, UI};
use lvgl_sys; use lvgl_sys;
use std::sync::{mpsc, Arc, Mutex}; use std::sync::{mpsc, Arc, Mutex};

View file

@ -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 inflector::cases::pascalcase::to_pascal_case;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use proc_macro2::TokenStream; use proc_macro2::{Ident, TokenStream};
use quote::format_ident; use quote::format_ident;
use quote::quote; use quote::quote;
use regex::Regex; use regex::Regex;
@ -47,14 +47,13 @@ impl Rusty for LvWidget {
type Parent = (); type Parent = ();
fn code(&self, _parent: &Self::Parent) -> WrapperResult<TokenStream> { fn code(&self, _parent: &Self::Parent) -> WrapperResult<TokenStream> {
// 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 widget_name = format_ident!("{}", to_pascal_case(self.name.as_str()));
let methods: Vec<TokenStream> = self let methods: Vec<TokenStream> = self.methods.iter().flat_map(|m| m.code(self)).collect();
.methods
.iter()
.take(1)
.into_iter()
.flat_map(|m| m.code(self))
.collect();
Ok(quote! { Ok(quote! {
define_object!(#widget_name); define_object!(#widget_name);
@ -76,6 +75,14 @@ impl LvFunc {
pub fn new(name: String, args: Vec<LvArg>, ret: Option<LvType>) -> Self { pub fn new(name: String, args: Vec<LvArg>, ret: Option<LvType>) -> Self {
Self { name, args, ret } 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 { impl Rusty for LvFunc {
@ -108,6 +115,10 @@ impl Rusty for LvFunc {
for arg in self.args.iter().skip(1) { for arg in self.args.iter().skip(1) {
arg.code(self)?; 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 let args_decl = self
.args .args
@ -144,7 +155,7 @@ impl Rusty for LvFunc {
let next_arg = if i == 0 { let next_arg = if i == 0 {
quote!(self.core.raw()?.as_mut()) quote!(self.core.raw()?.as_mut())
} else { } else {
let var = format_ident!("{}", arg.name.as_str()); let var = arg.get_name_ident();
quote!(#var) quote!(#var)
}; };
if args.is_empty() { if args.is_empty() {
@ -160,7 +171,7 @@ impl Rusty for LvFunc {
// TODO: Handle methods that return types // TODO: Handle methods that return types
Ok(quote! { Ok(quote! {
pub fn #func_name(#args_decl) -> LvResult<()> { pub fn #func_name(#args_decl) -> crate::LvResult<()> {
unsafe { unsafe {
lvgl_sys::#original_func_name(#args_call); lvgl_sys::#original_func_name(#args_call);
} }
@ -201,6 +212,10 @@ impl LvArg {
Self { name, typ } Self { name, typ }
} }
pub fn get_name_ident(&self) -> Ident {
format_ident!("r#{}", self.name)
}
pub fn get_type(&self) -> &LvType { pub fn get_type(&self) -> &LvType {
&self.typ &self.typ
} }
@ -210,7 +225,7 @@ impl Rusty for LvArg {
type Parent = LvFunc; type Parent = LvFunc;
fn code(&self, _parent: &Self::Parent) -> WrapperResult<TokenStream> { fn code(&self, _parent: &Self::Parent) -> WrapperResult<TokenStream> {
let name = format_ident!("{}", self.name.as_str()); let name = self.get_name_ident();
let typ = self.typ.code(self)?; let typ = self.typ.code(self)?;
Ok(quote! { Ok(quote! {
#name: #typ #name: #typ
@ -287,6 +302,7 @@ impl CodeGen {
for widget_name in &widget_names { for widget_name in &widget_names {
if f.name if f.name
.starts_with(format!("{}{}", LIB_PREFIX, widget_name).as_str()) .starts_with(format!("{}{}", LIB_PREFIX, widget_name).as_str())
&& f.is_method()
{ {
ws.entry(widget_name.clone()) ws.entry(widget_name.clone())
.or_insert_with(|| LvWidget { .or_insert_with(|| LvWidget {
@ -335,6 +351,7 @@ impl CodeGen {
.into_iter() .into_iter()
.filter(|e| e.get_kind() == EntityKind::FunctionDecl) .filter(|e| e.get_kind() == EntityKind::FunctionDecl)
.filter(|e| e.get_name().is_some()) .filter(|e| e.get_name().is_some())
.filter(|e| e.get_linkage().unwrap() != Linkage::Internal)
.map(|e| e.into()) .map(|e| e.into())
.filter(|e: &LvFunc| e.name.starts_with(LIB_PREFIX)) .filter(|e: &LvFunc| e.name.starts_with(LIB_PREFIX))
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View file

@ -1,15 +1,17 @@
use std::ffi::OsStr; use std::env;
use std::path::{Path, PathBuf}; use std::path::Path;
use std::process::Command; use std::process::Command;
use std::{env, fs, path};
fn main() { fn main() {
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
let widgets_rs_path = manifest_dir.join("src/widgets/generated.rs"); 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`"); println!("Generating `src/widgets/generated.rs`");
let status = Command::new(manifest_dir.join("../target/debug/lvgl-codegen")) let status = Command::new(codegen_bin)
.spawn() .spawn()
.unwrap_or_else(|_| { .unwrap_or_else(|_| {
panic!( panic!(

View file

@ -1,7 +1,6 @@
use crate::Color; use crate::Color;
use alloc::boxed::Box; use alloc::boxed::Box;
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
use core::ptr;
use embedded_graphics::prelude::*; use embedded_graphics::prelude::*;
use embedded_graphics::{drawable, DrawTarget}; use embedded_graphics::{drawable, DrawTarget};

View file

@ -1,42 +1,41 @@
use crate::widgets::Arc; use crate::widgets::Arc;
use crate::{LvResult, NativeObject};
impl Arc { impl Arc {
/// Set the start angle, for the given arc part. // /// Set the start angle, for the given arc part.
/// 0 degrees for the right, 90 degrees for the bottom, etc. // /// 0 degrees for the right, 90 degrees for the bottom, etc.
pub fn set_start_angle(&mut self, angle: u16, part: ArcPart) -> LvResult<()> { // pub fn set_start_angle(&mut self, angle: u16, part: ArcPart) -> LvResult<()> {
match part { // match part {
ArcPart::Background => unsafe { // ArcPart::Background => unsafe {
lvgl_sys::lv_arc_set_bg_start_angle(self.core.raw()?.as_mut(), angle) // lvgl_sys::lv_arc_set_bg_start_angle(self.core.raw()?.as_mut(), angle)
}, // },
ArcPart::Indicator => unsafe { // ArcPart::Indicator => unsafe {
lvgl_sys::lv_arc_set_start_angle(self.core.raw()?.as_mut(), angle) // lvgl_sys::lv_arc_set_start_angle(self.core.raw()?.as_mut(), angle)
}, // },
} // }
Ok(()) // Ok(())
} // }
//
/// Set the end angle, for the given arc part. // /// Set the end angle, for the given arc part.
/// 0 degrees for the right, 90 degrees for the bottom, etc. // /// 0 degrees for the right, 90 degrees for the bottom, etc.
pub fn set_end_angle(&self, angle: u16, part: ArcPart) -> LvResult<()> { // pub fn set_end_angle(&self, angle: u16, part: ArcPart) -> LvResult<()> {
match part { // match part {
ArcPart::Background => unsafe { // ArcPart::Background => unsafe {
lvgl_sys::lv_arc_set_bg_end_angle(self.core.raw()?.as_mut(), angle) // lvgl_sys::lv_arc_set_bg_end_angle(self.core.raw()?.as_mut(), angle)
}, // },
ArcPart::Indicator => unsafe { // ArcPart::Indicator => unsafe {
lvgl_sys::lv_arc_set_end_angle(self.core.raw()?.as_mut(), angle) // lvgl_sys::lv_arc_set_end_angle(self.core.raw()?.as_mut(), angle)
}, // },
} // }
Ok(()) // Ok(())
} // }
//
/// Rotate the arc, `angle` degrees clockwise. // /// Rotate the arc, `angle` degrees clockwise.
pub fn set_rotation(&mut self, angle: u16) -> LvResult<()> { // pub fn set_rotation(&mut self, angle: u16) -> LvResult<()> {
unsafe { // unsafe {
lvgl_sys::lv_arc_set_rotation(self.core.raw()?.as_mut(), angle); // lvgl_sys::lv_arc_set_rotation(self.core.raw()?.as_mut(), angle);
} // }
Ok(()) // Ok(())
} // }
} }
/// The different parts, of an arc object. /// The different parts, of an arc object.

View file

@ -1,5 +1,3 @@
use crate::{LvResult, NativeObject};
pub enum GaugePart { pub enum GaugePart {
Main, Main,
Major, Major,

View file

@ -5,7 +5,7 @@ mod label;
include!("generated.rs"); include!("generated.rs");
use crate::Widget; use crate::{NativeObject, Widget};
pub use arc::*; pub use arc::*;
pub use bar::*; pub use bar::*;
pub use gauge::*; pub use gauge::*;