151 lines
3.3 KiB
Rust
151 lines
3.3 KiB
Rust
use crate::{SplitId, TabId};
|
|
|
|
pub const MAX_SPLIT_PANES: usize = 4;
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub enum SplitAxis {
|
|
Horizontal,
|
|
Vertical,
|
|
Grid,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub struct SplitPane {
|
|
tab_id: TabId,
|
|
weight: u16,
|
|
}
|
|
|
|
impl SplitPane {
|
|
#[must_use]
|
|
pub fn new(tab_id: TabId, weight: u16) -> Self {
|
|
Self { tab_id, weight }
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn tab_id(&self) -> &TabId {
|
|
&self.tab_id
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn weight(&self) -> u16 {
|
|
self.weight
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub struct SplitLayout {
|
|
id: SplitId,
|
|
axis: SplitAxis,
|
|
panes: Vec<SplitPane>,
|
|
title: String,
|
|
saved: bool,
|
|
}
|
|
|
|
impl SplitLayout {
|
|
#[must_use]
|
|
pub fn new(axis: SplitAxis, panes: Vec<SplitPane>) -> Self {
|
|
Self { id: SplitId::new(), axis, panes, title: "Split View".to_string(), saved: false }
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn id(&self) -> &SplitId {
|
|
&self.id
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn axis(&self) -> &SplitAxis {
|
|
&self.axis
|
|
}
|
|
|
|
pub fn set_axis(&mut self, axis: SplitAxis) {
|
|
self.axis = axis;
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn panes(&self) -> &[SplitPane] {
|
|
&self.panes
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn title(&self) -> &str {
|
|
&self.title
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn saved(&self) -> bool {
|
|
self.saved
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn contains_tab(&self, tab_id: &TabId) -> bool {
|
|
self.panes.iter().any(|pane| pane.tab_id() == tab_id)
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn pane_count(&self) -> usize {
|
|
self.panes.len()
|
|
}
|
|
|
|
pub fn add_pane(&mut self, pane: SplitPane) -> bool {
|
|
if self.panes.len() >= MAX_SPLIT_PANES || self.contains_tab(pane.tab_id()) {
|
|
return false;
|
|
}
|
|
|
|
self.panes.push(pane);
|
|
true
|
|
}
|
|
|
|
pub fn add_pane_after_tab(&mut self, after_tab_id: &TabId, pane: SplitPane) -> bool {
|
|
if self.panes.len() >= MAX_SPLIT_PANES || self.contains_tab(pane.tab_id()) {
|
|
return false;
|
|
}
|
|
|
|
let Some(index) = self.panes.iter().position(|existing| existing.tab_id() == after_tab_id)
|
|
else {
|
|
return false;
|
|
};
|
|
|
|
self.panes.insert(index + 1, pane);
|
|
true
|
|
}
|
|
|
|
pub fn swap_tab_with_previous(&mut self, tab_id: &TabId) -> bool {
|
|
let Some(index) = self.pane_index(tab_id) else {
|
|
return false;
|
|
};
|
|
if index == 0 {
|
|
return false;
|
|
}
|
|
|
|
self.panes.swap(index - 1, index);
|
|
true
|
|
}
|
|
|
|
pub fn swap_tab_with_next(&mut self, tab_id: &TabId) -> bool {
|
|
let Some(index) = self.pane_index(tab_id) else {
|
|
return false;
|
|
};
|
|
if index + 1 >= self.panes.len() {
|
|
return false;
|
|
}
|
|
|
|
self.panes.swap(index, index + 1);
|
|
true
|
|
}
|
|
|
|
pub fn remove_tab(&mut self, tab_id: &TabId) -> bool {
|
|
let original_len = self.panes.len();
|
|
self.panes.retain(|pane| pane.tab_id() != tab_id);
|
|
self.panes.len() != original_len
|
|
}
|
|
|
|
pub fn save(&mut self, title: impl Into<String>) {
|
|
self.title = title.into();
|
|
self.saved = true;
|
|
}
|
|
|
|
fn pane_index(&self, tab_id: &TabId) -> Option<usize> {
|
|
self.panes.iter().position(|pane| pane.tab_id() == tab_id)
|
|
}
|
|
}
|