use super::ControlBase;
use crate::{
graphics::{ClipArea, Point},
prelude::RuntimeManager,
system::{Handle, HandleSupport},
backend::Backend,
ui::common::traits::Control,
};
use std::ptr::NonNull;
pub(crate) struct ParentLayout {
pub(super) clip: ClipArea,
pub(super) origin: Point,
pub(super) client_width: u16,
pub(super) client_height: u16,
}
impl From<&ControlBase> for ParentLayout {
fn from(base: &ControlBase) -> Self {
let client_sz = base.client_size();
let mut pl = ParentLayout {
clip: base.client_clip(),
origin: base.screen_origin,
client_width: client_sz.width as u16,
client_height: client_sz.height as u16,
};
pl.origin.x += base.margins.left as i32;
pl.origin.y += base.margins.top as i32;
pl
}
}
impl From<&Box<dyn Backend>> for ParentLayout {
fn from(backend: &Box<dyn Backend>) -> Self {
let sz = backend.size();
ParentLayout {
clip: ClipArea::new(0, 0, (sz.width as i32) - 1, (sz.height as i32) - 1),
origin: Point::default(),
client_width: sz.width as u16,
client_height: sz.height as u16,
}
}
}
pub(crate) struct ControlManager {
interface: NonNull<dyn Control>,
base: *mut ControlBase,
}
impl ControlManager {
#[inline]
pub(crate) fn control(&self) -> &dyn Control {
unsafe { &*(self.interface.as_ptr()) }
}
#[inline]
pub(crate) fn control_mut(&mut self) -> &mut dyn Control {
unsafe { &mut *(self.interface.as_ptr()) }
}
#[inline(always)]
pub(crate) fn base(&self) -> &ControlBase {
unsafe { &*self.base }
}
#[inline(always)]
pub(crate) fn base_mut(&mut self) -> &mut ControlBase {
unsafe { &mut *self.base }
}
pub(crate) fn new<T>(obj: T) -> ControlManager
where
T: Control + 'static,
{
let ptr = Box::into_raw(Box::new(obj));
let ctrl: NonNull<dyn Control> = unsafe { NonNull::new_unchecked(ptr) };
ControlManager {
interface: ctrl,
base: ptr as *mut ControlBase,
}
}
pub(crate) fn get_mut<T>(&mut self) -> &mut T
where
T: Control + 'static,
{
unsafe { &mut *(self.base as *mut T) }
}
pub(crate) fn get<T>(&self) -> &T
where
T: Control + 'static,
{
unsafe { &*(self.base as *const T) }
}
}
impl Drop for ControlManager {
fn drop(&mut self) {
unsafe {
let _ = Box::from_raw(self.interface.as_ptr());
};
}
}
impl HandleSupport<ControlManager> for ControlManager {
fn handle(&self) -> Handle<ControlManager> {
self.base().handle.cast()
}
fn set_handle(&mut self, handle: Handle<ControlManager>) {
if !self.base().is_desktop_control() {
let controls = RuntimeManager::get().get_controls_mut();
for child in self.base().children.iter() {
if let Some(control) = controls.get_mut(*child) {
control.base_mut().parent = handle.cast();
}
}
}
self.base_mut().handle = handle.cast();
}
}