use std::any::Any;
use std::ops::DerefMut;
use super::{StackDst, Theme, Window};
use kas::draw::{Colour, DrawHandle, DrawShared, SizeHandle};
use kas::geom::Rect;
use kas::ThemeApi;
pub trait ThemeDst<D: DrawShared>: ThemeApi {
fn init(&mut self, draw: &mut D);
fn new_window(&self, draw: &mut D::Draw, dpi_factor: f32) -> StackDst<dyn WindowDst<D::Draw>>;
fn update_window(&self, window: &mut dyn WindowDst<D::Draw>, dpi_factor: f32);
#[cfg(not(feature = "gat"))]
unsafe fn draw_handle(
&self,
draw: &mut D::Draw,
window: &mut dyn WindowDst<D::Draw>,
rect: Rect,
) -> StackDst<dyn DrawHandle>;
#[cfg(feature = "gat")]
fn draw_handle<'a>(
&'a self,
draw: &'a mut D::Draw,
window: &'a mut dyn WindowDst<D::Draw>,
rect: Rect,
) -> StackDst<dyn DrawHandle + 'a>;
fn clear_colour(&self) -> Colour;
}
#[cfg(not(feature = "gat"))]
impl<'a, D: DrawShared, T: Theme<D>> ThemeDst<D> for T
where
<T as Theme<D>>::DrawHandle: 'static,
<<T as Theme<D>>::Window as Window<D::Draw>>::SizeHandle: 'static,
{
fn init(&mut self, draw: &mut D) {
self.init(draw);
}
fn new_window(&self, draw: &mut D::Draw, dpi_factor: f32) -> StackDst<dyn WindowDst<D::Draw>> {
let window = <T as Theme<D>>::new_window(self, draw, dpi_factor);
#[cfg(feature = "unsize")]
{
StackDst::new_or_boxed(window)
}
#[cfg(not(feature = "unsize"))]
{
match StackDst::new_stable(window, |w| w as &dyn WindowDst<D::Draw>) {
Ok(s) => s,
Err(window) => {
StackDst::new_stable(Box::new(window), |w| w as &dyn WindowDst<D::Draw>)
.ok()
.expect("boxed window too big for StackDst!")
}
}
}
}
fn update_window(&self, window: &mut dyn WindowDst<D::Draw>, dpi_factor: f32) {
let window = window.as_any_mut().downcast_mut().unwrap();
self.update_window(window, dpi_factor);
}
unsafe fn draw_handle(
&self,
draw: &mut D::Draw,
window: &mut dyn WindowDst<D::Draw>,
rect: Rect,
) -> StackDst<dyn DrawHandle> {
let window = window.as_any_mut().downcast_mut().unwrap();
let h = <T as Theme<D>>::draw_handle(self, draw, window, rect);
#[cfg(feature = "unsize")]
{
StackDst::new_or_boxed(h)
}
#[cfg(not(feature = "unsize"))]
{
StackDst::new_stable(h, |h| h as &dyn DrawHandle)
.ok()
.expect("handle too big for StackDst!")
}
}
fn clear_colour(&self) -> Colour {
self.clear_colour()
}
}
#[cfg(feature = "gat")]
impl<'a, D: DrawShared + 'static, T: Theme<D>> ThemeDst<D> for T {
fn init(&mut self, draw: &mut D) {
self.init(draw);
}
fn new_window(&self, draw: &mut D::Draw, dpi_factor: f32) -> StackDst<dyn WindowDst<D::Draw>> {
let window = <T as Theme<D>>::new_window(self, draw, dpi_factor);
StackDst::new_or_boxed(window)
}
fn update_window(&self, window: &mut dyn WindowDst<D::Draw>, dpi_factor: f32) {
let window = window.as_any_mut().downcast_mut().unwrap();
self.update_window(window, dpi_factor);
}
fn draw_handle<'b>(
&'b self,
draw: &'b mut D::Draw,
window: &'b mut dyn WindowDst<D::Draw>,
rect: Rect,
) -> StackDst<dyn DrawHandle + 'b> {
let window = window.as_any_mut().downcast_mut().unwrap();
let h = <T as Theme<D>>::draw_handle(self, draw, window, rect);
StackDst::new_or_boxed(h)
}
fn clear_colour(&self) -> Colour {
self.clear_colour()
}
}
pub trait WindowDst<Draw> {
#[cfg(not(feature = "gat"))]
unsafe fn size_handle(&mut self, draw: &mut Draw) -> StackDst<dyn SizeHandle>;
#[cfg(feature = "gat")]
fn size_handle<'a>(&'a mut self, draw: &'a mut Draw) -> StackDst<dyn SizeHandle + 'a>;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
#[cfg(not(feature = "gat"))]
impl<W: Window<Draw>, Draw> WindowDst<Draw> for W
where
<W as Window<Draw>>::SizeHandle: 'static,
{
unsafe fn size_handle<'a>(&'a mut self, draw: &'a mut Draw) -> StackDst<dyn SizeHandle> {
let h = <W as Window<Draw>>::size_handle(self, draw);
#[cfg(feature = "unsize")]
{
StackDst::new_or_boxed(h)
}
#[cfg(not(feature = "unsize"))]
{
StackDst::new_stable(h, |h| h as &dyn SizeHandle)
.ok()
.expect("handle too big for StackDst!")
}
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self.as_any_mut()
}
}
#[cfg(feature = "gat")]
impl<W: Window<Draw>, Draw> WindowDst<Draw> for W {
fn size_handle<'a>(&'a mut self, draw: &'a mut Draw) -> StackDst<dyn SizeHandle + 'a> {
let h = <W as Window<Draw>>::size_handle(self, draw);
StackDst::new_or_boxed(h)
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self.as_any_mut()
}
}
impl<Draw> Window<Draw> for StackDst<dyn WindowDst<Draw>> {
#[cfg(not(feature = "gat"))]
type SizeHandle = StackDst<dyn SizeHandle>;
#[cfg(feature = "gat")]
type SizeHandle<'a> = StackDst<dyn SizeHandle + 'a>;
#[cfg(not(feature = "gat"))]
unsafe fn size_handle(&mut self, draw: &mut Draw) -> Self::SizeHandle {
self.deref_mut().size_handle(draw)
}
#[cfg(feature = "gat")]
fn size_handle<'a>(&'a mut self, draw: &'a mut Draw) -> Self::SizeHandle<'a> {
self.deref_mut().size_handle(draw)
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self.deref_mut().as_any_mut()
}
}