Skip to content

Commit

Permalink
Create a UiBuilder for building Uis (#4969)
Browse files Browse the repository at this point in the history
* Part of #4634

The goals is to create fewer, more powerful entry points.


### Added
* `egui::UiBuilder`
* `Ui::allocate_new_ui`
* `Ui::new_child`

### Breaking changes
* `Ui::new` now takes a `UiBuilder`
* Deprecated
	* `ui.add_visible_ui`
	* `ui.allocate_ui_at_rect`
	* `ui.child_ui`
	* `ui.child_ui_with_id_source`
	* `ui.push_stack_info`
  • Loading branch information
emilk authored Aug 26, 2024
1 parent 06f88e1 commit 5a196f6
Show file tree
Hide file tree
Showing 14 changed files with 391 additions and 171 deletions.
27 changes: 12 additions & 15 deletions crates/egui/src/containers/area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,16 +532,19 @@ impl Prepared {
pub(crate) fn content_ui(&self, ctx: &Context) -> Ui {
let max_rect = self.state.rect();

let clip_rect = self.constrain_rect; // Don't paint outside our bounds
let mut ui_builder = UiBuilder::new()
.ui_stack_info(UiStackInfo::new(self.kind))
.max_rect(max_rect);

let mut ui = Ui::new(
ctx.clone(),
self.layer_id,
self.layer_id.id,
max_rect,
clip_rect,
UiStackInfo::new(self.kind),
);
if !self.enabled {
ui_builder = ui_builder.disabled();
}
if self.sizing_pass {
ui_builder = ui_builder.sizing_pass();
}

let mut ui = Ui::new(ctx.clone(), self.layer_id, self.layer_id.id, ui_builder);
ui.set_clip_rect(self.constrain_rect); // Don't paint outside our bounds

if self.fade_in {
if let Some(last_became_visible_at) = self.state.last_became_visible_at {
Expand All @@ -556,12 +559,6 @@ impl Prepared {
}
}

if !self.enabled {
ui.disable();
}
if self.sizing_pass {
ui.set_sizing_pass();
}
ui
}

Expand Down
2 changes: 1 addition & 1 deletion crates/egui/src/containers/combo_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ fn button_frame(
outer_rect.set_height(outer_rect.height().at_least(interact_size.y));

let inner_rect = outer_rect.shrink2(margin);
let mut content_ui = ui.child_ui(inner_rect, *ui.layout(), None);
let mut content_ui = ui.new_child(UiBuilder::new().max_rect(inner_rect));
add_contents(&mut content_ui);

let mut outer_rect = content_ui.min_rect().expand2(margin);
Expand Down
8 changes: 4 additions & 4 deletions crates/egui/src/containers/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,10 @@ impl Frame {
inner_rect.max.x = inner_rect.max.x.max(inner_rect.min.x);
inner_rect.max.y = inner_rect.max.y.max(inner_rect.min.y);

let content_ui = ui.child_ui(
inner_rect,
*ui.layout(),
Some(UiStackInfo::new(UiKind::Frame).with_frame(self)),
let content_ui = ui.new_child(
UiBuilder::new()
.ui_stack_info(UiStackInfo::new(UiKind::Frame).with_frame(self))
.max_rect(inner_rect),
);

// content_ui.set_clip_rect(outer_rect_bounds.shrink(self.stroke.width * 0.5)); // Can't do this since we don't know final size yet
Expand Down
61 changes: 29 additions & 32 deletions crates/egui/src/containers/panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,15 @@ impl SidePanel {
}
}

let mut panel_ui = ui.child_ui_with_id_source(
panel_rect,
Layout::top_down(Align::Min),
id,
Some(UiStackInfo::new(match side {
Side::Left => UiKind::LeftPanel,
Side::Right => UiKind::RightPanel,
})),
let mut panel_ui = ui.new_child(
UiBuilder::new()
.id_source(id)
.ui_stack_info(UiStackInfo::new(match side {
Side::Left => UiKind::LeftPanel,
Side::Right => UiKind::RightPanel,
}))
.max_rect(panel_rect)
.layout(Layout::top_down(Align::Min)),
);
panel_ui.expand_to_include_rect(panel_rect);
panel_ui.set_clip_rect(panel_rect); // If we overflow, don't do so visibly (#4475)
Expand Down Expand Up @@ -367,15 +368,13 @@ impl SidePanel {
let layer_id = LayerId::background();
let side = self.side;
let available_rect = ctx.available_rect();
let clip_rect = ctx.screen_rect();
let mut panel_ui = Ui::new(
ctx.clone(),
layer_id,
self.id,
available_rect,
clip_rect,
UiStackInfo::default(),
UiBuilder::new().max_rect(available_rect),
);
panel_ui.set_clip_rect(ctx.screen_rect());

let inner_response = self.show_inside_dyn(&mut panel_ui, add_contents);
let rect = inner_response.response.rect;
Expand Down Expand Up @@ -750,14 +749,15 @@ impl TopBottomPanel {
}
}

let mut panel_ui = ui.child_ui_with_id_source(
panel_rect,
Layout::top_down(Align::Min),
id,
Some(UiStackInfo::new(match side {
TopBottomSide::Top => UiKind::TopPanel,
TopBottomSide::Bottom => UiKind::BottomPanel,
})),
let mut panel_ui = ui.new_child(
UiBuilder::new()
.id_source(id)
.ui_stack_info(UiStackInfo::new(match side {
TopBottomSide::Top => UiKind::TopPanel,
TopBottomSide::Bottom => UiKind::BottomPanel,
}))
.max_rect(panel_rect)
.layout(Layout::top_down(Align::Min)),
);
panel_ui.expand_to_include_rect(panel_rect);
panel_ui.set_clip_rect(panel_rect); // If we overflow, don't do so visibly (#4475)
Expand Down Expand Up @@ -857,15 +857,13 @@ impl TopBottomPanel {
let available_rect = ctx.available_rect();
let side = self.side;

let clip_rect = ctx.screen_rect();
let mut panel_ui = Ui::new(
ctx.clone(),
layer_id,
self.id,
available_rect,
clip_rect,
UiStackInfo::default(), // set by show_inside_dyn
UiBuilder::new().max_rect(available_rect),
);
panel_ui.set_clip_rect(ctx.screen_rect());

let inner_response = self.show_inside_dyn(&mut panel_ui, add_contents);
let rect = inner_response.response.rect;
Expand Down Expand Up @@ -1091,10 +1089,11 @@ impl CentralPanel {
let Self { frame } = self;

let panel_rect = ui.available_rect_before_wrap();
let mut panel_ui = ui.child_ui(
panel_rect,
Layout::top_down(Align::Min),
Some(UiStackInfo::new(UiKind::CentralPanel)),
let mut panel_ui = ui.new_child(
UiBuilder::new()
.ui_stack_info(UiStackInfo::new(UiKind::CentralPanel))
.max_rect(panel_rect)
.layout(Layout::top_down(Align::Min)),
);
panel_ui.set_clip_rect(panel_rect); // If we overflow, don't do so visibly (#4475)

Expand Down Expand Up @@ -1124,15 +1123,13 @@ impl CentralPanel {
let layer_id = LayerId::background();
let id = Id::new((ctx.viewport_id(), "central_panel"));

let clip_rect = ctx.screen_rect();
let mut panel_ui = Ui::new(
ctx.clone(),
layer_id,
id,
available_rect,
clip_rect,
UiStackInfo::default(), // set by show_inside_dyn
UiBuilder::new().max_rect(available_rect),
);
panel_ui.set_clip_rect(ctx.screen_rect());

let inner_response = self.show_inside_dyn(&mut panel_ui, add_contents);

Expand Down
8 changes: 4 additions & 4 deletions crates/egui/src/containers/resize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,10 @@ impl Resize {

content_clip_rect = content_clip_rect.intersect(ui.clip_rect()); // Respect parent region

let mut content_ui = ui.child_ui(
inner_rect,
*ui.layout(),
Some(UiStackInfo::new(UiKind::Resize)),
let mut content_ui = ui.new_child(
UiBuilder::new()
.ui_stack_info(UiStackInfo::new(UiKind::Resize))
.max_rect(inner_rect),
);
content_ui.set_clip_rect(content_clip_rect);

Expand Down
10 changes: 5 additions & 5 deletions crates/egui/src/containers/scroll_area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,10 +560,10 @@ impl ScrollArea {
}

let content_max_rect = Rect::from_min_size(inner_rect.min - state.offset, content_max_size);
let mut content_ui = ui.child_ui(
content_max_rect,
*ui.layout(),
Some(UiStackInfo::new(UiKind::ScrollArea)),
let mut content_ui = ui.new_child(
UiBuilder::new()
.ui_stack_info(UiStackInfo::new(UiKind::ScrollArea))
.max_rect(content_max_rect),
);

{
Expand Down Expand Up @@ -732,7 +732,7 @@ impl ScrollArea {

let rect = Rect::from_x_y_ranges(ui.max_rect().x_range(), y_min..=y_max);

ui.allocate_ui_at_rect(rect, |viewport_ui| {
ui.allocate_new_ui(UiBuilder::new().max_rect(rect), |viewport_ui| {
viewport_ui.skip_ahead_auto_ids(min_row); // Make sure we get consistent IDs.
add_contents(viewport_ui, min_row..max_row)
})
Expand Down
13 changes: 8 additions & 5 deletions crates/egui/src/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,11 +425,14 @@ impl Grid {
// then we should pick a default layout that matches that alignment,
// which we do here:
let max_rect = ui.cursor().intersect(ui.max_rect());
ui.allocate_ui_at_rect(max_rect, |ui| {
if prev_state.is_none() {
// Hide the ui this frame, and make things as narrow as possible.
ui.set_sizing_pass();
}

let mut ui_builder = UiBuilder::new().max_rect(max_rect);
if prev_state.is_none() {
// Hide the ui this frame, and make things as narrow as possible.
ui_builder = ui_builder.sizing_pass();
}

ui.allocate_new_ui(ui_builder, |ui| {
ui.horizontal(|ui| {
let is_color = color_picker.is_some();
let mut grid = GridLayout {
Expand Down
4 changes: 3 additions & 1 deletion crates/egui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ mod sense;
pub mod style;
pub mod text_selection;
mod ui;
mod ui_builder;
mod ui_stack;
pub mod util;
pub mod viewport;
Expand Down Expand Up @@ -442,7 +443,7 @@ pub mod text {
};
}

pub use {
pub use self::{
containers::*,
context::{Context, RepaintCause, RequestRepaintInfo},
data::{
Expand All @@ -467,6 +468,7 @@ pub use {
style::{FontSelection, Style, TextStyle, Visuals},
text::{Galley, TextFormat},
ui::Ui,
ui_builder::UiBuilder,
ui_stack::*,
viewport::*,
widget_rect::{WidgetRect, WidgetRects},
Expand Down
Loading

0 comments on commit 5a196f6

Please sign in to comment.