altui-core 0.2.0

A library to build rich terminal user interfaces or dashboards
Documentation
use std::ops::Deref;

use cassowary::{Expression, Variable};

use crate::layout::Attr;

pub(crate) struct Variables {
    idxes: Vec<Variable>,
}

impl Default for Variables {
    fn default() -> Self {
        Self {
            idxes: Default::default(),
        }
    }
}

impl Variables {
    #[inline(always)]
    pub(crate) fn add(&mut self) -> Variable {
        let var = Variable::new();
        self.idxes.push(var);
        var
    }

    #[inline(always)]
    pub(crate) fn get_id(&self, var: Variable) -> usize {
        self.idxes.iter().position(|&x| x == var).expect(
            "Failed to find Cassowary Variable in vector of used Variables in split operation",
        )
    }
}

/// A container used by the solver inside split
#[derive(Debug, Clone, Copy)]
pub(crate) struct LineBox {
    pub(crate) cross_start: Variable,
    pub(crate) cross_size: Variable,
}

impl LineBox {
    pub(crate) fn new(variables: &mut Variables) -> Self {
        Self {
            cross_start: variables.add(),
            cross_size: variables.add(),
        }
    }

    #[inline(always)]
    pub(crate) fn vars(
        &self,
        vars: &mut Vec<Option<(usize, usize, Attr)>>,
        line: usize,
        variables: &Variables,
    ) {
        vars[variables.get_id(self.cross_start)] = Some((line, 0, Attr::CrossStart));
        vars[variables.get_id(self.cross_size)] = Some((line, 0, Attr::CrossSize));
    }

    #[inline(always)]
    pub(crate) fn cross_end(&self) -> Expression {
        self.cross_start + self.cross_size
    }
}

/// A container used by the solver inside split
#[derive(Debug, Clone, Copy)]
pub(crate) struct Element {
    pub(crate) start: Variable,
    pub(crate) size: Variable,
    pub(crate) strength: f64,
    pub(crate) constraint: ElConstraint,
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub(crate) enum ElConstraint {
    Min(f64),
    Max(f64),
    Percentage(f64),
    Ratio(f64),
    Length(f64),
}

impl Deref for ElConstraint {
    type Target = f64;

    fn deref(&self) -> &Self::Target {
        match self {
            ElConstraint::Min(v)
            | ElConstraint::Max(v)
            | ElConstraint::Percentage(v)
            | ElConstraint::Ratio(v)
            | ElConstraint::Length(v) => v,
        }
    }
}

impl Element {
    pub(crate) fn new(
        strength: f64,
        constraint: ElConstraint,
        variables: &mut Variables,
    ) -> Element {
        Element {
            start: variables.add(),
            size: variables.add(),
            strength,
            constraint,
        }
    }

    #[inline(always)]
    pub(crate) fn vars(
        &self,
        vars: &mut Vec<Option<(usize, usize, Attr)>>,
        line: usize,
        index: usize,
        variables: &Variables,
    ) {
        vars[variables.get_id(self.start)] = Some((line, index, Attr::Start));
        vars[variables.get_id(self.size)] = Some((line, index, Attr::Size));
    }

    #[inline(always)]
    pub(crate) fn end(&self) -> Expression {
        self.start + self.size
    }
}