1use crate::{AtomKind, 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 ) -> SizedAtom<'a> {
73 if !self.shrink && self.max_size.x.is_infinite() {
74 wrap_mode = Some(TextWrapMode::Extend);
75 }
76 available_size = available_size.at_most(self.max_size);
77 if let Some(size) = self.size {
78 available_size = available_size.at_most(size);
79 }
80 if self.max_size.x.is_finite() {
81 wrap_mode = Some(TextWrapMode::Truncate);
82 }
83
84 let (intrinsic, kind) = self.kind.into_sized(ui, available_size, wrap_mode);
85
86 let size = self
87 .size
88 .map_or_else(|| kind.size(), |s| s.at_most(self.max_size));
89
90 SizedAtom {
91 size,
92 intrinsic_size: intrinsic.at_least(self.size.unwrap_or_default()),
93 grow: self.grow,
94 kind,
95 }
96 }
97}
98
99impl<'a, T> From<T> for Atom<'a>
100where
101 T: Into<AtomKind<'a>>,
102{
103 fn from(value: T) -> Self {
104 Atom {
105 kind: value.into(),
106 ..Default::default()
107 }
108 }
109}