use alloc::boxed::Box;
use core::{marker::PhantomData, pin::Pin, ptr::null_mut};
use oxivgl_sys::*;
use super::Style;
use crate::widgets::WidgetError;
unsafe extern "C" {
static lv_button_class: lv_obj_class_t;
}
unsafe extern "C" fn apply_cb_trampoline(th: *mut lv_theme_t, obj: *mut lv_obj_t) {
unsafe {
if lv_obj_check_type(obj, &lv_button_class) {
let style_ptr = (*th).user_data as *const lv_style_t;
lv_obj_add_style(obj, style_ptr, 0);
}
}
}
pub struct Theme {
inner: Pin<Box<lv_theme_t>>,
_style: Style,
_not_send: PhantomData<*mut ()>,
}
impl core::fmt::Debug for Theme {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Theme").finish_non_exhaustive()
}
}
impl Theme {
pub fn extend_current(style: Style) -> Result<Self, WidgetError> {
let th_act = unsafe { lv_display_get_theme(null_mut()) };
if th_act.is_null() {
return Err(WidgetError::LvglNullPointer);
}
let th_new: lv_theme_t = unsafe { *th_act };
let mut inner = Box::into_pin(Box::new(th_new));
unsafe {
let p = inner.as_mut().get_unchecked_mut();
p.user_data = style.lv_ptr() as *mut core::ffi::c_void;
lv_theme_set_parent(p, th_act);
lv_theme_set_apply_cb(p, Some(apply_cb_trampoline));
lv_display_set_theme(null_mut(), p);
}
Ok(Theme { inner, _style: style, _not_send: PhantomData })
}
}
impl Drop for Theme {
fn drop(&mut self) {
unsafe {
let p = self.inner.as_mut().get_unchecked_mut();
lv_display_set_theme(null_mut(), p.parent);
}
}
}