use std::convert::TryFrom;
use strum::FromRepr;
use crate::tree::NodeId;
use crate::interface::model;
use crate::interface::controller::controls;
pub trait Application : Sized {
type CallbackIds : std::fmt::Debug + Into <CallbackId> + TryFrom <CallbackId>
+ std::ops::Deref <Target = Callback <Self>>;
type AxisControls : controls::Id <controls::Axis> = controls::Nil;
type ButtonControls : controls::Id <controls::Button> = controls::Nil;
type MotionControls : controls::Id <controls::Motion> = controls::Nil;
type PointerControls : controls::Id <controls::Pointer> = controls::Nil;
type SystemControls : controls::Id <controls::System> = controls::Nil;
type TextControls : controls::Id <controls::Text> = controls::Nil;
type WheelControls : controls::Id <controls::Wheel> = controls::Nil;
}
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
pub struct CallbackId (pub CallbackReprType);
pub type CallbackReprType = u16;
pub type Callback <A> = fn (&mut A, model::Component, NodeId);
pub fn callback <A : Application> (callback_id : CallbackId) -> A::CallbackIds {
A::CallbackIds::try_from (callback_id).ok().unwrap()
}
#[derive(Debug, Default)]
pub struct Default;
impl Application for Default {
type CallbackIds = Nil;
type AxisControls = controls::Nil;
type ButtonControls = controls::Nil;
type MotionControls = controls::Nil;
type PointerControls = controls::Nil;
type SystemControls = controls::Nil;
type TextControls = controls::Nil;
type WheelControls = controls::Nil;
}
#[derive(Debug, Eq, PartialEq, FromRepr)]
pub enum Nil { }
impl From <Nil> for CallbackId {
fn from (_ : Nil) -> CallbackId {
unreachable!()
}
}
impl std::convert::TryFrom <CallbackId> for Nil {
type Error = CallbackId;
fn try_from (_ : CallbackId) -> Result <Self, CallbackId> {
unreachable!()
}
}
impl std::ops::Deref for Nil {
type Target = fn (&mut Default, model::Component, NodeId);
fn deref (&self) -> &fn (&mut Default, model::Component, NodeId) {
unreachable!()
}
}
#[macro_export]
macro_rules! def_callback_ids {
( $callback_ids:ident <$application:ty> {
$($callback_id:ident => $callback:path)*
}
) => {
#[derive(Debug, Eq, PartialEq, $crate::strum::FromRepr)]
#[repr(u16)]
pub enum $callback_ids {
$($callback_id),*
}
impl From <$callback_ids> for $crate::application::CallbackId {
fn from (id : $callback_ids) -> $crate::application::CallbackId {
$crate::application::CallbackId (
id as $crate::application::CallbackReprType
)
}
}
impl std::convert::TryFrom <$crate::application::CallbackId> for $callback_ids {
type Error = $crate::application::CallbackId;
fn try_from (callback_id : $crate::application::CallbackId)
-> Result <Self, $crate::application::CallbackId>
{
$callback_ids::from_repr (callback_id.0).ok_or (callback_id)
}
}
impl std::ops::Deref for $callback_ids {
type Target = fn (&mut $application,
$crate::interface::model::Component, $crate::tree::NodeId);
fn deref (&self) -> &fn (&mut $application,
$crate::interface::model::Component, $crate::tree::NodeId
) {
match self {
$($callback_ids :: $callback_id => {
static F : fn (
&mut $application,
$crate::interface::model::Component,
$crate::tree::NodeId
) = $callback;
&F
})*
}
}
}
}
}