use crate::{
comms::Port,
geometry::{Point, Rect, Size, Transform},
Map,
};
#[derive(Debug, Default)]
pub struct Layout {
pub outputs: Map<Port, OutputConfig>,
}
impl Layout {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn outputs(&self) -> impl Iterator<Item = OutputRef<'_>> {
self.outputs
.iter()
.map(|(port, cfg)| OutputRef { port, cfg })
}
pub fn add(&mut self, output: Output) {
self.outputs.insert(output.port, output.cfg);
}
pub fn bounding_box(&self) -> Rect {
let mut bb = Rect::default();
for cfg in self.outputs.values() {
bb.stretch_to_rect(cfg.bounds);
}
bb
}
pub fn reset_to_origin(&mut self) {
let bb = self.bounding_box();
let least = Point {
x: bb.x.start(),
y: bb.y.start(),
};
for cfg in self.outputs.values_mut() {
cfg.bounds -= least;
}
}
}
impl FromIterator<Output> for Layout {
fn from_iter<I: IntoIterator<Item = Output>>(iter: I) -> Self {
let outputs = iter
.into_iter()
.map(|Output { port, cfg }| (port, cfg))
.collect();
Self { outputs }
}
}
#[derive(Copy, Clone, PartialEq, PartialOrd)]
pub struct Output {
pub port: Port,
pub cfg: OutputConfig,
}
#[derive(Copy, Clone, PartialEq, PartialOrd)]
pub struct OutputRef<'layout> {
pub port: &'layout Port,
pub cfg: &'layout OutputConfig,
}
impl From<OutputRef<'_>> for Output {
fn from(OutputRef { port, cfg }: OutputRef<'_>) -> Self {
Self {
port: port.to_owned(),
cfg: cfg.to_owned(),
}
}
}
impl<'a> From<&'a Output> for OutputRef<'a> {
fn from(Output { ref port, ref cfg }: &'a Output) -> Self {
Self { port, cfg }
}
}
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct OutputConfig {
pub bounds: Rect,
pub resolution: Option<Size>,
pub scale: f64,
pub transform: Transform,
pub active: bool,
}