Merge "[Copy&Paste popup] popup is hidden by only caller entry"
[framework/uifw/elementary.git] / src / modules / ctxpopup_copypasteUI / copypaste.c
1 #include <Elementary.h>
2 #include "elm_module_priv.h"
3 #include "elm_priv.h"
4
5 Elm_Entry_Extension_data *ext_mod;
6 static int _mod_hook_count = 0;
7
8 typedef struct _Elm_Entry_Context_Menu_Item Elm_Entry_Context_Menu_Item;
9 struct _Elm_Entry_Context_Menu_Item
10 {
11    Evas_Object *obj;
12    const char *label;
13    const char *icon_file;
14    const char *icon_group;
15    Elm_Icon_Type icon_type;
16    Evas_Smart_Cb func;
17    void *data;
18 };
19
20 static void
21 _ctxpopup_hide(Evas_Object *popup)
22 {
23    evas_object_hide(popup);
24    ext_mod->caller = NULL;
25 }
26
27 static void
28 _ctxpopup_position(Evas_Object *obj)
29 {
30    if(!ext_mod) return;
31
32    Evas_Coord cx, cy, cw, ch, x, y, w, h;
33    if (!edje_object_part_text_selection_geometry_get(ext_mod->ent, "elm.text", &x, &y, &w, &h))
34      {
35         evas_object_geometry_get(ext_mod->ent, &x, &y, NULL, NULL);
36         edje_object_part_text_cursor_geometry_get(ext_mod->ent, "elm.text",
37                                                   &cx, &cy, &cw, &ch);
38         evas_object_size_hint_min_get(ext_mod->popup, &w, &h);
39         if (cw < w)
40           {
41              cx += (cw - w) / 2;
42              cw = w;
43           }
44         if (ch < h)
45           {
46              cy += (ch - h) / 2;
47              ch = h;
48           }
49         evas_object_move(ext_mod->popup, x + cx, y + cy);
50         evas_object_resize(ext_mod->popup, cw, ch);
51      }
52    else
53      {
54         if (ext_mod->viewport_rect.x != -1 || ext_mod->viewport_rect.y != -1
55             || ext_mod->viewport_rect.w != -1 || ext_mod->viewport_rect.h != -1)
56           {
57              Evas_Coord vx, vy, vw, vh, x2, y2;
58              x2 = x + w;
59              y2 = y + h;
60              vx = ext_mod->viewport_rect.x;
61              vy = ext_mod->viewport_rect.y;
62              vw = ext_mod->viewport_rect.w;
63              vh = ext_mod->viewport_rect.h;
64
65              if (x < vx) x = vx;
66              if (y < vy) y = vy;
67              if (x2 > vx + vw) x2 = vx + vw;
68              if (y2 > vy + vh) y2 = vy + vh;
69              w = x2 - x;
70              h = y2 - y;
71           }
72         else
73           {
74              Evas_Coord sw, sh, x2, y2;
75              x2 = x + w;
76              y2 = y + h;
77              ecore_x_window_size_get(ecore_x_window_root_first_get(), &sw, &sh);
78
79              if (x < 0) x = 0;
80              if (y < 0) y = 0;
81              if (x2 > sw) x2 = sw;
82              if (y2 > sh) y2 = sh;
83              w = x2 - x;
84              h = y2 - y;
85           }
86         cx = x + (w / 2);
87         cy = y + (h / 2);
88         evas_object_move(ext_mod->popup, cx, cy);
89      }
90 }
91
92 static void
93 _select_all(void *data, Evas_Object *obj, void *event_info)
94 {
95    if(!ext_mod) return;
96
97    ext_mod->selectall(data,obj,event_info);
98    _ctxpopup_hide(obj);
99 }
100
101 static void
102 _select(void *data, Evas_Object *obj, void *event_info)
103 {
104    if(!ext_mod) return;
105
106    ext_mod->select(data,obj,event_info);
107    _ctxpopup_hide(obj);
108 }
109
110 static void
111 _paste(void *data, Evas_Object *obj, void *event_info)
112 {
113    if(!ext_mod) return;
114
115    ext_mod->paste(data,obj,event_info);
116    _ctxpopup_hide(obj);
117 }
118
119 static void
120 _cut(void *data, Evas_Object *obj, void *event_info)
121 {
122    if(!ext_mod) return;
123
124    ext_mod->cut(data,obj,event_info);
125    _ctxpopup_hide(obj);
126    elm_object_scroll_freeze_pop(ext_mod->popup);
127 }
128
129 static void
130 _copy(void *data, Evas_Object *obj, void *event_info)
131 {
132    if(!ext_mod) return;
133
134    ext_mod->copy(data,obj,event_info);
135    _ctxpopup_hide(obj);
136    elm_object_scroll_freeze_pop(ext_mod->popup);
137 }
138
139 static void
140 _cancel(void *data, Evas_Object *obj, void *event_info)
141 {
142    if(!ext_mod) return;
143
144    ext_mod->cancel(data,obj,event_info);
145    _ctxpopup_hide(obj);
146    elm_object_scroll_freeze_pop(ext_mod->popup);
147 }
148
149 static void
150 _clipboard_menu(void *data, Evas_Object *obj, void *event_info)
151 {
152    if(!ext_mod) return;
153
154    // start for cbhm
155 #ifdef HAVE_ELEMENTARY_X
156    ecore_x_selection_secondary_set(elm_win_xwindow_get(obj), "",1);
157 #endif
158    ext_mod->cnpinit(data,obj,event_info);
159    elm_cbhm_helper_init(obj);
160    if (ext_mod->cnp_mode != ELM_CNP_MODE_MARKUP)
161      elm_cbhm_send_raw_data("show0");
162    else
163      elm_cbhm_send_raw_data("show1");
164    _ctxpopup_hide(obj);
165    // end for cbhm
166 }
167
168 static void
169 _item_clicked(void *data, Evas_Object *obj, void *event_info)
170 {
171    Elm_Entry_Context_Menu_Item *it = data;
172    Evas_Object *obj2 = it->obj;
173
174    if (it->func) it->func(it->data, obj2, NULL);
175    _ctxpopup_hide(obj);
176 }
177
178 static void
179 _ctxpopup_dismissed_cb(void *data, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
180 {
181    if (!ext_mod) return;
182
183    elm_object_scroll_freeze_pop(ext_mod->popup);
184 }
185
186 // module api funcs needed
187 EAPI int
188 elm_modapi_init(void *m)
189 {
190    return 1; // succeed always
191 }
192
193 EAPI int
194 elm_modapi_shutdown(void *m)
195 {
196    return 1; // succeed always
197 }
198
199 // module funcs for the specific module type
200 EAPI void
201 obj_hook(Evas_Object *obj)
202 {
203    _mod_hook_count++;
204    //if(_mod_hook_count > 1) return;
205
206    if(!ext_mod)
207      {
208         ext_mod = ELM_NEW(Elm_Entry_Extension_data);
209         elm_entry_extension_module_data_get(obj,ext_mod);
210      }
211 }
212
213 EAPI void
214 obj_unhook(Evas_Object *obj)
215 {
216    _mod_hook_count--;
217    if(_mod_hook_count > 0) return;
218
219    if(ext_mod)
220      {
221         free(ext_mod);
222         ext_mod = NULL;
223      }
224 }
225
226 EAPI void
227 obj_longpress(Evas_Object *obj)
228 {
229    if(!ext_mod) return;
230
231    Evas_Object *top;
232    const Eina_List *l;
233    const Elm_Entry_Context_Menu_Item *it;
234    const char *context_menu_orientation;
235    char buf[255];
236    Evas_Object* icon;
237    Elm_Object_Item *added_item = NULL;
238
239    /*update*/
240    elm_entry_extension_module_data_get(obj,ext_mod);
241    if (ext_mod->context_menu)
242      {
243 #ifdef HAVE_ELEMENTARY_X
244         int cbhm_count = -1;
245         if (elm_cbhm_helper_init(obj))
246           cbhm_count = elm_cbhm_get_count();
247 #endif
248         if (ext_mod->popup) evas_object_del(ext_mod->popup);
249         //else elm_widget_scroll_freeze_push(obj);
250         top = elm_widget_top_get(obj);
251         if(top)
252           {
253              ext_mod->popup = elm_ctxpopup_add(top);
254              elm_object_tree_unfocusable_set(ext_mod->popup, EINA_TRUE);
255              evas_object_smart_callback_add(ext_mod->popup, "dismissed", _ctxpopup_dismissed_cb, NULL);
256           }
257         /*currently below theme not used,when guideline comes a new theme can be created if required*/
258         elm_object_style_set(ext_mod->popup,"extended/entry");
259         context_menu_orientation = edje_object_data_get
260            (ext_mod->ent, "context_menu_orientation");
261         if ((context_menu_orientation) &&
262             (!strcmp(context_menu_orientation, "horizontal")))
263           elm_ctxpopup_horizontal_set(ext_mod->popup, EINA_TRUE);
264
265         elm_widget_sub_object_add(obj, ext_mod->popup);
266         if (!ext_mod->selmode)
267           {
268              if (!ext_mod->password)
269                {
270                   if (!elm_entry_is_empty(obj))
271                     {
272                        added_item = elm_ctxpopup_item_append(ext_mod->popup, "Select", NULL, _select, obj );
273                        added_item = elm_ctxpopup_item_append(ext_mod->popup, "Select All", NULL, _select_all, obj );
274                     }
275                }
276
277 #ifdef HAVE_ELEMENTARY_X
278              if (cbhm_count)
279 #else
280              if (1) // need way to detect if someone has a selection
281 #endif
282                {
283                   if (ext_mod->editable)
284                     added_item = elm_ctxpopup_item_append(ext_mod->popup, "Paste", NULL, _paste, obj );
285                }
286              //elm_ctxpopup_item_append(wd->ctxpopup, NULL, "Selectall",_select_all, obj );
287              // start for cbhm
288 #ifdef HAVE_ELEMENTARY_X
289              if ((!ext_mod->password) && (ext_mod->editable) && (cbhm_count))
290 #else
291              if ((!ext_mod->password) && (ext_mod->editable))
292 #endif
293                {
294                   icon = elm_icon_add(ext_mod->popup);
295                   snprintf(buf, sizeof(buf), "%s/images/copypaste_icon_clipboard.png", PACKAGE_DATA_DIR);
296                   elm_icon_file_set(icon, buf, NULL);
297                   added_item = elm_ctxpopup_item_append(ext_mod->popup, NULL, icon, _clipboard_menu, obj);
298                   //elm_ctxpopup_item_append(ext_mod->popup, "More", NULL, _clipboard_menu, obj );
299                }
300              // end for cbhm
301           }
302         else
303           {
304              if (!ext_mod->password)
305                {
306                   if (ext_mod->have_selection)
307                     {
308                        added_item = elm_ctxpopup_item_append(ext_mod->popup, "Copy", NULL, _copy, obj );
309                        if (ext_mod->editable)
310                          added_item = elm_ctxpopup_item_append(ext_mod->popup, "Cut", NULL, _cut, obj );
311 #ifdef HAVE_ELEMENTARY_X
312                        if (ext_mod->editable && cbhm_count)
313 #else
314                        if (ext_mod->editable)
315 #endif
316                          added_item = elm_ctxpopup_item_append(ext_mod->popup, "Paste", NULL, _paste, obj );
317                     }
318                   else
319                     {
320                        _cancel(obj,ext_mod->popup,NULL);
321                        if (!elm_entry_is_empty(obj))
322                          {
323                             added_item = elm_ctxpopup_item_append(ext_mod->popup, "Select", NULL, _select, obj );
324                             added_item = elm_ctxpopup_item_append(ext_mod->popup, "Select All", NULL, _select_all, obj );
325                          }
326 #ifdef HAVE_ELEMENTARY_X
327                        if (cbhm_count)
328 #else
329                        if (1) // need way to detect if someone has a selection
330 #endif
331                          {
332                             if (ext_mod->editable)
333                               added_item = elm_ctxpopup_item_append(ext_mod->popup, "Paste", NULL, _paste, obj );
334                          }
335                     }
336                   // start for cbhm
337 #ifdef HAVE_ELEMENTARY_X
338                   if (ext_mod->editable && cbhm_count)
339 #else
340                   if (ext_mod->editable)
341 #endif
342                     {
343                        icon = elm_icon_add(ext_mod->popup);
344                        snprintf(buf, sizeof(buf), "%s/images/copypaste_icon_clipboard.png", PACKAGE_DATA_DIR);
345                        elm_icon_file_set(icon, buf, NULL);
346                        added_item = elm_ctxpopup_item_append(ext_mod->popup, NULL, icon, _clipboard_menu, obj);
347                        //elm_ctxpopup_item_append(ext_mod->popup, "More", NULL, _clipboard_menu, obj );
348                     }
349                   // end for cbhm
350                }
351           }
352         EINA_LIST_FOREACH(ext_mod->items, l, it)
353           {
354              added_item = elm_ctxpopup_item_append(ext_mod->popup, it->label, NULL, _item_clicked, it );
355           }
356         if (ext_mod->popup && added_item)
357           {
358              elm_object_scroll_freeze_push(ext_mod->popup);
359              _ctxpopup_position(obj);
360              evas_object_show(ext_mod->popup);
361              ext_mod->caller = obj;
362           }
363         else
364           ext_mod->caller = NULL;
365      }
366 }
367
368 EAPI void
369 obj_mouseup(Evas_Object *obj)
370 {
371    if (!obj || !ext_mod)
372      return;
373 }
374
375
376 EAPI void
377 obj_hidemenu(Evas_Object *obj)
378 {
379    if (!obj || !ext_mod || obj != ext_mod->caller)
380      return;
381
382    _ctxpopup_hide(ext_mod->popup);
383    // if (ext_mod->popup) evas_object_del(ext_mod->popup);
384 }