2020-06-04 17:47:57 +00:00
|
|
|
use crate::lv_core::style::Style;
|
2021-05-25 23:03:07 +00:00
|
|
|
use crate::Box;
|
2020-06-07 18:29:35 +00:00
|
|
|
use crate::{Align, LvError, LvResult};
|
2020-06-04 17:47:57 +00:00
|
|
|
use core::ptr;
|
|
|
|
|
2021-05-25 23:03:07 +00:00
|
|
|
/// Represents a native LVGL object
|
2020-06-04 17:47:57 +00:00
|
|
|
pub trait NativeObject {
|
|
|
|
/// Provide common way to access to the underlying native object pointer.
|
2020-06-07 18:29:35 +00:00
|
|
|
fn raw(&self) -> LvResult<ptr::NonNull<lvgl_sys::lv_obj_t>>;
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Generic LVGL object.
|
|
|
|
///
|
|
|
|
/// This is the parent object of all widget types. It stores the native LVGL raw pointer.
|
2020-06-05 21:22:21 +00:00
|
|
|
pub struct Obj {
|
2020-06-04 17:47:57 +00:00
|
|
|
// We use a raw pointer here because we do not control this memory address, it is controlled
|
|
|
|
// by LVGL's global state.
|
|
|
|
raw: *mut lvgl_sys::lv_obj_t,
|
|
|
|
}
|
|
|
|
|
2020-06-05 21:22:21 +00:00
|
|
|
impl NativeObject for Obj {
|
2020-06-07 18:29:35 +00:00
|
|
|
fn raw(&self) -> LvResult<ptr::NonNull<lvgl_sys::lv_obj_t>> {
|
|
|
|
if let Some(non_null_ptr) = ptr::NonNull::new(self.raw) {
|
|
|
|
Ok(non_null_ptr)
|
|
|
|
} else {
|
|
|
|
Err(LvError::InvalidReference)
|
|
|
|
}
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-25 23:03:07 +00:00
|
|
|
/// A wrapper for all LVGL common operations on generic objects.
|
2020-06-05 21:22:21 +00:00
|
|
|
pub trait Widget: NativeObject {
|
2020-06-04 17:47:57 +00:00
|
|
|
type SpecialEvent;
|
|
|
|
type Part: Into<u8>;
|
|
|
|
|
|
|
|
/// Construct an instance of the object from a raw pointer.
|
|
|
|
///
|
|
|
|
/// # Safety
|
|
|
|
/// Provided the LVGL library can allocate memory this should be safe.
|
|
|
|
///
|
|
|
|
unsafe fn from_raw(raw_pointer: ptr::NonNull<lvgl_sys::lv_obj_t>) -> Self;
|
|
|
|
|
2020-06-16 21:19:26 +00:00
|
|
|
fn add_style(&self, part: Self::Part, style: Style) -> LvResult<()> {
|
2020-06-04 17:47:57 +00:00
|
|
|
unsafe {
|
2020-06-07 18:29:35 +00:00
|
|
|
lvgl_sys::lv_obj_add_style(self.raw()?.as_mut(), part.into(), Box::into_raw(style.raw));
|
2020-06-04 17:47:57 +00:00
|
|
|
};
|
2020-06-07 18:29:35 +00:00
|
|
|
Ok(())
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
|
|
|
|
2020-06-07 18:29:35 +00:00
|
|
|
fn set_pos(&mut self, x: i16, y: i16) -> LvResult<()> {
|
2020-06-04 17:47:57 +00:00
|
|
|
unsafe {
|
|
|
|
lvgl_sys::lv_obj_set_pos(
|
2020-06-07 18:29:35 +00:00
|
|
|
self.raw()?.as_mut(),
|
2020-06-04 17:47:57 +00:00
|
|
|
x as lvgl_sys::lv_coord_t,
|
|
|
|
y as lvgl_sys::lv_coord_t,
|
|
|
|
);
|
|
|
|
}
|
2020-06-07 18:29:35 +00:00
|
|
|
Ok(())
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
|
|
|
|
2020-06-07 18:29:35 +00:00
|
|
|
fn set_size(&mut self, w: i16, h: i16) -> LvResult<()> {
|
2020-06-04 17:47:57 +00:00
|
|
|
unsafe {
|
|
|
|
lvgl_sys::lv_obj_set_size(
|
2020-06-07 18:29:35 +00:00
|
|
|
self.raw()?.as_mut(),
|
2020-06-04 17:47:57 +00:00
|
|
|
w as lvgl_sys::lv_coord_t,
|
|
|
|
h as lvgl_sys::lv_coord_t,
|
|
|
|
);
|
|
|
|
}
|
2020-06-07 18:29:35 +00:00
|
|
|
Ok(())
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
|
|
|
|
2020-06-07 18:29:35 +00:00
|
|
|
fn set_width(&mut self, w: u32) -> LvResult<()> {
|
2020-06-04 17:47:57 +00:00
|
|
|
unsafe {
|
2020-06-07 18:29:35 +00:00
|
|
|
lvgl_sys::lv_obj_set_width(self.raw()?.as_mut(), w as lvgl_sys::lv_coord_t);
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
2020-06-07 18:29:35 +00:00
|
|
|
Ok(())
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
|
|
|
|
2020-06-07 18:29:35 +00:00
|
|
|
fn set_height(&mut self, h: u32) -> LvResult<()> {
|
2020-06-04 17:47:57 +00:00
|
|
|
unsafe {
|
2020-06-07 18:29:35 +00:00
|
|
|
lvgl_sys::lv_obj_set_height(self.raw()?.as_mut(), h as lvgl_sys::lv_coord_t);
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
2020-06-07 18:29:35 +00:00
|
|
|
Ok(())
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
|
|
|
|
2020-06-07 18:29:35 +00:00
|
|
|
fn set_align<C>(&mut self, base: &mut C, align: Align, x_mod: i32, y_mod: i32) -> LvResult<()>
|
2020-06-04 17:47:57 +00:00
|
|
|
where
|
|
|
|
C: NativeObject,
|
|
|
|
{
|
|
|
|
unsafe {
|
|
|
|
lvgl_sys::lv_obj_align(
|
2020-06-07 18:29:35 +00:00
|
|
|
self.raw()?.as_mut(),
|
|
|
|
base.raw()?.as_mut(),
|
2020-06-04 17:47:57 +00:00
|
|
|
align.into(),
|
|
|
|
x_mod as lvgl_sys::lv_coord_t,
|
|
|
|
y_mod as lvgl_sys::lv_coord_t,
|
|
|
|
);
|
|
|
|
}
|
2020-06-07 18:29:35 +00:00
|
|
|
Ok(())
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-05 21:22:21 +00:00
|
|
|
impl Widget for Obj {
|
2020-06-04 17:47:57 +00:00
|
|
|
type SpecialEvent = ();
|
2020-06-04 21:09:54 +00:00
|
|
|
type Part = Part;
|
2020-06-04 17:47:57 +00:00
|
|
|
|
|
|
|
unsafe fn from_raw(raw: ptr::NonNull<lvgl_sys::lv_obj_t>) -> Self {
|
|
|
|
Self { raw: raw.as_ptr() }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-05 21:22:21 +00:00
|
|
|
impl Default for Obj {
|
2020-06-04 17:47:57 +00:00
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
raw: unsafe { lvgl_sys::lv_obj_create(ptr::null_mut(), ptr::null_mut()) },
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! define_object {
|
2020-06-12 10:41:20 +00:00
|
|
|
($item:ident) => {
|
|
|
|
define_object!($item, event = (), part = $crate::Part);
|
2020-06-04 17:47:57 +00:00
|
|
|
};
|
2020-06-12 10:41:20 +00:00
|
|
|
($item:ident, event = $event_type:ty) => {
|
|
|
|
define_object!($item, event = $event_type, part = $crate::Part);
|
2020-06-04 17:47:57 +00:00
|
|
|
};
|
2020-06-12 10:41:20 +00:00
|
|
|
($item:ident, part = $part_type:ty) => {
|
|
|
|
define_object!($item, event = (), part = $part_type);
|
2020-06-04 17:47:57 +00:00
|
|
|
};
|
2020-06-12 10:41:20 +00:00
|
|
|
($item:ident, part = $part_type:ty, event = $event_type:ty) => {
|
|
|
|
define_object!($item, event = $event_type, part = $part_type);
|
2020-06-04 17:47:57 +00:00
|
|
|
};
|
2020-06-12 10:41:20 +00:00
|
|
|
($item:ident, event = $event_type:ty, part = $part_type:ty) => {
|
2020-06-04 17:47:57 +00:00
|
|
|
pub struct $item {
|
2020-06-05 21:22:21 +00:00
|
|
|
core: $crate::Obj,
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
|
|
|
|
2020-06-12 10:41:20 +00:00
|
|
|
unsafe impl Send for $item {}
|
2020-06-05 20:36:15 +00:00
|
|
|
|
2020-06-12 10:41:20 +00:00
|
|
|
impl $item {
|
2020-06-07 18:29:35 +00:00
|
|
|
pub fn on_event<F>(&mut self, f: F) -> $crate::LvResult<()>
|
2020-06-04 17:47:57 +00:00
|
|
|
where
|
2020-06-05 21:22:21 +00:00
|
|
|
F: FnMut(Self, $crate::support::Event<<Self as $crate::Widget>::SpecialEvent>),
|
2020-06-04 17:47:57 +00:00
|
|
|
{
|
2020-06-05 21:22:21 +00:00
|
|
|
use $crate::NativeObject;
|
2020-06-04 17:47:57 +00:00
|
|
|
unsafe {
|
2020-06-07 18:29:35 +00:00
|
|
|
let mut raw = self.raw()?;
|
2020-06-04 17:47:57 +00:00
|
|
|
let obj = raw.as_mut();
|
2021-05-25 23:03:07 +00:00
|
|
|
let user_closure = $crate::Box::new(f);
|
|
|
|
obj.user_data = $crate::Box::into_raw(user_closure) as *mut cty::c_void;
|
2020-06-04 17:47:57 +00:00
|
|
|
lvgl_sys::lv_obj_set_event_cb(
|
|
|
|
obj,
|
|
|
|
lvgl_sys::lv_event_cb_t::Some($crate::support::event_callback::<Self, F>),
|
|
|
|
);
|
|
|
|
}
|
2020-06-07 18:29:35 +00:00
|
|
|
Ok(())
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl $crate::NativeObject for $item {
|
2020-06-07 18:29:35 +00:00
|
|
|
fn raw(&self) -> $crate::LvResult<core::ptr::NonNull<lvgl_sys::lv_obj_t>> {
|
2020-06-04 17:47:57 +00:00
|
|
|
self.core.raw()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-05 21:22:21 +00:00
|
|
|
impl $crate::Widget for $item {
|
2020-06-04 17:47:57 +00:00
|
|
|
type SpecialEvent = $event_type;
|
|
|
|
type Part = $part_type;
|
|
|
|
|
|
|
|
unsafe fn from_raw(raw_pointer: core::ptr::NonNull<lvgl_sys::lv_obj_t>) -> Self {
|
|
|
|
Self {
|
2020-06-05 21:22:21 +00:00
|
|
|
core: $crate::Obj::from_raw(raw_pointer),
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-06-04 18:14:43 +00:00
|
|
|
bitflags! {
|
|
|
|
pub struct State: u32 {
|
|
|
|
/// Normal, released
|
2022-05-17 01:32:56 +00:00
|
|
|
const DEFAULT = lvgl_sys::LV_STATE_DEFAULT as u32;
|
2020-06-04 18:14:43 +00:00
|
|
|
/// Toggled or checked
|
2022-05-17 01:32:56 +00:00
|
|
|
const CHECKED = lvgl_sys::LV_STATE_CHECKED as u32;
|
2020-06-04 18:14:43 +00:00
|
|
|
/// Focused via keypad or encoder or clicked via touchpad/mouse
|
2022-05-17 01:32:56 +00:00
|
|
|
const FOCUSED = lvgl_sys::LV_STATE_FOCUSED as u32;
|
2020-06-04 18:14:43 +00:00
|
|
|
/// Edit by an encoder
|
2022-05-17 01:32:56 +00:00
|
|
|
const EDITED = lvgl_sys::LV_STATE_EDITED as u32;
|
2020-06-04 18:14:43 +00:00
|
|
|
/// Hovered by mouse (not supported now)
|
2022-05-17 01:32:56 +00:00
|
|
|
const HOVERED = lvgl_sys::LV_STATE_HOVERED as u32;
|
2020-06-04 18:14:43 +00:00
|
|
|
/// Pressed
|
2022-05-17 01:32:56 +00:00
|
|
|
const PRESSED = lvgl_sys::LV_STATE_PRESSED as u32;
|
2020-06-04 18:14:43 +00:00
|
|
|
/// Disabled or inactive
|
2022-05-17 01:32:56 +00:00
|
|
|
const DISABLED = lvgl_sys::LV_STATE_DISABLED as u32;
|
2020-06-04 18:14:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl State {
|
|
|
|
pub(crate) fn get_bits(&self) -> u32 {
|
|
|
|
self.bits
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-04 21:09:54 +00:00
|
|
|
pub enum Part {
|
2020-06-04 17:47:57 +00:00
|
|
|
Main,
|
|
|
|
All,
|
|
|
|
}
|
|
|
|
|
2020-06-04 21:09:54 +00:00
|
|
|
impl Into<u8> for Part {
|
2020-06-04 17:47:57 +00:00
|
|
|
fn into(self) -> u8 {
|
|
|
|
match self {
|
2020-06-04 21:09:54 +00:00
|
|
|
Part::Main => lvgl_sys::LV_OBJ_PART_MAIN as u8,
|
|
|
|
Part::All => lvgl_sys::LV_OBJ_PART_ALL as u8,
|
2020-06-04 17:47:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|