use crate::geometry::*;
use crate::graphics::*;
use crate::widget::Painter;
use std::io;
use std::ops::Range;
#[derive(Debug)]
pub struct Screen {
size: Point,
points: Vec<Option<Spot>>,
}
impl Screen {
pub fn new(size: Point) -> Self {
let mut scr = Screen {
size: Point::default(),
points: vec![],
};
scr.resize(size).unwrap();
scr
}
pub fn get_size(&self) -> Point {
self.size
}
pub fn resize(&mut self, newsize: Point) -> io::Result<()> {
let mut newpoints = Vec::with_capacity(newsize.area() as usize);
for i in 0..newsize.area() {
if let Some(point) = newsize.point_at_idx(i) {
if let Some(idx) = self.size.idx_at_point(point) {
newpoints.push(self.points[idx as usize].take());
} else {
newpoints.push(None);
}
} else {
newpoints.push(None);
}
}
self.points = newpoints;
self.size = newsize;
Ok(())
}
pub fn draw(&mut self, drawing: Drawing) {
trace!("Screen drawing {:?}", drawing);
for (pos, spot) in drawing.spots() {
if let Some(i) = self.size.idx_at_point(pos + drawing.scope.position) {
self.points[i as usize] = Some(spot);
}
}
}
}
impl Painter for Screen {
fn get_area(&self) -> Window {
window(Point::default(), self.size)
}
fn paint(&mut self, mut drawing: Drawing) -> io::Result<()> {
drawing.scope = &self.get_area() & &drawing.scope;
self.draw(drawing);
Ok(())
}
}
#[derive(Debug)]
pub struct ScreenDrawings<'a> {
screen: &'a Screen,
counter: Range<usize>,
drawing: Option<Drawing>,
}
impl<'a> ScreenDrawings<'a> {
fn new(screen: &'a Screen) -> Self {
ScreenDrawings {
screen,
counter: (0..screen.points.len()),
drawing: None,
}
}
}
impl<'a> Iterator for ScreenDrawings<'a> {
type Item = Drawing;
fn next(&mut self) -> Option<Self::Item> {
while let Some(idx) = self.counter.next() {
if let Some(ref spot) = self.screen.points[idx] {
if let Some(mut d) = self.drawing.take() {
if spot.style == d.style {
self.drawing = Some(d.append(&spot.symbol));
} else {
put(self, idx, spot);
return Some(d);
}
} else {
put(self, idx, spot);
}
} else if self.drawing.is_some() {
return self.drawing.take();
}
}
self.drawing.take()
}
}
fn put(it: &mut ScreenDrawings, idx: usize, spot: &Spot) {
it.screen
.size
.point_at_idx(idx as u32)
.map(|pos| it.drawing = Some(spot.as_drawing().with_pos(pos)));
}
impl<'a> IntoIterator for &'a Screen {
type Item = Drawing;
type IntoIter = ScreenDrawings<'a>;
fn into_iter(self) -> Self::IntoIter {
ScreenDrawings::new(self)
}
}
#[test]
fn test_screen_drawing() {
let mut sut = Screen::new(point(x(4), y(3)));
assert_eq!(sut.size.area(), 12);
sut.draw("a".as_drawing().left(1).top(1));
println!("{:?}", sut.points);
assert_eq!(
sut.points[5],
Some(Spot {
symbol: "a".to_owned(),
..Default::default()
})
);
}
#[test]
fn test_screen_last_point() {
let mut sut = Screen::new(point(x(4), y(3)));
sut.draw("a".as_drawing().left(3).top(2));
println!("{:?}", sut.points);
assert_eq!(
sut.points[11],
Some(Spot {
symbol: "a".to_owned(),
..Default::default()
})
);
}
#[test]
fn test_screen_resize() {
let mut sut = Screen::new(point(x(1), y(1)));
sut.draw("a".as_drawing().left(0).top(0));
sut.resize(point(x(2), y(2))).unwrap();
println!("{:?}", sut.points);
assert_eq!(
sut.points[0],
Some(Spot {
symbol: "a".to_owned(),
..Default::default()
})
);
}
#[test]
fn test_screen_iterator() {
let sut = Screen {
points: vec![Some(Spot {
symbol: "x".to_owned(),
style: Style::default(),
})],
size: point(x(3), y(1)),
};
let mut sut = sut.into_iter();
println!("{:?}", sut);
let result = sut.next();
println!("{:?}", sut);
assert_eq!(result, Some("x".as_drawing()));
}