Skip to main content

egui/
ui.rs

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