mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 06:40:06 -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;
|
} = 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.
|
// 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.
|
// 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| {
|
let mut response = area.show(&ctx, |ui| {
|
||||||
style.apply(ui.style_mut());
|
style.apply(ui.style_mut());
|
||||||
frame.show(ui, content).inner
|
// frame.show(ui, content).inner
|
||||||
|
content(ui)
|
||||||
});
|
});
|
||||||
|
|
||||||
let closed_by_click = match close_behavior {
|
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.
|
/// 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`.
|
/// The cursor can thus be `style.spacing.item_spacing` pixels outside of the `min_rect`.
|
||||||
pub(crate) cursor: Rect,
|
pub(crate) cursor: Rect,
|
||||||
|
|
||||||
|
pub min_item_size: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Region {
|
impl Region {
|
||||||
@@ -426,6 +428,7 @@ impl Layout {
|
|||||||
min_rect: Rect::NOTHING, // temporary
|
min_rect: Rect::NOTHING, // temporary
|
||||||
max_rect,
|
max_rect,
|
||||||
cursor: self.initial_cursor(max_rect),
|
cursor: self.initial_cursor(max_rect),
|
||||||
|
min_item_size: Vec2::default(),
|
||||||
};
|
};
|
||||||
let seed = self.next_widget_position(®ion);
|
let seed = self.next_widget_position(®ion);
|
||||||
region.min_rect = Rect::from_center_size(seed, Vec2::ZERO);
|
region.min_rect = Rect::from_center_size(seed, Vec2::ZERO);
|
||||||
@@ -529,6 +532,7 @@ impl Layout {
|
|||||||
mut cursor,
|
mut cursor,
|
||||||
mut max_rect,
|
mut max_rect,
|
||||||
min_rect,
|
min_rect,
|
||||||
|
min_item_size,
|
||||||
} = *region;
|
} = *region;
|
||||||
|
|
||||||
match self.main_dir {
|
match self.main_dir {
|
||||||
@@ -590,6 +594,7 @@ impl Layout {
|
|||||||
min_rect,
|
min_rect,
|
||||||
max_rect,
|
max_rect,
|
||||||
cursor,
|
cursor,
|
||||||
|
min_item_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.next_frame_ignore_wrap(®ion, child_size)
|
self.next_frame_ignore_wrap(®ion, child_size)
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ impl Placer {
|
|||||||
frame_rect: Rect,
|
frame_rect: Rect,
|
||||||
widget_rect: Rect,
|
widget_rect: Rect,
|
||||||
item_spacing: Vec2,
|
item_spacing: Vec2,
|
||||||
|
desired_size: Vec2,
|
||||||
) {
|
) {
|
||||||
debug_assert!(!frame_rect.any_nan());
|
debug_assert!(!frame_rect.any_nan());
|
||||||
debug_assert!(!widget_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.expand_to_include_rect(frame_rect); // e.g. for centered layouts: pretend we used whole frame
|
||||||
|
|
||||||
self.region.sanity_check();
|
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.
|
/// Move to the next row in a grid layout or wrapping layout.
|
||||||
/// Otherwise does nothing.
|
/// Otherwise does nothing.
|
||||||
pub(crate) fn end_row(&mut self, item_spacing: Vec2, painter: &Painter) {
|
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);
|
let widget_rect = self.placer.justify_and_align(frame_rect, desired_size);
|
||||||
|
|
||||||
self.placer
|
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);
|
register_rect(self, widget_rect);
|
||||||
|
|
||||||
@@ -1426,7 +1426,8 @@ impl Ui {
|
|||||||
let rect = rect.round_ui();
|
let rect = rect.round_ui();
|
||||||
|
|
||||||
let item_spacing = self.spacing().item_spacing;
|
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);
|
register_rect(self, rect);
|
||||||
|
|
||||||
let id = Id::new(self.next_auto_id_salt);
|
let id = Id::new(self.next_auto_id_salt);
|
||||||
@@ -2412,8 +2413,22 @@ impl Ui {
|
|||||||
let mut child_ui = self.new_child(ui_builder);
|
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`.
|
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 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());
|
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)
|
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 = desired_size.at_least(Vec2::splat(spacing.interact_size.y));
|
||||||
desired_size.y = desired_size.y.max(icon_width);
|
desired_size.y = desired_size.y.max(icon_width);
|
||||||
|
dbg!(desired_size);
|
||||||
let (rect, mut response) = ui.allocate_exact_size(desired_size, Sense::click());
|
let (rect, mut response) = ui.allocate_exact_size(desired_size, Sense::click());
|
||||||
|
|
||||||
if response.clicked() {
|
if response.clicked() {
|
||||||
|
|||||||
@@ -70,6 +70,18 @@ fn nested_menus(ui: &mut egui::Ui, checked: &mut bool) {
|
|||||||
}
|
}
|
||||||
let _ = ui.button("Item");
|
let _ = ui.button("Item");
|
||||||
ui.menu_button("Recursive", |ui| nested_menus(ui, checked));
|
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| {
|
ui.menu_button("SubMenu", |ui| {
|
||||||
if ui.button("Open…").clicked() {
|
if ui.button("Open…").clicked() {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||||
|
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
|
use eframe::egui::{Align, Button, Layout, Popup, TextWrapMode, Widget};
|
||||||
|
|
||||||
fn main() -> eframe::Result {
|
fn main() -> eframe::Result {
|
||||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
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 name = "Arthur".to_owned();
|
||||||
let mut age = 42;
|
let mut age = 42;
|
||||||
|
|
||||||
|
let mut checked = true;
|
||||||
|
|
||||||
eframe::run_simple_native("My egui App", options, move |ctx, _frame| {
|
eframe::run_simple_native("My egui App", options, move |ctx, _frame| {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
ui.heading("My egui Application");
|
// ui.heading("My egui Application");
|
||||||
ui.horizontal(|ui| {
|
// ui.horizontal(|ui| {
|
||||||
let name_label = ui.label("Your name: ");
|
// let name_label = ui.label("Your name: ");
|
||||||
ui.text_edit_singleline(&mut name)
|
// ui.text_edit_singleline(&mut name)
|
||||||
.labelled_by(name_label.id);
|
// .labelled_by(name_label.id);
|
||||||
});
|
// });
|
||||||
ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));
|
// ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));
|
||||||
if ui.button("Increment").clicked() {
|
// if ui.button("Increment").clicked() {
|
||||||
age += 1;
|
// age += 1;
|
||||||
}
|
// }
|
||||||
ui.label(format!("Hello '{name}', age {age}"));
|
// 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