1 /**
2  * @file lv_calendar_obj_dropdown.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_calendar_header_dropdown.h"
10 #if LV_USE_CALENDAR_HEADER_DROPDOWN
11 
12 #include "lv_calendar.h"
13 #include "../../../widgets/lv_dropdown.h"
14 #include "../../layouts/flex/lv_flex.h"
15 
16 /*********************
17  *      DEFINES
18  *********************/
19 
20 /**********************
21  *      TYPEDEFS
22  **********************/
23 
24 /**********************
25  *  STATIC PROTOTYPES
26  **********************/
27 static void my_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
28 static void year_event_cb(lv_event_t * e);
29 static void month_event_cb(lv_event_t * e);
30 static void value_changed_event_cb(lv_event_t * e);
31 
32 /**********************
33  *  STATIC VARIABLES
34  **********************/
35 const lv_obj_class_t lv_calendar_header_dropdown_class = {
36     .base_class = &lv_obj_class,
37     .width_def = LV_PCT(100),
38     .height_def = LV_SIZE_CONTENT,
39     .constructor_cb = my_constructor
40 };
41 
42 static const char * month_list = "01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12";
43 static const char * year_list = {
44     "2023\n2022\n2021\n"
45     "2020\n2019\n2018\n2017\n2016\n2015\n2014\n2013\n2012\n2011\n2010\n2009\n2008\n2007\n2006\n2005\n2004\n2003\n2002\n2001\n"
46     "2000\n1999\n1998\n1997\n1996\n1995\n1994\n1993\n1992\n1991\n1990\n1989\n1988\n1987\n1986\n1985\n1984\n1983\n1982\n1981\n"
47     "1980\n1979\n1978\n1977\n1976\n1975\n1974\n1973\n1972\n1971\n1970\n1969\n1968\n1967\n1966\n1965\n1964\n1963\n1962\n1961\n"
48     "1960\n1959\n1958\n1957\n1956\n1955\n1954\n1953\n1952\n1951\n1950\n1949\n1948\n1947\n1946\n1945\n1944\n1943\n1942\n1941\n"
49     "1940\n1939\n1938\n1937\n1936\n1935\n1934\n1933\n1932\n1931\n1930\n1929\n1928\n1927\n1926\n1925\n1924\n1923\n1922\n1921\n"
50     "1920\n1919\n1918\n1917\n1916\n1915\n1914\n1913\n1912\n1911\n1910\n1909\n1908\n1907\n1906\n1905\n1904\n1903\n1902\n1901"
51 };
52 
53 /**********************
54  *      MACROS
55  **********************/
56 
57 /**********************
58  *   GLOBAL FUNCTIONS
59  **********************/
60 
lv_calendar_header_dropdown_create(lv_obj_t * parent)61 lv_obj_t * lv_calendar_header_dropdown_create(lv_obj_t * parent)
62 {
63     lv_obj_t * obj = lv_obj_class_create_obj(&lv_calendar_header_dropdown_class, parent);
64     lv_obj_class_init_obj(obj);
65 
66     return obj;
67 }
68 
lv_calendar_header_dropdown_set_year_list(lv_obj_t * parent,const char * years_list)69 void lv_calendar_header_dropdown_set_year_list(lv_obj_t * parent, const char * years_list)
70 {
71     bool child_found = false;
72     uint32_t idx = 0;
73     lv_obj_t * child = NULL;
74 
75     const uint32_t calendar_child_count = lv_obj_get_child_cnt(parent);
76 
77     /* Search for the header dropdown */
78     for(idx = 0; idx < calendar_child_count; idx++) {
79         child = lv_obj_get_child(parent, idx);
80         if(lv_obj_check_type(child, &lv_calendar_header_dropdown_class)) {
81             child_found = true;
82             break;
83         }
84     }
85 
86     if(!child_found) return;
87 
88     child_found = false;
89     const uint32_t header_child_count = lv_obj_get_child_cnt(child);
90 
91     /* Search for the year dropdown */
92     for(idx = 0; idx < header_child_count; idx++) {
93         child = lv_obj_get_child(child, idx);
94         if(lv_obj_check_type(child, &lv_dropdown_class)) {
95             child_found = true;
96             break;
97         }
98     }
99 
100     if(!child_found) return;
101 
102     lv_dropdown_clear_options(child);
103     lv_dropdown_set_options(child, years_list);
104 
105     lv_obj_invalidate(parent);
106 }
107 
108 /**********************
109  *  STATIC FUNCTIONS
110  **********************/
111 
my_constructor(const lv_obj_class_t * class_p,lv_obj_t * obj)112 static void my_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
113 {
114     LV_TRACE_OBJ_CREATE("begin");
115 
116     LV_UNUSED(class_p);
117 
118     lv_obj_t * calendar = lv_obj_get_parent(obj);
119     lv_obj_move_to_index(obj, 0);
120     lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW);
121 
122     lv_obj_t * year_dd = lv_dropdown_create(obj);
123     lv_dropdown_set_options(year_dd, year_list);
124     lv_obj_add_event_cb(year_dd, year_event_cb, LV_EVENT_VALUE_CHANGED, calendar);
125     lv_obj_set_flex_grow(year_dd, 1);
126 
127     lv_obj_t * month_dd = lv_dropdown_create(obj);
128     lv_dropdown_set_options(month_dd, month_list);
129     lv_obj_add_event_cb(month_dd, month_event_cb, LV_EVENT_VALUE_CHANGED, calendar);
130     lv_obj_set_flex_grow(month_dd, 1);
131 
132     lv_obj_add_event_cb(obj, value_changed_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
133     /*Refresh the drop downs*/
134     lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL);
135 }
136 
month_event_cb(lv_event_t * e)137 static void month_event_cb(lv_event_t * e)
138 {
139     lv_obj_t * dropdown = lv_event_get_target(e);
140     lv_obj_t * calendar = lv_event_get_user_data(e);
141 
142     uint16_t sel = lv_dropdown_get_selected(dropdown);
143 
144     const lv_calendar_date_t * d;
145     d = lv_calendar_get_showed_date(calendar);
146     lv_calendar_date_t newd = *d;
147     newd.month = sel + 1;
148 
149     lv_calendar_set_showed_date(calendar, newd.year, newd.month);
150 }
151 
year_event_cb(lv_event_t * e)152 static void year_event_cb(lv_event_t * e)
153 {
154     lv_obj_t * dropdown = lv_event_get_target(e);
155     lv_obj_t * calendar = lv_event_get_user_data(e);
156 
157     uint16_t sel = lv_dropdown_get_selected(dropdown);
158 
159     const lv_calendar_date_t * d;
160     d = lv_calendar_get_showed_date(calendar);
161     lv_calendar_date_t newd = *d;
162 
163     /* Get the first year on the options list
164      * NOTE: Assumes the first 4 digits in the option list are numbers */
165     const char * year_p = lv_dropdown_get_options(dropdown);
166     const uint32_t year = (year_p[0] - '0') * 1000 + (year_p[1] - '0') * 100 + (year_p[2] - '0') * 10 +
167                           (year_p[3] - '0');
168 
169     newd.year = year - sel;
170 
171     lv_calendar_set_showed_date(calendar, newd.year, newd.month);
172 }
173 
value_changed_event_cb(lv_event_t * e)174 static void value_changed_event_cb(lv_event_t * e)
175 {
176     lv_obj_t * header = lv_event_get_target(e);
177     lv_obj_t * calendar = lv_obj_get_parent(header);
178     const lv_calendar_date_t * cur_date = lv_calendar_get_showed_date(calendar);
179 
180     lv_obj_t * year_dd = lv_obj_get_child(header, 0);
181 
182     /* Get the first year on the options list
183      * NOTE: Assumes the first 4 digits in the option list are numbers */
184     const char * year_p = lv_dropdown_get_options(year_dd);
185     const uint32_t year = (year_p[0] - '0') * 1000 + (year_p[1] - '0') * 100 + (year_p[2] - '0') * 10 +
186                           (year_p[3] - '0');
187 
188     lv_dropdown_set_selected(year_dd, year - cur_date->year);
189 
190     lv_obj_t * month_dd = lv_obj_get_child(header, 1);
191     lv_dropdown_set_selected(month_dd, cur_date->month - 1);
192 }
193 
194 #endif /*LV_USE_CALENDAR_HEADER_ARROW*/
195 
196