use std::{
any::{Any, TypeId},
collections::VecDeque,
};
use crate::{
commands, Command, Data, Env, Event, MenuDesc, SingleUse, Target, WindowDesc, WindowId,
};
pub struct DelegateCtx<'a> {
pub(crate) command_queue: &'a mut VecDeque<(Target, Command)>,
pub(crate) app_data_type: TypeId,
}
impl<'a> DelegateCtx<'a> {
pub fn submit_command(
&mut self,
command: impl Into<Command>,
target: impl Into<Option<Target>>,
) {
let command = command.into();
let target = target.into().unwrap_or(Target::Global);
self.command_queue.push_back((target, command))
}
pub fn new_window<T: Any>(&mut self, desc: WindowDesc<T>) {
if self.app_data_type == TypeId::of::<T>() {
self.submit_command(
Command::new(commands::NEW_WINDOW, SingleUse::new(Box::new(desc))),
Target::Global,
);
} else {
const MSG: &str = "WindowDesc<T> - T must match the application data type.";
if cfg!(debug_assertions) {
panic!(MSG);
} else {
log::error!("DelegateCtx::new_window: {}", MSG)
}
}
}
pub fn set_menu<T: Any>(&mut self, menu: MenuDesc<T>, window: WindowId) {
if self.app_data_type == TypeId::of::<T>() {
self.submit_command(
Command::new(commands::SET_MENU, Box::new(menu)),
Target::Window(window),
);
} else {
const MSG: &str = "MenuDesc<T> - T must match the application data type.";
if cfg!(debug_assertions) {
panic!(MSG);
} else {
log::error!("DelegateCtx::set_menu: {}", MSG)
}
}
}
}
#[allow(unused)]
pub trait AppDelegate<T: Data> {
fn event(
&mut self,
ctx: &mut DelegateCtx,
window_id: WindowId,
event: Event,
data: &mut T,
env: &Env,
) -> Option<Event> {
Some(event)
}
fn command(
&mut self,
ctx: &mut DelegateCtx,
target: Target,
cmd: &Command,
data: &mut T,
env: &Env,
) -> bool {
true
}
fn window_added(&mut self, id: WindowId, data: &mut T, env: &Env, ctx: &mut DelegateCtx) {}
fn window_removed(&mut self, id: WindowId, data: &mut T, env: &Env, ctx: &mut DelegateCtx) {}
}