30cab7d9a2e9af8a783edadc070b7f621ebe4326
[platform/core/uifw/inputmethod-setting.git] / im_setting_list / input_method_setting_list_ui.cpp
1 /*
2  * Copyright (c) 2014 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 "input_method_setting_list.h"
18 #include "input_method_setting_list_ui.h"
19 #include "input_method_setting_list_popup_view.h"
20 #include "../common/input_method_setting_genlist.h"
21 #include "../common/input_method_setting_win.h"
22 #include "../common/ime_info.h"
23
24 #include <string>
25 #include <app.h>
26 #include <vector>
27 #include <tzplatform_config.h>
28 #include <inputmethod_manager.h>
29 #include <package_manager.h>
30 #include <vconf.h>
31 #include <isf_control.h>
32
33 #define IM_SETTING_LIST_PACKAGE                 PACKAGE
34 #define IM_SETTING_LIST_LOCALE_DIR              tzplatform_mkpath(TZ_SYS_RO_APP, PACKAGE_NAME"/res/locale")
35 #define IM_SETTING_LIST_TITLE                   "IDS_IME_BODY_KEYBOARD"
36 #define IM_SETTING_LIST_KEYBOARD_HEADER         "IDS_ST_HEADER_KEYBOARDS"
37 #define IM_SETTING_LIST_POPUP_TITLE             "IDS_ST_BODY_ATTENTION"
38 #define IM_SETTING_LIST_POPUP_CANCEL            "IDS_COM_SK_CANCEL_ABB"
39 #define IM_SETTING_LIST_POPUP_ENABLE            "IDS_ST_BUTTON_ENABLE"
40 #define IM_SETTING_LIST_VIRTUAL_KEYBOARD        "IDS_ST_HEADER_VIRTUAL_KEYBOARD"
41 #define IM_SETTING_LIST_DEFAULT_KEYBOARD        "IDS_ST_HEADER_DEFAULT_KEYBOARD_ABB"
42 #define IM_SETTING_LIST_KEYBOARD_SETTING        "IDS_IME_HEADER_KEYBOARD_SETTINGS_ABB"
43 #define IM_SETTING_LIST_TURNON_KEYBOARD         "IDS_ST_BUTTON_TURN_ON_KEYBOARD_ABB"
44 #define IM_SETTING_LIST_TURNON                  "IDS_ST_BUTTON_TURN_ON_ABB3"
45 #define IM_SETTING_LIST_POPUP_TEXT              dgettext(PACKAGE, "IDS_ST_POP_THIS_INPUT_METHOD_MAY_BE_ABLE_TO_COLLECT_ALL_THE"\
46                                                                   "_TEXT_YOU_TYPE_INCLUDING_PERSONAL_DATA_LIKE_PASSWORDS_AND"\
47                                                                   "_CREDIT_CARD_NUMBERS_MSG")
48
49
50 #define MAIN_LAYOUT_EDJ                         RESDIR"/edje/main_layout.edj"
51
52 typedef struct list_item_text_s
53 {
54     char main_text[256];
55     char sub_text[512];
56 } list_item_text;
57
58 typedef struct popup_cb_data_s
59 {
60     Evas_Object *popup;
61     void *data;
62 } popup_cb_data;
63
64 typedef struct gen_item_data_s
65 {
66     Elm_Object_Item *gen_item;
67     int chk_status;
68 } gen_item_data;
69
70 typedef struct _Item_Data
71 {
72     int index;
73     Elm_Object_Item *item;
74 } Item_Data;
75
76 typedef void (*popup_ok_cb)(void *data, Evas_Object *obj, void *event_info);
77 typedef void (*popup_cancel_cb)(void *data, Evas_Object *obj, void *event_info);
78
79 static std::vector<ime_info_s>      g_ime_info_list;
80 static Elm_Genlist_Item_Class       *itc_im_list_keyboard_list = NULL;
81 static Elm_Genlist_Item_Class       *itc_im_list_group = NULL;
82 static Elm_Genlist_Item_Class       *itc_im_list_item = NULL;
83 static Elm_Genlist_Item_Class       *itc_im_list_item_one_line = NULL;
84 static Elm_Genlist_Item_Class       *itc_im_list_title = NULL;
85 static int                          g_active_ime_index = -1;
86 static list_item_text               item_text[2];
87 static std::vector<gen_item_data>   g_gen_item_data;
88 static package_manager_h            pkgmgr = NULL;
89
90 void im_setting_list_update_window(void *data);
91
92 static void im_setting_list_text_domain_set(void)
93 {
94     bindtextdomain(IM_SETTING_LIST_PACKAGE, IM_SETTING_LIST_LOCALE_DIR);
95     textdomain(IM_SETTING_LIST_PACKAGE);
96 }
97
98 static Evas_Object *
99 im_setting_list_main_window_create(const char *name, int app_type)
100 {
101     Evas_Object *eo = im_setting_window_create(name, app_type == APP_TYPE_SETTING_NO_ROTATION ? EINA_FALSE : EINA_TRUE, EINA_FALSE);
102
103     return eo;
104 }
105
106 static Evas_Object* im_setting_list_bg_create(Evas_Object *parent)
107 {
108     Evas_Object *bg;
109     if (parent == NULL) return NULL;
110     bg = elm_bg_add(parent);
111     evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
112     elm_win_resize_object_add(parent, bg);
113     evas_object_show(bg);
114     return bg;
115 }
116
117 static int im_setting_list_get_active_ime_index(void)
118 {
119     char *active_ime_appid = NULL;
120
121     int ret = ime_manager_get_active_ime(&active_ime_appid);
122     if (ret == IME_MANAGER_ERROR_NONE)
123         LOGD("get active ime : %s\n", active_ime_appid);
124     else
125         LOGW("Failed to get active ime. error : %d\n", ret);
126
127     std::vector<ime_info_s>::iterator iter = g_ime_info_list.begin();
128     std::vector<ime_info_s>::iterator end = g_ime_info_list.end();
129     for (; iter != end; ++iter)
130     {
131         if (active_ime_appid && (!strcmp(active_ime_appid, iter->appid)))
132         {
133             break;
134         }
135     }
136     if (active_ime_appid)
137     {
138         free(active_ime_appid);
139     }
140     return (iter - g_ime_info_list.begin());
141 }
142
143 static void
144 im_setting_list_check_popup_ok_cb(void *data, Evas_Object *obj, void *event_info)
145 {
146     popup_cb_data *cb_data = (popup_cb_data *)data;
147     if (!cb_data)
148         return;
149     int index = (int)reinterpret_cast<long>(cb_data->data);
150     if (index < 0 || index >= (int)g_ime_info_list.size()) {
151         LOGW("Wrong value. index : %d, g_ime_info_list.size() : %zu\n", index, g_ime_info_list.size());
152         return;
153     }
154     Eina_Bool state = EINA_FALSE;
155     state = g_gen_item_data[index].chk_status;
156     if (isf_control_set_enable_ime(g_ime_info_list[index].appid, state) != 0)
157         LOGW("Failed to set enable ime : %s\n", g_ime_info_list[index].appid);
158
159     evas_object_del(cb_data->popup);
160 }
161
162 static void
163 im_setting_list_check_popup_cancel_cb(void *data, Evas_Object *obj, void *event_info)
164 {
165     popup_cb_data *cb_data = (popup_cb_data *)data;
166     if (!cb_data)
167         return;
168     int index = (int)reinterpret_cast<long>(cb_data->data);
169     if (index < 0 || index >= (int)g_ime_info_list.size()) {
170         LOGW("Wrong value. index : %d, g_ime_info_list.size() : %zu\n", index, g_ime_info_list.size());
171         return;
172     }
173
174     Eina_Bool state = g_gen_item_data[index].chk_status;
175     if (isf_control_set_enable_ime(g_ime_info_list[index].appid, !state) == 0) {
176         g_gen_item_data[index].chk_status = !state;
177         elm_genlist_item_update(g_gen_item_data[index].gen_item);
178     } else {
179         LOGW("Failed to set enable ime : %s\n", g_ime_info_list[index].appid);
180     }
181
182     evas_object_del(cb_data->popup);
183 }
184
185 static void _popup_back_cb(void *data, Evas_Object *obj, void *event_info)
186 {
187     eext_object_event_callback_del(obj, EEXT_CALLBACK_BACK, _popup_back_cb);
188     popup_cb_data *cb_data = (popup_cb_data *)data;
189     if (!cb_data)
190         return;
191     int index = (int)reinterpret_cast<long>(cb_data->data);
192     if (index < 0 || index >= (int)g_ime_info_list.size()) {
193         LOGW("Wrong value. index : %d, g_ime_info_list.size() : %zu\n", index, g_ime_info_list.size());
194         return;
195     }
196
197     if (g_gen_item_data[index].chk_status) {
198         im_setting_list_check_popup_cancel_cb(data, NULL, NULL);
199     } else {
200         evas_object_del(cb_data->popup);
201     }
202 }
203
204 static void _popup_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
205 {
206     popup_cb_data *cb_data = (popup_cb_data *)data;
207     if (!cb_data)
208         return;
209
210     delete cb_data;
211 }
212
213 static void _active_keyboard_changed_cb(keynode_t* node, void* data)
214 {
215     appdata *ad = (appdata *)data;
216     int active_ime_index = im_setting_list_get_active_ime_index();
217
218     if (g_active_ime_index != active_ime_index) {
219         g_active_ime_index = active_ime_index;
220         if (g_active_ime_index < 0 || g_active_ime_index >= (int)g_ime_info_list.size()) {
221             LOGW("Wrong value. g_active_ime_index : %d, g_ime_info_list.size() : %zu\n", g_active_ime_index, g_ime_info_list.size());
222             return;
223         }
224
225         /* Default keyboard selector */
226         snprintf(item_text[0].main_text, sizeof(item_text[0].main_text), "%s", IM_SETTING_LIST_DEFAULT_KEYBOARD);
227 #ifdef _WEARABLE
228         if(g_ime_info_list.size() > 1)
229             snprintf(item_text[0].sub_text, sizeof(item_text[0].sub_text), "<color=#4CABFF>%s</color>", g_ime_info_list[g_active_ime_index].label);
230         else
231 #endif
232             snprintf(item_text[0].sub_text, sizeof(item_text[0].sub_text), "%s", g_ime_info_list[g_active_ime_index].label);
233
234         if (ad->genlist) {
235             Elm_Object_Item *item = elm_genlist_first_item_get(ad->genlist);
236             list_item_text *item_data = NULL;
237             while (item) {
238                 item_data = (list_item_text*)elm_object_item_data_get(item);
239                 elm_genlist_item_update(item);
240                 if (item_data && strncmp(item_data->main_text, IM_SETTING_LIST_KEYBOARD_SETTING, sizeof(item_data->main_text)) == 0)
241                     elm_object_item_disabled_set(item, !(g_ime_info_list[g_active_ime_index].has_option));
242
243                 item = elm_genlist_item_next_get(item);
244             }
245         }
246     }
247 }
248
249 static void set_popup_message(Evas_Object *obj, int index)
250 {
251     char chFormatMsg[255] = {'\0'};
252     char chPopupMsg[255] = {'\0'};
253     snprintf(chFormatMsg, sizeof(chFormatMsg), "%s", IM_SETTING_LIST_POPUP_TEXT);
254     snprintf(chPopupMsg, sizeof(chPopupMsg), chFormatMsg, g_ime_info_list[index].label);
255     elm_object_text_set(obj, chPopupMsg);
256 }
257
258 static void popup_lang_changed(void *data, Evas_Object *obj, void *event_info)
259 {
260     int index = (int)reinterpret_cast<long>(data);
261     set_popup_message(obj, index);
262 }
263
264 static void add_popup_button(Evas_Object *popup, const char *button_text, const char *part_name, popup_ok_cb popup_cb, void *cb_data)
265 {
266     Evas_Object *btn_obj = elm_button_add(popup);
267     elm_object_domain_translatable_text_set(btn_obj, PACKAGE, button_text);
268     elm_object_part_content_set(popup, part_name, btn_obj);
269     evas_object_smart_callback_add(btn_obj, "clicked", popup_cb, cb_data);
270 }
271
272 static void im_setting_list_show_popup(void *data, Evas_Object *obj, popup_ok_cb ime_setting_list_ok_callback, popup_cancel_cb ime_setting_list_cancel_callback)
273 {
274     int index = (int)reinterpret_cast<long>(data);
275     if (index < 0 || index >= (int)g_ime_info_list.size()) {
276         LOGW("Wrong value. index : %d, g_ime_info_list.size() : %zu\n", index, g_ime_info_list.size());
277         return;
278     }
279
280     Evas_Object *top_widget = elm_object_top_widget_get(obj);
281     Evas_Object *popup = elm_popup_add(top_widget);
282     elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0);
283     elm_object_domain_translatable_part_text_set(popup, "title,text", PACKAGE, IM_SETTING_LIST_TURNON_KEYBOARD);
284     evas_object_smart_callback_add(popup, "language,changed", popup_lang_changed, (void *)(unsigned long int)index);
285
286     set_popup_message(popup, index);
287
288     popup_cb_data *cb_data = new popup_cb_data;
289     cb_data->popup = popup;
290     cb_data->data = data;
291
292     add_popup_button(popup, IM_SETTING_LIST_POPUP_CANCEL, "button1", ime_setting_list_cancel_callback, cb_data);
293     add_popup_button(popup, IM_SETTING_LIST_TURNON, "button2", ime_setting_list_ok_callback, cb_data);
294
295     eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, _popup_back_cb, cb_data);
296     evas_object_event_callback_add(popup, EVAS_CALLBACK_DEL, _popup_del_cb, cb_data);
297     evas_object_show(popup);
298 }
299
300 static void im_setting_list_check_button_change_cb(void *data, Evas_Object *obj, void *event_info)
301 {
302     /*save the checked ime*/
303     int index = (int)reinterpret_cast<long>(data);
304     if (index < 0 || index >= (int)g_ime_info_list.size()) {
305         LOGW("Wrong value. index : %d, g_ime_info_list.size() : %zu\n", index, g_ime_info_list.size());
306         return;
307     }
308
309     Eina_Bool state = g_gen_item_data[index].chk_status;
310
311     if (!state) {
312         if (isf_control_set_enable_ime(g_ime_info_list[index].appid, state) != 0)
313             LOGW("Failed to set enable ime : %s\n", g_ime_info_list[index].appid);
314     } else {
315         im_setting_list_show_popup(data, obj, im_setting_list_check_popup_ok_cb, im_setting_list_check_popup_cancel_cb);
316     }
317 }
318
319 static void
320 im_setting_list_popup_ok_cb(void *data, Evas_Object *obj, void *event_info)
321 {
322     popup_cb_data *cb_data = (popup_cb_data *)data;
323     if (!cb_data)
324         return;
325     int index = (int)reinterpret_cast<long>(cb_data->data);
326     if (index < 0 || index >= (int)g_ime_info_list.size()) {
327         LOGW("Wrong value. index : %d, g_ime_info_list.size() : %zu\n", index, g_ime_info_list.size());
328         return;
329     }
330
331     Eina_Bool state = g_gen_item_data[index].chk_status;
332     if (isf_control_set_enable_ime(g_ime_info_list[index].appid, !state) == 0) {
333         g_gen_item_data[index].chk_status = !state;
334         Evas_Object *ck = elm_object_item_part_content_get(g_gen_item_data[index].gen_item, "elm.swallow.end");
335         if (ck == NULL) {
336             ck = elm_object_item_part_content_get(g_gen_item_data[index].gen_item, "elm.icon");
337         }
338
339         if (ck) {
340             elm_object_signal_emit(ck, "elm,activate,check,on", "elm");
341             elm_check_state_set(ck, !state);
342         }
343     } else {
344         LOGW("Failed to set enable ime : %s\n", g_ime_info_list[index].appid);
345     }
346     evas_object_del(cb_data->popup);
347 }
348
349 static void
350 im_setting_list_popup_cancel_cb(void *data, Evas_Object *obj, void *event_info)
351 {
352     popup_cb_data *cb_data = (popup_cb_data *)data;
353     if (!cb_data)
354         return;
355     evas_object_del(cb_data->popup);
356 }
357
358 static void im_setting_list_item_sel_cb(void *data, Evas_Object *obj, void *event_info)
359 {
360     Elm_Object_Item *item = (Elm_Object_Item *)event_info;
361     elm_genlist_item_selected_set(item, EINA_FALSE);
362
363     int index = (int)reinterpret_cast<long>(data);
364     if (index < 0 || index >= (int)g_ime_info_list.size()) {
365         LOGW("Wrong value. index : %d, g_ime_info_list.size() : %zu\n", index, g_ime_info_list.size());
366         return;
367     }
368
369     if (g_ime_info_list[index].is_preinstalled || (index == g_active_ime_index))
370     {
371         return;
372     }
373
374     Evas_Object *ck = elm_object_item_part_content_get(item, "elm.swallow.end");
375     if (ck == NULL) {
376         ck = elm_object_item_part_content_get(item, "elm.icon");
377     }
378     Eina_Bool state = g_gen_item_data[index].chk_status;
379
380     if (state) {
381         if (isf_control_set_enable_ime(g_ime_info_list[index].appid, !state) == 0) {
382             if (ck) {
383                 elm_object_signal_emit(ck, "elm,activate,check,off", "elm");
384                 elm_check_state_set(ck, !state);
385             }
386             g_gen_item_data[index].chk_status = !state;
387         } else {
388             LOGW("Failed to set enable ime : %s\n", g_ime_info_list[index].appid);
389         }
390     } else {
391         im_setting_list_show_popup(data, obj, im_setting_list_popup_ok_cb, im_setting_list_popup_cancel_cb);
392     }
393 }
394
395 static void im_setting_list_set_default_keyboard_item_sel_cb(void *data, Evas_Object *obj, void *event_info)
396 {
397     Elm_Object_Item *item = (Elm_Object_Item *)event_info;
398
399     elm_genlist_item_selected_set(item, EINA_FALSE);
400     im_setting_list_popup_view_create(data);
401 }
402
403 static void im_setting_list_keyboard_setting_item_sel_cb(void *data, Evas_Object *obj, void *event_info)
404 {
405     appdata *ad = (appdata *)data;
406     if (ad->app_state == APP_STATE_PAUSE)
407         return;
408
409     Elm_Object_Item *item = (Elm_Object_Item *)event_info;
410     elm_genlist_item_selected_set(item, EINA_FALSE);
411     isf_control_open_ime_option_window();
412 }
413
414 static Evas_Object *im_setting_list_conform_create(Evas_Object *parentWin)
415 {
416     Evas_Object *conform = elm_conformant_add(parentWin);
417     evas_object_size_hint_weight_set(conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
418     evas_object_size_hint_align_set(conform, EVAS_HINT_FILL, EVAS_HINT_FILL);
419
420     Evas_Object *bg = elm_bg_add(conform);
421     elm_object_style_set(bg, "indicator/headerbg");
422     elm_object_part_content_set(conform, "elm.swallow.indicator_bg", bg);
423     evas_object_show(bg);
424
425     elm_win_resize_object_add(parentWin, conform);
426     evas_object_show(conform);
427
428     return conform;
429 }
430
431 static Evas_Object *im_setting_list_naviframe_create(Evas_Object* parent)
432 {
433     Evas_Object *naviframe = elm_naviframe_add(parent);
434     elm_naviframe_prev_btn_auto_pushed_set(naviframe, EINA_TRUE);
435     eext_object_event_callback_add(naviframe, EEXT_CALLBACK_BACK, eext_naviframe_back_cb, NULL);
436     evas_object_size_hint_weight_set(naviframe, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
437     evas_object_size_hint_align_set(naviframe, EVAS_HINT_FILL, EVAS_HINT_FILL);
438     elm_object_part_content_set(parent, "elm.swallow.content", naviframe);
439     evas_object_show(naviframe);
440     return naviframe;
441 }
442
443 static void gl_lang_changed(void *data, Evas_Object *obj, void *event_info)
444 {
445     /* Reload ime list for getting translated IME name */
446     im_setting_load_ime_info(g_ime_info_list, g_active_ime_index, false);
447
448     /* Set translated active IME name */
449     snprintf(item_text[0].sub_text, sizeof(item_text[0].sub_text), "%s", g_ime_info_list[g_active_ime_index].label);
450
451     elm_genlist_realized_items_update(obj);
452 }
453
454 static char *im_setting_list_genlist_group_label_get(void *data, Evas_Object *obj, const char *part)
455 {
456     char *text = (char *)data;
457     if (!text)
458         return NULL;
459     if (!strcmp(part, "elm.text")) {
460         return strdup(dgettext(PACKAGE, text));
461     }
462     return NULL;
463 }
464
465 static void
466 im_setting_list_genlist_keyboard_list_item_del(void *data, Evas_Object *obj)
467 {
468     Item_Data *id = (Item_Data *)data;
469     if (id) free(id);
470 }
471
472 static char *im_setting_list_genlist_keyboard_list_item_label_get(void *data, Evas_Object *obj, const char *part)
473 {
474     Item_Data *id = (Item_Data *)data;
475     int index = id->index;
476     if (index < 0 || index >= (int)g_ime_info_list.size()) {
477         LOGW("Wrong value. index : %d, g_ime_info_list.size() : %zu\n", index, g_ime_info_list.size());
478         return NULL;
479     }
480
481     if (!strcmp(part, "elm.text.main.left.top") ||
482         !strcmp(part, "elm.text.main.left") ||
483         !strcmp(part, "elm.text.main") ||
484         !strcmp(part, "elm.text") ||
485         !strcmp(part, "elm.text.1")) {
486         return strdup(g_ime_info_list[index].label);
487     }
488     return NULL;
489 }
490
491 #ifdef _WEARABLE
492 static char *im_setting_list_genlist_title_label_get(void *data, Evas_Object *obj, const char *part)
493 {
494     if (!strcmp(part, "elm.text")) {
495         return strdup(dgettext(PACKAGE, IM_SETTING_LIST_TITLE));
496     }
497     return NULL;
498 }
499 #endif
500
501 static Evas_Object *im_setting_list_genlist_keyboard_list_item_icon_get(void *data, Evas_Object *obj, const char *part)
502 {
503     Item_Data *id = (Item_Data *)data;
504     int index = id->index;
505
506     if (index < 0 || index >= (int)g_ime_info_list.size()) {
507         LOGW("Wrong value. index : %d, g_ime_info_list.size() : %zu\n", index, g_ime_info_list.size());
508         return NULL;
509     }
510
511     if (!strcmp(part, "elm.swallow.end") ||
512         !strcmp(part, "elm.icon")) {
513         Evas_Object *ck = elm_check_add(obj);
514         elm_object_style_set(ck, "on&off");
515         elm_check_state_set(ck, g_gen_item_data[index].chk_status);
516 #ifdef _WEARABLE
517         elm_object_disabled_set(ck, EINA_TRUE);
518 #else
519         elm_object_disabled_set(ck, g_ime_info_list[index].is_preinstalled || (index == g_active_ime_index));
520 #endif
521
522         evas_object_propagate_events_set(ck, EINA_FALSE);
523         evas_object_size_hint_align_set(ck, EVAS_HINT_FILL, EVAS_HINT_FILL);
524         evas_object_size_hint_weight_set(ck, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
525         elm_check_state_pointer_set(ck, (Eina_Bool *)(&(g_gen_item_data[index].chk_status)));
526         evas_object_pass_events_set(ck, EINA_TRUE);
527         evas_object_smart_callback_add(ck, "changed", im_setting_list_check_button_change_cb, (void *)(unsigned long int)(index));
528         evas_object_show(ck);
529
530         elm_atspi_accessible_relationship_append(ck, ELM_ATSPI_RELATION_CONTROLLED_BY, id->item);
531         elm_atspi_accessible_relationship_append(id->item, ELM_ATSPI_RELATION_CONTROLLER_FOR, ck);
532         elm_atspi_accessible_relationship_append(id->item, ELM_ATSPI_RELATION_DESCRIBED_BY, ck);
533
534         return ck;
535     }
536     return NULL;
537 }
538
539 static char *im_setting_list_genlist_item_label_get(void *data, Evas_Object *obj, const char *part)
540 {
541     list_item_text *item_text = (list_item_text *)data;
542     if (!item_text)
543         return NULL;
544
545     if (!strcmp(part, "elm.text.main.left.top") ||
546         !strcmp(part, "elm.text.main.left") ||
547         !strcmp(part, "elm.text.main") ||
548         !strcmp(part, "elm.text")) {
549         return strdup(dgettext(PACKAGE, item_text->main_text));
550     }
551     if (!strcmp(part, "elm.text.sub") ||
552         !strcmp(part, "elm.text.sub.left.bottom") ||
553         !strcmp(part, "elm.text.multiline") ||
554         !strcmp(part, "elm.text.1") ||
555         !strcmp(part, "elm.text.2")) {
556         return strdup(dgettext(PACKAGE, item_text->sub_text));
557     }
558     return NULL;
559 }
560
561 static char *im_setting_list_genlist_item_one_line_label_get(void *data, Evas_Object *obj, const char *part)
562 {
563     list_item_text *item_text = (list_item_text *)data;
564     if (!item_text)
565         return NULL;
566     if (!strcmp(part, "elm.text.main.left.top") ||
567         !strcmp(part, "elm.text.main.left") ||
568         !strcmp(part, "elm.text.main") ||
569         !strcmp(part, "elm.text") ||
570         !strcmp(part, "elm.text.1")) {
571         return strdup(dgettext(PACKAGE, item_text->main_text));
572     }
573     return NULL;
574 }
575
576 static void im_setting_list_genlist_item_class_create(int app_type)
577 {
578     if (NULL == itc_im_list_group)
579     {
580         itc_im_list_group = elm_genlist_item_class_new();
581         if (itc_im_list_group)
582         {
583 #ifdef _WEARABLE
584             itc_im_list_group->item_style = "groupindex";
585 #else
586             itc_im_list_group->item_style = "group_index";
587 #endif
588             itc_im_list_group->func.text_get = im_setting_list_genlist_group_label_get;
589             itc_im_list_group->func.content_get = NULL;
590             itc_im_list_group->func.state_get = NULL;
591             itc_im_list_group->func.del = NULL;
592         }
593     }
594
595     if (NULL == itc_im_list_keyboard_list)
596     {
597         itc_im_list_keyboard_list = elm_genlist_item_class_new();
598         if (itc_im_list_keyboard_list)
599         {
600             itc_im_list_keyboard_list->item_style = IME_SETTING_LIST_1LINE_STYLE;
601             itc_im_list_keyboard_list->func.text_get = im_setting_list_genlist_keyboard_list_item_label_get;
602             itc_im_list_keyboard_list->func.content_get = im_setting_list_genlist_keyboard_list_item_icon_get;
603             itc_im_list_keyboard_list->func.state_get = NULL;
604             itc_im_list_keyboard_list->func.del = im_setting_list_genlist_keyboard_list_item_del;
605         }
606     }
607
608 #ifdef _WEARABLE
609     if (NULL == itc_im_list_title)
610     {
611         itc_im_list_title = elm_genlist_item_class_new();
612         if (itc_im_list_title)
613         {
614             itc_im_list_title->item_style = "title";
615             itc_im_list_title->func.text_get = im_setting_list_genlist_title_label_get;
616         }
617     }
618 #endif
619
620     if (app_type == APP_TYPE_SETTING || app_type == APP_TYPE_SETTING_NO_ROTATION)
621     {
622         if (NULL == itc_im_list_item)
623         {
624             itc_im_list_item = elm_genlist_item_class_new();
625             if (itc_im_list_item)
626             {
627 #ifdef _WEARABLE
628                 itc_im_list_item->item_style = "2text";
629 #elif _MOBILE
630                 itc_im_list_item->item_style = "type1";
631 #else
632                 itc_im_list_item->item_style = "2line";
633 #endif
634                 itc_im_list_item->func.text_get = im_setting_list_genlist_item_label_get;
635                 itc_im_list_item->func.content_get = NULL;
636                 itc_im_list_item->func.state_get = NULL;
637                 itc_im_list_item->func.del = NULL;
638             }
639         }
640
641         if (NULL == itc_im_list_item_one_line)
642         {
643             itc_im_list_item_one_line = elm_genlist_item_class_new();
644             if (itc_im_list_item_one_line)
645             {
646 #ifdef _WEARABLE
647                 itc_im_list_item_one_line->item_style = "1text";
648 #elif _MOBILE
649                 itc_im_list_item_one_line->item_style = "type1";
650 #else
651                 itc_im_list_item_one_line->item_style = "1line";
652 #endif
653                 itc_im_list_item_one_line->func.text_get = im_setting_list_genlist_item_one_line_label_get;
654                 itc_im_list_item_one_line->func.content_get = NULL;
655                 itc_im_list_item_one_line->func.state_get = NULL;
656                 itc_im_list_item_one_line->func.del = NULL;
657             }
658         }
659     }
660 }
661
662 static void im_setting_list_add_ime(void *data) {
663     appdata *ad = (appdata *)data;
664     if (!ad)
665         return;
666     im_setting_list_genlist_item_class_create(ad->app_type);
667
668     if (NULL != ad->genlist)
669     {
670         elm_genlist_clear(ad->genlist);
671     }
672
673     g_active_ime_index = im_setting_list_get_active_ime_index();
674     if (g_active_ime_index < 0 || g_active_ime_index >= (int)g_ime_info_list.size()) {
675         LOGW("Wrong value. g_active_ime_index : %d, g_ime_info_list.size() : %zu\n", g_active_ime_index, g_ime_info_list.size());
676         return;
677     }
678
679 #ifdef _WEARABLE
680     /* Add scrollable title area in wearable profile */
681     elm_genlist_item_append(ad->genlist, itc_im_list_title, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
682 #endif
683
684     memset(&item_text, 0, sizeof(item_text));
685     if (ad->app_type == APP_TYPE_SETTING || ad->app_type == APP_TYPE_SETTING_NO_ROTATION)
686     {
687         /* Default keyboard selector */
688         snprintf(item_text[0].main_text, sizeof(item_text[0].main_text), "%s", IM_SETTING_LIST_DEFAULT_KEYBOARD);
689         snprintf(item_text[0].sub_text, sizeof(item_text[0].sub_text), "%s", g_ime_info_list[g_active_ime_index].label);
690         Elm_Object_Item *item = elm_genlist_item_append(ad->genlist,
691             itc_im_list_item,
692             (void *)&item_text[0],
693             NULL,
694             ELM_GENLIST_ITEM_NONE,
695             im_setting_list_set_default_keyboard_item_sel_cb,
696             data);
697
698         elm_object_item_domain_text_translatable_set(item, PACKAGE, EINA_TRUE);
699
700 #ifdef _WEARABLE
701         if (g_ime_info_list.size() <= 1) {
702             LOGD("The number of IME : %zu\n", g_ime_info_list.size());
703             elm_object_item_disabled_set(item, EINA_TRUE);
704         }
705 #endif
706
707         /* Keyboard settings */
708         snprintf(item_text[1].main_text, sizeof(item_text[1].main_text), "%s", IM_SETTING_LIST_KEYBOARD_SETTING);
709         item = elm_genlist_item_append(ad->genlist,
710             itc_im_list_item_one_line,
711             (void *)&item_text[1],
712             NULL,
713             ELM_GENLIST_ITEM_NONE,
714             im_setting_list_keyboard_setting_item_sel_cb,
715             ad);
716         elm_object_item_domain_text_translatable_set(item, PACKAGE, EINA_TRUE);
717
718         elm_object_item_disabled_set(item, !(g_ime_info_list[g_active_ime_index].has_option));
719
720 #ifndef _WEARABLE
721         /* Keyboards group */
722         Elm_Object_Item *group_header_item = NULL;
723         group_header_item = elm_genlist_item_append(ad->genlist,
724                 itc_im_list_group,
725                 IM_SETTING_LIST_KEYBOARD_HEADER,
726                 NULL,
727                 ELM_GENLIST_ITEM_GROUP,
728                 NULL,
729                 NULL);
730         elm_genlist_item_select_mode_set(group_header_item, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
731         elm_object_item_domain_text_translatable_set(group_header_item, PACKAGE, EINA_TRUE);
732 #endif
733     }
734
735 #ifdef _WEARABLE
736     if (ad->app_type == APP_TYPE_NORMAL)
737 #endif
738     {
739         Item_Data *id = NULL;
740
741         /* keyboard list */
742         int info_list_size = g_ime_info_list.size();
743         for (int i = 0; i < info_list_size; i++) {
744             gen_item_data item_data;
745             item_data.gen_item = NULL;
746
747             if (g_ime_info_list[i].is_preinstalled || (i == g_active_ime_index)) {
748                 item_data.chk_status = EINA_TRUE;
749             } else {
750                 item_data.chk_status = g_ime_info_list[i].is_enabled;
751             }
752             g_gen_item_data.push_back(item_data);
753
754             id = (Item_Data *)calloc(sizeof(Item_Data), 1);
755             if (id) {
756                 id->index = i;
757
758                 id->item = elm_genlist_item_append(ad->genlist,
759                         itc_im_list_keyboard_list,
760                         id,
761                         NULL,
762                         ELM_GENLIST_ITEM_NONE,
763                         im_setting_list_item_sel_cb,
764                         (void *)(unsigned long int)(i));
765
766                 if (g_ime_info_list[i].is_preinstalled || (i == g_active_ime_index)) {
767                     elm_object_item_disabled_set(id->item, EINA_TRUE);
768                 }
769
770                 g_gen_item_data[i].gen_item = id->item;
771             }
772         }
773     }
774
775 #ifdef _CIRCLE
776     im_setting_list_add_padding(ad->genlist);
777 #endif
778 }
779
780 static Eina_Bool im_setting_list_navi_item_pop_cb(void *data, Elm_Object_Item *it)
781 {
782     static bool in_exit = false;
783     if (in_exit)
784         return EINA_TRUE;
785     in_exit = true;
786     if (data == NULL)
787         return EINA_TRUE;
788     ui_app_exit();
789     return EINA_TRUE;
790 }
791
792 static void im_setting_list_navi_back_btn_call_cb(void *data, Evas_Object *obj, void *event_info)
793 {
794     evas_object_smart_callback_del(obj, "clicked", im_setting_list_navi_back_btn_call_cb);
795     ui_app_exit();
796 }
797
798 void im_setting_list_add_padding(Evas_Object *genlist)
799 {
800     /* Add padding area in wearable circle profile */
801     Elm_Genlist_Item_Class *ptc = elm_genlist_item_class_new();
802     Elm_Object_Item *item;
803     if (!ptc) return;
804
805     ptc->item_style = "padding";
806     item = elm_genlist_item_append(genlist, ptc, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
807     elm_atspi_accessible_role_set(item, ELM_ATSPI_ROLE_REDUNDANT_OBJECT);
808     elm_genlist_item_class_free(ptc);
809 }
810
811 Evas_Object *im_setting_list_list_create(void *data)
812 {
813     appdata *ad = (appdata *)data;
814     if (!ad)
815         return NULL;
816     ad->conform = im_setting_list_conform_create(ad->win);
817     ad->naviframe = im_setting_list_naviframe_create(ad->conform);
818     ad->genlist = im_setting_genlist_create(ad->naviframe, ad->conform, &ad->main_circle_genlist);
819     evas_object_smart_callback_add(ad->genlist, "language,changed", gl_lang_changed, NULL);
820     im_setting_list_add_ime(ad);
821
822     /* Add genlist to naviframe */
823     Evas_Object *back_btn = NULL;
824     const char *title = NULL;
825     const char *item_style = NULL;
826     Elm_Object_Item *nf_main_item = NULL;
827
828 #ifdef _WEARABLE
829     item_style = "empty";
830 #else
831     title = IM_SETTING_LIST_TITLE;
832
833     back_btn = elm_button_add(ad->naviframe);
834     elm_object_style_set(back_btn, "naviframe/back_btn/default");
835     evas_object_smart_callback_add(back_btn, "clicked", im_setting_list_navi_back_btn_call_cb, NULL);
836 #endif
837
838     Evas_Object *layout = elm_layout_add(ad->naviframe);
839 #if defined(_WEARABLE) || defined(_MOBILE)
840     elm_layout_theme_set(layout, "layout", "application", "default");
841 #else
842     elm_layout_file_set(layout, MAIN_LAYOUT_EDJ, "main_layout");
843 #endif
844
845     elm_object_content_set(layout, ad->genlist);
846     evas_object_show(layout);
847
848     nf_main_item = elm_naviframe_item_push(ad->naviframe,
849                 title,
850                 back_btn,
851                 NULL,
852                 layout,
853                 item_style);
854
855 #ifdef _WEARABLE
856     elm_atspi_accessible_name_set(nf_main_item, dgettext(PACKAGE, IM_SETTING_LIST_TITLE));
857 #endif
858     elm_object_item_domain_text_translatable_set(nf_main_item, PACKAGE, EINA_TRUE);
859
860     elm_naviframe_item_title_enabled_set(nf_main_item, EINA_TRUE, EINA_TRUE);
861     elm_naviframe_item_pop_cb_set(nf_main_item, im_setting_list_navi_item_pop_cb, ad);
862     elm_object_content_set(ad->conform, ad->naviframe);
863
864     return ad->genlist;
865 }
866
867 void im_setting_list_app_terminate(void *data)
868 {
869     g_ime_info_list.clear();
870     g_gen_item_data.clear();
871     if (NULL != itc_im_list_keyboard_list)
872     {
873         elm_genlist_item_class_free(itc_im_list_keyboard_list);
874         itc_im_list_keyboard_list = NULL;
875     }
876
877     if (NULL != itc_im_list_group)
878     {
879         elm_genlist_item_class_free(itc_im_list_group);
880         itc_im_list_group = NULL;
881     }
882
883     if (NULL != itc_im_list_item)
884     {
885         elm_genlist_item_class_free(itc_im_list_item);
886         itc_im_list_item = NULL;
887     }
888
889     if (NULL != itc_im_list_title)
890     {
891         elm_genlist_item_class_free(itc_im_list_title);
892         itc_im_list_title = NULL;
893     }
894
895     if (pkgmgr) {
896         package_manager_destroy(pkgmgr);
897         pkgmgr = NULL;
898     }
899
900     vconf_ignore_key_changed(VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, _active_keyboard_changed_cb);
901 }
902
903 void im_setting_list_update_window(void *data)
904 {
905     appdata *ad = (appdata *)data;
906     if (!ad)
907         return;
908
909     im_setting_load_ime_info(g_ime_info_list, g_active_ime_index, false);
910     im_setting_list_add_ime(ad);
911 }
912
913 static void _package_manager_event_cb(const char *type, const char *package, package_manager_event_type_e event_type, package_manager_event_state_e event_state, int progress, package_manager_error_e error, void *user_data)
914 {
915     appdata *ad = (appdata *)user_data;
916
917     if (!package || !type)
918         return;
919
920     if (event_state != PACKAGE_MANAGER_EVENT_STATE_COMPLETED)
921         return;
922
923     if (event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL ||
924         event_type == PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL ||
925         event_type == PACKAGE_MANAGER_EVENT_TYPE_UPDATE) {
926         LOGD("PACKAGE_MANAGER_EVENT type : %d", event_type);
927         /* Wait for updating IME package list in ISF */
928         usleep(20000);
929         im_setting_list_popup_view_del(ad);
930         im_setting_list_popup_view_create(ad);
931     }
932 }
933
934 void
935 im_setting_list_app_create(void *data)
936 {
937     appdata *ad = (appdata *)data;
938     if (!ad)
939         return;
940     im_setting_list_text_domain_set();
941     ad->win = im_setting_list_main_window_create(PACKAGE, ad->app_type);
942     im_setting_list_bg_create(ad->win);
943     im_setting_load_ime_info(g_ime_info_list, g_active_ime_index, false);
944
945     if (!pkgmgr) {
946         int ret = package_manager_create(&pkgmgr);
947         if (ret == PACKAGE_MANAGER_ERROR_NONE) {
948             ret = package_manager_set_event_cb(pkgmgr, _package_manager_event_cb, ad);
949             if (ret == PACKAGE_MANAGER_ERROR_NONE) {
950                 LOGD("package_manager_set_event_cb succeeded.\n");
951             } else {
952                 LOGW("package_manager_set_event_cb failed(%d)\n", ret);
953             }
954         } else {
955             LOGW("package_manager_create failed(%d)\n", ret);
956         }
957     }
958
959     im_setting_list_list_create(ad);
960     evas_object_show(ad->win);
961
962     vconf_notify_key_changed(VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, _active_keyboard_changed_cb, data);
963 }
964
965 void
966 im_setting_list_app_resume(void *data)
967 {
968     appdata *ad = (appdata *)data;
969     if (!ad)
970         return;
971
972     isf_control_resume_ime_option_window();
973 }