apply FSL(Flora Software License)
[apps/home/memo.git] / src / memo_list_viewer.c
1 /*
2   * Copyright 2012  Samsung Electronics Co., Ltd
3   * 
4   * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
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 <stdlib.h>
18 #include <stdio.h>
19 #include <appcore-efl.h>
20 #include <Elementary.h>
21 #include <dlog.h>
22 #include <gravel.h>
23 #include <vconf-keys.h>
24 #include <extended-elm.h>
25 #include <supplement.h>
26 #include <memo-assist.h>
27 #include <memo_string.h>
28 #include <memo-genlist.h>
29 #include <memo_ug.h>
30
31 typedef struct __list_viewer_t {
32     Evas_Object *parent;
33     Memo_Component_Callback cb;
34     void *data;
35     char buf[MEMO_BUFFER_SIZE]; /* for temporarily usage only */
36
37     /* content */
38     Evas_Object *body_main;
39     Evas_Object *searchbar;
40     Evas_Object *searchbar_layout;
41     Evas_Object *genlist;
42     Evas_Object *nocontent;
43
44     /* other */
45     Evas_Object *win_main;
46     Elm_Genlist_Item_Class itc;
47     Elm_Genlist_Item_Class itc_draw;
48     Ecore_IMF_Context *imf_context;
49     Elm_Entry_Filter_Limit_Size limit_filter_data;
50     int mode; /* 0:list, 1:search */
51     char *search_str;
52     int count; /* count of records */
53 } list_viewer_t;
54
55 static void _on_item_select_cb(void *data, Evas_Object *obj, void *event_info)
56 {
57     Elm_Object_Item *it = (Elm_Object_Item *)event_info;
58     gl_data_t *gld = (gl_data_t *)elm_object_item_data_get(it);
59     list_viewer_t *lv = (list_viewer_t *)gld->user_data;
60
61     elm_genlist_item_selected_set(it, 0);
62     RETIF(gld->index == -1);
63     lv->cb(lv->data, "select", (void *)gld->index);
64 }
65
66 static void _on_delete_yes(void *data, Evas_Object *obj, void *event_info)
67 {
68     gl_data_t *gld = (gl_data_t *)data;
69     gl_data_t *d = NULL;
70     list_viewer_t *lv = (list_viewer_t *)gld->user_data;
71     Elm_Object_Item *it = NULL;
72
73     it = elm_genlist_first_item_get(lv->genlist);
74     while (it != NULL) {
75         d = (gl_data_t *)elm_object_item_data_get(it);
76         if (d->index == gld->index) {
77             memo_del_data(gld->index);
78             lv->cb(lv->data, "delete", NULL);
79             elm_object_item_del(it);
80             lv->count--;
81             snprintf(lv->buf, MEMO_BUFFER_SIZE, "%s(%d)", MEMO_I18N_MEMO, lv->count);
82             lv->cb(lv->data, "title", lv->buf);
83             lv->cb(lv->data, "count", (void *)lv->count);
84             break;
85         }
86         it = elm_genlist_item_next_get(it);
87     }
88 }
89
90 static void _on_delete_button_clicked(void *data, Evas_Object *obj, void *event_info)
91 {
92     gl_data_t *gld = (gl_data_t *)data;
93     list_viewer_t *lv = (list_viewer_t *)gld->user_data;
94     snprintf(lv->buf, MEMO_BUFFER_SIZE, "%s?", MEMO_I18N_DELETE);
95     memo_create_yes_no_popup(lv->win_main,lv->buf, _on_delete_yes, NULL, gld);
96 }
97
98 static void _on_send_button_clicked(void *data, Evas_Object *obj, void *event_info)
99 {
100     gl_data_t *gld = (gl_data_t *)data;
101     gl_data_t *d = NULL;
102     list_viewer_t *lv = (list_viewer_t *)gld->user_data;
103     Elm_Object_Item *it = NULL;
104
105     it = elm_genlist_first_item_get(lv->genlist);
106     while (it != NULL) {
107         d = (gl_data_t *)elm_object_item_data_get(it);
108         if (d->index == gld->index) {
109             memo_share(lv->win_main, &gld->index, 1);
110             break;
111         }
112         it = elm_genlist_item_next_get(it);
113     }
114 }
115
116 static void memo_data_iterate_cb (memo_data_t *md, void *user_data)
117 {
118     list_viewer_t *lv = (list_viewer_t *)user_data;
119     gl_data_t *gld = SMALLOC(gl_data_t);
120     RETIF(gld == NULL);
121     memo_gld_init(gld, md, lv, NULL);
122     gld->on_send = _on_send_button_clicked;
123     gld->on_delete = _on_delete_button_clicked;
124     gld->search = (lv->mode==1 ? lv->search_str : NULL);
125     if (md->has_doodle) {
126         elm_genlist_item_append(lv->genlist, &lv->itc_draw,(void *)gld,
127             NULL, ELM_GENLIST_ITEM_NONE, _on_item_select_cb, NULL);
128     } else {
129         elm_genlist_item_append(lv->genlist, &lv->itc,(void *)gld,
130             NULL, ELM_GENLIST_ITEM_NONE, _on_item_select_cb, NULL);
131     }
132     lv->count++;
133 }
134
135 static void _on_search_activated(void *data, Evas_Object *obj, void *event_info)
136 {
137     list_viewer_t *lv = (list_viewer_t *)data;
138     ecore_imf_context_input_panel_hide(lv->imf_context);
139 }
140
141 static void _update_list(void *data, Evas_Object *obj, void *event_info)
142 {
143     list_viewer_t *lv = (list_viewer_t *)data;
144
145     /* clear search result */
146     elm_genlist_clear(lv->genlist);
147     /* get search string */
148     SFREE(lv->search_str);
149     lv->search_str = elm_entry_markup_to_utf8(elm_object_text_get(lv->searchbar));
150     if (strcmp(lv->search_str, "") == 0) {
151         SFREE(lv->search_str);
152         lv->search_str = NULL;
153     }
154
155     if (lv->mode == 0) {
156         lv->count = 0;
157         memo_all_data(memo_data_iterate_cb, lv);
158         snprintf(lv->buf, MEMO_BUFFER_SIZE, "%s(%d)", MEMO_I18N_MEMO, lv->count);
159         lv->cb(lv->data, "title", lv->buf);
160         lv->cb(lv->data, "count", (void *)lv->count);
161     } else {
162         memo_search_data((lv->search_str == NULL ? "" : lv->search_str) , -1, 0, MEMO_SORT_CREATE_TIME, memo_data_iterate_cb, lv);
163     }
164     if (lv->count == 0) {
165         edje_object_signal_emit(elm_layout_edje_get(lv->body_main), "show", "nocontent");
166     } else {
167         edje_object_signal_emit(elm_layout_edje_get(lv->body_main), "hide", "nocontent");
168     }
169 }
170
171 static void _focused_cb(void *data, Evas_Object *obj, void *event_info)
172 {
173     if (!elm_entry_is_empty(obj))
174         elm_object_signal_emit(data, "elm,state,eraser,show", "elm");
175     elm_object_signal_emit(data, "elm,state,guidetext,hide", "elm");
176     elm_object_signal_emit(data, "cancel,in", "");
177 }
178
179 static void _on_searchbar_clicked(void *data, Evas_Object *obj, void *event_info)
180 {
181     list_viewer_t *lv = (list_viewer_t *)data;
182     lv->mode = 1;        /* shift to search mode */
183     if (!elm_entry_is_empty(obj)) {
184         elm_object_signal_emit(lv->searchbar_layout, "elm,state,eraser,show", "elm");
185     }
186     elm_object_signal_emit(lv->searchbar_layout, "elm,state,guidetext,hide","elm");
187     _update_list(lv, NULL, NULL);
188 }
189
190 static void _unfocused_cb(void *data, Evas_Object *obj, void *event_info)
191 {
192     if (elm_entry_is_empty(obj))
193         elm_object_signal_emit(data, "elm,state,guidetext,show", "elm");
194     elm_object_signal_emit(data, "elm,state,eraser,hide", "elm");
195 }
196
197 // When X marked button is clicked, empty entry’s contents
198 static void _eraser_clicked_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
199 {
200     elm_entry_entry_set(data, "");
201 }
202
203 static void _bg_clicked_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
204 {
205     elm_object_focus_set(data, EINA_TRUE);
206 }
207
208 static void _searchsymbol_clicked_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
209 {
210     //LOGD("[Search Bar] SearchSymbol Callback Called");
211     elm_object_focus_set(data, EINA_TRUE);
212 }
213
214 static void _cancel_clicked_cb(void *data, Evas_Object *obj, void *event_info)
215 {
216     list_viewer_t *lv = (list_viewer_t *)data;
217     lv->mode = 0;        /* shift to list mode */
218     const char* text;
219     evas_object_hide(obj);
220
221     elm_object_signal_emit(lv->searchbar_layout, "cancel,out", "");
222     text = elm_entry_entry_get(lv->searchbar);
223     if (text != NULL && strlen(text) > 0) {
224         elm_entry_entry_set(lv->searchbar, NULL);
225     }
226     elm_object_focus_set(lv->searchbar, EINA_FALSE);
227 }
228
229 static void _create_list_viewer_layout(list_viewer_t *lv, bundle *bd)
230 {
231     lv->body_main = elm_layout_create(lv->parent, EDJ_FILE, "list_frame");
232     lv->cb(lv->data, "layout", lv->body_main);
233
234     /* search bar */
235     Evas_Object *searchbar_layout = elm_layout_add(lv->body_main);
236     elm_layout_theme_set(searchbar_layout, "layout", "searchbar", "cancel_button");
237     Evas_Object *entry = elm_entry_add(searchbar_layout); /*Create entry*/
238     elm_entry_scrollable_set(entry, EINA_TRUE);
239     elm_entry_single_line_set(entry, EINA_TRUE);
240     elm_object_part_content_set(searchbar_layout, "elm.swallow.content", entry);
241     elm_object_part_text_set(searchbar_layout, "elm.guidetext", "Search"); /*Should be Language Specific*/
242
243     evas_object_size_hint_weight_set(searchbar_layout, EVAS_HINT_EXPAND, 0);
244     evas_object_size_hint_align_set(searchbar_layout, EVAS_HINT_FILL, 0.0);
245     elm_object_part_content_set(lv->body_main, "elm.swallow.search", searchbar_layout);
246
247     Evas_Object *cancel_btn = elm_button_add(searchbar_layout);
248     elm_object_part_content_set(searchbar_layout, "button_cancel", cancel_btn);
249     elm_object_style_set(cancel_btn, "searchbar/default");
250     elm_object_text_set(cancel_btn, "Cancel");
251
252     lv->searchbar = entry;
253     lv->searchbar_layout = searchbar_layout;
254     elm_entry_cnp_mode_set(entry, ELM_CNP_MODE_NO_IMAGE);
255     lv->imf_context = elm_entry_imf_context_get(entry);
256     lv->limit_filter_data.max_char_count = 0;
257     lv->limit_filter_data.max_byte_count = 64;
258
259     /* limit size */
260     elm_entry_markup_filter_append(entry, elm_entry_filter_limit_size, &lv->limit_filter_data);
261     evas_object_smart_callback_add(entry, "changed", _on_searchbar_clicked, lv);
262     evas_object_smart_callback_add(entry, "focused", _focused_cb, searchbar_layout);
263     evas_object_smart_callback_add(entry, "unfocused", _unfocused_cb, searchbar_layout);
264     elm_object_signal_callback_add(searchbar_layout, "elm,eraser,clicked", "elm", _eraser_clicked_cb, entry);
265     elm_object_signal_callback_add(searchbar_layout, "elm,bg,clicked", "elm", _bg_clicked_cb, entry);
266     elm_object_signal_callback_add(searchbar_layout, "elm,action,click", "", _searchsymbol_clicked_cb, entry);
267     evas_object_smart_callback_add(cancel_btn, "clicked", _cancel_clicked_cb, lv);
268     evas_object_smart_callback_add(entry, "activated", _on_search_activated, lv);
269
270     /* no content */
271     lv->nocontent = elm_layout_add(lv->body_main);
272     elm_layout_theme_set(lv->nocontent, "layout", "nocontents", "text");
273     elm_object_part_text_set(lv->nocontent, "elm.text", MEMO_I18N_NO_MEMOS);
274     elm_object_style_set(lv->nocontent, "text");
275     elm_object_part_content_set(lv->body_main, "elm.swallow.nocontent", lv->nocontent);
276
277     /* genlist  */
278     lv->genlist = elm_genlist_add(lv->body_main);
279     elm_object_part_content_set(lv->body_main, "elm.swallow.content", lv->genlist);
280     elm_genlist_block_count_set(lv->genlist, 10);
281
282     _update_list(lv, NULL, NULL);
283 }
284
285 void *memo_load_list_viewer(Evas_Object *parent, Evas_Object *win, bundle *bd, Memo_Component_Callback cb, void *data)
286 {
287     list_viewer_t *lv = SMALLOC(list_viewer_t);
288     RETVIF(lv==NULL, NULL);
289     bundle_dump(bd);
290     lv->parent = parent;
291     lv->cb = (cb==NULL ? memo_com_dummy_cb : cb); /* make sure cb is not null, no need to check legitimacy of cb when call */
292     lv->data = data;
293
294     /* init */
295     memo_gl_itc_init(&lv->itc, "memo/list");
296     memo_gl_itc_init(&lv->itc_draw, "memo/list_draw");
297     lv->win_main = win;
298
299     _create_list_viewer_layout(lv, bd);
300     return (void *)lv;
301 }
302
303 void memo_destroy_list_viewer(void *h_lv)
304 {
305     list_viewer_t *lv = (list_viewer_t *)h_lv;
306     evas_object_del(lv->body_main);
307     SFREE(lv->search_str);
308     SFREE(lv);
309 }
310