egui/widgets/separator.rs
1use crate::{vec2, Response, Sense, Ui, Vec2, Widget};
2
3/// 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}
20
21impl Default for Separator {
22 fn default() -> Self {
23 Self {
24 spacing: 6.0,
25 grow: 0.0,
26 is_horizontal_line: None,
27 }
28 }
29}
30
31impl 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]
40 pub fn spacing(mut self, spacing: f32) -> Self {
41 self.spacing = spacing;
42 self
43 }
44
45 /// 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]
50 pub fn horizontal(mut self) -> Self {
51 self.is_horizontal_line = Some(true);
52 self
53 }
54
55 /// 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]
60 pub fn vertical(mut self) -> Self {
61 self.is_horizontal_line = Some(false);
62 self
63 }
64
65 /// 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]
71 pub fn grow(mut self, extra: f32) -> Self {
72 self.grow += extra;
73 self
74 }
75
76 /// 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]
82 pub fn shrink(mut self, shrink: f32) -> Self {
83 self.grow -= shrink;
84 self
85 }
86}
87
88impl Widget for Separator {
89 fn ui(self, ui: &mut Ui) -> Response {
90 let Self {
91 spacing,
92 grow,
93 is_horizontal_line,
94 } = self;
95
96 let is_horizontal_line = is_horizontal_line
97 .unwrap_or_else(|| ui.is_grid() || !ui.layout().main_dir().is_horizontal());
98
99 let available_space = if ui.is_sizing_pass() {
100 Vec2::ZERO
101 } else {
102 ui.available_size_before_wrap()
103 };
104
105 let size = if is_horizontal_line {
106 vec2(available_space.x, spacing)
107 } else {
108 vec2(spacing, available_space.y)
109 };
110
111 let (rect, response) = ui.allocate_at_least(size, Sense::hover());
112
113 if ui.is_rect_visible(response.rect) {
114 let stroke = ui.visuals().widgets.noninteractive.bg_stroke;
115 let painter = ui.painter();
116 if is_horizontal_line {
117 painter.hline(
118 (rect.left() - grow)..=(rect.right() + grow),
119 rect.center().y,
120 stroke,
121 );
122 } else {
123 painter.vline(
124 rect.center().x,
125 (rect.top() - grow)..=(rect.bottom() + grow),
126 stroke,
127 );
128 }
129 }
130
131 response
132 }
133}