1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
use geometry::ColumnType;
use geometry::Rect;
use layouts::columns::{main_stack, stack, stack_main_stack};
pub use layouts::LayoutDefinition;
pub use layouts::Layouts;
pub mod geometry;
pub mod layouts;
pub fn apply(definition: LayoutDefinition, window_count: usize, container: Rect) -> Vec<Rect> {
let aspect_ratio_changes = definition.rotation.aspect_ratio_changes(&container);
// if the aspect-ratio changes with the provided rotation,
// create a new rect with a swapped aspect-ratio.
// This makes it easier to rotate the layout later.
let container = if aspect_ratio_changes {
Rect {
h: container.w,
w: container.h,
..container
}
} else {
container
};
// calculate the layout
let mut rects = match definition.column_type {
ColumnType::Stack => stack(window_count, container, &definition),
ColumnType::MainAndStack => main_stack(window_count, container, &definition),
ColumnType::CenterMain => stack_main_stack(window_count, container, &definition),
};
// flip the layout (if necessary)
geometry::flip(container, &mut rects, &definition.flipped);
// rotate the layout (if necessary)
rects
.iter_mut()
.for_each(|rect| geometry::translate_rotation(container, rect, &definition.rotation));
rects
}
#[cfg(test)]
mod tests {
/*use crate::{
apply, layouts::columns::ColumnType, LayoutDefinition, LayoutEnum, LayoutModifiers,
LayoutOptions,
};
const MAIN_STACK: LayoutDefinition = LayoutDefinition {
..Default::default()
};
const CENTER_MAIN: LayoutDefinition = LayoutDefinition {
column_type: ColumnType::CenterMain,
..Default::default()
};
const ALL_LAYOUTS: &[LayoutEnum] = &[
LayoutEnum::Monocle,
LayoutEnum::MainAndVertStack,
LayoutEnum::CenterMain,
LayoutEnum::Fibonacci,
];*/
/*#[test]
fn returned_tiles_must_never_exceed_window_count() {
let modifiers: LayoutModifiers = LayoutModifiers::default();
let options: LayoutOptions = LayoutOptions::default();
for window_count in 0..25 {
for layout in ALL_LAYOUTS {
let layout = layout.get();
let len = layout
.apply(window_count, options.container_size, &modifiers)
.len();
assert!(len <= window_count);
}
}
}*/
// todo
//fn no_overlap_of_rects() {
// todo!()
//}
/*#[test]
fn container_must_always_be_filled() {
let modifiers: LayoutModifiers = LayoutModifiers::default();
let options: LayoutOptions = LayoutOptions::default();
let container_area = options.container_size.surface_area();
for window_count in 1..10 {
for layout in ALL_LAYOUTS {
let filled_area = apply(layout, window_count, &options, &modifiers)
.into_iter()
.fold(0u32, |a, b| a + b.surface_area());
assert_eq!(container_area, filled_area);
}
}
}*/
/*#[test]
fn test_monocle_layout() {
let modifiers: LayoutModifiers = LayoutModifiers::default();
let options: LayoutOptions = LayoutOptions::default();
let monocle = LayoutEnum::Monocle.get();
let monocle_positions = monocle.apply(1, options.container_size, &modifiers);
assert_eq!(monocle_positions.len(), 1);
}*/
}