summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmitesh Singh <amitesh.sh@samsung.com>2016-11-03 12:00:17 +0530
committerAmitesh Singh <amitesh.sh@samsung.com>2016-11-03 12:00:17 +0530
commit0bcb0302fb647b43cef4e633cf0c0b16e5521e04 (patch)
tree8a8740ec411786877b242dd7fbbfd93eb6fe1ac2
parentb0d2e987f3a37291cd1e1090ba0812c3b4a0ed67 (diff)
efl_ui_clock: Merge datetime/dayselector/clock widgets into efl_ui_clock.
Summary: Datetime widget is module based, so datetime widget is used as base for efl_ui_clock and merged dayselector/clock features into efl_ui_clock. Added day selection and seconds support in efl_ui_clock. Added clock features like auto updation of time, stop timer etc in efl_ui_clock. Added API to enable/disable edit_mode. efl_ui_clock can be configurable to display either only day/date/time or display any two of them or display all three. Added efl_ui_clock.c and test_ui_clock.c. Theme and Module is added in another patch by Amitesh. Original author is Yeshwanth <r.yeshwanth@samsung.com>. I have polished this patch a bit and make it compatible with current EFL code. Test Plan: test_ui_clock Reviewers: bu5hm4n, tasn, yashu21985, jpeg, cedric, raster Subscribers: CHAN, woohyun Differential Revision: https://phab.enlightenment.org/D3938
-rw-r--r--config/default/base.src.in4
-rw-r--r--config/mobile/base.src.in4
-rw-r--r--config/standard/base.src.in4
-rw-r--r--src/Makefile_Elementary.am3
-rw-r--r--src/bin/elementary/Makefile.am1
-rw-r--r--src/bin/elementary/test.c2
-rw-r--r--src/bin/elementary/test_ui_clock.c117
-rw-r--r--src/lib/elementary/Elementary.h1
-rw-r--r--src/lib/elementary/efl_ui_clock.c1189
-rw-r--r--src/lib/elementary/efl_ui_clock.eo260
-rw-r--r--src/lib/elementary/efl_ui_clock.h204
-rw-r--r--src/lib/elementary/efl_ui_clock_private.h130
-rw-r--r--src/lib/elementary/elm_config.c4
13 files changed, 1917 insertions, 6 deletions
diff --git a/config/default/base.src.in b/config/default/base.src.in
index 90188f3827..9f27fd4f5a 100644
--- a/config/default/base.src.in
+++ b/config/default/base.src.in
@@ -1,5 +1,5 @@
1group "Elm_Config" struct { 1group "Elm_Config" struct {
2 value "config_version" int: 131084; 2 value "config_version" int: 131085;
3 value "engine" string: ""; 3 value "engine" string: "";
4 value "vsync" uchar: 0; 4 value "vsync" uchar: 0;
5 value "thumbscroll_enable" uchar: 1; 5 value "thumbscroll_enable" uchar: 1;
@@ -39,7 +39,7 @@ group "Elm_Config" struct {
39 value "finger_size" int: 10; 39 value "finger_size" int: 10;
40 value "fps" double: 60.0; 40 value "fps" double: 60.0;
41 value "theme" string: "default"; 41 value "theme" string: "default";
42 value "modules" string: "prefs>prefs_iface:access_output>access/api:datetime_input_ctxpopup>datetime/api"; 42 value "modules" string: "prefs>prefs_iface:access_output>access/api:datetime_input_ctxpopup>datetime/api:clock_input_ctxpopup>clock/api";
43 value "tooltip_delay" double: 1.0; 43 value "tooltip_delay" double: 1.0;
44 value "cursor_engine_only" uchar: 0; 44 value "cursor_engine_only" uchar: 0;
45 value "focus_highlight_enable" uchar: 0; 45 value "focus_highlight_enable" uchar: 0;
diff --git a/config/mobile/base.src.in b/config/mobile/base.src.in
index 5619970c93..fedba06f64 100644
--- a/config/mobile/base.src.in
+++ b/config/mobile/base.src.in
@@ -1,5 +1,5 @@
1group "Elm_Config" struct { 1group "Elm_Config" struct {
2 value "config_version" int: 131084; 2 value "config_version" int: 131085;
3 value "engine" string: ""; 3 value "engine" string: "";
4 value "vsync" uchar: 0; 4 value "vsync" uchar: 0;
5 value "thumbscroll_enable" uchar: 1; 5 value "thumbscroll_enable" uchar: 1;
@@ -39,7 +39,7 @@ group "Elm_Config" struct {
39 value "finger_size" int: 40; 39 value "finger_size" int: 40;
40 value "fps" double: 60.0; 40 value "fps" double: 60.0;
41 value "theme" string: "default"; 41 value "theme" string: "default";
42 value "modules" string: "prefs>prefs_iface:access_output>access/api:datetime_input_ctxpopup>datetime/api"; 42 value "modules" string: "prefs>prefs_iface:access_output>access/api:datetime_input_ctxpopup>datetime/api:clock_input_ctxpopup>clock/api";
43 value "tooltip_delay" double: 1.0; 43 value "tooltip_delay" double: 1.0;
44 value "cursor_engine_only" uchar: 0; 44 value "cursor_engine_only" uchar: 0;
45 value "focus_highlight_enable" uchar: 0; 45 value "focus_highlight_enable" uchar: 0;
diff --git a/config/standard/base.src.in b/config/standard/base.src.in
index 849185f6e5..b201a3edd9 100644
--- a/config/standard/base.src.in
+++ b/config/standard/base.src.in
@@ -1,5 +1,5 @@
1group "Elm_Config" struct { 1group "Elm_Config" struct {
2 value "config_version" int: 131084; 2 value "config_version" int: 131085;
3 value "engine" string: ""; 3 value "engine" string: "";
4 value "vsync" uchar: 0; 4 value "vsync" uchar: 0;
5 value "thumbscroll_enable" uchar: 0; 5 value "thumbscroll_enable" uchar: 0;
@@ -39,7 +39,7 @@ group "Elm_Config" struct {
39 value "finger_size" int: 10; 39 value "finger_size" int: 10;
40 value "fps" double: 60.0; 40 value "fps" double: 60.0;
41 value "theme" string: "default"; 41 value "theme" string: "default";
42 value "modules" string: "prefs>prefs_iface:access_output>access/api:datetime_input_ctxpopup>datetime/api"; 42 value "modules" string: "prefs>prefs_iface:access_output>access/api:datetime_input_ctxpopup>datetime/api:clock_input_ctxpopup>clock/api";
43 value "tooltip_delay" double: 1.0; 43 value "tooltip_delay" double: 1.0;
44 value "cursor_engine_only" uchar: 0; 44 value "cursor_engine_only" uchar: 0;
45 value "focus_highlight_enable" uchar: 0; 45 value "focus_highlight_enable" uchar: 0;
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index dd7813423d..d2beac4358 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -121,6 +121,7 @@ elm_public_eolian_files = \
121# Private classes (not exposed or shipped) 121# Private classes (not exposed or shipped)
122elm_private_eolian_files = \ 122elm_private_eolian_files = \
123 lib/elementary/efl_ui_internal_text_interactive.eo \ 123 lib/elementary/efl_ui_internal_text_interactive.eo \
124 lib/elementary/efl_ui_clock.eo \
124 $(NULL) 125 $(NULL)
125 126
126# Legacy classes - not part of public EO API 127# Legacy classes - not part of public EO API
@@ -662,6 +663,7 @@ lib_elementary_libelementary_la_SOURCES = \
662 lib/elementary/efl_ui_grid_static.c \ 663 lib/elementary/efl_ui_grid_static.c \
663 lib/elementary/efl_ui_grid_private.h \ 664 lib/elementary/efl_ui_grid_private.h \
664 lib/elementary/efl_ui_text.c \ 665 lib/elementary/efl_ui_text.c \
666 lib/elementary/efl_ui_clock.c \
665 $(NULL) 667 $(NULL)
666 668
667 669
@@ -823,6 +825,7 @@ bin/elementary/test_tooltip.c \
823bin/elementary/test_transit.c \ 825bin/elementary/test_transit.c \
824bin/elementary/test_transit_bezier.c \ 826bin/elementary/test_transit_bezier.c \
825bin/elementary/test_ui_box.c \ 827bin/elementary/test_ui_box.c \
828bin/elementary/test_ui_clock.c \
826bin/elementary/test_ui_grid.c \ 829bin/elementary/test_ui_grid.c \
827bin/elementary/test_video.c \ 830bin/elementary/test_video.c \
828bin/elementary/test_weather.c \ 831bin/elementary/test_weather.c \
diff --git a/src/bin/elementary/Makefile.am b/src/bin/elementary/Makefile.am
index 8f64a68c1a..3bb7ea9279 100644
--- a/src/bin/elementary/Makefile.am
+++ b/src/bin/elementary/Makefile.am
@@ -125,6 +125,7 @@ test_toolbar.c \
125test_tooltip.c \ 125test_tooltip.c \
126test_transit.c \ 126test_transit.c \
127test_transit_bezier.c \ 127test_transit_bezier.c \
128test_ui_clock.c \
128test_video.c \ 129test_video.c \
129test_weather.c \ 130test_weather.c \
130test_web.c \ 131test_web.c \
diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c
index 0c3fa6c01d..36f2e14721 100644
--- a/src/bin/elementary/test.c
+++ b/src/bin/elementary/test.c
@@ -254,6 +254,7 @@ void test_naviframe3(void *data, Evas_Object *obj, void *event_info);
254void test_naviframe_complex(void *data, Evas_Object *obj, void *event_info); 254void test_naviframe_complex(void *data, Evas_Object *obj, void *event_info);
255//void test_factory(void *data, Evas_Object *obj, void *event_info); 255//void test_factory(void *data, Evas_Object *obj, void *event_info);
256void test_datetime(void *data, Evas_Object *obj, void *event_info); 256void test_datetime(void *data, Evas_Object *obj, void *event_info);
257void test_ui_clock(void *data, Evas_Object *obj, void *event_info);
257void test_popup(void *data, Evas_Object *obj, void *event_info); 258void test_popup(void *data, Evas_Object *obj, void *event_info);
258void test_dayselector(void *data, Evas_Object *obj, void *event_info); 259void test_dayselector(void *data, Evas_Object *obj, void *event_info);
259void test_image(void *data, Evas_Object *obj, void *event_info); 260void test_image(void *data, Evas_Object *obj, void *event_info);
@@ -917,6 +918,7 @@ add_tests:
917 ADD_TEST(NULL, "Times & Dates", "Clock Edit 2", test_clock_edit2); 918 ADD_TEST(NULL, "Times & Dates", "Clock Edit 2", test_clock_edit2);
918 ADD_TEST(NULL, "Times & Dates", "Clock Pause", test_clock_pause); 919 ADD_TEST(NULL, "Times & Dates", "Clock Pause", test_clock_pause);
919 ADD_TEST(NULL, "Times & Dates", "Datetime", test_datetime); 920 ADD_TEST(NULL, "Times & Dates", "Datetime", test_datetime);
921 ADD_TEST(NULL, "Times & Dates", "Ui.Clock", test_ui_clock);
920 922
921 //------------------------------// 923 //------------------------------//
922 ADD_TEST(NULL, "Text", "Label", test_label); 924 ADD_TEST(NULL, "Text", "Label", test_label);
diff --git a/src/bin/elementary/test_ui_clock.c b/src/bin/elementary/test_ui_clock.c
new file mode 100644
index 0000000000..47f7f6cc77
--- /dev/null
+++ b/src/bin/elementary/test_ui_clock.c
@@ -0,0 +1,117 @@
1#ifdef HAVE_CONFIG_H
2#include "elementary_config.h"
3#endif
4#include <Elementary.h>
5
6/* A simple test, just displaying clock in its default format */
7
8Evas_Object *dt1, *dt2, *dt3, *dt4;
9
10static void
11_changed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
12{
13 printf("Clock value is changed\n");
14}
15
16static void
17_bt_clicked(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
18{
19 time_t t;
20 struct tm new_time;
21
22 t = time(NULL);
23 localtime_r(&t, &new_time);
24
25 new_time.tm_year = 85;
26 new_time.tm_mon = 9;
27 new_time.tm_mday = 26;
28 new_time.tm_hour = 9;
29 new_time.tm_min = 0;
30 efl_ui_clock_field_visible_set(dt1, EFL_UI_CLOCK_TYPE_HOUR, EINA_TRUE);
31 efl_ui_clock_field_visible_set(dt1, EFL_UI_CLOCK_TYPE_MINUTE, EINA_TRUE);
32 efl_ui_clock_field_visible_set(dt1, EFL_UI_CLOCK_TYPE_AMPM, EINA_TRUE);
33 efl_ui_clock_field_visible_set(dt1, EFL_UI_CLOCK_TYPE_SECOND, EINA_TRUE);
34 efl_ui_clock_field_visible_set(dt1, EFL_UI_CLOCK_TYPE_DAY, EINA_TRUE);
35
36 efl_ui_clock_value_set(dt1, &new_time);
37 elm_object_disabled_set(dt1, EINA_TRUE);
38
39 elm_object_disabled_set(obj, EINA_TRUE);
40 evas_object_del(dt2);
41 evas_object_del(dt3);
42 dt2 = dt3 = NULL;
43}
44
45void
46test_ui_clock(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
47{
48 Evas_Object *win, *bx, *bt, *lb;
49
50 win = elm_win_util_standard_add("ui_clock", "ui_clock");
51 elm_win_autodel_set(win, EINA_TRUE);
52
53 bx = elm_box_add(win);
54 evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
55 elm_win_resize_object_add(win, bx);
56 elm_box_horizontal_set(bx, EINA_FALSE);
57 evas_object_show(bx);
58 evas_object_size_hint_min_set(bx, 360, 240);
59
60 dt1 = efl_add(EFL_UI_CLOCK_CLASS, bx);
61 evas_object_size_hint_weight_set(dt1, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
62 evas_object_size_hint_align_set(dt1, EVAS_HINT_FILL, 0.5);
63 efl_ui_clock_field_visible_set(dt1, EFL_UI_CLOCK_TYPE_HOUR, EINA_FALSE);
64 efl_ui_clock_field_visible_set(dt1, EFL_UI_CLOCK_TYPE_MINUTE, EINA_FALSE);
65 efl_ui_clock_field_visible_set(dt1, EFL_UI_CLOCK_TYPE_AMPM, EINA_FALSE);
66 efl_ui_clock_field_visible_set(dt1, EFL_UI_CLOCK_TYPE_SECOND, EINA_FALSE);
67 efl_ui_clock_field_visible_set(dt1, EFL_UI_CLOCK_TYPE_DAY, EINA_FALSE);
68 efl_ui_clock_pause_set(dt1, EINA_TRUE);
69 elm_box_pack_end(bx, dt1);
70 evas_object_smart_callback_add(dt1, "changed", _changed_cb, NULL);
71 evas_object_show(dt1);
72
73 dt2 = efl_add(EFL_UI_CLOCK_CLASS, bx);
74 evas_object_size_hint_weight_set(dt2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
75 evas_object_size_hint_align_set(dt2, EVAS_HINT_FILL, 0.5);
76 efl_ui_clock_field_visible_set(dt2, EFL_UI_CLOCK_TYPE_YEAR, EINA_FALSE);
77 efl_ui_clock_field_visible_set(dt2, EFL_UI_CLOCK_TYPE_MONTH, EINA_FALSE);
78 efl_ui_clock_field_visible_set(dt2, EFL_UI_CLOCK_TYPE_DATE, EINA_FALSE);
79 efl_ui_clock_field_visible_set(dt1, EFL_UI_CLOCK_TYPE_SECOND, EINA_FALSE);
80 elm_box_pack_end(bx, dt2);
81 efl_ui_clock_pause_set(dt2, EINA_TRUE);
82 elm_object_disabled_set(dt2, EINA_TRUE);
83 evas_object_show(dt2);
84
85 dt3 = efl_add(EFL_UI_CLOCK_CLASS, bx);
86 evas_object_size_hint_weight_set(dt3, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
87 evas_object_size_hint_align_set(dt3, EVAS_HINT_FILL, 0.5);
88 elm_box_pack_end(bx, dt3);
89 evas_object_show(dt3);
90
91 //editable
92 lb = efl_add(ELM_LABEL_CLASS, bx);
93 elm_object_text_set(lb,
94 "<b>Editable Clock:</b>"
95 );
96 evas_object_size_hint_weight_set(lb, 0.0, 0.0);
97 evas_object_size_hint_align_set(lb, 0, EVAS_HINT_FILL);
98 evas_object_size_hint_min_set(lb, 100, 25);
99 elm_box_pack_end(bx, lb);
100 evas_object_show(lb);
101
102 dt4 = efl_add(EFL_UI_CLOCK_CLASS, bx);
103 evas_object_size_hint_weight_set(dt4, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
104 evas_object_size_hint_align_set(dt4, EVAS_HINT_FILL, 0.5);
105 efl_ui_clock_edit_mode_set(dt4, EINA_TRUE);
106 efl_ui_clock_pause_set(dt4, EINA_TRUE);
107 elm_box_pack_end(bx, dt4);
108 evas_object_show(dt4);
109
110 bt = elm_button_add(win);
111 elm_object_text_set(bt, "Back to the future...");
112 evas_object_smart_callback_add(bt, "clicked", _bt_clicked, NULL);
113 elm_box_pack_end(bx, bt);
114 evas_object_show(bt);
115
116 evas_object_show(win);
117}
diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h
index 9de820265d..5b956a341c 100644
--- a/src/lib/elementary/Elementary.h
+++ b/src/lib/elementary/Elementary.h
@@ -263,6 +263,7 @@ EAPI extern Elm_Version *elm_version;
263# include <efl_ui_text_interactive.eo.h> 263# include <efl_ui_text_interactive.eo.h>
264# include <efl_ui_text.eo.h> 264# include <efl_ui_text.eo.h>
265# include <efl_ui_text_editable.eo.h> 265# include <efl_ui_text_editable.eo.h>
266# include <efl_ui_clock.eo.h>
266#endif 267#endif
267 268
268/* include deprecated calls last of all */ 269/* include deprecated calls last of all */
diff --git a/src/lib/elementary/efl_ui_clock.c b/src/lib/elementary/efl_ui_clock.c
new file mode 100644
index 0000000000..6c2d86469d
--- /dev/null
+++ b/src/lib/elementary/efl_ui_clock.c
@@ -0,0 +1,1189 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
6
7#include <Elementary.h>
8#include "elm_priv.h"
9#include <efl_ui_clock.h>
10#include <efl_ui_clock_private.h>
11
12#define MY_CLASS EFL_UI_CLOCK_CLASS
13
14#define MY_CLASS_NAME "Efl_Ui_Clock"
15#define MY_CLASS_NAME_LEGACY "efl_ui_clock"
16
17#ifdef HAVE_LOCALE_H
18# include <locale.h>
19#endif
20
21#ifdef HAVE_LANGINFO_H
22# include <langinfo.h>
23#endif
24
25#define MAX_SEPARATOR_LEN 6
26#define MIN_DAYS_IN_MONTH 28
27#define BUFFER_SIZE 1024
28
29/* interface between EDC & C code (field & signal names). values 0 to
30 * EFL_UI_CLOCK_TYPE_COUNT are in the valid range, and must get in the
31 * place of "%d".
32 */
33#define EDC_CLOCK_FOCUSIN_SIG_STR "elm,action,focus"
34#define EDC_CLOCK_FOCUSOUT_SIG_STR "elm,action,unfocus"
35#define EDC_PART_FIELD_STR "field%d"
36#define EDC_PART_SEPARATOR_STR "separator%d"
37#define EDC_PART_FIELD_ENABLE_SIG_STR "field%d,enable"
38#define EDC_PART_FIELD_DISABLE_SIG_STR "field%d,disable"
39
40/* struct tm does not define the fields in the order year, month,
41 * date, hour, minute. values are reassigned to an array for easy
42 * handling.
43 */
44#define CLOCK_TM_ARRAY(intptr, tmptr) \
45 int *intptr[] = { \
46 &(tmptr)->tm_year, \
47 &(tmptr)->tm_mon, \
48 &(tmptr)->tm_mday, \
49 &(tmptr)->tm_hour, \
50 &(tmptr)->tm_min, \
51 &(tmptr)->tm_sec, \
52 &(tmptr)->tm_wday, \
53 &(tmptr)->tm_hour}
54
55// default limits for individual fields
56static Format_Map mapping[EFL_UI_CLOCK_TYPE_COUNT] = {
57 [EFL_UI_CLOCK_TYPE_YEAR] = { "Yy", -1, -1, "" },
58 [EFL_UI_CLOCK_TYPE_MONTH] = { "mbBh", 0, 11, "" },
59 [EFL_UI_CLOCK_TYPE_DATE] = { "de", 1, 31, "" },
60 [EFL_UI_CLOCK_TYPE_HOUR] = { "IHkl", 0, 23, "" },
61 [EFL_UI_CLOCK_TYPE_MINUTE] = { "M", 0, 59, "" },
62 [EFL_UI_CLOCK_TYPE_SECOND] = { "S", 0, 59, "" },
63 [EFL_UI_CLOCK_TYPE_DAY] = { "Aa", 0, 6, "" },
64 [EFL_UI_CLOCK_TYPE_AMPM] = { "pP", 0, 1, "" }
65};
66
67static const char *multifield_formats = "cxXrRTDF";
68static const char *ignore_separators = "()";
69static Clock_Mod_Api *dt_mod = NULL;
70
71static const char SIG_CHANGED[] = "changed";
72static const Evas_Smart_Cb_Description _smart_callbacks[] = {
73 {SIG_CHANGED, ""},
74 {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
75 {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
76 {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
77 {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
78 {NULL, NULL}
79};
80
81static Clock_Mod_Api *
82_dt_mod_init()
83{
84 Elm_Module *mod = NULL;
85
86 if (!(mod = _elm_module_find_as("clock/api"))) return NULL;
87
88 mod->api = malloc(sizeof(Clock_Mod_Api));
89 if (!mod->api) return NULL;
90
91 ((Clock_Mod_Api *)(mod->api))->obj_hook =
92 _elm_module_symbol_get(mod, "obj_hook");
93 ((Clock_Mod_Api *)(mod->api))->obj_unhook =
94 _elm_module_symbol_get(mod, "obj_unhook");
95 ((Clock_Mod_Api *)(mod->api))->obj_hide =
96 _elm_module_symbol_get(mod, "obj_hide");
97 ((Clock_Mod_Api *)(mod->api))->field_create =
98 _elm_module_symbol_get(mod, "field_create");
99 ((Clock_Mod_Api *)(mod->api))->field_value_display =
100 _elm_module_symbol_get(mod, "field_value_display");
101
102 return mod->api;
103}
104
105static void
106_field_list_display(Evas_Object *obj)
107{
108 Clock_Field *field;
109 unsigned int idx = 0;
110
111 EFL_UI_CLOCK_DATA_GET(obj, sd);
112
113 if (!dt_mod || !dt_mod->field_value_display) return;
114
115 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
116 {
117 field = sd->field_list + idx;
118 if (field->fmt_exist && field->visible)
119 dt_mod->field_value_display(sd->mod_data, field->item_obj);
120 }
121}
122
123// FIXME: provide nl_langinfo on Windows if possible
124// returns expanded format string for corresponding multi-field format character
125static char *
126_expanded_fmt_str_get(char ch)
127{
128 char *exp_fmt = "";
129 switch (ch)
130 {
131 case 'c':
132#if defined(HAVE_LANGINFO_H) || defined (HAVE_EVIL)
133 exp_fmt = nl_langinfo(D_T_FMT);
134#else
135 exp_fmt = "";
136#endif
137 break;
138
139 case 'x':
140#if defined(HAVE_LANGINFO_H) || defined (HAVE_EVIL)
141 exp_fmt = nl_langinfo(D_FMT);
142#else
143 exp_fmt = "";
144#endif
145 break;
146
147 case 'X':
148#if defined(HAVE_LANGINFO_H) || defined (HAVE_EVIL)
149 exp_fmt = nl_langinfo(T_FMT);
150#else
151 exp_fmt = "";
152#endif
153 break;
154
155 case 'r':
156#if defined(HAVE_LANGINFO_H) || defined (HAVE_EVIL)
157 exp_fmt = nl_langinfo(T_FMT_AMPM);
158#else
159 exp_fmt = "";
160#endif
161 break;
162
163 case 'R':
164 exp_fmt = "%H:%M";
165 break;
166
167 case 'T':
168 exp_fmt = "%H:%M:%S";
169 break;
170
171 case 'D':
172 exp_fmt = "%m/%d/%y";
173 break;
174
175 case 'F':
176 exp_fmt = "%Y-%m-%d";
177 break;
178
179 default:
180 exp_fmt = "";
181 break;
182 }
183
184 return exp_fmt;
185}
186
187static void
188_expand_format(char *dt_fmt)
189{
190 char *ptr, *expanded_fmt, ch;
191 unsigned int idx = 0, len = 0;
192 char buf[EFL_UI_CLOCK_MAX_FORMAT_LEN] = {0, };
193 Eina_Bool fmt_char = EINA_FALSE;
194
195 ptr = dt_fmt;
196 while ((ch = *ptr))
197 {
198 if ((fmt_char) && (strchr(multifield_formats, ch)))
199 {
200 /* replace the multi-field format characters with
201 * corresponding expanded format */
202 expanded_fmt = _expanded_fmt_str_get(ch);
203 len = strlen(expanded_fmt);
204 buf[--idx] = 0;
205 strncat(buf, expanded_fmt, len);
206 idx += len;
207 }
208 else buf[idx++] = ch;
209
210 if (ch == '%') fmt_char = EINA_TRUE;
211 else fmt_char = EINA_FALSE;
212
213 ptr++;
214 }
215
216 buf[idx] = 0;
217 strncpy(dt_fmt, buf, EFL_UI_CLOCK_MAX_FORMAT_LEN);
218}
219
220static void
221_field_list_arrange(Evas_Object *obj)
222{
223 Clock_Field *field;
224 char buf[BUFFER_SIZE];
225 int idx;
226 Eina_Bool freeze;
227
228 EFL_UI_CLOCK_DATA_GET(obj, sd);
229
230 freeze = sd->freeze_sizing;
231 sd->freeze_sizing = EINA_TRUE;
232 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
233 {
234 field = sd->field_list + idx;
235 snprintf(buf, sizeof(buf), EDC_PART_FIELD_STR, field->location);
236
237 if (field->visible && field->fmt_exist)
238 {
239 evas_object_hide(elm_layout_content_unset(obj, buf));
240 elm_layout_content_set(obj, buf, field->item_obj);
241 }
242 else
243 evas_object_hide(elm_layout_content_unset(obj, buf));
244 }
245 sd->freeze_sizing = freeze;
246
247 elm_layout_sizing_eval(obj);
248 _field_list_display(obj);
249}
250
251static unsigned int
252_parse_format(Evas_Object *obj,
253 char *fmt_ptr)
254{
255 Eina_Bool fmt_parsing = EINA_FALSE, sep_parsing = EINA_FALSE,
256 sep_lookup = EINA_FALSE;
257 unsigned int len = 0, idx = 0, location = 0;
258 char separator[MAX_SEPARATOR_LEN];
259 Clock_Field *field = NULL;
260 char cur;
261
262 EFL_UI_CLOCK_DATA_GET(obj, sd);
263
264 while ((cur = *fmt_ptr))
265 {
266 if (fmt_parsing)
267 {
268 if (cur == '_' || cur == '-' || cur == '0' || cur == '^' || cur == '#')
269 {
270 fmt_ptr++;
271 continue;
272 }
273 fmt_parsing = EINA_FALSE;
274 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
275 {
276 if (strchr(mapping[idx].fmt_char, cur))
277 {
278 field = sd->field_list + idx;
279 /* ignore the fields already have or disabled
280 * valid formats, means already parsed &
281 * repeated, ignore. */
282 if (field->location != -1) break;
283 field->fmt[1] = cur;
284 field->fmt_exist = EINA_TRUE;
285 field->location = location++;
286 sep_lookup = EINA_TRUE;
287 len = 0;
288 break;
289 }
290 }
291 }
292 if (cur == '%')
293 {
294 fmt_parsing = EINA_TRUE;
295 sep_parsing = EINA_FALSE;
296 // set the separator to previous field
297 separator[len] = 0;
298 if (field) eina_stringshare_replace(&field->separator, separator);
299 }
300 // ignore the set of chars (global, field specific) as field separators
301 if (sep_parsing &&
302 (len < MAX_SEPARATOR_LEN - 1) &&
303 (field->type != EFL_UI_CLOCK_TYPE_AMPM) &&
304 (!strchr(ignore_separators, cur)) &&
305 (!strchr(mapping[idx].ignore_sep, cur)))
306 separator[len++] = cur;
307 if (sep_lookup) sep_parsing = EINA_TRUE;
308 sep_lookup = EINA_FALSE;
309 fmt_ptr++;
310 }
311 // return the number of valid fields parsed.
312 return location;
313}
314
315static void
316_reload_format(Evas_Object *obj)
317{
318 unsigned int idx, field_count;
319 Clock_Field *field;
320 char buf[BUFFER_SIZE];
321 char *dt_fmt;
322
323 EFL_UI_CLOCK_DATA_GET(obj, sd);
324 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
325
326 // FIXME: provide nl_langinfo on Windows if possible
327 // fetch the default format from Libc.
328 if (!sd->user_format)
329#if defined(HAVE_LANGINFO_H) || defined (HAVE_EVIL)
330 strncpy(sd->format, nl_langinfo(D_T_FMT), EFL_UI_CLOCK_MAX_FORMAT_LEN);
331#else
332 strncpy(sd->format, "", EFL_UI_CLOCK_MAX_FORMAT_LEN);
333#endif
334 sd->format[EFL_UI_CLOCK_MAX_FORMAT_LEN - 1] = '\0';
335
336 dt_fmt = (char *)malloc(EFL_UI_CLOCK_MAX_FORMAT_LEN);
337 if (!dt_fmt) return;
338
339 strncpy(dt_fmt, sd->format, EFL_UI_CLOCK_MAX_FORMAT_LEN);
340
341 _expand_format(dt_fmt);
342
343 // reset all the fields to disable state
344 sd->enabled_field_count = 0;
345 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
346 {
347 field = sd->field_list + idx;
348 field->fmt_exist = EINA_FALSE;
349 field->location = -1;
350 }
351
352 field_count = _parse_format(obj, dt_fmt);
353 free(dt_fmt);
354
355 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
356 {
357 field = sd->field_list + idx;
358 if (field->fmt_exist && field->visible)
359 sd->enabled_field_count++;
360 }
361
362 // assign locations to disabled fields for uniform usage
363 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
364 {
365 field = sd->field_list + idx;
366 if (field->location == -1) field->location = field_count++;
367
368 if (field->fmt_exist && field->visible)
369 {
370 snprintf(buf, sizeof(buf), EDC_PART_FIELD_ENABLE_SIG_STR,
371 field->location);
372 elm_layout_signal_emit(obj, buf, "elm");
373 }
374 else
375 {
376 snprintf(buf, sizeof(buf), EDC_PART_FIELD_DISABLE_SIG_STR,
377 field->location);
378 elm_layout_signal_emit(obj, buf, "elm");
379 }
380 snprintf
381 (buf, sizeof(buf), EDC_PART_SEPARATOR_STR, (field->location + 1));
382 elm_layout_text_set(obj, buf, field->separator);
383 }
384
385 edje_object_message_signal_process(wd->resize_obj);
386 _field_list_arrange(obj);
387}
388
389EOLIAN static Eina_Bool
390_efl_ui_clock_elm_widget_translate(Eo *obj, Efl_Ui_Clock_Data *sd)
391{
392 if (!sd->user_format) _reload_format(obj);
393 else _field_list_display(obj);
394
395 elm_obj_widget_translate(efl_super(obj, MY_CLASS));
396
397 return EINA_TRUE;
398}
399
400static Eina_List *
401_clock_items_get(const Evas_Object *obj)
402{
403 Eina_List *items = NULL;
404 Clock_Field *field;
405 unsigned int idx;
406 Clock_Field *sorted_fields[EFL_UI_CLOCK_TYPE_COUNT];
407
408 EFL_UI_CLOCK_DATA_GET(obj, sd);
409
410 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
411 {
412 field = sd->field_list + idx;
413 sorted_fields[field->location] = field;
414 }
415
416 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
417 {
418 field = sorted_fields[idx];
419 if (field->fmt_exist && field->visible)
420 items = eina_list_append(items, field->item_obj);
421 }
422
423 // ACCESS
424 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
425 items = eina_list_append(items, sd->access_obj);
426
427 return items;
428}
429
430EOLIAN static Eina_Bool
431_efl_ui_clock_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Efl_Ui_Clock_Data *_pd EINA_UNUSED)
432{
433 return EINA_TRUE;
434}
435
436EOLIAN static void
437_efl_ui_clock_pause_set(Eo *obj EINA_UNUSED, Efl_Ui_Clock_Data *sd, Eina_Bool paused)
438{
439 paused = !!paused;
440 if (sd->paused == paused)
441 return;
442 sd->paused = paused;
443 if (paused)
444 ecore_timer_freeze(sd->ticker);
445 else
446 ecore_timer_thaw(sd->ticker);
447}
448
449EOLIAN static Eina_Bool
450_efl_ui_clock_pause_get(Eo *obj EINA_UNUSED, Efl_Ui_Clock_Data *sd)
451{
452 return sd->paused;
453}
454
455EOLIAN static void
456_efl_ui_clock_edit_mode_set(Eo *obj EINA_UNUSED, Efl_Ui_Clock_Data *sd, Eina_Bool edit_mode)
457{
458 sd->edit_mode = edit_mode;
459}
460
461EOLIAN static Eina_Bool
462_efl_ui_clock_edit_mode_get(Eo *obj EINA_UNUSED, Efl_Ui_Clock_Data *sd)
463{
464 return sd->edit_mode;
465}
466
467EOLIAN static Eina_Bool
468_efl_ui_clock_elm_widget_focus_next(Eo *obj, Efl_Ui_Clock_Data *_pd EINA_UNUSED, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item)
469{
470 const Eina_List *items;
471 Eina_List *(*list_free)(Eina_List *list);
472 void *(*list_data_get)(const Eina_List *list);
473
474 Eina_Bool int_ret;
475
476 if ((items = elm_widget_focus_custom_chain_get(obj)))
477 {
478 list_data_get = eina_list_data_get;
479 list_free = NULL;
480 }
481 else
482 {
483 items = _clock_items_get(obj);
484 list_data_get = eina_list_data_get;
485 list_free = eina_list_free;
486 if (!items) return EINA_FALSE;
487 }
488
489 int_ret = elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next, next_item);
490 if (list_free) list_free((Eina_List *)items);
491
492 return int_ret;
493}
494
495EOLIAN static Eina_Bool
496_efl_ui_clock_elm_widget_on_focus(Eo *obj, Efl_Ui_Clock_Data *sd, Elm_Object_Item *item EINA_UNUSED)
497{
498 Eina_Bool int_ret = EINA_FALSE;
499
500 int_ret = elm_obj_widget_on_focus(efl_super(obj, MY_CLASS), NULL);
501 if (!int_ret) return EINA_FALSE;
502
503 if (!elm_widget_focus_get(obj))
504 {
505 if ((dt_mod) && (dt_mod->obj_hide))
506 dt_mod->obj_hide(sd->mod_data);
507 }
508
509 return EINA_TRUE;
510}
511
512EOLIAN static Eina_Bool
513_efl_ui_clock_elm_widget_disable(Eo *obj, Efl_Ui_Clock_Data *sd)
514{
515 Clock_Field *field;
516 unsigned int idx = 0;
517 Eina_Bool int_ret = EINA_FALSE;
518
519 int_ret = elm_obj_widget_disable(efl_super(obj, MY_CLASS));
520 if (!int_ret) return EINA_FALSE;
521
522 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
523 {
524 field = sd->field_list + idx;
525 elm_object_disabled_set(field->item_obj, elm_object_disabled_get(obj));
526 }
527 return EINA_TRUE;
528}
529
530EOLIAN static void
531_efl_ui_clock_elm_layout_sizing_eval(Eo *obj, Efl_Ui_Clock_Data *sd)
532{
533 Evas_Coord minw = -1, minh = -1;
534
535 if (sd->freeze_sizing) return;
536
537 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
538
539 if (sd->enabled_field_count)
540 elm_coords_finger_size_adjust(sd->enabled_field_count, &minw, 1, &minh);
541
542 edje_object_size_min_restricted_calc
543 (wd->resize_obj, &minw, &minh, minw, minh);
544 evas_object_size_hint_min_set(obj, minw, minh);
545 evas_object_size_hint_max_set(obj, -1, -1);
546}
547
548EOLIAN static Elm_Theme_Apply
549_efl_ui_clock_elm_widget_theme_apply(Eo *obj, Efl_Ui_Clock_Data *sd)
550{
551 Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED;
552
553 Clock_Field *field;
554 char buf[BUFFER_SIZE];
555 unsigned int idx;
556
557 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
558
559 int_ret = elm_obj_widget_theme_apply(efl_super(obj, MY_CLASS));
560 if (!int_ret) return ELM_THEME_APPLY_FAILED;
561
562 if ((!dt_mod) || (!dt_mod->field_value_display)) return EINA_TRUE;
563
564 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
565 {
566 field = sd->field_list + idx;
567 if (field->fmt_exist && field->visible)
568 {
569 snprintf(buf, sizeof(buf), EDC_PART_FIELD_ENABLE_SIG_STR,
570 field->location);
571 elm_layout_signal_emit(obj, buf, "elm");
572
573 snprintf
574 (buf, sizeof(buf), EDC_PART_SEPARATOR_STR, field->location);
575 elm_layout_text_set(obj, buf, field->separator);
576
577 dt_mod->field_value_display(sd->mod_data, field->item_obj);
578 }
579 else
580 {
581 snprintf(buf, sizeof(buf), EDC_PART_FIELD_DISABLE_SIG_STR,
582 field->location);
583 elm_layout_signal_emit(obj, buf, "elm");
584 }
585 }
586
587 edje_object_message_signal_process(wd->resize_obj);
588 elm_layout_sizing_eval(obj);
589
590 return int_ret;
591}
592
593static int
594_max_days_get(int year,
595 int month)
596{
597 struct tm time1;
598 time_t t;
599 int day;
600
601 t = time(NULL);
602 localtime_r(&t, &time1);
603 time1.tm_year = year;
604 time1.tm_mon = month;
605 for (day = MIN_DAYS_IN_MONTH; day <= mapping[EFL_UI_CLOCK_TYPE_DATE].def_max;
606 day++)
607 {
608 time1.tm_mday = day;
609 mktime(&time1);
610 /* To restrict month wrapping because of summer time in some locales,
611 * ignore day light saving mode in mktime(). */
612 time1.tm_isdst = -1;
613 if (time1.tm_mday == 1) break;
614 }
615 day--;
616
617 return day;
618}
619
620static Eina_Bool
621_date_cmp(const struct tm *time1,
622 const struct tm *time2)
623{
624 unsigned int idx;
625
626 const CLOCK_TM_ARRAY(timearr1, time1);
627 const CLOCK_TM_ARRAY(timearr2, time2);
628
629 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
630 {
631 if (*timearr1[idx] != *timearr2[idx])
632 return EINA_FALSE;
633 }
634
635 return EINA_TRUE;
636}
637
638static Eina_Bool
639_field_cmp(Efl_Ui_Clock_Type field_type,
640 struct tm *time1,
641 struct tm *time2)
642{
643 CLOCK_TM_ARRAY(timearr1, time1);
644 CLOCK_TM_ARRAY(timearr2, time2);
645
646 if (*timearr1[field_type] != *timearr2[field_type])
647 return EINA_FALSE;
648 else
649 return EINA_TRUE;
650}
651
652// validates curr_time/min_limt/max_limit according to the newly set value
653static void
654_validate_clock_limits(struct tm *time1,
655 struct tm *time2,
656 Eina_Bool swap)
657{
658 struct tm *t1, *t2;
659 unsigned int idx;
660
661 if (!time1 || !time2) return;
662
663 t1 = (swap) ? time2 : time1;
664 t2 = (swap) ? time1 : time2;
665
666 CLOCK_TM_ARRAY(timearr1, time1);
667 CLOCK_TM_ARRAY(timearr2, time2);
668 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT - 1; idx++)
669 {
670 if (*timearr1[idx] < *timearr2[idx])
671 {
672 memcpy(t1, t2, sizeof(struct tm));
673 break;
674 }
675 else if (*timearr1[idx] > *timearr2[idx])
676 break;
677 }
678}
679
680static void
681_apply_field_limits(Evas_Object *obj)
682{
683 Clock_Field *field;
684 unsigned int idx = 0;
685 int val;
686
687 EFL_UI_CLOCK_DATA_GET(obj, sd);
688
689 CLOCK_TM_ARRAY(timearr, &sd->curr_time);
690 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT - 1; idx++)
691 {
692 field = sd->field_list + idx;
693 val = *timearr[idx];
694 if (val < field->min)
695 *timearr[idx] = field->min;
696 else if (val > field->max)
697 *timearr[idx] = field->max;
698 }
699
700 _field_list_display(obj);
701}
702
703static void
704_apply_range_restrictions(struct tm *tim)
705{
706 unsigned int idx;
707 int val, min, max;
708
709 if (!tim) return;
710
711 CLOCK_TM_ARRAY(timearr, tim);
712 for (idx = EFL_UI_CLOCK_TYPE_MONTH; idx < EFL_UI_CLOCK_TYPE_COUNT - 1; idx++)
713 {
714 val = *timearr[idx];
715 min = mapping[idx].def_min;
716 max = mapping[idx].def_max;
717 if (idx == EFL_UI_CLOCK_TYPE_DATE)
718 max = _max_days_get(tim->tm_year, tim->tm_mon);
719 if (val < min)
720 *timearr[idx] = min;
721 else if (val > max)
722 *timearr[idx] = max;
723 }
724}
725
726static const char *
727_field_format_get(Evas_Object *obj,
728 Efl_Ui_Clock_Type field_type)
729{
730 Clock_Field *field;
731
732 if (field_type > EFL_UI_CLOCK_TYPE_DAY) return NULL;
733
734 EFL_UI_CLOCK_DATA_GET(obj, sd);
735
736 field = sd->field_list + field_type;
737
738 return field->fmt;
739}
740
741static void
742_field_limit_get(Evas_Object *obj,
743 Efl_Ui_Clock_Type field_type,
744 int *range_min,
745 int *range_max)
746{
747 int min, max, max_days;
748 Clock_Field *field;
749 unsigned int idx;
750
751 if (field_type > EFL_UI_CLOCK_TYPE_DAY) return;
752
753 EFL_UI_CLOCK_DATA_GET(obj, sd);
754
755 field = sd->field_list + field_type;
756
757 min = field->min;
758 max = field->max;
759
760 CLOCK_TM_ARRAY(curr_timearr, &sd->curr_time);
761 CLOCK_TM_ARRAY(min_timearr, &sd->min_limit);
762 CLOCK_TM_ARRAY(max_timearr, &sd->max_limit);
763
764 for (idx = 0; idx < field->type; idx++)
765 if (*curr_timearr[idx] > *min_timearr[idx]) break;
766 if ((idx == field_type) && (min < *min_timearr[field_type]))
767 min = *min_timearr[field_type];
768 if (field_type == EFL_UI_CLOCK_TYPE_DATE)
769 {
770 max_days = _max_days_get(sd->curr_time.tm_year, sd->curr_time.tm_mon);
771 if (max > max_days) max = max_days;
772 }
773 for (idx = 0; idx < field->type; idx++)
774 if (*curr_timearr[idx] < *max_timearr[idx]) break;
775 if ((idx == field_type) && (max > *max_timearr[field_type]))
776 max = *max_timearr[field_type];
777
778 *range_min = min;
779 *range_max = max;
780}
781
782static void
783_field_list_init(Evas_Object *obj)
784{
785 Clock_Field *field;
786 unsigned int idx;
787 time_t t;
788
789 EFL_UI_CLOCK_DATA_GET(obj, sd);
790
791 t = time(NULL);
792 localtime_r(&t, &sd->curr_time);
793
794 mapping[EFL_UI_CLOCK_TYPE_YEAR].def_min = _elm_config->year_min;
795 mapping[EFL_UI_CLOCK_TYPE_YEAR].def_max = _elm_config->year_max;
796 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
797 {
798 field = sd->field_list + idx;
799 field->type = EFL_UI_CLOCK_TYPE_YEAR + idx;
800 field->fmt[0] = '%';
801 field->fmt_exist = EINA_FALSE;
802 field->visible = EINA_TRUE;
803 field->min = mapping[idx].def_min;
804 field->max = mapping[idx].def_max;
805 }
806 CLOCK_TM_ARRAY(min_timearr, &sd->min_limit);
807 CLOCK_TM_ARRAY(max_timearr, &sd->max_limit);
808 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT - 1; idx++)
809 {
810 *min_timearr[idx] = mapping[idx].def_min;
811 *max_timearr[idx] = mapping[idx].def_max;
812 }
813}
814
815static char *
816_access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
817{
818 char *ret;
819 Eina_Strbuf *buf;
820 buf = eina_strbuf_new();
821
822 EFL_UI_CLOCK_DATA_GET(data, sd);
823 eina_strbuf_append_printf(buf,
824 "%d year, %d month, %d date, %d hour, %d minute",
825 sd->curr_time.tm_year, sd->curr_time.tm_mon + 1,
826 sd->curr_time.tm_mday, sd->curr_time.tm_hour,
827 sd->curr_time.tm_min);
828
829 ret = eina_strbuf_string_steal(buf);
830 eina_strbuf_free(buf);
831 return ret;
832}
833
834static Eina_Bool
835_ticker(void *data)
836{
837 double t;
838 time_t tt;
839 struct timeval timev;
840 Clock_Field *field;
841
842 EFL_UI_CLOCK_DATA_GET(data, sd);
843
844 tt = time(NULL);
845 localtime_r(&tt, &sd->curr_time);
846
847 if (sd->curr_time.tm_sec > 0)
848 {
849 field = sd->field_list + EFL_UI_CLOCK_TYPE_SECOND;
850 if (field->fmt_exist && field->visible)
851 dt_mod->field_value_display(sd->mod_data, field->item_obj);
852 }
853 else
854 _field_list_display(data);
855
856 gettimeofday(&timev, NULL);
857 t = ((double)(1000000 - timev.tv_usec)) / 1000000.0;
858 sd->ticker = ecore_timer_add(t, _ticker, data);
859
860 return ECORE_CALLBACK_CANCEL;
861}
862
863EOLIAN static void
864_efl_ui_clock_efl_canvas_group_group_add(Eo *obj, Efl_Ui_Clock_Data *priv)
865{
866 Clock_Field *field;
867 int idx;
868
869 efl_canvas_group_add(efl_super(obj, MY_CLASS));
870 elm_widget_sub_object_parent_add(obj);
871
872 // module - initialise module for clock
873 if (!dt_mod) dt_mod = _dt_mod_init();
874 if (dt_mod)
875 {
876 if (dt_mod->obj_hook)
877 {
878 priv->mod_data = dt_mod->obj_hook(obj);
879
880 // update module data
881 if (priv->mod_data)
882 {
883 priv->mod_data->base = obj;
884 priv->mod_data->field_limit_get = _field_limit_get;
885 priv->mod_data->field_format_get = _field_format_get;
886 }
887 }
888
889 if (dt_mod->field_create)
890 {
891 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
892 {
893 field = priv->field_list + idx;
894 field->item_obj = dt_mod->field_create(priv->mod_data, idx);
895 }
896 }
897 }
898
899 priv->freeze_sizing = EINA_TRUE;
900 if (!elm_layout_theme_set(obj, "uiclock", "base",
901 elm_widget_style_get(obj)))
902 CRI("Failed to set layout!");
903
904 _field_list_init(obj);
905 _reload_format(obj);
906 _ticker(obj);
907
908 elm_widget_can_focus_set(obj, EINA_TRUE);
909
910 priv->freeze_sizing = EINA_FALSE;
911 elm_layout_sizing_eval(obj);
912
913 // ACCESS
914 if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
915 {
916 Elm_Access_Info *ai;
917
918 priv->access_obj = _elm_access_edje_object_part_object_register
919 (obj, elm_layout_edje_get(obj), "elm.access");
920 if (!priv->access_obj)
921 priv->access_obj = _elm_access_edje_object_part_object_register
922 (obj, elm_layout_edje_get(obj), "access");
923
924 ai = _elm_access_info_get(priv->access_obj);
925 _elm_access_text_set(ai, ELM_ACCESS_TYPE, "date time");
926 _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, obj);
927 }
928}
929
930EOLIAN static void
931_efl_ui_clock_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Clock_Data *sd)
932{
933 Clock_Field *tmp;
934 unsigned int idx;
935
936 ecore_timer_del(sd->ticker);
937 for (idx = 0; idx < EFL_UI_CLOCK_TYPE_COUNT; idx++)
938 {
939 tmp = sd->field_list + idx;
940 evas_object_del(tmp->item_obj);
941 eina_stringshare_del(tmp->separator);
942 }
943
944 if ((dt_mod) && (dt_mod->obj_unhook))
945 dt_mod->obj_unhook(sd->mod_data); // module - unhook
946
947 efl_canvas_group_del(efl_super(obj, MY_CLASS));
948}
949
950EOLIAN static Eo *
951_efl_ui_clock_efl_object_constructor(Eo *obj, Efl_Ui_Clock_Data *_pd EINA_UNUSED)
952{
953 obj = efl_constructor(efl_super(obj, MY_CLASS));
954 efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
955 evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
956 elm_interface_atspi_accessible_role_set(obj, ELM_ATSPI_ROLE_DATE_EDITOR);
957
958 return obj;
959}
960
961EOLIAN static const char*
962_efl_ui_clock_format_get(Eo *obj EINA_UNUSED, Efl_Ui_Clock_Data *sd)
963{
964 return sd->format;
965}
966
967EOLIAN static void
968_efl_ui_clock_format_set(Eo *obj, Efl_Ui_Clock_Data *sd, const char *fmt)
969{
970 if (fmt)
971 {
972 strncpy(sd->format, fmt, EFL_UI_CLOCK_MAX_FORMAT_LEN);
973 sd->format[EFL_UI_CLOCK_MAX_FORMAT_LEN - 1] = '\0';
974 sd->user_format = EINA_TRUE;
975 }
976 else sd->user_format = EINA_FALSE;
977
978 _reload_format(obj);
979}
980
981EOLIAN static Eina_Bool
982_efl_ui_clock_field_visible_get(Eo *obj EINA_UNUSED, Efl_Ui_Clock_Data *sd, Efl_Ui_Clock_Type fieldtype)
983{
984 Clock_Field *field;
985
986 if (fieldtype > EFL_UI_CLOCK_TYPE_DAY) return EINA_FALSE;
987
988 field = sd->field_list + fieldtype;
989
990 return field->visible;
991}
992
993EOLIAN static void
994_efl_ui_clock_field_visible_set(Eo *obj, Efl_Ui_Clock_Data *sd, Efl_Ui_Clock_Type fieldtype, Eina_Bool visible)
995{
996 char buf[BUFFER_SIZE];
997 Clock_Field *field;
998
999 if (fieldtype > EFL_UI_CLOCK_TYPE_DAY) return;
1000
1001 field = sd->field_list + fieldtype;
1002 visible = !!visible;
1003 if (field->visible == visible) return;
1004
1005 field->visible = visible;
1006
1007 sd->freeze_sizing = EINA_TRUE;
1008 if (visible)
1009 {
1010 sd->enabled_field_count++;
1011
1012 if (!field->fmt_exist) return;
1013
1014 snprintf(buf, sizeof(buf), EDC_PART_FIELD_ENABLE_SIG_STR,
1015 field->location);
1016 elm_layout_signal_emit(obj, buf, "elm");
1017
1018 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1019 edje_object_message_signal_process(wd->resize_obj);
1020
1021 snprintf(buf, sizeof(buf), EDC_PART_FIELD_STR, field->location);
1022 elm_layout_content_unset(obj, buf);
1023 elm_layout_content_set(obj, buf, field->item_obj);
1024 }
1025 else
1026 {
1027 sd->enabled_field_count--;
1028
1029 if (!field->fmt_exist) return;
1030
1031 snprintf(buf, sizeof(buf), EDC_PART_FIELD_DISABLE_SIG_STR,
1032 field->location);
1033 elm_layout_signal_emit(obj, buf, "elm");
1034
1035 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1036 edje_object_message_signal_process(wd->resize_obj);
1037
1038 snprintf(buf, sizeof(buf), EDC_PART_FIELD_STR, field->location);
1039 evas_object_hide(elm_layout_content_unset(obj, buf));
1040 }
1041 sd->freeze_sizing = EINA_FALSE;
1042
1043 elm_layout_sizing_eval(obj);
1044
1045 if (!visible) return;
1046 if (!dt_mod || !dt_mod->field_value_display) return;
1047
1048 dt_mod->field_value_display(sd->mod_data, field->item_obj);
1049}
1050
1051EOLIAN static void
1052_efl_ui_clock_field_limit_get(Eo *obj EINA_UNUSED, Efl_Ui_Clock_Data *sd, Efl_Ui_Clock_Type fieldtype, int *min, int *max)
1053{
1054 Clock_Field *field;
1055
1056 if (fieldtype >= EFL_UI_CLOCK_TYPE_DAY) return;
1057
1058 field = sd->field_list + fieldtype;
1059 if (min) *min = field->min;
1060 if (max) *max = field->max;
1061}
1062
1063EOLIAN static void
1064_efl_ui_clock_field_limit_set(Eo *obj, Efl_Ui_Clock_Data *sd, Efl_Ui_Clock_Type fieldtype, int min, int max)
1065{
1066 Clock_Field *field;
1067 struct tm old_time;
1068
1069 if (fieldtype >= EFL_UI_CLOCK_TYPE_DAY) return;
1070
1071 if (min > max) return;
1072
1073 old_time = sd->curr_time;
1074 field = sd->field_list + fieldtype;
1075 if (((min >= mapping[fieldtype].def_min) &&
1076 (min <= mapping[fieldtype].def_max)) ||
1077 (field->type == EFL_UI_CLOCK_TYPE_YEAR))
1078 field->min = min;
1079 if (((max >= mapping[fieldtype].def_min) &&
1080 (max <= mapping[fieldtype].def_max)) ||
1081 (field->type == EFL_UI_CLOCK_TYPE_YEAR))
1082 field->max = max;
1083
1084 _apply_field_limits(obj);
1085
1086 if (!_field_cmp(fieldtype, &old_time, &sd->curr_time))
1087 efl_event_callback_legacy_call(obj, EFL_UI_CLOCK_EVENT_CHANGED, NULL);
1088
1089}
1090
1091EOLIAN static Eina_Bool
1092_efl_ui_clock_value_get(Eo *obj EINA_UNUSED, Efl_Ui_Clock_Data *sd, struct tm *currtime)
1093{
1094 EINA_SAFETY_ON_NULL_RETURN_VAL(currtime, EINA_FALSE);
1095
1096 *currtime = sd->curr_time;
1097 return EINA_TRUE;
1098}
1099
1100EOLIAN static Eina_Bool
1101_efl_ui_clock_value_set(Eo *obj, Efl_Ui_Clock_Data *sd, struct tm *newtime)
1102{
1103 EINA_SAFETY_ON_NULL_RETURN_VAL(newtime, EINA_FALSE);
1104
1105 if (_date_cmp(&sd->curr_time, newtime)) return EINA_TRUE;
1106 sd->curr_time = *newtime;
1107 // apply default field restrictions for curr_time
1108 _apply_range_restrictions(&sd->curr_time);
1109 // validate the curr_time according to the min_limt and max_limt
1110 _validate_clock_limits(&sd->curr_time, &sd->min_limit, EINA_FALSE);
1111 _validate_clock_limits(&sd->max_limit, &sd->curr_time, EINA_TRUE);
1112 _apply_field_limits(obj);
1113
1114 efl_event_callback_legacy_call(obj, EFL_UI_CLOCK_EVENT_CHANGED, NULL);
1115
1116 return EINA_TRUE;
1117}
1118
1119EOLIAN static Eina_Bool
1120_efl_ui_clock_value_min_get(Eo *obj EINA_UNUSED, Efl_Ui_Clock_Data *sd, Efl_Time *mintime)
1121{
1122 EINA_SAFETY_ON_NULL_RETURN_VAL(mintime, EINA_FALSE);
1123
1124 *mintime = sd->min_limit;
1125 return EINA_TRUE;
1126}
1127
1128EOLIAN static Eina_Bool
1129_efl_ui_clock_value_min_set(Eo *obj, Efl_Ui_Clock_Data *sd, Efl_Time *mintime)
1130{
1131 struct tm old_time;
1132
1133 EINA_SAFETY_ON_NULL_RETURN_VAL(mintime, EINA_FALSE);
1134
1135 if (_date_cmp(&sd->min_limit, mintime)) return EINA_TRUE;
1136 sd->min_limit = *mintime;
1137 old_time = sd->curr_time;
1138 // apply default field restrictions for min_limit
1139 _apply_range_restrictions(&sd->min_limit);
1140 // validate curr_time and max_limt according to the min_limit
1141 _validate_clock_limits(&sd->max_limit, &sd->min_limit, EINA_FALSE);
1142 _validate_clock_limits(&sd->curr_time, &sd->min_limit, EINA_FALSE);
1143 _apply_field_limits(obj);
1144
1145 if (!_date_cmp(&old_time, &sd->curr_time))
1146 efl_event_callback_legacy_call(obj, EFL_UI_CLOCK_EVENT_CHANGED, NULL);
1147
1148 return EINA_TRUE;
1149}
1150
1151EOLIAN static Eina_Bool
1152_efl_ui_clock_value_max_get(Eo *obj EINA_UNUSED, Efl_Ui_Clock_Data *sd, struct tm *maxtime)
1153{
1154 EINA_SAFETY_ON_NULL_RETURN_VAL(maxtime, EINA_FALSE);
1155
1156 *maxtime = sd->max_limit;
1157 return EINA_TRUE;
1158}
1159
1160EOLIAN static Eina_Bool
1161_efl_ui_clock_value_max_set(Eo *obj, Efl_Ui_Clock_Data *sd, struct tm *maxtime)
1162{
1163 struct tm old_time;
1164
1165 EINA_SAFETY_ON_NULL_RETURN_VAL(maxtime, EINA_FALSE);
1166
1167 if (_date_cmp(&sd->max_limit, maxtime)) return EINA_TRUE;
1168 sd->max_limit = *maxtime;
1169 old_time = sd->curr_time;
1170 // apply default field restrictions for max_limit
1171 _apply_range_restrictions(&sd->max_limit);
1172 // validate curr_time and min_limt according to the max_limit
1173 _validate_clock_limits(&sd->max_limit, &sd->min_limit, EINA_TRUE);
1174 _validate_clock_limits(&sd->max_limit, &sd->curr_time, EINA_TRUE);
1175 _apply_field_limits(obj);
1176
1177 if (!_date_cmp(&old_time, &sd->curr_time))
1178 efl_event_callback_legacy_call(obj, EFL_UI_CLOCK_EVENT_CHANGED, NULL);
1179
1180 return EINA_TRUE;
1181}
1182
1183EOLIAN static void
1184_efl_ui_clock_class_constructor(Efl_Class *klass)
1185{
1186 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1187}
1188
1189#include "efl_ui_clock.eo.c"
diff --git a/src/lib/elementary/efl_ui_clock.eo b/src/lib/elementary/efl_ui_clock.eo
new file mode 100644
index 0000000000..1261cec7e7
--- /dev/null
+++ b/src/lib/elementary/efl_ui_clock.eo
@@ -0,0 +1,260 @@
1import efl_types;
2
3enum Efl.Ui.Clock.Type
4{
5 [[Identifies a clock field, The widget supports 6 fields : Year, month,
6 Date, Hour, Minute, AM/PM
7 ]]
8
9 year = 0, [[Indicates Year field.]]
10 month = 1, [[Indicates Month field.]]
11 date = 2, [[Indicates Date field.]]
12 hour = 3, [[Indicates Hour field.]]
13 minute = 4, [[Indicates Minute field.]]
14 second = 5, [[Indicates Second field.]]
15 day = 6, [[Indicated Day field.]]
16 ampm = 7, [[Indicates AM/PM field .]]
17}
18
19class Efl.Ui.Clock (Elm.Layout)
20{
21 methods {
22 @property format {
23 [[The current clock format.
24 Format is a combination of allowed
25 Libc date format specifiers like: "%b %d, %Y %I : %M %p".
26
27 Maximum allowed format length is 64 chars.
28
29 Format can include separators for each individual clock
30 field except for AM/PM field.
31
32 Each separator can be a maximum of 6 UTF-8 bytes.
33 Space is also taken as a separator.
34
35 These specifiers can be arranged in any order and the widget
36 will display the fields accordingly.
37
38 Default format is taken as per the system locale settings.
39 ]]
40 /* FIXME-doc
41 Following are the allowed set of format specifiers for each clock field.
42
43 @b %%Y : The year as a decimal number including the century.
44
45 @b %%y : The year as a decimal number without a century (range 00 to 99).
46
47 @b %%m : The month as a decimal number (range 01 to 12).
48
49 @b %%b : The abbreviated month name according to the current locale.
50
51 @b %%B : The full month name according to the current locale.
52
53 @b %%h : The abbreviated month name according to the current locale(same as %%b).
54
55 @b %%d : The day of the month as a decimal number (range 01 to 31).
56
57 @b %%e : The day of the month as a decimal number (range 1 to 31). single
58 digits are preceded by a blank.
59
60 @b %%I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
61
62 @b %%H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
63
64 @b %%k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
65 digits are preceded by a blank.
66
67 @b %%l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
68 digits are preceded by a blank.
69
70 @b %%M : The minute as a decimal number (range 00 to 59).
71
72 @b %%p : Either 'AM' or 'PM' according to the given time value, or the
73 corresponding strings for the current locale. Noon is treated as 'PM'
74 and midnight as 'AM'.
75
76 @b %%P : Like %p but in lower case: 'am' or 'pm' or a corresponding string for
77 the current locale.
78
79 @b %%c : The preferred date and time representation for the current locale.
80
81 @b %%x : The preferred date representation for the current locale without the time.
82
83 @b %%X : The preferred time representation for the current locale without the date.
84
85 @b %%r : The complete calendar time using the AM/PM format of the current locale.
86
87 @b %%R : The hour and minute in decimal numbers using the format %H:%M.
88
89 @b %%T : The time of day in decimal numbers using the format %H:%M:%S.
90
91 @b %%D : The date using the format %%m/%%d/%%y.
92
93 @b %%F : The date using the format %%Y-%%m-%%d.
94 */
95 set {} get {}
96 values {
97 fmt: const(char)* @nullable; [[The clock format.]]
98 }
99 }
100 @property pause {
101 [[Whether the given clock widget should be paused or not.
102
103 This function pauses or starts the clock widget.
104 ]]
105 set {} get {}
106 values {
107 paused: bool; [[$true to pause clock, $false otherwise]]
108 }
109 }
110 @property edit_mode {
111 [[Digits of the given clock widget should be editable when in editing mode.]]
112 set {} get {}
113 values {
114 value: bool; [[$true to set edit mode, $false otherwise]]
115 }
116 }
117 @property value_min {
118 [[The lower boundary of a field.
119
120 Year: years since 1900. Negative value represents year below 1900
121 (year value -30 represents 1870). Year default range is from 70
122 to 137.
123
124 Month: default value range is from 0 to 11.
125
126 Date: default value range is from 1 to 31 according to the month
127 value.
128
129 Hour: default value will be in terms of 24 hr format (0~23)
130
131 Minute: default value range is from 0 to 59.
132 ]]
133 set {
134 return: bool;
135 }
136 get {
137 return: bool;
138 }
139
140 keys {
141 mintime: Efl.Time*; [[Time structure containing the minimum time value.]]
142 }
143 }
144 @property value_max {
145 [[The upper boundary of a field.
146
147 Year: years since 1900. Negative value represents year below 1900
148 (year value -30 represents 1870). Year default range is from 70
149 to 137.
150
151 Month: default value range is from 0 to 11.
152
153 Date: default value range is from 1 to 31 according to the month
154 value.
155
156 Hour: default value will be in terms of 24 hr format (0~23)
157
158 Minute: default value range is from 0 to 59.
159 ]]
160 set {
161 return: bool;
162 }
163 get {
164 return: bool;
165 }
166
167 keys {
168 maxtime: Efl.Time*; [[Time structure containing the minimum time value.]]
169 }
170 }
171 @property value {
172 [[The current value of a clock object.
173
174 Year: years since 1900. Negative value represents year below 1900
175 (year value -30 represents 1870). Year default range is from 70
176 to 137.
177
178 Month: default value range is from 0 to 11.
179
180 Date: default value range is from 1 to 31 according to the month
181 value.
182
183 Hour: default value will be in terms of 24 hr format (0~23)
184
185 Minute: default value range is from 0 to 59.
186 ]]
187 set {
188 return: bool;
189 }
190 get {
191 return: bool;
192 }
193 keys {
194 curtime: Efl.Time*; [[Time structure containing the minimum time value.]]
195 }
196 }
197 @property field_visible {
198 [[ The field to be visible/not.]]
199 set{} get{}
200 keys {
201 fieldtype: Efl.Ui.Clock.Type; [[Type of the field. #EFL_UI_CLOCK_TYPE_YEAR etc.]]
202 }
203 values {
204 visible: bool; [[$true field can be visible, $false otherwise.]]
205 }
206 }
207 @property field_limit {
208 set {
209 [[Set a field to be visible or not.
210
211 Setting this API to $true does not ensure that the field is
212 visible, apart from this, the field's format must be present
213 in clock overall format. If a field's visibility is set
214 to $false then it won't appear even though its format is
215 present in overall format. So if and only if this API is
216 set true and the corresponding field's format is present
217 in clock format, the field is visible.
218
219 By default the field visibility is set to $true.
220 ]]
221 }
222 get {
223 [[ Get the field limits of a field.
224
225 Limits can be set to individual fields, independently, except
226 for AM/PM field. Any field can display the values only in between
227 these minimum and maximum limits unless the corresponding time
228 value is restricted from MinTime to MaxTime. That is, min/max
229 field limits always works under the limitations of mintime/maxtime.
230
231 There is no provision to set the limits of AM/PM field.
232 ]]
233 }
234 keys {
235 fieldtype: Efl.Ui.Clock.Type; [[Type of the field. #EFL_UI_CLOCK_TYPE_YEAR etc.]]
236 }
237 values {
238 min: int; [[Reference to field's minimum value.]]
239 max: int; [[Reference to field's maximum value.]]
240 }
241 }
242 }
243 implements {
244 class.constructor;
245 Efl.Object.constructor;
246 Efl.Canvas.Group.group_add;
247 Efl.Canvas.Group.group_del;
248 Elm.Widget.theme_apply;
249 Elm.Widget.focus_next_manager_is;
250 Elm.Widget.focus_next;
251 Elm.Widget.disable;
252 Elm.Widget.on_focus;
253 Elm.Widget.translate;
254 Elm.Layout.sizing_eval;
255 }
256 events {
257 changed;
258 }
259
260}
diff --git a/src/lib/elementary/efl_ui_clock.h b/src/lib/elementary/efl_ui_clock.h
new file mode 100644
index 0000000000..4607d39af6
--- /dev/null
+++ b/src/lib/elementary/efl_ui_clock.h
@@ -0,0 +1,204 @@
1/**
2 * @defgroup efl_ui_clock
3 * @ingroup Elementary
4 *
5 * @image html clock_inheritance_tree.png
6 * @image latex clock_inheritance_tree.eps
7 *
8 * @image html img/widget/clock/preview-00.png
9 * @image latex img/widget/clock/preview-00.eps
10 *
11 * @image html img/widget/clock/preview-01.png
12 * @image latex img/widget/clock/preview-01.eps
13 *
14 * @image html img/widget/clock/preview-02.png
15 * @image latex img/widget/clock/preview-02.eps
16 *
17 * Clock widget is used to display and input date & time values.
18 * This widget displays date and time as per the <b>system's locale</b> settings (Date
19 * includes Day, Month & Year along with the defined separators and
20 * Time includes Hour, Minute & AM/PM fields. Separator for AM/PM field is ignored.
21 *
22 * The corresponding Month, AM/PM strings are displayed according to the
23 * system’s language settings.
24 *
25 * Clock format is a combination of LIBC standard characters like
26 * “%%d %%b %%Y %%I : %%M %%p” which, as a whole represents both Date as well as Time
27 * format.
28 *
29 * efl_ui_clock supports only the following sub set of libc date format specifiers:
30 *
31 * @b %%Y : The year as a decimal number including the century (example: 2011).
32 *
33 * @b %%y : The year as a decimal number without a century (range 00 to 99)
34 *
35 * @b %%m : The month as a decimal number (range 01 to 12).
36 *
37 * @b %%b : The abbreviated month name according to the current locale.
38 *
39 * @b %%B : The full month name according to the current locale.
40 *
41 * @b %%h : The abbreviated month name according to the current locale(same as %%b).
42 *
43 * @b %%d : The day of the month as a decimal number (range 01 to 31).
44 *
45 * @b %%e : The day of the month as a decimal number (range 1 to 31). single
46 * digits are preceded by a blank.
47 *
48 * @b %%I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
49 *
50 * @b %%H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
51 *
52 * @b %%k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
53 * digits are preceded by a blank.
54 *
55 * @b %%l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
56 * digits are preceded by a blank.
57 *
58 * @b %%M : The minute as a decimal number (range 00 to 59).
59 *
60 * @b %%p : Either 'AM' or 'PM' according to the given time value, or the
61 * corresponding strings for the current locale. Noon is treated as 'PM'
62 * and midnight as 'AM'
63 *
64 * @b %%P : Like %p but in lower case: 'am' or 'pm' or a corresponding string for
65 * the current locale.
66 *
67 * @b %%c : The preferred date and time representation for the current locale.
68 *
69 * @b %%x : The preferred date representation for the current locale without the time.
70 *
71 * @b %%X : The preferred time representation for the current locale without the date.
72 *
73 * @b %%r : The complete calendar time using the AM/PM format of the current locale.
74 *
75 * @b %%R : The hour and minute in decimal numbers using the format %H:%M.
76 *
77 * @b %%T : The time of day in decimal numbers using the format %H:%M:%S.
78 *
79 * @b %%D : The date using the format %%m/%%d/%%y.
80 *
81 * @b %%F : The date using the format %%Y-%%m-%%d.
82 *
83 * (For more reference on the available <b>LIBC date format specifiers</b>, please
84 * visit the link:
85 * http://www.gnu.org/s/hello/manual/libc.html#Formatting-Calendar-Time )
86 *
87 * Clock widget can provide Unicode @b separators in between its fields
88 * except for AM/PM field.
89 * A separator can be any <b>Unicode character</b> other than the LIBC standard
90 * date format specifiers.( Example: In the format %%b %%d @b , %%y %%H @b : %%M
91 * comma(,) is separator for date field %%d and colon(:) is separator for
92 * hour field %%H ).
93 *
94 * The default format is a predefined one, based on the system Locale.
95 *
96 * Hour format 12hr(1-12) or 24hr(0-23) display can be selected by setting
97 * the corresponding user format.
98 *
99 * Clock supports six fields: Year, Month, Date, Hour, Minute, AM/PM.
100 * Depending on the Clock module that is loaded, the user can see
101 * different UI to select the individual field values.
102 *
103 * The individual fields of Clock can be arranged in any order according to the format
104 * set by application.
105 *
106 * There is a provision to set the visibility of a particular field as TRUE/ FALSE
107 * so that <b>only time/ only date / only required fields</b> will be displayed.
108 *
109 * Each field is having a default minimum and maximum values just like the daily
110 * calendar information. These min/max values can be modified as per the application usage.
111 *
112 * User can enter the values only in between the range of maximum and minimum.
113 * Apart from these APIs, there is a provision to display only a limited set of
114 * values out of the possible values. APIs to select the individual field limits
115 * are intended for this purpose.
116 *
117 * The whole widget is left aligned and its size grows horizontally depending
118 * on the current format and each field's visible/disabled state.
119 *
120 * Clock individual field selection is implemented in a modular style.
121 * Module can be implemented as a Ctxpopup based selection or an ISE based
122 * selection or even a spinner like selection etc.
123 *
124 * <b>Clock Module design:</b>
125 *
126 * The following functions are expected to be implemented in a Clock module:
127 *
128 * <b>Field creation:</b>
129 * <pre>
130 *
131 * __________ __________
132 * | |----- obj_hook() ---------------------->>>| |
133 * | |<<<----------------returns Mod_data ------| |
134 * | Clock |_______ | |
135 * | widget | |Assign module call backs | Module |
136 * | base |<<<____| | |
137 * | | | |
138 * | |----- field_create() ------------------>>>| |
139 * |__________|<<<----------------returns field_obj -----|__________|
140 *
141 * </pre>
142 *
143 * <b>Field value setting:</b>
144 * <pre>
145 *
146 * __________ __________
147 * | | | |
148 * | Clock |<<<----------efl_ui_clock_value_set()---| |
149 * | widget | | Module |
150 * | base |----display_field_value()------------>>>| |
151 * |__________| |__________|
152 *
153 * </pre>
154 *
155 * <b>del_hook:</b>
156 * <pre>
157 * __________ __________
158 * | | | |
159 * | Clock |----obj_unhook()-------------------->>>>| |
160 * | widget | | Module |
161 * | base | <<<-----frees mod_data---------| |
162 * |__________| |__________|
163 *
164 * </pre>
165 *
166 *
167 * Any module can use the following shared functions that are implemented in efl_ui_clock.c :
168 *
169 * <b>field_format_get()</b> - gives the field format.
170 *
171 * <b>field_limit_get()</b> - gives the field minimum, maximum limits.
172 *
173 * To enable a module, set the ELM_MODULES environment variable as shown:
174 *
175 * <b>export ELM_MODULES="clock_input_ctxpopup>clock/api"</b>
176 *
177 * This widget inherits from the @ref Layout one, so that all the
178 * functions acting on it also work for Clock objects.
179 *
180 * This widget emits the following signals, besides the ones sent from
181 * @ref Layout:
182 * @li @b "changed" - whenever Clock field value is changed, this
183 * signal is sent.
184 * @li @b "language,changed" - whenever system locale changes, this
185 * signal is sent.
186 * @li @c "focused" - When the Clock has received focus. (since 1.8)
187 * @li @c "unfocused" - When the Clock has lost focus. (since 1.8)
188 *
189 * Here is an example on its usage:
190 * @li @ref clock_example
191 *
192 */
193
194/**
195 * @addtogroup efl_ui_clock
196 * @{
197 */
198
199#ifdef EFL_EO_API_SUPPORT
200#include "efl_ui_clock.eo.h"
201#endif
202/**
203 * @}
204 */
diff --git a/src/lib/elementary/efl_ui_clock_private.h b/src/lib/elementary/efl_ui_clock_private.h
new file mode 100644
index 0000000000..976fbbdbab
--- /dev/null
+++ b/src/lib/elementary/efl_ui_clock_private.h
@@ -0,0 +1,130 @@
1#ifndef EFL_UI_CLOCK_PRIVATE_H
2#define EFL_UI_CLOCK_PRIVATE_H
3
4#include "Elementary.h"
5
6/* DO NOT USE THIS HEADER UNLESS YOU ARE PREPARED FOR BREAKING OF YOUR
7 * CODE. THIS IS ELEMENTARY'S INTERNAL WIDGET API (for now) AND IS NOT
8 * FINAL. CALL elm_widget_api_check(ELM_INTERNAL_API_VERSION) TO CHECK
9 * IT AT RUNTIME.
10 */
11
12/**
13 * @addtogroup Widget
14 * @{
15 *
16 * @section efl-ui-clock-class The Elementary Clock Class
17 *
18 * Elementary, besides having the @ref Clock widget, exposes its
19 * foundation -- the Elementary Clock Class -- in order to create other
20 * widgets which are a Clock with some more logic on top.
21 */
22
23/**
24 * Base layout smart data extended with Clock instance data.
25 */
26typedef struct _Efl_Ui_Clock_Module_Data Efl_Ui_Clock_Module_Data;
27typedef struct _Efl_Ui_Clock_Data Efl_Ui_Clock_Data;
28typedef struct _Clock_Field Clock_Field;
29typedef struct _Clock_Mod_Api Clock_Mod_Api;
30typedef struct _Format_Map Format_Map;
31
32#define EFL_UI_CLOCK_TYPE_COUNT 8
33#define EFL_UI_CLOCK_MAX_FORMAT_LEN 64
34#define EFL_UI_CLOCK_MAX_FIELD_FORMAT_LEN 3
35
36struct _Efl_Ui_Clock_Module_Data
37{
38 Evas_Object *base;
39 void (*field_limit_get)(Evas_Object *obj,
40 Efl_Ui_Clock_Type field_type,
41 int *range_min,
42 int *range_max);
43 const char *(*field_format_get)(Evas_Object * obj,
44 Efl_Ui_Clock_Type field_type);
45};
46
47struct _Clock_Field
48{
49 Evas_Object *item_obj;
50 char fmt[EFL_UI_CLOCK_MAX_FIELD_FORMAT_LEN];
51 Efl_Ui_Clock_Type type;
52 const char *separator;
53 int location; /* location of the field as per
54 * current format */
55 int min, max;
56 Eina_Bool fmt_exist : 1; /* whether field format is
57 * present or not */
58 Eina_Bool visible : 1; /* whether field can be
59 * visible or not */
60};
61
62struct _Clock_Mod_Api
63{
64 Efl_Ui_Clock_Module_Data *(*obj_hook)(Evas_Object * obj);
65 void (*obj_unhook)(Efl_Ui_Clock_Module_Data *mdata);
66 void (*obj_hide)(Efl_Ui_Clock_Module_Data *mdata);
67 Evas_Object *(*field_create)(Efl_Ui_Clock_Module_Data * mdata,
68 Efl_Ui_Clock_Type ftype);
69 void (*field_value_display)(Efl_Ui_Clock_Module_Data
70 *mdata,
71 Evas_Object *obj);
72};
73
74struct _Efl_Ui_Clock_Data
75{
76 /* fixed set of fields. */
77 Clock_Field field_list[EFL_UI_CLOCK_TYPE_COUNT];
78 struct tm curr_time, min_limit, max_limit;
79 Efl_Ui_Clock_Module_Data *mod_data;
80 char format[EFL_UI_CLOCK_MAX_FORMAT_LEN];
81 Evas_Object *access_obj;
82 int enabled_field_count;
83 Ecore_Timer *ticker;
84 Eina_Bool paused : 1;
85 Eina_Bool edit_mode : 1;
86 Eina_Bool user_format : 1; /* whether user set
87 * format or default
88 * format. */
89 Eina_Bool freeze_sizing : 1; /* freeze sizing_eval to
90 * reduce unnecessary sizing */
91};
92
93struct _Format_Map
94{
95 char *fmt_char;
96 int def_min;
97 int def_max;
98 char *ignore_sep;
99};
100
101/**
102 * @}
103 */
104
105#define EFL_UI_CLOCK_DATA_GET(o, sd) \
106 Efl_Ui_Clock_Data * sd = efl_data_scope_get(o, EFL_UI_CLOCK_CLASS)
107
108#define EFL_UI_CLOCK_DATA_GET_OR_RETURN(o, ptr) \
109 EFL_UI_CLOCK_DATA_GET(o, ptr); \
110 if (EINA_UNLIKELY(!ptr)) \
111 { \
112 CRI("No widget data for object %p (%s)", \
113 o, evas_object_type_get(o)); \
114 return; \
115 }
116
117#define EFL_UI_CLOCK_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
118 EFL_UI_CLOCK_DATA_GET(o, ptr); \
119 if (EINA_UNLIKELY(!ptr)) \
120 { \
121 CRI("No widget data for object %p (%s)", \
122 o, evas_object_type_get(o)); \
123 return val; \
124 }
125
126#define EFL_UI_CLOCK_CHECK(obj) \
127 if (EINA_UNLIKELY(!eo_isa((obj), EFL_UI_CLOCK_CLASS))) \
128 return
129
130#endif
diff --git a/src/lib/elementary/elm_config.c b/src/lib/elementary/elm_config.c
index 4661611fed..513a1546fa 100644
--- a/src/lib/elementary/elm_config.c
+++ b/src/lib/elementary/elm_config.c
@@ -2194,6 +2194,10 @@ _config_update(void)
2194 IFCFG(0x000a) 2194 IFCFG(0x000a)
2195 _elm_config->icon_theme = eina_stringshare_add(ELM_CONFIG_ICON_THEME_ELEMENTARY); 2195 _elm_config->icon_theme = eina_stringshare_add(ELM_CONFIG_ICON_THEME_ELEMENTARY);
2196 IFCFGEND 2196 IFCFGEND
2197
2198 IFCFG(0x000b)
2199 eina_stringshare_refplace(&_elm_config->modules, tcfg->modules);
2200 IFCFGEND
2197 /** 2201 /**
2198 * Fix user config for current ELM_CONFIG_EPOCH here. 2202 * Fix user config for current ELM_CONFIG_EPOCH here.
2199 **/ 2203 **/