diff --git a/komorebi-core/src/arrangement.rs b/komorebi-core/src/arrangement.rs index 2cb8608a..3189646a 100644 --- a/komorebi-core/src/arrangement.rs +++ b/komorebi-core/src/arrangement.rs @@ -44,8 +44,54 @@ impl Arrangement for DefaultLayout { layout_flip, calculate_resize_adjustments(resize_dimensions), ), - Self::Columns => columns(area, len), - Self::Rows => rows(area, len), + Self::Columns => { + let mut layouts = columns(area, len); + + let adjustment = calculate_columns_adjustment(resize_dimensions); + layouts + .iter_mut() + .zip(adjustment.iter()) + .for_each(|(layout, adjustment)| { + layout.top += adjustment.top; + layout.bottom += adjustment.bottom; + layout.left += adjustment.left; + layout.right += adjustment.right; + }); + + match layout_flip { + Some(Axis::Horizontal | Axis::HorizontalAndVertical) => match len { + 2.. => columns_reverse(&mut layouts), + _ => {} + }, + _ => {} + } + + layouts + } + Self::Rows => { + let mut layouts = rows(area, len); + + let adjustment = calculate_rows_adjustment(resize_dimensions); + layouts + .iter_mut() + .zip(adjustment.iter()) + .for_each(|(layout, adjustment)| { + layout.top += adjustment.top; + layout.bottom += adjustment.bottom; + layout.left += adjustment.left; + layout.right += adjustment.right; + }); + + match layout_flip { + Some(Axis::Vertical | Axis::HorizontalAndVertical) => match len { + 2.. => rows_reverse(&mut layouts), + _ => {} + }, + _ => {} + } + + layouts + } Self::VerticalStack => { let mut layouts: Vec = vec![]; @@ -89,6 +135,30 @@ impl Arrangement for DefaultLayout { layout.right += adjustment.right; }); + match layout_flip { + Some(Axis::Horizontal | Axis::HorizontalAndVertical) => match len { + 2.. => { + let (primary, rest) = layouts.split_at_mut(1); + let primary = &mut primary[0]; + + for rect in rest.iter_mut() { + rect.left = primary.left; + } + primary.left = rest[0].left + rest[0].right; + } + _ => {} + }, + _ => {} + } + + match layout_flip { + Some(Axis::Vertical | Axis::HorizontalAndVertical) => match len { + 3.. => rows_reverse(&mut layouts[1..]), + _ => {} + }, + _ => {} + } + layouts } Self::RightMainVerticalStack => { @@ -137,6 +207,30 @@ impl Arrangement for DefaultLayout { layout.right += adjustment.right; }); + match layout_flip { + Some(Axis::Horizontal | Axis::HorizontalAndVertical) => match len { + 2.. => { + let (primary, rest) = layouts.split_at_mut(1); + let primary = &mut primary[0]; + + primary.left = rest[0].left; + for rect in rest.iter_mut() { + rect.left = primary.left + primary.right; + } + } + _ => {} + }, + _ => {} + } + + match layout_flip { + Some(Axis::Vertical | Axis::HorizontalAndVertical) => match len { + 3.. => rows_reverse(&mut layouts[1..]), + _ => {} + }, + _ => {} + } + layouts } Self::HorizontalStack => { @@ -147,16 +241,8 @@ impl Arrangement for DefaultLayout { _ => area.bottom / 2, }; - let mut main_top = area.top; - let mut stack_top = area.top + bottom; - - match layout_flip { - Some(Axis::Vertical | Axis::HorizontalAndVertical) if len > 1 => { - main_top = main_top + area.bottom - bottom; - stack_top = area.top; - } - _ => {} - } + let main_top = area.top; + let stack_top = area.top + bottom; if len >= 1 { layouts.push(Rect { @@ -179,9 +265,152 @@ impl Arrangement for DefaultLayout { } } + let adjustment = calculate_horizontal_stack_adjustment(resize_dimensions); + layouts + .iter_mut() + .zip(adjustment.iter()) + .for_each(|(layout, adjustment)| { + layout.top += adjustment.top; + layout.bottom += adjustment.bottom; + layout.left += adjustment.left; + layout.right += adjustment.right; + }); + + match layout_flip { + Some(Axis::Vertical | Axis::HorizontalAndVertical) => match len { + 2.. => { + let (primary, rest) = layouts.split_at_mut(1); + let primary = &mut primary[0]; + + for rect in rest.iter_mut() { + rect.top = primary.top; + } + primary.top = rest[0].top + rest[0].bottom; + } + _ => {} + }, + _ => {} + } + + match layout_flip { + Some(Axis::Horizontal | Axis::HorizontalAndVertical) => match len { + 3.. => columns_reverse(&mut layouts[1..]), + _ => {} + }, + _ => {} + } + layouts } - Self::UltrawideVerticalStack => ultrawide(area, len, layout_flip, resize_dimensions), + Self::UltrawideVerticalStack => { + let mut layouts: Vec = vec![]; + + let primary_right = match len { + 1 => area.right, + _ => area.right / 2, + }; + + let secondary_right = match len { + 1 => 0, + 2 => area.right - primary_right, + _ => (area.right - primary_right) / 2, + }; + + let (primary_left, secondary_left, stack_left) = match len { + 1 => (area.left, 0, 0), + 2 => { + let primary = area.left + secondary_right; + let secondary = area.left; + + (primary, secondary, 0) + } + _ => { + let primary = area.left + secondary_right; + let secondary = area.left; + let stack = area.left + primary_right + secondary_right; + + (primary, secondary, stack) + } + }; + + if len >= 1 { + layouts.push(Rect { + left: primary_left, + top: area.top, + right: primary_right, + bottom: area.bottom, + }); + + if len >= 2 { + layouts.push(Rect { + left: secondary_left, + top: area.top, + right: secondary_right, + bottom: area.bottom, + }); + + if len > 2 { + layouts.append(&mut rows( + &Rect { + left: stack_left, + top: area.top, + right: secondary_right, + bottom: area.bottom, + }, + len - 2, + )); + } + } + } + + let adjustment = calculate_ultrawide_adjustment(resize_dimensions); + layouts + .iter_mut() + .zip(adjustment.iter()) + .for_each(|(layout, adjustment)| { + layout.top += adjustment.top; + layout.bottom += adjustment.bottom; + layout.left += adjustment.left; + layout.right += adjustment.right; + }); + + match layout_flip { + Some(Axis::Horizontal | Axis::HorizontalAndVertical) => match len { + 2 => { + let (primary, secondary) = layouts.split_at_mut(1); + let primary = &mut primary[0]; + let secondary = &mut secondary[0]; + + primary.left = secondary.left; + secondary.left = primary.left + primary.right; + } + 3.. => { + let (primary, rest) = layouts.split_at_mut(1); + let (secondary, tertiary) = rest.split_at_mut(1); + let primary = &mut primary[0]; + let secondary = &mut secondary[0]; + + for rect in tertiary.iter_mut() { + rect.left = secondary.left; + } + primary.left = tertiary[0].left + tertiary[0].right; + secondary.left = primary.left + primary.right; + } + _ => {} + }, + _ => {} + } + + match layout_flip { + Some(Axis::Vertical | Axis::HorizontalAndVertical) => match len { + 4.. => rows_reverse(&mut layouts[2..]), + _ => {} + }, + _ => {} + } + + layouts + }, #[allow( clippy::cast_precision_loss, clippy::cast_possible_truncation, @@ -420,6 +649,22 @@ fn rows(area: &Rect, len: usize) -> Vec { layouts } +fn columns_reverse(columns: &mut [Rect]) { + let len = columns.len(); + columns[len - 1].left = columns[0].left; + for i in (0..len - 1).rev() { + columns[i].left = columns[i + 1].left + columns[i + 1].right; + } +} + +fn rows_reverse(rows: &mut [Rect]) { + let len = rows.len(); + rows[len - 1].top = rows[0].top; + for i in (0..len - 1).rev() { + rows[i].top = rows[i + 1].top + rows[i + 1].bottom; + } +} + fn calculate_resize_adjustments(resize_dimensions: &[Option]) -> Vec> { let mut resize_adjustments = resize_dimensions.to_vec(); @@ -613,6 +858,56 @@ fn recursive_fibonacci( } } +fn calculate_columns_adjustment(resize_dimensions: &[Option]) -> Vec { + let len = resize_dimensions.len(); + let mut result = vec![Rect::default(); len]; + match len { + 0 | 1 => (), + _ => { + for (i, rect) in resize_dimensions.iter().enumerate() { + if let Some(rect) = rect { + if i != 0 { + resize_right(&mut result[i - 1], rect.left); + resize_left(&mut result[i], rect.left); + } + + if i != len - 1 { + resize_right(&mut result[i], rect.right); + resize_left(&mut result[i + 1], rect.right); + } + } + } + } + }; + + result +} + +fn calculate_rows_adjustment(resize_dimensions: &[Option]) -> Vec { + let len = resize_dimensions.len(); + let mut result = vec![Rect::default(); len]; + match len { + 0 | 1 => (), + _ => { + for (i, rect) in resize_dimensions.iter().enumerate() { + if let Some(rect) = rect { + if i != 0 { + resize_bottom(&mut result[i - 1], rect.top); + resize_top(&mut result[i], rect.top); + } + + if i != len - 1 { + resize_bottom(&mut result[i], rect.bottom); + resize_top(&mut result[i + 1], rect.bottom); + } + } + } + } + }; + + result +} + fn calculate_vertical_stack_adjustment(resize_dimensions: &[Option]) -> Vec { let len = resize_dimensions.len(); let mut result = vec![Rect::default(); len]; @@ -705,6 +1000,45 @@ fn calculate_right_vertical_stack_adjustment(resize_dimensions: &[Option]) result } +fn calculate_horizontal_stack_adjustment(resize_dimensions: &[Option]) -> Vec { + let len = resize_dimensions.len(); + let mut result = vec![Rect::default(); len]; + match len { + 0 | 1 => (), + _ => { + let (primary, rest) = result.split_at_mut(1); + let primary = &mut primary[0]; + if let Some(resize_primary) = resize_dimensions[0] { + resize_bottom(primary, resize_primary.bottom); + + for horizontal_element in &mut *rest { + resize_top(horizontal_element, resize_primary.bottom); + } + } + + for (i, rect) in resize_dimensions[1..].iter().enumerate() { + if let Some(rect) = rect { + resize_bottom(primary, rect.top); + rest.iter_mut() + .for_each(|vertical_element| resize_top(vertical_element, rect.top)); + + if i != 0 { + resize_right(&mut rest[i - 1], rect.left); + resize_left(&mut rest[i], rect.left); + } + + if i != rest.len() - 1 { + resize_right(&mut rest[i], rect.right); + resize_left(&mut rest[i + 1], rect.right); + } + } + } + } + }; + + result +} + fn calculate_ultrawide_adjustment(resize_dimensions: &[Option]) -> Vec { let len = resize_dimensions.len(); let mut result = vec![Rect::default(); len]; @@ -795,99 +1129,3 @@ fn resize_top(rect: &mut Rect, resize: i32) { fn resize_bottom(rect: &mut Rect, resize: i32) { rect.bottom += resize / 2; } - -fn ultrawide( - area: &Rect, - len: usize, - layout_flip: Option, - resize_dimensions: &[Option], -) -> Vec { - let mut layouts: Vec = vec![]; - - let primary_right = match len { - 1 => area.right, - _ => area.right / 2, - }; - - let secondary_right = match len { - 1 => 0, - 2 => area.right - primary_right, - _ => (area.right - primary_right) / 2, - }; - - let (primary_left, secondary_left, stack_left) = match len { - 1 => (area.left, 0, 0), - 2 => { - let mut primary = area.left + secondary_right; - let mut secondary = area.left; - - match layout_flip { - Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => { - primary = area.left; - secondary = area.left + primary_right; - } - _ => {} - } - - (primary, secondary, 0) - } - _ => { - let primary = area.left + secondary_right; - let mut secondary = area.left; - let mut stack = area.left + primary_right + secondary_right; - - match layout_flip { - Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => { - secondary = area.left + primary_right + secondary_right; - stack = area.left; - } - _ => {} - } - - (primary, secondary, stack) - } - }; - - if len >= 1 { - layouts.push(Rect { - left: primary_left, - top: area.top, - right: primary_right, - bottom: area.bottom, - }); - - if len >= 2 { - layouts.push(Rect { - left: secondary_left, - top: area.top, - right: secondary_right, - bottom: area.bottom, - }); - - if len > 2 { - layouts.append(&mut rows( - &Rect { - left: stack_left, - top: area.top, - right: secondary_right, - bottom: area.bottom, - }, - len - 2, - )); - } - } - } - - let adjustment = calculate_ultrawide_adjustment(resize_dimensions); - layouts - .iter_mut() - .zip(adjustment.iter()) - .for_each(|(layout, adjustment)| { - layout.top += adjustment.top; - layout.bottom += adjustment.bottom; - layout.left += adjustment.left; - layout.right += adjustment.right; - }); - - layouts -} diff --git a/komorebi-core/src/default_layout.rs b/komorebi-core/src/default_layout.rs index 54d15c67..acb2a450 100644 --- a/komorebi-core/src/default_layout.rs +++ b/komorebi-core/src/default_layout.rs @@ -48,9 +48,12 @@ impl DefaultLayout { if !matches!( self, Self::BSP - | Self::UltrawideVerticalStack + | Self::Columns + | Self::Rows | Self::VerticalStack | Self::RightMainVerticalStack + | Self::HorizontalStack + | Self::UltrawideVerticalStack ) { return None; }; diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index 6f5d64dc..1fb139a1 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -898,11 +898,16 @@ impl Workspace { fn enforce_resize_constraints(&mut self) { match self.layout { Layout::Default(DefaultLayout::BSP) => self.enforce_resize_constraints_for_bsp(), + Layout::Default(DefaultLayout::Columns) => self.enforce_resize_for_columns(), + Layout::Default(DefaultLayout::Rows) => self.enforce_resize_for_rows(), Layout::Default(DefaultLayout::VerticalStack) => { - self.enforce_resize_for_vertical_stack() + self.enforce_resize_for_vertical_stack(); } Layout::Default(DefaultLayout::RightMainVerticalStack) => { - self.enforce_resize_for_right_vertical_stack() + self.enforce_resize_for_right_vertical_stack(); + } + Layout::Default(DefaultLayout::HorizontalStack) => { + self.enforce_resize_for_horizontal_stack(); } Layout::Default(DefaultLayout::UltrawideVerticalStack) => { self.enforce_resize_for_ultrawide(); @@ -937,6 +942,52 @@ impl Workspace { } } + fn enforce_resize_for_columns(&mut self) { + let resize_dimensions = self.resize_dimensions_mut(); + match resize_dimensions.len() { + 0 | 1 => self.enforce_no_resize(), + _ => { + let len = resize_dimensions.len(); + for (i, rect) in resize_dimensions.iter_mut().enumerate() { + if let Some(rect) = rect { + rect.top = 0; + rect.bottom = 0; + + if i == 0 { + rect.left = 0; + } + if i == len - 1 { + rect.right = 0; + } + } + } + } + } + } + + fn enforce_resize_for_rows(&mut self) { + let resize_dimensions = self.resize_dimensions_mut(); + match resize_dimensions.len() { + 0 | 1 => self.enforce_no_resize(), + _ => { + let len = resize_dimensions.len(); + for (i, rect) in resize_dimensions.iter_mut().enumerate() { + if let Some(rect) = rect { + rect.left = 0; + rect.right = 0; + + if i == 0 { + rect.top = 0; + } + if i == len - 1 { + rect.bottom = 0; + } + } + } + } + } + } + fn enforce_resize_for_vertical_stack(&mut self) { let resize_dimensions = self.resize_dimensions_mut(); match resize_dimensions.len() { @@ -1003,6 +1054,34 @@ impl Workspace { } } + fn enforce_resize_for_horizontal_stack(&mut self) { + let resize_dimensions = self.resize_dimensions_mut(); + match resize_dimensions.len() { + 0 | 1 => self.enforce_no_resize(), + _ => { + if let Some(mut left) = resize_dimensions[0] { + left.top = 0; + left.left = 0; + left.right = 0; + } + + let stack_size = resize_dimensions[1..].len(); + for (i, rect) in resize_dimensions[1..].iter_mut().enumerate() { + if let Some(rect) = rect { + rect.bottom = 0; + + if i == 0 { + rect.left = 0; + } + if i == stack_size - 1 { + rect.right = 0; + } + } + } + } + } + } + fn enforce_resize_for_ultrawide(&mut self) { let resize_dimensions = self.resize_dimensions_mut(); match resize_dimensions.len() {