pierro 0.1.0

An immediate mode UI library for Rust
Documentation

mod render;
mod command;

use std::{collections::HashMap, usize};

use crate::{Axis, UI};

pub trait DockingTab: Sized {

    type Context;

    fn title(&self) -> String;
    fn render(&mut self, ui: &mut UI, context: &mut Self::Context);

    fn add_tab_dropdown<F: FnMut(Self)>(ui: &mut UI, add_tab: F, context: &mut Self::Context);
    
}

struct Tabs<Tab: DockingTab> {
    tabs: Vec<Tab>,
    active_tab: usize
}

impl<Tab:DockingTab> Tabs<Tab> {

    pub fn new(tabs: Vec<Tab>) -> Self {
        Self {
            tabs: tabs,
            active_tab: 0,
        }
    }

}

#[derive(Copy, Clone, PartialEq, Eq, Hash)]
struct DockingNodeId(usize);

impl DockingNodeId {

    const NULL: Self = Self(usize::MAX);

    fn is_null(&self) -> bool {
        *self == Self::NULL
    }

}

struct Split {
    nodes: Vec<(f32, DockingNodeId)>,
    direction: Axis
}

enum DockingNodeKind<Tab: DockingTab> {
    Tabs(Tabs<Tab>),
    Split(Split) 
}

struct DockingNode<Tab: DockingTab> {
    parent: DockingNodeId,
    kind: DockingNodeKind<Tab>
}

struct DockingTree<Tab: DockingTab> {
    nodes: HashMap<DockingNodeId, DockingNode<Tab>>,
    curr_id: usize,
    root: DockingNodeId 
}

impl<Tab: DockingTab> DockingTree<Tab> {

    fn new(tabs: Vec<Tab>) -> Self {
        let mut nodes = HashMap::new();
        let root = DockingNodeId(0);
        nodes.insert(root, DockingNode {
            parent: DockingNodeId::NULL,
            kind: DockingNodeKind::Tabs(Tabs::new(tabs)),
        });
        Self {
            nodes,
            curr_id: 1,
            root
        }
    }

    fn get(&self, id: DockingNodeId) -> Option<&DockingNode<Tab>> {
        self.nodes.get(&id)
    }

    fn get_mut(&mut self, id: DockingNodeId) -> Option<&mut DockingNode<Tab>> {
        self.nodes.get_mut(&id)
    }

    fn add_node(&mut self, node: DockingNode<Tab>) -> DockingNodeId {
        let id = DockingNodeId(self.curr_id);
        self.curr_id += 1;
        self.nodes.insert(id, node);
        id
    }

    fn delete_node(&mut self, node: DockingNodeId) {
        self.nodes.remove(&node);
    }

    fn get_tabs(&self, id: DockingNodeId) -> Option<&Tabs<Tab>> { 
        let node = self.get(id)?;
        match &node.kind {
            DockingNodeKind::Tabs(tabs) => Some(tabs),
            DockingNodeKind::Split { .. } => None,
        }
    }

    fn get_tabs_mut(&mut self, id: DockingNodeId) -> Option<&mut Tabs<Tab>> { 
        let node = self.get_mut(id)?;
        match &mut node.kind {
            DockingNodeKind::Tabs(tabs) => Some(tabs),
            DockingNodeKind::Split { .. } => None,
        }
    }

    fn add_tabs(&mut self, parent: DockingNodeId, tabs: Vec<Tab>) -> DockingNodeId {
        self.add_node(DockingNode {
            parent,
            kind: DockingNodeKind::Tabs(Tabs::new(tabs)),
        })
    }

    fn get_split(&self, id: DockingNodeId) -> Option<&Split> {
        let node = self.get(id)?;
        match &node.kind {
            DockingNodeKind::Tabs { .. } => None,
            DockingNodeKind::Split(split) => Some(split),
        }
    }

    fn get_split_mut(&mut self, id: DockingNodeId) -> Option<&mut Split> {
        let node = self.get_mut(id)?;
        match &mut node.kind {
            DockingNodeKind::Tabs { .. } => None,
            DockingNodeKind::Split(split) => Some(split),
        }
    }

    fn add_split(&mut self, parent: DockingNodeId, direction: Axis) -> DockingNodeId {
        self.add_node(DockingNode {
            parent,
            kind: DockingNodeKind::Split(Split {
                nodes: Vec::new(),
                direction
            }),
        })
    }

    fn get_parent(&self, id: DockingNodeId) -> Option<DockingNodeId> {
        Some(self.get(id)?.parent)
    }

    fn set_parent(&mut self, id: DockingNodeId, parent: DockingNodeId) -> Option<()> {
        self.get_mut(id)?.parent = parent;
        Some(())
    } 

}

pub struct DockingState<Tab: DockingTab> {
    tree: DockingTree<Tab>
}

impl<Tab: DockingTab> DockingState<Tab> {

    pub fn new(tabs: Vec<Tab>) -> Self {
        Self {
            tree: DockingTree::new(tabs)
        }
    }

}