diff --git a/CHANGELOG.md b/CHANGELOG.md index e01cf5ac..6f2356ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ NOTE: [`eframe`](eframe/CHANGELOG.md), [`egui_web`](egui_web/CHANGELOG.md), [`eg * MSRV (Minimum Supported Rust Version) is now `1.54.0`. * By default, `DragValue`:s no longer show a tooltip when hovered. Change with `Style::explanation_tooltips`. * Smaller and nicer color picker. +* `ScrollArea` will auto-shrink to content size unless told otherwise using `ScollArea::auto_shrink`. ### Fixed 🐛 * Fix wrongly sized multiline `TextEdit` in justified layouts. diff --git a/egui/src/containers/scroll_area.rs b/egui/src/containers/scroll_area.rs index 39dd1de9..d408b78c 100644 --- a/egui/src/containers/scroll_area.rs +++ b/egui/src/containers/scroll_area.rs @@ -341,14 +341,14 @@ impl ScrollArea { let y_min = ui.max_rect().top() + min_row as f32 * row_height_with_spacing; let y_max = ui.max_rect().top() + max_row as f32 * row_height_with_spacing; - let mut viewport_ui = ui.child_ui( - Rect::from_x_y_ranges(ui.max_rect().x_range(), y_min..=y_max), - *ui.layout(), - ); - viewport_ui.skip_ahead_auto_ids(min_row); // Make sure we get consistent IDs. + let rect = Rect::from_x_y_ranges(ui.max_rect().x_range(), y_min..=y_max); - add_contents(&mut viewport_ui, min_row..max_row) + ui.allocate_ui_at_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) + }) + .inner }) } @@ -389,10 +389,9 @@ impl Prepared { let content_size = content_ui.min_size(); - // We take the scroll target so only this ScrollArea will use it. - for d in 0..2 { if has_bar[d] { + // We take the scroll target so only this ScrollArea will use it: let scroll_target = content_ui.ctx().frame_state().scroll_target[d].take(); if let Some((scroll, align)) = scroll_target { let center_factor = align.to_factor(); @@ -412,19 +411,15 @@ impl Prepared { } let inner_rect = { + // At this point this is the available size for the inner rect. let mut inner_size = inner_rect.size(); for d in 0..2 { - inner_size[d] = if has_bar[d] { - if auto_shrink[d] { - inner_size[d].min(content_size[d]) // shrink scroll area if content is small - } else { - inner_size[d] // let scroll area be larger than content; fill with blank space - } - } else if inner_size[d].is_finite() { - inner_size[d].max(content_size[d]) // Expand to fit content - } else { - content_size[d] // ScrollArea is in an infinitely sized parent; take size of parent + inner_size[d] = match (has_bar[d], auto_shrink[d]) { + (true, true) => inner_size[d].min(content_size[d]), // shrink scroll area if content is small + (true, false) => inner_size[d], // let scroll area be larger than content; fill with blank space + (false, true) => content_size[d], // Follow the content (expand/contract to fit it). + (false, false) => inner_size[d].max(content_size[d]), // Expand to fit content }; } diff --git a/egui_demo_lib/src/apps/demo/scrolling.rs b/egui_demo_lib/src/apps/demo/scrolling.rs index fdbd2ff5..7812de68 100644 --- a/egui_demo_lib/src/apps/demo/scrolling.rs +++ b/egui_demo_lib/src/apps/demo/scrolling.rs @@ -32,7 +32,7 @@ impl super::Demo for Scrolling { .open(open) .resizable(false) .show(ctx, |ui| { - use super::View; + use super::View as _; self.ui(ui); }); } @@ -77,12 +77,17 @@ fn huge_content_lines(ui: &mut egui::Ui) { let text_style = TextStyle::Body; let row_height = ui.fonts()[text_style].row_height(); let num_rows = 10_000; - ScrollArea::vertical().show_rows(ui, row_height, num_rows, |ui, row_range| { - for row in row_range { - let text = format!("This is row {}/{}", row + 1, num_rows); - ui.label(text); - } - }); + ScrollArea::vertical().auto_shrink([false; 2]).show_rows( + ui, + row_height, + num_rows, + |ui, row_range| { + for row in row_range { + let text = format!("This is row {}/{}", row + 1, num_rows); + ui.label(text); + } + }, + ); } fn huge_content_painter(ui: &mut egui::Ui) { @@ -94,32 +99,39 @@ fn huge_content_painter(ui: &mut egui::Ui) { let row_height = ui.fonts()[text_style].row_height() + ui.spacing().item_spacing.y; let num_rows = 10_000; - ScrollArea::vertical().show_viewport(ui, |ui, viewport| { - ui.set_height(row_height * num_rows as f32); + ScrollArea::vertical() + .auto_shrink([false; 2]) + .show_viewport(ui, |ui, viewport| { + ui.set_height(row_height * num_rows as f32); - let first_item = (viewport.min.y / row_height).floor().at_least(0.0) as usize; - let last_item = (viewport.max.y / row_height).ceil() as usize + 1; - let last_item = last_item.at_most(num_rows); + let first_item = (viewport.min.y / row_height).floor().at_least(0.0) as usize; + let last_item = (viewport.max.y / row_height).ceil() as usize + 1; + let last_item = last_item.at_most(num_rows); - for i in first_item..last_item { - let indentation = (i % 100) as f32; - let x = ui.min_rect().left() + indentation; - let y = ui.min_rect().top() + i as f32 * row_height; - let text = format!( - "This is row {}/{}, indented by {} pixels", - i + 1, - num_rows, - indentation - ); - ui.painter().text( - pos2(x, y), - Align2::LEFT_TOP, - text, - text_style, - ui.visuals().text_color(), - ); - } - }); + let mut used_rect = Rect::NOTHING; + + for i in first_item..last_item { + let indentation = (i % 100) as f32; + let x = ui.min_rect().left() + indentation; + let y = ui.min_rect().top() + i as f32 * row_height; + let text = format!( + "This is row {}/{}, indented by {} pixels", + i + 1, + num_rows, + indentation + ); + let text_rect = ui.painter().text( + pos2(x, y), + Align2::LEFT_TOP, + text, + text_style, + ui.visuals().text_color(), + ); + used_rect = used_rect.union(text_rect); + } + + ui.allocate_rect(used_rect, Sense::hover()); // make sure it is visible! + }); } // ---------------------------------------------------------------------------- @@ -184,7 +196,9 @@ impl super::View for ScrollTo { scroll_bottom |= ui.button("Scroll to bottom").clicked(); }); - let mut scroll_area = ScrollArea::vertical().max_height(200.0); + let mut scroll_area = ScrollArea::vertical() + .max_height(200.0) + .auto_shrink([false; 2]); if go_to_scroll_offset { scroll_area = scroll_area.scroll_offset(self.offset); }