use daggy;
use graph::Graph;
use std;
pub type Id = daggy::NodeIndex<u32>;
pub struct Generator<'a> {
widget_graph: &'a mut Graph,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct List(Vec<Id>);
#[allow(missing_copy_implementations)]
pub struct ListWalk {
i: usize,
}
impl<'a> Generator<'a> {
pub fn new(widget_graph: &'a mut Graph) -> Self {
Generator {
widget_graph: widget_graph,
}
}
pub fn next(&mut self) -> Id {
self.widget_graph.add_placeholder()
}
}
impl List {
pub fn new() -> Self {
List(Vec::new())
}
pub fn walk(&self) -> ListWalk {
ListWalk { i: 0 }
}
pub fn resize(&mut self, target_len: usize, id_generator: &mut Generator) {
if self.len() < target_len {
self.0.reserve(target_len);
while self.len() < target_len {
self.0.push(id_generator.next());
}
}
while self.len() > target_len {
self.0.pop();
}
}
}
impl std::ops::Deref for List {
type Target = [Id];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl ListWalk {
pub fn next(&mut self, &mut List(ref mut ids): &mut List, id_gen: &mut Generator) -> Id {
while self.i >= ids.len() {
ids.push(id_gen.next());
}
let ix = ids[self.i];
self.i += 1;
ix
}
}
#[macro_export]
macro_rules! widget_ids {
($(#[$attr:meta])* struct $Ids:ident { $($id:tt)* }) => {
widget_ids! { implement $(#[$attr])* [] $Ids { $($id)* } }
};
($(#[$attr:meta])* pub struct $Ids:ident { $($id:tt)* }) => {
widget_ids! { implement $(#[$attr])* [pub] $Ids { $($id)* } }
};
(implement $(#[$attr:meta])* [$($public:tt)*] $Ids:ident { $($id:tt)* }) => {
widget_ids! {
define_struct $(#[$attr])* [$($public)*] $Ids { {} $($id)* }
}
impl $Ids {
#[allow(unused_mut, unused_variables)]
pub fn new(mut generator: $crate::widget::id::Generator) -> Self {
widget_ids! {
constructor $Ids, generator { {} $($id)* }
}
}
}
};
(define_struct $(#[$attr:meta])* [$($public:tt)*] $Ids:ident {
{ $($id_field:ident: $T:path,)* } $id:ident[], $($rest:tt)*
}) => {
widget_ids! {
define_struct $(#[$attr])* [$($public)*] $Ids {
{
$($id_field: $T,)*
$id: $crate::widget::id::List,
}
$($rest)*
}
}
};
(define_struct $(#[$attr:meta])* [$($public:tt)*] $Ids:ident {
{ $($id_field:ident: $T:path,)* } $id:ident, $($rest:tt)*
}) => {
widget_ids! {
define_struct $(#[$attr])* [$($public)*] $Ids {
{
$($id_field: $T,)*
$id: $crate::widget::Id,
}
$($rest)*
}
}
};
(define_struct $(#[$attr:meta])* [$($public:tt)*] $Ids:ident {
{ $($id_field:ident: $T:path,)* } $id:ident[]
}) => {
widget_ids! {
define_struct $(#[$attr])* [$($public)*] $Ids { { $($id_field: $T,)* } $id[], }
}
};
(define_struct $(#[$attr:meta])* [$($public:tt)*] $Ids:ident {
{ $($id_field:ident: $T:path,)* } $id:ident
}) => {
widget_ids! {
define_struct $(#[$attr])* [$($public)*] $Ids { { $($id_field: $T,)* } $id, }
}
};
(define_struct $(#[$attr:meta])* [pub] $Ids:ident { { $($id:ident: $T:path,)* } }) => {
$(#[$attr])*
pub struct $Ids {
$(pub $id: $T,
)*
}
};
(define_struct $(#[$attr:meta])* [] $Ids:ident { { $($id:ident: $T:path,)* } }) => {
$(#[$attr])*
struct $Ids {
$(pub $id: $T,
)*
}
};
(constructor $Ids:ident, $generator:ident {
{ $($id_field:ident: $new:expr,)* } $id:ident[], $($rest:tt)*
}) => {
widget_ids! {
constructor $Ids, $generator {
{
$($id_field: $new,)*
$id: $crate::widget::id::List::new(),
}
$($rest)*
}
}
};
(constructor $Ids:ident, $generator:ident {
{ $($id_field:ident: $new:expr,)* } $id:ident, $($rest:tt)*
}) => {
widget_ids! {
constructor $Ids, $generator {
{
$($id_field: $new,)*
$id: $generator.next(),
}
$($rest)*
}
}
};
(constructor $Ids:ident, $generator:ident {
{ $($id_field:ident: $new:expr,)* } $id:ident[]
}) => {
widget_ids! { constructor $Ids, $generator { { $($id_field: $new,)* } $id[], } }
};
(constructor $Ids:ident, $generator:ident {
{ $($id_field:ident: $new:expr,)* } $id:ident
}) => {
widget_ids! { constructor $Ids, $generator { { $($id_field: $new,)* } $id, } }
};
(constructor $Ids:ident, $generator:ident { { $($id:ident: $new:expr,)* } }) => {
$Ids {
$(
$id: $new,
)*
}
};
}
#[test]
fn test() {
use ui::UiBuilder;
use widget::{self, Widget};
widget_ids! {
#[derive(Clone)]
pub struct Ids {
button,
toggles[],
}
}
let mut ui = UiBuilder::new([800.0, 600.0]).build();
let mut ids = Ids::new(ui.widget_id_generator());
for _ in 0..10 {
let ref mut ui = ui.set_widgets();
widget::Button::new().set(ids.button, ui);
ids.toggles.resize(5, &mut ui.widget_id_generator());
for &id in ids.toggles.iter() {
widget::Toggle::new(true).set(id, ui);
}
}
}
#[test]
#[allow(unused_variables)]
fn test_invocation_variations() {
use ui::UiBuilder;
widget_ids! { struct A { foo, bar } }
widget_ids! { pub struct B { foo, bar } }
widget_ids! { struct C { foo, bar, } }
widget_ids! { pub struct D { foo, bar, } }
widget_ids! { struct E { foo[], bar } }
widget_ids! { pub struct F { foo, bar[] } }
widget_ids! { struct G { foo[], bar, } }
widget_ids! { pub struct H { foo, bar[], } }
let mut ui = UiBuilder::new([800.0, 600.0]).build();
let mut ui = ui.set_widgets();
let a = A::new(ui.widget_id_generator());
let b = B::new(ui.widget_id_generator());
let c = C::new(ui.widget_id_generator());
let d = D::new(ui.widget_id_generator());
let e = E::new(ui.widget_id_generator());
let f = F::new(ui.widget_id_generator());
let g = G::new(ui.widget_id_generator());
let h = H::new(ui.widget_id_generator());
}