Modify the screen UI for stt mode and refactoring code
[platform/core/uifw/inputdelegator.git] / src / w-input-emoticon.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
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 #include <app.h>
18 #include <app_preference.h>
19 #include <Elementary.h>
20 #include <string>
21 #include <vector>
22 #include <stdint.h>
23
24 #include <vconf.h>
25 #include <vconf-keys.h>
26
27 #include "Debug.h"
28 #include "w-input-selector.h"
29
30 #define RECENT_EMOJI_LIST "recent_emoji_list"
31
32 #define EMOTICON_CNT 180
33 #define RECENT_CNT 9
34
35 extern App_Data* app_data;
36
37 static int is_content_reuse_on = 0;
38
39
40 using namespace std;
41
42 vector <int> recent_emoji_list;
43
44 typedef struct {
45     int code;
46     const char* name;
47 }Emoticon;
48
49 static Elm_Object_Item *it_emoticon_empty = NULL;
50 static Elm_Object_Item *it_emoticon_recent_group = NULL;
51 static Elm_Object_Item *it_emoticon_emoji_group = NULL;
52 static Elm_Object_Item* it_drawing = NULL;
53 static Elm_Object_Item *it_last = NULL;
54
55 static Elm_Genlist_Item_Class *itc_emoticon = NULL;
56
57 #define INITAL_ITEM_UNIT 24
58 #define LOADING_ITEM_UNIT 27
59 static int loading_done_for_item = 0;
60 Ecore_Timer *lazy_loading_timer_for_items = NULL;
61
62 #define INITAL_CONTENT_UNIT 51
63 #define LOADING_CONTENT_UNIT 9
64 static int loading_done_for_contents = 0;
65 Ecore_Timer *lazy_loading_timer_for_contents = NULL;
66
67
68 typedef struct emoticon_content
69 {
70     int index;
71     Evas_Object *content;
72     int used;
73 } emoticon_content_s;
74
75 static emoticon_content_s emoticon_contents_pool[EMOTICON_CNT] = { 0, };
76 static emoticon_content_s emoticon_drawing_pool = { 0, };
77 static emoticon_content_s emoticon_recents_pool[RECENT_CNT] = { 0, };
78
79
80 Emoticon emoticon_info[EMOTICON_CNT] = {
81     {0x1f600, ""},
82     {0x1f601, ""},
83     {0x1f602, ""},
84     {0x1f603, ""},
85     {0x1f604, ""},
86     {0x1f605, ""},
87     {0x1f606, ""},
88     {0x1f609, ""},
89     {0x1f60a, ""},
90     {0x1f60b, ""},
91     {0x1f60e, ""},
92     {0x1f60d, ""},
93     {0x1f618, ""},
94     {0x1f617, ""},
95     {0x1f619, ""},
96     {0x1f61a, ""},
97     {0x263a, ""},
98     {0x1f642, ""},
99     {0x1f917, ""},
100     {0x1f607, ""},
101     {0x1f914, ""},
102     {0x1f610, ""},
103     {0x1f611, ""},
104     {0x1f636, ""},
105     {0x1f644, ""},
106     {0x1f60f, ""},
107     {0x1f623, ""},
108     {0x1f625, ""},
109     {0x1f62e, ""},
110     {0x1f910, ""},
111     {0x1f62f, ""},
112     {0x1f634, ""},
113     {0x1f62a, ""},
114     {0x1f62b, ""},
115     {0x1f60c, ""},
116     {0x1f913, ""},
117     {0x1f61b, ""},
118     {0x1f61c, ""},
119     {0x1f61d, ""},
120     {0x1f641, ""},
121     {0x1f612, ""},
122     {0x1f613, ""},
123     {0x1f614, ""},
124     {0x1f615, ""},
125     {0x1f616, ""},
126     {0x1f643, ""},
127     {0x1f637, ""},
128     {0x1f912, ""},
129     {0x1f915, ""},
130     {0x1f911, ""},
131     {0x1f632, ""},
132     {0x1f61e, ""},
133     {0x1f61f, ""},
134     {0x1f624, ""},
135     {0x1f622, ""},
136     {0x1f62d, ""},
137     {0x1f626, ""},
138     {0x1f627, ""},
139     {0x1f628, ""},
140     {0x1f629, ""},
141     {0x1f62c, ""},
142     {0x1f630, ""},
143     {0x1f631, ""},
144     {0x1f633, ""},
145     {0x1f635, ""},
146     {0x1f621, ""},
147     {0x1f620, ""},
148     {0x1f608, ""},
149     {0x1f648, ""},
150     {0x1f649, ""},
151     {0x1f64a, ""},
152     {0x1f448, ""},
153     {0x1f449, ""},
154     {0x261d, ""},
155     {0x1f446, ""},
156     {0x1f595, ""},
157     {0x1f447, ""},
158     {0x270c, ""},
159     {0x1f596, ""},
160     {0x1f918, ""},
161     {0x1f591, ""},
162     {0x1f590, ""},
163     {0x270a, ""},
164     {0x270b, ""},
165     {0x1f44a, ""},
166     {0x1f44c, ""},
167     {0x1f44d, ""},
168     {0x1f44e, ""},
169     {0x1f592, ""},
170     {0x1f593, ""},
171     {0x1f44b, ""},
172     {0x1f44f, ""},
173     {0x1f450, ""},
174     {0x1f493, ""},
175     {0x1f494, ""},
176     {0x1f495, ""},
177     {0x1f496, ""},
178     {0x1f497, ""},
179     {0x1f49d, ""},
180     {0x1f49e, ""},
181     {0x1f49f, ""},
182     {0x2763, ""},
183     {0x1f35e, ""},
184     {0x1f9c0, ""},
185     {0x1f356, ""},
186     {0x1f357, ""},
187     {0x1f354, ""},
188     {0x1f35f, ""},
189     {0x1f355, ""},
190     {0x1f32d, ""},
191     {0x1f32e, ""},
192     {0x1f32f, ""},
193     {0x1f37f, ""},
194     {0x1f372, ""},
195     {0x1f371, ""},
196     {0x1f358, ""},
197     {0x1f359, ""},
198     {0x1f35a, ""},
199     {0x1f35c, ""},
200     {0x1f35b, ""},
201     {0x1f35d, ""},
202     {0x1f360, ""},
203     {0x1f362, ""},
204     {0x1f363, ""},
205     {0x1f364, ""},
206     {0x1f365, ""},
207     {0x1f361, ""},
208     {0x1f366, ""},
209     {0x1f368, ""},
210     {0x1f367, ""},
211     {0x1f369, ""},
212     {0x1f36a, ""},
213     {0x1f382, ""},
214     {0x1f370, ""},
215     {0x1f36b, ""},
216     {0x1f36c, ""},
217     {0x1f36d, ""},
218     {0x1f36e, ""},
219     {0x1f36f, ""},
220     {0x1f37c, ""},
221     {0x2615, ""},
222     {0x1f375, ""},
223     {0x1f376, ""},
224     {0x1f37e, ""},
225     {0x1f377, ""},
226     {0x1f378, ""},
227     {0x1f379, ""},
228     {0x1f37a, ""},
229     {0x1f37b, ""},
230     {0x1f383, ""},
231     {0x1f384, ""},
232     {0x1f388, ""},
233     {0x1f389, ""},
234     {0x1f38a, ""},
235     {0x26bd, ""},
236     {0x26be, ""},
237     {0x1f3c0, ""},
238     {0x1f3c8, ""},
239     {0x1f3c9, ""},
240     {0x1f3be, ""},
241     {0x1f3b1, ""},
242     {0x1f3b3, ""},
243     {0x26f3, ""},
244     {0x26f8, ""},
245     {0x1f3a3, ""},
246     {0x1f3bf, ""},
247     {0x1f3cf, ""},
248     {0x1f3d0, ""},
249     {0x1f3d1, ""},
250     {0x1f3d2, ""},
251     {0x1f3d3, ""},
252     {0x1f3f8, ""},
253     {0x1f3af, ""},
254     {0x1f3b2, ""},
255     {0x1f3df, ""},
256     {0x1f3db, ""},
257     {0x1f3e0, ""},
258     {0x1f3e2, ""},
259     {0x1f3e5, ""},
260     {0x1f3eb, ""},
261 };
262
263
264 //---------------------------------------------------------------------------------------//
265
266 static Eina_Bool _custom_back_cb2(void *data, Elm_Object_Item *it)
267 {
268     PRINTFUNC(DLOG_DEBUG, "");
269
270     if (is_content_reuse_on) {
271         int i;
272
273         if (lazy_loading_timer_for_items != NULL) {
274             ecore_timer_del(lazy_loading_timer_for_items);
275             lazy_loading_timer_for_items = NULL;
276         }
277
278         if (lazy_loading_timer_for_contents != NULL) {
279             ecore_timer_del(lazy_loading_timer_for_contents);
280             lazy_loading_timer_for_contents = NULL;
281         }
282
283         if (emoticon_drawing_pool.used == 0){
284             evas_object_del(emoticon_drawing_pool.content);
285         }
286         emoticon_drawing_pool.content = NULL;
287
288         //Recent EMOTICONS : the recent emoiton need to be updated whenever emoticon view is generated, so deleted here.
289         for (i=0;i< RECENT_CNT;i++)
290         {
291             if (emoticon_recents_pool[i].used == 0 && emoticon_recents_pool[i].content) {
292                 evas_object_del(emoticon_recents_pool[i].content);
293             }
294             emoticon_recents_pool[i].content = NULL;
295         }
296     }
297
298     _back_to_genlist_for_selector();
299     return EINA_TRUE;
300 }
301
302
303 void get_recent_emoticons(vector <int> &emoticon_list)
304 {
305     int ret = PREFERENCE_ERROR_NONE;
306     char *str = NULL;
307
308     ret = preference_get_string(RECENT_EMOJI_LIST, &str);
309     if (PREFERENCE_ERROR_NONE != ret) {
310         PRINTFUNC(DLOG_ERROR, "preference_get_string error!(%d)", ret);
311     }
312
313     emoticon_list.clear();
314
315     PRINTFUNC(DLOG_DEBUG, "str = %s", str);
316
317     if (str != NULL) {
318         char *tok, *ptr;
319         tok = strtok_r(str, ",", &ptr);
320         while (tok != NULL) {
321             PRINTFUNC(DLOG_DEBUG, "tok = %s", tok);
322             emoticon_list.push_back(strtol(tok, (char **)NULL, 10));
323             tok = strtok_r(NULL, ",", &ptr);
324         }
325     }
326
327     if (str)
328         free(str);
329
330     return;
331 }
332
333 void set_recent_emoticons(vector <int> &emoticon_list, int val)
334 {
335     unsigned int i;
336     int ret = PREFERENCE_ERROR_NONE;
337
338     if (emoticon_list.size() > 0) {
339         for (i = 0; i < emoticon_list.size(); i++) {
340             PRINTFUNC(DLOG_DEBUG, "%d == %d", emoticon_list.at(i), val);
341
342             if (emoticon_list.at(i) == val) {
343                 emoticon_list.erase(emoticon_list.begin()+i);
344                 break;
345             }
346         }
347
348         if (emoticon_list.size() >= RECENT_CNT) {
349             emoticon_list.erase(emoticon_list.end());
350         }
351     }
352
353     emoticon_list.insert(emoticon_list.begin(), val);
354
355     string stored;
356     char str[10] = {0, };
357
358     for (i = 0; i < emoticon_list.size(); i++) {
359         snprintf(str, sizeof(str), "%d", emoticon_list.at(i));
360         stored += str;
361         if (i+1 != emoticon_list.size())
362             stored += ",";
363     }
364
365     PRINTFUNC(DLOG_DEBUG, "%s", stored.c_str());
366
367     ret = preference_set_string(RECENT_EMOJI_LIST, stored.c_str());
368     if (PREFERENCE_ERROR_NONE != ret) {
369         PRINTFUNC(DLOG_ERROR, "preference_set_string error!(%d)", ret);
370     }
371 }
372
373 static void _drawing_app_control_reply_cb(app_control_h request, app_control_h reply, app_control_result_e result, void *user_data)
374 {
375     char* path = NULL;
376     app_control_get_extra_data(reply, APP_CONTROL_DATA_PATH, &path);
377
378     if (path){
379         PRINTFUNC(DLOG_DEBUG, "path=%s", path);
380         char *pathes[] = {path, };
381         reply_to_sender_by_callback(NULL, "image", (const char **)pathes, NULL);
382         free(path);
383     }
384     ui_app_exit();
385 }
386
387 static void _drawing_item_clicked_cb(void *data, Evas_Object * obj, void *event_info)
388 {
389     PRINTFUNC(DLOG_DEBUG, "%s", __func__);
390     App_Data* ad = (App_Data*) data;
391     if (!ad)
392         return;
393
394     Elm_Object_Item *item = (Elm_Object_Item *) event_info;
395     if (item)
396         elm_genlist_item_selected_set(item, EINA_FALSE);
397
398     /* launch */
399     app_control_h request = NULL;
400     app_control_create(&request);
401     app_control_set_app_id(request, "org.tizen.sketch");
402
403     int ret = app_control_send_launch_request(request, _drawing_app_control_reply_cb, NULL);
404     if (ret != APP_CONTROL_ERROR_NONE) {
405         PRINTFUNC(DLOG_DEBUG, "error code = 0x%x", ret);
406     }
407     app_control_destroy(request);
408 }
409
410 static void _emoticon_item_clicked_cb(void *data, Evas_Object * obj, void *event_info)
411 {
412     int index = (uintptr_t)data;
413
414     PRINTFUNC(DLOG_DEBUG, "index = %d", index);
415
416     // store in recents list
417     set_recent_emoticons(recent_emoji_list, index);
418
419     int length;
420     const Eina_Unicode unicode_event[2] = { (Eina_Unicode)emoticon_info[index].code, 0 };
421     char* utf_8 = eina_unicode_unicode_to_utf8(unicode_event, &length);
422
423     reply_to_sender_by_callback((const char*)utf_8, "emoticon", NULL, NULL);
424
425     PRINTFUNC(SECURE_DEBUG, "[%d]%s", index, utf_8);
426     if (utf_8)
427         free(utf_8);
428
429     ui_app_exit();
430 }
431
432 Evas_Object* get_emoticon_button(Evas_Object* parent, int index){
433     if (parent == NULL)
434         return NULL;
435
436      Evas_Object* btn = elm_button_add(parent);
437      elm_object_style_set(btn, "emoticon");
438      evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
439      evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
440
441      int length;
442      const Eina_Unicode unicode_event[2] = { (Eina_Unicode)emoticon_info[index].code, 0 };
443      char* utf_8 = eina_unicode_unicode_to_utf8(unicode_event, &length);
444      elm_object_part_text_set(btn, "elm.text", utf_8);
445
446      if (utf_8)
447          free(utf_8);
448
449      evas_object_layer_set(btn, 32000);
450
451      evas_object_smart_callback_add(btn, "clicked", _emoticon_item_clicked_cb, (void *)(uintptr_t)index);
452
453      return btn;
454 }
455
456 Evas_Object* get_recent_emoticon_button(Evas_Object* parent, int index){
457     if (parent == NULL)
458         return NULL;
459
460      Evas_Object* btn = elm_button_add(parent);
461      elm_object_style_set(btn, "emoticon");
462      evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
463      evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
464
465      int length;
466      const Eina_Unicode unicode_event[2] = { (Eina_Unicode)emoticon_info[recent_emoji_list.at(index)].code, 0 };
467      char* utf_8 = eina_unicode_unicode_to_utf8(unicode_event, &length);
468      elm_object_part_text_set(btn, "elm.text", utf_8);
469
470      evas_object_data_set(btn, "index", (void*)(uintptr_t) recent_emoji_list.at(index));
471
472      if (utf_8)
473          free(utf_8);
474
475      evas_object_layer_set(btn, 32000);
476      evas_object_smart_callback_add(btn, "clicked", _emoticon_item_clicked_cb, (void*)(uintptr_t) recent_emoji_list.at(index));
477
478      return btn;
479 }
480
481 static void _emoticon_gl_lang_changed(void *data, Evas_Object *obj, void *event_info)
482 {
483     elm_genlist_realized_items_update(obj);
484 }
485
486 static char * __emoticon_gl_text_get(void *data, Evas_Object *obj, const char *part)
487 {
488     //PRINTFUNC(DLOG_DEBUG,"part = %s", part);
489     const char* str = (const char*) data;
490     if (!str)
491         return NULL;
492
493     if (!strcmp(part, "elm.text")) {
494         //PRINTFUNC(DLOG_DEBUG,"str = %s", str);
495         return strdup(gettext(str));
496     }
497     return NULL;
498 }
499
500 static void _emoticon_gl_content_unswallowed_cb(void *data, Evas_Object *obj, void *event_info)
501 {
502     Elm_Object_Item *it = (Elm_Object_Item *)event_info;
503
504     const Elm_Genlist_Item_Class *itc = elm_genlist_item_item_class_get(it);
505
506     //PRINTFUNC(DLOG_DEBUG,"%s - stype[%s]", __func__, itc->item_style);
507     if (!strcmp(itc->item_style, "3button_flat")) {
508         int index = (uintptr_t)elm_object_item_data_get(it);
509         //PRINTFUNC(DLOG_DEBUG,"it = %p", it);
510         PRINTFUNC(DLOG_DEBUG, "index = %d %d %d", index, index+1, index+2);
511
512         if (index < EMOTICON_CNT) {
513             emoticon_contents_pool[index].used = 0;
514         }
515         if (index + 1 < EMOTICON_CNT) {
516             emoticon_contents_pool[index+1].used = 0;
517         }
518         if (index + 2 < EMOTICON_CNT) {
519             emoticon_contents_pool[index+2].used = 0;
520         }
521     } else if (!strcmp(itc->item_style, "3button_flat_recent")) {
522         unsigned int index = (uintptr_t)elm_object_item_data_get(it);
523         //PRINTFUNC(DLOG_DEBUG,"index = %d",index);
524
525         if (index < recent_emoji_list.size()) {
526             emoticon_recents_pool[index].used = 0;
527         }
528         if (index + 1 < recent_emoji_list.size()) {
529             emoticon_recents_pool[index+1].used = 0;
530         }
531         if (index + 2 < recent_emoji_list.size()) {
532             emoticon_recents_pool[index+2].used = 0;
533         }
534     } else if (it_drawing == it) {
535         //PRINTFUNC(DLOG_DEBUG,"it_drawing = %p", it_drawing);
536         emoticon_drawing_pool.used = 0;
537     }
538 }
539
540 static Evas_Object * __emoticon_gl_1_content_get(void *data, Evas_Object *obj, const char *part)
541 {
542     if (!strcmp(part, "elm.icon")) {
543         Evas_Object* btn = elm_button_add(obj);
544         evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
545         evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
546         Evas_Object* ic = elm_image_add(btn);
547         elm_image_resizable_set(ic, EINA_TRUE, EINA_TRUE);
548
549         string path = get_resource_path();
550         if (_WEARABLE)
551             path = path + "wearable/";
552         else if (_TV)
553             path = path + "tv/";
554         else
555             path = path + "mobile/";
556
557         elm_object_style_set(btn, "ime_button_drawing");
558         string path_ic = path + "images/wi_drawing_icon.png";
559         PRINTFUNC(DLOG_DEBUG, "path_ic = %s", path_ic.c_str());
560         elm_image_file_set(ic, path_ic.c_str(), NULL);
561         elm_object_content_set(btn, ic);
562         evas_object_layer_set(btn, 32000);
563
564         emoticon_drawing_pool.index = 0;
565         emoticon_drawing_pool.content = btn;
566         emoticon_drawing_pool.used = 0;
567         return btn;
568     } else if (!strcmp(part, "base")){
569         Evas_Object* btn = elm_button_add(obj);
570         elm_object_style_set(btn, "ime/transparent");
571         return btn;
572     }
573     return NULL;
574 }
575
576 static Evas_Object * __emoticon_gl_recent_content_get(void *data, Evas_Object *obj, const char *part)
577 {
578     if (is_content_reuse_on) {
579         unsigned int index = (uintptr_t)data;
580         int new_index = 0;
581
582         //PRINTFUNC(DLOG_DEBUG,"%s %d", part, index);
583         if (!strcmp(part, "elm.icon.1") || (!strcmp(part, "elm.icon.2")) || (!strcmp(part, "elm.icon.3"))) {
584             if (!strcmp(part, "elm.icon.1")) {
585                 if (index >= recent_emoji_list.size()) return NULL;
586                 new_index = index;
587             } else if (!strcmp(part, "elm.icon.2")) {
588                 if (index + 1 >= recent_emoji_list.size()) return NULL;
589                 new_index = index + 1;
590             } else if (!strcmp(part, "elm.icon.3")) {
591                 if (index + 2 >= recent_emoji_list.size()) return NULL;
592                 new_index = index + 2;
593             }
594
595             Evas_Object* btn = NULL;
596             btn = (Evas_Object*)emoticon_recents_pool[new_index].content;
597             emoticon_recents_pool[new_index].used = 1;
598             return btn;
599         } else if (!strcmp(part, "base")) {
600             Evas_Object* btn = elm_button_add(obj);
601             elm_object_style_set(btn, "ime/transparent");
602             return btn;
603         }
604     } else {
605         unsigned int index = (uintptr_t)data;
606         int new_index = 0;
607
608         //PRINTFUNC(DLOG_DEBUG,"%s %d", part, index);
609         if (!strcmp(part, "elm.icon.1") || (!strcmp(part, "elm.icon.2")) || (!strcmp(part, "elm.icon.3"))) {
610             if (!strcmp(part, "elm.icon.1")) {
611                 if (index >= recent_emoji_list.size()) return NULL;
612                 new_index = index;
613             } else if (!strcmp(part, "elm.icon.2")) {
614                 if (index + 1 >= recent_emoji_list.size()) return NULL;
615                 new_index = index + 1;
616             } else if (!strcmp(part, "elm.icon.3")) {
617                 if (index + 2 >= recent_emoji_list.size()) return NULL;
618                 new_index = index + 2;
619             }
620             return get_recent_emoticon_button(obj, new_index);
621         } else if (!strcmp(part, "base")) {
622             Evas_Object* btn = elm_button_add(obj);
623             elm_object_style_set(btn, "ime/transparent");
624             return btn;
625         }
626     }
627     return NULL;
628 }
629
630 static Evas_Object * __emoticon_gl_emoticon_content_get(void *data, Evas_Object *obj, const char *part)
631 {
632     //PRINTFUNC(DLOG_DEBUG,"%s", __func__);
633     if (is_content_reuse_on) {
634         int index = (uintptr_t)data;
635         int new_index = 0;
636
637         if (!strcmp(part, "elm.icon.1") || (!strcmp(part, "elm.icon.2")) || (!strcmp(part, "elm.icon.3"))) {
638             if (!strcmp(part, "elm.icon.1")) {
639                 if (index >= EMOTICON_CNT) return NULL;
640                 new_index = index;
641             } else if (!strcmp(part, "elm.icon.2")) {
642                 if (index + 1 >= EMOTICON_CNT) return NULL;
643                 new_index = index + 1;
644             } else if (!strcmp(part, "elm.icon.3")) {
645                 if (index + 2 >= EMOTICON_CNT) return NULL;
646                 new_index = index + 2;
647             }
648
649             Evas_Object* btn = NULL;
650             btn = (Evas_Object*)emoticon_contents_pool[new_index].content;
651             emoticon_contents_pool[new_index].used = 1;
652 #if 0
653             char utf_8[10] = {0, };
654             snprintf(utf_8, sizeof(utf_8), "%d", new_index);
655             elm_object_part_text_set(btn, "elm.text", strdup(utf_8));
656 #else
657             int length;
658             const Eina_Unicode unicode_event[2] = { (Eina_Unicode)emoticon_info[new_index].code, 0 };
659             char* utf_8 = eina_unicode_unicode_to_utf8(unicode_event, &length);
660             elm_object_part_text_set(btn, "elm.text", utf_8);
661             evas_object_data_set(btn, "index", (void*)(uintptr_t)new_index);
662
663             if (utf_8)
664                 free(utf_8);
665 #endif
666             return btn;
667
668         } else if (!strcmp(part, "base")) {
669             Evas_Object* btn = elm_button_add(obj);
670             elm_object_style_set(btn, "ime/transparent");
671             return btn;
672         }
673     } else {
674         int index = (uintptr_t)data;
675         int new_index = 0;
676
677         if (!strcmp(part, "elm.icon.1") ||  (!strcmp(part, "elm.icon.2")) ||  (!strcmp(part, "elm.icon.3"))) {
678             if (!strcmp(part, "elm.icon.1")) {
679                 if (index >= EMOTICON_CNT) return NULL;
680                 new_index = index;
681             } else if (!strcmp(part, "elm.icon.2")) {
682                 if (index + 1 >= EMOTICON_CNT) return NULL;
683                 new_index = index + 1;
684             } else if (!strcmp(part, "elm.icon.3")) {
685                 if (index + 2 >= EMOTICON_CNT) return NULL;
686                 new_index = index + 2;
687             }
688             return get_emoticon_button(obj, new_index);
689         } else if (!strcmp(part, "base")) {
690             Evas_Object* btn = elm_button_add(obj);
691             elm_object_style_set(btn, "ime/transparent");
692             return btn;
693         }
694     }
695     return NULL;
696 }
697
698 void _create_reusable_recents(Evas_Object *parent)
699 {
700     if (!parent) {
701         PRINTFUNC(DLOG_ERROR, "parent is null");
702         return;
703     }
704
705     unsigned int i;
706     for (i = 0; i < recent_emoji_list.size(); i++ ) {
707         emoticon_recents_pool[i].index = i;
708         emoticon_recents_pool[i].content = get_recent_emoticon_button(parent, i);
709         emoticon_recents_pool[i].used = 0;
710     }
711 }
712
713 static Eina_Bool _lazy_loader_cb_for_contents(void *data)
714 {
715     Evas_Object *gl = (Evas_Object *)data;
716     if (!gl) {
717         PRINTFUNC(DLOG_ERROR, "gl is null");
718         lazy_loading_timer_for_contents = NULL;
719         return ECORE_CALLBACK_CANCEL;
720     }
721
722     if (loading_done_for_contents == EMOTICON_CNT) {
723         PRINTFUNC(DLOG_DEBUG, "lazy loading contents done");
724         lazy_loading_timer_for_contents = NULL;
725         return ECORE_CALLBACK_CANCEL;
726     }
727
728     int loading_top = 0;
729     if (loading_done_for_contents + LOADING_CONTENT_UNIT > EMOTICON_CNT) {
730         loading_top = EMOTICON_CNT;
731     } else {
732         loading_top = loading_done_for_contents + LOADING_CONTENT_UNIT;
733     }
734
735     PRINTFUNC(DLOG_DEBUG, "_lazy_loader_cb_for_contents loading_done = %d", loading_done_for_contents);
736
737     int i;
738     for (i = loading_done_for_contents; i < loading_top; i++) {
739         emoticon_contents_pool[i].index = i;
740         emoticon_contents_pool[i].used = 0;
741
742         if (emoticon_contents_pool[i].content == NULL) { // reusable
743             emoticon_contents_pool[i].content = get_emoticon_button(gl, i);
744         }
745     }
746
747     loading_done_for_contents = loading_top;
748
749     return ECORE_CALLBACK_RENEW;
750 }
751
752 void create_reusable_button(Evas_Object *parent)
753 {
754     if (!parent) {
755         PRINTFUNC(DLOG_ERROR, "parent is null");
756         return;
757     }
758     loading_done_for_contents = INITAL_CONTENT_UNIT;
759
760     int i;
761     for (i = 0; i < INITAL_CONTENT_UNIT; i++ ) {
762         emoticon_contents_pool[i].index = i;
763         emoticon_contents_pool[i].used = 0;
764
765         if (emoticon_contents_pool[i].content == NULL) { // reusable
766             emoticon_contents_pool[i].content = get_emoticon_button(parent, i);
767         }
768     }
769
770     lazy_loading_timer_for_contents = ecore_timer_add(0.25, _lazy_loader_cb_for_contents, (void *)parent);
771 }
772
773 static Eina_Bool _lazy_loader_cb_for_items(void *data)
774 {
775     Evas_Object *gl = (Evas_Object *)data;
776     if (!gl) {
777         PRINTFUNC(DLOG_ERROR, "gl is null");
778         lazy_loading_timer_for_items = NULL;
779         return ECORE_CALLBACK_CANCEL;
780     }
781
782     if (loading_done_for_item == EMOTICON_CNT) {
783         PRINTFUNC(DLOG_DEBUG, "lazy loading item done");
784         //elm_genlist_realized_items_update(gl);
785         elm_genlist_item_class_free(itc_emoticon);
786         lazy_loading_timer_for_items = NULL;
787
788         return ECORE_CALLBACK_CANCEL;
789     }
790
791     int loading_top = 0;
792     if (loading_done_for_item + LOADING_ITEM_UNIT > EMOTICON_CNT) {
793         loading_top = EMOTICON_CNT;
794     } else {
795         loading_top = loading_done_for_item + LOADING_ITEM_UNIT;
796     }
797
798     if (loading_top > loading_done_for_contents) {
799         PRINTFUNC(DLOG_DEBUG, "Wait for content loading");
800         return ECORE_CALLBACK_RENEW;
801     }
802     PRINTFUNC(DLOG_DEBUG, "_lazy_loader_cb_for_items loading_done_for_item = %d", loading_done_for_item);
803
804     int i;
805     for (i = loading_done_for_item; i < loading_top; i++ ) {
806         if (i%3 == 0)
807             elm_genlist_item_append(gl, itc_emoticon, (void*)(uintptr_t)i, NULL, ELM_GENLIST_ITEM_NONE, NULL, (void *)(uintptr_t)i);
808     }
809
810     loading_done_for_item = loading_top;
811     return ECORE_CALLBACK_RENEW;
812 }
813
814 void _create_reusable_contents(Evas_Object *gl){
815     if (!gl) {
816         PRINTFUNC(DLOG_ERROR, "gl is null");
817         return;
818     }
819     int i;
820     loading_done_for_item = INITAL_ITEM_UNIT;
821
822     for (i = 0; i < INITAL_ITEM_UNIT; i++ ) {
823         if (i%3 == 0)
824             elm_genlist_item_append(gl, itc_emoticon, (void*)(uintptr_t)i, NULL, ELM_GENLIST_ITEM_NONE, NULL, (void *)(uintptr_t)i);
825     }
826
827     lazy_loading_timer_for_items = ecore_timer_add(0.1, _lazy_loader_cb_for_items, (void *)gl);
828 }
829
830 Evas_Object* _create_emoticon_genlist(void* data)
831 {
832     PRINTFUNC(DLOG_DEBUG, "%s", __func__);
833     App_Data* ad = (App_Data*) data;
834     if (!ad)
835         return NULL;
836
837     Evas_Object* genlist = elm_genlist_add(ad->naviframe);
838     if (NULL == genlist)
839         return NULL;
840
841     if (_WEARABLE) {
842         Evas_Object* circle_object_genlist = eext_circle_object_genlist_add(genlist, ad->circle_surface);
843         eext_circle_object_genlist_scroller_policy_set(circle_object_genlist, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
844         evas_object_data_set(genlist, "circle", (void *) circle_object_genlist);
845         eext_rotary_object_event_activated_set(circle_object_genlist, EINA_TRUE);
846     }
847     evas_object_size_hint_weight_set(genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
848     evas_object_size_hint_align_set(genlist, EVAS_HINT_FILL, EVAS_HINT_FILL);
849     evas_object_show(genlist);
850
851     const char *item_style = NULL;
852     if (_WEARABLE)
853         item_style = "empty";
854     Elm_Object_Item *nf_emoticon_item = elm_naviframe_item_push(ad->naviframe, NULL, NULL, NULL, genlist, item_style);
855
856     elm_naviframe_item_pop_cb_set(nf_emoticon_item, _custom_back_cb2, ad);
857
858     evas_object_smart_callback_add(genlist, "language,changed", _emoticon_gl_lang_changed, genlist);
859
860     if (is_content_reuse_on) {
861         evas_object_smart_callback_add(genlist, "content,unswallowed", _emoticon_gl_content_unswallowed_cb, NULL);
862     }
863
864     return genlist;
865 }
866
867 void _update_emoticon_items(void *data)
868 {
869     PRINTFUNC(DLOG_DEBUG, "%s", __func__);
870     Evas_Object* gl = (Evas_Object*) data;
871     if (!gl)
872         return;
873
874     unsigned int i;
875     Elm_Object_Item *it = NULL;
876     Elm_Object_Item *first_it = NULL;
877
878     Elm_Genlist_Item_Class * itc_dummy = elm_genlist_item_class_new();
879     itc_dummy->item_style = "title";
880     itc_dummy->func.text_get = NULL;
881     itc_dummy->func.content_get = NULL;
882     itc_dummy->func.state_get = NULL;
883     itc_dummy->func.del = NULL;
884
885     Elm_Genlist_Item_Class *itc_1text_1icon = NULL;
886     if (app_data->mime_type == MIME_TYPE_ALL) {
887         itc_1text_1icon = elm_genlist_item_class_new();
888         itc_1text_1icon->item_style = "drawing";
889         itc_1text_1icon->func.text_get = __emoticon_gl_text_get;
890         itc_1text_1icon->func.content_get = __emoticon_gl_1_content_get;
891         itc_1text_1icon->func.state_get = NULL;
892         itc_1text_1icon->func.del = NULL;
893     }
894
895     Elm_Genlist_Item_Class *itc_group = elm_genlist_item_class_new();
896     itc_group->item_style = "groupindex";
897     itc_group->func.text_get = __emoticon_gl_text_get;
898     itc_group->func.content_get = NULL;
899     itc_group->func.state_get = NULL;
900     itc_group->func.del = NULL;
901
902     Elm_Genlist_Item_Class *itc_recent = elm_genlist_item_class_new();
903     itc_recent->item_style = "3button_flat_recent";
904     itc_recent->func.text_get = NULL;
905     itc_recent->func.content_get = __emoticon_gl_recent_content_get;
906     itc_recent->func.state_get = NULL;
907     itc_recent->func.del = NULL;
908
909     itc_emoticon = elm_genlist_item_class_new();
910     itc_emoticon->item_style = "3button_flat";
911     itc_emoticon->func.text_get = NULL;
912     itc_emoticon->func.content_get = __emoticon_gl_emoticon_content_get;
913     itc_emoticon->func.state_get = NULL;
914     itc_emoticon->func.del = NULL;
915
916     // dummy title for empty space
917     it_emoticon_empty = elm_genlist_item_append(gl, itc_dummy, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
918
919     // Drawing
920     if (app_data->mime_type == MIME_TYPE_ALL) {
921         it_drawing = elm_genlist_item_append(gl, itc_1text_1icon, "Doodle", NULL, ELM_GENLIST_ITEM_NONE, _drawing_item_clicked_cb, (void *)app_data);
922         first_it = it_drawing;
923     }
924
925     if (recent_emoji_list.size() > 0) {
926         if (is_content_reuse_on) {
927             _create_reusable_recents(gl);
928         }
929
930         // Group Recents
931         it_emoticon_recent_group = elm_genlist_item_append(gl, itc_group, (void*)"IDS_IME_HEADER_RECENT_M_RECETLY_SENT_EMOJIS_ABB", NULL, ELM_GENLIST_ITEM_NONE, NULL, (void *)2);
932         elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
933         if (first_it == NULL)
934             first_it = it_emoticon_recent_group;
935
936         PRINTFUNC(DLOG_DEBUG, "size = %d", recent_emoji_list.size());
937
938         for (i=0;i < recent_emoji_list.size();i=i+3)
939         {
940             it = elm_genlist_item_append(gl, itc_recent, (void*)(uintptr_t)i, NULL, ELM_GENLIST_ITEM_NONE, NULL, (void *)(uintptr_t)i);
941         }
942     }
943
944     // Group Emoticons
945     it_emoticon_emoji_group = elm_genlist_item_append(gl, itc_group, (void*)"IDS_IME_HEADER_EMOJIS_ABB", NULL, ELM_GENLIST_ITEM_NONE, NULL, (void *)2);
946     elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
947     if (first_it == NULL)
948         first_it = it_emoticon_emoji_group;
949
950     if (is_content_reuse_on) {
951         _create_reusable_contents(gl);
952     } else {
953         // Emoticons
954         for (i=0;i< EMOTICON_CNT;i=i+3) {
955             it = elm_genlist_item_append(gl, itc_emoticon, (void*)(uintptr_t)i, NULL, ELM_GENLIST_ITEM_NONE, NULL, (void *)(uintptr_t)i);
956             it_last = it;
957         }
958         elm_genlist_item_class_free(itc_emoticon);
959     }
960     it = elm_genlist_item_next_get(first_it);
961     const Elm_Genlist_Item_Class *itc_temp = elm_genlist_item_item_class_get(it);
962     if (itc_temp == itc_group) {
963         it = elm_genlist_item_next_get(it);
964     }
965     elm_genlist_item_show(it, ELM_GENLIST_ITEM_SCROLLTO_MIDDLE);
966
967     elm_genlist_item_class_free(itc_recent);
968     elm_genlist_item_class_free(itc_group);
969     elm_genlist_item_class_free(itc_1text_1icon);
970     elm_genlist_item_class_free(itc_dummy);
971 }
972
973 void ise_show_emoticon_list(void *data)
974 {
975     App_Data* ad = (App_Data*) data;
976     if (!ad)
977         return;
978
979     it_emoticon_empty = NULL;
980     it_emoticon_recent_group = NULL;
981     it_emoticon_emoji_group = NULL;
982     it_drawing = NULL;
983     it_last = NULL;
984
985     get_recent_emoticons(recent_emoji_list);
986
987     Evas_Object* emoticon_list = NULL;
988
989     emoticon_list = _create_emoticon_genlist(ad);
990
991     if (is_content_reuse_on) {
992         create_reusable_button(ad->naviframe); // button object need to survive even if genlist is deleted.
993     }
994     _update_emoticon_items(emoticon_list);
995 }
996
997 void launch_drawing_app(void *data)
998 {
999     App_Data* ad = (App_Data*) data;
1000     if (!ad)
1001         return;
1002
1003     _drawing_item_clicked_cb(ad, NULL, NULL);
1004 }