egui/ui_builder.rs
1use std::{hash::Hash, sync::Arc};
2
3use crate::ClosableTag;
4#[expect(unused_imports)] // Used for doclinks
5use crate::Ui;
6use crate::{Id, LayerId, Layout, Rect, Sense, Style, UiStackInfo};
7
8/// Build a [`Ui`] as the child of another [`Ui`].
9///
10/// By default, everything is inherited from the parent,
11/// except for `max_rect` which by default is set to
12/// the parent [`Ui::available_rect_before_wrap`].
13#[must_use]
14#[derive(Clone, Default)]
15pub struct UiBuilder {
16 pub id_salt: Option<Id>,
17 pub global_scope: bool,
18 pub ui_stack_info: UiStackInfo,
19 pub layer_id: Option<LayerId>,
20 pub max_rect: Option<Rect>,
21 pub layout: Option<Layout>,
22 pub disabled: bool,
23 pub invisible: bool,
24 pub sizing_pass: bool,
25 pub style: Option<Arc<Style>>,
26 pub sense: Option<Sense>,
27 pub accessibility_parent: Option<Id>,
28}
29
30impl UiBuilder {
31 #[inline]
32 pub fn new() -> Self {
33 Self::default()
34 }
35
36 /// Seed the child `Ui` with this `id_salt`, which will be mixed
37 /// with the [`Ui::id`] of the parent.
38 ///
39 /// You should give each [`Ui`] an `id_salt` that is unique
40 /// within the parent, or give it none at all.
41 #[inline]
42 pub fn id_salt(mut self, id_salt: impl Hash) -> Self {
43 self.id_salt = Some(Id::new(id_salt));
44 self
45 }
46
47 /// Set an id of the new `Ui` that is independent of the parent `Ui`.
48 /// This way child widgets can be moved in the ui tree without losing state.
49 /// You have to ensure that in a frame the child widgets do not get rendered in multiple places.
50 ///
51 /// You should set the same unique `id` at every place in the ui tree where you want the
52 /// child widgets to share state.
53 /// If the child widgets are not moved in the ui tree, use [`UiBuilder::id_salt`] instead.
54 ///
55 /// This is a shortcut for `.id_salt(my_id).global_scope(true)`.
56 #[inline]
57 pub fn id(mut self, id: Id) -> Self {
58 self.id_salt = Some(id);
59 self.global_scope = true;
60 self
61 }
62
63 /// Make the new `Ui` child ids independent of the parent `Ui`.
64 /// This way child widgets can be moved in the ui tree without losing state.
65 /// You have to ensure that in a frame the child widgets do not get rendered in multiple places.
66 ///
67 /// You should set the same globally unique `id_salt` at every place in the ui tree where you want the
68 /// child widgets to share state.
69 #[inline]
70 pub fn global_scope(mut self, global_scope: bool) -> Self {
71 self.global_scope = global_scope;
72 self
73 }
74
75 /// Provide some information about the new `Ui` being built.
76 #[inline]
77 pub fn ui_stack_info(mut self, ui_stack_info: UiStackInfo) -> Self {
78 self.ui_stack_info = ui_stack_info;
79 self
80 }
81
82 /// Show the [`Ui`] in a different [`LayerId`] from its parent.
83 #[inline]
84 pub fn layer_id(mut self, layer_id: LayerId) -> Self {
85 self.layer_id = Some(layer_id);
86 self
87 }
88
89 /// Set the max rectangle, within which widgets will go.
90 ///
91 /// New widgets will *try* to fit within this rectangle.
92 ///
93 /// Text labels will wrap to fit within `max_rect`.
94 /// Separator lines will span the `max_rect`.
95 ///
96 /// If a new widget doesn't fit within the `max_rect` then the
97 /// [`Ui`] will make room for it by expanding both `min_rect` and
98 ///
99 /// If not set, this will be set to the parent
100 /// [`Ui::available_rect_before_wrap`].
101 #[inline]
102 pub fn max_rect(mut self, max_rect: Rect) -> Self {
103 self.max_rect = Some(max_rect);
104 self
105 }
106
107 /// Override the layout.
108 ///
109 /// Will otherwise be inherited from the parent.
110 #[inline]
111 pub fn layout(mut self, layout: Layout) -> Self {
112 self.layout = Some(layout);
113 self
114 }
115
116 /// Make the new `Ui` disabled, i.e. grayed-out and non-interactive.
117 ///
118 /// Note that if the parent `Ui` is disabled, the child will always be disabled.
119 #[inline]
120 pub fn disabled(mut self) -> Self {
121 self.disabled = true;
122 self
123 }
124
125 /// Make the contents invisible.
126 ///
127 /// Will also disable the `Ui` (see [`Self::disabled`]).
128 ///
129 /// If the parent `Ui` is invisible, the child will always be invisible.
130 #[inline]
131 pub fn invisible(mut self) -> Self {
132 self.invisible = true;
133 self.disabled = true;
134 self
135 }
136
137 /// Set to true in special cases where we do one frame
138 /// where we size up the contents of the Ui, without actually showing it.
139 ///
140 /// If the `sizing_pass` flag is set on the parent,
141 /// the child will inherit it automatically.
142 #[inline]
143 pub fn sizing_pass(mut self) -> Self {
144 self.sizing_pass = true;
145 self
146 }
147
148 /// Override the style.
149 ///
150 /// Otherwise will inherit the style of the parent.
151 #[inline]
152 pub fn style(mut self, style: impl Into<Arc<Style>>) -> Self {
153 self.style = Some(style.into());
154 self
155 }
156
157 /// Set if you want sense clicks and/or drags. Default is [`Sense::hover`].
158 ///
159 /// The sense will be registered below the Senses of any widgets contained in this [`Ui`], so
160 /// if the user clicks a button contained within this [`Ui`], that button will receive the click
161 /// instead.
162 ///
163 /// The response can be read early with [`Ui::response`].
164 #[inline]
165 pub fn sense(mut self, sense: Sense) -> Self {
166 self.sense = Some(sense);
167 self
168 }
169
170 /// Make this [`Ui`] closable.
171 ///
172 /// Calling [`Ui::close`] in a child [`Ui`] will mark this [`Ui`] for closing.
173 /// After [`Ui::close`] was called, [`Ui::should_close`] and [`crate::Response::should_close`] will
174 /// return `true` (for this frame).
175 ///
176 /// This works by adding a [`ClosableTag`] to the [`UiStackInfo`].
177 #[inline]
178 pub fn closable(mut self) -> Self {
179 self.ui_stack_info
180 .tags
181 .insert(ClosableTag::NAME, Some(Arc::new(ClosableTag::default())));
182 self
183 }
184
185 /// Set the accessibility parent for this [`Ui`].
186 ///
187 /// This will override the automatic parent assignment for accessibility purposes.
188 /// If not set, the parent [`Ui`]'s ID will be used as the accessibility parent.
189 #[inline]
190 pub fn accessibility_parent(mut self, parent_id: Id) -> Self {
191 self.accessibility_parent = Some(parent_id);
192 self
193 }
194}