apply FSL(Flora Software License)
[apps/home/draglock.git] / src / draglock-time.c
1 /*
2   * Copyright 2012  Samsung Electronics Co., Ltd
3   * 
4   * Licensed under the Flora License, Version 1.0 (the License);
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   * 
8   *     http://www.tizenopensource.org/license
9   * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an AS IS BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16
17
18 #include <time.h>
19 #include <runtime_info.h>
20 #include <unicode/uloc.h>
21 #include <unicode/udat.h>
22 #include <unicode/udatpg.h>
23 #include <unicode/ustring.h>
24
25 #include "draglock.h"
26 #include "draglock-util.h"
27
28 #define DRAGLOCK_SUPPORT_ICU
29
30 static Eina_Bool _draglock_get_time(struct tm *st, char *data, int len,
31                 int *is_24hour) {
32
33         int r = -1, hour = 0;
34         char temp[32] = { 0, };
35         bool is_24hour_enabled = 0;
36
37         if (st == NULL) {
38                 DRAGLOCK_ERR("st is NULL");
39                 return EINA_FALSE;
40         }
41         if (data == NULL || len <= 0) {
42                 DRAGLOCK_ERR("data is NULL");
43                 return EINA_FALSE;
44         }
45         if (is_24hour == NULL) {
46                 DRAGLOCK_ERR("is_24hour is NULL");
47                 return EINA_FALSE;
48         }
49
50         r = runtime_info_get_value_bool(
51                         RUNTIME_INFO_KEY_24HOUR_CLOCK_FORMAT_ENABLED, &is_24hour_enabled);
52
53         DRAGLOCK_DBG("r:%d, is_24hour_enabled:%d bufSize:%d",
54                         r, is_24hour_enabled, sizeof(data));
55
56         if (r == RUNTIME_INFO_ERROR_NONE && is_24hour_enabled == 1) {
57                 strftime(data, len, "%H:%M", st);
58         } else {
59                 /* if %l is 1 ~9, it has blank space in front. Trim it using atoi function */
60                 strftime(temp, sizeof(temp), "%l", st);
61                 hour = atoi(temp);
62                 strftime(temp, sizeof(temp), ":%M", st);
63
64                 snprintf(data, len, "%d%s", hour, temp);
65         }
66
67         *is_24hour = is_24hour_enabled;
68         DRAGLOCK_DBG("data = %s", data);
69
70         return EINA_TRUE;
71 }
72
73 static Eina_Bool _draglock_get_date(time_t tt, char *data) {
74         UErrorCode status = U_ZERO_ERROR;
75         UDateTimePatternGenerator *generator;
76         UDateFormat *formatter;
77         UChar skeleton[40] = { 0 }, pattern[40] = { 0 }, formatted[40] = { 0 };
78         int32_t patternCapacity, formattedCapacity;
79         int32_t skeletonLength, patternLength, formattedLength;
80         UDate date;
81         const char *locale;
82         const char customSkeleton[] = UDAT_MONTH_WEEKDAY_DAY;
83
84         /* set UDate  from time_t */
85         date = (UDate) tt * 1000;
86
87         /* get default locale  */
88         uloc_setDefault(__secure_getenv("LC_TIME"), &status); /* for thread saftey  */
89         locale = uloc_getDefault();
90
91         /* open datetime pattern generator */
92         generator = udatpg_open(locale, &status);
93         if (generator == NULL)
94                 return EINA_FALSE;
95
96         /* calculate pattern string capacity */
97         patternCapacity = (int32_t)(sizeof(pattern) / sizeof((pattern)[0]));
98
99         /* ascii to unicode for input skeleton */
100         u_uastrcpy(skeleton, customSkeleton);
101
102         /* get skeleton length */
103         skeletonLength = strlen(customSkeleton);
104
105         /* get best pattern using skeleton */
106         patternLength = udatpg_getBestPattern(generator, skeleton, skeletonLength,
107                         pattern, patternCapacity, &status);
108
109         /* open datetime formatter using best pattern */
110         formatter = udat_open(UDAT_IGNORE, UDAT_DEFAULT, locale, NULL, -1, pattern,
111                         patternLength, &status);
112         if (formatter == NULL) {
113                 udatpg_close(generator);
114                 return EINA_FALSE;
115         }
116
117         /* calculate formatted string capacity */
118         formattedCapacity = (int32_t)(sizeof(formatted) / sizeof((formatted)[0]));
119
120         /* formatting date using formatter by best pattern */
121         formattedLength = udat_format(formatter, date, formatted, formattedCapacity,
122                         NULL, &status);
123
124         /* unicode to ascii to display */
125         u_austrcpy(data, formatted);
126         DRAGLOCK_DBG("formatted string=%s", data);
127
128         /* close datetime pattern generator */
129         udatpg_close(generator);
130
131         /* close datetime formatter */
132         udat_close(formatter);
133
134         return EINA_TRUE;
135 }
136
137 static Eina_Bool _draglock_time_set_date(void *data) {
138         struct appdata *ad = (struct appdata *) data;
139
140         if (ad == NULL || ad->time_layout == NULL) {
141                 return ECORE_CALLBACK_CANCEL;
142         }
143
144         int is_24hour = 0;
145         struct tm st;
146         time_t tt;
147         char buf[128] = { 0, };
148
149         tt = time(NULL);
150         localtime_r(&tt, &st);
151
152         if (ad->clock_timer != NULL) {
153                 ecore_timer_del(ad->clock_timer);
154                 ad->clock_timer = NULL;
155         }
156
157         ad->clock_timer = ecore_timer_add(60 - st.tm_sec, _draglock_time_set_date,
158                         ad);
159
160 #ifdef DRAGLOCK_SUPPORT_ICU
161         if (_draglock_get_date(tt, buf) == EINA_TRUE)
162                 elm_object_part_text_set(ad->time_layout, "text.date", buf);
163 #else
164         strftime(buf, sizeof(buf), "%b %d, %A", &st);
165         elm_object_part_text_set(ad->time_layout, "text.date", buf);
166 #endif
167
168         if (_draglock_get_time(&st, buf, sizeof(buf), &is_24hour) == EINA_TRUE) {
169
170                 if (is_24hour == 0) {
171                         if ((st.tm_hour >= 22 && st.tm_hour <= 23)
172                                         || (st.tm_hour >= 10 && st.tm_hour <= 12)
173                                         || (st.tm_hour == 0)) {
174                                 edje_object_signal_emit(_EDJ(ad->time_layout), "period.stretch",
175                                                 "rect.time.period");
176                         } else {
177                                 edje_object_signal_emit(_EDJ(ad->time_layout), "period.default",
178                                                 "rect.time.period");
179                         }
180
181                         if (st.tm_hour >= 0 && st.tm_hour < 12) {
182                                 elm_object_part_text_set(ad->time_layout, "text.time.period",
183                                                 "AM");
184                         } else {
185                                 elm_object_part_text_set(ad->time_layout, "text.time.period",
186                                                 "PM");
187                         }
188                 } else {
189                         elm_object_part_text_set(ad->time_layout, "text.time.period", "");
190                 }
191                 elm_object_part_text_set(ad->time_layout, "text.time", buf);
192         }
193
194         return ECORE_CALLBACK_CANCEL;
195 }
196
197 static void _draglock_power_changed_cb(power_state_e state, void *user_data) {
198         power_state_e current_power_state;
199         struct appdata *ad = (struct appdata *) user_data;
200
201         if (ad == NULL) {
202                 DRAGLOCK_DBG("ad or ad->ui_layout is null");
203                 return;
204         }
205
206         current_power_state = power_get_state();
207
208         DRAGLOCK_DBG("prev p-state:%d cur p-state:%d",
209                         ad->power_state, current_power_state);
210
211         if (ad->power_state == POWER_STATE_SCREEN_OFF
212                         && (current_power_state == POWER_STATE_SCREEN_DIM
213                                         || current_power_state == POWER_STATE_NORMAL)) {
214                 _draglock_time_set_date(user_data);
215                 DRAGLOCK_DBG("(after sleep)time updated");
216         }
217
218         ad->power_state = current_power_state;
219 }
220
221 Evas_Object *draglock_time_get_time(void *data) {
222         struct appdata *ad = (struct appdata *) data;
223         Evas_Object *layout = NULL;
224
225         if (ad == NULL || ad->ui_layout == NULL) {
226                 DRAGLOCK_DBG("ad or ad->ui_layout is null");
227                 return NULL;
228         }
229
230         layout = draglock_util_add_layout(ad->ui_layout, EDJEFILE, "draglock-time");
231         ad->time_layout = layout;
232
233         if (layout == NULL) {
234                 return NULL;
235         }
236
237         _draglock_time_set_date(ad);
238
239         ad->power_state = power_get_state();
240         power_set_changed_cb(_draglock_power_changed_cb, ad);
241
242         return layout;
243 }