icmd 0.1.0

A command-line software framework
Documentation
//! Module for measurement utilities used in layout calculations.

use crate::{node::Node, utils::LazyMeasure};
use std::sync::Arc;

/// Trait representing a horizontal measurement.
/// Used to abstract over different horizontal measurement types.
pub trait HorizontalMeasure {}

/// Trait representing a vertical measurement.
/// Used to abstract over different vertical measurement types.
pub trait VerticalMeasure {}

/// A fixed measurement value.
pub struct Fixed(pub i32);

impl HorizontalMeasure for Fixed {}
impl VerticalMeasure for Fixed {}

/// Converts an i32 value into a Fixed measurement.
impl From<i32> for Fixed {
    fn from(value: i32) -> Self {
        Fixed(value)
    }
}

/// Converts a Fixed measurement into a LazyMeasure.
impl From<Fixed> for LazyMeasure {
    fn from(fixed: Fixed) -> Self {
        LazyMeasure::lazy(fixed.0)
    }
}

/// Macro to define relative measurement types.
/// It generates a struct and associated methods for obtaining measurements relative to a Node.
macro_rules! def_relative_measure {
    ($implement: ident, $name:ident, $measure:ident) => {
        /// Relative measurement type.
        pub struct $name {
            measure: LazyMeasure,
        }

        impl $name {
            /// Creates a relative measurement based on a Node.
            pub fn of(node: &Arc<impl Node + Sync + 'static>) -> Self {
                let node = node.clone();
                let measure = LazyMeasure::new(move || Node::$measure(node.as_ref()).into());
                $name { measure }
            }

            /// Creates a relative measurement with an offset from a Node.
            pub fn away_from(node: &Arc<impl Node + Sync + 'static>, offset: i32) -> Self {
                let node = node.clone();
                let measure =
                    LazyMeasure::new(move || (Node::$measure(node.as_ref()) - offset).into());
                $name { measure }
            }
        }

        impl From<$name> for LazyMeasure {
            fn from(value: $name) -> Self {
                value.measure
            }
        }

        impl $implement for $name {}
    };
}

def_relative_measure!(HorizontalMeasure, Left, get_left);
def_relative_measure!(HorizontalMeasure, Right, get_right);
def_relative_measure!(VerticalMeasure, Top, get_top);
def_relative_measure!(VerticalMeasure, Bottom, get_bottom);