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:
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user