use crate::knob::{KnobSpec, KnobValues};
use crate::source_loc::SourceLoc;
use crate::variant::PreviewVariant;
use teksilo_core::widget::Widget;
use teksilo_core::widget_id::WidgetId;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WidgetCategory {
Leaf,
ContainerA,
ContainerB,
}
#[derive(Debug, Clone)]
pub struct SlottedChild {
pub slot: Option<String>,
pub id: WidgetId,
}
pub trait WidgetCatalog: 'static {
fn id() -> &'static str;
fn group() -> &'static str;
fn display_name() -> &'static str;
fn variants() -> Vec<PreviewVariant>;
fn knobs() -> KnobSpec {
KnobSpec::empty()
}
fn build(variant: &str, knobs: &KnobValues) -> Box<dyn Widget>;
fn icon() -> Option<Box<dyn Widget>> {
None
}
fn category() -> WidgetCategory {
WidgetCategory::Leaf
}
fn slots() -> &'static [&'static str] {
&[]
}
fn build_with_children(
variant: &str,
knobs: &KnobValues,
children: Vec<SlottedChild>,
) -> Box<dyn Widget> {
let _ = children;
Self::build(variant, knobs)
}
}
pub trait CatalogEntry: Sync {
fn id(&self) -> &'static str;
fn group(&self) -> &'static str;
fn display_name(&self) -> &'static str;
fn source(&self) -> SourceLoc;
fn variants(&self) -> Vec<PreviewVariant>;
fn knobs(&self) -> KnobSpec;
fn build(&self, variant: &str, knobs: &KnobValues) -> Box<dyn Widget>;
fn icon(&self) -> Option<Box<dyn Widget>> {
None
}
fn category(&self) -> WidgetCategory {
WidgetCategory::Leaf
}
fn slots(&self) -> &'static [&'static str] {
&[]
}
fn build_with_children(
&self,
variant: &str,
knobs: &KnobValues,
children: Vec<SlottedChild>,
) -> Box<dyn Widget> {
let _ = children;
self.build(variant, knobs)
}
}
inventory::collect!(&'static dyn CatalogEntry);
#[macro_export]
macro_rules! register_widget_catalog {
($t:ty) => {
$crate::__register_widget_catalog_with!($t, file!(), line!());
};
}
#[macro_export]
macro_rules! register_widget_catalog_at {
($file:literal, $t:ty) => {
$crate::__register_widget_catalog_with!($t, $file, 1u32);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __register_widget_catalog_with {
($t:ty, $file:expr, $line:expr) => {
const _: () = {
#[allow(non_camel_case_types)]
struct __Entry;
impl $crate::CatalogEntry for __Entry {
fn id(&self) -> &'static str {
<$t as $crate::WidgetCatalog>::id()
}
fn group(&self) -> &'static str {
<$t as $crate::WidgetCatalog>::group()
}
fn display_name(&self) -> &'static str {
<$t as $crate::WidgetCatalog>::display_name()
}
fn source(&self) -> $crate::SourceLoc {
$crate::SourceLoc::new($file, $line)
}
fn variants(&self) -> ::std::vec::Vec<$crate::PreviewVariant> {
<$t as $crate::WidgetCatalog>::variants()
}
fn knobs(&self) -> $crate::KnobSpec {
<$t as $crate::WidgetCatalog>::knobs()
}
fn build(
&self,
variant: &str,
knobs: &$crate::KnobValues,
) -> ::std::boxed::Box<dyn $crate::__widget::Widget> {
<$t as $crate::WidgetCatalog>::build(variant, knobs)
}
fn icon(
&self,
) -> ::std::option::Option<::std::boxed::Box<dyn $crate::__widget::Widget>>
{
<$t as $crate::WidgetCatalog>::icon()
}
fn category(&self) -> $crate::WidgetCategory {
<$t as $crate::WidgetCatalog>::category()
}
fn slots(&self) -> &'static [&'static str] {
<$t as $crate::WidgetCatalog>::slots()
}
fn build_with_children(
&self,
variant: &str,
knobs: &$crate::KnobValues,
children: ::std::vec::Vec<$crate::SlottedChild>,
) -> ::std::boxed::Box<dyn $crate::__widget::Widget> {
<$t as $crate::WidgetCatalog>::build_with_children(variant, knobs, children)
}
}
static __ENTRY: __Entry = __Entry;
$crate::__inventory::submit! {
&__ENTRY as &'static dyn $crate::CatalogEntry
}
};
};
}