mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 14:49:06 -04:00
Deduplicate shared builder fns
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use crate::{
|
||||
AtomKind, Atoms, FontSelection, Frame, Id, Image, IntoAtoms, SizedAtom, SizedAtomKind, Ui,
|
||||
WidgetAtom,
|
||||
};
|
||||
use emath::{Align2, GuiRounding as _, NumExt as _, Rect, Vec2};
|
||||
use epaint::text::TextWrapMode;
|
||||
@@ -64,99 +65,6 @@ impl<'a> ContainerAtom<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the gap between atoms.
|
||||
///
|
||||
/// Default: `Spacing::icon_spacing`
|
||||
#[inline]
|
||||
pub fn gap(mut self, gap: f32) -> Self {
|
||||
self.gap = Some(gap);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the [`Frame`].
|
||||
#[inline]
|
||||
pub fn frame(mut self, frame: Frame) -> Self {
|
||||
self.frame = frame;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the fallback (default) text color.
|
||||
///
|
||||
/// Default: [`crate::Visuals::text_color`]
|
||||
#[inline]
|
||||
pub fn fallback_text_color(mut self, color: Color32) -> Self {
|
||||
self.fallback_text_color = Some(color);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the fallback (default) font.
|
||||
#[inline]
|
||||
pub fn fallback_font(mut self, font: impl Into<FontSelection>) -> Self {
|
||||
self.fallback_font = Some(font.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the minimum size of the Widget.
|
||||
///
|
||||
/// This will find and expand atoms with `grow: true`.
|
||||
/// If there are no growable atoms then everything will be left-aligned.
|
||||
#[inline]
|
||||
pub fn min_size(mut self, size: Vec2) -> Self {
|
||||
self.min_size = size;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the maximum size of the Widget.
|
||||
///
|
||||
/// By default, the size is limited by the available size in the [`Ui`].
|
||||
#[inline]
|
||||
pub fn max_size(mut self, size: Vec2) -> Self {
|
||||
self.max_size = size;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the maximum width of the Widget.
|
||||
///
|
||||
/// By default, the width is limited by the available width in the [`Ui`].
|
||||
#[inline]
|
||||
pub fn max_width(mut self, width: f32) -> Self {
|
||||
self.max_size.x = width;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the maximum height of the Widget.
|
||||
///
|
||||
/// By default, the height is limited by the available height in the [`Ui`].
|
||||
#[inline]
|
||||
pub fn max_height(mut self, height: f32) -> Self {
|
||||
self.max_size.y = height;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the [`TextWrapMode`] for the [`crate::Atom`] marked as `shrink`.
|
||||
///
|
||||
/// Only a single [`crate::Atom`] may shrink. If this (or `ui.wrap_mode()`) is not
|
||||
/// [`TextWrapMode::Extend`] and no item is set to shrink, the first (left-most)
|
||||
/// [`AtomKind::Text`] will be set to shrink.
|
||||
#[inline]
|
||||
pub fn wrap_mode(mut self, wrap_mode: TextWrapMode) -> Self {
|
||||
self.wrap_mode = Some(wrap_mode);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the [`Align2`].
|
||||
///
|
||||
/// This will align the [`crate::Atom`]s within the [`Rect`] returned by [`Ui::allocate_space`].
|
||||
///
|
||||
/// The default is chosen based on the [`Ui`]s [`crate::Layout`]. See
|
||||
/// [this snapshot](https://github.com/emilk/egui/blob/master/tests/egui_tests/tests/snapshots/layout/button.png)
|
||||
/// for info on how the [`crate::Layout`] affects the alignment.
|
||||
#[inline]
|
||||
pub fn align2(mut self, align2: Align2) -> Self {
|
||||
self.align2 = Some(align2);
|
||||
self
|
||||
}
|
||||
|
||||
/// Measure the atoms (sizing only), without allocating space or interacting.
|
||||
///
|
||||
/// This converts texts to [`Galley`]s and calculates sizes, but it does *not* call
|
||||
@@ -312,6 +220,118 @@ impl<'a> ContainerAtom<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates the layout-builder methods shared by [`ContainerAtom`] and [`WidgetAtom`] from a
|
||||
/// single definition, so the two can never drift apart.
|
||||
///
|
||||
/// Each entry is written as it appears on [`ContainerAtom`] (mutating its own fields). The
|
||||
/// matching method on [`WidgetAtom`] is generated automatically, forwarding to its inner
|
||||
/// `container`. [`WidgetAtom`]-only builders (`id`, `sense`) stay inherent on [`WidgetAtom`].
|
||||
macro_rules! shared_container_builders {
|
||||
(
|
||||
$(
|
||||
$(#[$meta:meta])*
|
||||
fn $name:ident($self:ident, $($arg:ident: $arg_ty:ty),* $(,)?) $body:block
|
||||
)*
|
||||
) => {
|
||||
impl<'a> ContainerAtom<'a> {
|
||||
$(
|
||||
$(#[$meta])*
|
||||
#[inline]
|
||||
pub fn $name(mut $self, $($arg: $arg_ty),*) -> Self {
|
||||
$body
|
||||
$self
|
||||
}
|
||||
)*
|
||||
}
|
||||
|
||||
impl<'a> WidgetAtom<'a> {
|
||||
$(
|
||||
$(#[$meta])*
|
||||
#[inline]
|
||||
pub fn $name(mut self, $($arg: $arg_ty),*) -> Self {
|
||||
self.container = self.container.$name($($arg),*);
|
||||
self
|
||||
}
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
shared_container_builders! {
|
||||
/// Set the gap between atoms.
|
||||
///
|
||||
/// Default: `Spacing::icon_spacing`
|
||||
fn gap(self, gap: f32) {
|
||||
self.gap = Some(gap);
|
||||
}
|
||||
|
||||
/// Set the [`Frame`].
|
||||
fn frame(self, frame: Frame) {
|
||||
self.frame = frame;
|
||||
}
|
||||
|
||||
/// Set the fallback (default) text color.
|
||||
///
|
||||
/// Default: [`crate::Visuals::text_color`]
|
||||
fn fallback_text_color(self, color: Color32) {
|
||||
self.fallback_text_color = Some(color);
|
||||
}
|
||||
|
||||
/// Set the fallback (default) font.
|
||||
fn fallback_font(self, font: impl Into<FontSelection>) {
|
||||
self.fallback_font = Some(font.into());
|
||||
}
|
||||
|
||||
/// Set the minimum size of the Widget.
|
||||
///
|
||||
/// This will find and expand atoms with `grow: true`.
|
||||
/// If there are no growable atoms then everything will be left-aligned.
|
||||
fn min_size(self, size: Vec2) {
|
||||
self.min_size = size;
|
||||
}
|
||||
|
||||
/// Set the maximum size of the Widget.
|
||||
///
|
||||
/// By default, the size is limited by the available size in the [`Ui`].
|
||||
fn max_size(self, size: Vec2) {
|
||||
self.max_size = size;
|
||||
}
|
||||
|
||||
/// Set the maximum width of the Widget.
|
||||
///
|
||||
/// By default, the width is limited by the available width in the [`Ui`].
|
||||
fn max_width(self, width: f32) {
|
||||
self.max_size.x = width;
|
||||
}
|
||||
|
||||
/// Set the maximum height of the Widget.
|
||||
///
|
||||
/// By default, the height is limited by the available height in the [`Ui`].
|
||||
fn max_height(self, height: f32) {
|
||||
self.max_size.y = height;
|
||||
}
|
||||
|
||||
/// Set the [`TextWrapMode`] for the [`crate::Atom`] marked as `shrink`.
|
||||
///
|
||||
/// Only a single [`crate::Atom`] may shrink. If this (or `ui.wrap_mode()`) is not
|
||||
/// [`TextWrapMode::Extend`] and no item is set to shrink, the first (left-most)
|
||||
/// [`AtomKind::Text`] will be set to shrink.
|
||||
fn wrap_mode(self, wrap_mode: TextWrapMode) {
|
||||
self.wrap_mode = Some(wrap_mode);
|
||||
}
|
||||
|
||||
/// Set the [`Align2`].
|
||||
///
|
||||
/// This will align the [`crate::Atom`]s within the [`Rect`] returned by [`Ui::allocate_space`].
|
||||
///
|
||||
/// The default is chosen based on the [`Ui`]s [`crate::Layout`]. See
|
||||
/// [this snapshot](https://github.com/emilk/egui/blob/master/tests/egui_tests/tests/snapshots/layout/button.png)
|
||||
/// for info on how the [`crate::Layout`] affects the alignment.
|
||||
fn align2(self, align2: Align2) {
|
||||
self.align2 = Some(align2);
|
||||
}
|
||||
}
|
||||
|
||||
/// A measured [`ContainerAtom`], ready to be painted at a [`Rect`].
|
||||
///
|
||||
/// Produced by [`ContainerAtom::measure`]. It has not yet allocated space or interacted, so it
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
use crate::{
|
||||
Align2, Color32, ContainerAtom, FontSelection, Frame, Id, IntoAtoms, Response, Sense,
|
||||
SizedContainerAtom, Ui, Widget,
|
||||
};
|
||||
use crate::{ContainerAtom, Id, IntoAtoms, Response, Sense, SizedContainerAtom, Ui, Widget};
|
||||
use emath::{Rect, Vec2};
|
||||
use epaint::text::TextWrapMode;
|
||||
use smallvec::SmallVec;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
@@ -20,9 +16,9 @@ use std::ops::{Deref, DerefMut};
|
||||
/// - allocates a [`Response`]
|
||||
/// - returns an [`AllocatedWidgetAtom`]
|
||||
/// - [`AllocatedWidgetAtom::paint`]
|
||||
/// - paints the [`Frame`] and each single atom
|
||||
/// - paints the [`crate::Frame`] and each single atom
|
||||
///
|
||||
/// You can use this to first allocate a response and then modify, e.g., the [`Frame`] on the
|
||||
/// You can use this to first allocate a response and then modify, e.g., the [`crate::Frame`] on the
|
||||
/// [`AllocatedWidgetAtom`] for interaction styling.
|
||||
#[derive(Clone)]
|
||||
pub struct WidgetAtom<'a> {
|
||||
@@ -60,98 +56,9 @@ impl<'a> WidgetAtom<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the gap between atoms.
|
||||
///
|
||||
/// Default: `Spacing::icon_spacing`
|
||||
#[inline]
|
||||
pub fn gap(mut self, gap: f32) -> Self {
|
||||
self.container = self.container.gap(gap);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the [`Frame`].
|
||||
#[inline]
|
||||
pub fn frame(mut self, frame: Frame) -> Self {
|
||||
self.container = self.container.frame(frame);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the fallback (default) text color.
|
||||
///
|
||||
/// Default: [`crate::Visuals::text_color`]
|
||||
#[inline]
|
||||
pub fn fallback_text_color(mut self, color: Color32) -> Self {
|
||||
self.container = self.container.fallback_text_color(color);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the fallback (default) font.
|
||||
#[inline]
|
||||
pub fn fallback_font(mut self, font: impl Into<FontSelection>) -> Self {
|
||||
self.container = self.container.fallback_font(font);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the minimum size of the Widget.
|
||||
///
|
||||
/// This will find and expand atoms with `grow: true`.
|
||||
/// If there are no growable atoms then everything will be left-aligned.
|
||||
#[inline]
|
||||
pub fn min_size(mut self, size: Vec2) -> Self {
|
||||
self.container = self.container.min_size(size);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the maximum size of the Widget.
|
||||
///
|
||||
/// By default, the size is limited by the available size in the [`Ui`].
|
||||
#[inline]
|
||||
pub fn max_size(mut self, size: Vec2) -> Self {
|
||||
self.container = self.container.max_size(size);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the maximum width of the Widget.
|
||||
///
|
||||
/// By default, the width is limited by the available width in the [`Ui`].
|
||||
#[inline]
|
||||
pub fn max_width(mut self, width: f32) -> Self {
|
||||
self.container = self.container.max_width(width);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the maximum height of the Widget.
|
||||
///
|
||||
/// By default, the height is limited by the available height in the [`Ui`].
|
||||
#[inline]
|
||||
pub fn max_height(mut self, height: f32) -> Self {
|
||||
self.container = self.container.max_height(height);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the [`TextWrapMode`] for the [`crate::Atom`] marked as `shrink`.
|
||||
///
|
||||
/// Only a single [`crate::Atom`] may shrink. If this (or `ui.wrap_mode()`) is not
|
||||
/// [`TextWrapMode::Extend`] and no item is set to shrink, the first (left-most)
|
||||
/// [`crate::AtomKind::Text`] will be set to shrink.
|
||||
#[inline]
|
||||
pub fn wrap_mode(mut self, wrap_mode: TextWrapMode) -> Self {
|
||||
self.container = self.container.wrap_mode(wrap_mode);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the [`Align2`].
|
||||
///
|
||||
/// This will align the [`crate::Atom`]s within the [`Rect`] returned by [`Ui::allocate_space`].
|
||||
///
|
||||
/// The default is chosen based on the [`Ui`]s [`crate::Layout`]. See
|
||||
/// [this snapshot](https://github.com/emilk/egui/blob/master/tests/egui_tests/tests/snapshots/layout/button.png)
|
||||
/// for info on how the [`crate::Layout`] affects the alignment.
|
||||
#[inline]
|
||||
pub fn align2(mut self, align2: Align2) -> Self {
|
||||
self.container = self.container.align2(align2);
|
||||
self
|
||||
}
|
||||
// The builders shared with `ContainerAtom` (`gap`, `frame`, `fallback_font`, `min_size`,
|
||||
// `wrap_mode`, …) are generated by the `shared_container_builders!` macro in
|
||||
// `container_atom.rs`, so the two types can never drift apart.
|
||||
|
||||
/// [`WidgetAtom::allocate`] and [`AllocatedWidgetAtom::paint`] in one go.
|
||||
pub fn show(self, ui: &mut Ui) -> WidgetAtomResponse {
|
||||
@@ -223,7 +130,7 @@ impl<'a> SizedWidgetAtom<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Interact at `rect` and paint the [`Frame`] and atoms there.
|
||||
/// Interact at `rect` and paint the [`crate::Frame`] and atoms there.
|
||||
///
|
||||
/// Unlike [`Self::allocate`] this does not call [`Ui::allocate_space`]; it interacts at the
|
||||
/// given `rect` using this widget's [`Id`] and [`Sense`]. This is used when nesting one
|
||||
@@ -251,7 +158,7 @@ pub struct AllocatedWidgetAtom<'a> {
|
||||
}
|
||||
|
||||
impl AllocatedWidgetAtom<'_> {
|
||||
/// Paint the [`Frame`] and individual [`crate::Atom`]s at the allocated [`Response`]'s rect.
|
||||
/// Paint the [`crate::Frame`] and individual [`crate::Atom`]s at the allocated [`Response`]'s rect.
|
||||
pub fn paint(self, ui: &Ui) -> WidgetAtomResponse {
|
||||
let rect = self.response.rect;
|
||||
let custom_rects = self.container.paint_at(ui, rect);
|
||||
|
||||
Reference in New Issue
Block a user