use crate::error::DisplayResult;
use crate::types::Rect;
pub trait OverlapCheckable {
fn is_enabled(&self) -> bool;
fn geometry(&self) -> Rect;
}
pub fn check_overlap<T: OverlapCheckable>(outputs: &[T]) -> DisplayResult<()> {
for (i, out_a) in outputs.iter().enumerate() {
for out_b in outputs.iter().skip(i + 1) {
if out_a.is_enabled() && out_b.is_enabled() {
let a = out_a.geometry();
let b = out_b.geometry();
let a_x2 = a.origin.x + a.size.width as i32;
let a_y2 = a.origin.y + a.size.height as i32;
let b_x2 = b.origin.x + b.size.width as i32;
let b_y2 = b.origin.y + b.size.height as i32;
let overlap_x = a.origin.x < b_x2 && a_x2 > b.origin.x;
let overlap_y = a.origin.y < b_y2 && a_y2 > b.origin.y;
if overlap_x && overlap_y {
return Err(crate::error::DisplayError::ConfigurationRejected);
}
}
}
}
Ok(())
}
impl OverlapCheckable for (bool, Rect) {
fn is_enabled(&self) -> bool {
self.0
}
fn geometry(&self) -> Rect {
self.1
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::{Extent2D, Point2D};
#[test]
fn no_overlap() {
let outputs = vec![
(
true,
Rect {
origin: Point2D { x: 0, y: 0 },
size: Extent2D {
width: 1920,
height: 1080,
},
},
),
(
true,
Rect {
origin: Point2D { x: 1920, y: 0 },
size: Extent2D {
width: 1920,
height: 1080,
},
},
),
];
assert!(check_overlap(&outputs).is_ok());
}
#[test]
fn overlapping_detected() {
let outputs = vec![
(
true,
Rect {
origin: Point2D { x: 0, y: 0 },
size: Extent2D {
width: 1920,
height: 1080,
},
},
),
(
true,
Rect {
origin: Point2D { x: 500, y: 500 },
size: Extent2D {
width: 1920,
height: 1080,
},
},
),
];
assert!(check_overlap(&outputs).is_err());
}
#[test]
fn disabled_ignored() {
let outputs = vec![
(
true,
Rect {
origin: Point2D { x: 0, y: 0 },
size: Extent2D {
width: 1920,
height: 1080,
},
},
),
(
false,
Rect {
origin: Point2D { x: 0, y: 0 },
size: Extent2D {
width: 1920,
height: 1080,
},
},
),
];
assert!(check_overlap(&outputs).is_ok());
}
#[test]
fn empty_slice() {
let outputs: Vec<(bool, Rect)> = vec![];
assert!(check_overlap(&outputs).is_ok());
}
}