From f05a8d5458522c4468116cdf5909ab370e8f6005 Mon Sep 17 00:00:00 2001 From: rustbasic <127506429+rustbasic@users.noreply.github.com> Date: Sat, 29 Jun 2024 11:38:24 +0900 Subject: [PATCH] Update scroll_area.rs --- crates/egui/src/containers/scroll_area.rs | 65 +++++++++++------------ 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/crates/egui/src/containers/scroll_area.rs b/crates/egui/src/containers/scroll_area.rs index 536b3c33a94..da7004ba06f 100644 --- a/crates/egui/src/containers/scroll_area.rs +++ b/crates/egui/src/containers/scroll_area.rs @@ -793,14 +793,7 @@ impl Prepared { let content_size = content_ui.min_size(); - let scroll_delta = content_ui - .ctx() - .frame_state_mut(|state| std::mem::take(&mut state.scroll_delta)); - for d in 0..2 { - // FrameState::scroll_delta is inverted from the way we apply the delta, so we need to negate it. - let mut delta = -scroll_delta[d]; - // We always take both scroll targets regardless of which scroll axes are enabled. This // is to avoid them leaking to other scroll areas. let scroll_target = content_ui @@ -808,6 +801,13 @@ impl Prepared { .frame_state_mut(|state| state.scroll_target[d].take()); if scroll_enabled[d] { + let scroll_delta = content_ui + .ctx() + .frame_state_mut(|state| std::mem::take(&mut state.scroll_delta[d])); + + // FrameState::scroll_delta is inverted from the way we apply the delta, so we need to negate it. + let mut delta = -scroll_delta; + delta += if let Some((target_range, align)) = scroll_target { let min = content_ui.min_rect().min[d]; let clip_rect = content_ui.clip_rect(); @@ -963,16 +963,30 @@ impl Prepared { let inner_margin = show_factor * scroll_style.bar_inner_margin; let outer_margin = show_factor * scroll_style.bar_outer_margin; + let mut max_cross = outer_rect.max[1 - d] - outer_margin; + 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. + max_cross = ui.clip_rect().max[1 - d] - outer_margin; + } + // top/bottom of a horizontal scroll (d==0). // left/rigth of a vertical scroll (d==1). - let mut cross = if scroll_style.floating { + let cross = if scroll_style.floating { let max_bar_rect = if d == 0 { - outer_rect.with_min_y(outer_rect.max.y - scroll_style.allocated_width()) + outer_rect.with_min_y(max_cross - scroll_style.bar_width) } else { - outer_rect.with_min_x(outer_rect.max.x - scroll_style.allocated_width()) + outer_rect.with_min_x(max_cross - scroll_style.bar_width) }; - let is_hovering_bar_area = is_hovering_outer_rect - && ui.rect_contains_pointer(max_bar_rect) + let is_hovering_bar_area = (is_hovering_outer_rect + && ui.rect_contains_pointer(max_bar_rect)) || state.scroll_bar_interaction[d]; let is_hovering_bar_area_t = ui .ctx() @@ -983,39 +997,22 @@ impl Prepared { is_hovering_bar_area_t, ); - let max_cross = outer_rect.max[1 - d] - outer_margin; let min_cross = max_cross - width; Rangef::new(min_cross, max_cross) } else { - let min_cross = inner_rect.max[1 - d] + inner_margin; - let max_cross = outer_rect.max[1 - d] - outer_margin; + let min_cross = max_cross - scroll_style.bar_width; Rangef::new(min_cross, max_cross) }; - if ui.clip_rect().max[1 - d] < cross.max + 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 = cross.max - cross.min; - cross.max = ui.clip_rect().max[1 - d] - outer_margin; - cross.min = cross.max - width; - } - let outer_scroll_rect = if d == 0 { Rect::from_min_max( - pos2(inner_rect.left(), cross.min), - pos2(inner_rect.right(), cross.max), + pos2(inner_rect.left(), cross.min - inner_margin), + pos2(inner_rect.right(), cross.max + outer_margin), ) } else { Rect::from_min_max( - pos2(cross.min, inner_rect.top()), - pos2(cross.max, inner_rect.bottom()), + pos2(cross.min - inner_margin, inner_rect.top()), + pos2(cross.max + outer_margin, inner_rect.bottom()), ) };