@@ -16,12 +16,13 @@ use rodio::{Decoder, OutputStream, Sink};
16
16
fn main ( ) -> Result < ( ) , eframe:: Error > {
17
17
let result = fs:: read_to_string ( "conf.ini" ) ;
18
18
if let Err ( _) = result {
19
- fs:: write ( "conf.ini" , "[Config]\n time=:30:,:00:\n #sound=assets/sound.ogg" ) . unwrap ( )
19
+ fs:: write ( "conf.ini" , "[Config]\n time=:30:,:00:\n #sound=assets/sound.ogg\n #countdown=:20:,::20 " ) . unwrap ( )
20
20
}
21
21
22
22
let i = Ini :: load_from_file ( "conf.ini" ) . unwrap ( ) ;
23
23
let mut time_str = "" . to_string ( ) ;
24
24
let mut sound_path = "" . to_string ( ) ;
25
+ let mut countdown = "" . to_string ( ) ;
25
26
for ( sec, prop) in i. iter ( ) {
26
27
if let Some ( s) = sec {
27
28
if s == "Config" {
@@ -30,6 +31,8 @@ fn main() -> Result<(), eframe::Error> {
30
31
time_str = v. to_string ( ) ;
31
32
} else if k == "sound" {
32
33
sound_path = v. to_string ( ) ;
34
+ } else if k == "countdown" {
35
+ countdown = v. to_string ( ) ;
33
36
}
34
37
}
35
38
}
@@ -40,6 +43,7 @@ fn main() -> Result<(), eframe::Error> {
40
43
41
44
let tray_menu = Menu :: new ( ) ;
42
45
let quit_i = MenuItem :: new ( "Quit" , true , None ) ;
46
+ let countdown_i = MenuItem :: new ( "Countdown" , true , None ) ;
43
47
tray_menu. append_items ( & [
44
48
& PredefinedMenuItem :: about (
45
49
None ,
@@ -50,6 +54,8 @@ fn main() -> Result<(), eframe::Error> {
50
54
} ) ,
51
55
) ,
52
56
& PredefinedMenuItem :: separator ( ) ,
57
+ & countdown_i,
58
+ & PredefinedMenuItem :: separator ( ) ,
53
59
& quit_i,
54
60
] ) ;
55
61
@@ -76,18 +82,20 @@ fn main() -> Result<(), eframe::Error> {
76
82
"Rust clock" , // unused title
77
83
options,
78
84
Box :: new ( move |_cc| Box :: new ( MyApp {
79
- quit : quit_i. id ( ) ,
85
+ quit_index : quit_i. id ( ) ,
80
86
visible : true ,
81
87
time2show : time_str,
82
88
sound_path : sound_path,
89
+ countdown : countdown,
90
+ countdown_index : countdown_i. id ( ) ,
83
91
..MyApp :: default ( )
84
92
} ) ) ,
85
93
)
86
94
}
87
95
88
96
#[ derive( Default ) ]
89
97
struct MyApp {
90
- quit : u32 ,
98
+ quit_index : u32 ,
91
99
time : f32 ,
92
100
time2show : String ,
93
101
tikpop : bool ,
@@ -96,7 +104,11 @@ struct MyApp {
96
104
last_pos_y : f32 ,
97
105
last_visible : bool ,
98
106
sound_path : String ,
99
- inited : bool
107
+ countdown : String ,
108
+ countdown_index : u32 ,
109
+ inited : bool ,
110
+ countdown_start : bool ,
111
+ countdown_start_time : i64
100
112
}
101
113
102
114
impl eframe:: App for MyApp {
@@ -121,7 +133,89 @@ impl eframe::App for MyApp {
121
133
. insert ( 0 , "my_font" . to_owned ( ) ) ;
122
134
ctx. set_fonts ( fonts) ;
123
135
}
124
- clock_window_frame ( ctx, frame, self ) ;
136
+ let mut begin_tik = || {
137
+ self . last_visible = self . visible ;
138
+ if let Some ( pos) = frame. get_window_pos ( ) {
139
+ self . last_pos_x = pos. x ;
140
+ self . last_pos_y = pos. y ;
141
+ }
142
+ self . visible = true ;
143
+ frame. set_visible ( true ) ;
144
+ self . time = 0.0 ;
145
+ frame. set_window_pos ( Pos2 :: new ( init_x, init_y) ) ;
146
+ if self . sound_path != "" {
147
+ let result = fs:: File :: open ( & self . sound_path ) ;
148
+ if let Ok ( file) = result {
149
+ let file = BufReader :: new ( file) ;
150
+ std:: thread:: spawn ( move || {
151
+ let ( _stream, stream_handle) = OutputStream :: try_default ( ) . unwrap ( ) ;
152
+ let source = Decoder :: new ( file) . unwrap ( ) ;
153
+ let sink = Sink :: try_new ( & stream_handle) . unwrap ( ) ;
154
+ sink. append ( source) ;
155
+ sink. sleep_until_end ( ) ;
156
+ } ) ;
157
+ }
158
+ }
159
+ ctx. request_repaint_after ( std:: time:: Duration :: from_millis ( 16 ) ) ;
160
+ } ;
161
+ let mut custom_clock = "" . to_string ( ) ;
162
+ if self . countdown_start == true {
163
+ let mut over_time = ( Local :: now ( ) . timestamp ( ) - self . countdown_start_time ) as i32 ;
164
+ if self . countdown == "" {
165
+ if over_time > 600 {
166
+ self . countdown_start_time = Local :: now ( ) . timestamp ( ) ;
167
+ if self . tikpop == false {
168
+ begin_tik ( ) ;
169
+ self . tikpop = true ;
170
+ }
171
+ }
172
+ let left_time = 600.0 - over_time as f32 ;
173
+ let minute = ( left_time / 60.0 ) as u32 ;
174
+ let second = ( left_time % 60.0 ) as u32 ;
175
+ custom_clock = format ! ( "00:{:02}:{:02}" , minute, second) ;
176
+ } else {
177
+ let countdown_arr: Vec < & str > = self . countdown . split ( ',' ) . collect ( ) ;
178
+ let mut total_time: i32 = 0 ;
179
+ for x in & countdown_arr {
180
+ let single_time: Vec < & str > = x. split ( ':' ) . collect ( ) ;
181
+ let mut cur_time: i32 = 0 ;
182
+ if single_time[ 0 ] != "" {
183
+ cur_time = cur_time + single_time[ 0 ] . to_string ( ) . parse :: < i32 > ( ) . unwrap ( ) * 3600 ;
184
+ }
185
+ if single_time[ 1 ] != "" {
186
+ cur_time = cur_time + single_time[ 1 ] . to_string ( ) . parse :: < i32 > ( ) . unwrap ( ) * 60 ;
187
+ }
188
+ if single_time[ 2 ] != "" {
189
+ cur_time = cur_time + single_time[ 2 ] . to_string ( ) . parse :: < i32 > ( ) . unwrap ( ) ;
190
+ }
191
+ total_time = total_time + cur_time;
192
+ if self . tikpop == false && over_time == total_time. into ( ) {
193
+ begin_tik ( ) ;
194
+ self . tikpop = true ;
195
+ } else if over_time < total_time {
196
+ let left_time = ( total_time - over_time) as f32 ;
197
+ let hour = ( left_time / 60.0 / 60.0 ) as u32 ;
198
+ let minute = ( left_time / 60.0 ) as u32 ;
199
+ let second = ( left_time % 60.0 ) as u32 ;
200
+ custom_clock = format ! ( "{:02}:{:02}:{:02}" , hour, minute, second) ;
201
+ break ;
202
+ }
203
+ }
204
+ if custom_clock == "" {
205
+ over_time = 0 ;
206
+ self . countdown_start_time = Local :: now ( ) . timestamp ( ) ;
207
+ let left_time = ( total_time - over_time) as f32 ;
208
+ let hour = ( left_time / 60.0 / 60.0 ) as u32 ;
209
+ let minute = ( left_time / 60.0 ) as u32 ;
210
+ let second = ( left_time % 60.0 ) as u32 ;
211
+ custom_clock = format ! ( "{:02}:{:02}:{:02}" , hour, minute, second) ;
212
+ if self . tikpop == false {
213
+ begin_tik ( ) ;
214
+ self . tikpop = true ;
215
+ }
216
+ }
217
+ }
218
+ }
125
219
if self . tikpop == true {
126
220
self . time += 2.0 ;
127
221
frame. set_mouse_passthrough ( false ) ;
@@ -153,38 +247,19 @@ impl eframe::App for MyApp {
153
247
let time2show_arr: Vec < & str > = self . time2show . split ( ',' ) . collect ( ) ;
154
248
for x in & time2show_arr {
155
249
let single_time: Vec < & str > = x. split ( ':' ) . collect ( ) ;
156
- if ( single_time[ 0 ] == "" || single_time[ 0 ] == hour) &&
157
- ( single_time[ 1 ] == "" || single_time[ 1 ] == minute) &&
158
- ( ( single_time[ 2 ] == "" && second == "0" ) || single_time[ 2 ] == second) {
159
- self . last_visible = self . visible ;
160
- if let Some ( pos) = frame. get_window_pos ( ) {
161
- self . last_pos_x = pos. x ;
162
- self . last_pos_y = pos. y ;
250
+ if ( single_time[ 0 ] == "" || single_time[ 0 ] == hour || single_time[ 0 ] == "0" . to_string ( ) + & hour) &&
251
+ ( single_time[ 1 ] == "" || single_time[ 1 ] == minute || single_time[ 1 ] == "0" . to_string ( ) + & minute) &&
252
+ ( ( single_time[ 2 ] == "" && ( second == "0" || second == "00" ) ) || single_time[ 2 ] == second) {
253
+ if self . tikpop == false {
254
+ begin_tik ( ) ;
255
+ self . tikpop = true ;
163
256
}
164
- self . visible = true ;
165
- self . tikpop = true ;
166
- frame. set_visible ( true ) ;
167
- self . time = 0.0 ;
168
- frame. set_window_pos ( Pos2 :: new ( init_x, init_y) ) ;
169
- if self . sound_path != "" {
170
- let result = fs:: File :: open ( & self . sound_path ) ;
171
- if let Ok ( file) = result {
172
- let file = BufReader :: new ( file) ;
173
- std:: thread:: spawn ( move || {
174
- let ( _stream, stream_handle) = OutputStream :: try_default ( ) . unwrap ( ) ;
175
- let source = Decoder :: new ( file) . unwrap ( ) ;
176
- let sink = Sink :: try_new ( & stream_handle) . unwrap ( ) ;
177
- sink. append ( source) ;
178
- sink. sleep_until_end ( ) ;
179
- } ) ;
180
- }
181
- }
182
- ctx. request_repaint_after ( std:: time:: Duration :: from_millis ( 16 ) ) ;
183
257
break ;
184
258
}
185
259
}
186
260
}
187
261
}
262
+ clock_window_frame ( ctx, frame, self , custom_clock) ;
188
263
189
264
if let Ok ( TrayEvent {
190
265
event : tray_icon:: ClickEvent :: Left ,
@@ -201,8 +276,15 @@ impl eframe::App for MyApp {
201
276
}
202
277
}
203
278
if let Ok ( event) = MenuEvent :: receiver ( ) . try_recv ( ) {
204
- if event. id == self . quit {
279
+ if event. id == self . quit_index {
205
280
std:: process:: exit ( 0 )
281
+ } else if event. id == self . countdown_index {
282
+ self . countdown_start = !self . countdown_start ;
283
+ if self . countdown_start == true {
284
+ self . visible = true ;
285
+ frame. set_visible ( self . visible ) ;
286
+ self . countdown_start_time = Local :: now ( ) . timestamp ( ) ;
287
+ }
206
288
}
207
289
}
208
290
}
@@ -211,7 +293,8 @@ impl eframe::App for MyApp {
211
293
fn clock_window_frame (
212
294
ctx : & egui:: Context ,
213
295
frame : & mut eframe:: Frame ,
214
- app : & mut MyApp
296
+ app : & mut MyApp ,
297
+ custom_clock : String
215
298
) {
216
299
use egui:: * ;
217
300
let text_color = ctx. style ( ) . visuals . text_color ( ) ;
@@ -240,13 +323,23 @@ fn clock_window_frame(
240
323
) ;
241
324
242
325
// Paint the title:
243
- painter. text (
244
- rect. center_top ( ) + vec2 ( -41.0 , 51.0 ) ,
245
- Align2 :: LEFT_CENTER ,
246
- now. format ( "%H:%M:%S" ) ,
247
- FontId :: proportional ( 50.0 ) ,
248
- text_color,
249
- ) ;
326
+ if custom_clock == "" {
327
+ painter. text (
328
+ rect. center_top ( ) + vec2 ( -41.0 , 51.0 ) ,
329
+ Align2 :: LEFT_CENTER ,
330
+ now. format ( "%H:%M:%S" ) ,
331
+ FontId :: proportional ( 50.0 ) ,
332
+ text_color,
333
+ ) ;
334
+ } else {
335
+ painter. text (
336
+ rect. center_top ( ) + vec2 ( -41.0 , 51.0 ) ,
337
+ Align2 :: LEFT_CENTER ,
338
+ custom_clock,
339
+ FontId :: proportional ( 50.0 ) ,
340
+ text_color,
341
+ ) ;
342
+ }
250
343
251
344
painter. circle_filled (
252
345
Pos2 :: new ( 55.0 , 50.0 ) ,
@@ -294,7 +387,7 @@ fn clock_window_frame(
294
387
if app. tikpop == false {
295
388
let close_response = ui. put (
296
389
Rect :: from_min_size ( rect. left_top ( ) , Vec2 :: splat ( 28.0 ) ) ,
297
- Button :: new ( RichText :: new ( "❌ " ) . size ( 24 .0) ) . frame ( false ) ,
390
+ Button :: new ( RichText :: new ( "⭕ " ) . size ( 16 .0) ) . frame ( false ) ,
298
391
) ;
299
392
if close_response. clicked ( ) {
300
393
frame. set_visible ( false ) ;
0 commit comments