14
14
15
15
//! A toggle switch widget.
16
16
17
- use crate :: kurbo:: { Circle , Point , Rect , RoundedRect , Size } ;
18
- use crate :: piet:: { FontBuilder , Text , TextLayout , TextLayoutBuilder } ;
19
- use crate :: piet:: { LinearGradient , RenderContext , UnitPoint } ;
17
+ use crate :: kurbo:: { Circle , Point , Rect , RoundedRect , Shape , Size } ;
18
+ use crate :: piet:: {
19
+ FontBuilder , LinearGradient , RenderContext , Text , TextLayout , TextLayoutBuilder , UnitPoint ,
20
+ } ;
20
21
use crate :: theme;
21
22
use crate :: widget:: Align ;
22
23
use crate :: {
23
- BaseState , BoxConstraints , Env , Event , EventCtx , LayoutCtx , PaintCtx , UpdateCtx , Widget ,
24
+ BaseState , BoxConstraints , Env , Event , EventCtx , LayoutCtx , LocalizedString , PaintCtx ,
25
+ UpdateCtx , Widget ,
24
26
} ;
25
27
26
- #[ derive( Debug , Clone ) ]
27
- pub struct Switch ;
28
-
29
- impl Switch {
30
- pub fn new ( ) -> impl Widget < bool > {
31
- Align :: vertical ( UnitPoint :: CENTER , SwitchRaw :: default ( ) )
32
- }
33
- }
34
-
28
+ /// A switch that toggles a boolean.
35
29
#[ derive( Debug , Clone , Default ) ]
36
- pub struct SwitchRaw {
30
+ pub struct Switch {
37
31
knob_pos : Point ,
38
32
knob_hovered : bool ,
39
33
}
40
34
41
- impl SwitchRaw {
35
+ impl Switch {
36
+ pub fn new ( ) -> impl Widget < bool > {
37
+ Align :: vertical ( UnitPoint :: CENTER , Self :: default ( ) )
38
+ }
39
+
42
40
fn knob_hit_test ( & self , knob_width : f64 , mouse_pos : Point ) -> bool {
43
41
let knob_circle = Circle :: new ( self . knob_pos , knob_width / 2. ) ;
44
- if mouse_pos. distance ( knob_circle. center ) < knob_circle. radius {
45
- return true ;
46
- }
47
- false
42
+ knob_circle. winding ( mouse_pos) > 0
48
43
}
49
44
50
45
fn paint_label (
@@ -58,33 +53,37 @@ impl SwitchRaw {
58
53
) {
59
54
let font_name = env. get ( theme:: FONT_NAME ) ;
60
55
let font_size = env. get ( theme:: TEXT_SIZE_NORMAL ) ;
56
+ let switch_height = env. get ( theme:: BORDERED_WIDGET_HEIGHT ) ;
61
57
62
- let label = if * data { "ON" } else { "OFF" } ;
58
+ let label: LocalizedString < & str > = if * data {
59
+ LocalizedString :: new ( "On" )
60
+ } else {
61
+ LocalizedString :: new ( "Off" )
62
+ } ;
63
+ let localized_label = label. localized_str ( ) . to_uppercase ( ) ;
63
64
64
65
let font = paint_ctx
65
66
. text ( )
66
67
. new_font_by_name ( font_name, font_size)
67
- . unwrap ( )
68
68
. build ( )
69
69
. unwrap ( ) ;
70
70
71
71
let text_layout = paint_ctx
72
72
. text ( )
73
- . new_text_layout ( & font, label)
74
- . unwrap ( )
73
+ . new_text_layout ( & font, & localized_label)
75
74
. build ( )
76
75
. unwrap ( ) ;
77
76
78
77
let mut origin = UnitPoint :: LEFT . resolve ( Rect :: from_origin_size (
79
78
Point :: ORIGIN ,
80
79
Size :: new (
81
80
( base_state. size ( ) . width - text_layout. width ( ) ) . max ( 0.0 ) ,
82
- base_state . size ( ) . height + ( font_size * 1.2 ) / 2. ,
81
+ switch_height + ( font_size * 1.2 ) / 2. ,
83
82
) ,
84
83
) ) ;
85
84
86
85
// adjust label position
87
- origin. y = origin. y . min ( base_state . size ( ) . height ) ;
86
+ origin. y = origin. y . min ( switch_height ) ;
88
87
89
88
if * data {
90
89
origin. x = switch_padding * 2.
@@ -96,7 +95,7 @@ impl SwitchRaw {
96
95
}
97
96
}
98
97
99
- impl Widget < bool > for SwitchRaw {
98
+ impl Widget < bool > for Switch {
100
99
fn paint ( & mut self , paint_ctx : & mut PaintCtx , base_state : & BaseState , data : & bool , env : & Env ) {
101
100
let switch_padding = 3. ;
102
101
let switch_height = env. get ( theme:: BORDERED_WIDGET_HEIGHT ) ;
@@ -110,6 +109,7 @@ impl Widget<bool> for SwitchRaw {
110
109
) ;
111
110
112
111
// paint different background for on and off state
112
+ // todo: make color configurable
113
113
let background_gradient = if * data {
114
114
LinearGradient :: new (
115
115
UnitPoint :: TOP ,
@@ -210,11 +210,7 @@ impl Widget<bool> for SwitchRaw {
210
210
if ctx. is_active ( ) {
211
211
ctx. set_active ( false ) ;
212
212
if ctx. is_hot ( ) {
213
- if * data {
214
- * data = false ;
215
- } else {
216
- * data = true ;
217
- }
213
+ * data = !* data
218
214
}
219
215
ctx. invalidate ( ) ;
220
216
}
@@ -224,11 +220,7 @@ impl Widget<bool> for SwitchRaw {
224
220
// todo: animate dragging of knob
225
221
}
226
222
if ctx. is_hot ( ) {
227
- if self . knob_hit_test ( knob_size, mouse. pos ) {
228
- self . knob_hovered = true
229
- } else {
230
- self . knob_hovered = false
231
- }
223
+ self . knob_hovered = self . knob_hit_test ( knob_size, mouse. pos )
232
224
}
233
225
ctx. invalidate ( ) ;
234
226
}
0 commit comments