use traits::*;
use panel::*;
use enum_set::{EnumSet, CLike};
use std::marker;
use std::fmt;
use rin::events::*;
use rin::window;
use rin::window::events::*;
use rin::graphics::{Vertex2DColor, Vertex2DTex, Ttf};
use rin::math::{origin, Pnt2, Rect};
use rin::color::*;
use rin::color::consts::*;
use std::any::Any;
use std::collections::BTreeMap;
use std::fmt::Debug;
use control_shape::ControlShape;
pub struct Iter<E: EnumIter>{
i: usize,
marker: marker::PhantomData<E>,
}
impl<E: EnumIter> Iterator for Iter<E>{
type Item=E;
fn next(&mut self) -> Option<E>{
if self.i < E::len(){
let ret = Some(E::from_usize(self.i));
self.i += 1;
ret
}else{
None
}
}
}
impl<E: EnumIter> Iter<E>{
pub fn new() -> Iter<E>{
Iter{
i: 0,
marker: marker::PhantomData,
}
}
}
pub trait EnumIter where Self: Sized + fmt::Debug + CLike + PartialEq{
type Iter: Iterator<Item=Self>;
fn len() -> usize;
fn iter() -> Self::Iter;
}
pub struct ListBoxBuilder<P: Clone + Debug + 'static>{
label: String,
events: StreamRc<'static, window::Event>,
parameter: Property<'static, P>,
shape: ControlShape,
}
impl<P: Clone + Debug + 'static> ListBoxBuilder<P>{
pub fn new_multi<E: EnumIter + Clone + 'static, S: StreamT<'static, window::Event>>(name: &str, parameter: Property<'static, EnumSet<E>>, events: S) -> ListBoxBuilder<EnumSet<E>>{
let pos = Property::new(origin());
let width = Property::new(200.);
let height = Property::new(0.);
let h_margin = 10.;
let v_margin = 5.;
ListBoxBuilder{
label: name.to_string(),
events: events.rc(),
parameter: parameter,
shape: ControlShape::new(pos, width, height, h_margin, v_margin, WHITE),
}
}
pub fn new_optional<E: EnumIter + Clone + 'static, S: StreamT<'static, window::Event>>(name: &str, parameter: Property<'static, Option<E>>, events: S) -> ListBoxBuilder<Option<E>>{
let pos = Property::new(origin());
let width = Property::new(200.);
let height = Property::new(0.);
let h_margin = 10.;
let v_margin = 5.;
ListBoxBuilder{
label: name.to_string(),
events: events.rc(),
parameter: parameter,
shape: ControlShape::new(pos, width, height, h_margin, v_margin, WHITE),
}
}
pub fn new<E: EnumIter + Clone + 'static, S: StreamT<'static, window::Event>>(name: &str, parameter: Property<'static, E>, events: S) -> ListBoxBuilder<E>{
let pos = Property::new(origin());
let width = Property::new(200.);
let height = Property::new(0.);
let h_margin = 10.;
let v_margin = 5.;
ListBoxBuilder{
label: name.to_string(),
events: events.rc(),
parameter: parameter,
shape: ControlShape::new(pos, width, height, h_margin, v_margin, WHITE),
}
}
}
impl<E: EnumIter + Clone + 'static> ListBoxBuilder<EnumSet<E>> {
pub fn create(mut self) -> ListBoxMulti<E>{
let groupbuilder = PanelBuilder::new(&self.label, self.shape.position(), self.events.clone())
.color(self.shape.color())
.width_property(self.shape.width());
let groupbuilder = if self.shape.label_visible(){
groupbuilder
}else{
groupbuilder.hide_label()
};
let groupbuilder = if let Some(font) = self.shape.font(){
groupbuilder.font(font)
}else{
groupbuilder
};
let mut group = groupbuilder.create();
let mut all_parameters = vec![];
let parameter = self.parameter.clone();
let value = E::iter().fold(Stream::never(), |value, e|{
let name = format!("{:?}",e);
let toggle_parameter = Property::new(self.parameter.contains(&e));
all_parameters.push(toggle_parameter.clone());
let toggle = group.new_control(&name, toggle_parameter.clone());
let parameter = parameter.clone();
value.merge(toggle.stream().map(move |enabled|{
let mut enumset = *parameter;
if enabled{
enumset.insert(e.clone());
}else{
enumset.remove(&e);
}
enumset
}))
}).connect_to_property(&mut self.parameter);
let mut parameter_index: Vec<(E, Property<bool>)> = E::iter()
.zip(all_parameters.iter())
.map(|(e,p)| (e,p.clone()))
.collect();
let parameter = self.parameter.clone();
let update_from_parameter = self.events.clone()
.update()
.map(move |_| *parameter)
.dedup()
.on_value(move |set|{
for &mut (ref e, ref param) in parameter_index.iter_mut(){
let mut param = param.clone();
if set.contains(e){
param.set(true)
}else{
param.set(false)
}
}
}).to_bool();
ListBoxMulti{
group: group,
streams: vec![update_from_parameter],
value: value.rc(),
marker: marker::PhantomData,
}
}
}
impl<E: EnumIter + Clone + 'static> ControlBuilder for ListBoxBuilder<EnumSet<E>>{
type Control = ListBoxMulti<E>;
fn shape(&mut self) -> &mut ControlShape {
&mut self.shape
}
fn create(self) -> ListBoxMulti<E>{
self.create()
}
}
impl<E: EnumIter + Clone + 'static> ControlBuilt<Property<'static, EnumSet<E>>> for ListBoxMulti<E>{
type Builder = ListBoxBuilder<EnumSet<E>>;
}
impl<E: EnumIter + Clone + 'static> ControlDefaultProperty for Property<'static, EnumSet<E>>{
type Builder = ListBoxBuilder<EnumSet<E>>;
}
impl<E: EnumIter + Clone + 'static> BuilderFromProperty<Property<'static, EnumSet<E>>> for ListBoxBuilder<EnumSet<E>>{
fn from_parameter<S: StreamT<'static, window::Event>>(parameter: Property<'static, EnumSet<E>>, name: &str, events: S) -> ListBoxBuilder<EnumSet<E>>{
ListBoxBuilder::<EnumSet<E>>::new_multi(name, parameter, events)
}
}
impl<E: EnumIter + Clone + 'static> ListBoxBuilder<Option<E>>{
pub fn create(mut self) -> ListBoxOption<E>{
let groupbuilder = PanelBuilder::new(&self.label, self.shape.position(), self.events.clone())
.color(self.shape.color())
.width_property(self.shape.width());
let groupbuilder = if self.shape.label_visible(){
groupbuilder
}else{
groupbuilder.hide_label()
};
let groupbuilder = if let Some(font) = self.shape.font(){
groupbuilder.font(font)
}else{
groupbuilder
};
let mut group = groupbuilder.create();
let mut all_parameters = vec![];
let mut streams = vec![];
let value = E::iter().fold(Stream::never(), |value, e|{
let name = format!("{:?}",e);
let toggle_parameter = Property::new((*self.parameter).as_ref().map(|p| *p == e).unwrap_or(false));
all_parameters.push(toggle_parameter.clone());
let toggle = group.new_control(&name, toggle_parameter.clone());
streams.push(toggle.stream());
value.merge(toggle.stream()
.map(move |enabled| {
if enabled{
Some(e.clone())
}else{
None
}
})
)
}).connect_to_property(&mut self.parameter);
{
let mut streams_copy = streams.clone();
let disable_others_streams = all_parameters.iter_mut().enumerate().map(|(param_idx, mut param)|{
let others_stream = streams_copy.iter_mut().enumerate().fold(Stream::never(), |others_stream, (stream_idx, stream)|{
if stream_idx != param_idx{
others_stream.merge(stream.clone())
}else{
others_stream
}
});
others_stream.filter(|enabled| *enabled)
.not()
.connect_to_property(&mut param)
.rc()
});
streams.extend(disable_others_streams);
}
let parameter_index: BTreeMap<usize, Property<bool>> = E::iter()
.zip(all_parameters.iter())
.map(|(e,p)| (e.to_usize(), p.clone()))
.collect();
let parameter = self.parameter.clone();
let update_from_parameter = self.events.clone()
.update()
.filter_map(move |_| parameter.to_value().map(|e| e.to_usize()))
.dedup()
.on_value(move |e|{
let mut active_param = parameter_index[&e].clone();
active_param.set(true);
for p in all_parameters.iter_mut(){
if !p.is(&active_param){
p.set(false);
}
}
}).to_bool().rc();
streams.push(update_from_parameter);
ListBoxOption{
group: group,
streams: streams,
value: value.rc(),
marker: marker::PhantomData,
}
}
}
impl<E: EnumIter + Clone + 'static> ControlBuilder for ListBoxBuilder<Option<E>>{
type Control = ListBoxOption<E>;
fn shape(&mut self) -> &mut ControlShape {
&mut self.shape
}
fn create(self) -> ListBoxOption<E>{
self.create()
}
}
impl<E: EnumIter + Clone + 'static> ControlBuilt<Property<'static, Option<E>>> for ListBoxOption<E>{
type Builder = ListBoxBuilder<Option<E>>;
}
impl<E: EnumIter + Clone + 'static> ControlDefaultProperty for Property<'static, Option<E>>{
type Builder = ListBoxBuilder<Option<E>>;
}
impl<E: EnumIter + Clone + 'static> BuilderFromProperty<Property<'static, Option<E>>> for ListBoxBuilder<Option<E>>{
fn from_parameter<S: StreamT<'static, window::Event>>(parameter: Property<'static, Option<E>>, name: &str, events: S) -> ListBoxBuilder<Option<E>>{
ListBoxBuilder::<Option<E>>::new_optional(name, parameter, events)
}
}
impl<E: EnumIter + Clone + 'static> ListBoxBuilder<E>{
pub fn create(mut self) -> ListBox<E>{
let groupbuilder = PanelBuilder::new(&self.label, self.shape.position(), self.events.clone())
.color(self.shape.color())
.width_property(self.shape.width());
let groupbuilder = if self.shape.label_visible(){
groupbuilder
}else{
groupbuilder.hide_label()
};
let groupbuilder = if let Some(font) = self.shape.font(){
groupbuilder.font(font)
}else{
groupbuilder
};
let mut group = groupbuilder.create();
let mut all_parameters = vec![];
let mut streams = vec![];
let value = E::iter().fold(Stream::never(), |value,e|{
let name = format!("{:?}",e);
let mut toggle_parameter = Property::new(*self.parameter == e);
all_parameters.push(toggle_parameter.clone());
let toggle = group.new_control(&name, toggle_parameter.clone());
streams.push(toggle.stream());
value.merge(
toggle.stream().filter_map(move |enabled|{
if enabled{
Some(e.clone())
}else{
toggle_parameter.set(true);
None
}
})
)
}).connect_to_property(&mut self.parameter);
{
let mut streams_copy = streams.clone();
let disable_others_streams = all_parameters.iter_mut().enumerate().map(|(param_idx, mut param)|{
let others_stream = streams_copy.iter_mut().enumerate().fold(Stream::never(), |others_stream, (stream_idx, stream)|{
if stream_idx != param_idx{
others_stream.merge(stream.clone())
}else{
others_stream
}
});
others_stream.filter(|enabled| *enabled).not().connect_to_property(&mut param).rc()
});
streams.extend(disable_others_streams);
}
let parameter_index: BTreeMap<usize, Property<bool>> = E::iter()
.zip(all_parameters.iter())
.map(|(e,p)| (e.to_usize(), p.clone()))
.collect();
let parameter = self.parameter.clone();
let update_from_parameter = self.events.clone()
.update()
.map(move |_| parameter.to_usize())
.dedup()
.on_value(move |e|{
let mut active_param = parameter_index[&e].clone();
active_param.set(true);
for p in all_parameters.iter_mut(){
if !p.is(&active_param){
p.set(false);
}
}
}).to_bool().rc();
streams.push(update_from_parameter);
ListBox{
group: group,
streams: streams,
value: value.rc(),
marker: marker::PhantomData,
}
}
}
impl<E: EnumIter + Clone + 'static> ControlBuilder for ListBoxBuilder<E>{
type Control = ListBox<E>;
fn shape(&mut self) -> &mut ControlShape {
&mut self.shape
}
fn create(self) -> ListBox<E>{
self.create()
}
}
impl<E: EnumIter + Clone + 'static> ControlBuilt<Property<'static, E>> for ListBox<E>{
type Builder = ListBoxBuilder<E>;
}
impl<E: EnumIter + Clone + 'static> ControlDefaultProperty for Property<'static, E>{
type Builder = ListBoxBuilder<E>;
}
impl<E: EnumIter + Clone + 'static> BuilderFromProperty<Property<'static, E>> for ListBoxBuilder<E>{
fn from_parameter<S: StreamT<'static, window::Event>>(parameter: Property<'static, E>, name: &str, events: S) -> ListBoxBuilder<E>{
ListBoxBuilder::<E>::new(name, parameter, events)
}
}
pub struct ListBox<E: EnumIter + Clone + 'static>{
group: Panel,
#[allow(dead_code)]
streams: Vec<StreamRc<'static, bool>>,
value: StreamRc<'static, E>,
marker: marker::PhantomData<E>,
}
impl<E: EnumIter + Clone> ListBox<E>{
pub fn stream(&self) -> StreamRc<'static, E>{
self.value.clone()
}
}
impl<E:EnumIter + Clone> ControlGeometry for ListBox<E>{
fn flexible() -> bool{
true
}
fn geometry(&self, container: Option<&Rect<f32>>) -> Option<Vec<Vertex2DColor>>{
self.group.geometry(container)
}
fn text_geometry(&self, container: Option<&Rect<f32>>) -> Option<Vec<Vertex2DTex>>{
self.group.text_geometry(container)
}
fn texture_geometry(&self, _container: Option<&Rect<f32>>) -> Option<Vec<Vertex2DTex>>{
None
}
fn font(&self) -> Option<&Ttf>{
self.group.font()
}
fn color(&self) -> &Rgb<f32>{
self.group.color()
}
fn position(&self) -> &Property<'static, Pnt2>{
self.group.position()
}
fn width(&self) -> &Property<'static, f32>{
self.group.width()
}
fn height(&self) -> &Property<'static, f32>{
self.group.height()
}
}
impl<E:EnumIter + Clone> ControlEvents for ListBox<E>{
fn non_attended(&self) -> StreamRc<'static, window::Event>{
self.group.non_attended()
}
}
impl<E:EnumIter + Any + 'static + Clone> Control for ListBox<E>{
fn name(&self) -> &str{
self.group.name()
}
}
pub struct ListBoxMulti<E: EnumIter + Clone + 'static>{
group: Panel,
#[allow(dead_code)]
streams: Vec<Stream<'static, bool>>,
value: StreamRc<'static, EnumSet<E>>,
marker: marker::PhantomData<E>,
}
impl<E: EnumIter + Clone> ListBoxMulti<E>{
pub fn stream(&self) -> StreamRc<'static, EnumSet<E>>{
self.value.clone()
}
}
impl<E:EnumIter + Clone> ControlGeometry for ListBoxMulti<E>{
fn flexible() -> bool{
true
}
fn geometry(&self, container: Option<&Rect<f32>>) -> Option<Vec<Vertex2DColor>>{
self.group.geometry(container)
}
fn text_geometry(&self, container: Option<&Rect<f32>>) -> Option<Vec<Vertex2DTex>>{
self.group.text_geometry(container)
}
fn texture_geometry(&self, _container: Option<&Rect<f32>>) -> Option<Vec<Vertex2DTex>>{
None
}
fn font(&self) -> Option<&Ttf>{
self.group.font()
}
fn color(&self) -> &Rgb<f32>{
self.group.color()
}
fn position(&self) -> &Property<'static, Pnt2>{
self.group.position()
}
fn width(&self) -> &Property<'static, f32>{
self.group.width()
}
fn height(&self) -> &Property<'static, f32>{
self.group.height()
}
}
impl<E:EnumIter + Clone> ControlEvents for ListBoxMulti<E>{
fn non_attended(&self) -> StreamRc<'static, window::Event>{
self.group.non_attended()
}
}
impl<E:EnumIter + Any + 'static + Clone> Control for ListBoxMulti<E>{
fn name(&self) -> &str{
self.group.name()
}
}
pub struct ListBoxOption<E: EnumIter + Clone + 'static>{
group: Panel,
#[allow(dead_code)]
streams: Vec<StreamRc<'static, bool>>,
value: StreamRc<'static, Option<E>>,
marker: marker::PhantomData<E>,
}
impl<E: EnumIter + Clone> ListBoxOption<E>{
pub fn stream(&self) -> StreamRc<'static, Option<E>>{
self.value.clone()
}
}
impl<E:EnumIter + Clone> ControlGeometry for ListBoxOption<E>{
fn flexible() -> bool{
true
}
fn geometry(&self, container: Option<&Rect<f32>>) -> Option<Vec<Vertex2DColor>>{
self.group.geometry(container)
}
fn text_geometry(&self, container: Option<&Rect<f32>>) -> Option<Vec<Vertex2DTex>>{
self.group.text_geometry(container)
}
fn texture_geometry(&self, _container: Option<&Rect<f32>>) -> Option<Vec<Vertex2DTex>>{
None
}
fn font(&self) -> Option<&Ttf>{
self.group.font()
}
fn color(&self) -> &Rgb<f32>{
&self.group.color()
}
fn position(&self) -> &Property<'static, Pnt2>{
self.group.position()
}
fn width(&self) -> &Property<'static, f32>{
self.group.width()
}
fn height(&self) -> &Property<'static, f32>{
self.group.height()
}
}
impl<E:EnumIter + Clone> ControlEvents for ListBoxOption<E>{
fn non_attended(&self) -> StreamRc<'static, window::Event>{
self.group.non_attended()
}
}
impl<E:EnumIter + Any + 'static + Clone> Control for ListBoxOption<E>{
fn name(&self) -> &str{
self.group.name()
}
}