use crate::{
graphics::{Aligner, Point, Shape, Size},
widgets::{Container, Image, Label, Layout},
Direction, Widget, controllers::tap,
};
use super::calculate_size;
pub trait Drawer {
fn shape(&mut self, shape: &Shape);
fn image(&mut self, position: Point, image: &Image);
fn label(&mut self, position: Point, label: &Label);
fn layout(&self) -> &Layout;
fn size_all_containers(containers: &Vec<&Container>) -> Size {
if containers.len() == 0 {
return [0, 0];
}
let mut total_size = [0, 0];
let sizes = containers.iter().map(|container| container.size);
for container_size in sizes {
total_size[0] += container_size[0];
total_size[1] += container_size[1];
}
total_size
}
fn size_each_not_container(
widgets: &Vec<&Box<dyn Widget>>,
size: &Size,
direction: &Direction,
size_all_containers: &Size
) -> Size {
assert!(widgets.len() != 0);
match direction {
Direction::Column => [
if size_all_containers[0] > size[0] {
0
} else {
(size[0] - size_all_containers[0]) / widgets.len()
},
size[1]
],
Direction::Row => [
size[0],
if size_all_containers[1] > size[1] {
0
} else {
(size[1] - size_all_containers[1]) / widgets.len()
}
],
}
}
fn build_shapes(layout: &Layout, size: Size) -> Vec<Shape> {
if layout.widgets.len() == 0 {
return vec![]
}
let not_containers = layout.not_widget::<Container>();
let containers = layout.widgets::<Container>();
if not_containers.len() == 0 {
return containers
.iter()
.map(|container| container.shape(None))
.collect::<Vec<Shape>>();
}
let size_all_containers: Size = Self::size_all_containers(&containers);
let size_each_not_container: Size = Self::size_each_not_container(
¬_containers,
&size,
&layout.direction,
&size_all_containers
);
layout.widgets
.iter()
.map(|widget| match widget.as_any().downcast_ref::<Container>() {
Some(container) => container.shape(None),
None => widget.shape(Some(size_each_not_container)),
})
.collect()
}
fn build_layout_shape(layout: &Layout, position: Point, size: Size) -> Shape {
let mut layout_shape = layout.shape(Some(size));
layout_shape.move_by(position);
layout_shape
}
fn build_layout_shapes(&self, layout: &Layout, position: Point, size: Size) -> Vec<Shape> {
let layout_shape: Shape = Self::build_layout_shape(layout, position, size);
let mut widgets_shapes: Vec<Shape> = Self::build_shapes(layout, size);
let mut aligner = Aligner::new(&widgets_shapes);
let mut more_shapes: Vec<Shape> = vec![];
for (i, shape) in widgets_shapes.iter_mut().enumerate() {
aligner.align_shape(layout, &layout_shape, shape);
let widget_as_any = layout.widgets[i].as_any();
match widget_as_any.downcast_ref::<Layout>() {
Some(sub_layout) => {
more_shapes.extend(
self.build_layout_shapes(
sub_layout,
shape.points()[0],
calculate_size(&shape)
)
);
}
None => {}
}
match widget_as_any.downcast_ref::<Container>() {
Some(container) => {
let mut container_widget_shape = container
.widget
.shape(Some(container.size));
container_widget_shape.move_by(shape.points()[0]);
more_shapes.push(container_widget_shape);
}
None => {}
}
}
more_shapes.push(layout_shape);
widgets_shapes.extend(more_shapes);
widgets_shapes
}
fn draw(&mut self, position: Point, size: Size) {
let layout = self.layout();
let all_shapes = self.build_layout_shapes(layout, position, size);
for shape in &all_shapes {
self.shape(shape);
}
}
}