Skip to content

Commit 56bb200

Browse files
committed
Return more info from ScrollArea::show
1 parent 26be0ac commit 56bb200

File tree

6 files changed

+72
-34
lines changed

6 files changed

+72
-34
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w
3333
* Replaced `Style::body_text_style` with more generic `Style::text_styles` ([#1154](https://github.com/emilk/egui/pull/1154)).
3434
* `TextStyle` is no longer `Copy` ([#1154](https://github.com/emilk/egui/pull/1154)).
3535
* Replaced `TextEdit::text_style` with `TextEdit::font` ([#1154](https://github.com/emilk/egui/pull/1154)).
36-
* `Plot::highlight` now takes a `bool` argument ([#1159](https://github.com/emilk/egui/pull/1159)),
36+
* `Plot::highlight` now takes a `bool` argument ([#1159](https://github.com/emilk/egui/pull/1159)).
37+
* `ScrollArea::show` now returns a `ScrollAreaOutput`, so you might need to add `.inner` after the call to it ([#1166](https://github.com/emilk/egui/pull/1166)).
3738

3839
### Fixed 🐛
3940
* Context menu now respects the theme ([#1043](https://github.com/emilk/egui/pull/1043))

egui/src/containers/combo_box.rs

+1
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ fn combo_box_dyn<'c, R>(
196196
ScrollArea::vertical()
197197
.max_height(ui.spacing().combo_height)
198198
.show(ui, menu_contents)
199+
.inner
199200
});
200201

201202
InnerResponse {

egui/src/containers/scroll_area.rs

+42-10
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ use crate::*;
1010
#[derive(Clone, Copy, Debug)]
1111
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
1212
#[cfg_attr(feature = "serde", serde(default))]
13-
pub(crate) struct State {
13+
pub struct State {
1414
/// Positive offset means scrolling down/right
15-
offset: Vec2,
15+
pub offset: Vec2,
1616

1717
show_scroll: [bool; 2],
1818

@@ -51,6 +51,20 @@ impl State {
5151
}
5252
}
5353

54+
pub struct ScrollAreaOutput<R> {
55+
/// What the user closure returned.
56+
pub inner: R,
57+
58+
/// `Id` of the `ScrollArea`.
59+
pub id: Id,
60+
61+
/// The current state of the scroll area.
62+
pub state: State,
63+
64+
/// Where on the screen the content is (excludes scroll bars).
65+
pub inner_rect: Rect,
66+
}
67+
5468
/// Add vertical and/or horizontal scrolling to a contained [`Ui`].
5569
///
5670
/// ```
@@ -258,6 +272,7 @@ struct Prepared {
258272
/// width of the vertical bar, and the height of the horizontal bar?
259273
current_bar_use: Vec2,
260274
always_show_scroll: bool,
275+
/// Where on the screen the content is (excludes scroll bars).
261276
inner_rect: Rect,
262277
content_ui: Ui,
263278
/// Relative coordinates: the offset and size of the view of the inner UI.
@@ -365,7 +380,11 @@ impl ScrollArea {
365380
/// Show the `ScrollArea`, and add the contents to the viewport.
366381
///
367382
/// If the inner area can be very long, consider using [`Self::show_rows`] instead.
368-
pub fn show<R>(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> R {
383+
pub fn show<R>(
384+
self,
385+
ui: &mut Ui,
386+
add_contents: impl FnOnce(&mut Ui) -> R,
387+
) -> ScrollAreaOutput<R> {
369388
self.show_viewport_dyn(ui, Box::new(|ui, _viewport| add_contents(ui)))
370389
}
371390

@@ -391,7 +410,7 @@ impl ScrollArea {
391410
row_height_sans_spacing: f32,
392411
total_rows: usize,
393412
add_contents: impl FnOnce(&mut Ui, std::ops::Range<usize>) -> R,
394-
) -> R {
413+
) -> ScrollAreaOutput<R> {
395414
let spacing = ui.spacing().item_spacing;
396415
let row_height_with_spacing = row_height_sans_spacing + spacing.y;
397416
self.show_viewport(ui, |ui, viewport| {
@@ -420,24 +439,35 @@ impl ScrollArea {
420439
///
421440
/// `add_contents` is past the viewport, which is the relative view of the content.
422441
/// So if the passed rect has min = zero, then show the top left content (the user has not scrolled).
423-
pub fn show_viewport<R>(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui, Rect) -> R) -> R {
442+
pub fn show_viewport<R>(
443+
self,
444+
ui: &mut Ui,
445+
add_contents: impl FnOnce(&mut Ui, Rect) -> R,
446+
) -> ScrollAreaOutput<R> {
424447
self.show_viewport_dyn(ui, Box::new(add_contents))
425448
}
426449

427450
fn show_viewport_dyn<'c, R>(
428451
self,
429452
ui: &mut Ui,
430453
add_contents: Box<dyn FnOnce(&mut Ui, Rect) -> R + 'c>,
431-
) -> R {
454+
) -> ScrollAreaOutput<R> {
432455
let mut prepared = self.begin(ui);
433-
let ret = add_contents(&mut prepared.content_ui, prepared.viewport);
434-
prepared.end(ui);
435-
ret
456+
let id = prepared.id;
457+
let inner_rect = prepared.inner_rect;
458+
let inner = add_contents(&mut prepared.content_ui, prepared.viewport);
459+
let state = prepared.end(ui);
460+
ScrollAreaOutput {
461+
inner,
462+
id,
463+
state,
464+
inner_rect,
465+
}
436466
}
437467
}
438468

439469
impl Prepared {
440-
fn end(self, ui: &mut Ui) {
470+
fn end(self, ui: &mut Ui) -> State {
441471
let Prepared {
442472
id,
443473
mut state,
@@ -747,6 +777,8 @@ impl Prepared {
747777
state.show_scroll = show_scroll_this_frame;
748778

749779
state.store(ui.ctx(), id);
780+
781+
state
750782
}
751783
}
752784

egui/src/containers/window.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ impl<'open> Window<'open> {
354354
}
355355

356356
if scroll.has_any_bar() {
357-
scroll.show(ui, add_contents)
357+
scroll.show(ui, add_contents).inner
358358
} else {
359359
add_contents(ui)
360360
}

egui/src/response.rs

+2
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,9 @@ impl std::ops::BitOrAssign for Response {
586586
/// ```
587587
#[derive(Debug)]
588588
pub struct InnerResponse<R> {
589+
/// What the user closure returned.
589590
pub inner: R,
591+
/// The response of the area.
590592
pub response: Response,
591593
}
592594

egui_demo_lib/src/apps/demo/scrolling.rs

+24-22
Original file line numberDiff line numberDiff line change
@@ -210,32 +210,34 @@ impl super::View for ScrollTo {
210210
}
211211

212212
ui.separator();
213-
let (current_scroll, max_scroll) = scroll_area.show(ui, |ui| {
214-
if scroll_top {
215-
ui.scroll_to_cursor(Align::TOP);
216-
}
217-
ui.vertical(|ui| {
218-
for item in 1..=50 {
219-
if track_item && item == self.track_item {
220-
let response =
221-
ui.colored_label(Color32::YELLOW, format!("This is item {}", item));
222-
response.scroll_to_me(self.tack_item_align);
223-
} else {
224-
ui.label(format!("This is item {}", item));
225-
}
213+
let (current_scroll, max_scroll) = scroll_area
214+
.show(ui, |ui| {
215+
if scroll_top {
216+
ui.scroll_to_cursor(Align::TOP);
226217
}
227-
});
218+
ui.vertical(|ui| {
219+
for item in 1..=50 {
220+
if track_item && item == self.track_item {
221+
let response =
222+
ui.colored_label(Color32::YELLOW, format!("This is item {}", item));
223+
response.scroll_to_me(self.tack_item_align);
224+
} else {
225+
ui.label(format!("This is item {}", item));
226+
}
227+
}
228+
});
228229

229-
if scroll_bottom {
230-
ui.scroll_to_cursor(Align::BOTTOM);
231-
}
230+
if scroll_bottom {
231+
ui.scroll_to_cursor(Align::BOTTOM);
232+
}
232233

233-
let margin = ui.visuals().clip_rect_margin;
234+
let margin = ui.visuals().clip_rect_margin;
234235

235-
let current_scroll = ui.clip_rect().top() - ui.min_rect().top() + margin;
236-
let max_scroll = ui.min_rect().height() - ui.clip_rect().height() + 2.0 * margin;
237-
(current_scroll, max_scroll)
238-
});
236+
let current_scroll = ui.clip_rect().top() - ui.min_rect().top() + margin;
237+
let max_scroll = ui.min_rect().height() - ui.clip_rect().height() + 2.0 * margin;
238+
(current_scroll, max_scroll)
239+
})
240+
.inner;
239241
ui.separator();
240242

241243
ui.label(format!(

0 commit comments

Comments
 (0)