use egui::Rect;
use crate::Tree;
use super::{Behavior, DropContext, SimplifyAction, TileId, Tiles};
mod grid;
mod linear;
mod tabs;
pub use grid::{Grid, GridLayout};
pub use linear::{Linear, LinearDir, Shares};
pub use tabs::Tabs;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum ContainerKind {
#[default]
Tabs,
Horizontal,
Vertical,
Grid,
}
impl ContainerKind {
pub const ALL: [Self; 4] = [Self::Tabs, Self::Horizontal, Self::Vertical, Self::Grid];
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum Container {
Tabs(Tabs),
Linear(Linear),
Grid(Grid),
}
impl From<Tabs> for Container {
#[inline]
fn from(tabs: Tabs) -> Self {
Self::Tabs(tabs)
}
}
impl From<Linear> for Container {
#[inline]
fn from(linear: Linear) -> Self {
Self::Linear(linear)
}
}
impl From<Grid> for Container {
#[inline]
fn from(grid: Grid) -> Self {
Self::Grid(grid)
}
}
impl Container {
pub fn new(typ: ContainerKind, children: Vec<TileId>) -> Self {
match typ {
ContainerKind::Tabs => Self::new_tabs(children),
ContainerKind::Horizontal => Self::new_horizontal(children),
ContainerKind::Vertical => Self::new_vertical(children),
ContainerKind::Grid => Self::new_grid(children),
}
}
pub fn new_linear(dir: LinearDir, children: Vec<TileId>) -> Self {
Self::Linear(Linear::new(dir, children))
}
pub fn new_horizontal(children: Vec<TileId>) -> Self {
Self::new_linear(LinearDir::Horizontal, children)
}
pub fn new_vertical(children: Vec<TileId>) -> Self {
Self::new_linear(LinearDir::Vertical, children)
}
pub fn new_tabs(children: Vec<TileId>) -> Self {
Self::Tabs(Tabs::new(children))
}
pub fn new_grid(children: Vec<TileId>) -> Self {
Self::Grid(Grid::new(children))
}
pub fn is_empty(&self) -> bool {
self.num_children() == 0
}
pub fn num_children(&self) -> usize {
match self {
Container::Tabs(tabs) => tabs.children.len(),
Container::Linear(linear) => linear.children.len(),
Container::Grid(grid) => grid.num_children(),
}
}
pub fn children(&self) -> impl Iterator<Item = &TileId> {
match self {
Self::Tabs(tabs) => itertools::Either::Left(tabs.children.iter()),
Self::Linear(linear) => itertools::Either::Left(linear.children.iter()),
Self::Grid(grid) => itertools::Either::Right(grid.children()),
}
}
pub fn active_children(&self) -> impl Iterator<Item = &TileId> {
match self {
Self::Tabs(tabs) => {
itertools::Either::Left(itertools::Either::Left(tabs.active.iter()))
}
Self::Linear(linear) => {
itertools::Either::Left(itertools::Either::Right(linear.children.iter()))
}
Self::Grid(grid) => itertools::Either::Right(grid.children()),
}
}
pub fn only_child(&self) -> Option<TileId> {
let mut only_child = None;
for &child in self.children() {
if only_child.is_none() {
only_child = Some(child);
} else {
return None;
}
}
only_child
}
pub fn children_vec(&self) -> Vec<TileId> {
self.children().copied().collect()
}
pub fn has_child(&self, needle: TileId) -> bool {
self.children().any(|&t| t == needle)
}
pub fn add_child(&mut self, child: TileId) {
match self {
Self::Tabs(tabs) => tabs.add_child(child),
Self::Linear(linear) => linear.add_child(child),
Self::Grid(grid) => grid.add_child(child),
}
}
pub fn retain(&mut self, mut retain: impl FnMut(TileId) -> bool) {
match self {
Self::Tabs(tabs) => tabs.children.retain(|tile_id: &TileId| retain(*tile_id)),
Self::Linear(linear) => linear.children.retain(|tile_id: &TileId| retain(*tile_id)),
Self::Grid(grid) => grid.retain(retain),
}
}
pub fn remove_child(&mut self, child: TileId) -> Option<usize> {
match self {
Container::Tabs(tabs) => tabs.remove_child(child),
Container::Linear(linear) => linear.remove_child(child),
Container::Grid(grid) => grid.remove_child(child),
}
}
pub fn kind(&self) -> ContainerKind {
match self {
Self::Tabs(_) => ContainerKind::Tabs,
Self::Linear(linear) => match linear.dir {
LinearDir::Horizontal => ContainerKind::Horizontal,
LinearDir::Vertical => ContainerKind::Vertical,
},
Self::Grid(_) => ContainerKind::Grid,
}
}
pub fn set_kind(&mut self, kind: ContainerKind) {
if kind == self.kind() {
return;
}
*self = match kind {
ContainerKind::Tabs => Self::Tabs(Tabs::new(self.children_vec())),
ContainerKind::Horizontal => {
Self::Linear(Linear::new(LinearDir::Horizontal, self.children_vec()))
}
ContainerKind::Vertical => {
Self::Linear(Linear::new(LinearDir::Vertical, self.children_vec()))
}
ContainerKind::Grid => Self::Grid(Grid::new(self.children_vec())),
};
}
pub(super) fn simplify_children(&mut self, simplify: impl FnMut(TileId) -> SimplifyAction) {
match self {
Self::Tabs(tabs) => tabs.simplify_children(simplify),
Self::Linear(linear) => linear.simplify_children(simplify),
Self::Grid(grid) => grid.simplify_children(simplify),
}
}
pub(super) fn layout<Pane>(
&mut self,
tiles: &mut Tiles<Pane>,
style: &egui::Style,
behavior: &mut dyn Behavior<Pane>,
rect: Rect,
) {
if self.is_empty() {
return;
}
match self {
Container::Tabs(tabs) => tabs.layout(tiles, style, behavior, rect),
Container::Linear(linear) => {
linear.layout(tiles, style, behavior, rect);
}
Container::Grid(grid) => grid.layout(tiles, style, behavior, rect),
}
}
pub(super) fn ui<Pane>(
&mut self,
tree: &mut Tree<Pane>,
behavior: &mut dyn Behavior<Pane>,
drop_context: &mut DropContext,
ui: &mut egui::Ui,
rect: Rect,
tile_id: TileId,
) {
match self {
Container::Tabs(tabs) => {
tabs.ui(tree, behavior, drop_context, ui, rect, tile_id);
}
Container::Linear(linear) => {
linear.ui(tree, behavior, drop_context, ui, tile_id);
}
Container::Grid(grid) => {
grid.ui(tree, behavior, drop_context, ui, tile_id);
}
}
}
}