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, title: String, saved: bool, } impl SplitLayout { #[must_use] pub fn new(axis: SplitAxis, panes: Vec) -> 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) { self.title = title.into(); self.saved = true; } fn pane_index(&self, tab_id: &TabId) -> Option { self.panes.iter().position(|pane| pane.tab_id() == tab_id) } }