mirror of
https://github.com/emilk/egui.git
synced 2026-06-27 23:13:13 -04:00
Experiment with calculating an Ui's "intrinsic size" by remembering the widget's size
This commit is contained in:
@@ -613,7 +613,9 @@ impl Prepared {
|
||||
..
|
||||
} = self;
|
||||
|
||||
state.size = Some(content_ui.min_size());
|
||||
state.size = Some(content_ui.placer().min_item_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.
|
||||
|
||||
@@ -568,7 +568,8 @@ impl<'a> Popup<'a> {
|
||||
|
||||
let mut response = area.show(&ctx, |ui| {
|
||||
style.apply(ui.style_mut());
|
||||
frame.show(ui, content).inner
|
||||
// frame.show(ui, content).inner
|
||||
content(ui)
|
||||
});
|
||||
|
||||
let closed_by_click = match close_behavior {
|
||||
|
||||
@@ -45,6 +45,8 @@ 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 min_item_size: Vec2,
|
||||
}
|
||||
|
||||
impl Region {
|
||||
@@ -426,6 +428,7 @@ impl Layout {
|
||||
min_rect: Rect::NOTHING, // temporary
|
||||
max_rect,
|
||||
cursor: self.initial_cursor(max_rect),
|
||||
min_item_size: Vec2::default(),
|
||||
};
|
||||
let seed = self.next_widget_position(®ion);
|
||||
region.min_rect = Rect::from_center_size(seed, Vec2::ZERO);
|
||||
@@ -529,6 +532,7 @@ impl Layout {
|
||||
mut cursor,
|
||||
mut max_rect,
|
||||
min_rect,
|
||||
min_item_size,
|
||||
} = *region;
|
||||
|
||||
match self.main_dir {
|
||||
@@ -590,6 +594,7 @@ impl Layout {
|
||||
min_rect,
|
||||
max_rect,
|
||||
cursor,
|
||||
min_item_size,
|
||||
};
|
||||
|
||||
self.next_frame_ignore_wrap(®ion, child_size)
|
||||
|
||||
@@ -163,6 +163,7 @@ impl Placer {
|
||||
frame_rect: Rect,
|
||||
widget_rect: Rect,
|
||||
item_spacing: Vec2,
|
||||
desired_size: Vec2,
|
||||
) {
|
||||
debug_assert!(!frame_rect.any_nan());
|
||||
debug_assert!(!widget_rect.any_nan());
|
||||
@@ -179,11 +180,17 @@ impl Placer {
|
||||
);
|
||||
}
|
||||
|
||||
self.region.min_item_size = self.region.min_item_size.max(desired_size);
|
||||
|
||||
self.expand_to_include_rect(frame_rect); // e.g. for centered layouts: pretend we used whole frame
|
||||
|
||||
self.region.sanity_check();
|
||||
}
|
||||
|
||||
pub(crate) fn min_item_size(&self) -> Vec2 {
|
||||
self.region.min_item_size
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
|
||||
@@ -1403,7 +1403,7 @@ impl Ui {
|
||||
let widget_rect = self.placer.justify_and_align(frame_rect, desired_size);
|
||||
|
||||
self.placer
|
||||
.advance_after_rects(frame_rect, widget_rect, item_spacing);
|
||||
.advance_after_rects(frame_rect, widget_rect, item_spacing, desired_size);
|
||||
|
||||
register_rect(self, widget_rect);
|
||||
|
||||
@@ -1426,7 +1426,8 @@ impl Ui {
|
||||
let rect = rect.round_ui();
|
||||
|
||||
let item_spacing = self.spacing().item_spacing;
|
||||
self.placer.advance_after_rects(rect, rect, item_spacing);
|
||||
self.placer
|
||||
.advance_after_rects(rect, rect, item_spacing, rect.size());
|
||||
register_rect(self, rect);
|
||||
|
||||
let id = Id::new(self.next_auto_id_salt);
|
||||
@@ -2412,8 +2413,22 @@ impl Ui {
|
||||
let mut child_ui = self.new_child(ui_builder);
|
||||
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`.
|
||||
let ret = add_contents(&mut child_ui);
|
||||
let response = child_ui.remember_min_rect();
|
||||
let mut response = child_ui.remember_min_rect();
|
||||
self.advance_cursor_after_rect(child_ui.min_rect());
|
||||
match self.layout().is_horizontal() {
|
||||
true => {
|
||||
response.intrinsic_size = Some(Vec2::new(
|
||||
response.rect.width(),
|
||||
self.placer.min_item_size().y,
|
||||
));
|
||||
}
|
||||
false => {
|
||||
response.intrinsic_size = Some(Vec2::new(
|
||||
self.placer.min_item_size().x,
|
||||
response.rect.height(),
|
||||
));
|
||||
}
|
||||
}
|
||||
InnerResponse::new(ret, response)
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ impl Widget for Checkbox<'_> {
|
||||
|
||||
desired_size = desired_size.at_least(Vec2::splat(spacing.interact_size.y));
|
||||
desired_size.y = desired_size.y.max(icon_width);
|
||||
dbg!(desired_size);
|
||||
let (rect, mut response) = ui.allocate_exact_size(desired_size, Sense::click());
|
||||
|
||||
if response.clicked() {
|
||||
|
||||
@@ -70,6 +70,18 @@ fn nested_menus(ui: &mut egui::Ui, checked: &mut bool) {
|
||||
}
|
||||
let _ = ui.button("Item");
|
||||
ui.menu_button("Recursive", |ui| nested_menus(ui, checked));
|
||||
|
||||
// if ui.button(if *checked { "short" } else { "Very long text for this item that should be wrapped" }).clicked() {
|
||||
// *checked = !*checked;
|
||||
// }
|
||||
ui.checkbox(
|
||||
checked,
|
||||
if *checked {
|
||||
"short"
|
||||
} else {
|
||||
"Very long text for this item that should be wrapped"
|
||||
},
|
||||
);
|
||||
});
|
||||
ui.menu_button("SubMenu", |ui| {
|
||||
if ui.button("Open…").clicked() {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||
|
||||
use eframe::egui;
|
||||
use eframe::egui::{Align, Button, Layout, Popup, TextWrapMode, Widget};
|
||||
|
||||
fn main() -> eframe::Result {
|
||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||
@@ -15,19 +16,46 @@ fn main() -> eframe::Result {
|
||||
let mut name = "Arthur".to_owned();
|
||||
let mut age = 42;
|
||||
|
||||
let mut checked = true;
|
||||
|
||||
eframe::run_simple_native("My egui App", options, move |ctx, _frame| {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.heading("My egui Application");
|
||||
ui.horizontal(|ui| {
|
||||
let name_label = ui.label("Your name: ");
|
||||
ui.text_edit_singleline(&mut name)
|
||||
.labelled_by(name_label.id);
|
||||
});
|
||||
ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));
|
||||
if ui.button("Increment").clicked() {
|
||||
age += 1;
|
||||
}
|
||||
ui.label(format!("Hello '{name}', age {age}"));
|
||||
// ui.heading("My egui Application");
|
||||
// ui.horizontal(|ui| {
|
||||
// let name_label = ui.label("Your name: ");
|
||||
// ui.text_edit_singleline(&mut name)
|
||||
// .labelled_by(name_label.id);
|
||||
// });
|
||||
// ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));
|
||||
// if ui.button("Increment").clicked() {
|
||||
// age += 1;
|
||||
// }
|
||||
// ui.label(format!("Hello '{name}', age {age}"));
|
||||
|
||||
let response = ui.button("Hiiii");
|
||||
|
||||
let text = if checked {
|
||||
"short"
|
||||
} else {
|
||||
"Very long text for this item that should be wrapped"
|
||||
};
|
||||
Popup::from_response(&response)
|
||||
.layout(Layout::top_down_justified(Align::Min))
|
||||
.show(|ui| {
|
||||
// ui.checkbox(&mut checked, text);
|
||||
|
||||
ui.button("Hiiii");
|
||||
|
||||
if Button::new(text)
|
||||
.wrap_mode(TextWrapMode::Extend)
|
||||
.ui(ui)
|
||||
.clicked()
|
||||
{
|
||||
checked = !checked;
|
||||
}
|
||||
|
||||
ui.button("Some other button");
|
||||
});
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user