leftwm_layouts/geometry/
rotation.rs1use serde::{Deserialize, Serialize};
2
3use super::Rect;
4
5#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7pub enum Rotation {
8 #[default]
21 North,
22
23 East,
35
36 South,
48
49 West,
61}
62
63impl Rotation {
64 pub fn aspect_ratio_changes(&self, rect: &Rect) -> bool {
67 rect.h != rect.w && matches!(self, Self::West | Self::East)
70 }
71
72 pub fn next_anchor(&self, rect: &Rect) -> (i32, i32) {
81 match self {
82 Self::North => (rect.x, rect.y),
84 Self::East => (rect.x, rect.y + rect.h as i32),
86 Self::South => (rect.x + rect.w as i32, rect.y + rect.h as i32),
88 Self::West => (rect.x + rect.w as i32, rect.y),
90 }
91 }
92
93 #[must_use]
95 pub fn clockwise(&self) -> Self {
96 match self {
97 Rotation::North => Rotation::East,
98 Rotation::East => Rotation::South,
99 Rotation::South => Rotation::West,
100 Rotation::West => Rotation::North,
101 }
102 }
103
104 #[must_use]
106 pub fn counter_clockwise(&self) -> Self {
107 match self {
108 Rotation::North => Rotation::West,
109 Rotation::West => Rotation::South,
110 Rotation::South => Rotation::East,
111 Rotation::East => Rotation::North,
112 }
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::Rotation;
119 use crate::geometry::Rect;
120
121 const SQUARE: Rect = Rect {
122 x: 0,
123 y: 0,
124 w: 200,
125 h: 200,
126 };
127
128 const RECTANGLE: Rect = Rect {
129 x: 0,
130 y: 0,
131 w: 400,
132 h: 200,
133 };
134
135 #[test]
136 fn square_never_changes_aspect_ratio() {
137 let rotations = vec![
138 Rotation::North,
139 Rotation::East,
140 Rotation::South,
141 Rotation::West,
142 ];
143 for rotation in rotations {
144 assert!(!rotation.aspect_ratio_changes(&SQUARE));
145 }
146 }
147
148 #[test]
149 fn non_square_changes_aspect_ratio_east_west() {
150 assert!(Rotation::East.aspect_ratio_changes(&RECTANGLE));
151 assert!(Rotation::West.aspect_ratio_changes(&RECTANGLE));
152 }
153
154 #[test]
155 fn non_square_doesnt_change_aspect_ratio_north_south() {
156 assert!(!Rotation::North.aspect_ratio_changes(&RECTANGLE));
157 assert!(!Rotation::South.aspect_ratio_changes(&RECTANGLE));
158 }
159
160 #[test]
161 fn calc_anchor_north() {
162 let rect = Rect::new(0, 0, 1920, 1080);
163 let anchor = Rotation::North.next_anchor(&rect);
164 assert_eq!(anchor, (0, 0));
165 }
166
167 #[test]
168 fn calc_anchor_east() {
169 let rect = Rect::new(0, 0, 1920, 1080);
170 let anchor = Rotation::East.next_anchor(&rect);
171 assert_eq!(anchor, (0, 1080));
172 }
173
174 #[test]
175 fn calc_anchor_south() {
176 let rect = Rect::new(0, 0, 1920, 1080);
177 let anchor = Rotation::South.next_anchor(&rect);
178 assert_eq!(anchor, (1920, 1080));
179 }
180
181 #[test]
182 fn calc_anchor_west() {
183 let rect = Rect::new(0, 0, 1920, 1080);
184 let anchor = Rotation::West.next_anchor(&rect);
185 assert_eq!(anchor, (1920, 0));
186 }
187}