2 * Copyright (c) 2009 Samsung Electronics Co., Ltd All Rights Reserved
4 * PROPRIETARY/CONFIDENTIAL
6 * This software is the confidential and proprietary information of
7 * SAMSUNG ELECTRONICS ("Confidential Information"). You agree and
8 * acknowledge that this software is owned by Samsung and you shall
9 * not disclose such Confidential Information and shall use it only
10 * in accordance with the terms of the license agreement you entered
11 * into with SAMSUNG ELECTRONICS. SAMSUNG make no representations
12 * or warranties about the suitability of the software, either express
13 * or implied, including but not limited to the implied warranties of
14 * merchantability, fitness for a particular purpose, or non-infringement.
15 * SAMSUNG shall not be liable for any damages suffered by
16 * licensee arising out of or releated to this software.
20 #include "cbhm_main.h"
22 #include "xcnphandler.h"
23 #include "clipdrawer.h"
25 #define DELETE_ICON_PATH "/usr/share/cbhm/icons/05_delete.png"
26 #define IM "/usr/share/cbhm/icons/"
27 static const char *g_images_path[] = {
28 IM"cbhm_default_img.png",
32 #define GRID_ITEM_SPACE_W 6
33 #define GRID_ITEM_SINGLE_W 185
34 #define GRID_ITEM_SINGLE_H 161
35 #define GRID_ITEM_W (GRID_ITEM_SINGLE_W+(GRID_ITEM_SPACE_W*2))
36 #define GRID_ITEM_H (GRID_ITEM_SINGLE_H)
37 #define GRID_IMAGE_LIMIT_W 91
38 #define GRID_IMAGE_LIMIT_H 113
40 #define ANIM_DURATION 30 // 1 seconds
41 #define ANIM_FLOPS (0.5/30)
43 // gic should live at gengrid callback functions
44 Elm_Gengrid_Item_Class gic;
45 static Ecore_Timer *anim_timer = NULL;
47 typedef struct tag_griditem
50 Elm_Gengrid_Item *item;
51 const char *ipathdata;
52 Eina_Strbuf *istrdata;
58 remove_tags(const char *p)
64 q = malloc(strlen(p) + 1);
70 if ((*p != '<')) *q++ = *p++;
73 if ((p[1] == 'b') && (p[2] == 'r') &&
74 ((p[3] == ' ') || (p[3] == '/') || (p[3] == '>')))
76 while ((*p) && (*p != '>')) p++;
85 const char* clipdrawer_get_plain_string_from_escaped(char *escstr)
87 /* NOTE : return string should be freed */
88 return remove_tags(escstr);
91 static char* _get_string_for_entry(char *str)
96 Eina_Strbuf *strbuf = eina_strbuf_new();
99 eina_strbuf_prepend(strbuf, "<font_size=18><color=#000000FF>");
103 while (trail && *trail)
105 char *pretrail = trail;
106 unsigned long length;
110 trail = strchr(trail, '<');
113 eina_strbuf_append(strbuf, pretrail);
116 endtag = strchr(trail, '>');
120 length = trail - pretrail;
122 temp = strndup(pretrail, length);
129 DTRACE("temp str: %s \n", temp);
130 eina_strbuf_append(strbuf, temp);
140 if (strncmp(trail, "br", 2) == 0)
142 eina_strbuf_append(strbuf, "<br>");
147 if (strncmp(trail, "img", 3) == 0)
149 char *src = strstr(trail, "file://");
150 char *src_endtag = strchr(trail, '>');
151 if (!src || !src_endtag || src_endtag < src)
154 length = src_endtag - src;
156 src = strndup(src, length);
165 if (*temp == '\"' || *temp == '>')
171 eina_strbuf_append_printf(strbuf, "<item absize=66x62 href=%s></item>", src);
172 DTRACE("src str: %s \n", src);
178 char *ret = eina_strbuf_string_steal(strbuf);
179 eina_strbuf_free(strbuf);
180 DTRACE("result str: %s \n", ret);
184 static void _grid_del_response_cb(void *data, Evas_Object *obj, void *event_info)
186 Elm_Gengrid_Item *it = (Elm_Gengrid_Item *)data;
187 evas_object_del(obj);
189 if((int)event_info == ELM_POPUP_RESPONSE_OK)
191 struct appdata *ad = g_get_main_appdata();
192 elm_gengrid_item_del(it);
197 Elm_Gengrid_Item *trail = elm_gengrid_first_item_get(ad->hig);
201 elm_gengrid_item_next_get(trail);
204 DTRACE("ERR: cbhm history cnt < 0, gengrid item cnt: %d\n", cnt);
209 static void _grid_click_delete(void *data, Evas_Object *obj, void *event_info)
211 struct appdata *ad = data;
215 _grid_item_ly_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
217 struct appdata *ad = g_get_main_appdata();
219 if (ad->anim_status != STATUS_NONE)
222 Elm_Gengrid_Item *sgobj = NULL;
223 sgobj = elm_gengrid_selected_item_get(ad->hig);
224 griditem_t *ti = NULL;
225 ti = elm_gengrid_item_data_get(sgobj);
227 #define EDJE_DELBTN_PART_PREFIX "delbtn"
228 if (strncmp(source, EDJE_DELBTN_PART_PREFIX, strlen(EDJE_DELBTN_PART_PREFIX)))
232 DTRACE("ERR: cbhm can't get the selected image\n");
236 elm_gengrid_item_selected_set(sgobj, EINA_FALSE);
238 if (ti->itype == GI_TEXT)
240 char *p = strdup(eina_strbuf_string_get(ti->istrdata));
242 elm_selection_set(1, ad->hig, /*ELM_SEL_FORMAT_HTML*/0x10, p);
244 else //if (ti->itype == GI_IMAGE)
246 if (!clipdrawer_paste_textonly_get(ad))
248 int len = strlen(ti->ipathdata);
249 char *p = malloc(len + 10);
250 snprintf(p,len+10, "file:///%s", ti->ipathdata);
252 elm_selection_set(/*secondary*/1, ad->hig,/*ELM_SEL_FORMAT_IMAGE*/4,p);
256 DTRACE("ERR: cbhm image paste mode is false\n");
264 DTRACE("ERR: cbhm can't get the selected item\n");
268 elm_gengrid_item_selected_set(sgobj, EINA_FALSE);
270 Evas_Object *popup = elm_popup_add(ad->win_main);
271 elm_popup_timeout_set(popup, 5);
272 evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
273 elm_popup_desc_set(popup, "Are you sure delete this?");
274 elm_popup_buttons_add(popup, 2,
275 "Yes", ELM_POPUP_RESPONSE_OK,
276 "No", ELM_POPUP_RESPONSE_CANCEL,
278 evas_object_smart_callback_add(popup, "response", _grid_del_response_cb, sgobj);
279 evas_object_show(popup);
282 Evas_Object* _grid_icon_get(const void *data, Evas_Object *obj, const char *part)
284 griditem_t *ti = (griditem_t *)data;
286 if (!strcmp(part, "elm.swallow.icon"))
288 if (ti->itype == GI_TEXT)
290 Evas_Object *layout = elm_layout_add (obj);
291 elm_layout_theme_set(layout, "gengrid", "widestyle", "horizontal_layout");
292 edje_object_signal_callback_add(elm_layout_edje_get(layout),
293 "mouse,up,1", "*", _grid_item_ly_clicked, data);
294 Evas_Object *rect = evas_object_rectangle_add(evas_object_evas_get(obj));
295 evas_object_resize(rect, GRID_ITEM_W, GRID_ITEM_H);
296 evas_object_color_set(rect, 242, 233, 183, 255);
297 evas_object_show(rect);
298 elm_layout_content_set(layout, "elm.swallow.icon", rect);
300 // FIXME: add string length check
301 Evas_Object *ientry = elm_entry_add(obj);
302 evas_object_size_hint_weight_set(ientry, 0, 0);
303 Eina_Strbuf *strent = NULL;
304 char *strdata = eina_strbuf_string_get(ti->istrdata);
305 int i, skipflag, strcnt;
307 strent = eina_strbuf_new();
310 for (i = 0; i < eina_strbuf_length_get(ti->istrdata); i++)
328 eina_strbuf_append_n(strent, strdata, i);
329 eina_strbuf_replace_all(strent, " absize=240x180 ", " absize=52x39 ");
331 eina_strbuf_append(strent, "...");
332 elm_entry_scrollable_set(ientry, EINA_TRUE);
333 char *entry_text = eina_strbuf_string_get(strent);
334 entry_text = _get_string_for_entry(entry_text);
337 elm_object_text_part_set(ientry, NULL, entry_text);
340 elm_entry_editable_set(ientry, EINA_FALSE);
341 elm_entry_context_menu_disabled_set(ientry, EINA_TRUE);
342 evas_object_show(ientry);
343 elm_layout_content_set(layout, "elm.swallow.inner", ientry);
345 eina_strbuf_free(strent);
349 else// if (ti->itype == GI_IMAGE)
351 Evas_Object *layout = elm_layout_add (obj);
352 elm_layout_theme_set(layout, "gengrid", "widestyle", "horizontal_layout");
353 edje_object_signal_callback_add(elm_layout_edje_get(layout),
354 "mouse,up,1", "*", _grid_item_ly_clicked, data);
357 sicon = evas_object_image_add(evas_object_evas_get(obj));
358 evas_object_image_load_size_set(sicon, GRID_ITEM_SINGLE_W, GRID_ITEM_SINGLE_H);
359 evas_object_image_file_set(sicon, ti->ipathdata, NULL);
360 evas_object_image_fill_set(sicon, 0, 0, GRID_ITEM_SINGLE_W, GRID_ITEM_SINGLE_H);
361 evas_object_resize(sicon, GRID_ITEM_SINGLE_W, GRID_ITEM_SINGLE_H);
362 elm_layout_content_set(layout, "elm.swallow.icon", sicon);
364 struct appdata *ad = g_get_main_appdata();
366 if (clipdrawer_paste_textonly_get(ad))
367 edje_object_signal_emit(elm_layout_edje_get(layout), "elm,state,show,dim", "elm");
369 edje_object_signal_emit(elm_layout_edje_get(layout), "elm,state,hide,dim", "elm");
371 ti->ilayout = layout;
379 static void _grid_longpress(void *data, Evas_Object *obj, void *event_info)
381 struct appdata *ad = data;
384 static void _grid_click_paste(void *data, Evas_Object *obj, void *event_info)
386 struct appdata *ad = data;
387 if (ad->anim_status != STATUS_NONE)
390 Elm_Gengrid_Item *sgobj = NULL;
391 sgobj = elm_gengrid_selected_item_get(ad->hig);
392 griditem_t *ti = NULL;
393 ti = elm_gengrid_item_data_get(sgobj);
396 void _grid_del(const void *data, Evas_Object *obj)
398 griditem_t *ti = (griditem_t *)data;
399 if (ti->itype == GI_TEXT)
400 eina_strbuf_free(ti->istrdata);
402 eina_stringshare_del(ti->ipathdata);
406 char* clipdrawer_get_item_data(void *data, int pos)
408 struct appdata *ad = data;
409 griditem_t *ti = NULL;
410 griditem_t *newgi = NULL;
413 if (pos < 0 || pos > ad->hicount)
416 Elm_Gengrid_Item *item = elm_gengrid_first_item_get(ad->hig);
419 ti = elm_gengrid_item_data_get(item);
424 if (ti->itype == GI_TEXT)
425 return (char*)eina_strbuf_string_get(ti->istrdata);
427 return ti->ipathdata;
430 item = elm_gengrid_item_next_get(item);
436 // FIXME: how to remove calling g_get_main_appdata()?
437 // it's mainly used at 'clipdrawer_image_item'
438 int clipdrawer_add_item(char *idata, int type)
440 struct appdata *ad = g_get_main_appdata();
441 griditem_t *newgi = NULL;
443 newgi = malloc(sizeof(griditem_t));
446 fprintf(stderr, "## add - %d : %s\n", newgi->itype, idata);
449 newgi->istrdata = eina_strbuf_new();
450 eina_strbuf_append(newgi->istrdata, idata);
452 else //if (type == GI_IMAGE)
454 Elm_Gengrid_Item *item = elm_gengrid_first_item_get(ad->hig);
455 griditem_t *ti = NULL;
457 if (!check_regular_file(idata))
459 DTRACE("Error : it isn't normal file = %s\n", idata);
465 ti = elm_gengrid_item_data_get(item);
466 if ((ti->itype == type) && !strcmp(ti->ipathdata, idata))
468 DTRACE("Error : duplicated file path = %s\n", idata);
471 item = elm_gengrid_item_next_get(item);
473 newgi->ipathdata = eina_stringshare_add(idata);
476 if (ad->hicount >= HISTORY_QUEUE_MAX_ITEMS)
479 // FIXME: add routine that is removing its elements
480 elm_gengrid_item_del(elm_gengrid_last_item_get(ad->hig));
484 newgi->item = elm_gengrid_item_prepend(ad->hig, &gic, newgi, NULL, NULL);
490 clipdrawer_ly_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
492 struct appdata *ad = data;
494 if (ad->anim_status != STATUS_NONE)
497 #define EDJE_CLOSE_PART_PREFIX "background/close"
498 if (!strncmp(source, EDJE_CLOSE_PART_PREFIX, strlen(EDJE_CLOSE_PART_PREFIX)))
500 clipdrawer_lower_view(ad);
504 static void set_sliding_win_geometry(void *data)
506 struct appdata *ad = data;
507 Ecore_X_Window zone, xwin;
508 Evas_Coord x, y, w, h;
509 xwin = elm_win_xwindow_get(ad->win_main);
510 zone = ecore_x_e_illume_zone_get(xwin);
511 DTRACE("[CBHM] xwin:%x, zone:%x\n", xwin, zone);
513 // ecore_evas_geometry_get(ecore_evas_ecore_evas_get(evas_object_evas_get(ad->win_main)), &x, &y, &w, &h);
515 if (ad->o_degree == 90 || ad->o_degree == 270)
517 h = ad->anim_count * CLIPDRAWER_HEIGHT_LANDSCAPE / ANIM_DURATION;
524 h = ad->anim_count * CLIPDRAWER_HEIGHT / ANIM_DURATION;
533 DTRACE("[CBHM] change degree geometry... (%d, %d, %d x %d)\n", x, y, w, h);
534 ecore_x_e_illume_sliding_win_geometry_set(zone, x, y, w, h);
535 ecore_x_e_illume_sliding_win_state_set(zone, ad->anim_count != 0);
538 void set_rotation_to_clipdrawer(void *data)
540 struct appdata *ad = data;
541 int angle = ad->o_degree;
544 if (angle == 180) // reverse
546 h = CLIPDRAWER_HEIGHT;
551 else if (angle == 90) // right rotate
553 h = CLIPDRAWER_HEIGHT_LANDSCAPE;
558 else if (angle == 270) // left rotate
560 h = CLIPDRAWER_HEIGHT_LANDSCAPE;
567 h = CLIPDRAWER_HEIGHT;
573 evas_object_resize(ad->win_main, w, h);
574 evas_object_move(ad->win_main, x, y);
575 if (ad->anim_count == ANIM_DURATION)
576 set_sliding_win_geometry(data);
579 int clipdrawer_init(void *data)
581 struct appdata *ad = data;
584 ad->windowshow = EINA_FALSE;
586 ad->pastetextonly = EINA_TRUE;
587 ad->anim_status = STATUS_NONE;
591 elm_theme_extension_add(NULL, APP_EDJ_FILE);
593 edje_object_signal_callback_add(elm_layout_edje_get(ad->ly_main),
594 "mouse,up,1", "*", clipdrawer_ly_clicked, ad);
597 ad->hig = elm_gengrid_add(ad->win_main);
598 elm_layout_content_set(ad->ly_main, "historyitems", ad->hig);
599 elm_gengrid_item_size_set(ad->hig, GRID_ITEM_W+2, GRID_ITEM_H);
600 elm_gengrid_align_set(ad->hig, 0.5, 0.5);
601 elm_gengrid_horizontal_set(ad->hig, EINA_TRUE);
602 elm_gengrid_bounce_set(ad->hig, EINA_TRUE, EINA_FALSE);
603 elm_gengrid_multi_select_set(ad->hig, EINA_FALSE);
604 evas_object_smart_callback_add(ad->hig, "selected", _grid_click_paste, ad);
605 // evas_object_smart_callback_add(ad->hig, "longpressed", _grid_longpress, ad);
606 evas_object_size_hint_weight_set(ad->hig, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
608 elm_gengrid_clear(ad->hig);
610 gic.item_style = "default_grid";
611 gic.func.label_get = NULL;
612 gic.func.icon_get = _grid_icon_get;
613 gic.func.state_get = NULL;
614 gic.func.del = _grid_del;
619 for (i = 0; i < N_IMAGES; i++)
621 clipdrawer_add_item(g_images_path[0], GI_IMAGE);
624 clipdrawer_add_item("clipboard history", GI_TEXT);
626 evas_object_show (ad->hig);
628 // for debugging, calc history pos
630 Evas_Coord x, y, w, h;
631 Evas_Coord vx, vy, vw, vh;
633 edje_object_part_geometry_get(elm_layout_edje_get(ad->ly_main),"imagehistory/list",&x,&y,&w,&h);
634 evas_object_geometry_get (ad->hig, &vx,&vy,&vw,&vh);
635 fprintf(stderr, "## x = %d, y = %d, w = %d, h = %d\n", x, y, w, h);
636 fprintf(stderr, "## vx = %d, vy = %d, vw = %d, vh = %d\n", vx, vy, vw, vh);
639 // if (get_item_counts() != 0)
640 // clipdrawer_update_contents(ad);
645 int clipdrawer_create_view(void *data)
647 struct appdata *ad = data;
652 // at starting, showing app view
653 //clipdrawer_activate_view(ad);
658 Eina_Bool _get_anim_pos(void *data, int *sp, int *ep)
663 struct appdata *ad = data;
664 int angle = ad->o_degree;
665 int anim_start, anim_end;
667 if (angle == 180) // reverse
669 anim_start = -(ad->root_h - CLIPDRAWER_HEIGHT);
672 else if (angle == 90) // right rotate
674 anim_start = ad->root_w;
675 anim_end = anim_start - CLIPDRAWER_HEIGHT_LANDSCAPE;
677 else if (angle == 270) // left rotate
679 anim_start = -(ad->root_w - CLIPDRAWER_HEIGHT_LANDSCAPE);
684 anim_start = ad->root_h;
685 anim_end = anim_start - CLIPDRAWER_HEIGHT;
693 Eina_Bool _do_anim_delta_pos(void *data, int sp, int ep, int ac, int *dp)
698 struct appdata *ad = data;
699 int angle = ad->o_degree;
702 posprop = 1.0*ac/ANIM_DURATION;
704 if (angle == 180) // reverse
706 delta = (int)((ep-sp)*posprop);
707 evas_object_move(ad->win_main, 0, sp+delta);
709 else if (angle == 90) // right rotate
711 delta = (int)((ep-sp)*posprop);
712 evas_object_move(ad->win_main, sp+delta, 0);
714 else if (angle == 270) // left rotate
716 delta = (int)((ep-sp)*posprop);
717 evas_object_move(ad->win_main, sp+delta, 0);
721 delta = (int)((sp-ep)*posprop);
722 evas_object_move(ad->win_main, 0, sp-delta);
730 static void stop_animation(void *data)
732 struct appdata *ad = data;
734 ad->anim_status = STATUS_NONE;
737 ecore_timer_del(anim_timer);
741 set_sliding_win_geometry(data);
744 Eina_Bool anim_pos_calc_cb(void *data)
746 struct appdata *ad = data;
748 int anim_start, anim_end, delta;
750 _get_anim_pos(ad, &anim_start, &anim_end);
752 if (ad->anim_status == SHOW_ANIM)
754 if (ad->anim_count > ANIM_DURATION)
756 ad->anim_count = ANIM_DURATION;
757 stop_animation(data);
760 _do_anim_delta_pos(ad, anim_start, anim_end, ad->anim_count, &delta);
763 else if (ad->anim_status == HIDE_ANIM)
765 if (ad->anim_count < 0)
768 evas_object_hide(ad->win_main);
769 elm_win_lower(ad->win_main);
770 unset_transient_for(ad);
771 stop_animation(data);
774 _do_anim_delta_pos(ad, anim_start, anim_end, ad->anim_count, &delta);
779 stop_animation(data);
786 Eina_Bool clipdrawer_anim_effect(void *data, anim_status_t atype)
788 struct appdata *ad = data;
790 if (atype == ad->anim_status)
792 DTRACE("Warning: Animation effect is already in progress. \n");
796 ad->anim_status = atype;
799 ecore_timer_del(anim_timer);
801 anim_timer = ecore_timer_add(ANIM_FLOPS, anim_pos_calc_cb, ad);
806 void clipdrawer_activate_view(void *data)
808 struct appdata *ad = data;
812 set_transient_for(ad);
813 ad->o_degree = get_active_window_degree(ad->active_win);
814 elm_win_rotation_set(ad->win_main, ad->o_degree);
815 set_rotation_to_clipdrawer(data);
816 evas_object_show(ad->win_main);
817 elm_win_activate(ad->win_main);
818 if (clipdrawer_anim_effect(ad, SHOW_ANIM))
819 ad->windowshow = EINA_TRUE;
823 void clipdrawer_lower_view(void *data)
825 struct appdata *ad = data;
827 if (ad->win_main && ad->windowshow)
829 if (clipdrawer_anim_effect(ad, HIDE_ANIM))
830 ad->windowshow = EINA_FALSE;
834 void _change_gengrid_paste_textonly_mode(void *data)
836 struct appdata *ad = data;
838 griditem_t *ti = NULL;
840 Elm_Gengrid_Item *item = elm_gengrid_first_item_get(ad->hig);
844 ti = elm_gengrid_item_data_get(item);
845 if ((ti->itype == GI_IMAGE) && (ti->ilayout))
847 if (clipdrawer_paste_textonly_get(ad))
848 edje_object_signal_emit(elm_layout_edje_get(ti->ilayout), "elm,state,show,dim", "elm");
850 edje_object_signal_emit(elm_layout_edje_get(ti->ilayout), "elm,state,hide,dim", "elm");
852 item = elm_gengrid_item_next_get(item);
856 void clipdrawer_paste_textonly_set(void *data, Eina_Bool textonly)
858 struct appdata *ad = data;
859 textonly = !!textonly;
860 if (ad->pastetextonly != textonly)
861 ad->pastetextonly = textonly;
862 DTRACE("paste textonly mode = %d\n", textonly);
864 _change_gengrid_paste_textonly_mode(ad);
867 Eina_Bool clipdrawer_paste_textonly_get(void *data)
869 struct appdata *ad = data;
870 return ad->pastetextonly;