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/// 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}