Skip to main content

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}