1 #include <Elementary.h>
4 #include "elementary_config.h"
7 #define DATETIME_FIELD_COUNT 6
8 #define FIELD_FORMAT_LEN 3
9 #define DISKSELECTOR_MIN_ITEMS 4
10 #define BUFF_SIZE 1024
12 typedef struct _Ctxpopup_Module_Data Ctxpopup_Module_Data;
13 typedef struct _DiskItem_Data DiskItem_Data;
15 struct _Ctxpopup_Module_Data
17 Elm_Datetime_Module_Data mod_data;
18 Evas_Object *ctxpopup;
19 unsigned char still_in : 1;
24 Ctxpopup_Module_Data *ctx_mod;
25 Elm_Datetime_Field_Type sel_field_type;
26 unsigned int sel_field_value;
30 _diskselector_item_free_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
36 _ctxpopup_dismissed_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__ )
38 Evas_Object *diskselector;
40 diskselector = elm_object_content_unset(obj);
41 if (diskselector) evas_object_del(diskselector);
45 _datetime_resize_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__,
46 void *event_info __UNUSED__)
48 Ctxpopup_Module_Data *ctx_mod;
50 ctx_mod = (Ctxpopup_Module_Data *)data;
53 evas_object_hide(ctx_mod->ctxpopup);
57 _ctxpopup_parent_resize_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__,
58 void *event_info __UNUSED__)
60 Ctxpopup_Module_Data *ctx_mod;
62 ctx_mod = (Ctxpopup_Module_Data *)data;
64 elm_ctxpopup_hover_parent_set(ctx_mod->ctxpopup, elm_widget_top_get(ctx_mod->mod_data.base));
68 _datetime_move_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__,
69 void *event_info __UNUSED__)
71 Ctxpopup_Module_Data *ctx_mod;
73 ctx_mod = (Ctxpopup_Module_Data *)data;
76 evas_object_hide(ctx_mod->ctxpopup);
80 _field_value_set(struct tm *tim, Elm_Datetime_Field_Type field_type, int val)
82 if (field_type >= DATETIME_FIELD_COUNT - 1) return;
84 int *timearr[]= { &tim->tm_year, &tim->tm_mon, &tim->tm_mday, &tim->tm_hour, &tim->tm_min };
85 *timearr[field_type] = val;
89 _field_value_get(struct tm *tim, Elm_Datetime_Field_Type field_type)
91 if (field_type >= DATETIME_FIELD_COUNT - 1) return -1;
93 int *timearr[]= { &tim->tm_year, &tim->tm_mon, &tim->tm_mday, &tim->tm_hour, &tim->tm_min };
94 return (*timearr[field_type]);
98 _diskselector_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
100 DiskItem_Data *disk_data;
104 disk_data = (DiskItem_Data *)data;
105 if (!disk_data || !(disk_data->ctx_mod)) return;
107 elm_datetime_value_get(disk_data->ctx_mod->mod_data.base, &curr_time);
108 fmt = disk_data->ctx_mod->mod_data.field_format_get(disk_data->ctx_mod->mod_data.base, disk_data->sel_field_type);
109 if ((disk_data->sel_field_type == ELM_DATETIME_HOUR) && ((!strncmp(fmt, "%I", FIELD_FORMAT_LEN)) ||
110 (!strncmp(fmt, "%l", FIELD_FORMAT_LEN))) && (curr_time.tm_hour >= 12))
111 disk_data->sel_field_value += 12;
112 _field_value_set(&curr_time, disk_data->sel_field_type, disk_data->sel_field_value);
113 elm_datetime_value_set(disk_data->ctx_mod->mod_data.base, &curr_time);
114 evas_object_hide(disk_data->ctx_mod->ctxpopup);
118 _ampm_clicked_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
120 Ctxpopup_Module_Data *ctx_mod;
123 ctx_mod = (Ctxpopup_Module_Data *)data;
124 if (!ctx_mod) return;
126 elm_datetime_value_get(ctx_mod->mod_data.base, &curr_time);
127 if (curr_time.tm_hour >= 12) curr_time.tm_hour -= 12;
128 else curr_time.tm_hour += 12;
129 elm_datetime_value_set(ctx_mod->mod_data.base, &curr_time);
133 _field_clicked_cb(void *data, Evas_Object *obj)
135 Ctxpopup_Module_Data *ctx_mod;
136 Evas_Object *diskselector;
137 Elm_Object_Item *item;
138 DiskItem_Data *disk_data;
139 Elm_Datetime_Field_Type field_type;
142 char buf[BUFF_SIZE], label[BUFF_SIZE];
144 int idx, min, max, val;
145 unsigned int display_item_num, text_len = 0;
146 Evas_Coord x = 0, y = 0, w = 0, h = 0, width;
148 ctx_mod = (Ctxpopup_Module_Data *)data;
149 if (!ctx_mod || !ctx_mod->ctxpopup) return;
151 // because of the diskselector behaviour, it is being recreated
152 diskselector = elm_diskselector_add(elm_widget_top_get(ctx_mod->mod_data.base));
153 snprintf(buf, sizeof(buf), "datetime/%s", elm_object_style_get(obj));
154 elm_object_style_set(diskselector, buf);
155 elm_object_content_set(ctx_mod->ctxpopup, diskselector);
158 localtime_r(&t, &time1);
160 field_type = (Elm_Datetime_Field_Type )evas_object_data_get(obj, "_field_type");
161 fmt = ctx_mod->mod_data.field_format_get(ctx_mod->mod_data.base, field_type);
162 elm_datetime_value_get(ctx_mod->mod_data.base, &time1);
163 val = _field_value_get(&time1, field_type);
164 ctx_mod->mod_data.field_limit_get(ctx_mod->mod_data.base, field_type, &min, &max);
166 time1.tm_mday = 1; // To avoid month wrapping, set the first day of the month to start with.
168 if ((field_type == ELM_DATETIME_HOUR) && ((!strncmp(fmt, "%I", FIELD_FORMAT_LEN)) ||
169 (!strncmp(fmt, "%l", FIELD_FORMAT_LEN))))
171 if (max >= 12) max -= 12;
172 if (val >= 12) val -= 12;
173 if (min >= 12) min -= 12;
175 for (idx = min; idx <= max; idx++)
177 _field_value_set(&time1, field_type, idx);
178 strftime(label, BUFF_SIZE, fmt, &time1);
179 if (strlen(label) > text_len) text_len = strlen(label);
182 item = elm_diskselector_item_append(diskselector, label, NULL, NULL, NULL);
183 elm_diskselector_item_selected_set(item, EINA_TRUE);
187 disk_data = (DiskItem_Data *) malloc (sizeof(DiskItem_Data));
188 disk_data->ctx_mod = ctx_mod;
189 disk_data->sel_field_type = field_type;
190 disk_data->sel_field_value = idx;
191 item = elm_diskselector_item_append(diskselector, label, NULL, _diskselector_cb, disk_data);
192 elm_object_item_del_cb_set(item, _diskselector_item_free_cb);
195 elm_diskselector_side_text_max_length_set(diskselector, text_len);
197 evas_object_geometry_get(obj, &x, &y, &w, &h);
198 evas_object_geometry_get(elm_widget_top_get(ctx_mod->mod_data.base), NULL, NULL, &width, NULL);
199 evas_object_size_hint_min_set(ctx_mod->ctxpopup, width, -1);
200 display_item_num = width / (w + elm_config_finger_size_get());
201 // always display even number of items to avoid autoselection
202 if (display_item_num % 2) display_item_num -= 1;
203 if (display_item_num < DISKSELECTOR_MIN_ITEMS)
204 display_item_num = DISKSELECTOR_MIN_ITEMS;
205 elm_diskselector_display_item_num_set(diskselector, display_item_num);
206 elm_diskselector_round_enabled_set(diskselector, EINA_TRUE);
208 elm_ctxpopup_direction_priority_set(ctx_mod->ctxpopup, ELM_CTXPOPUP_DIRECTION_DOWN,
209 ELM_CTXPOPUP_DIRECTION_UP, -1, -1);
210 evas_object_move(ctx_mod->ctxpopup, (x+w/2), (y+h));
212 // if the direction of Ctxpopup is upwards, move it to the top of datetime
213 if (elm_ctxpopup_direction_get (ctx_mod->ctxpopup) == ELM_CTXPOPUP_DIRECTION_UP)
215 elm_ctxpopup_direction_priority_set(ctx_mod->ctxpopup, ELM_CTXPOPUP_DIRECTION_UP,
216 ELM_CTXPOPUP_DIRECTION_DOWN, -1, -1);
217 evas_object_move(ctx_mod->ctxpopup, (x+w/2), y);
219 evas_object_show(ctx_mod->ctxpopup);
223 _field_mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
225 Evas_Event_Mouse_Down *ev;
226 Ctxpopup_Module_Data *ctx_mod;
229 ctx_mod = (Ctxpopup_Module_Data *)data;
230 if (!ctx_mod || !ctx_mod->ctxpopup) return;
232 if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
234 ctx_mod->still_in = 1;
239 _field_mouse_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
241 Evas_Event_Mouse_Move *ev;
242 Ctxpopup_Module_Data *ctx_mod;
245 ctx_mod = (Ctxpopup_Module_Data *)data;
246 if (!ctx_mod || !ctx_mod->ctxpopup) return;
248 if (ctx_mod->still_in)
251 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
252 ctx_mod->still_in = 0;
255 Evas_Coord x, y, w, h;
257 evas_object_geometry_get(obj, &x, &y, &w, &h);
258 if ((ev->cur.canvas.x < x) || (ev->cur.canvas.y < y) ||
259 (ev->cur.canvas.x >= (x + w)) || (ev->cur.canvas.y >= (y + h)))
260 ctx_mod->still_in = 0;
265 if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
267 Evas_Coord x, y, w, h;
269 evas_object_geometry_get(obj, &x, &y, &w, &h);
270 if ((ev->cur.canvas.x >= x) && (ev->cur.canvas.y >= y) &&
271 (ev->cur.canvas.x < (x + w)) && (ev->cur.canvas.y < (y + h)))
272 ctx_mod->still_in = 1;
278 _field_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
280 Evas_Event_Mouse_Up *ev;
281 Ctxpopup_Module_Data *ctx_mod;
284 ctx_mod = (Ctxpopup_Module_Data *)data;
285 if (!ctx_mod || !ctx_mod->ctxpopup) return;
287 if (ctx_mod->still_in)
289 _field_clicked_cb(ctx_mod, obj);
291 ctx_mod->still_in = 0;
294 // module fucns for the specific module type
296 field_value_display(Elm_Datetime_Module_Data *module_data, Evas_Object *obj)
298 Ctxpopup_Module_Data *ctx_mod;
299 Elm_Datetime_Field_Type field_type;
301 char buf[BUFF_SIZE] = {0};
304 ctx_mod = (Ctxpopup_Module_Data *)module_data;
305 if (!ctx_mod || !obj) return;
307 elm_datetime_value_get(ctx_mod->mod_data.base, &tim);
308 field_type = (Elm_Datetime_Field_Type )evas_object_data_get(obj, "_field_type");
309 fmt = ctx_mod->mod_data.field_format_get(ctx_mod->mod_data.base, field_type);
310 strftime(buf, sizeof(buf), fmt, &tim);
312 // If a locale doesn't support AM/PM strings, set the default values
313 if ((buf[0] == 0) && (!strncmp(fmt, "%p", BUFF_SIZE) || strncmp(fmt, "%P", BUFF_SIZE)))
315 if (tim.tm_hour < 12) strncpy(buf, "AM", BUFF_SIZE);
316 else strncpy(buf, "PM", BUFF_SIZE);
319 elm_object_text_set(obj, buf);
323 field_create(Elm_Datetime_Module_Data *module_data, Elm_Datetime_Field_Type field_type)
325 Ctxpopup_Module_Data *ctx_mod;
326 Evas_Object *field_obj;
328 ctx_mod = (Ctxpopup_Module_Data *)module_data;
329 if (!ctx_mod) return NULL;
331 if (field_type == ELM_DATETIME_AMPM)
333 field_obj = elm_button_add(ctx_mod->mod_data.base);
334 elm_object_style_set(field_obj, "datetime_ampm/default");
335 evas_object_smart_callback_add(field_obj, "clicked", _ampm_clicked_cb, ctx_mod);
339 field_obj = elm_label_add(ctx_mod->mod_data.base);
340 evas_object_event_callback_add(field_obj, EVAS_CALLBACK_MOUSE_DOWN, _field_mouse_down_cb, ctx_mod);
341 evas_object_event_callback_add(field_obj, EVAS_CALLBACK_MOUSE_MOVE, _field_mouse_move_cb, ctx_mod);
342 evas_object_event_callback_add(field_obj, EVAS_CALLBACK_MOUSE_UP, _field_mouse_up_cb, ctx_mod);
343 elm_object_style_set(field_obj,"datetime");
345 evas_object_data_set(field_obj, "_field_type", (void *)field_type);
349 EAPI Elm_Datetime_Module_Data *
350 obj_hook(Evas_Object *obj)
352 Ctxpopup_Module_Data *ctx_mod;
355 ctx_mod = ELM_NEW(Ctxpopup_Module_Data);
356 if (!ctx_mod) return NULL;
358 ctx_mod->ctxpopup = elm_ctxpopup_add(elm_widget_top_get(obj));
359 snprintf(buf, sizeof(buf), "datetime/%s", elm_object_style_get(obj));
360 elm_object_style_set(ctx_mod->ctxpopup, buf);
361 elm_ctxpopup_horizontal_set(ctx_mod->ctxpopup, EINA_TRUE);
362 evas_object_size_hint_weight_set(ctx_mod->ctxpopup, EVAS_HINT_EXPAND,
364 evas_object_size_hint_align_set(ctx_mod->ctxpopup, EVAS_HINT_FILL, 0.5);
365 evas_object_smart_callback_add(ctx_mod->ctxpopup, "dismissed",
366 _ctxpopup_dismissed_cb, ctx_mod);
367 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
368 _datetime_resize_cb, ctx_mod);
369 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
370 _datetime_move_cb, ctx_mod);
371 evas_object_event_callback_add(elm_widget_top_get(obj), EVAS_CALLBACK_RESIZE,
372 _ctxpopup_parent_resize_cb, ctx_mod);
374 return ((Elm_Datetime_Module_Data*)ctx_mod);
378 obj_unhook(Elm_Datetime_Module_Data *module_data)
380 Ctxpopup_Module_Data *ctx_mod;
382 ctx_mod = (Ctxpopup_Module_Data *)module_data;
383 if (!ctx_mod) return;
385 evas_object_event_callback_del_full(elm_widget_top_get(module_data->base),
386 EVAS_CALLBACK_RESIZE,
387 _ctxpopup_parent_resize_cb, ctx_mod);
388 if (ctx_mod->ctxpopup)
389 evas_object_del(ctx_mod->ctxpopup);
398 // module api funcs needed
400 elm_modapi_init(void *m __UNUSED__)
402 return 1; // succeed always
406 elm_modapi_shutdown(void *m __UNUSED__)
408 return 1; // succeed always