Skip to main content

egui/
ui.rs

1#![warn(missing_docs)] // Let's keep `Ui` well-documented.
2#![expect(clippy::use_self)]
3
4use core::{any::Any, ops::Deref};
5use std::sync::Arc;
6
7use crate::containers::menu;
8use crate::widget_style::{HasClasses as _, ROOT_CLASS};
9use crate::{IdSource, containers::*, ecolor::*, layout::*, placer::Placer, widgets::*, *};
10use emath::GuiRounding as _;
11
12// ----------------------------------------------------------------------------
13
14/// This is what you use to place widgets.
15///
16/// Represents a region of the screen with a type of layout (horizontal or vertical).
17///
18/// ```
19/// # egui::__run_test_ui(|ui| {
20/// ui.add(egui::Label::new("Hello World!"));
21/// ui.label("A shorter and more convenient way to add a label.");
22/// ui.horizontal(|ui| {
23///     ui.label("Add widgets");
24///     if ui.button("on the same row!").clicked() {
25///         /* … */
26///     }
27/// });
28/// # });
29/// ```
30pub struct Ui {
31    /// Generated based on id of parent ui together with an optional id salt.
32    ///
33    /// This should be stable from one frame to next
34    /// so it can be used as a source for storing state
35    /// (e.g. window position, or if a collapsing header is open).
36    ///
37    /// However, it is not necessarily globally unique.
38    /// For instance, sibling `Ui`s share the same [`Self::id`]
39    /// unless they where explicitly given different id salts using
40    /// [`UiBuilder::id_salt`].
41    id: Id,
42
43    /// This is a globally unique ID of this `Ui`,
44    /// based on where in the hierarchy of widgets this Ui is in.
45    ///
46    /// This means it is not _stable_, as it can change if new widgets
47    /// are added or removed prior to this one.
48    /// It should therefore only be used for transient interactions (clicks etc),
49    /// not for storing state over time.
50    unique_id: Id,
51
52    /// This is used to create a unique interact ID for some widgets.
53    ///
54    /// This value is based on where in the hierarchy of widgets this Ui is in,
55    /// and the value is increment with each added child widget.
56    /// This works as an Id source only as long as new widgets aren't added or removed.
57    /// They are therefore only good for Id:s that have no state.
58    next_auto_id_salt: u64,
59
60    /// Specifies paint layer, clip rectangle and a reference to [`Context`].
61    painter: Painter,
62
63    /// The [`Style`] (visuals, spacing, etc) of this ui.
64    /// Commonly many [`Ui`]s share the same [`Style`].
65    /// The [`Ui`] implements copy-on-write for this.
66    style: Arc<Style>,
67
68    /// Handles the [`Ui`] size and the placement of new widgets.
69    placer: Placer,
70
71    /// If false we are unresponsive to input,
72    /// and all widgets will assume a gray style.
73    enabled: bool,
74
75    /// Set to true in special cases where we do one frame
76    /// where we size up the contents of the Ui, without actually showing it.
77    sizing_pass: bool,
78
79    /// The [`UiStack`] for this [`Ui`].
80    stack: Arc<UiStack>,
81
82    /// The sense for the ui background.
83    sense: Sense,
84
85    /// Whether [`Ui::remember_min_rect`] should be called when the [`Ui`] is dropped.
86    /// This is an optimization, so we don't call [`Ui::remember_min_rect`] multiple times at the
87    /// end of a [`Ui::scope`].
88    min_rect_already_remembered: bool,
89}
90
91/// Allow using [`Ui`] like a [`Context`].
92impl Deref for Ui {
93    type Target = Context;
94
95    #[inline]
96    fn deref(&self) -> &Self::Target {
97        self.ctx()
98    }
99}
100
101impl Ui {
102    // ------------------------------------------------------------------------
103    // Creation:
104
105    /// Create a new top-level [`Ui`].
106    ///
107    /// Normally you would not use this directly, but instead use
108    /// [`crate::Panel`], [`crate::CentralPanel`], [`crate::Window`] or [`crate::Area`].
109    pub fn new(ctx: Context, id: Id, ui_builder: UiBuilder) -> Self {
110        let UiBuilder {
111            id_source,
112            ui_stack_info,
113            layer_id,
114            max_rect,
115            layout,
116            disabled,
117            invisible,
118            sizing_pass,
119            style,
120            sense,
121            accessibility_parent,
122            classes,
123        } = ui_builder;
124
125        let layer_id = layer_id.unwrap_or_else(LayerId::background);
126
127        debug_assert!(
128            id_source.is_none(),
129            "Top-level Ui:s should not have an UiBuilder::id_source"
130        );
131
132        let max_rect = max_rect.unwrap_or_else(|| ctx.content_rect());
133        let clip_rect = max_rect;
134        let layout = layout.unwrap_or_default();
135        let disabled = disabled || invisible;
136        let style = style.unwrap_or_else(|| ctx.global_style());
137        let sense = sense.unwrap_or_else(Sense::hover);
138        let classes = classes.with_class(ROOT_CLASS);
139
140        let placer = Placer::new(max_rect, layout);
141        let ui_stack = UiStack {
142            id,
143            layout_direction: layout.main_dir,
144            info: ui_stack_info,
145            parent: None,
146            min_rect: placer.min_rect(),
147            max_rect: placer.max_rect(),
148            classes,
149        };
150
151        let mut ui = Ui {
152            id,
153            unique_id: id,
154            next_auto_id_salt: id.with("auto").value(),
155            painter: Painter::new(ctx, layer_id, clip_rect),
156            style,
157            placer,
158            enabled: true,
159            sizing_pass,
160            stack: Arc::new(ui_stack),
161            sense,
162            min_rect_already_remembered: false,
163        };
164
165        if let Some(accessibility_parent) = accessibility_parent {
166            ui.ctx()
167                .register_accesskit_parent(ui.unique_id, accessibility_parent);
168        }
169
170        // Register in the widget stack early, to ensure we are behind all widgets we contain:
171        let start_rect = Rect::NOTHING; // This will be overwritten when `remember_min_rect` is called
172        ui.ctx().create_widget(
173            WidgetRect {
174                id: ui.unique_id,
175                parent_id: ui.id,
176                layer_id: ui.layer_id(),
177                rect: start_rect,
178                interact_rect: start_rect,
179                sense,
180                enabled: ui.enabled,
181            },
182            true,
183            Default::default(),
184        );
185
186        if disabled {
187            ui.disable();
188        }
189        if invisible {
190            ui.set_invisible();
191        }
192
193        ui.ctx().accesskit_node_builder(ui.unique_id, |node| {
194            node.set_role(accesskit::Role::GenericContainer);
195        });
196
197        ui
198    }
199
200    /// Create a child `Ui` with the properties of the given builder.
201    ///
202    /// This is a very low-level function.
203    /// Usually you are better off using [`Self::scope_builder`].
204    ///
205    /// Note that calling this does not allocate any space in the parent `Ui`,
206    /// so after adding widgets to the child `Ui` you probably want to allocate
207    /// the [`Ui::min_rect`] of the child in the parent `Ui` using e.g.
208    /// [`Ui::advance_cursor_after_rect`].
209    pub fn new_child(&mut self, ui_builder: UiBuilder) -> Self {
210        let UiBuilder {
211            id_source,
212            ui_stack_info,
213            layer_id,
214            max_rect,
215            layout,
216            disabled,
217            invisible,
218            sizing_pass,
219            style,
220            sense,
221            accessibility_parent,
222            classes,
223        } = ui_builder;
224
225        let mut painter = self.painter.clone();
226
227        let max_rect = max_rect.unwrap_or_else(|| self.available_rect_before_wrap());
228        let mut layout = layout.unwrap_or_else(|| *self.layout());
229        let enabled = self.enabled && !disabled && !invisible;
230        if let Some(layer_id) = layer_id {
231            painter.set_layer_id(layer_id);
232        }
233        if invisible {
234            painter.set_invisible();
235        }
236        let sizing_pass = self.sizing_pass || sizing_pass;
237        let style = style.unwrap_or_else(|| Arc::clone(&self.style));
238        let sense = sense.unwrap_or_else(Sense::hover);
239
240        if sizing_pass {
241            // During the sizing pass we want widgets to use up as little space as possible,
242            // so that we measure the only the space we _need_.
243            layout.cross_justify = false;
244            if layout.cross_align == Align::Center {
245                layout.cross_align = Align::Min;
246            }
247        }
248
249        debug_assert!(!max_rect.any_nan(), "max_rect is NaN: {max_rect:?}");
250
251        let id_source = id_source.unwrap_or_else(|| IdSource::Child(IdSalt::new("child")));
252        let (stable_id, unique_id) = match id_source {
253            IdSource::Explicit(id) => (id, id),
254            IdSource::Child(id_salt) => {
255                let stable_id = self.id.with(id_salt);
256                let unique_id = stable_id.with(self.next_auto_id_salt);
257                (stable_id, unique_id)
258            }
259        };
260        let next_auto_id_salt = unique_id.value().wrapping_add(1);
261
262        self.next_auto_id_salt = self.next_auto_id_salt.wrapping_add(1);
263
264        let placer = Placer::new(max_rect, layout);
265        let ui_stack = UiStack {
266            id: unique_id,
267            layout_direction: layout.main_dir,
268            info: ui_stack_info,
269            parent: Some(Arc::clone(&self.stack)),
270            min_rect: placer.min_rect(),
271            max_rect: placer.max_rect(),
272            classes,
273        };
274
275        let mut child_ui = Ui {
276            id: stable_id,
277            unique_id,
278            next_auto_id_salt,
279            painter,
280            style,
281            placer,
282            enabled,
283            sizing_pass,
284            stack: Arc::new(ui_stack),
285            sense,
286            min_rect_already_remembered: false,
287        };
288
289        if disabled {
290            child_ui.disable();
291        }
292
293        child_ui.ctx().register_accesskit_parent(
294            child_ui.unique_id,
295            accessibility_parent.unwrap_or(self.unique_id),
296        );
297
298        // Register in the widget stack early, to ensure we are behind all widgets we contain:
299        let start_rect = Rect::NOTHING; // This will be overwritten when `remember_min_rect` is called
300        child_ui.ctx().create_widget(
301            WidgetRect {
302                id: child_ui.unique_id,
303                parent_id: self.id,
304                layer_id: child_ui.layer_id(),
305                rect: start_rect,
306                interact_rect: start_rect,
307                sense,
308                enabled: child_ui.enabled,
309            },
310            true,
311            Default::default(),
312        );
313
314        child_ui
315            .ctx()
316            .accesskit_node_builder(child_ui.unique_id, |node| {
317                node.set_role(accesskit::Role::GenericContainer);
318            });
319
320        child_ui
321    }
322
323    // -------------------------------------------------
324
325    /// Set to true in special cases where we do one frame
326    /// where we size up the contents of the Ui, without actually showing it.
327    #[inline]
328    pub fn is_sizing_pass(&self) -> bool {
329        self.sizing_pass
330    }
331
332    // -------------------------------------------------
333
334    /// Generated based on id of parent ui together with an optional id salt.
335    ///
336    /// This should be stable from one frame to next
337    /// so it can be used as a source for storing state
338    /// (e.g. window position, or if a collapsing header is open).
339    ///
340    /// However, it is not necessarily globally unique.
341    /// For instance, sibling `Ui`s share the same [`Self::id`]
342    /// unless they were explicitly given different id salts using
343    /// [`UiBuilder::id_salt`].
344    #[inline]
345    pub fn id(&self) -> Id {
346        self.id
347    }
348
349    /// This is a globally unique ID of this `Ui`,
350    /// based on where in the hierarchy of widgets this Ui is in.
351    ///
352    /// This means it is not _stable_, as it can change if new widgets
353    /// are added or removed prior to this one.
354    /// It should therefore only be used for transient interactions (clicks etc),
355    /// not for storing state over time.
356    #[inline]
357    pub fn unique_id(&self) -> Id {
358        self.unique_id
359    }
360
361    /// Style options for this [`Ui`] and its children.
362    ///
363    /// Note that this may be a different [`Style`] than that of [`Context::global_style`].
364    #[inline]
365    pub fn style(&self) -> &Arc<Style> {
366        &self.style
367    }
368
369    /// Mutably borrow internal [`Style`].
370    /// Changes apply to this [`Ui`] and its subsequent children.
371    ///
372    /// To set the style of all [`Ui`]s, use [`Context::set_style_of`].
373    ///
374    /// Example:
375    /// ```
376    /// # egui::__run_test_ui(|ui| {
377    /// ui.style_mut().override_text_style = Some(egui::TextStyle::Heading);
378    /// # });
379    /// ```
380    pub fn style_mut(&mut self) -> &mut Style {
381        Arc::make_mut(&mut self.style) // clone-on-write
382    }
383
384    /// Changes apply to this [`Ui`] and its subsequent children.
385    ///
386    /// To set the style of all [`Ui`]s, use [`Context::set_style_of`].
387    pub fn set_style(&mut self, style: impl Into<Arc<Style>>) {
388        self.style = style.into();
389    }
390
391    /// Reset to the default style set in [`Context`].
392    pub fn reset_style(&mut self) {
393        self.style = self.ctx().global_style();
394    }
395
396    /// The current spacing options for this [`Ui`].
397    /// Short for `ui.style().spacing`.
398    #[inline]
399    pub fn spacing(&self) -> &crate::style::Spacing {
400        &self.style.spacing
401    }
402
403    /// Mutably borrow internal [`Spacing`].
404    /// Changes apply to this [`Ui`] and its subsequent children.
405    ///
406    /// Example:
407    /// ```
408    /// # egui::__run_test_ui(|ui| {
409    /// ui.spacing_mut().item_spacing = egui::vec2(10.0, 2.0);
410    /// # });
411    /// ```
412    pub fn spacing_mut(&mut self) -> &mut crate::style::Spacing {
413        &mut self.style_mut().spacing
414    }
415
416    /// The current visuals settings of this [`Ui`].
417    /// Short for `ui.style().visuals`.
418    #[inline]
419    pub fn visuals(&self) -> &crate::Visuals {
420        &self.style.visuals
421    }
422
423    /// Mutably borrow internal `visuals`.
424    /// Changes apply to this [`Ui`] and its subsequent children.
425    ///
426    /// To set the visuals of all [`Ui`]s, use [`Context::set_visuals_of`].
427    ///
428    /// Example:
429    /// ```
430    /// # egui::__run_test_ui(|ui| {
431    /// ui.visuals_mut().override_text_color = Some(egui::Color32::RED);
432    /// # });
433    /// ```
434    pub fn visuals_mut(&mut self) -> &mut crate::Visuals {
435        &mut self.style_mut().visuals
436    }
437
438    /// Is this [`Ui`] in a tooltip?
439    #[inline]
440    pub fn is_tooltip(&self) -> bool {
441        self.layer_id().order == Order::Tooltip
442    }
443
444    /// Get a reference to this [`Ui`]'s [`UiStack`].
445    #[inline]
446    pub fn stack(&self) -> &Arc<UiStack> {
447        &self.stack
448    }
449
450    /// Get a reference to the parent [`Context`].
451    #[inline]
452    pub fn ctx(&self) -> &Context {
453        self.painter.ctx()
454    }
455
456    /// Use this to paint stuff within this [`Ui`].
457    #[inline]
458    pub fn painter(&self) -> &Painter {
459        &self.painter
460    }
461
462    /// Number of physical pixels for each logical UI point.
463    #[inline]
464    pub fn pixels_per_point(&self) -> f32 {
465        self.painter.pixels_per_point()
466    }
467
468    /// If `false`, the [`Ui`] does not allow any interaction and
469    /// the widgets in it will draw with a gray look.
470    #[inline]
471    pub fn is_enabled(&self) -> bool {
472        self.enabled
473    }
474
475    /// Calling `disable()` will cause the [`Ui`] to deny all future interaction
476    /// and all the widgets will draw with a gray look.
477    ///
478    /// Usually it is more convenient to use [`Self::add_enabled_ui`] or [`Self::add_enabled`].
479    ///
480    /// Note that once disabled, there is no way to re-enable the [`Ui`].
481    ///
482    /// ### Example
483    /// ```
484    /// # egui::__run_test_ui(|ui| {
485    /// # let mut enabled = true;
486    /// ui.group(|ui| {
487    ///     ui.checkbox(&mut enabled, "Enable subsection");
488    ///     if !enabled {
489    ///         ui.disable();
490    ///     }
491    ///     if ui.button("Button that is not always clickable").clicked() {
492    ///         /* … */
493    ///     }
494    /// });
495    /// # });
496    /// ```
497    pub fn disable(&mut self) {
498        self.enabled = false;
499        if self.is_visible() {
500            self.painter
501                .multiply_opacity(self.visuals().disabled_alpha());
502        }
503    }
504
505    /// If `false`, any widgets added to the [`Ui`] will be invisible and non-interactive.
506    ///
507    /// This is `false` if any parent had [`UiBuilder::invisible`]
508    /// or if [`Context::will_discard`].
509    #[inline]
510    pub fn is_visible(&self) -> bool {
511        self.painter.is_visible()
512    }
513
514    /// Calling `set_invisible()` will cause all further widgets to be invisible,
515    /// yet still allocate space.
516    ///
517    /// The widgets will not be interactive (`set_invisible()` implies `disable()`).
518    ///
519    /// Once invisible, there is no way to make the [`Ui`] visible again.
520    ///
521    /// Usually it is more convenient to use [`Self::add_visible`].
522    ///
523    /// ### Example
524    /// ```
525    /// # egui::__run_test_ui(|ui| {
526    /// # let mut visible = true;
527    /// ui.group(|ui| {
528    ///     ui.checkbox(&mut visible, "Show subsection");
529    ///     if !visible {
530    ///         ui.set_invisible();
531    ///     }
532    ///     if ui.button("Button that is not always shown").clicked() {
533    ///         /* … */
534    ///     }
535    /// });
536    /// # });
537    /// ```
538    pub fn set_invisible(&mut self) {
539        self.painter.set_invisible();
540        self.disable();
541    }
542
543    /// Make the widget in this [`Ui`] semi-transparent.
544    ///
545    /// `opacity` must be between 0.0 and 1.0, where 0.0 means fully transparent (i.e., invisible)
546    /// and 1.0 means fully opaque.
547    ///
548    /// ### Example
549    /// ```
550    /// # egui::__run_test_ui(|ui| {
551    /// ui.group(|ui| {
552    ///     ui.set_opacity(0.5);
553    ///     if ui.button("Half-transparent button").clicked() {
554    ///         /* … */
555    ///     }
556    /// });
557    /// # });
558    /// ```
559    ///
560    /// See also: [`Self::opacity`] and [`Self::multiply_opacity`].
561    pub fn set_opacity(&mut self, opacity: f32) {
562        self.painter.set_opacity(opacity);
563    }
564
565    /// Like [`Self::set_opacity`], but multiplies the given value with the current opacity.
566    ///
567    /// See also: [`Self::set_opacity`] and [`Self::opacity`].
568    pub fn multiply_opacity(&mut self, opacity: f32) {
569        self.painter.multiply_opacity(opacity);
570    }
571
572    /// Read the current opacity of the underlying painter.
573    ///
574    /// See also: [`Self::set_opacity`] and [`Self::multiply_opacity`].
575    #[inline]
576    pub fn opacity(&self) -> f32 {
577        self.painter.opacity()
578    }
579
580    /// Read the [`Layout`].
581    #[inline]
582    pub fn layout(&self) -> &Layout {
583        self.placer.layout()
584    }
585
586    /// Which wrap mode should the text use in this [`Ui`]?
587    ///
588    /// This is determined first by [`Style::wrap_mode`], and then by the layout of this [`Ui`].
589    pub fn wrap_mode(&self) -> TextWrapMode {
590        if let Some(wrap_mode) = self.style.wrap_mode {
591            wrap_mode
592        } else if let Some(grid) = self.placer.grid() {
593            if grid.wrap_text() {
594                TextWrapMode::Wrap
595            } else {
596                TextWrapMode::Extend
597            }
598        } else {
599            let layout = self.layout();
600            if layout.is_vertical() || layout.is_horizontal() && layout.main_wrap() {
601                TextWrapMode::Wrap
602            } else {
603                TextWrapMode::Extend
604            }
605        }
606    }
607
608    /// How to vertically align text
609    #[inline]
610    pub fn text_valign(&self) -> Align {
611        self.style()
612            .override_text_valign
613            .unwrap_or_else(|| self.layout().vertical_align())
614    }
615
616    /// Create a painter for a sub-region of this Ui.
617    ///
618    /// The clip-rect of the returned [`Painter`] will be the intersection
619    /// of the given rectangle and the `clip_rect()` of this [`Ui`].
620    pub fn painter_at(&self, rect: Rect) -> Painter {
621        self.painter().with_clip_rect(rect)
622    }
623
624    /// Use this to paint stuff within this [`Ui`].
625    #[inline]
626    pub fn layer_id(&self) -> LayerId {
627        self.painter().layer_id()
628    }
629
630    /// The height of text of this text style.
631    ///
632    /// Returns a value rounded to [`emath::GUI_ROUNDING`].
633    pub fn text_style_height(&self, style: &TextStyle) -> f32 {
634        self.fonts_mut(|f| f.row_height(&style.resolve(self.style())))
635    }
636
637    /// Screen-space rectangle for clipping what we paint in this ui.
638    /// This is used, for instance, to avoid painting outside a window that is smaller than its contents.
639    #[inline]
640    pub fn clip_rect(&self) -> Rect {
641        self.painter.clip_rect()
642    }
643
644    /// Constrain the rectangle in which we can paint.
645    ///
646    /// Short for `ui.set_clip_rect(ui.clip_rect().intersect(new_clip_rect))`.
647    ///
648    /// See also: [`Self::clip_rect`] and [`Self::set_clip_rect`].
649    #[inline]
650    pub fn shrink_clip_rect(&mut self, new_clip_rect: Rect) {
651        self.painter.shrink_clip_rect(new_clip_rect);
652    }
653
654    /// Screen-space rectangle for clipping what we paint in this ui.
655    /// This is used, for instance, to avoid painting outside a window that is smaller than its contents.
656    ///
657    /// Warning: growing the clip rect might cause unexpected results!
658    /// When in doubt, use [`Self::shrink_clip_rect`] instead.
659    pub fn set_clip_rect(&mut self, clip_rect: Rect) {
660        self.painter.set_clip_rect(clip_rect);
661    }
662
663    /// Can be used for culling: if `false`, then no part of `rect` will be visible on screen.
664    ///
665    /// This is false if the whole `Ui` is invisible (see [`UiBuilder::invisible`])
666    /// or if [`Context::will_discard`] is true.
667    pub fn is_rect_visible(&self, rect: Rect) -> bool {
668        self.is_visible() && rect.intersects(self.clip_rect())
669    }
670}
671
672// ------------------------------------------------------------------------
673
674/// # Sizes etc
675impl Ui {
676    /// Where and how large the [`Ui`] is already.
677    /// All widgets that have been added to this [`Ui`] fits within this rectangle.
678    ///
679    /// No matter what, the final Ui will be at least this large.
680    ///
681    /// This will grow as new widgets are added, but never shrink.
682    pub fn min_rect(&self) -> Rect {
683        self.placer.min_rect()
684    }
685
686    /// Size of content; same as `min_rect().size()`
687    pub fn min_size(&self) -> Vec2 {
688        self.min_rect().size()
689    }
690
691    /// New widgets will *try* to fit within this rectangle.
692    ///
693    /// Text labels will wrap to fit within `max_rect`.
694    /// Separator lines will span the `max_rect`.
695    ///
696    /// If a new widget doesn't fit within the `max_rect` then the
697    /// [`Ui`] will make room for it by expanding both `min_rect` and `max_rect`.
698    pub fn max_rect(&self) -> Rect {
699        self.placer.max_rect()
700    }
701
702    /// Used for animation, kind of hacky
703    pub(crate) fn force_set_min_rect(&mut self, min_rect: Rect) {
704        self.placer.force_set_min_rect(min_rect);
705    }
706
707    // ------------------------------------------------------------------------
708
709    /// Set the maximum size of the ui.
710    /// You won't be able to shrink it below the current minimum size.
711    pub fn set_max_size(&mut self, size: Vec2) {
712        self.set_max_width(size.x);
713        self.set_max_height(size.y);
714    }
715
716    /// Set the maximum width of the ui.
717    /// You won't be able to shrink it below the current minimum size.
718    pub fn set_max_width(&mut self, width: f32) {
719        self.placer.set_max_width(width);
720    }
721
722    /// Set the maximum height of the ui.
723    /// You won't be able to shrink it below the current minimum size.
724    pub fn set_max_height(&mut self, height: f32) {
725        self.placer.set_max_height(height);
726    }
727
728    // ------------------------------------------------------------------------
729
730    /// Set the minimum size of the ui.
731    /// This can't shrink the ui, only make it larger.
732    pub fn set_min_size(&mut self, size: Vec2) {
733        self.set_min_width(size.x);
734        self.set_min_height(size.y);
735    }
736
737    /// Set the minimum width of the ui.
738    /// This can't shrink the ui, only make it larger.
739    pub fn set_min_width(&mut self, width: f32) {
740        debug_assert!(
741            0.0 <= width,
742            "Negative width makes no sense, but got: {width}"
743        );
744        self.placer.set_min_width(width);
745    }
746
747    /// Set the minimum height of the ui.
748    /// This can't shrink the ui, only make it larger.
749    pub fn set_min_height(&mut self, height: f32) {
750        debug_assert!(
751            0.0 <= height,
752            "Negative height makes no sense, but got: {height}"
753        );
754        self.placer.set_min_height(height);
755    }
756
757    /// Makes the ui always fill up the available space.
758    ///
759    /// This can be useful to call inside a panel with `resizable == true`
760    /// to make sure the resized space is used.
761    pub fn take_available_space(&mut self) {
762        self.set_min_size(self.available_size());
763    }
764
765    /// Makes the ui always fill up the available space in the x axis.
766    ///
767    /// This can be useful to call inside a side panel with
768    /// `resizable == true` to make sure the resized space is used.
769    pub fn take_available_width(&mut self) {
770        self.set_min_width(self.available_width());
771    }
772
773    /// Makes the ui always fill up the available space in the y axis.
774    ///
775    /// This can be useful to call inside a top bottom panel with
776    /// `resizable == true` to make sure the resized space is used.
777    pub fn take_available_height(&mut self) {
778        self.set_min_height(self.available_height());
779    }
780
781    // ------------------------------------------------------------------------
782
783    /// Helper: shrinks the max width to the current width,
784    /// so further widgets will try not to be wider than previous widgets.
785    /// Useful for normal vertical layouts.
786    pub fn shrink_width_to_current(&mut self) {
787        self.set_max_width(self.min_rect().width());
788    }
789
790    /// Helper: shrinks the max height to the current height,
791    /// so further widgets will try not to be taller than previous widgets.
792    pub fn shrink_height_to_current(&mut self) {
793        self.set_max_height(self.min_rect().height());
794    }
795
796    /// Expand the `min_rect` and `max_rect` of this ui to include a child at the given rect.
797    pub fn expand_to_include_rect(&mut self, rect: Rect) {
798        self.placer.expand_to_include_rect(rect);
799    }
800
801    /// `ui.set_width_range(min..=max);` is equivalent to `ui.set_min_width(min); ui.set_max_width(max);`.
802    pub fn set_width_range(&mut self, width: impl Into<Rangef>) {
803        let width = width.into();
804        self.set_min_width(width.min);
805        self.set_max_width(width.max);
806    }
807
808    /// `ui.set_height_range(min..=max);` is equivalent to `ui.set_min_height(min); ui.set_max_height(max);`.
809    pub fn set_height_range(&mut self, height: impl Into<Rangef>) {
810        let height = height.into();
811        self.set_min_height(height.min);
812        self.set_max_height(height.max);
813    }
814
815    /// Set both the minimum and maximum width.
816    pub fn set_width(&mut self, width: f32) {
817        self.set_min_width(width);
818        self.set_max_width(width);
819    }
820
821    /// Set both the minimum and maximum height.
822    pub fn set_height(&mut self, height: f32) {
823        self.set_min_height(height);
824        self.set_max_height(height);
825    }
826
827    /// Ensure we are big enough to contain the given x-coordinate.
828    /// This is sometimes useful to expand a ui to stretch to a certain place.
829    pub fn expand_to_include_x(&mut self, x: f32) {
830        self.placer.expand_to_include_x(x);
831    }
832
833    /// Ensure we are big enough to contain the given y-coordinate.
834    /// This is sometimes useful to expand a ui to stretch to a certain place.
835    pub fn expand_to_include_y(&mut self, y: f32) {
836        self.placer.expand_to_include_y(y);
837    }
838
839    // ------------------------------------------------------------------------
840    // Layout related measures:
841
842    /// The available space at the moment, given the current cursor.
843    ///
844    /// This how much more space we can take up without overflowing our parent.
845    /// Shrinks as widgets allocate space and the cursor moves.
846    /// A small size should be interpreted as "as little as possible".
847    /// An infinite size should be interpreted as "as much as you want".
848    pub fn available_size(&self) -> Vec2 {
849        self.placer.available_size()
850    }
851
852    /// The available width at the moment, given the current cursor.
853    ///
854    /// See [`Self::available_size`] for more information.
855    pub fn available_width(&self) -> f32 {
856        self.available_size().x
857    }
858
859    /// The available height at the moment, given the current cursor.
860    ///
861    /// See [`Self::available_size`] for more information.
862    pub fn available_height(&self) -> f32 {
863        self.available_size().y
864    }
865
866    /// In case of a wrapping layout, how much space is left on this row/column?
867    ///
868    /// If the layout does not wrap, this will return the same value as [`Self::available_size`].
869    pub fn available_size_before_wrap(&self) -> Vec2 {
870        self.placer.available_rect_before_wrap().size()
871    }
872
873    /// In case of a wrapping layout, how much space is left on this row/column?
874    ///
875    /// If the layout does not wrap, this will return the same value as [`Self::available_size`].
876    pub fn available_rect_before_wrap(&self) -> Rect {
877        self.placer.available_rect_before_wrap()
878    }
879}
880
881/// # [`Id`] creation
882impl Ui {
883    /// Use this to generate widget ids for widgets that have persistent state in [`Memory`].
884    pub fn make_persistent_id(&self, id_salt: impl AsIdSalt) -> Id {
885        self.id.with(id_salt)
886    }
887
888    /// This is the `Id` that will be assigned to the next widget added to this `Ui`.
889    pub fn next_auto_id(&self) -> Id {
890        Id::new(self.next_auto_id_salt)
891    }
892
893    /// Same as `ui.next_auto_id().with(id_salt)`
894    pub fn auto_id_with(&self, id_salt: impl AsIdSalt) -> Id {
895        Id::new(self.next_auto_id_salt).with(id_salt)
896    }
897
898    /// Pretend like `count` widgets have been allocated.
899    pub fn skip_ahead_auto_ids(&mut self, count: usize) {
900        self.next_auto_id_salt = self.next_auto_id_salt.wrapping_add(count as u64);
901    }
902}
903
904/// # Interaction
905impl Ui {
906    /// Check for clicks, drags and/or hover on a specific region of this [`Ui`].
907    pub fn interact(&self, rect: Rect, id: Id, sense: Sense) -> Response {
908        self.interact_opt(rect, id, sense, Default::default())
909    }
910
911    /// Check for clicks, drags and/or hover on a specific region of this [`Ui`].
912    pub fn interact_opt(
913        &self,
914        rect: Rect,
915        id: Id,
916        sense: Sense,
917        options: crate::InteractOptions,
918    ) -> Response {
919        self.ctx().register_accesskit_parent(id, self.unique_id);
920
921        self.ctx().create_widget(
922            WidgetRect {
923                id,
924                parent_id: self.id,
925                layer_id: self.layer_id(),
926                rect,
927                interact_rect: self.clip_rect().intersect(rect),
928                sense,
929                enabled: self.enabled,
930            },
931            true,
932            options,
933        )
934    }
935
936    /// Read the [`Ui`]'s background [`Response`].
937    /// Its [`Sense`] will be based on the [`UiBuilder::sense`] used to create this [`Ui`].
938    ///
939    /// The rectangle of the [`Response`] (and interactive area) will be [`Self::min_rect`]
940    /// of the last pass.
941    ///
942    /// The very first time when the [`Ui`] is created, this will return a [`Response`] with a
943    /// [`Rect`] of [`Rect::NOTHING`].
944    pub fn response(&self) -> Response {
945        // This is the inverse of Context::read_response. We prefer a response
946        // based on last frame's widget rect since the one from this frame is Rect::NOTHING until
947        // Ui::remember_min_rect is called or the Ui is dropped.
948        let mut response = self
949            .ctx()
950            .viewport(|viewport| {
951                viewport
952                    .prev_pass
953                    .widgets
954                    .get(self.unique_id)
955                    .or_else(|| viewport.this_pass.widgets.get(self.unique_id))
956                    .copied()
957            })
958            .map(|widget_rect| self.ctx().get_response(widget_rect))
959            .expect(
960                "Since we always call Context::create_widget in Ui::new, this should never be None",
961            );
962        if self.should_close() {
963            response.set_close();
964        }
965        response
966    }
967
968    /// Update the [`WidgetRect`] created in [`Ui::new`] or [`Ui::new_child`] with the current
969    /// [`Ui::min_rect`].
970    fn remember_min_rect(&mut self) -> Response {
971        self.min_rect_already_remembered = true;
972        // We remove the id from used_ids to prevent a duplicate id warning from showing
973        // when the ui was created with `UiBuilder::sense`.
974        // This is a bit hacky, is there a better way?
975        self.ctx().pass_state_mut(|fs| {
976            fs.used_ids.remove(&self.unique_id);
977        });
978        // This will update the WidgetRect that was first created in `Ui::new`.
979        let mut response = self.ctx().create_widget(
980            WidgetRect {
981                id: self.unique_id,
982                parent_id: self.id,
983                layer_id: self.layer_id(),
984                rect: self.min_rect(),
985                interact_rect: self.clip_rect().intersect(self.min_rect()),
986                sense: self.sense,
987                enabled: self.enabled,
988            },
989            false,
990            Default::default(),
991        );
992        if self.should_close() {
993            response.set_close();
994        }
995        response
996    }
997
998    /// Is the pointer (mouse/touch) above this rectangle in this [`Ui`]?
999    ///
1000    /// The `clip_rect` and layer of this [`Ui`] will be respected, so, for instance,
1001    /// if this [`Ui`] is behind some other window, this will always return `false`.
1002    ///
1003    /// However, this will NOT check if any other _widget_ in the same layer is covering this widget. For that, use [`Response::contains_pointer`] instead.
1004    pub fn rect_contains_pointer(&self, rect: Rect) -> bool {
1005        self.ctx()
1006            .rect_contains_pointer(self.layer_id(), self.clip_rect().intersect(rect))
1007    }
1008
1009    /// Is the pointer (mouse/touch) above the current [`Ui`]?
1010    ///
1011    /// Equivalent to `ui.rect_contains_pointer(ui.min_rect())`
1012    ///
1013    /// Note that this tests against the _current_ [`Ui::min_rect`].
1014    /// If you want to test against the final `min_rect`,
1015    /// use [`Self::response`] instead.
1016    pub fn ui_contains_pointer(&self) -> bool {
1017        self.rect_contains_pointer(self.min_rect())
1018    }
1019
1020    /// Find and close the first closable parent.
1021    ///
1022    /// Use [`UiBuilder::closable`] to make a [`Ui`] closable.
1023    /// You can then use [`Ui::should_close`] to check if it should be closed.
1024    ///
1025    /// This is implemented for all egui containers, e.g. [`crate::Popup`], [`crate::Modal`],
1026    /// [`crate::Area`], [`crate::Window`], [`crate::CollapsingHeader`], etc.
1027    ///
1028    /// What exactly happens when you close a container depends on the container implementation.
1029    /// [`crate::Area`] e.g. will return true from its [`Response::should_close`] method.
1030    ///
1031    /// If you want to close a specific kind of container, use [`Ui::close_kind`] instead.
1032    ///
1033    /// Also note that this won't bubble up across [`crate::Area`]s. If needed, you can check
1034    /// `response.should_close()` and close the parent manually. ([`menu`] does this for example).
1035    ///
1036    /// See also:
1037    /// - [`Ui::close_kind`]
1038    /// - [`Ui::should_close`]
1039    /// - [`Ui::will_parent_close`]
1040    pub fn close(&self) {
1041        let tag = self.stack.iter().find_map(|stack| {
1042            stack
1043                .info
1044                .tags
1045                .get_downcast::<ClosableTag>(ClosableTag::NAME)
1046        });
1047        if let Some(tag) = tag {
1048            tag.set_close();
1049        } else {
1050            log::warn!("Called ui.close() on a Ui that has no closable parent.");
1051        }
1052    }
1053
1054    /// Find and close the first closable parent of a specific [`UiKind`].
1055    ///
1056    /// This is useful if you want to e.g. close a [`crate::Window`]. Since it contains a
1057    /// `Collapsible`, [`Ui::close`] would close the `Collapsible` instead.
1058    /// You can close the [`crate::Window`] by calling `ui.close_kind(UiKind::Window)`.
1059    ///
1060    /// See also:
1061    /// - [`Ui::close`]
1062    /// - [`Ui::should_close`]
1063    /// - [`Ui::will_parent_close`]
1064    pub fn close_kind(&self, ui_kind: UiKind) {
1065        let tag = self
1066            .stack
1067            .iter()
1068            .filter(|stack| stack.info.kind == Some(ui_kind))
1069            .find_map(|stack| {
1070                stack
1071                    .info
1072                    .tags
1073                    .get_downcast::<ClosableTag>(ClosableTag::NAME)
1074            });
1075        if let Some(tag) = tag {
1076            tag.set_close();
1077        } else {
1078            log::warn!("Called ui.close_kind({ui_kind:?}) on ui with no such closable parent.");
1079        }
1080    }
1081
1082    /// Was [`Ui::close`] called on this [`Ui`] or any of its children?
1083    /// Only works if the [`Ui`] was created with [`UiBuilder::closable`].
1084    ///
1085    /// You can also check via this [`Ui`]'s [`Response::should_close`].
1086    ///
1087    /// See also:
1088    /// - [`Ui::will_parent_close`]
1089    /// - [`Ui::close`]
1090    /// - [`Ui::close_kind`]
1091    /// - [`Response::should_close`]
1092    pub fn should_close(&self) -> bool {
1093        self.stack
1094            .info
1095            .tags
1096            .get_downcast(ClosableTag::NAME)
1097            .is_some_and(|tag: &ClosableTag| tag.should_close())
1098    }
1099
1100    /// Will this [`Ui`] or any of its parents close this frame?
1101    ///
1102    /// See also
1103    /// - [`Ui::should_close`]
1104    /// - [`Ui::close`]
1105    /// - [`Ui::close_kind`]
1106    pub fn will_parent_close(&self) -> bool {
1107        self.stack.iter().any(|stack| {
1108            stack
1109                .info
1110                .tags
1111                .get_downcast::<ClosableTag>(ClosableTag::NAME)
1112                .is_some_and(|tag| tag.should_close())
1113        })
1114    }
1115}
1116
1117/// # Allocating space: where do I put my widgets?
1118impl Ui {
1119    /// Allocate space for a widget and check for interaction in the space.
1120    /// Returns a [`Response`] which contains a rectangle, id, and interaction info.
1121    ///
1122    /// ## How sizes are negotiated
1123    /// Each widget should have a *minimum desired size* and a *desired size*.
1124    /// When asking for space, ask AT LEAST for your minimum, and don't ask for more than you need.
1125    /// If you want to fill the space, ask about [`Ui::available_size`] and use that.
1126    ///
1127    /// You may get MORE space than you asked for, for instance
1128    /// for justified layouts, like in menus.
1129    ///
1130    /// You will never get a rectangle that is smaller than the amount of space you asked for.
1131    ///
1132    /// ```
1133    /// # egui::__run_test_ui(|ui| {
1134    /// let response = ui.allocate_response(egui::vec2(100.0, 200.0), egui::Sense::click());
1135    /// if response.clicked() { /* … */ }
1136    /// ui.painter().rect_stroke(response.rect, 0.0, (1.0, egui::Color32::WHITE), egui::StrokeKind::Inside);
1137    /// # });
1138    /// ```
1139    pub fn allocate_response(&mut self, desired_size: Vec2, sense: Sense) -> Response {
1140        let (id, rect) = self.allocate_space(desired_size);
1141        let mut response = self.interact(rect, id, sense);
1142        response.set_intrinsic_size(desired_size);
1143        response
1144    }
1145
1146    /// Returns a [`Rect`] with exactly what you asked for.
1147    ///
1148    /// The response rect will be larger if this is part of a justified layout or similar.
1149    /// This means that if this is a narrow widget in a wide justified layout, then
1150    /// the widget will react to interactions outside the returned [`Rect`].
1151    pub fn allocate_exact_size(&mut self, desired_size: Vec2, sense: Sense) -> (Rect, Response) {
1152        let response = self.allocate_response(desired_size, sense);
1153        let rect = self
1154            .placer
1155            .align_size_within_rect(desired_size, response.rect);
1156        (rect, response)
1157    }
1158
1159    /// Allocate at least as much space as needed, and interact with that rect.
1160    ///
1161    /// The returned [`Rect`] will be the same size as `Response::rect`.
1162    pub fn allocate_at_least(&mut self, desired_size: Vec2, sense: Sense) -> (Rect, Response) {
1163        let response = self.allocate_response(desired_size, sense);
1164        (response.rect, response)
1165    }
1166
1167    /// Reserve this much space and move the cursor.
1168    /// Returns where to put the widget.
1169    ///
1170    /// ## How sizes are negotiated
1171    /// Each widget should have a *minimum desired size* and a *desired size*.
1172    /// When asking for space, ask AT LEAST for your minimum, and don't ask for more than you need.
1173    /// If you want to fill the space, ask about [`Ui::available_size`] and use that.
1174    ///
1175    /// You may get MORE space than you asked for, for instance
1176    /// for justified layouts, like in menus.
1177    ///
1178    /// You will never get a rectangle that is smaller than the amount of space you asked for.
1179    ///
1180    /// Returns an automatic [`Id`] (which you can use for interaction) and the [`Rect`] of where to put your widget.
1181    ///
1182    /// ```
1183    /// # egui::__run_test_ui(|ui| {
1184    /// let (id, rect) = ui.allocate_space(egui::vec2(100.0, 200.0));
1185    /// let response = ui.interact(rect, id, egui::Sense::click());
1186    /// # });
1187    /// ```
1188    pub fn allocate_space(&mut self, desired_size: Vec2) -> (Id, Rect) {
1189        #[cfg(debug_assertions)]
1190        let original_available = self.available_size_before_wrap();
1191
1192        let rect = self.allocate_space_impl(desired_size);
1193
1194        #[cfg(debug_assertions)]
1195        {
1196            let too_wide = desired_size.x > original_available.x;
1197            let too_high = desired_size.y > original_available.y;
1198
1199            let debug_expand_width = self.style().debug.show_expand_width;
1200            let debug_expand_height = self.style().debug.show_expand_height;
1201
1202            if (debug_expand_width && too_wide) || (debug_expand_height && too_high) {
1203                self.painter.rect_stroke(
1204                    rect,
1205                    0.0,
1206                    (1.0, Color32::LIGHT_BLUE),
1207                    crate::StrokeKind::Inside,
1208                );
1209
1210                let stroke = crate::Stroke::new(2.5, Color32::from_rgb(200, 0, 0));
1211                let paint_line_seg = |a, b| self.painter().line_segment([a, b], stroke);
1212
1213                if debug_expand_width && too_wide {
1214                    paint_line_seg(rect.left_top(), rect.left_bottom());
1215                    paint_line_seg(rect.left_center(), rect.right_center());
1216                    paint_line_seg(
1217                        pos2(rect.left() + original_available.x, rect.top()),
1218                        pos2(rect.left() + original_available.x, rect.bottom()),
1219                    );
1220                    paint_line_seg(rect.right_top(), rect.right_bottom());
1221                }
1222
1223                if debug_expand_height && too_high {
1224                    paint_line_seg(rect.left_top(), rect.right_top());
1225                    paint_line_seg(rect.center_top(), rect.center_bottom());
1226                    paint_line_seg(rect.left_bottom(), rect.right_bottom());
1227                }
1228            }
1229        }
1230
1231        let id = Id::new(self.next_auto_id_salt);
1232        self.next_auto_id_salt = self.next_auto_id_salt.wrapping_add(1);
1233
1234        (id, rect)
1235    }
1236
1237    /// Reserve this much space and move the cursor.
1238    /// Returns where to put the widget.
1239    fn allocate_space_impl(&mut self, desired_size: Vec2) -> Rect {
1240        let item_spacing = self.spacing().item_spacing;
1241        let frame_rect = self.placer.next_space(desired_size, item_spacing);
1242        debug_assert!(!frame_rect.any_nan(), "frame_rect is nan in allocate_space");
1243        let widget_rect = self.placer.justify_and_align(frame_rect, desired_size);
1244
1245        self.placer
1246            .advance_after_rects(frame_rect, widget_rect, item_spacing);
1247
1248        register_rect(self, widget_rect);
1249
1250        widget_rect
1251    }
1252
1253    /// Allocate a specific part of the [`Ui`].
1254    ///
1255    /// Ignore the layout of the [`Ui`]: just put my widget here!
1256    /// The layout cursor will advance to past this `rect`.
1257    pub fn allocate_rect(&mut self, rect: Rect, sense: Sense) -> Response {
1258        let rect = rect.round_ui();
1259        let id = self.advance_cursor_after_rect(rect);
1260        self.interact(rect, id, sense)
1261    }
1262
1263    /// Allocate a rect without interacting with it.
1264    pub fn advance_cursor_after_rect(&mut self, rect: Rect) -> Id {
1265        debug_assert!(!rect.any_nan(), "rect is nan in advance_cursor_after_rect");
1266        let rect = rect.round_ui();
1267
1268        let item_spacing = self.spacing().item_spacing;
1269        self.placer.advance_after_rects(rect, rect, item_spacing);
1270        register_rect(self, rect);
1271
1272        let id = Id::new(self.next_auto_id_salt);
1273        self.next_auto_id_salt = self.next_auto_id_salt.wrapping_add(1);
1274        id
1275    }
1276
1277    pub(crate) fn placer(&self) -> &Placer {
1278        &self.placer
1279    }
1280
1281    /// Where the next widget will be put.
1282    ///
1283    /// One side of this will always be infinite: the direction in which new widgets will be added.
1284    /// The opposing side is what is incremented.
1285    /// The crossing sides are initialized to `max_rect`.
1286    ///
1287    /// So one can think of `cursor` as a constraint on the available region.
1288    ///
1289    /// If something has already been added, this will point to `style.spacing.item_spacing` beyond the latest child.
1290    /// The cursor can thus be `style.spacing.item_spacing` pixels outside of the `min_rect`.
1291    pub fn cursor(&self) -> Rect {
1292        self.placer.cursor()
1293    }
1294
1295    pub(crate) fn set_cursor(&mut self, cursor: Rect) {
1296        self.placer.set_cursor(cursor);
1297    }
1298
1299    /// Where do we expect a zero-sized widget to be placed?
1300    pub fn next_widget_position(&self) -> Pos2 {
1301        self.placer.next_widget_position()
1302    }
1303
1304    /// Allocated the given space and then adds content to that space.
1305    /// If the contents overflow, more space will be allocated.
1306    /// When finished, the amount of space actually used (`min_rect`) will be allocated.
1307    /// So you can request a lot of space and then use less.
1308    #[inline]
1309    pub fn allocate_ui<R>(
1310        &mut self,
1311        desired_size: Vec2,
1312        add_contents: impl FnOnce(&mut Self) -> R,
1313    ) -> InnerResponse<R> {
1314        self.allocate_ui_with_layout(desired_size, *self.layout(), add_contents)
1315    }
1316
1317    /// Allocated the given space and then adds content to that space.
1318    /// If the contents overflow, more space will be allocated.
1319    /// When finished, the amount of space actually used (`min_rect`) will be allocated.
1320    /// So you can request a lot of space and then use less.
1321    #[inline]
1322    pub fn allocate_ui_with_layout<R>(
1323        &mut self,
1324        desired_size: Vec2,
1325        layout: Layout,
1326        add_contents: impl FnOnce(&mut Self) -> R,
1327    ) -> InnerResponse<R> {
1328        self.allocate_ui_with_layout_dyn(desired_size, layout, Box::new(add_contents))
1329    }
1330
1331    fn allocate_ui_with_layout_dyn<'c, R>(
1332        &mut self,
1333        desired_size: Vec2,
1334        layout: Layout,
1335        add_contents: Box<dyn FnOnce(&mut Self) -> R + 'c>,
1336    ) -> InnerResponse<R> {
1337        debug_assert!(
1338            desired_size.x >= 0.0 && desired_size.y >= 0.0,
1339            "Negative desired size: {desired_size:?}"
1340        );
1341        let item_spacing = self.spacing().item_spacing;
1342        let frame_rect = self.placer.next_space(desired_size, item_spacing);
1343        let child_rect = self.placer.justify_and_align(frame_rect, desired_size);
1344        self.scope_dyn(
1345            UiBuilder::new().max_rect(child_rect).layout(layout),
1346            add_contents,
1347        )
1348    }
1349
1350    /// Convenience function to get a region to paint on.
1351    ///
1352    /// Note that egui uses screen coordinates for everything.
1353    ///
1354    /// ```
1355    /// # use egui::*;
1356    /// # use std::f32::consts::TAU;
1357    /// # egui::__run_test_ui(|ui| {
1358    /// let size = Vec2::splat(16.0);
1359    /// let (response, painter) = ui.allocate_painter(size, Sense::hover());
1360    /// let rect = response.rect;
1361    /// let c = rect.center();
1362    /// let r = rect.width() / 2.0 - 1.0;
1363    /// let color = Color32::from_gray(128);
1364    /// let stroke = Stroke::new(1.0, color);
1365    /// painter.circle_stroke(c, r, stroke);
1366    /// painter.line_segment([c - vec2(0.0, r), c + vec2(0.0, r)], stroke);
1367    /// painter.line_segment([c, c + r * Vec2::angled(TAU * 1.0 / 8.0)], stroke);
1368    /// painter.line_segment([c, c + r * Vec2::angled(TAU * 3.0 / 8.0)], stroke);
1369    /// # });
1370    /// ```
1371    pub fn allocate_painter(&mut self, desired_size: Vec2, sense: Sense) -> (Response, Painter) {
1372        let response = self.allocate_response(desired_size, sense);
1373        let clip_rect = self.clip_rect().intersect(response.rect); // Make sure we don't paint out of bounds
1374        let painter = self.painter().with_clip_rect(clip_rect);
1375        (response, painter)
1376    }
1377}
1378
1379/// # Scrolling
1380impl Ui {
1381    /// Adjust the scroll position of any parent [`crate::ScrollArea`] so that the given [`Rect`] becomes visible.
1382    ///
1383    /// If `align` is [`Align::TOP`] it means "put the top of the rect at the top of the scroll area", etc.
1384    /// If `align` is `None`, it'll scroll enough to bring the cursor into view.
1385    ///
1386    /// See also: [`Response::scroll_to_me`], [`Ui::scroll_to_cursor`]. [`Ui::scroll_with_delta`]..
1387    ///
1388    /// ```
1389    /// # use egui::Align;
1390    /// # egui::__run_test_ui(|ui| {
1391    /// egui::ScrollArea::vertical().show(ui, |ui| {
1392    ///     // …
1393    ///     let response = ui.button("Center on me.");
1394    ///     if response.clicked() {
1395    ///         ui.scroll_to_rect(response.rect, Some(Align::Center));
1396    ///     }
1397    /// });
1398    /// # });
1399    /// ```
1400    pub fn scroll_to_rect(&self, rect: Rect, align: Option<Align>) {
1401        self.scroll_to_rect_animation(rect, align, self.style.scroll_animation);
1402    }
1403
1404    /// Same as [`Self::scroll_to_rect`], but allows you to specify the [`style::ScrollAnimation`].
1405    pub fn scroll_to_rect_animation(
1406        &self,
1407        rect: Rect,
1408        align: Option<Align>,
1409        animation: style::ScrollAnimation,
1410    ) {
1411        for d in 0..2 {
1412            let range = Rangef::new(rect.min[d], rect.max[d]);
1413            self.ctx().pass_state_mut(|state| {
1414                state.scroll_target[d] =
1415                    Some(pass_state::ScrollTarget::new(range, align, animation));
1416            });
1417        }
1418    }
1419
1420    /// Adjust the scroll position of any parent [`crate::ScrollArea`] so that the cursor (where the next widget goes) becomes visible.
1421    ///
1422    /// If `align` is [`Align::TOP`] it means "put the top of the rect at the top of the scroll area", etc.
1423    /// If `align` is not provided, it'll scroll enough to bring the cursor into view.
1424    ///
1425    /// See also: [`Response::scroll_to_me`], [`Ui::scroll_to_rect`]. [`Ui::scroll_with_delta`].
1426    ///
1427    /// ```
1428    /// # use egui::Align;
1429    /// # egui::__run_test_ui(|ui| {
1430    /// egui::ScrollArea::vertical().show(ui, |ui| {
1431    ///     let scroll_bottom = ui.button("Scroll to bottom.").clicked();
1432    ///     for i in 0..1000 {
1433    ///         ui.label(format!("Item {}", i));
1434    ///     }
1435    ///
1436    ///     if scroll_bottom {
1437    ///         ui.scroll_to_cursor(Some(Align::BOTTOM));
1438    ///     }
1439    /// });
1440    /// # });
1441    /// ```
1442    pub fn scroll_to_cursor(&self, align: Option<Align>) {
1443        self.scroll_to_cursor_animation(align, self.style.scroll_animation);
1444    }
1445
1446    /// Same as [`Self::scroll_to_cursor`], but allows you to specify the [`style::ScrollAnimation`].
1447    pub fn scroll_to_cursor_animation(
1448        &self,
1449        align: Option<Align>,
1450        animation: style::ScrollAnimation,
1451    ) {
1452        let target = self.next_widget_position();
1453        for d in 0..2 {
1454            let target = Rangef::point(target[d]);
1455            self.ctx().pass_state_mut(|state| {
1456                state.scroll_target[d] =
1457                    Some(pass_state::ScrollTarget::new(target, align, animation));
1458            });
1459        }
1460    }
1461
1462    /// Scroll this many points in the given direction, in the parent [`crate::ScrollArea`].
1463    ///
1464    /// The delta dictates how the _content_ (i.e. this UI) should move.
1465    ///
1466    /// A positive X-value indicates the content is being moved right,
1467    /// as when swiping right on a touch-screen or track-pad with natural scrolling.
1468    ///
1469    /// A positive Y-value indicates the content is being moved down,
1470    /// as when swiping down on a touch-screen or track-pad with natural scrolling.
1471    ///
1472    /// If this is called multiple times per frame for the same [`crate::ScrollArea`], the deltas will be summed.
1473    ///
1474    /// See also: [`Response::scroll_to_me`], [`Ui::scroll_to_rect`], [`Ui::scroll_to_cursor`]
1475    ///
1476    /// ```
1477    /// # use egui::{Align, Vec2};
1478    /// # egui::__run_test_ui(|ui| {
1479    /// let mut scroll_delta = Vec2::ZERO;
1480    /// if ui.button("Scroll down").clicked() {
1481    ///     scroll_delta.y -= 64.0; // move content up
1482    /// }
1483    /// egui::ScrollArea::vertical().show(ui, |ui| {
1484    ///     ui.scroll_with_delta(scroll_delta);
1485    ///     for i in 0..1000 {
1486    ///         ui.label(format!("Item {}", i));
1487    ///     }
1488    /// });
1489    /// # });
1490    /// ```
1491    pub fn scroll_with_delta(&self, delta: Vec2) {
1492        self.scroll_with_delta_animation(delta, self.style.scroll_animation);
1493    }
1494
1495    /// Same as [`Self::scroll_with_delta`], but allows you to specify the [`style::ScrollAnimation`].
1496    pub fn scroll_with_delta_animation(&self, delta: Vec2, animation: style::ScrollAnimation) {
1497        self.ctx().pass_state_mut(|state| {
1498            state.scroll_delta.0 += delta;
1499            state.scroll_delta.1 = animation;
1500        });
1501    }
1502}
1503
1504/// # Adding widgets
1505impl Ui {
1506    /// Add a [`Widget`] to this [`Ui`] at a location dependent on the current [`Layout`].
1507    ///
1508    /// The returned [`Response`] can be used to check for interactions,
1509    /// as well as adding tooltips using [`Response::on_hover_text`].
1510    ///
1511    /// See also [`Self::add_sized`], [`Self::place`] and [`Self::put`].
1512    ///
1513    /// ```
1514    /// # egui::__run_test_ui(|ui| {
1515    /// # let mut my_value = 42;
1516    /// let response = ui.add(egui::Slider::new(&mut my_value, 0..=100));
1517    /// response.on_hover_text("Drag me!");
1518    /// # });
1519    /// ```
1520    #[inline]
1521    pub fn add(&mut self, widget: impl Widget) -> Response {
1522        widget.ui(self)
1523    }
1524
1525    /// Add a [`Widget`] to this [`Ui`] with a given size.
1526    /// The widget will attempt to fit within the given size, but some widgets may overflow.
1527    ///
1528    /// To fill all remaining area, use `ui.add_sized(ui.available_size(), widget);`
1529    ///
1530    /// See also [`Self::add`], [`Self::place`] and [`Self::put`].
1531    ///
1532    /// ```
1533    /// # egui::__run_test_ui(|ui| {
1534    /// # let mut my_value = 42;
1535    /// ui.add_sized([40.0, 20.0], egui::DragValue::new(&mut my_value));
1536    /// # });
1537    /// ```
1538    pub fn add_sized(&mut self, max_size: impl Into<Vec2>, widget: impl Widget) -> Response {
1539        // TODO(emilk): configure to overflow to main_dir instead of centered overflow
1540        // to handle the bug mentioned at https://github.com/emilk/egui/discussions/318#discussioncomment-627578
1541        // and fixed in https://github.com/emilk/egui/commit/035166276322b3f2324bd8b97ffcedc63fa8419f
1542        //
1543        // Make sure we keep the same main direction since it changes e.g. how text is wrapped:
1544        let layout = Layout::centered_and_justified(self.layout().main_dir());
1545        self.allocate_ui_with_layout(max_size.into(), layout, |ui| ui.add(widget))
1546            .inner
1547    }
1548
1549    /// Add a [`Widget`] to this [`Ui`] at a specific location (manual layout) without
1550    /// affecting this [`Ui`]s cursor.
1551    ///
1552    /// See also [`Self::add`] and [`Self::add_sized`] and [`Self::put`].
1553    pub fn place(&mut self, max_rect: Rect, widget: impl Widget) -> Response {
1554        self.new_child(
1555            UiBuilder::new()
1556                .max_rect(max_rect)
1557                .layout(Layout::centered_and_justified(Direction::TopDown)),
1558        )
1559        .add(widget)
1560    }
1561
1562    /// Add a [`Widget`] to this [`Ui`] at a specific location (manual layout) and advance the
1563    /// cursor after the widget.
1564    ///
1565    /// See also [`Self::add`], [`Self::add_sized`], and [`Self::place`].
1566    pub fn put(&mut self, max_rect: Rect, widget: impl Widget) -> Response {
1567        self.scope_builder(
1568            UiBuilder::new()
1569                .max_rect(max_rect)
1570                .layout(Layout::centered_and_justified(Direction::TopDown)),
1571            |ui| ui.add(widget),
1572        )
1573        .inner
1574    }
1575
1576    /// Add a single [`Widget`] that is possibly disabled, i.e. greyed out and non-interactive.
1577    ///
1578    /// If you call `add_enabled` from within an already disabled [`Ui`],
1579    /// the widget will always be disabled, even if the `enabled` argument is true.
1580    ///
1581    /// See also [`Self::add_enabled_ui`] and [`Self::is_enabled`].
1582    ///
1583    /// ```
1584    /// # egui::__run_test_ui(|ui| {
1585    /// ui.add_enabled(false, egui::Button::new("Can't click this"));
1586    /// # });
1587    /// ```
1588    pub fn add_enabled(&mut self, enabled: bool, widget: impl Widget) -> Response {
1589        if self.is_enabled() && !enabled {
1590            let old_painter = self.painter.clone();
1591            self.disable();
1592            let response = self.add(widget);
1593            self.enabled = true;
1594            self.painter = old_painter;
1595            response
1596        } else {
1597            self.add(widget)
1598        }
1599    }
1600
1601    /// Add a section that is possibly disabled, i.e. greyed out and non-interactive.
1602    ///
1603    /// If you call `add_enabled_ui` from within an already disabled [`Ui`],
1604    /// the result will always be disabled, even if the `enabled` argument is true.
1605    ///
1606    /// See also [`Self::add_enabled`] and [`Self::is_enabled`].
1607    ///
1608    /// ### Example
1609    /// ```
1610    /// # egui::__run_test_ui(|ui| {
1611    /// # let mut enabled = true;
1612    /// ui.checkbox(&mut enabled, "Enable subsection");
1613    /// ui.add_enabled_ui(enabled, |ui| {
1614    ///     if ui.button("Button that is not always clickable").clicked() {
1615    ///         /* … */
1616    ///     }
1617    /// });
1618    /// # });
1619    /// ```
1620    pub fn add_enabled_ui<R>(
1621        &mut self,
1622        enabled: bool,
1623        add_contents: impl FnOnce(&mut Ui) -> R,
1624    ) -> InnerResponse<R> {
1625        self.scope(|ui| {
1626            if !enabled {
1627                ui.disable();
1628            }
1629            add_contents(ui)
1630        })
1631    }
1632
1633    /// Add a single [`Widget`] that is possibly invisible.
1634    ///
1635    /// An invisible widget still takes up the same space as if it were visible.
1636    ///
1637    /// If you call `add_visible` from within an already invisible [`Ui`],
1638    /// the widget will always be invisible, even if the `visible` argument is true.
1639    ///
1640    /// See also [`Self::set_invisible`] and [`Self::is_visible`].
1641    ///
1642    /// ```
1643    /// # egui::__run_test_ui(|ui| {
1644    /// ui.add_visible(false, egui::Label::new("You won't see me!"));
1645    /// # });
1646    /// ```
1647    pub fn add_visible(&mut self, visible: bool, widget: impl Widget) -> Response {
1648        if self.is_visible() && !visible {
1649            // temporary make us invisible:
1650            let old_painter = self.painter.clone();
1651            let old_enabled = self.enabled;
1652
1653            self.set_invisible();
1654
1655            let response = self.add(widget);
1656
1657            self.painter = old_painter;
1658            self.enabled = old_enabled;
1659            response
1660        } else {
1661            self.add(widget)
1662        }
1663    }
1664
1665    /// Add extra space before the next widget.
1666    ///
1667    /// The direction is dependent on the layout.
1668    /// Note that `add_space` isn't supported when in a grid layout.
1669    ///
1670    /// This will be in addition to the [`crate::style::Spacing::item_spacing`]
1671    /// that is always added, but `item_spacing` won't be added _again_ by `add_space`.
1672    ///
1673    /// [`Self::min_rect`] will expand to contain the space.
1674    #[inline]
1675    pub fn add_space(&mut self, amount: f32) {
1676        debug_assert!(!self.is_grid(), "add_space makes no sense in a grid layout");
1677        self.placer.advance_cursor(amount.round_ui());
1678    }
1679
1680    /// Show some text.
1681    ///
1682    /// Shortcut for `add(Label::new(text))`
1683    ///
1684    /// See also [`Label`].
1685    ///
1686    /// ### Example
1687    /// ```
1688    /// # egui::__run_test_ui(|ui| {
1689    /// use egui::{RichText, FontId, Color32};
1690    /// ui.label("Normal text");
1691    /// ui.label(RichText::new("Large text").font(FontId::proportional(40.0)));
1692    /// ui.label(RichText::new("Red text").color(Color32::RED));
1693    /// # });
1694    /// ```
1695    #[inline]
1696    pub fn label(&mut self, text: impl Into<WidgetText>) -> Response {
1697        Label::new(text).ui(self)
1698    }
1699
1700    /// Show colored text.
1701    ///
1702    /// Shortcut for `ui.label(RichText::new(text).color(color))`
1703    pub fn colored_label(
1704        &mut self,
1705        color: impl Into<Color32>,
1706        text: impl Into<RichText>,
1707    ) -> Response {
1708        Label::new(text.into().color(color)).ui(self)
1709    }
1710
1711    /// Show large text.
1712    ///
1713    /// Shortcut for `ui.label(RichText::new(text).heading())`
1714    pub fn heading(&mut self, text: impl Into<RichText>) -> Response {
1715        Label::new(text.into().heading()).ui(self)
1716    }
1717
1718    /// Show monospace (fixed width) text.
1719    ///
1720    /// Shortcut for `ui.label(RichText::new(text).monospace())`
1721    pub fn monospace(&mut self, text: impl Into<RichText>) -> Response {
1722        Label::new(text.into().monospace()).ui(self)
1723    }
1724
1725    /// Show text as monospace with a gray background.
1726    ///
1727    /// Shortcut for `ui.label(RichText::new(text).code())`
1728    pub fn code(&mut self, text: impl Into<RichText>) -> Response {
1729        Label::new(text.into().code()).ui(self)
1730    }
1731
1732    /// Show small text.
1733    ///
1734    /// Shortcut for `ui.label(RichText::new(text).small())`
1735    pub fn small(&mut self, text: impl Into<RichText>) -> Response {
1736        Label::new(text.into().small()).ui(self)
1737    }
1738
1739    /// Show text that stand out a bit (e.g. slightly brighter).
1740    ///
1741    /// Shortcut for `ui.label(RichText::new(text).strong())`
1742    pub fn strong(&mut self, text: impl Into<RichText>) -> Response {
1743        Label::new(text.into().strong()).ui(self)
1744    }
1745
1746    /// Show text that is weaker (fainter color).
1747    ///
1748    /// Shortcut for `ui.label(RichText::new(text).weak())`
1749    pub fn weak(&mut self, text: impl Into<RichText>) -> Response {
1750        Label::new(text.into().weak()).ui(self)
1751    }
1752
1753    /// Looks like a hyperlink.
1754    ///
1755    /// Shortcut for `add(Link::new(text))`.
1756    ///
1757    /// ```
1758    /// # egui::__run_test_ui(|ui| {
1759    /// if ui.link("Documentation").clicked() {
1760    ///     // …
1761    /// }
1762    /// # });
1763    /// ```
1764    ///
1765    /// See also [`Link`].
1766    #[must_use = "You should check if the user clicked this with `if ui.link(…).clicked() { … } "]
1767    pub fn link(&mut self, text: impl Into<WidgetText>) -> Response {
1768        Link::new(text).ui(self)
1769    }
1770
1771    /// Link to a web page.
1772    ///
1773    /// Shortcut for `add(Hyperlink::new(url))`.
1774    ///
1775    /// ```
1776    /// # egui::__run_test_ui(|ui| {
1777    /// ui.hyperlink("https://www.egui.rs/");
1778    /// # });
1779    /// ```
1780    ///
1781    /// See also [`Hyperlink`].
1782    pub fn hyperlink(&mut self, url: impl ToString) -> Response {
1783        Hyperlink::new(url).ui(self)
1784    }
1785
1786    /// Shortcut for `add(Hyperlink::from_label_and_url(label, url))`.
1787    ///
1788    /// ```
1789    /// # egui::__run_test_ui(|ui| {
1790    /// ui.hyperlink_to("egui on GitHub", "https://www.github.com/emilk/egui/");
1791    /// # });
1792    /// ```
1793    ///
1794    /// See also [`Hyperlink`].
1795    pub fn hyperlink_to(&mut self, label: impl Into<WidgetText>, url: impl ToString) -> Response {
1796        Hyperlink::from_label_and_url(label, url).ui(self)
1797    }
1798
1799    /// No newlines (`\n`) allowed. Pressing enter key will result in the [`TextEdit`] losing focus (`response.lost_focus`).
1800    ///
1801    /// See also [`TextEdit`].
1802    pub fn text_edit_singleline<S: widgets::text_edit::TextBuffer>(
1803        &mut self,
1804        text: &mut S,
1805    ) -> Response {
1806        TextEdit::singleline(text).ui(self)
1807    }
1808
1809    /// A [`TextEdit`] for multiple lines. Pressing enter key will create a new line.
1810    ///
1811    /// See also [`TextEdit`].
1812    pub fn text_edit_multiline<S: widgets::text_edit::TextBuffer>(
1813        &mut self,
1814        text: &mut S,
1815    ) -> Response {
1816        TextEdit::multiline(text).ui(self)
1817    }
1818
1819    /// A [`TextEdit`] for code editing.
1820    ///
1821    /// This will be multiline, monospace, and will insert tabs instead of moving focus.
1822    ///
1823    /// See also [`TextEdit::code_editor`].
1824    pub fn code_editor<S: widgets::text_edit::TextBuffer>(&mut self, text: &mut S) -> Response {
1825        self.add(TextEdit::multiline(text).code_editor())
1826    }
1827
1828    /// Usage: `if ui.button("Click me").clicked() { … }`
1829    ///
1830    /// Shortcut for `add(Button::new(text))`
1831    ///
1832    /// See also [`Button`].
1833    ///
1834    /// ```
1835    /// # egui::__run_test_ui(|ui| {
1836    /// if ui.button("Click me!").clicked() {
1837    ///     // …
1838    /// }
1839    ///
1840    /// # use egui::{RichText, Color32};
1841    /// if ui.button(RichText::new("delete").color(Color32::RED)).clicked() {
1842    ///     // …
1843    /// }
1844    /// # });
1845    /// ```
1846    #[must_use = "You should check if the user clicked this with `if ui.button(…).clicked() { … } "]
1847    #[inline]
1848    pub fn button<'a>(&mut self, atoms: impl IntoAtoms<'a>) -> Response {
1849        Button::new(atoms).ui(self)
1850    }
1851
1852    /// A button as small as normal body text.
1853    ///
1854    /// Usage: `if ui.small_button("Click me").clicked() { … }`
1855    ///
1856    /// Shortcut for `add(Button::new(atoms).small())`
1857    #[must_use = "You should check if the user clicked this with `if ui.small_button(…).clicked() { … } "]
1858    pub fn small_button<'a>(&mut self, atoms: impl IntoAtoms<'a>) -> Response {
1859        Button::new(atoms).small().ui(self)
1860    }
1861
1862    /// Show a checkbox.
1863    ///
1864    /// See also [`Self::toggle_value`].
1865    #[inline]
1866    pub fn checkbox<'a>(&mut self, checked: &'a mut bool, atoms: impl IntoAtoms<'a>) -> Response {
1867        Checkbox::new(checked, atoms).ui(self)
1868    }
1869
1870    /// Acts like a checkbox, but looks like a [`Button::selectable`].
1871    ///
1872    /// Click to toggle to bool.
1873    ///
1874    /// See also [`Self::checkbox`].
1875    pub fn toggle_value<'a>(&mut self, selected: &mut bool, atoms: impl IntoAtoms<'a>) -> Response {
1876        let mut response = self.selectable_label(*selected, atoms);
1877        if response.clicked() {
1878            *selected = !*selected;
1879            response.mark_changed();
1880        }
1881        response
1882    }
1883
1884    /// Show a [`RadioButton`].
1885    /// Often you want to use [`Self::radio_value`] instead.
1886    #[must_use = "You should check if the user clicked this with `if ui.radio(…).clicked() { … } "]
1887    #[inline]
1888    pub fn radio<'a>(&mut self, selected: bool, atoms: impl IntoAtoms<'a>) -> Response {
1889        RadioButton::new(selected, atoms).ui(self)
1890    }
1891
1892    /// Show a [`RadioButton`]. It is selected if `*current_value == selected_value`.
1893    /// If clicked, `selected_value` is assigned to `*current_value`.
1894    ///
1895    /// ```
1896    /// # egui::__run_test_ui(|ui| {
1897    ///
1898    /// #[derive(PartialEq)]
1899    /// enum Enum { First, Second, Third }
1900    /// let mut my_enum = Enum::First;
1901    ///
1902    /// ui.radio_value(&mut my_enum, Enum::First, "First");
1903    ///
1904    /// // is equivalent to:
1905    ///
1906    /// if ui.add(egui::RadioButton::new(my_enum == Enum::First, "First")).clicked() {
1907    ///     my_enum = Enum::First
1908    /// }
1909    /// # });
1910    /// ```
1911    pub fn radio_value<'a, Value: PartialEq>(
1912        &mut self,
1913        current_value: &mut Value,
1914        alternative: Value,
1915        atoms: impl IntoAtoms<'a>,
1916    ) -> Response {
1917        let mut response = self.radio(*current_value == alternative, atoms);
1918        if response.clicked() && *current_value != alternative {
1919            *current_value = alternative;
1920            response.mark_changed();
1921        }
1922        response
1923    }
1924
1925    /// Show a label which can be selected or not.
1926    ///
1927    /// See also [`Button::selectable`] and [`Self::toggle_value`].
1928    #[must_use = "You should check if the user clicked this with `if ui.selectable_label(…).clicked() { … } "]
1929    pub fn selectable_label<'a>(&mut self, checked: bool, text: impl IntoAtoms<'a>) -> Response {
1930        Button::selectable(checked, text).ui(self)
1931    }
1932
1933    /// Show selectable text. It is selected if `*current_value == selected_value`.
1934    /// If clicked, `selected_value` is assigned to `*current_value`.
1935    ///
1936    /// Example: `ui.selectable_value(&mut my_enum, Enum::Alternative, "Alternative")`.
1937    ///
1938    /// See also [`Button::selectable`] and [`Self::toggle_value`].
1939    pub fn selectable_value<'a, Value: PartialEq>(
1940        &mut self,
1941        current_value: &mut Value,
1942        selected_value: Value,
1943        text: impl IntoAtoms<'a>,
1944    ) -> Response {
1945        let mut response = self.selectable_label(*current_value == selected_value, text);
1946        if response.clicked() && *current_value != selected_value {
1947            *current_value = selected_value;
1948            response.mark_changed();
1949        }
1950        response
1951    }
1952
1953    /// Shortcut for `add(Separator::default())`
1954    ///
1955    /// See also [`Separator`].
1956    #[inline]
1957    pub fn separator(&mut self) -> Response {
1958        Separator::default().ui(self)
1959    }
1960
1961    /// Shortcut for `add(Spinner::new())`
1962    ///
1963    /// See also [`Spinner`].
1964    #[inline]
1965    pub fn spinner(&mut self) -> Response {
1966        Spinner::new().ui(self)
1967    }
1968
1969    /// Modify an angle. The given angle should be in radians, but is shown to the user in degrees.
1970    /// The angle is NOT wrapped, so the user may select, for instance 720° = 2𝞃 = 4π
1971    pub fn drag_angle(&mut self, radians: &mut f32) -> Response {
1972        let mut degrees = radians.to_degrees();
1973        let mut response = self.add(DragValue::new(&mut degrees).speed(1.0).suffix("°"));
1974
1975        // only touch `*radians` if we actually changed the degree value
1976        if degrees != radians.to_degrees() {
1977            *radians = degrees.to_radians();
1978            response.mark_changed();
1979        }
1980
1981        response
1982    }
1983
1984    /// Modify an angle. The given angle should be in radians,
1985    /// but is shown to the user in fractions of one Tau (i.e. fractions of one turn).
1986    /// The angle is NOT wrapped, so the user may select, for instance 2𝞃 (720°)
1987    pub fn drag_angle_tau(&mut self, radians: &mut f32) -> Response {
1988        use core::f32::consts::TAU;
1989
1990        let mut taus = *radians / TAU;
1991        let mut response = self.add(DragValue::new(&mut taus).speed(0.01).suffix("τ"));
1992
1993        if self.style().explanation_tooltips {
1994            response =
1995                response.on_hover_text("1τ = one turn, 0.5τ = half a turn, etc. 0.25τ = 90°");
1996        }
1997
1998        // only touch `*radians` if we actually changed the value
1999        if taus != *radians / TAU {
2000            *radians = taus * TAU;
2001            response.mark_changed();
2002        }
2003
2004        response
2005    }
2006
2007    /// Show an image available at the given `uri`.
2008    ///
2009    /// ⚠ This will do nothing unless you install some image loaders first!
2010    /// The easiest way to do this is via [`egui_extras::install_image_loaders`](https://docs.rs/egui_extras/latest/egui_extras/loaders/fn.install_image_loaders.html).
2011    ///
2012    /// The loaders handle caching image data, sampled textures, etc. across frames, so calling this is immediate-mode safe.
2013    ///
2014    /// ```
2015    /// # egui::__run_test_ui(|ui| {
2016    /// ui.image("https://picsum.photos/480");
2017    /// ui.image("file://assets/ferris.png");
2018    /// ui.image(egui::include_image!("../assets/ferris.png"));
2019    /// ui.add(
2020    ///     egui::Image::new(egui::include_image!("../assets/ferris.png"))
2021    ///         .max_width(200.0)
2022    ///         .corner_radius(10),
2023    /// );
2024    /// # });
2025    /// ```
2026    ///
2027    /// Using [`crate::include_image`] is often the most ergonomic, and the path
2028    /// will be resolved at compile-time and embedded in the binary.
2029    /// When using a "file://" url on the other hand, you need to make sure
2030    /// the files can be found in the right spot at runtime!
2031    ///
2032    /// See also [`crate::Image`], [`crate::ImageSource`].
2033    #[inline]
2034    pub fn image<'a>(&mut self, source: impl Into<ImageSource<'a>>) -> Response {
2035        Image::new(source).ui(self)
2036    }
2037}
2038
2039/// # Colors
2040impl Ui {
2041    /// Shows a button with the given color.
2042    ///
2043    /// If the user clicks the button, a full color picker is shown.
2044    pub fn color_edit_button_srgba(&mut self, srgba: &mut Color32) -> Response {
2045        color_picker::color_edit_button_srgba(self, srgba, color_picker::Alpha::BlendOrAdditive)
2046    }
2047
2048    /// Shows a button with the given color.
2049    ///
2050    /// If the user clicks the button, a full color picker is shown.
2051    pub fn color_edit_button_hsva(&mut self, hsva: &mut Hsva) -> Response {
2052        color_picker::color_edit_button_hsva(self, hsva, color_picker::Alpha::BlendOrAdditive)
2053    }
2054
2055    /// Shows a button with the given color.
2056    ///
2057    /// If the user clicks the button, a full color picker is shown.
2058    /// The given color is in `sRGB` space.
2059    pub fn color_edit_button_srgb(&mut self, srgb: &mut [u8; 3]) -> Response {
2060        color_picker::color_edit_button_srgb(self, srgb)
2061    }
2062
2063    /// Shows a button with the given color.
2064    ///
2065    /// If the user clicks the button, a full color picker is shown.
2066    /// The given color is in linear RGB space.
2067    pub fn color_edit_button_rgb(&mut self, rgb: &mut [f32; 3]) -> Response {
2068        color_picker::color_edit_button_rgb(self, rgb)
2069    }
2070
2071    /// Shows a button with the given color.
2072    ///
2073    /// If the user clicks the button, a full color picker is shown.
2074    /// The given color is in `sRGBA` space with premultiplied alpha
2075    pub fn color_edit_button_srgba_premultiplied(&mut self, srgba: &mut [u8; 4]) -> Response {
2076        let mut color = Color32::from_rgba_premultiplied(srgba[0], srgba[1], srgba[2], srgba[3]);
2077        let response = self.color_edit_button_srgba(&mut color);
2078        *srgba = color.to_array();
2079        response
2080    }
2081
2082    /// Shows a button with the given color.
2083    ///
2084    /// If the user clicks the button, a full color picker is shown.
2085    /// The given color is in `sRGBA` space without premultiplied alpha.
2086    /// If unsure what "premultiplied alpha" is, then this is probably the function you want to use.
2087    pub fn color_edit_button_srgba_unmultiplied(&mut self, srgba: &mut [u8; 4]) -> Response {
2088        let mut rgba = Rgba::from_srgba_unmultiplied(srgba[0], srgba[1], srgba[2], srgba[3]);
2089        let response =
2090            color_picker::color_edit_button_rgba(self, &mut rgba, color_picker::Alpha::OnlyBlend);
2091        *srgba = rgba.to_srgba_unmultiplied();
2092        response
2093    }
2094
2095    /// Shows a button with the given color.
2096    ///
2097    /// If the user clicks the button, a full color picker is shown.
2098    /// The given color is in linear RGBA space with premultiplied alpha
2099    pub fn color_edit_button_rgba_premultiplied(&mut self, rgba_premul: &mut [f32; 4]) -> Response {
2100        let mut rgba = Rgba::from_rgba_premultiplied(
2101            rgba_premul[0],
2102            rgba_premul[1],
2103            rgba_premul[2],
2104            rgba_premul[3],
2105        );
2106        let response = color_picker::color_edit_button_rgba(
2107            self,
2108            &mut rgba,
2109            color_picker::Alpha::BlendOrAdditive,
2110        );
2111        *rgba_premul = rgba.to_array();
2112        response
2113    }
2114
2115    /// Shows a button with the given color.
2116    ///
2117    /// If the user clicks the button, a full color picker is shown.
2118    /// The given color is in linear RGBA space without premultiplied alpha.
2119    /// If unsure, what "premultiplied alpha" is, then this is probably the function you want to use.
2120    pub fn color_edit_button_rgba_unmultiplied(&mut self, rgba_unmul: &mut [f32; 4]) -> Response {
2121        let mut rgba = Rgba::from_rgba_unmultiplied(
2122            rgba_unmul[0],
2123            rgba_unmul[1],
2124            rgba_unmul[2],
2125            rgba_unmul[3],
2126        );
2127        let response =
2128            color_picker::color_edit_button_rgba(self, &mut rgba, color_picker::Alpha::OnlyBlend);
2129        *rgba_unmul = rgba.to_rgba_unmultiplied();
2130        response
2131    }
2132}
2133
2134/// # Adding Containers / Sub-uis:
2135impl Ui {
2136    /// Put into a [`Frame::group`], visually grouping the contents together
2137    ///
2138    /// ```
2139    /// # egui::__run_test_ui(|ui| {
2140    /// ui.group(|ui| {
2141    ///     ui.label("Within a frame");
2142    /// });
2143    /// # });
2144    /// ```
2145    ///
2146    /// See also [`Self::scope`].
2147    pub fn group<R>(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
2148        crate::Frame::group(self.style()).show(self, add_contents)
2149    }
2150
2151    /// Create a child Ui with an explicit [`Id`].
2152    ///
2153    /// ```
2154    /// # egui::__run_test_ui(|ui| {
2155    /// for i in 0..10 {
2156    ///     // ui.collapsing("Same header", |ui| { }); // this will cause an ID clash because of the same title!
2157    ///
2158    ///     ui.push_id(i, |ui| {
2159    ///         ui.collapsing("Same header", |ui| { }); // this is fine!
2160    ///     });
2161    /// }
2162    /// # });
2163    /// ```
2164    pub fn push_id<R>(
2165        &mut self,
2166        id_salt: impl AsIdSalt,
2167        add_contents: impl FnOnce(&mut Ui) -> R,
2168    ) -> InnerResponse<R> {
2169        self.scope_dyn(UiBuilder::new().id_salt(id_salt), Box::new(add_contents))
2170    }
2171
2172    /// Create a scoped child ui.
2173    ///
2174    /// You can use this to temporarily change the [`Style`] of a sub-region, for instance:
2175    ///
2176    /// ```
2177    /// # egui::__run_test_ui(|ui| {
2178    /// ui.scope(|ui| {
2179    ///     ui.spacing_mut().slider_width = 200.0; // Temporary change
2180    ///     // …
2181    /// });
2182    /// # });
2183    /// ```
2184    ///
2185    /// See also [`Self::scope_builder`] for more options.
2186    pub fn scope<R>(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
2187        self.scope_dyn(UiBuilder::new(), Box::new(add_contents))
2188    }
2189
2190    /// Create a scoped child ui, inheriting properties from the parent as specified by the [`UiBuilder`].
2191    /// In contrast to [`Self::new_child`], this allocates the space used by the child.
2192    ///
2193    /// See also [`Self::scope`] and [`Self::scope_dyn`].
2194    pub fn scope_builder<R>(
2195        &mut self,
2196        ui_builder: UiBuilder,
2197        add_contents: impl FnOnce(&mut Ui) -> R,
2198    ) -> InnerResponse<R> {
2199        self.scope_dyn(ui_builder, Box::new(add_contents))
2200    }
2201
2202    /// [`Self::scope_builder`] but with dynamic dispatch.
2203    pub fn scope_dyn<'c, R>(
2204        &mut self,
2205        ui_builder: UiBuilder,
2206        add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
2207    ) -> InnerResponse<R> {
2208        let next_auto_id_salt = self.next_auto_id_salt;
2209        let mut child_ui = self.new_child(ui_builder);
2210        self.next_auto_id_salt = next_auto_id_salt; // HACK: we want `scope` to only increment this once, so that `ui.scope` is equivalent to `ui.allocate_space`.
2211        let ret = add_contents(&mut child_ui);
2212        let response = child_ui.remember_min_rect();
2213        self.advance_cursor_after_rect(child_ui.min_rect());
2214        InnerResponse::new(ret, response)
2215    }
2216
2217    /// A [`CollapsingHeader`] that starts out collapsed.
2218    ///
2219    /// The name must be unique within the current parent,
2220    /// or you need to use [`CollapsingHeader::id_salt`].
2221    pub fn collapsing<R>(
2222        &mut self,
2223        heading: impl Into<WidgetText>,
2224        add_contents: impl FnOnce(&mut Ui) -> R,
2225    ) -> CollapsingResponse<R> {
2226        CollapsingHeader::new(heading).show(self, add_contents)
2227    }
2228
2229    /// Create a child ui which is indented to the right.
2230    ///
2231    /// The `id_salt` here be anything at all.
2232    // TODO(emilk): remove `id_salt` argument?
2233    #[inline]
2234    pub fn indent<R>(
2235        &mut self,
2236        id_salt: impl AsIdSalt,
2237        add_contents: impl FnOnce(&mut Ui) -> R,
2238    ) -> InnerResponse<R> {
2239        self.indent_dyn(id_salt, Box::new(add_contents))
2240    }
2241
2242    fn indent_dyn<'c, R>(
2243        &mut self,
2244        id_salt: impl AsIdSalt,
2245        add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
2246    ) -> InnerResponse<R> {
2247        assert!(
2248            self.layout().is_vertical(),
2249            "You can only indent vertical layouts, found {:?}",
2250            self.layout()
2251        );
2252
2253        let indent = self.spacing().indent;
2254        let mut child_rect = self.placer.available_rect_before_wrap();
2255        child_rect.min.x += indent;
2256
2257        let mut child_ui = self.new_child(UiBuilder::new().id_salt(id_salt).max_rect(child_rect));
2258        let ret = add_contents(&mut child_ui);
2259
2260        let left_vline = self.visuals().indent_has_left_vline;
2261        let end_with_horizontal_line = self.spacing().indent_ends_with_horizontal_line;
2262
2263        if left_vline || end_with_horizontal_line {
2264            if end_with_horizontal_line {
2265                child_ui.add_space(4.0);
2266            }
2267
2268            let stroke = self.visuals().widgets.noninteractive.bg_stroke;
2269            let left_top = child_rect.min - 0.5 * indent * Vec2::X;
2270            let left_bottom = pos2(left_top.x, child_ui.min_rect().bottom() - 2.0);
2271
2272            if left_vline {
2273                // draw a faint line on the left to mark the indented section
2274                self.painter.line_segment([left_top, left_bottom], stroke);
2275            }
2276
2277            if end_with_horizontal_line {
2278                let fudge = 2.0; // looks nicer with button rounding in collapsing headers
2279                let right_bottom = pos2(child_ui.min_rect().right() - fudge, left_bottom.y);
2280                self.painter
2281                    .line_segment([left_bottom, right_bottom], stroke);
2282            }
2283        }
2284
2285        let response = self.allocate_rect(child_ui.min_rect(), Sense::hover());
2286        InnerResponse::new(ret, response)
2287    }
2288
2289    /// Start a ui with horizontal layout.
2290    /// After you have called this, the function registers the contents as any other widget.
2291    ///
2292    /// Elements will be centered on the Y axis, i.e.
2293    /// adjusted up and down to lie in the center of the horizontal layout.
2294    /// The initial height is `style.spacing.interact_size.y`.
2295    /// Centering is almost always what you want if you are
2296    /// planning to mix widgets or use different types of text.
2297    ///
2298    /// If you don't want the contents to be centered, use [`Self::horizontal_top`] instead.
2299    ///
2300    /// The returned [`Response`] will only have checked for mouse hover
2301    /// but can be used for tooltips (`on_hover_text`).
2302    /// It also contains the [`Rect`] used by the horizontal layout.
2303    ///
2304    /// ```
2305    /// # egui::__run_test_ui(|ui| {
2306    /// ui.horizontal(|ui| {
2307    ///     ui.label("Same");
2308    ///     ui.label("row");
2309    /// });
2310    /// # });
2311    /// ```
2312    ///
2313    /// See also [`Self::with_layout`] for more options.
2314    #[inline]
2315    pub fn horizontal<R>(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
2316        self.horizontal_with_main_wrap_dyn(false, Box::new(add_contents))
2317    }
2318
2319    /// Like [`Self::horizontal`], but allocates the full vertical height and then centers elements vertically.
2320    pub fn horizontal_centered<R>(
2321        &mut self,
2322        add_contents: impl FnOnce(&mut Ui) -> R,
2323    ) -> InnerResponse<R> {
2324        let initial_size = self.available_size_before_wrap();
2325        let layout = if self.placer.prefer_right_to_left() {
2326            Layout::right_to_left(Align::Center)
2327        } else {
2328            Layout::left_to_right(Align::Center)
2329        }
2330        .with_cross_align(Align::Center);
2331        self.allocate_ui_with_layout_dyn(initial_size, layout, Box::new(add_contents))
2332    }
2333
2334    /// Like [`Self::horizontal`], but aligns content with top.
2335    pub fn horizontal_top<R>(
2336        &mut self,
2337        add_contents: impl FnOnce(&mut Ui) -> R,
2338    ) -> InnerResponse<R> {
2339        let initial_size = self.available_size_before_wrap();
2340        let layout = if self.placer.prefer_right_to_left() {
2341            Layout::right_to_left(Align::Center)
2342        } else {
2343            Layout::left_to_right(Align::Center)
2344        }
2345        .with_cross_align(Align::Min);
2346        self.allocate_ui_with_layout_dyn(initial_size, layout, Box::new(add_contents))
2347    }
2348
2349    /// Start a ui with horizontal layout that wraps to a new row
2350    /// when it reaches the right edge of the `max_size`.
2351    /// After you have called this, the function registers the contents as any other widget.
2352    ///
2353    /// Elements will be centered on the Y axis, i.e.
2354    /// adjusted up and down to lie in the center of the horizontal layout.
2355    /// The initial height is `style.spacing.interact_size.y`.
2356    /// Centering is almost always what you want if you are
2357    /// planning to mix widgets or use different types of text.
2358    ///
2359    /// The returned [`Response`] will only have checked for mouse hover
2360    /// but can be used for tooltips (`on_hover_text`).
2361    /// It also contains the [`Rect`] used by the horizontal layout.
2362    ///
2363    /// See also [`Self::with_layout`] for more options.
2364    pub fn horizontal_wrapped<R>(
2365        &mut self,
2366        add_contents: impl FnOnce(&mut Ui) -> R,
2367    ) -> InnerResponse<R> {
2368        self.horizontal_with_main_wrap_dyn(true, Box::new(add_contents))
2369    }
2370
2371    fn horizontal_with_main_wrap_dyn<'c, R>(
2372        &mut self,
2373        main_wrap: bool,
2374        add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
2375    ) -> InnerResponse<R> {
2376        let initial_size = vec2(
2377            self.available_size_before_wrap().x,
2378            self.spacing().interact_size.y, // Assume there will be something interactive on the horizontal layout
2379        );
2380
2381        let layout = if self.placer.prefer_right_to_left() {
2382            Layout::right_to_left(Align::Center)
2383        } else {
2384            Layout::left_to_right(Align::Center)
2385        }
2386        .with_main_wrap(main_wrap);
2387
2388        self.allocate_ui_with_layout_dyn(initial_size, layout, add_contents)
2389    }
2390
2391    /// Start a ui with vertical layout.
2392    /// Widgets will be left-justified.
2393    ///
2394    /// ```
2395    /// # egui::__run_test_ui(|ui| {
2396    /// ui.vertical(|ui| {
2397    ///     ui.label("over");
2398    ///     ui.label("under");
2399    /// });
2400    /// # });
2401    /// ```
2402    ///
2403    /// See also [`Self::with_layout`] for more options.
2404    #[inline]
2405    pub fn vertical<R>(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
2406        self.scope_builder(
2407            UiBuilder::new().layout(Layout::top_down(Align::Min)),
2408            add_contents,
2409        )
2410    }
2411
2412    /// Start a ui with vertical layout.
2413    /// Widgets will be horizontally centered.
2414    ///
2415    /// ```
2416    /// # egui::__run_test_ui(|ui| {
2417    /// ui.vertical_centered(|ui| {
2418    ///     ui.label("over");
2419    ///     ui.label("under");
2420    /// });
2421    /// # });
2422    /// ```
2423    #[inline]
2424    pub fn vertical_centered<R>(
2425        &mut self,
2426        add_contents: impl FnOnce(&mut Ui) -> R,
2427    ) -> InnerResponse<R> {
2428        self.scope_builder(
2429            UiBuilder::new().layout(Layout::top_down(Align::Center)),
2430            add_contents,
2431        )
2432    }
2433
2434    /// Start a ui with vertical layout.
2435    /// Widgets will be horizontally centered and justified (fill full width).
2436    ///
2437    /// ```
2438    /// # egui::__run_test_ui(|ui| {
2439    /// ui.vertical_centered_justified(|ui| {
2440    ///     ui.label("over");
2441    ///     ui.label("under");
2442    /// });
2443    /// # });
2444    /// ```
2445    pub fn vertical_centered_justified<R>(
2446        &mut self,
2447        add_contents: impl FnOnce(&mut Ui) -> R,
2448    ) -> InnerResponse<R> {
2449        self.scope_builder(
2450            UiBuilder::new().layout(Layout::top_down(Align::Center).with_cross_justify(true)),
2451            add_contents,
2452        )
2453    }
2454
2455    /// The new layout will take up all available space.
2456    ///
2457    /// ```
2458    /// # egui::__run_test_ui(|ui| {
2459    /// ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
2460    ///     ui.label("world!");
2461    ///     ui.label("Hello");
2462    /// });
2463    /// # });
2464    /// ```
2465    ///
2466    /// If you don't want to use up all available space, use [`Self::allocate_ui_with_layout`].
2467    ///
2468    /// See also the helpers [`Self::horizontal`], [`Self::vertical`], etc.
2469    #[inline]
2470    pub fn with_layout<R>(
2471        &mut self,
2472        layout: Layout,
2473        add_contents: impl FnOnce(&mut Self) -> R,
2474    ) -> InnerResponse<R> {
2475        self.scope_builder(UiBuilder::new().layout(layout), add_contents)
2476    }
2477
2478    /// This will make the next added widget centered and justified in the available space.
2479    ///
2480    /// Only one widget may be added to the inner `Ui`!
2481    pub fn centered_and_justified<R>(
2482        &mut self,
2483        add_contents: impl FnOnce(&mut Self) -> R,
2484    ) -> InnerResponse<R> {
2485        self.scope_builder(
2486            UiBuilder::new().layout(Layout::centered_and_justified(Direction::TopDown)),
2487            add_contents,
2488        )
2489    }
2490
2491    pub(crate) fn set_grid(&mut self, grid: grid::GridLayout) {
2492        self.placer.set_grid(grid);
2493    }
2494
2495    pub(crate) fn save_grid(&mut self) {
2496        self.placer.save_grid();
2497    }
2498
2499    pub(crate) fn is_grid(&self) -> bool {
2500        self.placer.is_grid()
2501    }
2502
2503    /// Move to the next row in a grid layout or wrapping layout.
2504    /// Otherwise does nothing.
2505    pub fn end_row(&mut self) {
2506        self.placer
2507            .end_row(self.spacing().item_spacing, &self.painter().clone());
2508    }
2509
2510    /// Set row height in horizontal wrapping layout.
2511    pub fn set_row_height(&mut self, height: f32) {
2512        self.placer.set_row_height(height);
2513    }
2514
2515    /// Temporarily split a [`Ui`] into several columns.
2516    ///
2517    /// ```
2518    /// # egui::__run_test_ui(|ui| {
2519    /// ui.columns(2, |columns| {
2520    ///     columns[0].label("First column");
2521    ///     columns[1].label("Second column");
2522    /// });
2523    /// # });
2524    /// ```
2525    #[inline]
2526    pub fn columns<R>(
2527        &mut self,
2528        num_columns: usize,
2529        add_contents: impl FnOnce(&mut [Self]) -> R,
2530    ) -> R {
2531        self.columns_dyn(num_columns, Box::new(add_contents))
2532    }
2533
2534    fn columns_dyn<'c, R>(
2535        &mut self,
2536        num_columns: usize,
2537        add_contents: Box<dyn FnOnce(&mut [Self]) -> R + 'c>,
2538    ) -> R {
2539        // TODO(emilk): ensure there is space
2540        let spacing = self.spacing().item_spacing.x;
2541        let total_spacing = spacing * (num_columns as f32 - 1.0);
2542        let column_width = (self.available_width() - total_spacing) / (num_columns as f32);
2543        let top_left = self.cursor().min;
2544
2545        let mut columns: Vec<Self> = (0..num_columns)
2546            .map(|col_idx| {
2547                let pos = top_left + vec2((col_idx as f32) * (column_width + spacing), 0.0);
2548                let child_rect = Rect::from_min_max(
2549                    pos,
2550                    pos2(pos.x + column_width, self.max_rect().right_bottom().y),
2551                );
2552                let mut column_ui = self.new_child(
2553                    UiBuilder::new()
2554                        .max_rect(child_rect)
2555                        .layout(Layout::top_down_justified(Align::LEFT)),
2556                );
2557                column_ui.set_width(column_width);
2558                column_ui
2559            })
2560            .collect();
2561
2562        let result = add_contents(&mut columns[..]);
2563
2564        let mut max_column_width = column_width;
2565        let mut max_height = 0.0;
2566        for column in &columns {
2567            max_column_width = max_column_width.max(column.min_rect().width());
2568            max_height = column.min_size().y.max(max_height);
2569        }
2570
2571        // Make sure we fit everything next frame:
2572        let total_required_width = total_spacing + max_column_width * (num_columns as f32);
2573
2574        let size = vec2(self.available_width().max(total_required_width), max_height);
2575        self.advance_cursor_after_rect(Rect::from_min_size(top_left, size));
2576        result
2577    }
2578
2579    /// Temporarily split a [`Ui`] into several columns.
2580    ///
2581    /// The same as [`Self::columns()`], but uses a constant for the column count.
2582    /// This allows for compile-time bounds checking, and makes the compiler happy.
2583    ///
2584    /// ```
2585    /// # egui::__run_test_ui(|ui| {
2586    /// ui.columns_const(|[col_1, col_2]| {
2587    ///     col_1.label("First column");
2588    ///     col_2.label("Second column");
2589    /// });
2590    /// # });
2591    /// ```
2592    #[inline]
2593    pub fn columns_const<const NUM_COL: usize, R>(
2594        &mut self,
2595        add_contents: impl FnOnce(&mut [Self; NUM_COL]) -> R,
2596    ) -> R {
2597        // TODO(emilk): ensure there is space
2598        let spacing = self.spacing().item_spacing.x;
2599        let total_spacing = spacing * (NUM_COL as f32 - 1.0);
2600        let column_width = (self.available_width() - total_spacing) / (NUM_COL as f32);
2601        let top_left = self.cursor().min;
2602
2603        let mut columns = core::array::from_fn(|col_idx| {
2604            let pos = top_left + vec2((col_idx as f32) * (column_width + spacing), 0.0);
2605            let child_rect = Rect::from_min_max(
2606                pos,
2607                pos2(pos.x + column_width, self.max_rect().right_bottom().y),
2608            );
2609            let mut column_ui = self.new_child(
2610                UiBuilder::new()
2611                    .max_rect(child_rect)
2612                    .layout(Layout::top_down_justified(Align::LEFT)),
2613            );
2614            column_ui.set_width(column_width);
2615            column_ui
2616        });
2617        let result = add_contents(&mut columns);
2618
2619        let mut max_column_width = column_width;
2620        let mut max_height = 0.0;
2621        for column in &columns {
2622            max_column_width = max_column_width.max(column.min_rect().width());
2623            max_height = column.min_size().y.max(max_height);
2624        }
2625
2626        // Make sure we fit everything next frame:
2627        let total_required_width = total_spacing + max_column_width * (NUM_COL as f32);
2628
2629        let size = vec2(self.available_width().max(total_required_width), max_height);
2630        self.advance_cursor_after_rect(Rect::from_min_size(top_left, size));
2631        result
2632    }
2633
2634    /// Create something that can be drag-and-dropped.
2635    ///
2636    /// The `id` needs to be globally unique.
2637    /// The payload is what will be dropped if the user starts dragging.
2638    ///
2639    /// In contrast to [`Response::dnd_set_drag_payload`],
2640    /// this function will paint the widget at the mouse cursor while the user is dragging.
2641    #[doc(alias = "drag and drop")]
2642    pub fn dnd_drag_source<Payload, R>(
2643        &mut self,
2644        id: Id,
2645        payload: Payload,
2646        add_contents: impl FnOnce(&mut Self) -> R,
2647    ) -> InnerResponse<R>
2648    where
2649        Payload: Any + Send + Sync,
2650    {
2651        let is_being_dragged = self.ctx().is_being_dragged(id);
2652
2653        if is_being_dragged {
2654            crate::DragAndDrop::set_payload(self.ctx(), payload);
2655
2656            // Paint the body to a new layer:
2657            let layer_id = LayerId::new(Order::Tooltip, id);
2658            let InnerResponse { inner, response } =
2659                self.scope_builder(UiBuilder::new().layer_id(layer_id), add_contents);
2660
2661            // Now we move the visuals of the body to where the mouse is.
2662            // Normally you need to decide a location for a widget first,
2663            // because otherwise that widget cannot interact with the mouse.
2664            // However, a dragged component cannot be interacted with anyway
2665            // (anything with `Order::Tooltip` always gets an empty [`Response`])
2666            // So this is fine!
2667
2668            if let Some(pointer_pos) = self.ctx().pointer_interact_pos() {
2669                let delta = pointer_pos - response.rect.center();
2670                self.ctx()
2671                    .transform_layer_shapes(layer_id, emath::TSTransform::from_translation(delta));
2672            }
2673
2674            InnerResponse::new(inner, response)
2675        } else {
2676            let InnerResponse { inner, response } = self.scope(add_contents);
2677
2678            // Check for drags:
2679            let dnd_response = self
2680                .interact(response.rect, id, Sense::drag())
2681                .on_hover_cursor(CursorIcon::Grab);
2682
2683            InnerResponse::new(inner, dnd_response | response)
2684        }
2685    }
2686
2687    /// Surround the given ui with a frame which
2688    /// changes colors when you can drop something onto it.
2689    ///
2690    /// Returns the dropped item, if it was released this frame.
2691    ///
2692    /// The given frame is used for its margins, but the color is ignored.
2693    #[doc(alias = "drag and drop")]
2694    pub fn dnd_drop_zone<Payload, R>(
2695        &mut self,
2696        frame: Frame,
2697        add_contents: impl FnOnce(&mut Ui) -> R,
2698    ) -> (InnerResponse<R>, Option<Arc<Payload>>)
2699    where
2700        Payload: Any + Send + Sync,
2701    {
2702        let is_anything_being_dragged = DragAndDrop::has_any_payload(self.ctx());
2703        let can_accept_what_is_being_dragged =
2704            DragAndDrop::has_payload_of_type::<Payload>(self.ctx());
2705
2706        let mut frame = frame.begin(self);
2707        let inner = add_contents(&mut frame.content_ui);
2708        let response = frame.allocate_space(self);
2709
2710        // NOTE: we use `response.contains_pointer` here instead of `hovered`, because
2711        // `hovered` is always false when another widget is being dragged.
2712        let style = if is_anything_being_dragged
2713            && can_accept_what_is_being_dragged
2714            && response.contains_pointer()
2715        {
2716            self.visuals().widgets.active
2717        } else {
2718            self.visuals().widgets.inactive
2719        };
2720
2721        let mut fill = style.bg_fill;
2722        let mut stroke = style.bg_stroke;
2723
2724        if is_anything_being_dragged && !can_accept_what_is_being_dragged {
2725            // When dragging something else, show that it can't be dropped here:
2726            fill = self.visuals().disable(fill);
2727            stroke.color = self.visuals().disable(stroke.color);
2728        }
2729
2730        frame.frame.fill = fill;
2731        frame.frame.stroke = stroke;
2732
2733        frame.paint(self);
2734
2735        let payload = response.dnd_release_payload::<Payload>();
2736
2737        (InnerResponse { inner, response }, payload)
2738    }
2739
2740    /// Create a new Scope and transform its contents via a [`emath::TSTransform`].
2741    /// This only affects visuals, inputs will not be transformed. So this is mostly useful
2742    /// to create visual effects on interactions, e.g. scaling a button on hover / click.
2743    ///
2744    /// Check out [`Context::set_transform_layer`] for a persistent transform that also affects
2745    /// inputs.
2746    pub fn with_visual_transform<R>(
2747        &mut self,
2748        transform: emath::TSTransform,
2749        add_contents: impl FnOnce(&mut Self) -> R,
2750    ) -> InnerResponse<R> {
2751        let start_idx = self.ctx().graphics(|gx| {
2752            gx.get(self.layer_id())
2753                .map_or(crate::layers::ShapeIdx(0), |l| l.next_idx())
2754        });
2755
2756        let r = self.scope_dyn(UiBuilder::new(), Box::new(add_contents));
2757
2758        self.ctx().graphics_mut(|g| {
2759            let list = g.entry(self.layer_id());
2760            let end_idx = list.next_idx();
2761            list.transform_range(start_idx, end_idx, transform);
2762        });
2763
2764        r
2765    }
2766}
2767
2768/// # Menus
2769impl Ui {
2770    #[inline]
2771    /// Create a menu button that when clicked will show the given menu.
2772    ///
2773    /// If called from within a menu this will instead create a button for a sub-menu.
2774    ///
2775    /// ```
2776    /// # egui::__run_test_ui(|ui| {
2777    /// ui.menu_button("My menu", |ui| {
2778    ///     ui.menu_button("My sub-menu", |ui| {
2779    ///         if ui.button("Close the menu").clicked() {
2780    ///             ui.close();
2781    ///         }
2782    ///     });
2783    /// });
2784    /// # });
2785    /// ```
2786    ///
2787    /// See also: [`Self::close`] and [`Response::context_menu`].
2788    pub fn menu_button<'a, R>(
2789        &mut self,
2790        atoms: impl IntoAtoms<'a>,
2791        add_contents: impl FnOnce(&mut Ui) -> R,
2792    ) -> InnerResponse<Option<R>> {
2793        let (response, inner) = if menu::is_in_menu(self) {
2794            menu::SubMenuButton::new(atoms).ui(self, add_contents)
2795        } else {
2796            menu::MenuButton::new(atoms).ui(self, add_contents)
2797        };
2798        InnerResponse::new(inner.map(|i| i.inner), response)
2799    }
2800
2801    /// Create a menu button with an image that when clicked will show the given menu.
2802    ///
2803    /// If called from within a menu this will instead create a button for a sub-menu.
2804    ///
2805    /// ```ignore
2806    /// # egui::__run_test_ui(|ui| {
2807    /// let img = egui::include_image!("../assets/ferris.png");
2808    ///
2809    /// ui.menu_image_button(title, img, |ui| {
2810    ///     ui.menu_button("My sub-menu", |ui| {
2811    ///         if ui.button("Close the menu").clicked() {
2812    ///             ui.close();
2813    ///         }
2814    ///     });
2815    /// });
2816    /// # });
2817    /// ```
2818    ///
2819    ///
2820    /// See also: [`Self::close`] and [`Response::context_menu`].
2821    #[inline]
2822    pub fn menu_image_button<'a, R>(
2823        &mut self,
2824        image: impl Into<Image<'a>>,
2825        add_contents: impl FnOnce(&mut Ui) -> R,
2826    ) -> InnerResponse<Option<R>> {
2827        let (response, inner) = if menu::is_in_menu(self) {
2828            menu::SubMenuButton::from_button(
2829                Button::image(image).right_text(menu::SubMenuButton::RIGHT_ARROW),
2830            )
2831            .ui(self, add_contents)
2832        } else {
2833            menu::MenuButton::from_button(Button::image(image)).ui(self, add_contents)
2834        };
2835        InnerResponse::new(inner.map(|i| i.inner), response)
2836    }
2837
2838    /// Create a menu button with an image and a text that when clicked will show the given menu.
2839    ///
2840    /// If called from within a menu this will instead create a button for a sub-menu.
2841    ///
2842    /// ```
2843    /// # egui::__run_test_ui(|ui| {
2844    /// let img = egui::include_image!("../assets/ferris.png");
2845    /// let title = "My Menu";
2846    ///
2847    /// ui.menu_image_text_button(img, title, |ui| {
2848    ///     ui.menu_button("My sub-menu", |ui| {
2849    ///         if ui.button("Close the menu").clicked() {
2850    ///             ui.close();
2851    ///         }
2852    ///     });
2853    /// });
2854    /// # });
2855    /// ```
2856    ///
2857    /// See also: [`Self::close`] and [`Response::context_menu`].
2858    #[inline]
2859    pub fn menu_image_text_button<'a, R>(
2860        &mut self,
2861        image: impl Into<Image<'a>>,
2862        title: impl Into<WidgetText>,
2863        add_contents: impl FnOnce(&mut Ui) -> R,
2864    ) -> InnerResponse<Option<R>> {
2865        let (response, inner) = if menu::is_in_menu(self) {
2866            menu::SubMenuButton::from_button(
2867                Button::image_and_text(image, title).right_text(menu::SubMenuButton::RIGHT_ARROW),
2868            )
2869            .ui(self, add_contents)
2870        } else {
2871            menu::MenuButton::from_button(Button::image_and_text(image, title))
2872                .ui(self, add_contents)
2873        };
2874        InnerResponse::new(inner.map(|i| i.inner), response)
2875    }
2876}
2877
2878// ----------------------------------------------------------------------------
2879
2880/// # Debug stuff
2881impl Ui {
2882    /// Shows where the next widget is going to be placed
2883    #[cfg(debug_assertions)]
2884    pub fn debug_paint_cursor(&self) {
2885        self.placer.debug_paint_cursor(&self.painter, "next");
2886    }
2887}
2888
2889impl Drop for Ui {
2890    fn drop(&mut self) {
2891        if !self.min_rect_already_remembered {
2892            // Register our final `min_rect`
2893            self.remember_min_rect();
2894        }
2895        #[cfg(debug_assertions)]
2896        register_rect(self, self.min_rect());
2897    }
2898}
2899
2900/// Show this rectangle to the user if certain debug options are set.
2901#[cfg(debug_assertions)]
2902fn register_rect(ui: &Ui, rect: Rect) {
2903    use emath::{Align2, GuiRounding as _};
2904
2905    let debug = ui.style().debug;
2906
2907    if debug.show_unaligned {
2908        let unaligned_line = |p0: Pos2, p1: Pos2| {
2909            let color = Color32::ORANGE;
2910            let font_id = TextStyle::Monospace.resolve(ui.style());
2911            ui.painter().line_segment([p0, p1], (1.0, color));
2912            ui.painter()
2913                .text(p0, Align2::LEFT_TOP, "Unaligned", font_id, color);
2914        };
2915
2916        if rect.left() != rect.left().round_ui() {
2917            unaligned_line(rect.left_top(), rect.left_bottom());
2918        }
2919        if rect.right() != rect.right().round_ui() {
2920            unaligned_line(rect.right_top(), rect.right_bottom());
2921        }
2922        if rect.top() != rect.top().round_ui() {
2923            unaligned_line(rect.left_top(), rect.right_top());
2924        }
2925        if rect.bottom() != rect.bottom().round_ui() {
2926            unaligned_line(rect.left_bottom(), rect.right_bottom());
2927        }
2928    }
2929
2930    let show_callstacks = debug.debug_on_hover
2931        || debug.debug_on_hover_with_all_modifiers && ui.input(|i| i.modifiers.all());
2932
2933    if !show_callstacks {
2934        return;
2935    }
2936
2937    if !ui.rect_contains_pointer(rect) {
2938        return;
2939    }
2940
2941    let is_clicking = ui.input(|i| i.pointer.could_any_button_be_click());
2942
2943    #[cfg(feature = "callstack")]
2944    let callstack = crate::callstack::capture();
2945
2946    #[cfg(not(feature = "callstack"))]
2947    let callstack = String::default();
2948
2949    // We only show one debug rectangle, or things get confusing:
2950    let debug_rect = pass_state::DebugRect {
2951        rect,
2952        callstack,
2953        is_clicking,
2954    };
2955
2956    let mut kept = false;
2957    ui.ctx().pass_state_mut(|fs| {
2958        if let Some(final_debug_rect) = &mut fs.debug_rect {
2959            // or maybe pick the one with deepest callstack?
2960            if final_debug_rect.rect.contains_rect(rect) {
2961                *final_debug_rect = debug_rect;
2962                kept = true;
2963            }
2964        } else {
2965            fs.debug_rect = Some(debug_rect);
2966            kept = true;
2967        }
2968    });
2969    if !kept {
2970        return;
2971    }
2972
2973    // ----------------------------------------------
2974
2975    // Use the debug-painter to avoid clip rect,
2976    // otherwise the content of the widget may cover what we paint here!
2977    let painter = ui.debug_painter();
2978
2979    if debug.hover_shows_next {
2980        ui.placer.debug_paint_cursor(&painter, "next");
2981    }
2982}
2983
2984#[cfg(not(debug_assertions))]
2985fn register_rect(_ui: &Ui, _rect: Rect) {}
2986
2987#[test]
2988fn ui_impl_send_sync() {
2989    fn assert_send_sync<T: Send + Sync>() {}
2990    assert_send_sync::<Ui>();
2991}