diff --git a/egui/src/containers/window.rs b/egui/src/containers/window.rs index 66afa97e..537eb352 100644 --- a/egui/src/containers/window.rs +++ b/egui/src/containers/window.rs @@ -741,9 +741,16 @@ fn paint_frame_interaction( // ---------------------------------------------------------------------------- struct TitleBar { + /// A title Id used for dragging windows id: Id, + /// Prepared text in the title title_galley: WidgetTextGalley, + /// Size of the title bar in a collapsed state (if window is collapsible), + /// which includes all necessary space for showing the expand button, the + /// title and the close button. min_rect: Rect, + /// Size of the title bar in an expanded state. This size become known only + /// after expanding window and painting its content rect: Rect, } @@ -804,6 +811,20 @@ fn show_title_bar( } impl TitleBar { + /// Finishes painting of the title bar when the window content size already known. + /// + /// # Parameters + /// + /// - `ui`: + /// - `outer_rect`: + /// - `content_response`: if `None`, window is collapsed at this frame, otherwise contains + /// a result of rendering the window content + /// - `open`: if `None`, no "Close" button will be rendered, otherwise renders and processes + /// the "Close" button and writes a `false` if window was closed + /// - `collapsing`: holds the current expanding state. Can be changed by double click on the + /// title if `collapsible` is `true` + /// - `collapsible`: if `true`, double click on the title bar will be handled for a change + /// of `collapsing` state fn ui( mut self, ui: &mut Ui, @@ -857,6 +878,11 @@ impl TitleBar { } } + /// Paints the "Close" button at the right side of the title bar + /// and processes clicks on it. + /// + /// The button is square and its size is determined by the + /// [`crate::style::Spacing::icon_width`] setting. fn close_button_ui(&self, ui: &mut Ui) -> Response { let button_size = Vec2::splat(ui.spacing().icon_width); let pad = (self.rect.height() - button_size.y) / 2.0; // calculated so that the icon is on the diagonal (if window padding is symmetrical) @@ -872,6 +898,16 @@ impl TitleBar { } } +/// Paints the "Close" button of the window and processes clicks on it. +/// +/// The close button is just an `X` symbol painted by a current stroke +/// for foreground elements (such as a label text). +/// +/// # Parameters +/// - `ui`: +/// - `rect`: The rectangular area to fit the button in +/// +/// Returns the result of a click on a button if it was pressed fn close_button(ui: &mut Ui, rect: Rect) -> Response { let close_id = ui.auto_id_with("window_close_button"); let response = ui.interact(rect, close_id, Sense::click()); @@ -880,9 +916,9 @@ fn close_button(ui: &mut Ui, rect: Rect) -> Response { let visuals = ui.style().interact(&response); let rect = rect.shrink(2.0).expand(visuals.expansion); let stroke = visuals.fg_stroke; - ui.painter() + ui.painter() // paints \ .line_segment([rect.left_top(), rect.right_bottom()], stroke); - ui.painter() + ui.painter() // paints / .line_segment([rect.right_top(), rect.left_bottom()], stroke); response } diff --git a/egui/src/painter.rs b/egui/src/painter.rs index e137f00a..6348a1f8 100644 --- a/egui/src/painter.rs +++ b/egui/src/painter.rs @@ -232,6 +232,8 @@ impl Painter { /// # Paint different primitives impl Painter { + /// Paints the line from the first point to the second using the `stroke` + /// for outlining shape. pub fn line_segment(&self, points: [Pos2; 2], stroke: impl Into) { self.add(Shape::LineSegment { points, diff --git a/egui/src/ui.rs b/egui/src/ui.rs index 8c53e3f2..0d5ea817 100644 --- a/egui/src/ui.rs +++ b/egui/src/ui.rs @@ -1073,7 +1073,7 @@ impl Ui { /// Add extra space before the next widget. /// /// The direction is dependent on the layout. - /// This will be in addition to the [`Spacing::item_spacing`}. + /// This will be in addition to the [`crate::style::Spacing::item_spacing`]. /// /// [`Self::min_rect`] will expand to contain the space. #[inline] diff --git a/egui/src/widgets/plot/items/values.rs b/egui/src/widgets/plot/items/values.rs index ce24a03d..01410c91 100644 --- a/egui/src/widgets/plot/items/values.rs +++ b/egui/src/widgets/plot/items/values.rs @@ -342,7 +342,7 @@ struct ExplicitGenerator { // ---------------------------------------------------------------------------- -/// Result of [`PlotItem::find_closest()`] search, identifies an element inside the item for immediate use +/// Result of [`super::PlotItem::find_closest()`] search, identifies an element inside the item for immediate use pub(crate) struct ClosestElem { /// Position of hovered-over value (or bar/box-plot/...) in PlotItem pub index: usize, diff --git a/emath/src/align.rs b/emath/src/align.rs index a5b26ec8..41801e36 100644 --- a/emath/src/align.rs +++ b/emath/src/align.rs @@ -47,20 +47,64 @@ impl Align { } } - /// ``` - /// assert_eq!(emath::Align::Min.align_size_within_range(2.0, 10.0..=20.0), 10.0..=12.0); - /// assert_eq!(emath::Align::Center.align_size_within_range(2.0, 10.0..=20.0), 14.0..=16.0); - /// assert_eq!(emath::Align::Max.align_size_within_range(2.0, 10.0..=20.0), 18.0..=20.0); - /// assert_eq!(emath::Align::Min.align_size_within_range(f32::INFINITY, 10.0..=20.0), 10.0..=f32::INFINITY); - /// assert_eq!(emath::Align::Center.align_size_within_range(f32::INFINITY, 10.0..=20.0), f32::NEG_INFINITY..=f32::INFINITY); - /// assert_eq!(emath::Align::Max.align_size_within_range(f32::INFINITY, 10.0..=20.0), f32::NEG_INFINITY..=20.0); + /// Returns a range of given size within a specified range. /// - /// assert_eq!(emath::Align::Min.align_size_within_range(f32::INFINITY, 10.0..=f32::INFINITY), 10.0..=f32::INFINITY); - /// assert_eq!(emath::Align::Min.align_size_within_range(f32::INFINITY, f32::NEG_INFINITY..=10.0), f32::NEG_INFINITY..=10.0); - /// assert_eq!(emath::Align::Center.align_size_within_range(f32::INFINITY, 10.0..=f32::INFINITY), 10.0..=f32::INFINITY); - /// assert_eq!(emath::Align::Center.align_size_within_range(f32::INFINITY, f32::NEG_INFINITY..=10.0), f32::NEG_INFINITY..=10.0); - /// assert_eq!(emath::Align::Max.align_size_within_range(f32::INFINITY, 10.0..=f32::INFINITY), 10.0..=f32::INFINITY); - /// assert_eq!(emath::Align::Max.align_size_within_range(f32::INFINITY, f32::NEG_INFINITY..=10.0), f32::NEG_INFINITY..=10.0); + /// If the requested `size` is bigger than the size of `range`, then the returned + /// range will not fit into the available `range`. The extra space will be allocated + /// from: + /// + /// |Align |Side | + /// |------|------------| + /// |Min |right (end) | + /// |Center|both | + /// |Max |left (start)| + /// + /// # Examples + /// ``` + /// use std::f32::{INFINITY, NEG_INFINITY}; + /// use emath::Align::*; + /// + /// // The size is smaller than a range + /// assert_eq!(Min .align_size_within_range(2.0, 10.0..=20.0), 10.0..=12.0); + /// assert_eq!(Center.align_size_within_range(2.0, 10.0..=20.0), 14.0..=16.0); + /// assert_eq!(Max .align_size_within_range(2.0, 10.0..=20.0), 18.0..=20.0); + /// + /// // The size is bigger than a range + /// assert_eq!(Min .align_size_within_range(20.0, 10.0..=20.0), 10.0..=30.0); + /// assert_eq!(Center.align_size_within_range(20.0, 10.0..=20.0), 5.0..=25.0); + /// assert_eq!(Max .align_size_within_range(20.0, 10.0..=20.0), 0.0..=20.0); + /// + /// // The size is infinity, but range is finite - a special case of a previous example + /// assert_eq!(Min .align_size_within_range(INFINITY, 10.0..=20.0), 10.0..=INFINITY); + /// assert_eq!(Center.align_size_within_range(INFINITY, 10.0..=20.0), NEG_INFINITY..=INFINITY); + /// assert_eq!(Max .align_size_within_range(INFINITY, 10.0..=20.0), NEG_INFINITY..=20.0); + /// ``` + /// + /// The infinity-sized ranges can produce a surprising results, if the size is also infinity, + /// use such ranges with carefully! + /// + /// ``` + /// use std::f32::{INFINITY, NEG_INFINITY}; + /// use emath::Align::*; + /// + /// // Allocating a size aligned for infinity bound will lead to empty ranges! + /// assert_eq!(Min .align_size_within_range(2.0, 10.0..=INFINITY), 10.0..=12.0); + /// assert_eq!(Center.align_size_within_range(2.0, 10.0..=INFINITY), INFINITY..=INFINITY);// (!) + /// assert_eq!(Max .align_size_within_range(2.0, 10.0..=INFINITY), INFINITY..=INFINITY);// (!) + /// + /// assert_eq!(Min .align_size_within_range(2.0, NEG_INFINITY..=20.0), NEG_INFINITY..=NEG_INFINITY);// (!) + /// assert_eq!(Center.align_size_within_range(2.0, NEG_INFINITY..=20.0), NEG_INFINITY..=NEG_INFINITY);// (!) + /// assert_eq!(Max .align_size_within_range(2.0, NEG_INFINITY..=20.0), 18.0..=20.0); + /// + /// + /// // The infinity size will always return the given range if it has at least one infinity bound + /// assert_eq!(Min .align_size_within_range(INFINITY, 10.0..=INFINITY), 10.0..=INFINITY); + /// assert_eq!(Center.align_size_within_range(INFINITY, 10.0..=INFINITY), 10.0..=INFINITY); + /// assert_eq!(Max .align_size_within_range(INFINITY, 10.0..=INFINITY), 10.0..=INFINITY); + /// + /// assert_eq!(Min .align_size_within_range(INFINITY, NEG_INFINITY..=20.0), NEG_INFINITY..=20.0); + /// assert_eq!(Center.align_size_within_range(INFINITY, NEG_INFINITY..=20.0), NEG_INFINITY..=20.0); + /// assert_eq!(Max .align_size_within_range(INFINITY, NEG_INFINITY..=20.0), NEG_INFINITY..=20.0); /// ``` #[inline] pub fn align_size_within_range( @@ -118,11 +162,13 @@ impl Align2 { } impl Align2 { + /// Returns an alignment by the X (horizontal) axis #[inline(always)] pub fn x(self) -> Align { self.0[0] } + /// Returns an alignment by the Y (vertical) axis #[inline(always)] pub fn y(self) -> Align { self.0[1] @@ -156,6 +202,26 @@ impl Align2 { Rect::from_x_y_ranges(x_range, y_range) } + /// Returns the point on the rect's frame or in the center of a rect according + /// to the alignments of this object. + /// + /// ```text + /// (*)-----------+------(*)------+-----------(*)--> X + /// | | | | + /// | Min, Min | Center, Min | Max, Min | + /// | | | | + /// +------------+---------------+------------+ + /// | | | | + /// (*)Min, Center|Center(*)Center|Max, Center(*) + /// | | | | + /// +------------+---------------+------------+ + /// | | | | + /// | Min, Max | Center, Max | Max, Max | + /// | | | | + /// (*)-----------+------(*)------+-----------(*) + /// | + /// Y + /// ``` pub fn pos_in_rect(self, frame: &Rect) -> Pos2 { let x = match self.x() { Align::Min => frame.left(), @@ -188,6 +254,11 @@ impl std::ops::IndexMut for Align2 { } } +/// Allocates a rectangle of the specified `size` inside the `frame` rectangle +/// around of its center. +/// +/// If `size` is bigger than the `frame`s size the returned rect will bounce out +/// of the `frame`. pub fn center_size_in_rect(size: Vec2, frame: Rect) -> Rect { Align2::CENTER_CENTER.align_size_within_rect(size, frame) } diff --git a/epaint/src/shape.rs b/epaint/src/shape.rs index 7e666b2e..792bfebc 100644 --- a/epaint/src/shape.rs +++ b/epaint/src/shape.rs @@ -15,10 +15,13 @@ pub enum Shape { /// For performance reasons it is better to avoid it. Vec(Vec), Circle(CircleShape), + /// A line between two points. LineSegment { points: [Pos2; 2], stroke: Stroke, }, + /// A series of lines between points. + /// The path can have a stroke and/or fill (if closed). Path(PathShape), Rect(RectShape), Text(TextShape),