1use crate::{AtomKind, FontSelection, Id, SizedAtom, Ui};
2use emath::{NumExt as _, Vec2};
3use epaint::text::TextWrapMode;
4
5#[derive(Clone, Debug)]
16pub struct Atom<'a> {
17    pub size: Option<Vec2>,
19
20    pub max_size: Vec2,
22
23    pub grow: bool,
25
26    pub shrink: bool,
28
29    pub kind: AtomKind<'a>,
31}
32
33impl Default for Atom<'_> {
34    fn default() -> Self {
35        Atom {
36            size: None,
37            max_size: Vec2::INFINITY,
38            grow: false,
39            shrink: false,
40            kind: AtomKind::Empty,
41        }
42    }
43}
44
45impl<'a> Atom<'a> {
46    pub fn grow() -> Self {
51        Atom {
52            grow: true,
53            ..Default::default()
54        }
55    }
56
57    pub fn custom(id: Id, size: impl Into<Vec2>) -> Self {
59        Atom {
60            size: Some(size.into()),
61            kind: AtomKind::Custom(id),
62            ..Default::default()
63        }
64    }
65
66    pub fn into_sized(
68        self,
69        ui: &Ui,
70        mut available_size: Vec2,
71        mut wrap_mode: Option<TextWrapMode>,
72        fallback_font: FontSelection,
73    ) -> SizedAtom<'a> {
74        if !self.shrink && self.max_size.x.is_infinite() {
75            wrap_mode = Some(TextWrapMode::Extend);
76        }
77        available_size = available_size.at_most(self.max_size);
78        if let Some(size) = self.size {
79            available_size = available_size.at_most(size);
80        }
81        if self.max_size.x.is_finite() {
82            wrap_mode = Some(TextWrapMode::Truncate);
83        }
84
85        let (intrinsic, kind) = self
86            .kind
87            .into_sized(ui, available_size, wrap_mode, fallback_font);
88
89        let size = self
90            .size
91            .map_or_else(|| kind.size(), |s| s.at_most(self.max_size));
92
93        SizedAtom {
94            size,
95            intrinsic_size: intrinsic.at_least(self.size.unwrap_or_default()),
96            grow: self.grow,
97            kind,
98        }
99    }
100}
101
102impl<'a, T> From<T> for Atom<'a>
103where
104    T: Into<AtomKind<'a>>,
105{
106    fn from(value: T) -> Self {
107        Atom {
108            kind: value.into(),
109            ..Default::default()
110        }
111    }
112}