Skip to main content

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}