Make sure scroll bars are always visible (#2371)
* Nicer debug rectangles * Move scrollbars into the clip-rect so they are always visible * Improve table demo * Add options for controlling inner and outer margin of the scroll bars * Add line to changelog * Update egui_extras changelog with recent Table improvements * Refactor Table:s scroll options * Add Table::auto_size * Rename it auto_shrink
This commit is contained in:
parent
85f8eeb9d5
commit
7133818c59
8 changed files with 147 additions and 92 deletions
|
@ -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)).
|
* 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)).
|
* 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 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` 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
|
## 0.19.0 - 2022-08-20
|
||||||
|
|
|
@ -635,23 +635,7 @@ impl Prepared {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut inner_rect = Rect::from_min_size(inner_rect.min, inner_size);
|
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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let outer_rect = Rect::from_min_size(inner_rect.min, inner_rect.size() + current_bar_use);
|
let outer_rect = Rect::from_min_size(inner_rect.min, inner_rect.size() + current_bar_use);
|
||||||
|
@ -703,13 +687,29 @@ impl Prepared {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// margin between contents and scroll bar
|
// margin on either side of the scroll bar
|
||||||
let margin = animation_t * ui.spacing().item_spacing.x;
|
let inner_margin = animation_t * ui.spacing().scroll_bar_inner_margin;
|
||||||
let min_cross = inner_rect.max[1 - d] + margin; // left of vertical scroll (d == 1)
|
let outer_margin = animation_t * ui.spacing().scroll_bar_outer_margin;
|
||||||
let max_cross = outer_rect.max[1 - d]; // right of vertical scroll (d == 1)
|
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 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)
|
let max_main = inner_rect.max[d]; // bottom of vertical scroll (d == 1)
|
||||||
|
|
||||||
|
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,
|
||||||
|
// 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.
|
||||||
|
// 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] - outer_margin;
|
||||||
|
min_cross = max_cross - width;
|
||||||
|
}
|
||||||
|
|
||||||
let outer_scroll_rect = if d == 0 {
|
let outer_scroll_rect = if d == 0 {
|
||||||
Rect::from_min_max(
|
Rect::from_min_max(
|
||||||
pos2(inner_rect.left(), min_cross),
|
pos2(inner_rect.left(), min_cross),
|
||||||
|
@ -865,5 +865,7 @@ impl Prepared {
|
||||||
|
|
||||||
/// Width of a vertical scrollbar, or height of a horizontal scroll bar
|
/// Width of a vertical scrollbar, or height of a horizontal scroll bar
|
||||||
fn max_scroll_bar_width_with_margin(ui: &Ui) -> f32 {
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,7 +208,12 @@ impl Painter {
|
||||||
impl Painter {
|
impl Painter {
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub fn debug_rect(&self, rect: Rect, color: Color32, text: impl ToString) {
|
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(
|
self.text(
|
||||||
rect.min,
|
rect.min,
|
||||||
Align2::LEFT_TOP,
|
Align2::LEFT_TOP,
|
||||||
|
|
|
@ -292,6 +292,11 @@ pub struct Spacing {
|
||||||
pub combo_height: f32,
|
pub combo_height: f32,
|
||||||
|
|
||||||
pub scroll_bar_width: 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 {
|
impl Spacing {
|
||||||
|
@ -658,6 +663,8 @@ impl Default for Spacing {
|
||||||
tooltip_width: 600.0,
|
tooltip_width: 600.0,
|
||||||
combo_height: 200.0,
|
combo_height: 200.0,
|
||||||
scroll_bar_width: 8.0,
|
scroll_bar_width: 8.0,
|
||||||
|
scroll_bar_inner_margin: 4.0,
|
||||||
|
scroll_bar_outer_margin: 0.0,
|
||||||
indent_ends_with_horizontal_line: false,
|
indent_ends_with_horizontal_line: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -941,6 +948,8 @@ impl Spacing {
|
||||||
indent_ends_with_horizontal_line,
|
indent_ends_with_horizontal_line,
|
||||||
combo_height,
|
combo_height,
|
||||||
scroll_bar_width,
|
scroll_bar_width,
|
||||||
|
scroll_bar_inner_margin,
|
||||||
|
scroll_bar_outer_margin,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
ui.add(slider_vec2(item_spacing, 0.0..=20.0, "Item spacing"));
|
ui.add(slider_vec2(item_spacing, 0.0..=20.0, "Item spacing"));
|
||||||
|
@ -1021,7 +1030,15 @@ impl Spacing {
|
||||||
});
|
});
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.add(DragValue::new(scroll_bar_width).clamp_range(0.0..=32.0));
|
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| {
|
ui.horizontal(|ui| {
|
||||||
|
|
|
@ -7,6 +7,7 @@ enum ScrollDemo {
|
||||||
ManyLines,
|
ManyLines,
|
||||||
LargeCanvas,
|
LargeCanvas,
|
||||||
StickToEnd,
|
StickToEnd,
|
||||||
|
Bidirectional,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ScrollDemo {
|
impl Default for ScrollDemo {
|
||||||
|
@ -55,6 +56,7 @@ impl super::View for Scrolling {
|
||||||
"Scroll a large canvas",
|
"Scroll a large canvas",
|
||||||
);
|
);
|
||||||
ui.selectable_value(&mut self.demo, ScrollDemo::StickToEnd, "Stick to end");
|
ui.selectable_value(&mut self.demo, ScrollDemo::StickToEnd, "Stick to end");
|
||||||
|
ui.selectable_value(&mut self.demo, ScrollDemo::Bidirectional, "Bidirectional");
|
||||||
});
|
});
|
||||||
ui.separator();
|
ui.separator();
|
||||||
match self.demo {
|
match self.demo {
|
||||||
|
@ -70,6 +72,14 @@ impl super::View for Scrolling {
|
||||||
ScrollDemo::StickToEnd => {
|
ScrollDemo::StickToEnd => {
|
||||||
self.scroll_stick_to.ui(ui);
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
impl super::View for TableDemo {
|
||||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
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:
|
// Leave room for the source code link after the table demo:
|
||||||
use egui_extras::{Size, StripBuilder};
|
use egui_extras::{Size, StripBuilder};
|
||||||
StripBuilder::new(ui)
|
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
|
.size(Size::exact(10.0)) // for the source code link
|
||||||
.vertical(|mut strip| {
|
.vertical(|mut strip| {
|
||||||
strip.cell(|ui| {
|
strip.cell(|ui| {
|
||||||
self.table_ui(ui);
|
egui::ScrollArea::horizontal().show(ui, |ui| {
|
||||||
|
self.table_ui(ui);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
strip.cell(|ui| {
|
strip.cell(|ui| {
|
||||||
ui.vertical_centered(|ui| {
|
ui.vertical_centered(|ui| {
|
||||||
|
@ -133,7 +135,8 @@ impl TableDemo {
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
.clip(true),
|
.clip(true),
|
||||||
)
|
)
|
||||||
.column(Column::remainder());
|
.column(Column::remainder())
|
||||||
|
.min_scrolled_height(0.0);
|
||||||
|
|
||||||
if let Some(row_nr) = self.scroll_to_row.take() {
|
if let Some(row_nr) = self.scroll_to_row.take() {
|
||||||
table = table.scroll_to_row(row_nr, None);
|
table = table.scroll_to_row(row_nr, None);
|
||||||
|
|
|
@ -5,6 +5,21 @@ All notable changes to the `egui_extras` integration will be noted in this file.
|
||||||
## Unreleased
|
## 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 `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.
|
* 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.
|
||||||
|
* 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
|
## 0.19.0 - 2022-08-20
|
||||||
* MSRV (Minimum Supported Rust Version) is now `1.61.0` ([#1846](https://github.com/emilk/egui/pull/1846)).
|
* MSRV (Minimum Supported Rust Version) is now `1.61.0` ([#1846](https://github.com/emilk/egui/pull/1846)).
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//! | fixed size | all available space/minimum | 30% of available width | fixed size |
|
//! | 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.
|
//! 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::{
|
use crate::{
|
||||||
layout::{CellDirection, CellSize},
|
layout::{CellDirection, CellSize},
|
||||||
|
@ -155,6 +155,32 @@ fn to_sizing(columns: &[Column]) -> crate::sizing::Sizing {
|
||||||
|
|
||||||
// -----------------------------------------------------------------=----------
|
// -----------------------------------------------------------------=----------
|
||||||
|
|
||||||
|
struct TableScrollOptions {
|
||||||
|
vscroll: bool,
|
||||||
|
stick_to_bottom: bool,
|
||||||
|
scroll_to_row: Option<(usize, Option<Align>)>,
|
||||||
|
scroll_offset_y: Option<f32>,
|
||||||
|
min_scrolled_height: f32,
|
||||||
|
max_scroll_height: f32,
|
||||||
|
auto_shrink: [bool; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
auto_shrink: [true; 2],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------=----------
|
||||||
|
|
||||||
/// Builder for a [`Table`] with (optional) fixed header and scrolling body.
|
/// Builder for a [`Table`] with (optional) fixed header and scrolling body.
|
||||||
///
|
///
|
||||||
/// You must pre-allocate all columns with [`Self::column`]/[`Self::columns`].
|
/// You must pre-allocate all columns with [`Self::column`]/[`Self::columns`].
|
||||||
|
@ -195,14 +221,7 @@ pub struct TableBuilder<'a> {
|
||||||
striped: bool,
|
striped: bool,
|
||||||
resizable: bool,
|
resizable: bool,
|
||||||
cell_layout: egui::Layout,
|
cell_layout: egui::Layout,
|
||||||
|
scroll_options: TableScrollOptions,
|
||||||
// Scroll stuff:
|
|
||||||
vscroll: bool,
|
|
||||||
stick_to_bottom: bool,
|
|
||||||
scroll_to_row: Option<(usize, Option<Align>)>,
|
|
||||||
scroll_offset_y: Option<f32>,
|
|
||||||
min_scrolled_height: f32,
|
|
||||||
max_scroll_height: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TableBuilder<'a> {
|
impl<'a> TableBuilder<'a> {
|
||||||
|
@ -214,13 +233,7 @@ impl<'a> TableBuilder<'a> {
|
||||||
striped: false,
|
striped: false,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
cell_layout,
|
cell_layout,
|
||||||
|
scroll_options: Default::default(),
|
||||||
vscroll: true,
|
|
||||||
stick_to_bottom: false,
|
|
||||||
scroll_to_row: None,
|
|
||||||
scroll_offset_y: None,
|
|
||||||
min_scrolled_height: 200.0,
|
|
||||||
max_scroll_height: 800.0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +260,7 @@ impl<'a> TableBuilder<'a> {
|
||||||
|
|
||||||
/// Enable vertical scrolling in body (default: `true`)
|
/// Enable vertical scrolling in body (default: `true`)
|
||||||
pub fn vscroll(mut self, vscroll: bool) -> Self {
|
pub fn vscroll(mut self, vscroll: bool) -> Self {
|
||||||
self.vscroll = vscroll;
|
self.scroll_options.vscroll = vscroll;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +273,7 @@ impl<'a> TableBuilder<'a> {
|
||||||
/// dynamically? The scroll handle remains stuck until manually changed, and will become stuck
|
/// dynamically? The scroll handle remains stuck until manually changed, and will become stuck
|
||||||
/// once again when repositioned to the bottom. Default: `false`.
|
/// once again when repositioned to the bottom. Default: `false`.
|
||||||
pub fn stick_to_bottom(mut self, stick: bool) -> Self {
|
pub fn stick_to_bottom(mut self, stick: bool) -> Self {
|
||||||
self.stick_to_bottom = stick;
|
self.scroll_options.stick_to_bottom = stick;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +285,7 @@ impl<'a> TableBuilder<'a> {
|
||||||
///
|
///
|
||||||
/// See also: [`Self::vertical_scroll_offset`].
|
/// See also: [`Self::vertical_scroll_offset`].
|
||||||
pub fn scroll_to_row(mut self, row: usize, align: Option<Align>) -> Self {
|
pub fn scroll_to_row(mut self, row: usize, align: Option<Align>) -> Self {
|
||||||
self.scroll_to_row = Some((row, align));
|
self.scroll_options.scroll_to_row = Some((row, align));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +293,7 @@ impl<'a> TableBuilder<'a> {
|
||||||
///
|
///
|
||||||
/// See also: [`Self::scroll_to_row`].
|
/// See also: [`Self::scroll_to_row`].
|
||||||
pub fn vertical_scroll_offset(mut self, offset: f32) -> Self {
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +304,7 @@ impl<'a> TableBuilder<'a> {
|
||||||
///
|
///
|
||||||
/// Default: `200.0`.
|
/// Default: `200.0`.
|
||||||
pub fn min_scrolled_height(mut self, min_scrolled_height: f32) -> Self {
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +313,19 @@ impl<'a> TableBuilder<'a> {
|
||||||
/// In other words: add scroll-bars when this height is reached.
|
/// In other words: add scroll-bars when this height is reached.
|
||||||
/// Default: `800.0`.
|
/// Default: `800.0`.
|
||||||
pub fn max_scroll_height(mut self, max_scroll_height: f32) -> Self {
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 auto_shrink(mut self, auto_shrink: [bool; 2]) -> Self {
|
||||||
|
self.scroll_options.auto_shrink = auto_shrink;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,8 +351,10 @@ impl<'a> TableBuilder<'a> {
|
||||||
|
|
||||||
fn available_width(&self) -> f32 {
|
fn available_width(&self) -> f32 {
|
||||||
self.ui.available_rect_before_wrap().width()
|
self.ui.available_rect_before_wrap().width()
|
||||||
- if self.vscroll {
|
- if self.scroll_options.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 {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
|
@ -343,13 +370,7 @@ impl<'a> TableBuilder<'a> {
|
||||||
striped,
|
striped,
|
||||||
resizable,
|
resizable,
|
||||||
cell_layout,
|
cell_layout,
|
||||||
|
scroll_options,
|
||||||
vscroll,
|
|
||||||
stick_to_bottom,
|
|
||||||
scroll_to_row,
|
|
||||||
scroll_offset_y,
|
|
||||||
min_scrolled_height,
|
|
||||||
max_scroll_height,
|
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
let state_id = ui.id().with("__table_state");
|
let state_id = ui.id().with("__table_state");
|
||||||
|
@ -390,13 +411,7 @@ impl<'a> TableBuilder<'a> {
|
||||||
resizable,
|
resizable,
|
||||||
striped,
|
striped,
|
||||||
cell_layout,
|
cell_layout,
|
||||||
|
scroll_options,
|
||||||
vscroll,
|
|
||||||
stick_to_bottom,
|
|
||||||
scroll_to_row,
|
|
||||||
scroll_offset_y,
|
|
||||||
min_scrolled_height,
|
|
||||||
max_scroll_height,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,13 +428,7 @@ impl<'a> TableBuilder<'a> {
|
||||||
striped,
|
striped,
|
||||||
resizable,
|
resizable,
|
||||||
cell_layout,
|
cell_layout,
|
||||||
|
scroll_options,
|
||||||
vscroll,
|
|
||||||
stick_to_bottom,
|
|
||||||
scroll_to_row,
|
|
||||||
scroll_offset_y,
|
|
||||||
min_scrolled_height,
|
|
||||||
max_scroll_height,
|
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
let state_id = ui.id().with("__table_state");
|
let state_id = ui.id().with("__table_state");
|
||||||
|
@ -445,13 +454,7 @@ impl<'a> TableBuilder<'a> {
|
||||||
resizable,
|
resizable,
|
||||||
striped,
|
striped,
|
||||||
cell_layout,
|
cell_layout,
|
||||||
|
scroll_options,
|
||||||
vscroll,
|
|
||||||
stick_to_bottom,
|
|
||||||
scroll_to_row,
|
|
||||||
scroll_offset_y,
|
|
||||||
min_scrolled_height,
|
|
||||||
max_scroll_height,
|
|
||||||
}
|
}
|
||||||
.body(add_body_contents);
|
.body(add_body_contents);
|
||||||
}
|
}
|
||||||
|
@ -509,13 +512,7 @@ pub struct Table<'a> {
|
||||||
striped: bool,
|
striped: bool,
|
||||||
cell_layout: egui::Layout,
|
cell_layout: egui::Layout,
|
||||||
|
|
||||||
// Scroll stuff:
|
scroll_options: TableScrollOptions,
|
||||||
vscroll: bool,
|
|
||||||
stick_to_bottom: bool,
|
|
||||||
scroll_to_row: Option<(usize, Option<Align>)>,
|
|
||||||
scroll_offset_y: Option<f32>,
|
|
||||||
min_scrolled_height: f32,
|
|
||||||
max_scroll_height: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Table<'a> {
|
impl<'a> Table<'a> {
|
||||||
|
@ -534,24 +531,29 @@ impl<'a> Table<'a> {
|
||||||
mut state,
|
mut state,
|
||||||
mut max_used_widths,
|
mut max_used_widths,
|
||||||
first_frame_auto_size_columns,
|
first_frame_auto_size_columns,
|
||||||
vscroll,
|
|
||||||
striped,
|
striped,
|
||||||
cell_layout,
|
cell_layout,
|
||||||
|
scroll_options,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
let TableScrollOptions {
|
||||||
|
vscroll,
|
||||||
stick_to_bottom,
|
stick_to_bottom,
|
||||||
scroll_to_row,
|
scroll_to_row,
|
||||||
scroll_offset_y,
|
scroll_offset_y,
|
||||||
min_scrolled_height,
|
min_scrolled_height,
|
||||||
max_scroll_height,
|
max_scroll_height,
|
||||||
} = self;
|
auto_shrink,
|
||||||
|
} = scroll_options;
|
||||||
|
|
||||||
let avail_rect = ui.available_rect_before_wrap();
|
let avail_rect = ui.available_rect_before_wrap();
|
||||||
|
|
||||||
let mut scroll_area = egui::ScrollArea::new([false, vscroll])
|
let mut scroll_area = ScrollArea::new([false, vscroll])
|
||||||
.auto_shrink([true; 2])
|
.auto_shrink([true; 2])
|
||||||
.stick_to_bottom(stick_to_bottom)
|
.stick_to_bottom(stick_to_bottom)
|
||||||
.min_scrolled_height(min_scrolled_height)
|
.min_scrolled_height(min_scrolled_height)
|
||||||
.max_height(max_scroll_height);
|
.max_height(max_scroll_height)
|
||||||
|
.auto_shrink(auto_shrink);
|
||||||
|
|
||||||
if let Some(scroll_offset_y) = scroll_offset_y {
|
if let Some(scroll_offset_y) = scroll_offset_y {
|
||||||
scroll_area = scroll_area.vertical_scroll_offset(scroll_offset_y);
|
scroll_area = scroll_area.vertical_scroll_offset(scroll_offset_y);
|
||||||
|
|
Loading…
Reference in a new issue