use crate::prelude::*;
use super::modal::Modals;
pub struct WidgetEntry<W> {
pub name: String,
pub create: fn() -> W,
}
pub struct WidgetContext<'a, C = (), M = ()> {
pub(crate) world: &'a mut World,
pub viewport_textures: &'a [egui::TextureId],
pub current_tile_id: egui_tiles::TileId,
pub selected_viewport_tile: &'a mut Option<egui_tiles::TileId>,
pub modals: &'a mut Modals,
pub app: &'a mut C,
pub window_index: Option<usize>,
pub is_active_window: bool,
pub cached_cameras: &'a [Entity],
pub(crate) messages: &'a mut Vec<M>,
pub(crate) incoming_messages: &'a mut std::collections::HashMap<egui_tiles::TileId, Vec<M>>,
}
impl<C, M> WidgetContext<'_, C, M> {
pub fn world(&self) -> &World {
self.world
}
pub fn world_mut(&mut self) -> &mut World {
self.world
}
pub fn world_and_app(&mut self) -> (&mut World, &mut C) {
(self.world, self.app)
}
pub fn world_app_modals(&mut self) -> (&mut World, &mut C, &mut Modals) {
(self.world, self.app, self.modals)
}
pub fn send(&mut self, message: M) {
self.messages.push(message);
}
pub fn receive(&mut self) -> Vec<M> {
self.incoming_messages
.remove(&self.current_tile_id)
.unwrap_or_default()
}
pub fn has_incoming(&self) -> bool {
self.incoming_messages
.get(&self.current_tile_id)
.is_some_and(|messages| !messages.is_empty())
}
}
pub trait Widget<C = (), M = ()>:
Clone + serde::Serialize + serde::de::DeserializeOwned + 'static
{
fn title(&self) -> String;
fn ui(&mut self, ui: &mut egui::Ui, context: &mut WidgetContext<C, M>);
fn on_add(&mut self, _context: &mut WidgetContext<C, M>) {}
fn on_remove(&mut self, _context: &mut WidgetContext<C, M>) {}
fn closable(&self) -> bool {
true
}
fn required_camera(&self, _cached_cameras: &[Entity]) -> Option<Entity> {
None
}
fn catalog() -> Vec<WidgetEntry<Self>>
where
Self: Sized;
}
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct Pane<W> {
pub widget: W,
}
impl<W> Pane<W> {
pub fn new(widget: W) -> Self {
Self { widget }
}
}