gled-ui 2.32.1

gled's egui interface, shared by the desktop app and the browser
Documentation
//! One attribute across a multiselection.

/// One attribute across a multiselection.
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum MultiValue<T> {
    Same(T),
    Differing,
}

impl<T: PartialEq> MultiValue<T> {
    /// `None` for an empty selection, so callers can tell "nothing selected"
    /// from "selected, but the values disagree".
    pub(crate) fn collect(values: impl Iterator<Item = T>) -> Option<Self> {
        let mut values = values;
        let first = values.next()?;
        for value in values {
            if value != first {
                return Some(Self::Differing);
            }
        }
        Some(Self::Same(first))
    }

    pub(crate) fn same(&self) -> Option<&T> {
        match self {
            Self::Same(value) => Some(value),
            Self::Differing => None,
        }
    }
}

/// Text for an attribute whose values may disagree across the selection.
pub(crate) fn shown<T: std::fmt::Display>(value: &Option<MultiValue<T>>) -> String {
    match value {
        Some(MultiValue::Same(value)) => value.to_string(),
        Some(MultiValue::Differing) => "-".to_string(),
        None => String::new(),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn differing_values_report_differing() {
        assert_eq!(
            MultiValue::collect([1, 2].into_iter()),
            Some(MultiValue::Differing)
        );
    }

    #[test]
    fn an_empty_selection_has_no_value() {
        assert_eq!(MultiValue::<i32>::collect(std::iter::empty()), None);
    }

    #[test]
    fn differing_values_are_shown_as_a_dash() {
        assert_eq!(shown(&Some(MultiValue::Differing::<&str>)), "-");
        assert_eq!(shown(&Some(MultiValue::Same("individual"))), "individual");
        assert_eq!(shown(&None::<MultiValue<&str>>), "");
    }

    #[test]
    fn identical_values_collapse_to_same() {
        assert_eq!(
            MultiValue::collect([1, 1, 1].into_iter()),
            Some(MultiValue::Same(1))
        );
    }
}