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