1
1
use crate :: {
2
2
strutil:: TString ,
3
3
ui:: {
4
- component:: { swipe_detect:: SwipeConfig , Component , Event , EventCtx , Qr } ,
4
+ component:: { swipe_detect:: SwipeConfig , Component , Event , EventCtx , Label , Pad , Qr } ,
5
5
flow:: Swipable ,
6
- geometry:: { Insets , Rect } ,
7
- shape:: { self , Renderer } ,
6
+ geometry:: { Alignment , Insets , Rect } ,
7
+ shape:: Renderer ,
8
8
util:: Pager ,
9
9
} ,
10
10
} ;
11
11
12
12
use super :: super :: {
13
+ component:: { Button , ButtonMsg } ,
13
14
constant:: SCREEN ,
14
- firmware:: { theme, ActionBar , Header , HeaderMsg } ,
15
+ firmware:: { theme, Header } ,
15
16
} ;
16
17
17
18
pub enum QrMsg {
18
19
Cancelled ,
19
20
}
20
21
21
22
pub struct QrScreen {
22
- header : Header ,
23
+ title : Label < ' static > ,
24
+ close_button : Button ,
23
25
qr : Qr ,
24
- action_bar : Option < ActionBar > ,
25
- pad : Rect ,
26
+ pad : Pad ,
26
27
}
27
28
28
29
impl QrScreen {
29
- const QR_PADDING : i16 = 8 ;
30
- const QR_HEIGHT : i16 = 300 ;
31
- const QR_PAD_RADIUS : i16 = 12 ;
32
-
33
- pub fn new ( qr : Qr ) -> Self {
30
+ const BUTTON_WIDTH : i16 = 80 ; // [px]
31
+ pub fn new ( title : TString < ' static > , qr : Qr ) -> Self {
34
32
Self {
35
- header : Header :: new ( TString :: empty ( ) ) ,
33
+ title : Label :: new ( title, Alignment :: Start , theme:: TEXT_SMALL_BLACK )
34
+ . vertically_centered ( ) ,
36
35
qr,
37
- action_bar : None ,
38
- pad : Rect :: zero ( ) ,
36
+ pad : Pad :: with_background ( theme:: FG ) ,
37
+ close_button : Button :: with_icon ( theme:: ICON_CLOSE )
38
+ . styled ( theme:: button_header_inverted ( ) ) ,
39
39
}
40
40
}
41
-
42
- pub fn with_header ( mut self , header : Header ) -> Self {
43
- self . header = header;
44
- self
45
- }
46
-
47
- pub fn with_action_bar ( mut self , action_bar : ActionBar ) -> Self {
48
- self . action_bar = Some ( action_bar) ;
49
- self
50
- }
51
41
}
52
42
53
43
impl Component for QrScreen {
@@ -58,43 +48,34 @@ impl Component for QrScreen {
58
48
debug_assert_eq ! ( bounds. height( ) , SCREEN . height( ) ) ;
59
49
debug_assert_eq ! ( bounds. width( ) , SCREEN . width( ) ) ;
60
50
61
- let ( header_area, mut rest) = bounds. split_top ( Header :: HEADER_HEIGHT ) ;
62
- if let Some ( action_bar) = & mut self . action_bar {
63
- let action_bar_area;
64
- ( rest, action_bar_area) = rest. split_bottom ( ActionBar :: ACTION_BAR_HEIGHT ) ;
65
- action_bar. place ( action_bar_area) ;
66
- }
67
- let ( qr_pad, _) = rest. split_top ( Self :: QR_HEIGHT + 2 * Self :: QR_PADDING ) ;
51
+ let ( header_area, mut qr_area) = bounds. split_top ( Header :: HEADER_HEIGHT ) ;
52
+ let ( mut title_area, button_area) = header_area. split_right ( Self :: BUTTON_WIDTH ) ;
53
+ title_area = title_area. inset ( Insets :: left ( theme:: SIDE_INSETS . left ) ) ;
68
54
69
- let side_padding = ( SCREEN . width ( ) - Self :: QR_HEIGHT - 2 * Self :: QR_PADDING ) / 2 ;
70
- let qr_pad = qr_pad . inset ( Insets :: sides ( side_padding ) ) ;
55
+ qr_area = qr_area . inset ( theme :: SIDE_INSETS ) ;
56
+ qr_area = qr_area . with_height ( qr_area . width ( ) ) ;
71
57
72
- self . pad = qr_pad ;
73
-
74
- self . header . place ( header_area ) ;
75
- self . qr . place ( qr_pad . shrink ( Self :: QR_PADDING ) ) ;
58
+ self . pad . place ( bounds ) ;
59
+ self . title . place ( title_area ) ;
60
+ self . close_button . place ( button_area ) ;
61
+ self . qr . place ( qr_area ) ;
76
62
77
63
bounds
78
64
}
79
65
80
66
fn event ( & mut self , ctx : & mut EventCtx , event : Event ) -> Option < Self :: Msg > {
81
- if let Some ( HeaderMsg :: Cancelled ) = self . header . event ( ctx, event) {
67
+ if let Some ( ButtonMsg :: Clicked ) = self . close_button . event ( ctx, event) {
82
68
return Some ( QrMsg :: Cancelled ) ;
83
69
}
70
+
84
71
None
85
72
}
86
73
87
74
fn render < ' s > ( & ' s self , target : & mut impl Renderer < ' s > ) {
88
- // Render white QR pad
89
- shape:: Bar :: new ( self . pad )
90
- . with_bg ( theme:: FG )
91
- . with_fg ( theme:: FG )
92
- . with_radius ( Self :: QR_PAD_RADIUS )
93
- . render ( target) ;
94
-
95
- self . header . render ( target) ;
75
+ self . pad . render ( target) ;
76
+ self . title . render ( target) ;
77
+ self . close_button . render ( target) ;
96
78
self . qr . render ( target) ;
97
- self . action_bar . render ( target) ;
98
79
}
99
80
}
100
81
@@ -115,20 +96,3 @@ impl crate::trace::Trace for QrScreen {
115
96
t. component ( "QrScreen" ) ;
116
97
}
117
98
}
118
-
119
- #[ cfg( test) ]
120
- mod tests {
121
- use super :: { super :: super :: constant:: SCREEN , * } ;
122
-
123
- #[ test]
124
- fn test_component_heights_fit_screen ( ) {
125
- assert ! (
126
- QrScreen :: QR_HEIGHT
127
- + 2 * QrScreen :: QR_PADDING
128
- + Header :: HEADER_HEIGHT
129
- + ActionBar :: ACTION_BAR_HEIGHT
130
- <= SCREEN . height( ) ,
131
- "Components overflow the screen height" ,
132
- ) ;
133
- }
134
- }
0 commit comments