use super::PaneManager;
use crate::config::Config;
use crate::pane::types::{Pane, PaneId, PaneNode, SplitDirection};
use crate::tmux::{LayoutNode, TmuxPaneId};
use anyhow::Result;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::runtime::Runtime;
impl PaneManager {
pub(super) fn convert_layout_node(
&mut self,
node: &LayoutNode,
config: &Config,
runtime: Arc<Runtime>,
mappings: &mut HashMap<TmuxPaneId, PaneId>,
) -> Result<PaneNode> {
match node {
LayoutNode::Pane {
id: tmux_id,
width: _,
height: _,
x: _,
y: _,
} => {
let native_id = self.next_pane_id;
self.next_pane_id += 1;
let pane = Pane::new_for_tmux(native_id, config, runtime)?;
mappings.insert(*tmux_id, native_id);
log::debug!(
"Created native pane {} for tmux pane %{}",
native_id,
tmux_id
);
Ok(PaneNode::leaf(pane))
}
LayoutNode::VerticalSplit {
width,
height: _,
x: _,
y: _,
children,
} => {
self.convert_multi_split_to_binary(
children,
SplitDirection::Vertical,
*width,
config,
runtime,
mappings,
)
}
LayoutNode::HorizontalSplit {
width: _,
height,
x: _,
y: _,
children,
} => {
self.convert_multi_split_to_binary(
children,
SplitDirection::Horizontal,
*height,
config,
runtime,
mappings,
)
}
}
}
pub(super) fn convert_multi_split_to_binary(
&mut self,
children: &[LayoutNode],
direction: SplitDirection,
total_size: usize,
config: &Config,
runtime: Arc<Runtime>,
mappings: &mut HashMap<TmuxPaneId, PaneId>,
) -> Result<PaneNode> {
if children.is_empty() {
anyhow::bail!("Empty children list in tmux layout");
}
if children.len() == 1 {
return self.convert_layout_node(&children[0], config, runtime, mappings);
}
let first_size = Self::get_node_size(&children[0], direction);
let ratio = (first_size as f32) / (total_size as f32);
let first = self.convert_layout_node(&children[0], config, runtime.clone(), mappings)?;
let remaining_size = total_size.saturating_sub(first_size + 1);
let second = if children.len() == 2 {
self.convert_layout_node(&children[1], config, runtime, mappings)?
} else {
let remaining = &children[1..];
self.convert_remaining_children(
remaining,
direction,
remaining_size,
config,
runtime,
mappings,
)?
};
Ok(PaneNode::split(direction, ratio, first, second))
}
pub(super) fn convert_remaining_children(
&mut self,
children: &[LayoutNode],
direction: SplitDirection,
total_size: usize,
config: &Config,
runtime: Arc<Runtime>,
mappings: &mut HashMap<TmuxPaneId, PaneId>,
) -> Result<PaneNode> {
if children.len() == 1 {
return self.convert_layout_node(&children[0], config, runtime, mappings);
}
let first_size = Self::get_node_size(&children[0], direction);
let ratio = (first_size as f32) / (total_size as f32);
let first = self.convert_layout_node(&children[0], config, runtime.clone(), mappings)?;
let remaining_size = total_size.saturating_sub(first_size + 1);
let second = self.convert_remaining_children(
&children[1..],
direction,
remaining_size,
config,
runtime,
mappings,
)?;
Ok(PaneNode::split(direction, ratio, first, second))
}
}