1use crate::{vec2, Response, Sense, Ui, Vec2, Widget};
23/// A visual separator. A horizontal or vertical line (depending on [`crate::Layout`]).
4///
5/// Usually you'd use the shorter version [`Ui::separator`].
6///
7/// ```
8/// # egui::__run_test_ui(|ui| {
9/// // These are equivalent:
10/// ui.separator();
11/// ui.add(egui::Separator::default());
12/// # });
13/// ```
14#[must_use = "You should put this widget in a ui with `ui.add(widget);`"]
15pub struct Separator {
16 spacing: f32,
17 grow: f32,
18 is_horizontal_line: Option<bool>,
19}
2021impl Default for Separator {
22fn default() -> Self {
23Self {
24 spacing: 6.0,
25 grow: 0.0,
26 is_horizontal_line: None,
27 }
28 }
29}
3031impl Separator {
32/// How much space we take up. The line is painted in the middle of this.
33 ///
34 /// In a vertical layout, with a horizontal Separator,
35 /// this is the height of the separator widget.
36 ///
37 /// In a horizontal layout, with a vertical Separator,
38 /// this is the width of the separator widget.
39#[inline]
40pub fn spacing(mut self, spacing: f32) -> Self {
41self.spacing = spacing;
42self
43}
4445/// Explicitly ask for a horizontal line.
46 ///
47 /// By default you will get a horizontal line in vertical layouts,
48 /// and a vertical line in horizontal layouts.
49#[inline]
50pub fn horizontal(mut self) -> Self {
51self.is_horizontal_line = Some(true);
52self
53}
5455/// Explicitly ask for a vertical line.
56 ///
57 /// By default you will get a horizontal line in vertical layouts,
58 /// and a vertical line in horizontal layouts.
59#[inline]
60pub fn vertical(mut self) -> Self {
61self.is_horizontal_line = Some(false);
62self
63}
6465/// Extend each end of the separator line by this much.
66 ///
67 /// The default is to take up the available width/height of the parent.
68 ///
69 /// This will make the line extend outside the parent ui.
70#[inline]
71pub fn grow(mut self, extra: f32) -> Self {
72self.grow += extra;
73self
74}
7576/// Contract each end of the separator line by this much.
77 ///
78 /// The default is to take up the available width/height of the parent.
79 ///
80 /// This effectively adds margins to the line.
81#[inline]
82pub fn shrink(mut self, shrink: f32) -> Self {
83self.grow -= shrink;
84self
85}
86}
8788impl Widget for Separator {
89fn ui(self, ui: &mut Ui) -> Response {
90let Self {
91 spacing,
92 grow,
93 is_horizontal_line,
94 } = self;
9596let is_horizontal_line = is_horizontal_line
97 .unwrap_or_else(|| ui.is_grid() || !ui.layout().main_dir().is_horizontal());
9899let available_space = if ui.is_sizing_pass() {
100 Vec2::ZERO
101 } else {
102 ui.available_size_before_wrap()
103 };
104105let size = if is_horizontal_line {
106 vec2(available_space.x, spacing)
107 } else {
108 vec2(spacing, available_space.y)
109 };
110111let (rect, response) = ui.allocate_at_least(size, Sense::hover());
112113if ui.is_rect_visible(response.rect) {
114let stroke = ui.visuals().widgets.noninteractive.bg_stroke;
115let painter = ui.painter();
116if is_horizontal_line {
117 painter.hline(
118 (rect.left() - grow)..=(rect.right() + grow),
119 painter.round_to_pixel_center(rect.center().y),
120 stroke,
121 );
122 } else {
123 painter.vline(
124 painter.round_to_pixel_center(rect.center().x),
125 (rect.top() - grow)..=(rect.bottom() + grow),
126 stroke,
127 );
128 }
129 }
130131 response
132 }
133}