4 #include "xcnphandler.h"
5 #include "clipdrawer.h"
7 #define DELETE_ICON_PATH "/usr/share/cbhm/icons/05_delete.png"
8 #define IM "/usr/share/cbhm/icons/"
9 static const char *g_images_path[] = {
10 IM"cbhm_default_img.png",
14 #define GRID_ITEM_SPACE_W 6
15 #define GRID_ITEM_SINGLE_W 185
16 #define GRID_ITEM_SINGLE_H 161
17 #define GRID_ITEM_W (GRID_ITEM_SINGLE_W+(GRID_ITEM_SPACE_W*2))
18 #define GRID_ITEM_H (GRID_ITEM_SINGLE_H)
19 #define GRID_IMAGE_LIMIT_W 91
20 #define GRID_IMAGE_LIMIT_H 113
22 #define ANIM_DURATION 30 // 1 seconds
23 #define ANIM_FLOPS (0.5/30)
25 // gic should live at gengrid callback functions
26 Elm_Gengrid_Item_Class gic;
27 static Ecore_Timer *anim_timer = NULL;
29 typedef struct tag_griditem
32 Elm_Gengrid_Item *item;
33 const char *ipathdata;
34 Eina_Strbuf *istrdata;
40 remove_tags(const char *p)
46 q = malloc(strlen(p) + 1);
52 if ((*p != '<')) *q++ = *p++;
55 if ((p[1] == 'b') && (p[2] == 'r') &&
56 ((p[3] == ' ') || (p[3] == '/') || (p[3] == '>')))
58 while ((*p) && (*p != '>')) p++;
67 const char* clipdrawer_get_plain_string_from_escaped(char *escstr)
69 /* NOTE : return string should be freed */
70 return remove_tags(escstr);
73 static char* _get_string_for_entry(char *str)
78 Eina_Strbuf *strbuf = eina_strbuf_new();
81 eina_strbuf_prepend(strbuf, "<font_size=18>");
85 while (trail && *trail)
87 char *pretrail = trail;
92 trail = strchr(trail, '<');
95 eina_strbuf_append(strbuf, pretrail);
98 endtag = strchr(trail, '>');
102 length = trail - pretrail;
104 temp = strndup(pretrail, length);
111 DTRACE("temp str: %s \n", temp);
112 eina_strbuf_append(strbuf, temp);
122 if (strncmp(trail, "br", 2) == 0)
124 eina_strbuf_append(strbuf, "<br>");
129 if (strncmp(trail, "img", 3) == 0)
131 char *src = strstr(trail, "file://");
132 char *src_endtag = strchr(trail, '>');
133 if (!src || !src_endtag || src_endtag < src)
136 length = src_endtag - src;
138 src = strndup(src, length);
147 if (*temp == '\"' || *temp == '>')
153 eina_strbuf_append_printf(strbuf, "<item absize=66x62 href=%s></item>", src);
154 DTRACE("src str: %s \n", src);
160 char *ret = eina_strbuf_string_steal(strbuf);
161 eina_strbuf_free(strbuf);
162 DTRACE("result str: %s \n", ret);
166 static void _grid_del_response_cb(void *data, Evas_Object *obj, void *event_info)
168 Elm_Gengrid_Item *it = (Elm_Gengrid_Item *)data;
169 evas_object_del(obj);
171 if((int)event_info == ELM_POPUP_RESPONSE_OK)
173 struct appdata *ad = g_get_main_appdata();
174 elm_gengrid_item_del(it);
179 Elm_Gengrid_Item *trail = elm_gengrid_first_item_get(ad->hig);
183 elm_gengrid_item_next_get(trail);
186 DTRACE("ERR: cbhm history cnt < 0, gengrid item cnt: %d\n", cnt);
191 static void _grid_click_delete(void *data, Evas_Object *obj, void *event_info)
193 struct appdata *ad = data;
197 _grid_item_ly_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
199 struct appdata *ad = g_get_main_appdata();
201 if (ad->anim_status != STATUS_NONE)
204 Elm_Gengrid_Item *sgobj = NULL;
205 sgobj = elm_gengrid_selected_item_get(ad->hig);
206 griditem_t *ti = NULL;
207 ti = elm_gengrid_item_data_get(sgobj);
209 #define EDJE_DELBTN_PART_PREFIX "delbtn"
210 if (strncmp(source, EDJE_DELBTN_PART_PREFIX, strlen(EDJE_DELBTN_PART_PREFIX)))
214 DTRACE("ERR: cbhm can't get the selected image\n");
218 elm_gengrid_item_selected_set(sgobj, EINA_FALSE);
220 if (ti->itype == GI_TEXT)
222 char *p = strdup(eina_strbuf_string_get(ti->istrdata));
224 elm_selection_set(1, ad->hig, /*ELM_SEL_FORMAT_HTML*/0x10, p);
226 else //if (ti->itype == GI_IMAGE)
228 if (!clipdrawer_paste_textonly_get(ad))
230 int len = strlen(ti->ipathdata);
231 char *p = malloc(len + 10);
232 snprintf(p,len+10, "file:///%s", ti->ipathdata);
234 elm_selection_set(/*secondary*/1, ad->hig,/*ELM_SEL_FORMAT_IMAGE*/4,p);
238 DTRACE("ERR: cbhm image paste mode is false\n");
247 DTRACE("ERR: cbhm can't get the selected item\n");
251 elm_gengrid_item_selected_set(sgobj, EINA_FALSE);
253 Evas_Object *popup = elm_popup_add(ad->win_main);
254 elm_popup_timeout_set(popup, 5);
255 evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
256 elm_popup_desc_set(popup, "Are you sure delete this?");
257 elm_popup_buttons_add(popup, 2,
258 "Yes", ELM_POPUP_RESPONSE_OK,
259 "No", ELM_POPUP_RESPONSE_CANCEL,
261 evas_object_smart_callback_add(popup, "response", _grid_del_response_cb, sgobj);
262 evas_object_show(popup);
265 Evas_Object* _grid_icon_get(const void *data, Evas_Object *obj, const char *part)
267 griditem_t *ti = (griditem_t *)data;
269 if (!strcmp(part, "elm.swallow.icon"))
271 if (ti->itype == GI_TEXT)
273 Evas_Object *layout = elm_layout_add (obj);
274 elm_layout_theme_set(layout, "gengrid", "widestyle", "horizontal_layout");
275 edje_object_signal_callback_add(elm_layout_edje_get(layout),
276 "mouse,up,1", "*", _grid_item_ly_clicked, data);
277 Evas_Object *rect = evas_object_rectangle_add(evas_object_evas_get(obj));
278 evas_object_resize(rect, GRID_ITEM_W, GRID_ITEM_H);
279 evas_object_color_set(rect, 242, 233, 183, 255);
280 evas_object_show(rect);
281 elm_layout_content_set(layout, "elm.swallow.icon", rect);
283 // FIXME: add string length check
284 Evas_Object *ientry = elm_entry_add(obj);
285 evas_object_size_hint_weight_set(ientry, 0, 0);
286 Eina_Strbuf *strent = NULL;
287 char *strdata = eina_strbuf_string_get(ti->istrdata);
288 int i, skipflag, strcnt;
290 strent = eina_strbuf_new();
293 for (i = 0; i < eina_strbuf_length_get(ti->istrdata); i++)
311 eina_strbuf_append_n(strent, strdata, i);
312 eina_strbuf_replace_all(strent, " absize=240x180 ", " absize=52x39 ");
314 eina_strbuf_append(strent, "...");
315 elm_entry_scrollable_set(ientry, EINA_TRUE);
316 char *entry_text = eina_strbuf_string_get(strent);
317 entry_text = _get_string_for_entry(entry_text);
320 elm_object_text_part_set(ientry, NULL, entry_text);
323 elm_entry_editable_set(ientry, EINA_FALSE);
324 elm_entry_context_menu_disabled_set(ientry, EINA_TRUE);
325 evas_object_show(ientry);
326 elm_layout_content_set(layout, "elm.swallow.inner", ientry);
328 eina_strbuf_free(strent);
332 else// if (ti->itype == GI_IMAGE)
334 Evas_Object *layout = elm_layout_add (obj);
335 elm_layout_theme_set(layout, "gengrid", "widestyle", "horizontal_layout");
336 edje_object_signal_callback_add(elm_layout_edje_get(layout),
337 "mouse,up,1", "*", _grid_item_ly_clicked, data);
340 sicon = evas_object_image_add(evas_object_evas_get(obj));
341 evas_object_image_load_size_set(sicon, GRID_ITEM_SINGLE_W, GRID_ITEM_SINGLE_H);
342 evas_object_image_file_set(sicon, ti->ipathdata, NULL);
343 evas_object_image_fill_set(sicon, 0, 0, GRID_ITEM_SINGLE_W, GRID_ITEM_SINGLE_H);
344 evas_object_resize(sicon, GRID_ITEM_SINGLE_W, GRID_ITEM_SINGLE_H);
345 elm_layout_content_set(layout, "elm.swallow.icon", sicon);
347 struct appdata *ad = g_get_main_appdata();
349 if (!clipdrawer_paste_textonly_get(ad))
351 // edje_object_signal_emit(elm_layout_edje_get(layout), "elm,state,hide,delbtn", "elm");
352 Evas_Object *rect = evas_object_rectangle_add(evas_object_evas_get(obj));
353 evas_object_color_set(rect, 0, 0, 0, 200);
354 evas_object_show(rect);
355 elm_layout_content_set(layout, "elm.swallow.cover", rect);
358 ti->ilayout = layout;
366 static void _grid_longpress(void *data, Evas_Object *obj, void *event_info)
368 struct appdata *ad = data;
371 static void _grid_click_paste(void *data, Evas_Object *obj, void *event_info)
373 struct appdata *ad = data;
374 if (ad->anim_status != STATUS_NONE)
377 Elm_Gengrid_Item *sgobj = NULL;
378 sgobj = elm_gengrid_selected_item_get(ad->hig);
379 griditem_t *ti = NULL;
380 ti = elm_gengrid_item_data_get(sgobj);
383 void _grid_del(const void *data, Evas_Object *obj)
385 griditem_t *ti = (griditem_t *)data;
386 if (ti->itype == GI_TEXT)
387 eina_strbuf_free(ti->istrdata);
389 eina_stringshare_del(ti->ipathdata);
393 char* clipdrawer_get_item_data(void *data, int pos)
395 struct appdata *ad = data;
396 griditem_t *ti = NULL;
397 griditem_t *newgi = NULL;
400 if (pos < 0 || pos > ad->hicount)
403 Elm_Gengrid_Item *item = elm_gengrid_first_item_get(ad->hig);
406 ti = elm_gengrid_item_data_get(item);
411 if (ti->itype == GI_TEXT)
412 return (char*)eina_strbuf_string_get(ti->istrdata);
414 return ti->ipathdata;
417 item = elm_gengrid_item_next_get(item);
423 // FIXME: how to remove calling g_get_main_appdata()?
424 // it's mainly used at 'clipdrawer_image_item'
425 int clipdrawer_add_item(char *idata, int type)
427 struct appdata *ad = g_get_main_appdata();
428 griditem_t *newgi = NULL;
430 newgi = malloc(sizeof(griditem_t));
433 fprintf(stderr, "## add - %d : %s\n", newgi->itype, idata);
436 newgi->istrdata = eina_strbuf_new();
437 eina_strbuf_append(newgi->istrdata, idata);
439 else //if (type == GI_IMAGE)
441 Elm_Gengrid_Item *item = elm_gengrid_first_item_get(ad->hig);
442 griditem_t *ti = NULL;
444 if (!check_regular_file(idata))
446 DTRACE("Error : it isn't normal file = %s\n", idata);
452 ti = elm_gengrid_item_data_get(item);
453 if ((ti->itype == type) && !strcmp(ti->ipathdata, idata))
455 DTRACE("Error : duplicated file path = %s\n", idata);
458 item = elm_gengrid_item_next_get(item);
460 newgi->ipathdata = eina_stringshare_add(idata);
463 if (ad->hicount >= HISTORY_QUEUE_MAX_ITEMS)
466 // FIXME: add routine that is removing its elements
467 elm_gengrid_item_del(elm_gengrid_last_item_get(ad->hig));
471 newgi->item = elm_gengrid_item_prepend(ad->hig, &gic, newgi, NULL, NULL);
477 clipdrawer_ly_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
479 struct appdata *ad = data;
481 if (ad->anim_status != STATUS_NONE)
484 #define EDJE_CLOSE_PART_PREFIX "background/close"
485 if (!strncmp(source, EDJE_CLOSE_PART_PREFIX, strlen(EDJE_CLOSE_PART_PREFIX)))
487 clipdrawer_lower_view(ad);
491 void set_rotation_to_clipdrawer(void *data)
493 struct appdata *ad = data;
496 int angle = ad->o_degree;
498 if (angle == 180) // reverse
500 wh = (1.0*CLIPDRAWER_HEIGHT/SCREEN_HEIGHT)*ad->root_h;
503 wposx = CLIPDRAWER_POS_X;
505 else if (angle == 90) // right rotate
507 wh = (1.0*CLIPDRAWER_HEIGHT_LANDSCAPE/SCREEN_WIDTH)*ad->root_w;
508 wy = (1.0*CLIPDRAWER_POS_X/SCREEN_WIDTH)*ad->root_w;
510 wposx = CLIPDRAWER_WIDTH-CLIPDRAWER_HEIGHT_LANDSCAPE;
512 else if (angle == 270) // left rotate
514 wh = (1.0*CLIPDRAWER_HEIGHT_LANDSCAPE/SCREEN_WIDTH)*ad->root_w;
515 wy = (1.0*CLIPDRAWER_POS_X/SCREEN_WIDTH)*ad->root_w;
517 wposx = CLIPDRAWER_POS_X;
521 wh = (1.0*CLIPDRAWER_HEIGHT/SCREEN_HEIGHT)*ad->root_h;
522 wy = (1.0*CLIPDRAWER_POS_Y/SCREEN_HEIGHT)*ad->root_h;
524 wposx = CLIPDRAWER_POS_X;
527 evas_object_resize(ad->win_main, wwidth, (int)wh);
528 evas_object_move(ad->win_main, wposx, (int)wy);
531 int clipdrawer_init(void *data)
533 struct appdata *ad = data;
536 ad->windowshow = EINA_FALSE;
538 ad->pastetextonly = EINA_TRUE;
539 ad->anim_status = STATUS_NONE;
543 elm_theme_extension_add(NULL, APP_EDJ_FILE);
545 edje_object_signal_callback_add(elm_layout_edje_get(ad->ly_main),
546 "mouse,up,1", "*", clipdrawer_ly_clicked, ad);
549 ad->hig = elm_gengrid_add(ad->win_main);
550 elm_layout_content_set(ad->ly_main, "historyitems", ad->hig);
551 elm_gengrid_item_size_set(ad->hig, GRID_ITEM_W+2, GRID_ITEM_H);
552 elm_gengrid_align_set(ad->hig, 0.5, 0.5);
553 elm_gengrid_horizontal_set(ad->hig, EINA_TRUE);
554 elm_gengrid_bounce_set(ad->hig, EINA_TRUE, EINA_FALSE);
555 elm_gengrid_multi_select_set(ad->hig, EINA_FALSE);
556 evas_object_smart_callback_add(ad->hig, "selected", _grid_click_paste, ad);
557 // evas_object_smart_callback_add(ad->hig, "longpressed", _grid_longpress, ad);
558 evas_object_size_hint_weight_set(ad->hig, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
560 elm_gengrid_clear(ad->hig);
562 gic.item_style = "default_grid";
563 gic.func.label_get = NULL;
564 gic.func.icon_get = _grid_icon_get;
565 gic.func.state_get = NULL;
566 gic.func.del = _grid_del;
571 for (i = 0; i < N_IMAGES; i++)
573 clipdrawer_add_item(g_images_path[0], GI_IMAGE);
576 clipdrawer_add_item("clipboard history", GI_TEXT);
578 evas_object_show (ad->hig);
580 // for debugging, calc history pos
582 Evas_Coord x, y, w, h;
583 Evas_Coord vx, vy, vw, vh;
585 edje_object_part_geometry_get(elm_layout_edje_get(ad->ly_main),"imagehistory/list",&x,&y,&w,&h);
586 evas_object_geometry_get (ad->hig, &vx,&vy,&vw,&vh);
587 fprintf(stderr, "## x = %d, y = %d, w = %d, h = %d\n", x, y, w, h);
588 fprintf(stderr, "## vx = %d, vy = %d, vw = %d, vh = %d\n", vx, vy, vw, vh);
591 // if (get_item_counts() != 0)
592 // clipdrawer_update_contents(ad);
597 int clipdrawer_create_view(void *data)
599 struct appdata *ad = data;
604 // at starting, showing app view
605 //clipdrawer_activate_view(ad);
610 Eina_Bool _get_anim_pos(void *data, int *sp, int *ep)
615 struct appdata *ad = data;
616 int angle = ad->o_degree;
617 int anim_start, anim_end, delta;
619 if (angle == 180) // reverse
621 anim_start = (int)(((double)CLIPDRAWER_HEIGHT/SCREEN_HEIGHT)*ad->root_h);
622 anim_start = ad->root_h - anim_start;
623 anim_start = -anim_start;
626 else if (angle == 90) // right rotate
628 anim_start = ad->root_w;
629 anim_end = (int)(((double)CLIPDRAWER_HEIGHT_LANDSCAPE/SCREEN_WIDTH)*ad->root_w);
630 anim_end = anim_start-anim_end;
632 else if (angle == 270) // left rotate
634 anim_start = (int)(((double)CLIPDRAWER_HEIGHT_LANDSCAPE/SCREEN_WIDTH)*ad->root_w);
635 anim_start = ad->root_w-anim_start;
636 anim_start = -anim_start;
641 anim_start = ad->root_h;
642 anim_end = (int)(((double)CLIPDRAWER_HEIGHT/SCREEN_HEIGHT)*ad->root_h);
643 anim_end = anim_start-anim_end;
651 Eina_Bool _do_anim_delta_pos(void *data, int sp, int ep, int ac, int *dp)
656 struct appdata *ad = data;
657 int angle = ad->o_degree;
660 posprop = 1.0*ac/ANIM_DURATION;
662 if (angle == 180) // reverse
664 delta = (int)((ep-sp)*posprop);
665 evas_object_move(ad->win_main, 0, sp+delta);
667 else if (angle == 90) // right rotate
669 delta = (int)((ep-sp)*posprop);
670 evas_object_move(ad->win_main, sp+delta, 0);
672 else if (angle == 270) // left rotate
674 delta = (int)((ep-sp)*posprop);
675 evas_object_move(ad->win_main, sp+delta, 0);
679 delta = (int)((sp-ep)*posprop);
680 evas_object_move(ad->win_main, 0, sp-delta);
688 static void stop_animation(void *data)
690 struct appdata *ad = data;
692 ad->anim_status = STATUS_NONE;
695 ecore_timer_del(anim_timer);
700 Eina_Bool anim_pos_calc_cb(void *data)
702 struct appdata *ad = data;
704 int anim_start, anim_end, delta;
706 _get_anim_pos(ad, &anim_start, &anim_end);
708 if (ad->anim_status == SHOW_ANIM)
710 if (ad->anim_count > ANIM_DURATION)
712 ad->anim_count = ANIM_DURATION;
713 stop_animation(data);
716 _do_anim_delta_pos(ad, anim_start, anim_end, ad->anim_count, &delta);
719 else if (ad->anim_status == HIDE_ANIM)
721 if (ad->anim_count < 0)
724 evas_object_hide(ad->win_main);
725 elm_win_lower(ad->win_main);
726 unset_transient_for(ad);
727 stop_animation(data);
730 _do_anim_delta_pos(ad, anim_start, anim_end, ad->anim_count, &delta);
735 stop_animation(data);
742 Eina_Bool clipdrawer_anim_effect(void *data, anim_status_t atype)
744 struct appdata *ad = data;
746 if (atype == ad->anim_status)
748 DTRACE("Warning: Animation effect is already in progress. \n");
752 ad->anim_status = atype;
755 ecore_timer_del(anim_timer);
757 anim_timer = ecore_timer_add(ANIM_FLOPS, anim_pos_calc_cb, ad);
762 void clipdrawer_activate_view(void *data)
764 struct appdata *ad = data;
768 set_transient_for(ad);
769 ad->o_degree = get_active_window_degree(ad->active_win);
770 elm_win_rotation_set(ad->win_main, ad->o_degree);
771 set_rotation_to_clipdrawer(data);
772 evas_object_show(ad->win_main);
773 elm_win_activate(ad->win_main);
774 if (clipdrawer_anim_effect(ad, SHOW_ANIM))
775 ad->windowshow = EINA_TRUE;
779 void clipdrawer_lower_view(void *data)
781 struct appdata *ad = data;
783 if (ad->win_main && ad->windowshow)
785 if (clipdrawer_anim_effect(ad, HIDE_ANIM))
786 ad->windowshow = EINA_FALSE;
790 void _change_gengrid_paste_textonly_mode(void *data)
792 struct appdata *ad = data;
794 Elm_Gengrid_Item *item;
795 griditem_t *ti = NULL;
797 if (clipdrawer_paste_textonly_get(ad))
798 { // textonly paste mode
799 Elm_Gengrid_Item *item = elm_gengrid_first_item_get(ad->hig);
803 ti = elm_gengrid_item_data_get(item);
804 if ((ti->itype == GI_IMAGE) && (ti->ilayout))
806 // edje_object_signal_emit(elm_layout_edje_get(ti->ilayout), "elm,state,hide,delbtn", "elm");
807 Evas_Object *rect = evas_object_rectangle_add(evas_object_evas_get(ad->hig));
808 evas_object_color_set(rect, 0, 0, 0, 200);
809 evas_object_show(rect);
810 elm_layout_content_set(ti->ilayout, "elm.swallow.cover", rect);
812 item = elm_gengrid_item_next_get(item);
816 { // text+image paste mode
817 Elm_Gengrid_Item *item = elm_gengrid_first_item_get(ad->hig);
821 ti = elm_gengrid_item_data_get(item);
822 if ((ti->itype == GI_IMAGE) && (ti->ilayout))
824 // edje_object_signal_emit(elm_layout_edje_get(ti->ilayout), "elm,state,show,delbtn", "elm");
825 Evas_Object *rect = elm_layout_content_unset(ti->ilayout, "elm.swallow.cover");
826 evas_object_hide(rect);
827 evas_object_del(rect);
829 item = elm_gengrid_item_next_get(item);
834 void clipdrawer_paste_textonly_set(void *data, Eina_Bool textonly)
836 struct appdata *ad = data;
837 textonly = !!textonly;
838 if (ad->pastetextonly != textonly)
839 ad->pastetextonly = textonly;
840 DTRACE("paste textonly mode = %d\n", textonly);
842 _change_gengrid_paste_textonly_mode(ad);
845 Eina_Bool clipdrawer_paste_textonly_get(void *data)
847 struct appdata *ad = data;
848 return ad->pastetextonly;