8000 Measure `intrinsic_size` in `Placer` by lucasmerlin · Pull Request #5831 · emilk/egui · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Measure intrinsic_size in Placer #5831

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion crates/egui/src/atomics/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl<'a> Atom<'a> {

SizedAtom {
size,
preferred_size: preferred,
preferred_size: preferred.at_least(size),
grow: self.grow,
kind,
}
Expand Down
16 changes: 14 additions & 2 deletions crates/egui/src/atomics/atom_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,21 @@ impl<'a> AtomKind<'a> {
) -> (Vec2, SizedAtomKind<'a>) {
match self {
AtomKind::Text(text) => {
let galley = text.into_galley(ui, wrap_mode, available_size.x, TextStyle::Button);
let wrap_mode = wrap_mode.unwrap_or(ui.wrap_mode());
let desired_size = matches!(wrap_mode, TextWrapMode::Truncate).then(|| {
text.clone()
.into_galley(
ui,
Some(TextWrapMode::Extend),
available_size.x,
TextStyle::Button,
)
.desired_size()
});
let galley =
text.into_galley(ui, Some(wrap_mode), available_size.x, TextStyle::Button);
(
galley.size(), // TODO(#5762): calculate the preferred size
desired_size.unwrap_or_else(|| galley.desired_size()),
SizedAtomKind::Text(galley),
)
}
Expand Down
7 changes: 4 additions & 3 deletions crates/egui/src/atomics/atom_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,12 @@ impl<'a> AtomLayout<'a> {
let desired_size = Vec2::new(desired_width, height);
let frame_size = (desired_size + margin.sum()).at_least(min_size);

let (_, rect) = ui.allocate_space(frame_size);
let intrinsic_size =
(Vec2::new(preferred_width, preferred_height) + margin.sum()).at_least(min_size);
let (_, rect) = ui.allocate_space(frame_size, intrinsic_size);
let mut response = ui.interact(rect, id, sense);

response.intrinsic_size =
Some((Vec2::new(preferred_width, preferred_height) + margin.sum()).at_least(min_size));
response.intrinsic_size = Some(intrinsic_size);

AllocatedAtomLayout {
sized_atoms: sized_items,
Expand Down
4 changes: 3 additions & 1 deletion crates/egui/src/containers/area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,9 @@ impl Prepared {
..
} = self;

state.size = Some(content_ui.min_size());
state.size = Some(content_ui.intrinsic_size());

dbg!(state.size);

// Make sure we report back the correct size.
// Very important after the initial sizing pass, when the initial estimate of the size is way off.
Expand Down
8 changes: 4 additions & 4 deletions crates/egui/src/containers/collapsing_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub(crate) struct InnerState {
open_height: Option<f32>,
}

/// This is a a building block for building collapsing regions.
/// This is a building block for building collapsing regions.
///
/// It is used by [`CollapsingHeader`] and [`crate::Window`], but can also be used on its own.
///
Expand Down Expand Up @@ -87,7 +87,7 @@ impl CollapsingState {
ui: &mut Ui,
button_size: Vec2,
) -> Response {
let (_id, rect) = ui.allocate_space(button_size);
let (_id, rect) = ui.allocate_space(button_size, Vec2::ZERO); // TODO
let response = ui.interact(rect, self.id, Sense::click());
response.widget_info(|| {
WidgetInfo::labeled(
Expand Down Expand Up @@ -117,7 +117,7 @@ impl CollapsingState {
icon_fn: impl FnOnce(&mut Ui, f32, &Response) + 'static,
) -> Response {
let size = vec2(ui.spacing().indent, ui.spacing().icon_width);
let (_id, rect) = ui.allocate_space(size);
let (_id, rect) = ui.allocate_space(size, Vec2::ZERO); // TODO
let response = ui.interact(rect, self.id, Sense::click());
if response.clicked() {
self.toggle(ui);
Expand Down Expand Up @@ -554,7 +554,7 @@ impl CollapsingHeader {

let mut desired_size = vec2(desired_width, galley.size().y + 2.0 * button_padding.y);
desired_size = desired_size.at_least(ui.spacing().interact_size);
let (_, rect) = ui.allocate_space(desired_size);
let (_, rect) = ui.allocate_space(desired_size, desired_size); // TODO

let mut header_response = ui.interact(rect, id, Sense::click());
let text_pos = pos2(
Expand Down
4 changes: 2 additions & 2 deletions crates/egui/src/containers/combo_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ fn combo_box_dyn<'c, R>(
let actual_width = (galley.size().x + icon_spacing + icon_size.x).at_least(minimum_width);
let actual_height = galley.size().y.max(icon_size.y);

let (_, rect) = ui.allocate_space(Vec2::new(actual_width, actual_height));
let (_, rect) = ui.allocate_space(Vec2::new(actual_width, actual_height), Vec2::ZERO); // TODO
let button_rect = ui.min_rect().expand2(ui.spacing().button_padding);
let response = ui.interact(button_rect, button_id, Sense::click());
// response.active |= is_popup_open;
Expand Down Expand Up @@ -449,7 +449,7 @@ fn button_frame(
);
}

ui.advance_cursor_after_rect(outer_rect);
ui.advance_cursor_after_rect(outer_rect, Vec2::ZERO); // TODO

response
}
Expand Down
6 changes: 5 additions & 1 deletion crates/egui/src/containers/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,11 @@ impl Prepared {
///
/// This can be called before or after [`Self::paint`].
pub fn allocate_space(&self, ui: &mut Ui) -> Response {
ui.allocate_rect(self.outer_rect(), Sense::hover())
ui.allocate_rect(
self.outer_rect(),
Sense::hover(),
self.content_ui.intrinsic_size() + self.frame.total_margin().sum(),
)
}

/// Paint the frame.
Expand Down
5 changes: 4 additions & 1 deletion crates/egui/src/containers/resize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,10 @@ impl Resize {
size[d] = state.last_content_size[d];
}
}
ui.advance_cursor_after_rect(Rect::from_min_size(content_ui.min_rect().min, size));
ui.advance_cursor_after_rect(
Rect::from_min_size(content_ui.min_rect().min, size),
Vec2::ZERO,
); // TODO

// ------------------------------

Expand Down
2 changes: 1 addition & 1 deletion crates/egui/src/containers/scroll_area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1415,7 +1415,7 @@ impl Prepared {
}
}

ui.advance_cursor_after_rect(outer_rect);
ui.advance_cursor_after_rect(outer_rect, content_ui.placer().intrinsic_size());

if show_scroll_this_frame != state.show_scroll {
ui.ctx().request_repaint();
Expand Down
17 changes: 11 additions & 6 deletions crates/egui/src/containers/sides.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use emath::Align;
use emath::{Align, Vec2};

use crate::{Layout, Ui, UiBuilder};

Expand Down Expand Up @@ -84,26 +84,26 @@ impl Sides {
let result_left;
let result_right;

let left_rect = {
let (left_rect, left_preferred_size) = {
let left_max_rect = top_rect;
let mut left_ui = ui.new_child(
UiBuilder::new()
.max_rect(left_max_rect)
.layout(Layout::left_to_right(Align::Center)),
);
result_left = add_left(&mut left_ui);
left_ui.min_rect()
(left_ui.min_rect(), left_ui.intrinsic_size())
};

let right_rect = {
let (right_rect, right_preferred_size) = {
let right_max_rect = top_rect.with_min_x(left_rect.max.x);
let mut right_ui = ui.new_child(
UiBuilder::new()
.max_rect(right_max_rect)
.layout(Layout::right_to_left(Align::Center)),
);
result_right = add_right(&mut right_ui);
right_ui.min_rect()
(right_ui.min_rect(), right_ui.intrinsic_size())
};

let mut final_rect = left_rect.union(right_rect);
Expand All @@ -118,7 +118,12 @@ impl Sides {
final_rect.max.x = final_rect.max.x.max(left_rect.min.x + min_width);
}

ui.advance_cursor_after_rect(final_rect);
let preferred_size = Vec2::new(
left_preferred_size.x + spacing + right_preferred_size.x,
left_preferred_size.y.max(right_preferred_size.y),
);

ui.advance_cursor_after_rect(final_rect, preferred_size);

(result_left, result_right)
}
Expand Down
6 changes: 4 additions & 2 deletions crates/egui/src/introspection.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! Showing UI:s for egui/epaint types.

use crate::{
epaint, memory, pos2, remap_clamp, vec2, Color32, CursorIcon, FontFamily, FontId, Label, Mesh,
NumExt as _, Rect, Response, Sense, Shape, Slider, TextStyle, TextWrapMode, Ui, Widget,
};
use emath::Vec2;

pub fn font_family_ui(ui: &mut Ui, font_family: &mut FontFamily) {
let families = ui.fonts(|f| f.families());
Expand Down Expand Up @@ -42,7 +44,7 @@ pub(crate) fn font_texture_ui(ui: &mut Ui, [width, height]: [usize; 2]) -> Respo
if size.x > ui.available_width() {
size *= ui.available_width() / size.x;
}
let (rect, response) = ui.allocate_at_least(size, Sense::hover());
let (rect, response) = ui.allocate_at_least(size, Sense::hover(), Vec2::ZERO); // TODO
let mut mesh = Mesh::default();
mesh.add_rect_with_uv(rect, [pos2(0.0, 0.0), pos2(1.0, 1.0)].into(), color);
ui.painter().add(Shape::mesh(mesh));
Expand All @@ -53,7 +55,7 @@ pub(crate) fn font_texture_ui(ui: &mut Ui, [width, height]: [usize; 2]) -> Respo
.on_hover_cursor(CursorIcon::ZoomIn)
.on_hover_ui_at_pointer(|ui| {
if let Some(pos) = ui.ctx().pointer_latest_pos() {
let (_id, zoom_rect) = ui.allocate_space(vec2(128.0, 128.0));
let (_id, zoom_rect) = ui.allocate_space(vec2(128.0, 128.0), Vec2::ZERO); // TODO
let u = remap_clamp(pos.x, rect.x_range(), 0.0..=tex_w);
let v = remap_clamp(pos.y, rect.y_range(), 0.0..=tex_h);

Expand Down
13 changes: 13 additions & 0 deletions crates/egui/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ pub(crate) struct Region {
/// If something has already been added, this will point to `style.spacing.item_spacing` beyond the latest child.
/// The cursor can thus be `style.spacing.item_spacing` pixels outside of the `min_rect`.
pub(crate) cursor: Rect,

pub(crate) intrinsic_size: Vec2,
pub max_intrinsic_width: Option<f32>,
pub max_intrinsic_height: Option<f32>,
}

impl Region {
Expand Down Expand Up @@ -434,6 +438,9 @@ impl Layout {
min_rect: Rect::NOTHING, // temporary
max_rect,
cursor: self.initial_cursor(max_rect),
intrinsic_size: Vec2::default(),
max_intrinsic_width: None,
max_intrinsic_height: None,
};
let seed = self.next_widget_position(&region);
region.min_rect = Rect::from_center_size(seed, Vec2::ZERO);
Expand Down Expand Up @@ -540,6 +547,9 @@ impl Layout {
mut cursor,
mut max_rect,
min_rect,
intrinsic_size: min_item_size,
max_intrinsic_width,
max_intrinsic_height,
} = *region;

match self.main_dir {
Expand Down Expand Up @@ -601,6 +611,9 @@ impl Layout {
min_rect,
max_rect,
cursor,
intrinsic_size: min_item_size,
max_intrinsic_width,
max_intrinsic_height,
};

self.next_frame_ignore_wrap(&region, child_size)
Expand Down
2 changes: 1 addition & 1 deletion crates/egui/src/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ impl SubMenuButton {
let mut desired_size = text_and_icon_size + 2.0 * button_padding;
desired_size.y = desired_size.y.at_least(ui.spacing().interact_size.y);

let (rect, response) = ui.allocate_at_least(desired_size, sense);
let (rect, response) = ui.allocate_at_least(desired_size, sense, Vec2::ZERO); // TODO
response.widget_info(|| {
crate::WidgetInfo::labeled(
crate::WidgetType::Button,
Expand Down
33 changes: 32 additions & 1 deletion crates/egui/src/placer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{grid, vec2, Layout, Painter, Pos2, Rect, Region, Vec2};
use crate::{grid, vec2, Direction, Layout, Painter, Pos2, Rect, Region, Vec2};

#[cfg(debug_assertions)]
use crate::{Align2, Color32, Stroke};
Expand Down Expand Up @@ -163,6 +163,7 @@ impl Placer {
frame_rect: Rect,
widget_rect: Rect,
item_spacing: Vec2,
intrinsic_size: Vec2,
) {
debug_assert!(!frame_rect.any_nan(), "frame_rect: {frame_rect:?}");
debug_assert!(
Expand All @@ -182,11 +183,37 @@ impl Placer {
);
}

if self.layout.is_horizontal() {
if self.region.intrinsic_size.x != 0.0 {
self.region.intrinsic_size.x += item_spacing.x;
}
self.region.intrinsic_size.x += intrinsic_size.x;
self.region.intrinsic_size.y = self.region.intrinsic_size.y.max(intrinsic_size.y);
} else {
if self.region.intrinsic_size.y != 0.0 {
self.region.intrinsic_size.y += item_spacing.y;
}
self.region.intrinsic_size.x = self.region.intrinsic_size.x.max(intrinsic_size.x);
self.region.intrinsic_size.y += intrinsic_size.y;
}

self.expand_to_include_rect(frame_rect); // e.g. for centered layouts: pretend we used whole frame

self.region.sanity_check();
}

pub(crate) fn intrinsic_size(&self) -> Vec2 {
//self.region.intrinsic_size.min(self.max_rect().size())
let mut intrinsic = self.region.intrinsic_size;
if let Some(max_x) = self.region.max_intrinsic_width {
intrinsic.x = intrinsic.x.min(max_x);
}
if let Some(max_y) = self.region.max_intrinsic_height {
intrinsic.y = intrinsic.y.min(max_y);
}
intrinsic
}

/// Move to the next row in a grid layout or wrapping layout.
/// Otherwise does nothing.
pub(crate) fn end_row(&mut self, item_spacing: Vec2, painter: &Painter) {
Expand Down Expand Up @@ -237,6 +264,8 @@ impl Placer {
region.cursor.max.x = region.max_rect.max.x;

region.sanity_check();

region.max_intrinsic_width = Some(width);
}

/// Set the maximum height of the ui.
Expand All @@ -252,6 +281,8 @@ impl Placer {
region.cursor.max.y = region.max_rect.max.y;

region.sanity_check();

region.max_intrinsic_height = Some(height);
}

/// Set the minimum width of the ui.
Expand Down
2 changes: 1 addition & 1 deletion crates/egui/src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2556,7 +2556,7 @@ impl Widget for &mut Stroke {
ui.color_edit_button_srgba(color);

// stroke preview:
let (_id, stroke_rect) = ui.allocate_space(ui.spacing().interact_size);
let (_id, stroke_rect) = ui.allocate_space(ui.spacing().interact_size, Vec2::ZERO); // TODO
let left = stroke_rect.left_center();
let right = stroke_rect.right_center();
ui.painter().line_segment([left, right], (*width, *color));
Expand Down
Loading
Loading
0