mod creation;
mod focus;
mod layout;
mod session;
mod tmux_convert;
mod tmux_layout;
mod tmux_update;
use crate::config::{Config, PaneBackgroundConfig};
use crate::pane::types::{Pane, PaneBounds, PaneId, PaneNode};
use crate::terminal::TerminalManager;
use anyhow::Result;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use tokio::runtime::Runtime;
use tokio::sync::RwLock;
pub struct PaneManager {
pub(super) root: Option<PaneNode>,
pub(super) focused_pane_id: Option<PaneId>,
pub(super) next_pane_id: PaneId,
pub(super) divider_width: f32,
pub(super) divider_hit_width: f32,
pub(super) total_bounds: PaneBounds,
}
impl PaneManager {
pub fn new() -> Self {
Self {
root: None,
focused_pane_id: None,
next_pane_id: 1,
divider_width: 1.0, divider_hit_width: 8.0, total_bounds: PaneBounds::default(),
}
}
pub fn new_with_existing_terminal(
terminal: Arc<RwLock<TerminalManager>>,
working_directory: Option<String>,
is_active: Arc<AtomicBool>,
) -> Self {
let mut manager = Self::new();
let primary_pane_id = manager.next_pane_id;
manager.next_pane_id += 1;
let pane =
Pane::new_wrapping_terminal(primary_pane_id, terminal, working_directory, is_active);
manager.root = Some(PaneNode::leaf(pane));
manager.focused_pane_id = Some(primary_pane_id);
manager
}
pub fn with_initial_pane(
config: &Config,
runtime: Arc<Runtime>,
working_directory: Option<String>,
) -> Result<Self> {
let mut manager = Self::new();
manager.divider_width = config.pane_divider_width.unwrap_or(1.0);
manager.divider_hit_width = config.pane_divider_hit_width;
manager.create_initial_pane(config, runtime, working_directory)?;
Ok(manager)
}
pub fn next_pane_id(&self) -> PaneId {
self.next_pane_id
}
pub fn get_pane(&self, id: PaneId) -> Option<&Pane> {
self.root.as_ref()?.find_pane(id)
}
pub fn get_pane_mut(&mut self, id: PaneId) -> Option<&mut Pane> {
self.root.as_mut()?.find_pane_mut(id)
}
pub fn all_panes(&self) -> Vec<&Pane> {
self.root
.as_ref()
.map(|r| r.all_panes())
.unwrap_or_default()
}
pub fn all_panes_mut(&mut self) -> Vec<&mut Pane> {
self.root
.as_mut()
.map(|r| r.all_panes_mut())
.unwrap_or_default()
}
pub fn collect_pane_backgrounds(&self) -> Vec<PaneBackgroundConfig> {
self.all_panes()
.iter()
.enumerate()
.filter_map(|(index, pane)| {
pane.background
.image_path
.as_ref()
.map(|path| PaneBackgroundConfig {
index,
image: path.clone(),
mode: pane.background.mode,
opacity: pane.background.opacity,
darken: pane.background.darken,
})
})
.collect()
}
pub fn pane_count(&self) -> usize {
self.root.as_ref().map(|r| r.pane_count()).unwrap_or(0)
}
pub fn has_multiple_panes(&self) -> bool {
self.pane_count() > 1
}
pub fn root(&self) -> Option<&PaneNode> {
self.root.as_ref()
}
pub fn root_mut(&mut self) -> Option<&mut PaneNode> {
self.root.as_mut()
}
}
impl Default for PaneManager {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pane_manager_new() {
let manager = PaneManager::new();
assert!(manager.root.is_none());
assert_eq!(manager.pane_count(), 0);
assert!(!manager.has_multiple_panes());
}
}