From e8f5e5059ca278db7bcf2c1c97f4488f3c5c80be Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 30 Nov 2022 21:57:26 +0100 Subject: [PATCH 1/9] Nicer debug rectangles --- crates/egui/src/painter.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/egui/src/painter.rs b/crates/egui/src/painter.rs index df3a5d95622..13cb6046d09 100644 --- a/crates/egui/src/painter.rs +++ b/crates/egui/src/painter.rs @@ -208,7 +208,12 @@ impl Painter { impl Painter { #[allow(clippy::needless_pass_by_value)] pub fn debug_rect(&self, rect: Rect, color: Color32, text: impl ToString) { - self.rect_stroke(rect, 0.0, (1.0, color)); + self.rect( + rect, + 0.0, + color.additive().linear_multiply(0.015), + (1.0, color), + ); self.text( rect.min, Align2::LEFT_TOP, From b8dd13db0308cdb612441412df18f156fab5a55b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 30 Nov 2022 22:03:52 +0100 Subject: [PATCH 2/9] Move scrollbars into the clip-rect so they are always visible --- crates/egui/src/containers/scroll_area.rs | 35 +++++++++++------------ 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/crates/egui/src/containers/scroll_area.rs b/crates/egui/src/containers/scroll_area.rs index 98bb959f9f5..8899b30f150 100644 --- a/crates/egui/src/containers/scroll_area.rs +++ b/crates/egui/src/containers/scroll_area.rs @@ -635,23 +635,7 @@ impl Prepared { }; } - let mut inner_rect = Rect::from_min_size(inner_rect.min, inner_size); - - // The window that egui sits in can't be expanded by egui, so we need to respect it: - for d in 0..2 { - if !has_bar[d] { - // HACK for when we have a vertical-only scroll area in a top level panel, - // and that panel is not wide enough for the contents. - // This code ensures we still see the scroll bar! - let max = ui.input().screen_rect().max[d] - - current_bar_use[d] - - ui.spacing().item_spacing[d]; - inner_rect.max[d] = inner_rect.max[d].at_most(max); - // TODO(emilk): maybe auto-enable horizontal/vertical scrolling if this limit is reached - } - } - - inner_rect + Rect::from_min_size(inner_rect.min, inner_size) }; let outer_rect = Rect::from_min_size(inner_rect.min, inner_rect.size() + current_bar_use); @@ -705,11 +689,24 @@ impl Prepared { // margin between contents and scroll bar let margin = animation_t * ui.spacing().item_spacing.x; - let min_cross = inner_rect.max[1 - d] + margin; // left of vertical scroll (d == 1) - let max_cross = outer_rect.max[1 - d]; // right of vertical scroll (d == 1) + let mut min_cross = inner_rect.max[1 - d] + margin; // left of vertical scroll (d == 1) + let mut max_cross = outer_rect.max[1 - d]; // right of vertical scroll (d == 1) let min_main = inner_rect.min[d]; // top of vertical scroll (d == 1) let max_main = inner_rect.max[d]; // bottom of vertical scroll (d == 1) + if ui.clip_rect().max[1 - d] < max_cross + ui.spacing().item_spacing.x { + // Move the scrollbar so it is visible. This is needed in some cases. + // For instance: + // * When we have a vertical-only scroll area in a top level panel, + // and that panel is not wide enough for the contents. + // * When one ScrollArea is nested inside another, and the outer + // is scrolled so that the scroll-bars of the inner ScrollArea (us) + // is outside the clip rectangle. + let width = max_cross - min_cross; + max_cross = ui.clip_rect().max[1 - d] - ui.spacing().item_spacing.x; + min_cross = max_cross - width; + } + let outer_scroll_rect = if d == 0 { Rect::from_min_max( pos2(inner_rect.left(), min_cross), From 7a58e8005d079f810bfe72e29957ec50a87882a4 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 30 Nov 2022 22:05:38 +0100 Subject: [PATCH 3/9] Improve table demo --- crates/egui_demo_lib/src/demo/table_demo.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/egui_demo_lib/src/demo/table_demo.rs b/crates/egui_demo_lib/src/demo/table_demo.rs index 01e0bdd9882..03f2d07b099 100644 --- a/crates/egui_demo_lib/src/demo/table_demo.rs +++ b/crates/egui_demo_lib/src/demo/table_demo.rs @@ -47,7 +47,7 @@ impl super::Demo for TableDemo { } } -const NUM_MANUAL_ROWS: usize = 32; +const NUM_MANUAL_ROWS: usize = 20; impl super::View for TableDemo { fn ui(&mut self, ui: &mut egui::Ui) { @@ -101,11 +101,13 @@ impl super::View for TableDemo { // Leave room for the source code link after the table demo: use egui_extras::{Size, StripBuilder}; StripBuilder::new(ui) - .size(Size::remainder()) // for the table + .size(Size::remainder().at_least(100.0)) // for the table .size(Size::exact(10.0)) // for the source code link .vertical(|mut strip| { strip.cell(|ui| { - self.table_ui(ui); + egui::ScrollArea::horizontal().show(ui, |ui| { + self.table_ui(ui); + }); }); strip.cell(|ui| { ui.vertical_centered(|ui| { @@ -133,7 +135,8 @@ impl TableDemo { .resizable(true) .clip(true), ) - .column(Column::remainder()); + .column(Column::remainder()) + .min_scrolled_height(0.0); if let Some(row_nr) = self.scroll_to_row.take() { table = table.scroll_to_row(row_nr, None); From 5481b8036a1f9ea9e65bae19a2396709222ac16b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 30 Nov 2022 22:28:06 +0100 Subject: [PATCH 4/9] Add options for controlling inner and outer margin of the scroll bars --- crates/egui/src/containers/scroll_area.rs | 19 ++++++++++++------- crates/egui/src/style.rs | 19 ++++++++++++++++++- crates/egui_demo_lib/src/demo/scrolling.rs | 10 ++++++++++ crates/egui_extras/src/table.rs | 4 +++- 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/crates/egui/src/containers/scroll_area.rs b/crates/egui/src/containers/scroll_area.rs index 8899b30f150..d4676957e73 100644 --- a/crates/egui/src/containers/scroll_area.rs +++ b/crates/egui/src/containers/scroll_area.rs @@ -687,14 +687,15 @@ impl Prepared { continue; } - // margin between contents and scroll bar - let margin = animation_t * ui.spacing().item_spacing.x; - let mut min_cross = inner_rect.max[1 - d] + margin; // left of vertical scroll (d == 1) - let mut max_cross = outer_rect.max[1 - d]; // right of vertical scroll (d == 1) + // margin on either side of the scroll bar + let inner_margin = animation_t * ui.spacing().scroll_bar_inner_margin; + let outer_margin = animation_t * ui.spacing().scroll_bar_outer_margin; + let mut min_cross = inner_rect.max[1 - d] + inner_margin; // left of vertical scroll (d == 1) + let mut max_cross = outer_rect.max[1 - d] - outer_margin; // right of vertical scroll (d == 1) let min_main = inner_rect.min[d]; // top of vertical scroll (d == 1) let max_main = inner_rect.max[d]; // bottom of vertical scroll (d == 1) - if ui.clip_rect().max[1 - d] < max_cross + ui.spacing().item_spacing.x { + if ui.clip_rect().max[1 - d] < max_cross + outer_margin { // Move the scrollbar so it is visible. This is needed in some cases. // For instance: // * When we have a vertical-only scroll area in a top level panel, @@ -702,8 +703,10 @@ impl Prepared { // * When one ScrollArea is nested inside another, and the outer // is scrolled so that the scroll-bars of the inner ScrollArea (us) // is outside the clip rectangle. + // Really this should use the tighter clip_rect that ignores clip_rect_margin, but we don't store that. + // clip_rect_margin is quite a hack. It would be nice to get rid of it. let width = max_cross - min_cross; - max_cross = ui.clip_rect().max[1 - d] - ui.spacing().item_spacing.x; + max_cross = ui.clip_rect().max[1 - d] - outer_margin; min_cross = max_cross - width; } @@ -862,5 +865,7 @@ impl Prepared { /// Width of a vertical scrollbar, or height of a horizontal scroll bar fn max_scroll_bar_width_with_margin(ui: &Ui) -> f32 { - ui.spacing().item_spacing.x + ui.spacing().scroll_bar_width + ui.spacing().scroll_bar_inner_margin + + ui.spacing().scroll_bar_width + + ui.spacing().scroll_bar_outer_margin } diff --git a/crates/egui/src/style.rs b/crates/egui/src/style.rs index 195577fa66c..a4cd8817255 100644 --- a/crates/egui/src/style.rs +++ b/crates/egui/src/style.rs @@ -292,6 +292,11 @@ pub struct Spacing { pub combo_height: f32, pub scroll_bar_width: f32, + + /// Margin between contents and scroll bar. + pub scroll_bar_inner_margin: f32, + /// Margin between scroll bar and the outer container (e.g. right of a vertical scroll bar). + pub scroll_bar_outer_margin: f32, } impl Spacing { @@ -658,6 +663,8 @@ impl Default for Spacing { tooltip_width: 600.0, combo_height: 200.0, scroll_bar_width: 8.0, + scroll_bar_inner_margin: 4.0, + scroll_bar_outer_margin: 0.0, indent_ends_with_horizontal_line: false, } } @@ -941,6 +948,8 @@ impl Spacing { indent_ends_with_horizontal_line, combo_height, scroll_bar_width, + scroll_bar_inner_margin, + scroll_bar_outer_margin, } = self; ui.add(slider_vec2(item_spacing, 0.0..=20.0, "Item spacing")); @@ -1021,7 +1030,15 @@ impl Spacing { }); ui.horizontal(|ui| { ui.add(DragValue::new(scroll_bar_width).clamp_range(0.0..=32.0)); - ui.label("Scroll-bar width width"); + ui.label("Scroll-bar width"); + }); + ui.horizontal(|ui| { + ui.add(DragValue::new(scroll_bar_inner_margin).clamp_range(0.0..=32.0)); + ui.label("Scroll-bar inner margin"); + }); + ui.horizontal(|ui| { + ui.add(DragValue::new(scroll_bar_outer_margin).clamp_range(0.0..=32.0)); + ui.label("Scroll-bar outer margin"); }); ui.horizontal(|ui| { diff --git a/crates/egui_demo_lib/src/demo/scrolling.rs b/crates/egui_demo_lib/src/demo/scrolling.rs index b375223b599..8eda415219a 100644 --- a/crates/egui_demo_lib/src/demo/scrolling.rs +++ b/crates/egui_demo_lib/src/demo/scrolling.rs @@ -7,6 +7,7 @@ enum ScrollDemo { ManyLines, LargeCanvas, StickToEnd, + Bidirectional, } impl Default for ScrollDemo { @@ -55,6 +56,7 @@ impl super::View for Scrolling { "Scroll a large canvas", ); ui.selectable_value(&mut self.demo, ScrollDemo::StickToEnd, "Stick to end"); + ui.selectable_value(&mut self.demo, ScrollDemo::Bidirectional, "Bidirectional"); }); ui.separator(); match self.demo { @@ -70,6 +72,14 @@ impl super::View for Scrolling { ScrollDemo::StickToEnd => { self.scroll_stick_to.ui(ui); } + ScrollDemo::Bidirectional => { + egui::ScrollArea::both().show(ui, |ui| { + ui.style_mut().wrap = Some(false); + for _ in 0..100 { + ui.label(crate::LOREM_IPSUM); + } + }); + } } } } diff --git a/crates/egui_extras/src/table.rs b/crates/egui_extras/src/table.rs index 91aeb219a74..ebd780c2e84 100644 --- a/crates/egui_extras/src/table.rs +++ b/crates/egui_extras/src/table.rs @@ -327,7 +327,9 @@ impl<'a> TableBuilder<'a> { fn available_width(&self) -> f32 { self.ui.available_rect_before_wrap().width() - if self.vscroll { - self.ui.spacing().item_spacing.x + self.ui.spacing().scroll_bar_width + self.ui.spacing().scroll_bar_inner_margin + + self.ui.spacing().scroll_bar_width + + self.ui.spacing().scroll_bar_outer_margin } else { 0.0 } From fb5fb44741dcf2078328671d102d2c45233e8578 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 30 Nov 2022 22:31:02 +0100 Subject: [PATCH 5/9] Add line to changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f5f34020b4..5ec4cc4f672 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,8 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG * Improved text rendering ([#2071](https://github.com/emilk/egui/pull/2071)). * Less jitter when calling `Context::set_pixels_per_point` ([#2239](https://github.com/emilk/egui/pull/2239)). * Fixed popups and color edit going outside the screen. -* Fixed keyboard support in `DragValue`. ([#2342](https://github.com/emilk/egui/pull/2342)). +* Fixed keyboard support in `DragValue` ([#2342](https://github.com/emilk/egui/pull/2342)). +* If you nest `ScrollAreas`, the inner scrollbar will now move its scroll bar so it is always visible ([#2371](https://github.com/emilk/egui/pull/2371)). ## 0.19.0 - 2022-08-20 From ce36640005ce484c2e3863d21db51aa92157679a Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 30 Nov 2022 22:36:12 +0100 Subject: [PATCH 6/9] Update egui_extras changelog with recent Table improvements --- CHANGELOG.md | 2 +- crates/egui_extras/CHANGELOG.md | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ec4cc4f672..45278cb31b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,7 +35,7 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG * Less jitter when calling `Context::set_pixels_per_point` ([#2239](https://github.com/emilk/egui/pull/2239)). * Fixed popups and color edit going outside the screen. * Fixed keyboard support in `DragValue` ([#2342](https://github.com/emilk/egui/pull/2342)). -* If you nest `ScrollAreas`, the inner scrollbar will now move its scroll bar so it is always visible ([#2371](https://github.com/emilk/egui/pull/2371)). +* If you nest `ScrollAreas` inside each other, the inner area will now move its scroll bar so it is always visible ([#2371](https://github.com/emilk/egui/pull/2371)). ## 0.19.0 - 2022-08-20 diff --git a/crates/egui_extras/CHANGELOG.md b/crates/egui_extras/CHANGELOG.md index 2e9fd663dfb..804312292c0 100644 --- a/crates/egui_extras/CHANGELOG.md +++ b/crates/egui_extras/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to the `egui_extras` integration will be noted in this file. ## Unreleased * Added `TableBuilder::vertical_scroll_offset`: method to set vertical scroll offset position for a table ([#1946](https://github.com/emilk/egui/pull/1946)). * Added `RetainedImage::from_svg_bytes_with_size` to be able to specify a size for SVGs to be rasterized at. +* Big `Table` improvements ([#2369](https://github.com/emilk/egui/pull/2369)): + * Double-click column separators to auto-size the column. + * All `Table` now store state. You may see warnings about reused table ids. Use `ui.push_id` to fix this. + * `TableBuilder::column` takes a `Column` instead of a `Size`. + * `Column` controls default size, size range, resizing, and clipping of columns. + * `Column::auto` will pick a size automatically + * Added `Table::scroll_to_row`. + * Added `Table::min_scrolled_height` and `Table::max_scroll_height`. + * Added `TableBody::max_size`. + * `Table::scroll` renamed to `Table::vscroll`. + * `egui_extras::Strip` now has `clip: false` by default. + * Fix bugs when putting `Table` inside of a horizontal `ScrollArea`. + * Many other bug fixes. + ## 0.19.0 - 2022-08-20 * MSRV (Minimum Supported Rust Version) is now `1.61.0` ([#1846](https://github.com/emilk/egui/pull/1846)). From 27fbcec1ca208089e6d90b8579a34c550982d4da Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 30 Nov 2022 22:44:28 +0100 Subject: [PATCH 7/9] Refactor Table:s scroll options --- crates/egui_extras/src/table.rs | 119 +++++++++++++------------------- 1 file changed, 47 insertions(+), 72 deletions(-) diff --git a/crates/egui_extras/src/table.rs b/crates/egui_extras/src/table.rs index ebd780c2e84..3b28137fb16 100644 --- a/crates/egui_extras/src/table.rs +++ b/crates/egui_extras/src/table.rs @@ -155,6 +155,30 @@ fn to_sizing(columns: &[Column]) -> crate::sizing::Sizing { // -----------------------------------------------------------------=---------- +struct TableScrollOptions { + vscroll: bool, + stick_to_bottom: bool, + scroll_to_row: Option<(usize, Option)>, + scroll_offset_y: Option, + min_scrolled_height: f32, + max_scroll_height: f32, +} + +impl Default for TableScrollOptions { + fn default() -> Self { + Self { + vscroll: true, + stick_to_bottom: false, + scroll_to_row: None, + scroll_offset_y: None, + min_scrolled_height: 200.0, + max_scroll_height: 800.0, + } + } +} + +// -----------------------------------------------------------------=---------- + /// Builder for a [`Table`] with (optional) fixed header and scrolling body. /// /// You must pre-allocate all columns with [`Self::column`]/[`Self::columns`]. @@ -195,14 +219,7 @@ pub struct TableBuilder<'a> { striped: bool, resizable: bool, cell_layout: egui::Layout, - - // Scroll stuff: - vscroll: bool, - stick_to_bottom: bool, - scroll_to_row: Option<(usize, Option)>, - scroll_offset_y: Option, - min_scrolled_height: f32, - max_scroll_height: f32, + scroll_options: TableScrollOptions, } impl<'a> TableBuilder<'a> { @@ -214,13 +231,7 @@ impl<'a> TableBuilder<'a> { striped: false, resizable: false, cell_layout, - - vscroll: true, - stick_to_bottom: false, - scroll_to_row: None, - scroll_offset_y: None, - min_scrolled_height: 200.0, - max_scroll_height: 800.0, + scroll_options: Default::default(), } } @@ -247,7 +258,7 @@ impl<'a> TableBuilder<'a> { /// Enable vertical scrolling in body (default: `true`) pub fn vscroll(mut self, vscroll: bool) -> Self { - self.vscroll = vscroll; + self.scroll_options.vscroll = vscroll; self } @@ -260,7 +271,7 @@ impl<'a> TableBuilder<'a> { /// dynamically? The scroll handle remains stuck until manually changed, and will become stuck /// once again when repositioned to the bottom. Default: `false`. pub fn stick_to_bottom(mut self, stick: bool) -> Self { - self.stick_to_bottom = stick; + self.scroll_options.stick_to_bottom = stick; self } @@ -272,7 +283,7 @@ impl<'a> TableBuilder<'a> { /// /// See also: [`Self::vertical_scroll_offset`]. pub fn scroll_to_row(mut self, row: usize, align: Option) -> Self { - self.scroll_to_row = Some((row, align)); + self.scroll_options.scroll_to_row = Some((row, align)); self } @@ -280,7 +291,7 @@ impl<'a> TableBuilder<'a> { /// /// See also: [`Self::scroll_to_row`]. pub fn vertical_scroll_offset(mut self, offset: f32) -> Self { - self.scroll_offset_y = Some(offset); + self.scroll_options.scroll_offset_y = Some(offset); self } @@ -291,7 +302,7 @@ impl<'a> TableBuilder<'a> { /// /// Default: `200.0`. pub fn min_scrolled_height(mut self, min_scrolled_height: f32) -> Self { - self.min_scrolled_height = min_scrolled_height; + self.scroll_options.min_scrolled_height = min_scrolled_height; self } @@ -300,7 +311,7 @@ impl<'a> TableBuilder<'a> { /// In other words: add scroll-bars when this height is reached. /// Default: `800.0`. pub fn max_scroll_height(mut self, max_scroll_height: f32) -> Self { - self.max_scroll_height = max_scroll_height; + self.scroll_options.max_scroll_height = max_scroll_height; self } @@ -326,7 +337,7 @@ impl<'a> TableBuilder<'a> { fn available_width(&self) -> f32 { self.ui.available_rect_before_wrap().width() - - if self.vscroll { + - if self.scroll_options.vscroll { self.ui.spacing().scroll_bar_inner_margin + self.ui.spacing().scroll_bar_width + self.ui.spacing().scroll_bar_outer_margin @@ -345,13 +356,7 @@ impl<'a> TableBuilder<'a> { striped, resizable, cell_layout, - - vscroll, - stick_to_bottom, - scroll_to_row, - scroll_offset_y, - min_scrolled_height, - max_scroll_height, + scroll_options, } = self; let state_id = ui.id().with("__table_state"); @@ -392,13 +397,7 @@ impl<'a> TableBuilder<'a> { resizable, striped, cell_layout, - - vscroll, - stick_to_bottom, - scroll_to_row, - scroll_offset_y, - min_scrolled_height, - max_scroll_height, + scroll_options, } } @@ -415,13 +414,7 @@ impl<'a> TableBuilder<'a> { striped, resizable, cell_layout, - - vscroll, - stick_to_bottom, - scroll_to_row, - scroll_offset_y, - min_scrolled_height, - max_scroll_height, + scroll_options, } = self; let state_id = ui.id().with("__table_state"); @@ -447,13 +440,7 @@ impl<'a> TableBuilder<'a> { resizable, striped, cell_layout, - - vscroll, - stick_to_bottom, - scroll_to_row, - scroll_offset_y, - min_scrolled_height, - max_scroll_height, + scroll_options, } .body(add_body_contents); } @@ -511,13 +498,7 @@ pub struct Table<'a> { striped: bool, cell_layout: egui::Layout, - // Scroll stuff: - vscroll: bool, - stick_to_bottom: bool, - scroll_to_row: Option<(usize, Option)>, - scroll_offset_y: Option, - min_scrolled_height: f32, - max_scroll_height: f32, + scroll_options: TableScrollOptions, } impl<'a> Table<'a> { @@ -536,26 +517,20 @@ impl<'a> Table<'a> { mut state, mut max_used_widths, first_frame_auto_size_columns, - vscroll, striped, cell_layout, - - stick_to_bottom, - scroll_to_row, - scroll_offset_y, - min_scrolled_height, - max_scroll_height, + scroll_options, } = self; let avail_rect = ui.available_rect_before_wrap(); - let mut scroll_area = egui::ScrollArea::new([false, vscroll]) + let mut scroll_area = egui::ScrollArea::new([false, scroll_options.vscroll]) .auto_shrink([true; 2]) - .stick_to_bottom(stick_to_bottom) - .min_scrolled_height(min_scrolled_height) - .max_height(max_scroll_height); + .stick_to_bottom(scroll_options.stick_to_bottom) + .min_scrolled_height(scroll_options.min_scrolled_height) + .max_height(scroll_options.max_scroll_height); - if let Some(scroll_offset_y) = scroll_offset_y { + if let Some(scroll_offset_y) = scroll_options.scroll_offset_y { scroll_area = scroll_area.vertical_scroll_offset(scroll_offset_y); } @@ -579,11 +554,11 @@ impl<'a> Table<'a> { row_nr: 0, start_y: avail_rect.top(), end_y: avail_rect.bottom(), - scroll_to_row: scroll_to_row.map(|(r, _)| r), + scroll_to_row: scroll_options.scroll_to_row.map(|(r, _)| r), scroll_to_y_range: &mut scroll_to_y_range, }); - if scroll_to_row.is_some() && scroll_to_y_range.is_none() { + if scroll_options.scroll_to_row.is_some() && scroll_to_y_range.is_none() { // TableBody::row didn't find the right row, so scroll to the bottom: scroll_to_y_range = Some((f32::INFINITY, f32::INFINITY)); } @@ -592,7 +567,7 @@ impl<'a> Table<'a> { if let Some((min_y, max_y)) = scroll_to_y_range { let x = 0.0; // ignored, we only have vertical scrolling let rect = egui::Rect::from_min_max(egui::pos2(x, min_y), egui::pos2(x, max_y)); - let align = scroll_to_row.and_then(|(_, a)| a); + let align = scroll_options.scroll_to_row.and_then(|(_, a)| a); ui.scroll_to_rect(rect, align); } }); From b77c15c1c76f7ad588a2a4e5450d477d46ae58d0 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 30 Nov 2022 22:49:59 +0100 Subject: [PATCH 8/9] Add Table::auto_size --- crates/egui_extras/CHANGELOG.md | 1 + crates/egui_extras/src/table.rs | 45 ++++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/crates/egui_extras/CHANGELOG.md b/crates/egui_extras/CHANGELOG.md index 804312292c0..56752e8da90 100644 --- a/crates/egui_extras/CHANGELOG.md +++ b/crates/egui_extras/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to the `egui_extras` integration will be noted in this file. * `egui_extras::Strip` now has `clip: false` by default. * Fix bugs when putting `Table` inside of a horizontal `ScrollArea`. * Many other bug fixes. +* Add `Table::auto_shrink` - set to `false` to expand table to fit its containing `Ui` ([#2371](https://github.com/emilk/egui/pull/2371)). ## 0.19.0 - 2022-08-20 diff --git a/crates/egui_extras/src/table.rs b/crates/egui_extras/src/table.rs index 3b28137fb16..505ee269341 100644 --- a/crates/egui_extras/src/table.rs +++ b/crates/egui_extras/src/table.rs @@ -3,7 +3,7 @@ //! | fixed size | all available space/minimum | 30% of available width | fixed size | //! Takes all available height, so if you want something below the table, put it in a strip. -use egui::{Align, NumExt as _, Rect, Response, Ui, Vec2}; +use egui::{Align, NumExt as _, Rect, Response, ScrollArea, Ui, Vec2}; use crate::{ layout::{CellDirection, CellSize}, @@ -162,6 +162,7 @@ struct TableScrollOptions { scroll_offset_y: Option, min_scrolled_height: f32, max_scroll_height: f32, + auto_shrink: [bool; 2], } impl Default for TableScrollOptions { @@ -173,6 +174,7 @@ impl Default for TableScrollOptions { scroll_offset_y: None, min_scrolled_height: 200.0, max_scroll_height: 800.0, + auto_shrink: [true; 2], } } } @@ -315,6 +317,20 @@ impl<'a> TableBuilder<'a> { self } + /// Only when scrolling is enabled. + /// + /// For each axis (x,y): + /// * If true, add blank space outside the table, keeping the table small. + /// * If false, add blank space inside the table, expanding the table to fit the containing ui. + /// + /// Default: `[true; 2]`. + /// + /// See [`ScrollArea::auto_shrink`] for more. + pub fn scroll_auto_shrink(mut self, auto_shrink: [bool; 2]) -> Self { + self.scroll_options.auto_shrink = auto_shrink; + self + } + /// What layout should we use for the individual cells? pub fn cell_layout(mut self, cell_layout: egui::Layout) -> Self { self.cell_layout = cell_layout; @@ -522,15 +538,26 @@ impl<'a> Table<'a> { scroll_options, } = self; + let TableScrollOptions { + vscroll, + stick_to_bottom, + scroll_to_row, + scroll_offset_y, + min_scrolled_height, + max_scroll_height, + auto_shrink, + } = scroll_options; + let avail_rect = ui.available_rect_before_wrap(); - let mut scroll_area = egui::ScrollArea::new([false, scroll_options.vscroll]) + let mut scroll_area = ScrollArea::new([false, vscroll]) .auto_shrink([true; 2]) - .stick_to_bottom(scroll_options.stick_to_bottom) - .min_scrolled_height(scroll_options.min_scrolled_height) - .max_height(scroll_options.max_scroll_height); + .stick_to_bottom(stick_to_bottom) + .min_scrolled_height(min_scrolled_height) + .max_height(max_scroll_height) + .auto_shrink(auto_shrink); - if let Some(scroll_offset_y) = scroll_options.scroll_offset_y { + if let Some(scroll_offset_y) = scroll_offset_y { scroll_area = scroll_area.vertical_scroll_offset(scroll_offset_y); } @@ -554,11 +581,11 @@ impl<'a> Table<'a> { row_nr: 0, start_y: avail_rect.top(), end_y: avail_rect.bottom(), - scroll_to_row: scroll_options.scroll_to_row.map(|(r, _)| r), + scroll_to_row: scroll_to_row.map(|(r, _)| r), scroll_to_y_range: &mut scroll_to_y_range, }); - if scroll_options.scroll_to_row.is_some() && scroll_to_y_range.is_none() { + if scroll_to_row.is_some() && scroll_to_y_range.is_none() { // TableBody::row didn't find the right row, so scroll to the bottom: scroll_to_y_range = Some((f32::INFINITY, f32::INFINITY)); } @@ -567,7 +594,7 @@ impl<'a> Table<'a> { if let Some((min_y, max_y)) = scroll_to_y_range { let x = 0.0; // ignored, we only have vertical scrolling let rect = egui::Rect::from_min_max(egui::pos2(x, min_y), egui::pos2(x, max_y)); - let align = scroll_options.scroll_to_row.and_then(|(_, a)| a); + let align = scroll_to_row.and_then(|(_, a)| a); ui.scroll_to_rect(rect, align); } }); From da6ba10fe9c5d41883ff4b0b6dd4b49e1b99a3f0 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 30 Nov 2022 22:50:56 +0100 Subject: [PATCH 9/9] Rename it auto_shrink --- crates/egui_extras/src/table.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/egui_extras/src/table.rs b/crates/egui_extras/src/table.rs index 505ee269341..aea2a2901ee 100644 --- a/crates/egui_extras/src/table.rs +++ b/crates/egui_extras/src/table.rs @@ -317,8 +317,6 @@ impl<'a> TableBuilder<'a> { self } - /// Only when scrolling is enabled. - /// /// For each axis (x,y): /// * If true, add blank space outside the table, keeping the table small. /// * If false, add blank space inside the table, expanding the table to fit the containing ui. @@ -326,7 +324,7 @@ impl<'a> TableBuilder<'a> { /// Default: `[true; 2]`. /// /// See [`ScrollArea::auto_shrink`] for more. - pub fn scroll_auto_shrink(mut self, auto_shrink: [bool; 2]) -> Self { + pub fn auto_shrink(mut self, auto_shrink: [bool; 2]) -> Self { self.scroll_options.auto_shrink = auto_shrink; self }