2
2
#include <furi.h>
3
3
#include <assets_icons.h>
4
4
5
- #define get_state (m , r , c ) \
6
- ((m)->row == (r) && (m)->column == (c) ? \
7
- ((m)->editing ? EditStateActiveEditing : EditStateActive) : \
8
- EditStateNone)
9
-
10
- #define ROW_0_Y (10 )
5
+ #define get_state (m , r , c , f ) \
6
+ ((m)->editable.f ? ((m)-> row == (r) && (m)->column == (c) ? \
7
+ ((m)->editing ? EditStateActiveEditing : EditStateActive) : \
8
+ EditStateNone) : \
9
+ EditStateDisabled)
10
+ #define ROW_0_Y (9 )
11
11
#define ROW_0_H (20)
12
12
13
13
#define ROW_1_Y (40)
@@ -28,6 +28,15 @@ typedef struct {
28
28
uint8_t column ;
29
29
bool editing ;
30
30
31
+ struct {
32
+ bool year ;
33
+ bool month ;
34
+ bool day ;
35
+ bool hour ;
36
+ bool minute ;
37
+ bool second ;
38
+ } editable ;
39
+
31
40
DateTimeChangedCallback changed_callback ;
32
41
DateTimeDoneCallback done_callback ;
33
42
void * callback_context ;
@@ -37,6 +46,7 @@ typedef enum {
37
46
EditStateNone ,
38
47
EditStateActive ,
39
48
EditStateActiveEditing ,
49
+ EditStateDisabled
40
50
} EditState ;
41
51
42
52
static inline void date_time_input_cleanup_date (DateTime * dt ) {
@@ -59,15 +69,17 @@ static inline void date_time_input_draw_block(
59
69
furi_assert (text );
60
70
61
71
canvas_set_color (canvas , ColorBlack );
62
- if (state != EditStateNone ) {
63
- if (state == EditStateActiveEditing ) {
64
- canvas_draw_icon (canvas , x + w / 2 - 2 , y - 1 - 3 , & I_SmallArrowUp_3x5 );
65
- canvas_draw_icon (canvas , x + w / 2 - 2 , y + h + 1 , & I_SmallArrowDown_3x5 );
72
+ if (state != EditStateDisabled ) {
73
+ if (state != EditStateNone ) {
74
+ if (state == EditStateActiveEditing ) {
75
+ canvas_draw_icon (canvas , x + w / 2 - 2 , y - 1 - 3 , & I_SmallArrowUp_3x5 );
76
+ canvas_draw_icon (canvas , x + w / 2 - 2 , y + h + 1 , & I_SmallArrowDown_3x5 );
77
+ }
78
+ canvas_draw_rbox (canvas , x , y , w , h , 1 );
79
+ canvas_set_color (canvas , ColorWhite );
80
+ } else {
81
+ canvas_draw_rframe (canvas , x , y , w , h , 1 );
66
82
}
67
- canvas_draw_rbox (canvas , x , y , w , h , 1 );
68
- canvas_set_color (canvas , ColorWhite );
69
- } else {
70
- canvas_draw_rframe (canvas , x , y , w , h , 1 );
71
83
}
72
84
73
85
canvas_set_font (canvas , font );
@@ -88,19 +100,19 @@ static void date_time_input_draw_time_callback(Canvas* canvas, DateTimeInputMode
88
100
89
101
snprintf (buffer , sizeof (buffer ), "%02u" , model -> datetime -> hour );
90
102
date_time_input_draw_block (
91
- canvas , 30 , ROW_1_Y , 28 , ROW_1_H , FontBigNumbers , get_state (model , 1 , 0 ), buffer );
103
+ canvas , 30 , ROW_1_Y , 28 , ROW_1_H , FontBigNumbers , get_state (model , 1 , 0 , hour ), buffer );
92
104
canvas_draw_box (canvas , 60 , ROW_1_Y + ROW_1_H - 7 , 2 , 2 );
93
105
canvas_draw_box (canvas , 60 , ROW_1_Y + ROW_1_H - 7 - 6 , 2 , 2 );
94
106
95
107
snprintf (buffer , sizeof (buffer ), "%02u" , model -> datetime -> minute );
96
108
date_time_input_draw_block (
97
- canvas , 64 , ROW_1_Y , 28 , ROW_1_H , FontBigNumbers , get_state (model , 1 , 1 ), buffer );
109
+ canvas , 64 , ROW_1_Y , 28 , ROW_1_H , FontBigNumbers , get_state (model , 1 , 1 , minute ), buffer );
98
110
canvas_draw_box (canvas , 94 , ROW_1_Y + ROW_1_H - 7 , 2 , 2 );
99
111
canvas_draw_box (canvas , 94 , ROW_1_Y + ROW_1_H - 7 - 6 , 2 , 2 );
100
112
101
113
snprintf (buffer , sizeof (buffer ), "%02u" , model -> datetime -> second );
102
114
date_time_input_draw_block (
103
- canvas , 98 , ROW_1_Y , 28 , ROW_1_H , FontBigNumbers , get_state (model , 1 , 2 ), buffer );
115
+ canvas , 98 , ROW_1_Y , 28 , ROW_1_H , FontBigNumbers , get_state (model , 1 , 2 , second ), buffer );
104
116
}
105
117
106
118
static void date_time_input_draw_date_callback (Canvas * canvas , DateTimeInputModel * model ) {
@@ -113,14 +125,14 @@ static void date_time_input_draw_date_callback(Canvas* canvas, DateTimeInputMode
113
125
canvas_set_font (canvas , FontPrimary );
114
126
snprintf (buffer , sizeof (buffer ), "%04u" , model -> datetime -> year );
115
127
date_time_input_draw_block (
116
- canvas , 2 , ROW_0_Y , 56 , ROW_0_H , FontBigNumbers , get_state (model , 0 , 0 ), buffer );
128
+ canvas , 2 , ROW_0_Y , 56 , ROW_0_H , FontBigNumbers , get_state (model , 0 , 0 , year ), buffer );
117
129
snprintf (buffer , sizeof (buffer ), "%02u" , model -> datetime -> month );
118
130
date_time_input_draw_block (
119
- canvas , 64 , ROW_0_Y , 28 , ROW_0_H , FontBigNumbers , get_state (model , 0 , 1 ), buffer );
131
+ canvas , 64 , ROW_0_Y , 28 , ROW_0_H , FontBigNumbers , get_state (model , 0 , 1 , month ), buffer );
120
132
canvas_draw_box (canvas , 64 - 5 , ROW_0_Y + (ROW_0_H / 2 ), 4 , 2 );
121
133
snprintf (buffer , sizeof (buffer ), "%02u" , model -> datetime -> day );
122
134
date_time_input_draw_block (
123
- canvas , 98 , ROW_0_Y , 28 , ROW_0_H , FontBigNumbers , get_state (model , 0 , 2 ), buffer );
135
+ canvas , 98 , ROW_0_Y , 28 , ROW_0_H , FontBigNumbers , get_state (model , 0 , 2 , day ), buffer );
124
136
canvas_draw_box (canvas , 98 - 5 , ROW_0_Y + (ROW_0_H / 2 ), 4 , 2 );
125
137
}
126
138
@@ -131,17 +143,36 @@ static void date_time_input_view_draw_callback(Canvas* canvas, void* _model) {
131
143
date_time_input_draw_date_callback (canvas , model );
132
144
}
133
145
146
+ static inline bool is_allowed_to_edit (DateTimeInputModel * model ) {
147
+ return (model -> row == 0 && ((model -> column == 0 && model -> editable .year ) |
148
+ (model -> column == 1 && model -> editable .month ) |
149
+ (model -> column == 2 && model -> editable .day ))) ||
150
+ ((model -> row == 1 ) && ((model -> column == 0 && model -> editable .hour ) |
151
+ (model -> column == 1 && model -> editable .minute ) |
152
+ (model -> column == 2 && model -> editable .second )));
153
+ }
154
+
134
155
static bool date_time_input_navigation_callback (InputEvent * event , DateTimeInputModel * model ) {
135
156
if (event -> key == InputKeyUp ) {
136
157
if (model -> row > 0 ) model -> row -- ;
158
+ if (!is_allowed_to_edit (model )) model -> row ++ ;
137
159
} else if (event -> key == InputKeyDown ) {
138
160
if (model -> row < ROW_COUNT - 1 ) model -> row ++ ;
161
+ if (!is_allowed_to_edit (model )) model -> row -- ;
139
162
} else if (event -> key == InputKeyOk ) {
140
163
model -> editing = !model -> editing ;
141
164
} else if (event -> key == InputKeyRight ) {
142
165
if (model -> column < COLUMN_COUNT - 1 ) model -> column ++ ;
166
+ while (model -> column < COLUMN_COUNT - 1 && !is_allowed_to_edit (model ))
167
+ model -> column ++ ;
168
+ while (model -> column > 0 && !is_allowed_to_edit (model ))
169
+ model -> column -- ;
143
170
} else if (event -> key == InputKeyLeft ) {
144
171
if (model -> column > 0 ) model -> column -- ;
172
+ while (model -> column > 0 && !is_allowed_to_edit (model ))
173
+ model -> column -- ;
174
+ while (model -> column < COLUMN_COUNT - 1 && !is_allowed_to_edit (model ))
175
+ model -> column ++ ;
145
176
} else if (event -> key == InputKeyBack && model -> editing ) {
146
177
model -> editing = false;
147
178
} else if (event -> key == InputKeyBack && model -> done_callback ) {
@@ -283,6 +314,13 @@ static void date_time_input_reset_model_input_data(DateTimeInputModel* model) {
283
314
model -> column = 0 ;
284
315
285
316
model -> datetime = NULL ;
317
+
318
+ model -> editable .year = true;
319
+ model -> editable .month = true;
320
+ model -> editable .day = true;
321
+ model -> editable .hour = true;
322
+ model -> editable .minute = true;
323
+ model -> editable .second = true;
286
324
}
287
325
288
326
DateTimeInput * date_time_input_alloc (void ) {
@@ -345,3 +383,39 @@ void date_time_input_set_header_text(DateTimeInput* date_time_input, const char*
345
383
with_view_model (
346
384
date_time_input -> view , DateTimeInputModel * model , { model -> header = text ; }, true);
347
385
}
386
+
387
+ void date_time_input_set_editable_fields (
388
+ DateTimeInput * date_time_input ,
389
+ bool year ,
390
+ bool month ,
391
+ bool day ,
392
+ bool hour ,
393
+ bool minute ,
394
+ bool second ) {
395
+ furi_check (date_time_input );
396
+
397
+ with_view_model (
398
+ date_time_input -> view ,
399
+ DateTimeInputModel * model ,
400
+ {
401
+ model -> editable .year = year ;
402
+ model -> editable .month = month ;
403
+ model -> editable .day = day ;
404
+ model -> editable .hour = hour ;
405
+ model -> editable .minute = minute ;
406
+ model -> editable .second = second ;
407
+
408
+ // Select first editable field
409
+ model -> row = 0 ;
410
+ model -> column = 0 ;
411
+ while (!is_allowed_to_edit (model )) {
412
+ // Cycle to next column and wrap around at end
413
+ model -> column = (model -> column + 1 ) % COLUMN_COUNT ;
414
+ // If the column is 0, we wrapped, so go to next row
415
+ if (model -> column == 0 ) model -> row ++ ;
416
+ // If we passed the last row, give up
417
+ if (model -> row >= ROW_COUNT ) break ;
418
+ };
419
+ },
420
+ true);
421
+ }
0 commit comments