mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-07-11 07:32:51 +02:00
feat(wm): add opt to constrain grid layout by rows
This commit adds a new LayoutOptions option, GridLayoutOptions, currently with a single configurable "rows" opt which can be use to constrain the grid by number of rows.
This commit is contained in:
@@ -542,14 +542,25 @@ impl Arrangement for DefaultLayout {
|
|||||||
|
|
||||||
let len = len as i32;
|
let len = len as i32;
|
||||||
|
|
||||||
let num_cols = (len as f32).sqrt().ceil() as i32;
|
let row_constraint = layout_options.and_then(|o| o.grid.map(|g| g.rows));
|
||||||
|
let num_cols = if let Some(rows) = row_constraint {
|
||||||
|
((len as f32) / (rows as f32)).ceil() as i32
|
||||||
|
} else {
|
||||||
|
(len as f32).sqrt().ceil() as i32
|
||||||
|
};
|
||||||
|
|
||||||
let mut iter = layouts.iter_mut().enumerate().peekable();
|
let mut iter = layouts.iter_mut().enumerate().peekable();
|
||||||
|
|
||||||
for col in 0..num_cols {
|
for col in 0..num_cols {
|
||||||
let iter_peek = iter.peek().map(|x| x.0).unwrap_or_default() as i32;
|
let iter_peek = iter.peek().map(|x| x.0).unwrap_or_default() as i32;
|
||||||
let remaining_windows = len - iter_peek;
|
let remaining_windows = len - iter_peek;
|
||||||
let remaining_columns = num_cols - col;
|
let remaining_columns = num_cols - col;
|
||||||
let num_rows_in_this_col = remaining_windows / remaining_columns;
|
|
||||||
|
let num_rows_in_this_col = if let Some(rows) = row_constraint {
|
||||||
|
(remaining_windows / remaining_columns).min(rows as i32)
|
||||||
|
} else {
|
||||||
|
remaining_windows / remaining_columns
|
||||||
|
};
|
||||||
|
|
||||||
let win_height = area.bottom / num_rows_in_this_col;
|
let win_height = area.bottom / num_rows_in_this_col;
|
||||||
let win_width = area.right / num_cols;
|
let win_width = area.right / num_cols;
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ pub enum DefaultLayout {
|
|||||||
pub struct LayoutOptions {
|
pub struct LayoutOptions {
|
||||||
/// Options related to the Scrolling layout
|
/// Options related to the Scrolling layout
|
||||||
pub scrolling: Option<ScrollingLayoutOptions>,
|
pub scrolling: Option<ScrollingLayoutOptions>,
|
||||||
|
/// Options related to the Grid layout
|
||||||
|
pub grid: Option<GridLayoutOptions>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
@@ -41,6 +43,13 @@ pub struct ScrollingLayoutOptions {
|
|||||||
pub center_focused_column: Option<bool>,
|
pub center_focused_column: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
|
pub struct GridLayoutOptions {
|
||||||
|
/// Maximum number of rows per grid column
|
||||||
|
pub rows: usize,
|
||||||
|
}
|
||||||
|
|
||||||
impl DefaultLayout {
|
impl DefaultLayout {
|
||||||
pub fn leftmost_index(&self, len: usize) -> usize {
|
pub fn leftmost_index(&self, len: usize) -> usize {
|
||||||
match self {
|
match self {
|
||||||
|
|||||||
+102
-36
@@ -4,6 +4,7 @@ use super::custom_layout::Column;
|
|||||||
use super::custom_layout::ColumnSplit;
|
use super::custom_layout::ColumnSplit;
|
||||||
use super::custom_layout::ColumnSplitWithCapacity;
|
use super::custom_layout::ColumnSplitWithCapacity;
|
||||||
use super::custom_layout::CustomLayout;
|
use super::custom_layout::CustomLayout;
|
||||||
|
use crate::default_layout::LayoutOptions;
|
||||||
|
|
||||||
pub trait Direction {
|
pub trait Direction {
|
||||||
fn index_in_direction(
|
fn index_in_direction(
|
||||||
@@ -11,6 +12,7 @@ pub trait Direction {
|
|||||||
op_direction: OperationDirection,
|
op_direction: OperationDirection,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: usize,
|
count: usize,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> Option<usize>;
|
) -> Option<usize>;
|
||||||
|
|
||||||
fn is_valid_direction(
|
fn is_valid_direction(
|
||||||
@@ -18,30 +20,35 @@ pub trait Direction {
|
|||||||
op_direction: OperationDirection,
|
op_direction: OperationDirection,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: usize,
|
count: usize,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> bool;
|
) -> bool;
|
||||||
fn up_index(
|
fn up_index(
|
||||||
&self,
|
&self,
|
||||||
op_direction: Option<OperationDirection>,
|
op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: Option<usize>,
|
count: Option<usize>,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> usize;
|
) -> usize;
|
||||||
fn down_index(
|
fn down_index(
|
||||||
&self,
|
&self,
|
||||||
op_direction: Option<OperationDirection>,
|
op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: Option<usize>,
|
count: Option<usize>,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> usize;
|
) -> usize;
|
||||||
fn left_index(
|
fn left_index(
|
||||||
&self,
|
&self,
|
||||||
op_direction: Option<OperationDirection>,
|
op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: Option<usize>,
|
count: Option<usize>,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> usize;
|
) -> usize;
|
||||||
fn right_index(
|
fn right_index(
|
||||||
&self,
|
&self,
|
||||||
op_direction: Option<OperationDirection>,
|
op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: Option<usize>,
|
count: Option<usize>,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> usize;
|
) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,32 +58,53 @@ impl Direction for DefaultLayout {
|
|||||||
op_direction: OperationDirection,
|
op_direction: OperationDirection,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: usize,
|
count: usize,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> Option<usize> {
|
) -> Option<usize> {
|
||||||
match op_direction {
|
match op_direction {
|
||||||
OperationDirection::Left => {
|
OperationDirection::Left => {
|
||||||
if self.is_valid_direction(op_direction, idx, count) {
|
if self.is_valid_direction(op_direction, idx, count, layout_options) {
|
||||||
Option::from(self.left_index(Some(op_direction), idx, Some(count)))
|
Option::from(self.left_index(
|
||||||
|
Some(op_direction),
|
||||||
|
idx,
|
||||||
|
Some(count),
|
||||||
|
layout_options,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OperationDirection::Right => {
|
OperationDirection::Right => {
|
||||||
if self.is_valid_direction(op_direction, idx, count) {
|
if self.is_valid_direction(op_direction, idx, count, layout_options) {
|
||||||
Option::from(self.right_index(Some(op_direction), idx, Some(count)))
|
Option::from(self.right_index(
|
||||||
|
Some(op_direction),
|
||||||
|
idx,
|
||||||
|
Some(count),
|
||||||
|
layout_options,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OperationDirection::Up => {
|
OperationDirection::Up => {
|
||||||
if self.is_valid_direction(op_direction, idx, count) {
|
if self.is_valid_direction(op_direction, idx, count, layout_options) {
|
||||||
Option::from(self.up_index(Some(op_direction), idx, Some(count)))
|
Option::from(self.up_index(
|
||||||
|
Some(op_direction),
|
||||||
|
idx,
|
||||||
|
Some(count),
|
||||||
|
layout_options,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OperationDirection::Down => {
|
OperationDirection::Down => {
|
||||||
if self.is_valid_direction(op_direction, idx, count) {
|
if self.is_valid_direction(op_direction, idx, count, layout_options) {
|
||||||
Option::from(self.down_index(Some(op_direction), idx, Some(count)))
|
Option::from(self.down_index(
|
||||||
|
Some(op_direction),
|
||||||
|
idx,
|
||||||
|
Some(count),
|
||||||
|
layout_options,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -89,6 +117,7 @@ impl Direction for DefaultLayout {
|
|||||||
op_direction: OperationDirection,
|
op_direction: OperationDirection,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: usize,
|
count: usize,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if count < 2 {
|
if count < 2 {
|
||||||
return false;
|
return false;
|
||||||
@@ -101,7 +130,7 @@ impl Direction for DefaultLayout {
|
|||||||
Self::Rows | Self::HorizontalStack => idx != 0,
|
Self::Rows | Self::HorizontalStack => idx != 0,
|
||||||
Self::VerticalStack | Self::RightMainVerticalStack => idx != 0 && idx != 1,
|
Self::VerticalStack | Self::RightMainVerticalStack => idx != 0 && idx != 1,
|
||||||
Self::UltrawideVerticalStack => idx > 2,
|
Self::UltrawideVerticalStack => idx > 2,
|
||||||
Self::Grid => !is_grid_edge(op_direction, idx, count),
|
Self::Grid => !is_grid_edge(op_direction, idx, count, layout_options),
|
||||||
Self::Scrolling => false,
|
Self::Scrolling => false,
|
||||||
},
|
},
|
||||||
OperationDirection::Down => match self {
|
OperationDirection::Down => match self {
|
||||||
@@ -111,7 +140,7 @@ impl Direction for DefaultLayout {
|
|||||||
Self::VerticalStack | Self::RightMainVerticalStack => idx != 0 && idx != count - 1,
|
Self::VerticalStack | Self::RightMainVerticalStack => idx != 0 && idx != count - 1,
|
||||||
Self::HorizontalStack => idx == 0,
|
Self::HorizontalStack => idx == 0,
|
||||||
Self::UltrawideVerticalStack => idx > 1 && idx != count - 1,
|
Self::UltrawideVerticalStack => idx > 1 && idx != count - 1,
|
||||||
Self::Grid => !is_grid_edge(op_direction, idx, count),
|
Self::Grid => !is_grid_edge(op_direction, idx, count, layout_options),
|
||||||
Self::Scrolling => false,
|
Self::Scrolling => false,
|
||||||
},
|
},
|
||||||
OperationDirection::Left => match self {
|
OperationDirection::Left => match self {
|
||||||
@@ -121,7 +150,7 @@ impl Direction for DefaultLayout {
|
|||||||
Self::Rows => false,
|
Self::Rows => false,
|
||||||
Self::HorizontalStack => idx != 0 && idx != 1,
|
Self::HorizontalStack => idx != 0 && idx != 1,
|
||||||
Self::UltrawideVerticalStack => idx != 1,
|
Self::UltrawideVerticalStack => idx != 1,
|
||||||
Self::Grid => !is_grid_edge(op_direction, idx, count),
|
Self::Grid => !is_grid_edge(op_direction, idx, count, layout_options),
|
||||||
Self::Scrolling => idx != 0,
|
Self::Scrolling => idx != 0,
|
||||||
},
|
},
|
||||||
OperationDirection::Right => match self {
|
OperationDirection::Right => match self {
|
||||||
@@ -135,7 +164,7 @@ impl Direction for DefaultLayout {
|
|||||||
2 => idx != 0,
|
2 => idx != 0,
|
||||||
_ => idx < 2,
|
_ => idx < 2,
|
||||||
},
|
},
|
||||||
Self::Grid => !is_grid_edge(op_direction, idx, count),
|
Self::Grid => !is_grid_edge(op_direction, idx, count, layout_options),
|
||||||
Self::Scrolling => idx != count - 1,
|
Self::Scrolling => idx != count - 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -146,6 +175,7 @@ impl Direction for DefaultLayout {
|
|||||||
op_direction: Option<OperationDirection>,
|
op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: Option<usize>,
|
count: Option<usize>,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Self::BSP => {
|
Self::BSP => {
|
||||||
@@ -161,7 +191,7 @@ impl Direction for DefaultLayout {
|
|||||||
| Self::UltrawideVerticalStack
|
| Self::UltrawideVerticalStack
|
||||||
| Self::RightMainVerticalStack => idx - 1,
|
| Self::RightMainVerticalStack => idx - 1,
|
||||||
Self::HorizontalStack => 0,
|
Self::HorizontalStack => 0,
|
||||||
Self::Grid => grid_neighbor(op_direction, idx, count),
|
Self::Grid => grid_neighbor(op_direction, idx, count, layout_options),
|
||||||
Self::Scrolling => unreachable!(),
|
Self::Scrolling => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,6 +201,7 @@ impl Direction for DefaultLayout {
|
|||||||
op_direction: Option<OperationDirection>,
|
op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: Option<usize>,
|
count: Option<usize>,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Self::BSP
|
Self::BSP
|
||||||
@@ -180,7 +211,7 @@ impl Direction for DefaultLayout {
|
|||||||
| Self::RightMainVerticalStack => idx + 1,
|
| Self::RightMainVerticalStack => idx + 1,
|
||||||
Self::Columns => unreachable!(),
|
Self::Columns => unreachable!(),
|
||||||
Self::HorizontalStack => 1,
|
Self::HorizontalStack => 1,
|
||||||
Self::Grid => grid_neighbor(op_direction, idx, count),
|
Self::Grid => grid_neighbor(op_direction, idx, count, layout_options),
|
||||||
Self::Scrolling => unreachable!(),
|
Self::Scrolling => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,6 +221,7 @@ impl Direction for DefaultLayout {
|
|||||||
op_direction: Option<OperationDirection>,
|
op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: Option<usize>,
|
count: Option<usize>,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Self::BSP => {
|
Self::BSP => {
|
||||||
@@ -208,7 +240,7 @@ impl Direction for DefaultLayout {
|
|||||||
1 => unreachable!(),
|
1 => unreachable!(),
|
||||||
_ => 0,
|
_ => 0,
|
||||||
},
|
},
|
||||||
Self::Grid => grid_neighbor(op_direction, idx, count),
|
Self::Grid => grid_neighbor(op_direction, idx, count, layout_options),
|
||||||
Self::Scrolling => idx - 1,
|
Self::Scrolling => idx - 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,6 +250,7 @@ impl Direction for DefaultLayout {
|
|||||||
op_direction: Option<OperationDirection>,
|
op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: Option<usize>,
|
count: Option<usize>,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Self::BSP | Self::Columns | Self::HorizontalStack => idx + 1,
|
Self::BSP | Self::Columns | Self::HorizontalStack => idx + 1,
|
||||||
@@ -229,7 +262,7 @@ impl Direction for DefaultLayout {
|
|||||||
0 => 2,
|
0 => 2,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
Self::Grid => grid_neighbor(op_direction, idx, count),
|
Self::Grid => grid_neighbor(op_direction, idx, count, layout_options),
|
||||||
Self::Scrolling => idx + 1,
|
Self::Scrolling => idx + 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,21 +293,32 @@ struct GridTouchingEdges {
|
|||||||
clippy::cast_precision_loss,
|
clippy::cast_precision_loss,
|
||||||
clippy::cast_sign_loss
|
clippy::cast_sign_loss
|
||||||
)]
|
)]
|
||||||
fn get_grid_item(idx: usize, count: usize) -> GridItem {
|
fn get_grid_item(idx: usize, count: usize, layout_options: Option<LayoutOptions>) -> GridItem {
|
||||||
let num_cols = (count as f32).sqrt().ceil() as usize;
|
let row_constraint = layout_options.and_then(|o| o.grid.map(|g| g.rows));
|
||||||
|
let num_cols = if let Some(rows) = row_constraint {
|
||||||
|
((count as f32) / (rows as f32)).ceil() as i32
|
||||||
|
} else {
|
||||||
|
(count as f32).sqrt().ceil() as i32
|
||||||
|
};
|
||||||
|
|
||||||
let mut iter = 0;
|
let mut iter = 0;
|
||||||
|
|
||||||
for col in 0..num_cols {
|
for col in 0..num_cols {
|
||||||
let remaining_windows = count - iter;
|
let remaining_windows = (count - iter) as i32;
|
||||||
let remaining_columns = num_cols - col;
|
let remaining_columns = num_cols - col;
|
||||||
let num_rows_in_this_col = remaining_windows / remaining_columns;
|
|
||||||
|
let num_rows_in_this_col = if let Some(rows) = row_constraint {
|
||||||
|
(remaining_windows / remaining_columns).min(rows as i32)
|
||||||
|
} else {
|
||||||
|
remaining_windows / remaining_columns
|
||||||
|
};
|
||||||
|
|
||||||
for row in 0..num_rows_in_this_col {
|
for row in 0..num_rows_in_this_col {
|
||||||
if iter == idx {
|
if iter == idx {
|
||||||
return GridItem {
|
return GridItem {
|
||||||
state: GridItemState::Valid,
|
state: GridItemState::Valid,
|
||||||
row: row + 1,
|
row: (row + 1) as usize,
|
||||||
num_rows: num_rows_in_this_col,
|
num_rows: num_rows_in_this_col as usize,
|
||||||
touching_edges: GridTouchingEdges {
|
touching_edges: GridTouchingEdges {
|
||||||
left: col == 0,
|
left: col == 0,
|
||||||
right: col == num_cols - 1,
|
right: col == num_cols - 1,
|
||||||
@@ -301,8 +345,13 @@ fn get_grid_item(idx: usize, count: usize) -> GridItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_grid_edge(op_direction: OperationDirection, idx: usize, count: usize) -> bool {
|
fn is_grid_edge(
|
||||||
let item = get_grid_item(idx, count);
|
op_direction: OperationDirection,
|
||||||
|
idx: usize,
|
||||||
|
count: usize,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
|
) -> bool {
|
||||||
|
let item = get_grid_item(idx, count, layout_options);
|
||||||
|
|
||||||
match item.state {
|
match item.state {
|
||||||
GridItemState::Invalid => false,
|
GridItemState::Invalid => false,
|
||||||
@@ -319,6 +368,7 @@ fn grid_neighbor(
|
|||||||
op_direction: Option<OperationDirection>,
|
op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: Option<usize>,
|
count: Option<usize>,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let Some(op_direction) = op_direction else {
|
let Some(op_direction) = op_direction else {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -328,11 +378,11 @@ fn grid_neighbor(
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
let item = get_grid_item(idx, count);
|
let item = get_grid_item(idx, count, layout_options);
|
||||||
|
|
||||||
match op_direction {
|
match op_direction {
|
||||||
OperationDirection::Left => {
|
OperationDirection::Left => {
|
||||||
let item_from_prev_col = get_grid_item(idx - item.row, count);
|
let item_from_prev_col = get_grid_item(idx - item.row, count, layout_options);
|
||||||
|
|
||||||
if item.touching_edges.up && item.num_rows != item_from_prev_col.num_rows {
|
if item.touching_edges.up && item.num_rows != item_from_prev_col.num_rows {
|
||||||
return idx - (item.num_rows - 1);
|
return idx - (item.num_rows - 1);
|
||||||
@@ -356,36 +406,42 @@ impl Direction for CustomLayout {
|
|||||||
op_direction: OperationDirection,
|
op_direction: OperationDirection,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: usize,
|
count: usize,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> Option<usize> {
|
) -> Option<usize> {
|
||||||
if count <= self.len() {
|
if count <= self.len() {
|
||||||
return DefaultLayout::Columns.index_in_direction(op_direction, idx, count);
|
return DefaultLayout::Columns.index_in_direction(
|
||||||
|
op_direction,
|
||||||
|
idx,
|
||||||
|
count,
|
||||||
|
layout_options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
match op_direction {
|
match op_direction {
|
||||||
OperationDirection::Left => {
|
OperationDirection::Left => {
|
||||||
if self.is_valid_direction(op_direction, idx, count) {
|
if self.is_valid_direction(op_direction, idx, count, layout_options) {
|
||||||
Option::from(self.left_index(None, idx, None))
|
Option::from(self.left_index(None, idx, None, layout_options))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OperationDirection::Right => {
|
OperationDirection::Right => {
|
||||||
if self.is_valid_direction(op_direction, idx, count) {
|
if self.is_valid_direction(op_direction, idx, count, layout_options) {
|
||||||
Option::from(self.right_index(None, idx, None))
|
Option::from(self.right_index(None, idx, None, layout_options))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OperationDirection::Up => {
|
OperationDirection::Up => {
|
||||||
if self.is_valid_direction(op_direction, idx, count) {
|
if self.is_valid_direction(op_direction, idx, count, layout_options) {
|
||||||
Option::from(self.up_index(None, idx, None))
|
Option::from(self.up_index(None, idx, None, layout_options))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OperationDirection::Down => {
|
OperationDirection::Down => {
|
||||||
if self.is_valid_direction(op_direction, idx, count) {
|
if self.is_valid_direction(op_direction, idx, count, layout_options) {
|
||||||
Option::from(self.down_index(None, idx, None))
|
Option::from(self.down_index(None, idx, None, layout_options))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -398,9 +454,15 @@ impl Direction for CustomLayout {
|
|||||||
op_direction: OperationDirection,
|
op_direction: OperationDirection,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
count: usize,
|
count: usize,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if count <= self.len() {
|
if count <= self.len() {
|
||||||
return DefaultLayout::Columns.is_valid_direction(op_direction, idx, count);
|
return DefaultLayout::Columns.is_valid_direction(
|
||||||
|
op_direction,
|
||||||
|
idx,
|
||||||
|
count,
|
||||||
|
layout_options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
match op_direction {
|
match op_direction {
|
||||||
@@ -444,6 +506,7 @@ impl Direction for CustomLayout {
|
|||||||
_op_direction: Option<OperationDirection>,
|
_op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
_count: Option<usize>,
|
_count: Option<usize>,
|
||||||
|
_layout_options: Option<LayoutOptions>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
idx - 1
|
idx - 1
|
||||||
}
|
}
|
||||||
@@ -453,6 +516,7 @@ impl Direction for CustomLayout {
|
|||||||
_op_direction: Option<OperationDirection>,
|
_op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
_count: Option<usize>,
|
_count: Option<usize>,
|
||||||
|
_layout_options: Option<LayoutOptions>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
idx + 1
|
idx + 1
|
||||||
}
|
}
|
||||||
@@ -462,6 +526,7 @@ impl Direction for CustomLayout {
|
|||||||
_op_direction: Option<OperationDirection>,
|
_op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
_count: Option<usize>,
|
_count: Option<usize>,
|
||||||
|
_layout_options: Option<LayoutOptions>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let column_idx = self.column_for_container_idx(idx);
|
let column_idx = self.column_for_container_idx(idx);
|
||||||
if column_idx - 1 == 0 {
|
if column_idx - 1 == 0 {
|
||||||
@@ -476,6 +541,7 @@ impl Direction for CustomLayout {
|
|||||||
_op_direction: Option<OperationDirection>,
|
_op_direction: Option<OperationDirection>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
_count: Option<usize>,
|
_count: Option<usize>,
|
||||||
|
_layout_options: Option<LayoutOptions>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let column_idx = self.column_for_container_idx(idx);
|
let column_idx = self.column_for_container_idx(idx);
|
||||||
self.first_container_idx(column_idx + 1)
|
self.first_container_idx(column_idx + 1)
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
|
|
||||||
|
use super::Axis;
|
||||||
|
use super::direction::Direction;
|
||||||
|
use crate::default_layout::LayoutOptions;
|
||||||
use clap::ValueEnum;
|
use clap::ValueEnum;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use strum::Display;
|
use strum::Display;
|
||||||
use strum::EnumString;
|
use strum::EnumString;
|
||||||
|
|
||||||
use super::Axis;
|
|
||||||
use super::direction::Direction;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum)]
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum)]
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
pub enum OperationDirection {
|
pub enum OperationDirection {
|
||||||
@@ -57,7 +57,8 @@ impl OperationDirection {
|
|||||||
layout_flip: Option<Axis>,
|
layout_flip: Option<Axis>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
len: NonZeroUsize,
|
len: NonZeroUsize,
|
||||||
|
layout_options: Option<LayoutOptions>,
|
||||||
) -> Option<usize> {
|
) -> Option<usize> {
|
||||||
layout.index_in_direction(self.flip(layout_flip), idx, len.get())
|
layout.index_in_direction(self.flip(layout_flip), idx, len.get(), layout_options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -923,6 +923,7 @@ impl WindowManager {
|
|||||||
columns: count.into(),
|
columns: count.into(),
|
||||||
center_focused_column: Default::default(),
|
center_focused_column: Default::default(),
|
||||||
}),
|
}),
|
||||||
|
grid: None,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1275,6 +1275,7 @@ impl WindowManager {
|
|||||||
workspace.layout_flip,
|
workspace.layout_flip,
|
||||||
focused_idx,
|
focused_idx,
|
||||||
len,
|
len,
|
||||||
|
workspace.layout_options,
|
||||||
)
|
)
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
@@ -2763,6 +2764,7 @@ impl WindowManager {
|
|||||||
workspace.layout_flip,
|
workspace.layout_flip,
|
||||||
workspace.focused_container_idx(),
|
workspace.focused_container_idx(),
|
||||||
len,
|
len,
|
||||||
|
workspace.layout_options,
|
||||||
)
|
)
|
||||||
.is_some();
|
.is_some();
|
||||||
|
|
||||||
|
|||||||
@@ -984,6 +984,7 @@ impl Workspace {
|
|||||||
self.layout_flip,
|
self.layout_flip,
|
||||||
self.focused_container_idx(),
|
self.focused_container_idx(),
|
||||||
len,
|
len,
|
||||||
|
self.layout_options,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
@@ -1807,6 +1807,21 @@
|
|||||||
"description": "Layout-specific options (default: None)",
|
"description": "Layout-specific options (default: None)",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"grid": {
|
||||||
|
"description": "Options related to the Grid layout",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"rows"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"rows": {
|
||||||
|
"description": "Maximum number of rows per grid column",
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint",
|
||||||
|
"minimum": 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"scrolling": {
|
"scrolling": {
|
||||||
"description": "Options related to the Scrolling layout",
|
"description": "Options related to the Scrolling layout",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|||||||
Reference in New Issue
Block a user