auto-shrink ScrollArea to content size
Unless the user disables it with `ScollArea::auto_shrink([false; 2])`.
This commit is contained in:
parent
a1bf5aff47
commit
ce8d863249
3 changed files with 60 additions and 50 deletions
|
@ -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`.
|
* 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`.
|
* By default, `DragValue`:s no longer show a tooltip when hovered. Change with `Style::explanation_tooltips`.
|
||||||
* Smaller and nicer color picker.
|
* Smaller and nicer color picker.
|
||||||
|
* `ScrollArea` will auto-shrink to content size unless told otherwise using `ScollArea::auto_shrink`.
|
||||||
|
|
||||||
### Fixed 🐛
|
### Fixed 🐛
|
||||||
* Fix wrongly sized multiline `TextEdit` in justified layouts.
|
* Fix wrongly sized multiline `TextEdit` in justified layouts.
|
||||||
|
|
|
@ -341,14 +341,14 @@ impl ScrollArea {
|
||||||
|
|
||||||
let y_min = ui.max_rect().top() + min_row as f32 * row_height_with_spacing;
|
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 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(),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
let rect = Rect::from_x_y_ranges(ui.max_rect().x_range(), y_min..=y_max);
|
||||||
|
|
||||||
|
ui.allocate_ui_at_rect(rect, |viewport_ui| {
|
||||||
viewport_ui.skip_ahead_auto_ids(min_row); // Make sure we get consistent IDs.
|
viewport_ui.skip_ahead_auto_ids(min_row); // Make sure we get consistent IDs.
|
||||||
|
add_contents(viewport_ui, min_row..max_row)
|
||||||
add_contents(&mut viewport_ui, min_row..max_row)
|
})
|
||||||
|
.inner
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,10 +389,9 @@ impl Prepared {
|
||||||
|
|
||||||
let content_size = content_ui.min_size();
|
let content_size = content_ui.min_size();
|
||||||
|
|
||||||
// We take the scroll target so only this ScrollArea will use it.
|
|
||||||
|
|
||||||
for d in 0..2 {
|
for d in 0..2 {
|
||||||
if has_bar[d] {
|
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();
|
let scroll_target = content_ui.ctx().frame_state().scroll_target[d].take();
|
||||||
if let Some((scroll, align)) = scroll_target {
|
if let Some((scroll, align)) = scroll_target {
|
||||||
let center_factor = align.to_factor();
|
let center_factor = align.to_factor();
|
||||||
|
@ -412,19 +411,15 @@ impl Prepared {
|
||||||
}
|
}
|
||||||
|
|
||||||
let inner_rect = {
|
let inner_rect = {
|
||||||
|
// At this point this is the available size for the inner rect.
|
||||||
let mut inner_size = inner_rect.size();
|
let mut inner_size = inner_rect.size();
|
||||||
|
|
||||||
for d in 0..2 {
|
for d in 0..2 {
|
||||||
inner_size[d] = if has_bar[d] {
|
inner_size[d] = match (has_bar[d], auto_shrink[d]) {
|
||||||
if auto_shrink[d] {
|
(true, true) => inner_size[d].min(content_size[d]), // shrink scroll area if content is small
|
||||||
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
|
||||||
} else {
|
(false, true) => content_size[d], // Follow the content (expand/contract to fit it).
|
||||||
inner_size[d] // let scroll area be larger than content; fill with blank space
|
(false, false) => inner_size[d].max(content_size[d]), // Expand to fit content
|
||||||
}
|
|
||||||
} 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
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ impl super::Demo for Scrolling {
|
||||||
.open(open)
|
.open(open)
|
||||||
.resizable(false)
|
.resizable(false)
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
use super::View;
|
use super::View as _;
|
||||||
self.ui(ui);
|
self.ui(ui);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -77,12 +77,17 @@ fn huge_content_lines(ui: &mut egui::Ui) {
|
||||||
let text_style = TextStyle::Body;
|
let text_style = TextStyle::Body;
|
||||||
let row_height = ui.fonts()[text_style].row_height();
|
let row_height = ui.fonts()[text_style].row_height();
|
||||||
let num_rows = 10_000;
|
let num_rows = 10_000;
|
||||||
ScrollArea::vertical().show_rows(ui, row_height, num_rows, |ui, row_range| {
|
ScrollArea::vertical().auto_shrink([false; 2]).show_rows(
|
||||||
|
ui,
|
||||||
|
row_height,
|
||||||
|
num_rows,
|
||||||
|
|ui, row_range| {
|
||||||
for row in row_range {
|
for row in row_range {
|
||||||
let text = format!("This is row {}/{}", row + 1, num_rows);
|
let text = format!("This is row {}/{}", row + 1, num_rows);
|
||||||
ui.label(text);
|
ui.label(text);
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn huge_content_painter(ui: &mut egui::Ui) {
|
fn huge_content_painter(ui: &mut egui::Ui) {
|
||||||
|
@ -94,13 +99,17 @@ fn huge_content_painter(ui: &mut egui::Ui) {
|
||||||
let row_height = ui.fonts()[text_style].row_height() + ui.spacing().item_spacing.y;
|
let row_height = ui.fonts()[text_style].row_height() + ui.spacing().item_spacing.y;
|
||||||
let num_rows = 10_000;
|
let num_rows = 10_000;
|
||||||
|
|
||||||
ScrollArea::vertical().show_viewport(ui, |ui, viewport| {
|
ScrollArea::vertical()
|
||||||
|
.auto_shrink([false; 2])
|
||||||
|
.show_viewport(ui, |ui, viewport| {
|
||||||
ui.set_height(row_height * num_rows as f32);
|
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 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 = (viewport.max.y / row_height).ceil() as usize + 1;
|
||||||
let last_item = last_item.at_most(num_rows);
|
let last_item = last_item.at_most(num_rows);
|
||||||
|
|
||||||
|
let mut used_rect = Rect::NOTHING;
|
||||||
|
|
||||||
for i in first_item..last_item {
|
for i in first_item..last_item {
|
||||||
let indentation = (i % 100) as f32;
|
let indentation = (i % 100) as f32;
|
||||||
let x = ui.min_rect().left() + indentation;
|
let x = ui.min_rect().left() + indentation;
|
||||||
|
@ -111,14 +120,17 @@ fn huge_content_painter(ui: &mut egui::Ui) {
|
||||||
num_rows,
|
num_rows,
|
||||||
indentation
|
indentation
|
||||||
);
|
);
|
||||||
ui.painter().text(
|
let text_rect = ui.painter().text(
|
||||||
pos2(x, y),
|
pos2(x, y),
|
||||||
Align2::LEFT_TOP,
|
Align2::LEFT_TOP,
|
||||||
text,
|
text,
|
||||||
text_style,
|
text_style,
|
||||||
ui.visuals().text_color(),
|
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();
|
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 {
|
if go_to_scroll_offset {
|
||||||
scroll_area = scroll_area.scroll_offset(self.offset);
|
scroll_area = scroll_area.scroll_offset(self.offset);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue