1 #include "../../lv_examples.h"
2 #if LV_USE_OBSERVER && LV_USE_SLIDER && LV_USE_LABEL && LV_USE_ROLLER && LV_USE_DROPDOWN && LV_FONT_MONTSERRAT_30 && LV_BUILD_EXAMPLES
3 
4 static lv_subject_t hour_subject;
5 static lv_subject_t minute_subject;
6 static lv_subject_t format_subject;
7 static lv_subject_t am_pm_subject;
8 static lv_subject_t time_subject;
9 static lv_subject_t * time_group_array_subject[] = {&hour_subject, &minute_subject, &format_subject, &am_pm_subject};
10 const char * hour12_options = "01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12";
11 const char * hour24_options =
12     "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23";
13 const char * minute_options =
14     "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59";
15 
16 static void set_btn_clicked_event_cb(lv_event_t * e);
17 static void close_clicked_event_cb(lv_event_t * e);
18 static void hour_roller_options_update(lv_observer_t * observer, lv_subject_t * subject);
19 static void time_observer_cb(lv_observer_t * observer, lv_subject_t * subject);
20 
21 typedef enum {
22     TIME_FORMAT_12,
23     TIME_FORMAT_24,
24 } time_format_t;
25 
26 typedef enum {
27     TIME_AM,
28     TIME_PM,
29 } time_am_pm_t;
30 
31 /**
32  * Show how to handle a complex time setting with hour, minute, 12/24 hour mode, and AM/PM switch
33  * In a real application the time can be displayed on multiple screens and it's not trivial
34  * how and where to store the current values and how to get them.
35  * In this example the widgets to set the time are create/deleted dynamically,
36  * yet they always know what the current values are by using subjects.
37  */
lv_example_observer_3(void)38 void lv_example_observer_3(void)
39 {
40     /*Initialize the subjects.
41      *The UI will update these and read the current values from here,
42      *however the application can update these values at any time and
43      *the widgets will be updated automatically. */
44     lv_subject_init_int(&hour_subject, 7);
45     lv_subject_init_int(&minute_subject, 45);
46     lv_subject_init_int(&format_subject, TIME_FORMAT_12);
47     lv_subject_init_int(&am_pm_subject, TIME_AM);
48     lv_subject_init_group(&time_subject, time_group_array_subject, 4);
49 
50     /*Create the UI*/
51     lv_obj_t * time_label = lv_label_create(lv_screen_active());
52     lv_obj_set_style_text_font(time_label, &lv_font_montserrat_30, 0);
53     lv_subject_add_observer_obj(&time_subject, time_observer_cb, time_label, NULL);
54     lv_obj_set_pos(time_label, 24, 24);
55 
56     lv_obj_t * set_btn = lv_button_create(lv_screen_active());
57     lv_obj_set_pos(set_btn, 180, 24);
58     lv_obj_add_event_cb(set_btn, set_btn_clicked_event_cb, LV_EVENT_CLICKED, NULL);
59 
60     lv_obj_t * set_label = lv_label_create(set_btn);
61     lv_label_set_text(set_label, "Set");
62 
63     /*Update some subjects to see if the UI is updated as well*/
64     lv_subject_set_int(&hour_subject, 9);
65     lv_subject_set_int(&minute_subject, 30);
66     lv_subject_set_int(&am_pm_subject, TIME_PM);
67 }
68 
set_btn_clicked_event_cb(lv_event_t * e)69 static void set_btn_clicked_event_cb(lv_event_t * e)
70 {
71     lv_obj_t * set_btn = lv_event_get_target(e);
72     lv_obj_add_state(set_btn, LV_STATE_DISABLED);
73 
74     lv_obj_t * cont = lv_obj_create(lv_screen_active());
75     lv_obj_set_size(cont, lv_pct(100), LV_SIZE_CONTENT);
76     lv_obj_align(cont, LV_ALIGN_BOTTOM_MID, 0, 0);
77 
78     lv_obj_t * hour_roller = lv_roller_create(cont);
79     lv_obj_add_flag(hour_roller, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);
80     lv_subject_add_observer_obj(&format_subject, hour_roller_options_update, hour_roller, NULL);
81     lv_roller_bind_value(hour_roller, &hour_subject);
82     lv_obj_set_pos(hour_roller, 0, 0);
83 
84     lv_obj_t * min_roller = lv_roller_create(cont);
85     lv_roller_set_options(min_roller, minute_options, LV_ROLLER_MODE_NORMAL);
86     lv_roller_bind_value(min_roller, &minute_subject);
87     lv_obj_set_pos(min_roller, 64, 0);
88 
89     lv_obj_t * format_dropdown = lv_dropdown_create(cont);
90     lv_dropdown_set_options(format_dropdown, "12\n24");
91     lv_dropdown_bind_value(format_dropdown, &format_subject);
92     lv_obj_set_pos(format_dropdown, 128, 0);
93     lv_obj_set_width(format_dropdown, 80);
94 
95     lv_obj_t * am_pm_dropdown = lv_dropdown_create(cont);
96     lv_dropdown_set_options(am_pm_dropdown, "am\npm");
97     lv_dropdown_bind_value(am_pm_dropdown, &am_pm_subject);
98     lv_obj_bind_state_if_eq(am_pm_dropdown, &format_subject, LV_STATE_DISABLED, TIME_FORMAT_24);
99     lv_obj_set_pos(am_pm_dropdown, 128, 48);
100     lv_obj_set_width(am_pm_dropdown, 80);
101 
102     lv_obj_t * close_btn = lv_button_create(cont);
103     lv_obj_align(close_btn, LV_ALIGN_TOP_RIGHT, 0, 0);
104     /*Pass the set_btn as user_data to make it non-disabled on close*/
105     lv_obj_add_event_cb(close_btn, close_clicked_event_cb, LV_EVENT_CLICKED, set_btn);
106 
107     lv_obj_t * close_label = lv_label_create(close_btn);
108     lv_label_set_text(close_label, LV_SYMBOL_CLOSE);
109 }
110 
close_clicked_event_cb(lv_event_t * e)111 static void close_clicked_event_cb(lv_event_t * e)
112 {
113     lv_obj_t * set_btn = lv_event_get_user_data(e);
114     lv_obj_t * close_btn = lv_event_get_target(e);
115     lv_obj_t * cont = lv_obj_get_parent(close_btn);
116     lv_obj_remove_state(set_btn, LV_STATE_DISABLED);
117     lv_obj_delete(cont);
118 }
119 
120 /*Watch all related subject to display the current time correctly*/
time_observer_cb(lv_observer_t * observer,lv_subject_t * subject)121 static void time_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
122 {
123     int32_t hour = lv_subject_get_int(lv_subject_get_group_element(subject, 0));
124     int32_t minute = lv_subject_get_int(lv_subject_get_group_element(subject, 1));
125     int32_t format = lv_subject_get_int(lv_subject_get_group_element(subject, 2));
126     int32_t am_pm = lv_subject_get_int(lv_subject_get_group_element(subject, 3));
127 
128     lv_obj_t * label = lv_observer_get_target(observer);
129 
130     if(format == TIME_FORMAT_24) {
131         lv_label_set_text_fmt(label, "%" LV_PRId32 ":%02" LV_PRId32, hour, minute);
132     }
133     else {
134         lv_label_set_text_fmt(label, "%"LV_PRId32":%02"LV_PRId32" %s", hour + 1, minute, am_pm == TIME_AM ? "am" : "pm");
135     }
136 }
137 
138 /*Change the hour options on format change*/
hour_roller_options_update(lv_observer_t * observer,lv_subject_t * subject)139 static void hour_roller_options_update(lv_observer_t * observer, lv_subject_t * subject)
140 {
141     lv_obj_t * roller = lv_observer_get_target(observer);
142     int32_t prev_selected = lv_roller_get_selected(roller);
143     int32_t v = lv_subject_get_int(subject);
144     if(v == TIME_FORMAT_12) {
145         prev_selected--;
146         if(prev_selected > 12) prev_selected -= 12;
147         lv_roller_set_options(roller, hour12_options, LV_ROLLER_MODE_NORMAL);
148     }
149     else {
150         prev_selected++;
151         lv_roller_set_options(roller, hour24_options, LV_ROLLER_MODE_NORMAL);
152     }
153 
154     lv_roller_set_selected(roller, prev_selected, LV_ANIM_OFF);
155     lv_obj_send_event(roller, LV_EVENT_VALUE_CHANGED, NULL);
156 }
157 
158 #endif
159