Support filter and popup notification for maximum characters length in keyboard input...
[platform/core/uifw/inputdelegator.git] / src / w-input-keyboard.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 "Debug.h"
18
19 #include <app.h>
20 #include <Elementary.h>
21
22 #include <stdlib.h>
23
24 #include "w-input-keyboard.h"
25 #include "w-input-selector.h"
26
27 extern InputKeyboardData g_input_keyboard_data;
28 extern App_Data* app_data;
29
30 Evas_Object *entry;
31
32 bool input_keyboard_init(app_control_h app_control)
33 {
34         int ret = -1;
35         char *default_text = NULL;
36         char *guide_text = NULL;
37         char *return_key_type = NULL;
38         char *max_text_length = NULL;
39
40         input_keyboard_deinit();
41
42         ret = app_control_get_extra_data(app_control, APP_CONTROL_DATA_INPUT_DEFAULT_TEXT, &default_text);
43         if (ret == APP_CONTROL_ERROR_NONE) {
44                 g_input_keyboard_data.default_text = default_text;
45         }
46         ret = app_control_get_extra_data(app_control, APP_CONTROL_DATA_INPUT_GUIDE_TEXT, &guide_text);
47         if (ret == APP_CONTROL_ERROR_NONE) {
48                 g_input_keyboard_data.guide_text = guide_text;
49         }
50         ret = app_control_get_extra_data(app_control, "return_key_type", &return_key_type);
51         if (ret == APP_CONTROL_ERROR_NONE) {
52                 g_input_keyboard_data.return_key_type = return_key_type;
53         }
54         ret = app_control_get_extra_data(app_control, "max_text_length", &max_text_length);
55         if (ret == APP_CONTROL_ERROR_NONE) {
56                 g_input_keyboard_data.max_text_length = atoi(max_text_length);
57         }
58
59         return true;
60 }
61
62 void input_keyboard_deinit(void)
63 {
64         if (g_input_keyboard_data.guide_text)
65                 free(g_input_keyboard_data.guide_text);
66
67         if (g_input_keyboard_data.default_text)
68                 free(g_input_keyboard_data.default_text);
69
70         if (g_input_keyboard_data.return_key_type)
71                 free(g_input_keyboard_data.return_key_type);
72
73         g_input_keyboard_data.default_text = NULL;
74         g_input_keyboard_data.guide_text = NULL;
75         g_input_keyboard_data.return_key_type = NULL;
76         g_input_keyboard_data.max_text_length = KEYBOARD_EDITOR_CHAR_COUNT_MAX;
77
78         return;
79 }
80
81 void exit_keyboard()
82 {
83         app_control_h app_control;
84         int ret = app_control_create(&app_control);
85         if (ret != APP_CONTROL_ERROR_NONE) {
86                 PRINTFUNC(DLOG_ERROR, "Can not create app_control : %d", ret);
87                 return;
88         }
89
90         const char *getText = elm_entry_entry_get(entry);
91         LOGD("button key clicked!! : getText = %s", getText);
92
93         char *app_id = NULL;
94         app_control_get_caller(app_data->source_app_control, &app_id);
95         if (app_id != NULL)
96                 app_control_set_app_id(app_control, app_id);
97         app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
98         set_source_caller_app_id(app_control);
99         free(app_id);
100         reply_to_sender_by_callback(getText, "keyboard", NULL);
101         ui_app_exit();
102
103 }
104
105 void btn_clicked_cb(void *data, Evas_Object *obj, void *event_info)
106 {
107         exit_keyboard();
108 }
109
110 static Eina_Bool custom_back_cb(void *data, Elm_Object_Item *it)
111 {
112         _back_to_genlist_for_selector();
113         return EINA_TRUE;
114 }
115
116 static void maxlength_cb(void *data, Evas_Object *obj, void *event_info)
117 {
118         LOGD("maxlength_cb : size = %d", KEYBOARD_EDITOR_CHAR_COUNT_MAX);
119         char text[512];
120         snprintf(text, sizeof(text), _(MAX_TEXT_LENGTH_REACH), g_input_keyboard_data.max_text_length);
121         show_popup_toast((const char *)text, false);
122 }
123
124 static void enter_keydown_cb(void *data, Evas_Object *obj, void *event_info)
125 {
126         LOGD("enter_keydown_cb");
127         Evas_Object *entry = obj;
128         if (entry == NULL)
129                 return;
130
131         Ecore_IMF_Context *imf_context = NULL;
132         imf_context = (Ecore_IMF_Context*)elm_entry_imf_context_get(entry);
133         if (imf_context)
134                 ecore_imf_context_input_panel_hide(imf_context);
135
136         elm_object_focus_set(entry, EINA_FALSE);
137
138         exit_keyboard();
139 }
140
141 void create_fullscreen_editor(void *data)
142 {
143         App_Data *ad = (App_Data *)data;
144
145         Evas_Object *box = elm_box_add(ad->naviframe);
146         evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
147         evas_object_show(box);
148         elm_win_resize_object_add(ad->naviframe, box);
149
150         entry = elm_entry_add(box);
151
152         static Elm_Entry_Filter_Limit_Size limit_filter_data;
153         limit_filter_data.max_char_count = g_input_keyboard_data.max_text_length;
154         elm_entry_markup_filter_append(entry, elm_entry_filter_limit_size, &limit_filter_data);
155         evas_object_smart_callback_add(entry, "maxlength,reached", maxlength_cb, data);
156
157         elm_entry_single_line_set(entry, EINA_TRUE);
158         elm_entry_scrollable_set(entry, EINA_TRUE);
159         elm_scroller_policy_set(entry, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
160         elm_object_part_text_set(entry, "elm.guide", g_input_keyboard_data.guide_text);
161         elm_entry_entry_set(entry, g_input_keyboard_data.default_text);
162         elm_entry_cursor_end_set(entry);
163         evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
164         evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
165         if (g_input_keyboard_data.return_key_type && strcmp(g_input_keyboard_data.return_key_type, "DONE") == 0) {
166                 elm_entry_input_panel_return_key_type_set(entry, ELM_INPUT_PANEL_RETURN_KEY_TYPE_DONE);
167                 evas_object_smart_callback_add(entry, "activated", enter_keydown_cb, ad);
168         }
169         evas_object_show(entry);
170         elm_box_pack_end(box, entry);
171
172         Evas_Object *btn = elm_button_add(box);
173         elm_object_text_set(btn, "SEND");
174         evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 0.5);
175         evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
176         evas_object_smart_callback_add(btn, "clicked", btn_clicked_cb, NULL);
177         evas_object_show(btn);
178         elm_box_pack_end(box, btn);
179         evas_object_resize(ad->naviframe, 360, 360);
180         evas_object_show(ad->naviframe);
181
182         const char *item_style = NULL;
183         if (_WEARABLE)
184                 item_style = "empty";
185         Elm_Object_Item *nf_item = elm_naviframe_item_push(ad->naviframe, NULL, NULL, NULL, box, item_style);
186         elm_naviframe_item_pop_cb_set(nf_item, custom_back_cb, NULL);
187 }
188
189 static void editfield_focused_cb(void *data, Evas_Object *obj, void *event_info)
190 {
191         Evas_Object *editfield = (Evas_Object *)data;
192         elm_object_signal_emit(editfield, "elm,state,focused", "");
193
194         if (!elm_entry_is_empty(obj))
195                 elm_object_signal_emit(editfield, "elm,action,show,button", "");
196 }
197
198 static void editfield_unfocused_cb(void *data, Evas_Object *obj, void *event_info)
199 {
200         Evas_Object *editfield = (Evas_Object *)data;
201         elm_object_signal_emit(editfield, "elm,state,unfocused", "");
202         elm_object_signal_emit(editfield, "elm,action,hide,button", "");
203 }
204
205 static Evas_Object *create_multiline_editfield_layout(Evas_Object *parent, void *data)
206 {
207         App_Data *ad = (App_Data *)data;
208         Evas_Object *editfield;
209
210         editfield = elm_layout_add(parent);
211         elm_layout_theme_set(editfield, "layout", "editfield", "multiline");
212         evas_object_size_hint_align_set(editfield, EVAS_HINT_FILL, 0.0);
213         evas_object_size_hint_weight_set(editfield, EVAS_HINT_EXPAND, 0.0);
214
215         entry = elm_entry_add(editfield);
216         static Elm_Entry_Filter_Limit_Size limit_filter_data;
217         limit_filter_data.max_char_count = g_input_keyboard_data.max_text_length;
218         elm_entry_markup_filter_append(entry, elm_entry_filter_limit_size, &limit_filter_data);
219         evas_object_smart_callback_add(entry, "maxlength,reached", maxlength_cb, data);
220
221         elm_entry_scrollable_set(entry, EINA_TRUE);
222         elm_scroller_policy_set(entry, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
223         elm_object_part_text_set(entry, "elm.guide", g_input_keyboard_data.guide_text);
224         elm_entry_entry_set(entry, g_input_keyboard_data.default_text);
225         elm_entry_cursor_end_set(entry);
226         evas_object_smart_callback_add(entry, "focused", editfield_focused_cb, editfield);
227         evas_object_smart_callback_add(entry, "unfocused", editfield_unfocused_cb, editfield);
228         if (g_input_keyboard_data.return_key_type && strcmp(g_input_keyboard_data.return_key_type, "DONE") == 0) {
229                 elm_entry_input_panel_return_key_type_set(entry, ELM_INPUT_PANEL_RETURN_KEY_TYPE_DONE);
230                 evas_object_smart_callback_add(entry, "activated", enter_keydown_cb, ad);
231         }
232
233         evas_object_show(entry);
234         elm_object_part_content_set(editfield, "elm.swallow.content", entry);
235
236         return editfield;
237 }
238
239 static Evas_Object *create_editfield_view(void *data)
240 {
241         App_Data *ad = (App_Data *)data;
242
243         Evas_Object *main_scroller, *main_box, *editfield;
244
245         main_scroller = elm_scroller_add(ad->naviframe);
246         elm_scroller_bounce_set(main_scroller, EINA_FALSE, EINA_TRUE);
247         evas_object_size_hint_weight_set(main_scroller, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
248         evas_object_size_hint_align_set(main_scroller, EVAS_HINT_FILL, EVAS_HINT_FILL);
249         evas_object_show(main_scroller);
250
251         main_box = elm_box_add(main_scroller);
252         evas_object_size_hint_align_set(main_box, EVAS_HINT_FILL, 0.0);
253         evas_object_size_hint_weight_set(main_box, EVAS_HINT_EXPAND, 0.0);
254         evas_object_show(main_box);
255
256         editfield = create_multiline_editfield_layout(main_box, data);
257         elm_box_pack_end(main_box, editfield);
258         evas_object_show(editfield);
259
260         Evas_Object *btn = elm_button_add(main_box);
261         elm_object_text_set(btn, "OK");
262         evas_object_size_hint_weight_set(btn, 0.5, 0.5);
263         evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
264         evas_object_smart_callback_add(btn, "clicked", btn_clicked_cb, NULL);
265         evas_object_show(btn);
266         elm_box_pack_end(main_box, btn);
267
268         elm_object_content_set(main_scroller, main_box);
269
270         evas_object_show(ad->naviframe);
271         const char *item_style = NULL;
272         if (_WEARABLE)
273                 item_style = "empty";
274         Elm_Object_Item *nf_item = elm_naviframe_item_push(ad->naviframe, NULL, NULL, NULL, main_scroller, item_style);
275         elm_naviframe_item_pop_cb_set(nf_item, custom_back_cb, NULL);
276
277         return main_scroller;
278 }
279
280 bool input_keyboard_launch(Evas_Object *window, void *data) {
281         if (window == NULL) {
282                 PRINTFUNC(DLOG_ERROR, "Can not get window");
283                 return false;
284         }
285
286         if (_WEARABLE)
287                 create_fullscreen_editor(data);
288         else
289                 create_editfield_view(data);
290
291         return true;
292 }
293