Change memo menu icon
[apps/home/memo.git] / src / memo_list_viewer.c
1 /*
2 *
3 * Copyright 2012  Samsung Electronics Co., Ltd
4 *
5 * Licensed under the Flora License, Version 1.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *    http://www.tizenopensource.org/license
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <appcore-efl.h>
22 #include <Elementary.h>
23 #include <dlog.h>
24 #include <gravel.h>
25 #include <vconf-keys.h>
26 #include <extended-elm.h>
27 #include <supplement.h>
28 #include <memo-assist.h>
29 #include <memo_string.h>
30 #include <memo-genlist.h>
31 #include <memo_ug.h>
32 #include "memo_log.h"
33
34 typedef struct __list_viewer_t {
35     Evas_Object *parent;
36     Memo_Component_Callback cb;
37     void *data;
38     char buf[MEMO_BUFFER_SIZE]; /* for temporarily usage only */
39
40     /* content */
41     Evas_Object *body_main;
42     Evas_Object *searchbar;
43     Evas_Object *searchbar_layout;
44     Evas_Object *genlist;
45     Evas_Object *nocontent;
46
47     /* other */
48     Evas_Object *win_main;
49     Elm_Genlist_Item_Class itc;
50     Elm_Genlist_Item_Class itc_draw;
51     Ecore_IMF_Context *imf_context;
52     Elm_Entry_Filter_Limit_Size limit_filter_data;
53     int mode; /* 0:list, 1:search */
54     char *search_str;
55     int count; /* count of records */
56 } list_viewer_t;
57
58 static void _on_item_select_cb(void *data, Evas_Object *obj, void *event_info)
59 {
60     Elm_Object_Item *it = (Elm_Object_Item *)event_info;
61     gl_data_t *gld = (gl_data_t *)elm_object_item_data_get(it);
62     list_viewer_t *lv = (list_viewer_t *)gld->user_data;
63
64     elm_genlist_item_selected_set(it, 0);
65     RETIF(gld->index == -1);
66     /* return directly in sweep mode */
67     RETIF(it == (Elm_Object_Item *)elm_genlist_decorated_item_get(obj));
68     lv->cb(lv->data, "select", (void *)gld->index);
69 }
70
71 static void _my_gl_mode_right(void *data, Evas_Object *obj, void *event_info)
72 {
73     if (!event_info) return;
74
75     Elm_Object_Item *it = (Elm_Object_Item *)event_info;
76     gl_data_t *gld = (gl_data_t *)elm_object_item_data_get(it);
77     list_viewer_t *lv = (list_viewer_t *)gld->user_data;
78     RETIF(lv->mode == 1); /* disable sweep feature when in search mode */
79
80     /* Start genlist sweep */
81     elm_genlist_item_decorate_mode_set(it, "slide", EINA_TRUE);
82     elm_genlist_item_select_mode_set(it, EINA_TRUE);
83 }
84
85 static void _my_gl_mode_left(void *data, Evas_Object *obj, void *event_info)
86 {
87     if (!event_info) return;
88
89     /* Finish genlist sweep */
90     elm_genlist_item_decorate_mode_set(event_info, "slide", EINA_FALSE);
91     elm_genlist_item_select_mode_set(event_info, EINA_FALSE);
92 }
93
94 static void _my_gl_mode_cancel(void *data, Evas_Object *obj, void *event_info)
95 {
96     if (!obj) return;
97
98     /* Get sweeped item */
99     Elm_Object_Item *it = (Elm_Object_Item *)elm_genlist_decorated_item_get(obj);
100
101     /* Finish genlist sweep */
102     if (it) {
103         elm_genlist_item_decorate_mode_set(it, "slide", EINA_FALSE);
104         elm_genlist_item_select_mode_set(it, EINA_FALSE);
105     }
106 }
107
108 static void _on_delete_yes(void *data, Evas_Object *obj, void *event_info)
109 {
110     gl_data_t *gld = (gl_data_t *)data;
111     gl_data_t *d = NULL;
112     list_viewer_t *lv = (list_viewer_t *)gld->user_data;
113     Elm_Object_Item *it = NULL;
114
115     it = elm_genlist_first_item_get(lv->genlist);
116     while (it != NULL) {
117         d = (gl_data_t *)elm_object_item_data_get(it);
118         if (d->index == gld->index) {
119             memo_del_data(gld->index);
120             lv->cb(lv->data, "delete", NULL);
121             elm_object_item_del(it);
122             lv->count--;
123             snprintf(lv->buf, MEMO_BUFFER_SIZE, "%s(%d)", MEMO_I18N_MEMO, lv->count);
124             lv->cb(lv->data, "title", lv->buf);
125             lv->cb(lv->data, "count", (void *)lv->count);
126             break;
127         }
128         it = elm_genlist_item_next_get(it);
129     }
130 }
131
132 static void _on_delete_button_clicked(void *data, Evas_Object *obj, void *event_info)
133 {
134     gl_data_t *gld = (gl_data_t *)data;
135     list_viewer_t *lv = (list_viewer_t *)gld->user_data;
136     snprintf(lv->buf, MEMO_BUFFER_SIZE, "%s?", MEMO_I18N_DELETE);
137     memo_create_yes_no_popup(lv->win_main,lv->buf, _on_delete_yes, NULL, gld);
138 }
139
140 static void _on_send_button_clicked(void *data, Evas_Object *obj, void *event_info)
141 {
142     gl_data_t *gld = (gl_data_t *)data;
143     gl_data_t *d = NULL;
144     list_viewer_t *lv = (list_viewer_t *)gld->user_data;
145     Elm_Object_Item *it = NULL;
146
147     it = elm_genlist_first_item_get(lv->genlist);
148     while (it != NULL) {
149         d = (gl_data_t *)elm_object_item_data_get(it);
150         if (d->index == gld->index) {
151             memo_share(lv->win_main, &gld->index, 1);
152             break;
153         }
154         it = elm_genlist_item_next_get(it);
155     }
156 }
157
158 static void memo_data_iterate_cb (memo_data_t *md, void *user_data)
159 {
160     list_viewer_t *lv = (list_viewer_t *)user_data;
161     gl_data_t *gld = SMALLOC(gl_data_t);
162     RETIF(gld == NULL);
163     memo_gld_init(gld, md, lv, NULL);
164     gld->on_send = _on_send_button_clicked;
165     gld->on_delete = _on_delete_button_clicked;
166     gld->search = (lv->mode==1 ? lv->search_str : NULL);
167     if (md->has_doodle) {
168         elm_genlist_item_append(lv->genlist, &lv->itc_draw,(void *)gld,
169             NULL, ELM_GENLIST_ITEM_NONE, _on_item_select_cb, NULL);
170     } else {
171         elm_genlist_item_append(lv->genlist, &lv->itc,(void *)gld,
172             NULL, ELM_GENLIST_ITEM_NONE, _on_item_select_cb, NULL);
173     }
174     lv->count++;
175 }
176
177 static void _on_search_activated(void *data, Evas_Object *obj, void *event_info)
178 {
179     list_viewer_t *lv = (list_viewer_t *)data;
180     ecore_imf_context_input_panel_hide(lv->imf_context);
181 }
182
183 static void _update_list(void *data, Evas_Object *obj, void *event_info)
184 {
185     MEMO_FUN_BEG();
186     list_viewer_t *lv = (list_viewer_t *)data;
187
188     /* clear search result */
189     elm_genlist_clear(lv->genlist);
190     /* get search string */
191     SFREE(lv->search_str);
192     lv->search_str = elm_entry_markup_to_utf8(elm_object_text_get(lv->searchbar));
193     if (strcmp(lv->search_str, "") == 0) {
194         SFREE(lv->search_str);
195         lv->search_str = NULL;
196     }
197
198     lv->count = 0;
199     if (lv->mode == 0) {
200         memo_all_data(memo_data_iterate_cb, lv);
201         snprintf(lv->buf, MEMO_BUFFER_SIZE, "%s(%d)", MEMO_I18N_MEMO, lv->count);
202         lv->cb(lv->data, "title", lv->buf);
203         lv->cb(lv->data, "count", (void *)lv->count);
204     } else {
205         memo_search_data((lv->search_str == NULL ? "" : lv->search_str) , -1, 0, MEMO_SORT_CREATE_TIME, memo_data_iterate_cb, lv);
206     }
207     if (lv->count == 0) {
208         edje_object_signal_emit(elm_layout_edje_get(lv->body_main), "show", "nocontent");
209     } else {
210         edje_object_signal_emit(elm_layout_edje_get(lv->body_main), "hide", "nocontent");
211     }
212     MEMO_FUN_END();
213 }
214
215 static void _focused_cb(void *data, Evas_Object *obj, void *event_info)
216 {
217     if (!elm_entry_is_empty(obj))
218         elm_object_signal_emit(data, "elm,state,eraser,show", "elm");
219     elm_object_signal_emit(data, "elm,state,guidetext,hide", "elm");
220     elm_object_signal_emit(data, "cancel,in", "");
221 }
222
223 static void _on_searchbar_clicked(void *data, Evas_Object *obj, void *event_info)
224 {
225     list_viewer_t *lv = (list_viewer_t *)data;
226     lv->mode = 1;        /* shift to search mode */
227     if (!elm_entry_is_empty(obj)) {
228         elm_object_signal_emit(lv->searchbar_layout, "elm,state,eraser,show", "elm");
229     }
230     elm_object_signal_emit(lv->searchbar_layout, "elm,state,guidetext,hide","elm");
231     _update_list(lv, NULL, NULL);
232 }
233
234 static void _unfocused_cb(void *data, Evas_Object *obj, void *event_info)
235 {
236     if (elm_entry_is_empty(obj))
237         elm_object_signal_emit(data, "elm,state,guidetext,show", "elm");
238     elm_object_signal_emit(data, "elm,state,eraser,hide", "elm");
239 }
240
241 // When X marked button is clicked, empty entry’s contents
242 static void _eraser_clicked_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
243 {
244     elm_entry_entry_set(data, "");
245 }
246
247 static void _bg_clicked_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
248 {
249     elm_object_focus_set(data, EINA_TRUE);
250 }
251
252 static void _searchsymbol_clicked_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
253 {
254     //LOGD("[Search Bar] SearchSymbol Callback Called");
255     elm_object_focus_set(data, EINA_TRUE);
256 }
257
258 static void _cancel_clicked_cb(void *data, Evas_Object *obj, void *event_info)
259 {
260     list_viewer_t *lv = (list_viewer_t *)data;
261     lv->mode = 0;        /* shift to list mode */
262     const char* text;
263     evas_object_hide(obj);
264
265     elm_object_signal_emit(lv->searchbar_layout, "cancel,out", "");
266     text = elm_entry_entry_get(lv->searchbar);
267     if (text != NULL && strlen(text) > 0) {
268         elm_entry_entry_set(lv->searchbar, NULL);
269     }
270     elm_object_focus_set(lv->searchbar, EINA_FALSE);
271 }
272
273 static void _create_list_viewer_layout(list_viewer_t *lv, service_h service)
274 {
275     MEMO_FUN_BEG();
276     lv->body_main = elm_layout_create(lv->parent, EDJ_FILE, "list_frame");
277     lv->cb(lv->data, "layout", lv->body_main);
278
279     /* search bar */
280     Evas_Object *searchbar_layout = elm_layout_add(lv->body_main);
281     elm_layout_theme_set(searchbar_layout, "layout", "searchbar", "cancel_button");
282     Evas_Object *entry = elm_entry_add(searchbar_layout); /*Create entry*/
283     elm_entry_scrollable_set(entry, EINA_TRUE);
284     elm_entry_single_line_set(entry, EINA_TRUE);
285     elm_object_part_content_set(searchbar_layout, "elm.swallow.content", entry);
286     elm_object_part_text_set(searchbar_layout, "elm.guidetext", "Search"); /*Should be Language Specific*/
287
288     evas_object_size_hint_weight_set(searchbar_layout, EVAS_HINT_EXPAND, 0);
289     evas_object_size_hint_align_set(searchbar_layout, EVAS_HINT_FILL, 0.0);
290     elm_object_part_content_set(lv->body_main, "elm.swallow.search", searchbar_layout);
291
292     Evas_Object *cancel_btn = elm_button_add(searchbar_layout);
293     elm_object_part_content_set(searchbar_layout, "button_cancel", cancel_btn);
294     elm_object_style_set(cancel_btn, "searchbar/default");
295     elm_object_text_set(cancel_btn, "Cancel");
296
297     lv->searchbar = entry;
298     lv->searchbar_layout = searchbar_layout;
299     elm_entry_cnp_mode_set(entry, ELM_CNP_MODE_PLAINTEXT);
300     lv->imf_context = elm_entry_imf_context_get(entry);
301     lv->limit_filter_data.max_char_count = 0;
302     lv->limit_filter_data.max_byte_count = 64;
303
304     /* limit size */
305     elm_entry_markup_filter_append(entry, elm_entry_filter_limit_size, &lv->limit_filter_data);
306     evas_object_smart_callback_add(entry, "changed", _on_searchbar_clicked, lv);
307     evas_object_smart_callback_add(entry, "preedit,changed", _on_searchbar_clicked, lv);
308     evas_object_smart_callback_add(entry, "focused", _focused_cb, searchbar_layout);
309     evas_object_smart_callback_add(entry, "unfocused", _unfocused_cb, searchbar_layout);
310     elm_object_signal_callback_add(searchbar_layout, "elm,eraser,clicked", "elm", _eraser_clicked_cb, entry);
311     elm_object_signal_callback_add(searchbar_layout, "elm,bg,clicked", "elm", _bg_clicked_cb, entry);
312     elm_object_signal_callback_add(searchbar_layout, "elm,action,click", "", _searchsymbol_clicked_cb, entry);
313     evas_object_smart_callback_add(cancel_btn, "clicked", _cancel_clicked_cb, lv);
314     evas_object_smart_callback_add(entry, "activated", _on_search_activated, lv);
315
316     /* no content */
317     lv->nocontent = elm_layout_add(lv->body_main);
318     elm_layout_theme_set(lv->nocontent, "layout", "nocontents", "text");
319     elm_object_part_text_set(lv->nocontent, "elm.text", MEMO_I18N_NO_MEMOS);
320     elm_object_style_set(lv->nocontent, "text");
321     elm_object_part_content_set(lv->body_main, "elm.swallow.nocontent", lv->nocontent);
322
323     /* genlist  */
324     lv->genlist = elm_genlist_add(lv->body_main);
325     evas_object_smart_callback_add(lv->genlist, "drag,start,right", _my_gl_mode_right, NULL);
326     evas_object_smart_callback_add(lv->genlist, "drag,start,left", _my_gl_mode_left, NULL);
327     evas_object_smart_callback_add(lv->genlist, "drag,start,up", _my_gl_mode_cancel, NULL);
328     evas_object_smart_callback_add(lv->genlist, "drag,start,down", _my_gl_mode_cancel, NULL);
329     elm_object_part_content_set(lv->body_main, "elm.swallow.content", lv->genlist);
330     elm_genlist_block_count_set(lv->genlist, 10);
331
332     _update_list(lv, NULL, NULL);
333     MEMO_FUN_END();
334 }
335
336 void *memo_load_list_viewer(Evas_Object *parent, Evas_Object *win, service_h service, Memo_Component_Callback cb, void *data)
337 {
338     MEMO_FUN_BEG();
339     list_viewer_t *lv = SMALLOC(list_viewer_t);
340     RETVIF(lv==NULL, NULL);
341     service_dump(service);
342     lv->parent = parent;
343     lv->cb = (cb==NULL ? memo_com_dummy_cb : cb); /* make sure cb is not null, no need to check legitimacy of cb when call */
344     lv->data = data;
345
346     /* init */
347     memo_gl_itc_init(&lv->itc, "memo/list");
348     lv->itc.decorate_item_style = "mode/slide2";
349     memo_gl_itc_init(&lv->itc_draw, "memo/list_draw");
350     lv->itc_draw.decorate_item_style = "mode/slide2";
351     lv->win_main = win;
352
353     _create_list_viewer_layout(lv, service);
354     MEMO_FUN_END();
355     return (void *)lv;
356 }
357
358 void memo_clear_list_viewer(void *h_lv)
359 {
360     list_viewer_t *lv = (list_viewer_t *)h_lv;
361     elm_genlist_clear(lv->genlist);
362 }
363
364 void memo_update_list_viewer(void *h_lv)
365 {
366     list_viewer_t *lv = (list_viewer_t *)h_lv;
367     _update_list(lv, NULL, NULL);
368 }
369
370 void memo_destroy_list_viewer(void *h_lv)
371 {
372     list_viewer_t *lv = (list_viewer_t *)h_lv;
373     evas_object_del(lv->body_main);
374     SFREE(lv->search_str);
375     SFREE(lv);
376 }
377