Skip to content

Commit 10ae832

Browse files
committed
Merge OFW #4261
2 parents 57a02ff + 65cd636 commit 10ae832

File tree

3 files changed

+114
-20
lines changed

3 files changed

+114
-20
lines changed

applications/services/gui/modules/date_time_input.c

Lines changed: 94 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
#include <furi.h>
33
#include <assets_icons.h>
44

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)
1111
#define ROW_0_H (20)
1212

1313
#define ROW_1_Y (40)
@@ -28,6 +28,15 @@ typedef struct {
2828
uint8_t column;
2929
bool editing;
3030

31+
struct {
32+
bool year;
33+
bool month;
34+
bool day;
35+
bool hour;
36+
bool minute;
37+
bool second;
38+
} editable;
39+
3140
DateTimeChangedCallback changed_callback;
3241
DateTimeDoneCallback done_callback;
3342
void* callback_context;
@@ -37,6 +46,7 @@ typedef enum {
3746
EditStateNone,
3847
EditStateActive,
3948
EditStateActiveEditing,
49+
EditStateDisabled
4050
} EditState;
4151

4252
static inline void date_time_input_cleanup_date(DateTime* dt) {
@@ -59,15 +69,17 @@ static inline void date_time_input_draw_block(
5969
furi_assert(text);
6070

6171
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);
6682
}
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);
7183
}
7284

7385
canvas_set_font(canvas, font);
@@ -88,19 +100,19 @@ static void date_time_input_draw_time_callback(Canvas* canvas, DateTimeInputMode
88100

89101
snprintf(buffer, sizeof(buffer), "%02u", model->datetime->hour);
90102
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);
92104
canvas_draw_box(canvas, 60, ROW_1_Y + ROW_1_H - 7, 2, 2);
93105
canvas_draw_box(canvas, 60, ROW_1_Y + ROW_1_H - 7 - 6, 2, 2);
94106

95107
snprintf(buffer, sizeof(buffer), "%02u", model->datetime->minute);
96108
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);
98110
canvas_draw_box(canvas, 94, ROW_1_Y + ROW_1_H - 7, 2, 2);
99111
canvas_draw_box(canvas, 94, ROW_1_Y + ROW_1_H - 7 - 6, 2, 2);
100112

101113
snprintf(buffer, sizeof(buffer), "%02u", model->datetime->second);
102114
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);
104116
}
105117

106118
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
113125
canvas_set_font(canvas, FontPrimary);
114126
snprintf(buffer, sizeof(buffer), "%04u", model->datetime->year);
115127
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);
117129
snprintf(buffer, sizeof(buffer), "%02u", model->datetime->month);
118130
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);
120132
canvas_draw_box(canvas, 64 - 5, ROW_0_Y + (ROW_0_H / 2), 4, 2);
121133
snprintf(buffer, sizeof(buffer), "%02u", model->datetime->day);
122134
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);
124136
canvas_draw_box(canvas, 98 - 5, ROW_0_Y + (ROW_0_H / 2), 4, 2);
125137
}
126138

@@ -131,17 +143,36 @@ static void date_time_input_view_draw_callback(Canvas* canvas, void* _model) {
131143
date_time_input_draw_date_callback(canvas, model);
132144
}
133145

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+
134155
static bool date_time_input_navigation_callback(InputEvent* event, DateTimeInputModel* model) {
135156
if(event->key == InputKeyUp) {
136157
if(model->row > 0) model->row--;
158+
if(!is_allowed_to_edit(model)) model->row++;
137159
} else if(event->key == InputKeyDown) {
138160
if(model->row < ROW_COUNT - 1) model->row++;
161+
if(!is_allowed_to_edit(model)) model->row--;
139162
} else if(event->key == InputKeyOk) {
140163
model->editing = !model->editing;
141164
} else if(event->key == InputKeyRight) {
142165
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--;
143170
} else if(event->key == InputKeyLeft) {
144171
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++;
145176
} else if(event->key == InputKeyBack && model->editing) {
146177
model->editing = false;
147178
} else if(event->key == InputKeyBack && model->done_callback) {
@@ -283,6 +314,13 @@ static void date_time_input_reset_model_input_data(DateTimeInputModel* model) {
283314
model->column = 0;
284315

285316
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;
286324
}
287325

288326
DateTimeInput* date_time_input_alloc(void) {
@@ -345,3 +383,39 @@ void date_time_input_set_header_text(DateTimeInput* date_time_input, const char*
345383
with_view_model(
346384
date_time_input->view, DateTimeInputModel * model, { model->header = text; }, true);
347385
}
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+
}

applications/services/gui/modules/date_time_input.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,25 @@ void date_time_input_set_result_callback(
6565
*/
6666
void date_time_input_set_header_text(DateTimeInput* date_time_input, const char* text);
6767

68+
/** Set date/time fields which can be edited
69+
*
70+
* @param date_time_input date/time input instance
71+
* @param year whether to allow editing the year
72+
* @param month whether to allow editing the month
73+
* @param day whether to allow editing the day
74+
* @param hour whether to allow editing the hour
75+
* @param minute whether to allow editing the minute
76+
* @param second whether to allow editing the second
77+
*/
78+
void date_time_input_set_editable_fields(
79+
DateTimeInput* date_time_input,
80+
bool year,
81+
bool month,
82+
bool day,
83+
bool hour,
84+
bool minute,
85+
bool second);
86+
6887
#ifdef __cplusplus
6988
}
7089
#endif

targets/f7/api_symbols.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,7 @@ Function,-,cuserid,char*,char*
957957
Function,+,date_time_input_alloc,DateTimeInput*,
958958
Function,+,date_time_input_free,void,DateTimeInput*
959959
Function,+,date_time_input_get_view,View*,DateTimeInput*
960+
Function,+,date_time_input_set_editable_fields,void,"DateTimeInput*, _Bool, _Bool, _Bool, _Bool, _Bool, _Bool"
960961
Function,+,date_time_input_set_header_text,void,"DateTimeInput*, const char*"
961962
Function,+,date_time_input_set_result_callback,void,"DateTimeInput*, DateTimeChangedCallback, DateTimeDoneCallback, void*, DateTime*"
962963
Function,+,datetime_datetime_to_timestamp,uint32_t,DateTime*

0 commit comments

Comments
 (0)