1
1
//! Adapted from `egui_demo_lib/src/demo/toggle_switch.rs`
2
+ pub fn toggle_ui ( ui : & mut egui:: Ui , on : & mut bool ) -> egui:: Response {
3
+ // Widget code can be broken up in four steps:
4
+ // 1. Decide a size for the widget
5
+ // 2. Allocate space for it
6
+ // 3. Handle interactions with the widget (if any)
7
+ // 4. Paint the widget
2
8
3
- fn toggle_switch_ui ( ui : & mut egui:: Ui , on : & mut bool ) -> egui:: Response {
4
- let interactive_size = egui:: vec2 ( 12.0 , ui. spacing ( ) . interact_size . y ) ;
5
- let ( interact_rect, mut response) =
6
- ui. allocate_exact_size ( interactive_size, egui:: Sense :: click ( ) ) ;
7
- let visual_size = egui:: vec2 ( 12.0 , 8.0 ) ; // 12x7 in figma, but 12x8 looks _much_ better in epaint
8
- let visual_rect =
9
- egui:: Align2 :: CENTER_CENTER . align_size_within_rect ( visual_size, interact_rect) ;
9
+ // 1. Deciding widget size:
10
+ // You can query the `ui` how much space is available,
11
+ // but in this example we have a fixed size widget based on the height of a standard button:
12
+ let desired_size = ui. spacing ( ) . interact_size . y * egui:: vec2 ( 2.0 , 1.0 ) ;
10
13
14
+ // 2. Allocating space:
15
+ // This is where we get a region of the screen assigned.
16
+ // We also tell the Ui to sense clicks in the allocated region.
17
+ let ( rect, mut response) = ui. allocate_exact_size ( desired_size, egui:: Sense :: click ( ) ) ;
18
+
19
+ // 3. Interact: Time to check for clicks!
11
20
if response. clicked ( ) {
12
21
* on = !* on;
13
- response. mark_changed ( ) ;
22
+ response. mark_changed ( ) ; // report back that the value changed
14
23
}
24
+
25
+ // Attach some meta-data to the response which can be used by screen readers:
15
26
response. widget_info ( || egui:: WidgetInfo :: selected ( egui:: WidgetType :: Checkbox , * on, "" ) ) ;
16
27
17
- if ui. is_rect_visible ( visual_rect) {
28
+ // 4. Paint!
29
+ // Make sure we need to paint:
30
+ if ui. is_rect_visible ( rect) {
31
+ // Let's ask for a simple animation from egui.
32
+ // egui keeps track of changes in the boolean associated with the id and
33
+ // returns an animated value in the 0-1 range for how much "on" we are.
18
34
let how_on = ui. ctx ( ) . animate_bool ( response. id , * on) ;
19
- let visuals = ui. style ( ) . interact ( & response) ;
20
- let expanded_rect = visual_rect. expand ( visuals. expansion ) ;
21
- let fg_fill = visuals. bg_fill ;
22
- let bg_fill = visuals. text_color ( ) ;
23
- let rounding = 0.5 * expanded_rect. height ( ) ;
35
+ // We will follow the current style by asking
36
+ // "how should something that is being interacted with be painted?".
37
+ // This will, for instance, give us different colors when the widget is hovered or clicked.
38
+ let visuals = ui. style ( ) . interact_selectable ( & response, * on) ;
39
+ // All coordinates are in absolute screen coordinates so we use `rect` to place the elements.
40
+ let rect = rect. expand ( visuals. expansion ) ;
41
+ let radius = 0.5 * rect. height ( ) ;
24
42
ui. painter ( )
25
- . rect ( expanded_rect, rounding, bg_fill, egui:: Stroke :: NONE ) ;
26
- let circle_x = egui:: lerp (
27
- ( expanded_rect. left ( ) + rounding) ..=( expanded_rect. right ( ) - rounding) ,
28
- how_on,
29
- ) ;
30
-
31
- let circle_center = egui:: pos2 ( circle_x, expanded_rect. center ( ) . y ) ;
32
- let circle_radius = 2.5 * expanded_rect. height ( ) / visual_size. y ;
43
+ . rect ( rect, radius, visuals. bg_fill , visuals. bg_stroke ) ;
44
+ // Paint the circle, animating it from left to right with `how_on`:
45
+ let circle_x = egui:: lerp ( ( rect. left ( ) + radius) ..=( rect. right ( ) - radius) , how_on) ;
46
+ let center = egui:: pos2 ( circle_x, rect. center ( ) . y ) ;
33
47
ui. painter ( )
34
- . circle ( circle_center , circle_radius , fg_fill , egui :: Stroke :: NONE ) ;
48
+ . circle ( center , 0.75 * radius , visuals . bg_fill , visuals . fg_stroke ) ;
35
49
}
36
50
51
+ // All done! Return the interaction response so the user can check what happened
52
+ // (hovered, clicked, ...) and maybe show a tooltip:
37
53
response
38
54
}
39
55
@@ -45,5 +61,5 @@ fn toggle_switch_ui(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
45
61
/// ui.add(toggle_switch(&mut my_bool));
46
62
/// ```
47
63
pub fn toggle_switch ( on : & mut bool ) -> impl egui:: Widget + ' _ {
48
- move |ui : & mut egui:: Ui | toggle_switch_ui ( ui, on)
64
+ move |ui : & mut egui:: Ui | toggle_ui ( ui, on)
49
65
}
0 commit comments