[Searchbar] mouse up signal replaced with clicked signal to fix CQ H0100121793.
[framework/uifw/elementary.git] / src / lib / elm_searchbar.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4 #include <Elementary.h>
5 #include "elm_priv.h"
6
7 /**
8  * @defgroup Searchbar Searchbar
9  * @ingroup Elementary
10  *
11  * This is Searchbar. 
12  * It can contain a simple entry and button object.
13  */
14
15 typedef struct _Widget_Data Widget_Data;
16
17 struct _Widget_Data
18 {
19    Evas_Object *base, *eb, *cancel_btn;
20    Eina_Bool cancel_btn_ani_flag;
21    Eina_Bool cancel_btn_show_mode;
22    Eina_Bool boundary_mode;
23 };
24
25 static void _del_hook(Evas_Object *obj);
26 static void _theme_hook(Evas_Object *obj);
27 static void _on_focus_hook(void *data, Evas_Object *obj);
28 static void _sizing_eval(Evas_Object *obj);
29 static void _clicked(void *data, Evas_Object *obj, void *event_info);
30 static void _changed(void *data, Evas_Object *obj, void *event_info);
31 static void _cancel_clicked(void *data, Evas_Object *obj, void *event_info);
32
33 static void _del_hook(Evas_Object *obj)
34 {
35    Widget_Data *wd = elm_widget_data_get(obj);
36
37    if (!wd) return;
38
39    free(wd);
40 }
41
42 static void _theme_hook(Evas_Object *obj)
43 {
44    Widget_Data *wd = elm_widget_data_get(obj);
45    if (!wd) return;
46
47    _elm_theme_object_set(obj, wd->base, "searchbar", "base", elm_widget_style_get(obj));
48
49    if (wd->eb)
50      edje_object_part_swallow(wd->base, "search_textfield", wd->eb);
51    if (wd->cancel_btn)
52      edje_object_part_swallow(wd->base, "button_cancel", wd->cancel_btn);
53
54    edje_object_scale_set(wd->cancel_btn, elm_widget_scale_get(obj) * _elm_config->scale);
55    _sizing_eval(obj);
56 }
57
58 static void
59 _on_focus_hook(void *data, Evas_Object *obj)
60 {
61    Widget_Data *wd = elm_widget_data_get(obj);
62    if (!wd || !wd->base)
63       return;   
64    if (elm_widget_focus_get(obj))
65      {
66         if (wd->cancel_btn_show_mode)
67           {
68              if (wd->cancel_btn_ani_flag) edje_object_signal_emit(wd->base, "CANCELIN", "PROG");
69              else edje_object_signal_emit(wd->base, "CANCELSHOW", "PROG");
70           }
71      }
72 }
73
74 static void _sizing_eval(Evas_Object *obj)
75 {
76    Widget_Data *wd = elm_widget_data_get(obj);
77    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
78
79    if (!wd) return;
80    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
81    edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
82    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
83    evas_object_size_hint_min_set(obj, minw, minh);
84    evas_object_size_hint_max_set(obj, maxw, maxh);
85 }
86
87 static void _clicked(void *data, Evas_Object *obj, void *event_info)
88 {
89    Widget_Data *wd = elm_widget_data_get(data);
90    if (!wd) return;
91
92    if (wd->cancel_btn_show_mode)
93      {
94         if (wd->cancel_btn_ani_flag) edje_object_signal_emit(wd->base, "CANCELIN", "PROG");
95         else edje_object_signal_emit(wd->base, "CANCELSHOW", "PROG");
96      }
97
98    evas_object_smart_callback_call(data, "clicked", NULL);
99 }
100
101 static void _changed(void *data, Evas_Object *obj, void *event_info)
102 {
103    Widget_Data *wd = elm_widget_data_get(data);
104
105    if (!wd) return;
106
107    // TODO : inform to use entry changed callback 
108 //   evas_object_smart_callback_call(data, "changed", NULL);
109 }
110
111 static void _cancel_clicked(void *data, Evas_Object *obj, void *event_info)
112 {
113    Widget_Data *wd = elm_widget_data_get(data);
114    if (!wd) return;
115
116    if (wd->cancel_btn_show_mode)
117      {
118         if (wd->cancel_btn_ani_flag) edje_object_signal_emit(wd->base, "CANCELOUT", "PROG");
119         else edje_object_signal_emit(wd->base, "CANCELHIDE", "PROG");
120      }
121
122    const char* text;
123    text = elm_entry_entry_get(elm_editfield_entry_get(wd->eb));
124    if (text != NULL && strlen(text) > 0) elm_entry_entry_set(elm_editfield_entry_get(wd->eb), NULL);
125
126    evas_object_smart_callback_call(data, "cancel,clicked", NULL);
127 }
128
129 static void
130 _basebg_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
131 {
132    Widget_Data *wd = elm_widget_data_get(data);
133
134    if (!wd) return;
135
136    if (!strcmp(source, "base_bg"))
137       _clicked(data, obj, NULL);
138 }
139
140 static void
141 _searchsymbol_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
142 {
143    Widget_Data *wd = elm_widget_data_get(data);
144
145    if (!wd) return;
146    evas_object_smart_callback_call(data, "searchsymbol,clicked", NULL);
147 }
148
149 /**
150  * Add a new searchbar to the parent
151  * @param parent The parent object
152  * @return The new object or NULL if it cannot be created
153  *
154  * @ingroup Searchbar
155  */
156 EAPI Evas_Object *elm_searchbar_add(Evas_Object *parent)
157 {
158    Evas_Object *obj;
159    Evas *e;
160    Widget_Data *wd;
161
162    wd = ELM_NEW(Widget_Data);
163    e = evas_object_evas_get(parent);
164    if (e == NULL) return NULL;
165    obj = elm_widget_add(e);
166    if (obj == NULL) return NULL;
167    elm_widget_type_set(obj, "searchbar");
168    elm_widget_sub_object_add(parent, obj);
169    elm_widget_data_set(obj, wd);
170    elm_widget_del_hook_set(obj, _del_hook);
171    elm_widget_theme_hook_set(obj, _theme_hook);
172    elm_widget_on_focus_hook_set( obj, _on_focus_hook, NULL );
173    elm_widget_can_focus_set(obj, 1 );
174
175    wd->base = edje_object_add(e);
176    if (wd->base == NULL) return NULL;
177
178    _elm_theme_object_set(obj, wd->base, "searchbar", "base", "default");
179
180    //   evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
181    //   evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
182
183    // Add Entry
184    wd->eb = elm_editfield_add(parent);
185    elm_object_style_set(wd->eb, "searchbar");
186    edje_object_part_swallow(wd->base, "search_textfield", wd->eb);
187 //   elm_editfield_guide_text_set(wd->eb, "Search");
188    elm_editfield_entry_single_line_set(wd->eb, EINA_TRUE);
189    elm_editfield_eraser_set(wd->eb, EINA_TRUE);
190    evas_object_smart_callback_add(wd->eb, "clicked", _clicked, obj);
191    evas_object_smart_callback_add(elm_editfield_entry_get(wd->eb), "changed", _changed, obj);
192    edje_object_signal_callback_add(wd->base, "mouse,up,1", "*", _basebg_clicked, obj);
193    edje_object_signal_callback_add(wd->base, "elm,action,click", "", _searchsymbol_clicked, obj);
194
195    elm_widget_sub_object_add(obj, wd->eb);
196
197    // Add Button
198    wd->cancel_btn = elm_button_add(parent);
199    edje_object_part_swallow(wd->base, "button_cancel", wd->cancel_btn);
200    elm_object_style_set(wd->cancel_btn, "custom/darkblue");
201    elm_button_label_set(wd->cancel_btn, "Cancel");
202    evas_object_smart_callback_add(wd->cancel_btn, "clicked", _cancel_clicked, obj);
203    elm_widget_sub_object_add(obj, wd->cancel_btn);
204
205    wd->cancel_btn_ani_flag = EINA_FALSE;
206    wd->cancel_btn_show_mode = EINA_TRUE;
207    wd->boundary_mode = EINA_TRUE;
208
209    elm_widget_resize_object_set(obj, wd->base);
210
211    _sizing_eval(obj);
212
213    return obj;
214 }
215
216 /**
217  * set the text of entry
218  *
219  * @param obj The searchbar object
220  * @return void
221  *
222  * @ingroup Searchbar
223  */
224 EAPI void elm_searchbar_text_set(Evas_Object *obj, const char *entry)
225 {
226    Widget_Data *wd = elm_widget_data_get(obj);
227    if (!wd) return;
228
229    elm_entry_entry_set(elm_editfield_entry_get(wd->eb), entry);
230 }
231
232 /**
233  * get the text of entry
234  *
235  * @param obj The searchbar object
236  * @return string pointer of entry
237  *
238  * @ingroup Searchbar
239  */
240 EAPI const char* elm_searchbar_text_get(Evas_Object *obj)
241 {
242    Widget_Data *wd = elm_widget_data_get(obj);
243    if (!wd) return NULL;
244
245    return elm_entry_entry_get(elm_editfield_entry_get(wd->eb));
246 }
247
248 /**
249  * get the pointer of entry
250  *
251  * @param obj The searchbar object
252  * @return the entry object
253  *
254  * @ingroup Searchbar
255  */
256 EAPI Evas_Object *elm_searchbar_entry_get(Evas_Object *obj)
257 {
258    Widget_Data *wd = elm_widget_data_get(obj);
259    if (!wd) return NULL;
260
261    return elm_editfield_entry_get(wd->eb);
262 }
263
264 /**
265  * set the cancel button animation flag
266  *
267  * @param obj The searchbar object
268  * @param cancel_btn_ani_flag The flag of animating cancen button or not
269  * @return void
270  *
271  * @ingroup Searchbar
272  */
273 EAPI void elm_searchbar_cancel_button_animation_set(Evas_Object *obj, Eina_Bool cancel_btn_ani_flag)
274 {
275    Widget_Data *wd = elm_widget_data_get(obj);
276    if (!wd) return;
277
278    if (wd->cancel_btn_ani_flag == cancel_btn_ani_flag) return;
279    else wd->cancel_btn_ani_flag = cancel_btn_ani_flag;
280 }
281
282 /**
283  * set the cancel button show mode
284  *
285  * @param obj The searchbar object
286  * @param visible The flag of cancen button show or not
287  * @return void
288  *
289  * @ingroup Searchbar
290  */
291 EAPI void elm_searchbar_cancel_button_set(Evas_Object *obj, Eina_Bool visible)
292 {
293    Widget_Data *wd = elm_widget_data_get(obj);
294    if (!wd) return;
295
296    if (wd->cancel_btn_show_mode == visible) return;
297    else wd->cancel_btn_show_mode = visible;
298
299    if (!visible)
300      {
301         if (wd->cancel_btn_ani_flag)
302            edje_object_signal_emit(wd->base, "CANCELOUT", "PROG");
303         else
304            edje_object_signal_emit(wd->base, "CANCELHIDE", "PROG");
305      }
306    _sizing_eval(obj);
307 }
308
309 /**
310  * clear searchbar status
311  *
312  * @param obj The searchbar object
313  * @return void
314  *
315  * @ingroup Searchbar
316  */
317 EAPI void elm_searchbar_clear(Evas_Object *obj)
318 {
319    Widget_Data *wd = elm_widget_data_get(obj);
320    if (!wd) return;
321
322    if (wd->cancel_btn_show_mode)
323      {
324         if (wd->cancel_btn_ani_flag)
325            edje_object_signal_emit(wd->base, "CANCELOUT", "PROG");
326         else
327            edje_object_signal_emit(wd->base, "CANCELHIDE", "PROG");
328      }
329 //   elm_entry_entry_set(elm_editfield_entry_get(wd->eb), NULL);
330 }
331
332 /**
333  * set the searchbar boundary rect mode(with bg rect) set
334  *
335  * @param obj The searchbar object
336  * @param boundary The present flag of boundary rect or not
337  * @return void
338  *
339  * @ingroup Searchbar
340  */
341 EAPI void elm_searchbar_boundary_rect_set(Evas_Object *obj, Eina_Bool boundary)
342 {
343    Widget_Data *wd = elm_widget_data_get(obj);
344    if (!wd) return;
345
346    if (wd->boundary_mode == boundary) return;
347    else wd->boundary_mode = boundary;
348
349    if (wd->boundary_mode)
350      {
351         edje_object_signal_emit(wd->base, "BDSHOW", "PROG");
352      }
353    else
354      {
355         edje_object_signal_emit(wd->base, "BDHIDE", "PROG");
356      }
357    _sizing_eval(obj);
358 }