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}