use crate::element_configuring::{ConfigureElements, ConfiguredParentElement};
use crate::layout::{LayoutFrameManager, LayoutManager, LayoutManagerCompatible};
use crate::pipes::LayoutRenderPipe;
use crate::renders::{CotisRenderer, CotisRendererAsync, RenderCompatibleWith};
pub struct CotisApp<
Renderer: RenderCompatibleWith<Manager>,
Manager: LayoutManagerCompatible<Renderer>,
Pipe,
> {
layout_manager: Manager,
render_engine: Renderer,
layout_render_pipe: Pipe,
}
impl<Renderer: RenderCompatibleWith<Manager>, Manager: LayoutManagerCompatible<Renderer>, Pipe>
CotisApp<Renderer, Manager, Pipe>
{
pub fn layout_manager(&mut self) -> &mut Manager {
&mut self.layout_manager
}
pub fn render(&mut self) -> &mut Renderer {
&mut self.render_engine
}
pub fn layout_manager_borrow(&self) -> &Manager {
&self.layout_manager
}
pub fn render_borrow(&self) -> &Renderer {
&self.render_engine
}
pub fn new(
mut render_engine: Renderer,
mut layout_manager: Manager,
layout_render_pipe: Pipe,
) -> Self {
render_engine.init(&mut layout_manager);
layout_manager.init(&mut render_engine);
CotisApp {
render_engine,
layout_manager,
layout_render_pipe,
}
}
}
pub trait UiFn<'inside, Configurer: ConfigureElements<ConfigType>, ConfigType>: Sized {
fn draw_in(self, layout: &mut ConfiguredParentElement<'inside, Configurer, ConfigType>);
}
impl<
'inside,
Configurer: ConfigureElements<ConfigType>,
ConfigType,
T: FnOnce(&mut ConfiguredParentElement<'inside, Configurer, ConfigType>),
> UiFn<'inside, Configurer, ConfigType> for T
{
fn draw_in(self, layout: &mut ConfiguredParentElement<'inside, Configurer, ConfigType>) {
self(layout);
}
}
pub trait AsyncRenderApp<'frame, ConfigType, ElementType, RenderCommandType, Renderer, Manager>
where
ConfigType: 'frame,
ElementType: 'frame,
Renderer: RenderCompatibleWith<Manager> + CotisRendererAsync<RenderCommandType>,
Manager: LayoutManager<'frame, ConfigType, ElementType> + LayoutManagerCompatible<Renderer>,
{
#[allow(async_fn_in_trait)]
async fn compute_frame_async<'layout>(
&'layout mut self,
ui: impl for<'a> UiFn<'a, Manager::ElementConfigurer<'layout>, ConfigType>,
) where
Manager: 'layout;
}
impl<'frame, ConfigType, ElementType, RenderCommandType, Renderer, Manager, Pipe>
AsyncRenderApp<'frame, ConfigType, ElementType, RenderCommandType, Renderer, Manager>
for CotisApp<Renderer, Manager, Pipe>
where
ConfigType: 'frame,
ElementType: 'frame,
Renderer: RenderCompatibleWith<Manager> + CotisRendererAsync<RenderCommandType>,
Manager: LayoutManager<'frame, ConfigType, ElementType> + LayoutManagerCompatible<Renderer>,
Pipe: LayoutRenderPipe<ElementType, RenderCommandType>,
{
async fn compute_frame_async<'layout>(
&'layout mut self,
ui: impl for<'a> UiFn<'a, Manager::ElementConfigurer<'layout>, ConfigType>,
) where
Manager: 'layout,
{
self.layout_manager.prepare(&self.render_engine);
let commands = {
let mut layout = self.layout_manager.begin_frame();
let mut parent = layout.begin();
ui.draw_in(&mut parent);
drop(parent);
self.layout_render_pipe.transform(layout.end())
};
CotisRendererAsync::draw_frame(&mut self.render_engine, commands).await;
}
}
pub trait RenderApp<'frame, ConfigType, ElementType, RenderCommandType, Renderer, Manager>
where
ConfigType: 'frame,
ElementType: 'frame,
Renderer: RenderCompatibleWith<Manager> + CotisRenderer<RenderCommandType>,
Manager: LayoutManager<'frame, ConfigType, ElementType> + LayoutManagerCompatible<Renderer>,
{
fn compute_frame<'layout>(
&'layout mut self,
ui: impl for<'a> UiFn<'a, Manager::ElementConfigurer<'layout>, ConfigType>,
) where
Manager: 'layout;
}
impl<'frame, ConfigType, ElementType, RenderCommandType, Renderer, Manager, Pipe>
RenderApp<'frame, ConfigType, ElementType, RenderCommandType, Renderer, Manager>
for CotisApp<Renderer, Manager, Pipe>
where
ConfigType: 'frame,
ElementType: 'frame,
Renderer: RenderCompatibleWith<Manager> + CotisRenderer<RenderCommandType>,
Manager: LayoutManager<'frame, ConfigType, ElementType> + LayoutManagerCompatible<Renderer>,
Pipe: LayoutRenderPipe<ElementType, RenderCommandType>,
{
fn compute_frame<'layout>(
&'layout mut self,
ui: impl for<'a> UiFn<'a, Manager::ElementConfigurer<'layout>, ConfigType>,
) where
Manager: 'layout,
{
self.layout_manager.prepare(&self.render_engine);
let commands = {
let mut layout = self.layout_manager.begin_frame();
let mut parent = layout.begin();
ui.draw_in(&mut parent);
drop(parent);
self.layout_render_pipe.transform(layout.end())
};
CotisRenderer::draw_frame(&mut self.render_engine, commands);
}
}
pub fn closure_helper<'frame, 'layout, F, Manager, ConfigType: 'frame, ElementType: 'frame>(
f: F,
) -> F
where
F: for<'a> FnOnce(
&mut ConfiguredParentElement<'a, Manager::ElementConfigurer<'layout>, ConfigType>,
),
Manager: LayoutManager<'frame, ConfigType, ElementType>,
{
f
}