use panes::{PanelEntry, PanelId, ResolvedLayout};
use ratatui::layout::Rect;
use rustc_hash::FxHashMap;
pub fn convert(resolved: &ResolvedLayout) -> FxHashMap<PanelId, Rect> {
resolved.iter().map(|(pid, r)| (pid, quantize(r))).collect()
}
pub fn convert_at(resolved: &ResolvedLayout, origin: Rect) -> FxHashMap<PanelId, Rect> {
resolved
.iter()
.map(|(pid, r)| {
let mut rect = quantize(r);
rect.x += origin.x;
rect.y += origin.y;
(pid, rect)
})
.collect()
}
pub fn panels(resolved: &ResolvedLayout) -> impl Iterator<Item = PanelEntry<'_, Rect>> {
resolved.panels().map(|e| e.map_rect(quantize))
}
pub fn panels_at(
resolved: &ResolvedLayout,
origin: Rect,
) -> impl Iterator<Item = PanelEntry<'_, Rect>> {
resolved.panels().map(move |e| {
e.map_rect(|r| {
let mut rect = quantize(r);
rect.x += origin.x;
rect.y += origin.y;
rect
})
})
}
pub fn focused_panels<'a>(
resolved: &'a ResolvedLayout,
focused: Option<PanelId>,
) -> impl Iterator<Item = (PanelEntry<'a, Rect>, bool)> {
let focused_kind = focused.and_then(|fid| {
resolved
.kinds()
.find(|kind| resolved.by_kind(kind).contains(&fid))
});
resolved.panels().map(move |e| {
let is_focused = match (focused, focused_kind) {
(Some(fid), _) if e.id == fid => true,
(_, Some(fk)) => e
.kind
.strip_suffix("_tab")
.or_else(|| e.kind.strip_suffix("_title"))
.is_some_and(|base| base == fk),
_ => false,
};
(e.map_rect(quantize), is_focused)
})
}
pub fn focused_panels_at<'a>(
resolved: &'a ResolvedLayout,
focused: Option<PanelId>,
origin: Rect,
) -> impl Iterator<Item = (PanelEntry<'a, Rect>, bool)> {
let focused_kind = focused.and_then(|fid| {
resolved
.kinds()
.find(|kind| resolved.by_kind(kind).contains(&fid))
});
resolved.panels().map(move |e| {
let is_focused = match (focused, focused_kind) {
(Some(fid), _) if e.id == fid => true,
(_, Some(fk)) => e
.kind
.strip_suffix("_tab")
.or_else(|| e.kind.strip_suffix("_title"))
.is_some_and(|base| base == fk),
_ => false,
};
let entry = e.map_rect(|r| {
let mut rect = quantize(r);
rect.x += origin.x;
rect.y += origin.y;
rect
});
(entry, is_focused)
})
}
fn quantize(r: &panes::Rect) -> Rect {
let left = clamp_edge(r.x.round());
let top = clamp_edge(r.y.round());
let right = clamp_edge((r.x + r.w).round());
let bottom = clamp_edge((r.y + r.h).round());
Rect {
x: left,
y: top,
width: right.saturating_sub(left),
height: bottom.saturating_sub(top),
}
}
fn clamp_edge(v: f32) -> u16 {
match v {
v if v <= 0.0 => 0,
v if v >= f32::from(u16::MAX) => u16::MAX,
_ => v as u16,
}
}