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