use std::any::TypeId;
use std::collections::HashMap;
use std::sync::Arc;
use repose_core::{PaintCallbackInfo, PaintCallbackPayload, Rect};
#[cfg(not(target_arch = "wasm32"))]
type AnyBox = Box<dyn std::any::Any + Send + Sync>;
#[cfg(target_arch = "wasm32")]
type AnyBox = Box<dyn std::any::Any>;
#[cfg(not(target_arch = "wasm32"))]
pub trait MaybeSendSync: Send + Sync + 'static {}
#[cfg(not(target_arch = "wasm32"))]
impl<T: Send + Sync + 'static> MaybeSendSync for T {}
#[cfg(target_arch = "wasm32")]
pub trait MaybeSendSync: 'static {}
#[cfg(target_arch = "wasm32")]
impl<T: 'static> MaybeSendSync for T {}
#[derive(Default)]
pub struct CallbackResources {
map: HashMap<TypeId, AnyBox>,
}
impl CallbackResources {
pub fn insert<T: MaybeSendSync>(&mut self, value: T) {
self.map.insert(TypeId::of::<T>(), Box::new(value));
}
pub fn get<T: MaybeSendSync>(&self) -> Option<&T> {
self.map
.get(&TypeId::of::<T>())
.and_then(|b| b.downcast_ref::<T>())
}
pub fn get_mut<T: MaybeSendSync>(&mut self) -> Option<&mut T> {
self.map
.get_mut(&TypeId::of::<T>())
.and_then(|b| b.downcast_mut::<T>())
}
pub fn get_or_insert_with<T: MaybeSendSync + Default>(&mut self) -> &mut T {
let id = TypeId::of::<T>();
if !self.map.contains_key(&id) {
self.map.insert(id, Box::new(T::default()));
}
self.map.get_mut(&id).unwrap().downcast_mut::<T>().unwrap()
}
pub fn remove<T: 'static>(&mut self) -> Option<T> {
self.map
.remove(&TypeId::of::<T>())
.and_then(|b| b.downcast::<T>().ok())
.map(|b| *b)
}
pub fn contains<T: 'static>(&self) -> bool {
self.map.contains_key(&TypeId::of::<T>())
}
}
#[derive(Clone, Copy, Debug)]
pub struct ScreenDescriptor {
pub size_in_pixels: [u32; 2],
pub pixels_per_point: f32,
pub target_format: wgpu::TextureFormat,
pub sample_count: u32,
}
pub trait WgpuCallback: Send + Sync + 'static {
fn prepare(
&self,
_device: &wgpu::Device,
_queue: &wgpu::Queue,
_encoder: &mut wgpu::CommandEncoder,
_screen_descriptor: &ScreenDescriptor,
_resources: &mut CallbackResources,
) -> Vec<wgpu::CommandBuffer> {
Vec::new()
}
fn finish_prepare(
&self,
_device: &wgpu::Device,
_queue: &wgpu::Queue,
_encoder: &mut wgpu::CommandEncoder,
_screen_descriptor: &ScreenDescriptor,
_resources: &mut CallbackResources,
) -> Vec<wgpu::CommandBuffer> {
Vec::new()
}
fn paint(
&self,
info: PaintCallbackInfo,
render_pass: &mut wgpu::RenderPass<'static>,
resources: &CallbackResources,
);
}
pub struct Callback(pub Box<dyn WgpuCallback>);
impl Callback {
#[deprecated(note = "rect is ignored; use Callback::new(callback) - layout supplies rect")]
pub fn new_paint_callback(
_rect: Rect,
callback: impl WgpuCallback + 'static,
) -> PaintCallbackPayload {
Arc::new(Self(Box::new(callback)))
}
pub fn new(callback: impl WgpuCallback + 'static) -> PaintCallbackPayload {
Arc::new(Self(Box::new(callback)))
}
pub fn embedded_view(
modifier: repose_core::Modifier,
callback: impl WgpuCallback + 'static,
) -> repose_core::View {
let payload = Self::new(callback);
let mut m = modifier.paint_callback(payload);
let has_size = m.size.is_some()
|| m.width.is_some()
|| m.height.is_some()
|| m.fill_max.is_some()
|| m.fill_max_w.is_some()
|| m.fill_max_h.is_some();
if !has_size {
m = m.size(100.0, 100.0);
}
repose_core::View::new(0, repose_core::ViewKind::Box).modifier(m)
}
}