mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 04:40:03 -04:00
Add atom_ignore_spacing
This commit is contained in:
@@ -46,6 +46,9 @@ pub struct Atom<'a> {
|
||||
/// See [`crate::AtomExt::atom_align`]
|
||||
pub align: Align2,
|
||||
|
||||
/// See [`crate::AtomExt::atom_ignore_spacing`]
|
||||
pub ignore_spacing: bool,
|
||||
|
||||
/// The atom type / content
|
||||
pub kind: AtomKind<'a>,
|
||||
}
|
||||
@@ -58,6 +61,7 @@ impl Default for Atom<'_> {
|
||||
max_size: Vec2::INFINITY,
|
||||
grow: false,
|
||||
shrink: false,
|
||||
ignore_spacing: false,
|
||||
align: Align2::CENTER_CENTER,
|
||||
kind: AtomKind::Empty,
|
||||
}
|
||||
@@ -72,6 +76,7 @@ impl<'a> Atom<'a> {
|
||||
pub fn grow() -> Self {
|
||||
Atom {
|
||||
grow: true,
|
||||
ignore_spacing: true,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
@@ -144,6 +149,7 @@ impl<'a> Atom<'a> {
|
||||
size,
|
||||
intrinsic_size: intrinsic_size.at_least(self.size.unwrap_or_default()),
|
||||
grow: self.grow,
|
||||
ignore_spacing: self.ignore_spacing,
|
||||
align: self.align,
|
||||
kind: sized,
|
||||
}
|
||||
|
||||
@@ -70,6 +70,12 @@ pub trait AtomExt<'a> {
|
||||
self.atom_max_height(height)
|
||||
}
|
||||
|
||||
/// If `true`, this atom will not contribute to inter-atom gap spacing.
|
||||
///
|
||||
/// This is useful for invisible spacers like [`Atom::grow()`] where you want
|
||||
/// the grow space to replace the gaps rather than adding to them.
|
||||
fn atom_ignore_spacing(self, ignore_spacing: bool) -> Atom<'a>;
|
||||
|
||||
/// Sets the [`emath::Align2`] of a single atom within its available space.
|
||||
///
|
||||
/// Defaults to center-center.
|
||||
@@ -122,6 +128,12 @@ where
|
||||
atom
|
||||
}
|
||||
|
||||
fn atom_ignore_spacing(self, ignore_spacing: bool) -> Atom<'a> {
|
||||
let mut atom = self.into();
|
||||
atom.ignore_spacing = ignore_spacing;
|
||||
atom
|
||||
}
|
||||
|
||||
fn atom_align(self, align: emath::Align2) -> Atom<'a> {
|
||||
let mut atom = self.into();
|
||||
atom.align = align;
|
||||
|
||||
@@ -10,6 +10,33 @@ use smallvec::SmallVec;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Compute the effective gap between atom `i` and atom `i+1`.
|
||||
///
|
||||
/// Each atom with `ignore_spacing` has a "budget" of 1 full gap to remove,
|
||||
/// distributed across its adjacent gaps:
|
||||
/// - Edge atom (first or last): 1 adjacent gap → fully removed
|
||||
/// - Middle atom: 2 adjacent gaps → each reduced by 0.5×
|
||||
fn gap_between(
|
||||
ignore_spacing: impl Fn(usize) -> bool,
|
||||
count: usize,
|
||||
gap: f32,
|
||||
i: usize,
|
||||
) -> f32 {
|
||||
debug_assert!(i + 1 < count);
|
||||
let mut reduction = 0.0_f32;
|
||||
if ignore_spacing(i) {
|
||||
reduction += if i == 0 || i == count - 1 { 1.0 } else { 0.5 };
|
||||
}
|
||||
if ignore_spacing(i + 1) {
|
||||
reduction += if i + 1 == 0 || i + 1 == count - 1 {
|
||||
1.0
|
||||
} else {
|
||||
0.5
|
||||
};
|
||||
}
|
||||
gap * (1.0 - reduction).max(0.0)
|
||||
}
|
||||
|
||||
/// Intra-widget layout utility.
|
||||
///
|
||||
/// Used to lay out and paint [`crate::Atom`]s.
|
||||
@@ -250,8 +277,22 @@ impl<'a> AtomLayout<'a> {
|
||||
Align2([ui.layout().horizontal_align(), ui.layout().vertical_align()])
|
||||
});
|
||||
|
||||
// Collect ignore_spacing flags before atoms are consumed by into_sized.
|
||||
let ignore_spacing_flags: SmallVec<[bool; ATOMS_SMALL_VEC_SIZE]> =
|
||||
atoms.iter().map(|a| a.ignore_spacing).collect();
|
||||
|
||||
if atoms.len() > 1 {
|
||||
let gap_space = gap * (atoms.len() as f32 - 1.0);
|
||||
let atom_count = atoms.len();
|
||||
let gap_space: f32 = (0..atom_count - 1)
|
||||
.map(|i| {
|
||||
gap_between(
|
||||
|idx| ignore_spacing_flags[idx],
|
||||
atom_count,
|
||||
gap,
|
||||
i,
|
||||
)
|
||||
})
|
||||
.sum();
|
||||
desired_width += gap_space;
|
||||
intrinsic_width += gap_space;
|
||||
}
|
||||
@@ -454,7 +495,10 @@ impl<'atom> AllocatedAtomLayout<'atom> {
|
||||
|
||||
let mut response = AtomLayoutResponse::empty(response);
|
||||
|
||||
for sized in sized_atoms {
|
||||
let atom_count = sized_atoms.len();
|
||||
let ignore_flags: SmallVec<[bool; ATOMS_SMALL_VEC_SIZE]> =
|
||||
sized_atoms.iter().map(|a| a.ignore_spacing()).collect();
|
||||
for (i, sized) in sized_atoms.into_iter().enumerate() {
|
||||
let size = sized.size;
|
||||
// TODO(lucasmerlin): This is not ideal, since this might lead to accumulated rounding errors
|
||||
// https://github.com/emilk/egui/pull/5830#discussion_r2079627864
|
||||
@@ -463,7 +507,12 @@ impl<'atom> AllocatedAtomLayout<'atom> {
|
||||
let frame = aligned_rect
|
||||
.with_min_x(cursor)
|
||||
.with_max_x(cursor + size.x + growth);
|
||||
cursor = frame.right() + gap;
|
||||
let effective_gap = if i + 1 < atom_count {
|
||||
gap_between(|idx| ignore_flags[idx], atom_count, gap, i)
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
cursor = frame.right() + effective_gap;
|
||||
let rect = sized.align.align_size_within_rect(size, frame);
|
||||
|
||||
if let Some(id) = sized.id {
|
||||
|
||||
@@ -8,6 +8,8 @@ pub struct SizedAtom<'a> {
|
||||
|
||||
pub(crate) grow: bool,
|
||||
|
||||
pub(crate) ignore_spacing: bool,
|
||||
|
||||
/// The size of the atom.
|
||||
///
|
||||
/// Used for placing this atom in [`crate::AtomLayout`], the cursor will advance by
|
||||
@@ -28,4 +30,9 @@ impl SizedAtom<'_> {
|
||||
pub fn is_grow(&self) -> bool {
|
||||
self.grow
|
||||
}
|
||||
|
||||
/// Was this [`crate::Atom`] marked as `ignore_spacing`?
|
||||
pub fn ignore_spacing(&self) -> bool {
|
||||
self.ignore_spacing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cbf68b6934dae0868bc9cf0891baf5acf110284d297cfa348e756237fca64a28
|
||||
size 1564
|
||||
oid sha256:b0b36160eff3335d10951d83cb20053bb15ff4b6fab68580710b509cd112b668
|
||||
size 1563
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:231ceab75a602eedcd11f4f4ed34f38fb9d072f5cb54e135a7e02d33d257f86b
|
||||
size 433973
|
||||
oid sha256:82f4334e848e762aa28a29904b569ca2af12b38f308434bdf5968f607fc2be0a
|
||||
size 433829
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cf00e99dbfdf7497688955feb8c417fab0a366588d92182eccee775abade5179
|
||||
size 361876
|
||||
oid sha256:2d018426f3014e79475d8d8f46a728632d7f15f2bfbf55b0ee648a56c792495c
|
||||
size 370212
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e298d89e6fb434e5010d96661fca40bf119118b6b31fdd9fc13201bcd74c8ffd
|
||||
size 15149
|
||||
oid sha256:99f33211696d454e1fdbfa39e94af4c09239a38e00a3c4ef22e36adfbb2ee3c4
|
||||
size 15073
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a0581d601f1e536298cb52bfc8a167aa37aebdf065fc910973a752c9c159223d
|
||||
size 14733
|
||||
oid sha256:6a4d8b64c9705e13e610a404b3eca780ecd26d7d10dba1c54207c6930018d06b
|
||||
size 14659
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:337dcbf0b3a344c6cadaf9500376a627739e19e9c47b5da23786c98c612ef4dc
|
||||
size 10028
|
||||
oid sha256:d47e3584a09ea9b024dd36293acac5d97a1784eb87a469c2aec4b1db455b4e45
|
||||
size 10514
|
||||
|
||||
Reference in New Issue
Block a user