use core::ops::DerefMut;
use super::*;
use self::OrthogonalAttitude::*;
pub struct Split<Ev: Positional, Surface: Surfacial, A,
W: DerefMut<Target = Widget<Ev, Surface, Output = A>>,
Ws: DerefMut<Target = [(u32, W)]>, F: Fn() -> A> {
pub widgets: Ws,
pub attitude: OrthogonalAttitude,
pub default: F,
}
pub enum OrthogonalAttitude { Vertical, Lateral, }
impl OrthogonalAttitude {
pub fn flip(self) -> Self { match self { Vertical => Lateral, Lateral => Vertical, } }
}
impl<Ev: Positional, Surface: Surfacial, A,
W: DerefMut<Target = Widget<Ev, Surface, Output = A>>,
Ws: DerefMut<Target = [(u32, W)]>, F: Fn() -> A>
Widget<Ev, Surface> for Split<Ev, Surface, A, W, Ws, F> {
type Output = A;
fn take_event(&self, ev: Ev, size: (u32, u32)) -> A {
let f = |(x, y)| match self.attitude { Vertical => x, Lateral => y, } as u64;
let t = self.widgets.iter().map(|&(r, _)|r).sum::<u32>() as u64;
self.widgets.iter()
.scan(0, |st, &(r, ref w)| { *st += r; Some((*st as u64, r as u64, w)) })
.find(|&(s, _, _)| f(size)*s > t*f(ev.pos()))
.map_or_else(&self.default,
|(_, r, w)| w.take_event(ev, {
let c = |s| ((s as u64)*r/t) as u32;
match self.attitude {
Vertical => (c(size.0), size.1),
Lateral => (size.0, c(size.1)),
}
}))
}
fn draw(&self, surface: &mut Surface) {
let t = self.widgets.iter().map(|&(r, _)|r).sum::<u32>() as u64;
let (w, h) = surface.size();
let f = |r, b| {
let c = |s| ((s as u64)*r/t) as u32;
match self.attitude {
Vertical => (c(w), if b { 0 } else { h }),
Lateral => (if b { 0 } else { w }, c(h)),
}
};
self.widgets.iter()
.scan(0, |st, &(r, ref w)| {
let r = r as u64;
w.draw(surface.sect_mut(f(*st, false), f(*st + r, true)));
*st += r;
Some(())
}).count();
}
}