1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 14:49:06 -04:00

Add ScrollArea::content_margin (#7722)

* Part of https://github.com/emilk/egui/issues/5605
* Part of https://github.com/emilk/egui/issues/3385
This commit is contained in:
Emil Ernerfeldt
2025-11-18 15:30:02 +01:00
committed by GitHub
parent f74b7c7e79
commit 178f3c9198
2 changed files with 52 additions and 3 deletions

View File

@@ -1,8 +1,11 @@
//! See [`ScrollArea`] for docs.
#![allow(clippy::needless_range_loop)]
use std::ops::{Add, AddAssign, BitOr, BitOrAssign};
use emath::GuiRounding as _;
use epaint::Margin;
use crate::{
Context, CursorIcon, Id, NumExt as _, Pos2, Rangef, Rect, Response, Sense, Ui, UiBuilder,
@@ -258,7 +261,7 @@ impl AddAssign for ScrollSource {
/// ### Coordinate system
/// * content: size of contents (generally large; that's why we want scroll bars)
/// * outer: size of scroll area including scroll bar(s)
/// * inner: excluding scroll bar(s). The area we clip the contents to.
/// * inner: excluding scroll bar(s). The area we clip the contents to. Includes `content_margin`.
///
/// If the floating scroll bars settings is turned on then `inner == outer`.
///
@@ -294,6 +297,8 @@ pub struct ScrollArea {
scroll_source: ScrollSource,
wheel_scroll_multiplier: Vec2,
content_margin: Option<Margin>,
/// If true for vertical or horizontal the scroll wheel will stick to the
/// end position until user manually changes position. It will become true
/// again once scroll handle makes contact with end.
@@ -346,6 +351,7 @@ impl ScrollArea {
on_drag_cursor: None,
scroll_source: ScrollSource::default(),
wheel_scroll_multiplier: Vec2::splat(1.0),
content_margin: None,
stick_to_end: Vec2b::FALSE,
animated: true,
}
@@ -593,6 +599,18 @@ impl ScrollArea {
self.direction_enabled[0] || self.direction_enabled[1]
}
/// Extra margin added around the contents.
///
/// The scroll bars will be either on top of this margin, or outside of it,
/// depending on the value of [`crate::style::ScrollStyle::floating`].
///
/// Default: [`crate::style::ScrollStyle::content_margin`].
#[inline]
pub fn content_margin(mut self, margin: impl Into<Margin>) -> Self {
self.content_margin = Some(margin.into());
self
}
/// The scroll handle will stick to the rightmost position even while the content size
/// changes dynamically. This can be useful to simulate text scrollers coming in from right
/// hand side. The scroll handle remains stuck until user manually changes position. Once "unstuck"
@@ -644,7 +662,7 @@ struct Prepared {
scroll_bar_visibility: ScrollBarVisibility,
scroll_bar_rect: Option<Rect>,
/// Where on the screen the content is (excludes scroll bars).
/// Where on the screen the content is (excludes scroll bars; includes `content_margin`).
inner_rect: Rect,
content_ui: Ui,
@@ -683,6 +701,7 @@ impl ScrollArea {
on_drag_cursor,
scroll_source,
wheel_scroll_multiplier,
content_margin: _, // Used elsewhere
stick_to_end,
animated,
} = self;
@@ -983,10 +1002,21 @@ impl ScrollArea {
ui: &mut Ui,
add_contents: Box<dyn FnOnce(&mut Ui, Rect) -> R + 'c>,
) -> ScrollAreaOutput<R> {
let margin = self
.content_margin
.unwrap_or_else(|| ui.spacing().scroll.content_margin);
let mut prepared = self.begin(ui);
let id = prepared.id;
let inner_rect = prepared.inner_rect;
let inner = add_contents(&mut prepared.content_ui, prepared.viewport);
let inner = crate::Frame::NONE
.inner_margin(margin)
.show(&mut prepared.content_ui, |ui| {
add_contents(ui, prepared.viewport)
})
.inner;
let (content_size, state) = prepared.end(ui);
ScrollAreaOutput {
inner,

View File

@@ -508,6 +508,12 @@ pub struct ScrollStyle {
/// it more promiment.
pub floating: bool,
/// Extra margin added around the contents of a [`crate::ScrollArea`].
///
/// The scroll bars will be either on top of this margin, or outside of it,
/// depending on the value of [`Self::floating`].
pub content_margin: Margin,
/// The width of the scroll bars at it largest.
pub bar_width: f32,
@@ -591,6 +597,7 @@ impl ScrollStyle {
pub fn solid() -> Self {
Self {
floating: false,
content_margin: Margin::ZERO,
bar_width: 6.0,
handle_min_length: 12.0,
bar_inner_margin: 4.0,
@@ -672,6 +679,9 @@ impl ScrollStyle {
pub fn details_ui(&mut self, ui: &mut Ui) {
let Self {
floating,
content_margin,
bar_width,
handle_min_length,
bar_inner_margin,
@@ -695,6 +705,11 @@ impl ScrollStyle {
ui.selectable_value(floating, true, "Floating");
});
ui.horizontal(|ui| {
ui.label("Content margin:");
content_margin.ui(ui);
});
ui.horizontal(|ui| {
ui.add(DragValue::new(bar_width).range(0.0..=32.0));
ui.label("Full bar width");
@@ -1824,6 +1839,10 @@ impl Spacing {
ui.add(window_margin);
ui.end_row();
ui.label("ScrollArea margin");
scroll.content_margin.ui(ui);
ui.end_row();
ui.label("Menu margin");
ui.add(menu_margin);
ui.end_row();