Merge with EFL svn repo
[framework/uifw/elementary.git] / src / modules / ctxpopup_copypasteUI / copypaste.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 typedef struct _Mod_Api Mod_Api;
5 typedef struct _Widget_Data Widget_Data;
6 typedef struct _Elm_Entry_Context_Menu_Item Elm_Entry_Context_Menu_Item;
7 struct _Widget_Data
8 {
9    Evas_Object *ent;
10    Evas_Object *popup;/*copy paste UI - elm_popup*/
11    Evas_Object *ctxpopup;/*copy paste UI - elm_ctxpopup*/
12    Evas_Object *hoversel;
13    Ecore_Job *deferred_recalc_job;
14    Ecore_Event_Handler *sel_notify_handler;
15    Ecore_Event_Handler *sel_clear_handler;
16    Ecore_Timer *longpress_timer;
17    const char *cut_sel;
18    const char *text;
19    Evas_Coord lastw;
20    Evas_Coord downx, downy;
21    Evas_Coord cx, cy, cw, ch;
22    Eina_List *items;
23    Eina_List *item_providers;
24    Mod_Api *api; // module api if supplied
25    int max_no_of_bytes;
26    Eina_Bool changed : 1;
27    Eina_Bool linewrap : 1;
28    Eina_Bool char_linewrap : 1;
29    Eina_Bool single_line : 1;
30    Eina_Bool password : 1;
31    Eina_Bool show_last_character : 1;
32    Eina_Bool editable : 1;
33    Eina_Bool selection_asked : 1;
34    Eina_Bool have_selection : 1;
35    Eina_Bool selmode : 1;
36    Eina_Bool deferred_cur : 1;
37    Eina_Bool disabled : 1;
38    Eina_Bool context_menu : 1;
39    Eina_Bool autoreturnkey : 1;
40 };
41
42 struct _Elm_Entry_Context_Menu_Item
43 {
44    Evas_Object *obj;
45    const char *label;
46    const char *icon_file;
47    const char *icon_group;
48    Elm_Icon_Type icon_type;
49    Evas_Smart_Cb func;
50    void *data;
51 };
52
53
54 static void
55 _store_selection(Evas_Object *obj)
56 {
57    Widget_Data *wd = elm_widget_data_get(obj);
58    const char *sel = edje_object_part_text_selection_get(wd->ent, "elm.text");
59    if (!wd) return;
60    if (wd->cut_sel) eina_stringshare_del(wd->cut_sel);
61    wd->cut_sel = eina_stringshare_add(sel);
62 }
63
64 static void
65 _ctxpopup_position(Evas_Object *obj)
66 {
67    Widget_Data *wd = elm_widget_data_get(obj);
68    Evas_Coord cx, cy, cw, ch, x, y, mw, mh;
69    if (!wd) return;
70    evas_object_geometry_get(wd->ent, &x, &y, NULL, NULL);
71    edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
72                                              &cx, &cy, &cw, &ch);
73    evas_object_size_hint_min_get(wd->ctxpopup, &mw, &mh);
74    if (cw < mw)
75      {
76         cx += (cw - mw) / 2;
77         cw = mw;
78      }
79    if (ch < mh)
80      {
81         cy += (ch - mh) / 2;
82         ch = mh;
83      }
84    evas_object_move(wd->ctxpopup, x + cx, y + cy);
85    evas_object_resize(wd->ctxpopup, cw, ch);
86 }
87
88 static void
89 _select(void *data, Evas_Object *obj, void *event_info)
90 {
91    Widget_Data *wd = elm_widget_data_get(data);
92    wd->selmode = EINA_TRUE;
93    edje_object_part_text_select_none(wd->ent, "elm.text");
94    edje_object_part_text_select_allow_set(wd->ent, "elm.text", 1);
95    if (!wd->password)
96       edje_object_signal_emit(wd->ent, "elm,state,select,on", "elm");
97    elm_ctxpopup_scroller_disabled_set(obj, EINA_FALSE);
98    elm_widget_scroll_hold_push(data);
99    evas_object_hide(obj);
100 }
101
102 static void
103 _paste(void *data, Evas_Object *obj, void *event_info)
104 {
105    Widget_Data *wd = elm_widget_data_get(data);
106     if (!wd) return;
107    evas_object_smart_callback_call(data, "selection,paste", NULL);
108    if (wd->sel_notify_handler)
109      {
110 #ifdef HAVE_ELEMENTARY_X
111         Evas_Object *top;
112
113         top = elm_widget_top_get(data);
114         if ((top) && (elm_win_xwindow_get(top)))
115           {
116              ecore_x_selection_primary_request
117                (elm_win_xwindow_get(top),
118                 ECORE_X_SELECTION_TARGET_UTF8_STRING);
119              wd->selection_asked = EINA_TRUE;
120           }
121 #endif
122      }  
123    elm_ctxpopup_scroller_disabled_set(obj, EINA_FALSE);
124    evas_object_hide(obj);
125 }
126
127 static void
128 _cut(void *data, Evas_Object *obj, void *event_info)
129 {
130    Widget_Data *wd = elm_widget_data_get(data);
131    wd->selmode = EINA_FALSE;
132    edje_object_part_text_select_allow_set(wd->ent, "elm.text", 0);
133    edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
134    elm_ctxpopup_scroller_disabled_set(obj, EINA_FALSE);
135    elm_widget_scroll_hold_pop(data);
136    _store_selection(data);
137    edje_object_part_text_insert(wd->ent, "elm.text", "");
138    edje_object_part_text_select_none(wd->ent, "elm.text");
139    evas_object_hide(obj);
140 }
141
142 static void
143 _copy(void *data, Evas_Object *obj, void *event_info)
144 {
145    Widget_Data *wd = elm_widget_data_get(data);
146    if (!wd) return;
147    wd->selmode = EINA_FALSE;
148    edje_object_part_text_select_allow_set(wd->ent, "elm.text", 0);
149    edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
150    elm_ctxpopup_scroller_disabled_set(obj, EINA_FALSE);
151    elm_widget_scroll_hold_pop(data);
152    _store_selection(data);
153    edje_object_part_text_select_none(wd->ent, "elm.text");
154    evas_object_hide(obj);
155 }
156
157 static void
158 _cancel(void *data, Evas_Object *obj, void *event_info)
159 {
160    Widget_Data *wd = elm_widget_data_get(data);
161    if (!wd) return;
162    wd->selmode = EINA_FALSE;
163    edje_object_part_text_select_allow_set(wd->ent, "elm.text", 0);
164    edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
165    elm_ctxpopup_scroller_disabled_set(obj, EINA_FALSE);
166    elm_widget_scroll_hold_pop(data);
167    edje_object_part_text_select_none(wd->ent, "elm.text");
168    evas_object_hide(obj);
169 }
170
171 static void
172 _item_clicked(void *data, Evas_Object *obj, void *event_info)
173 {
174    Elm_Entry_Context_Menu_Item *it = data;
175    Evas_Object *obj2 = it->obj;
176
177    if (it->func) it->func(it->data, obj2, NULL);
178 }
179
180 // module api funcs needed
181 EAPI int
182 elm_modapi_init(void *m)
183 {
184    return 1; // succeed always
185 }
186
187 EAPI int
188 elm_modapi_shutdown(void *m)
189 {
190    return 1; // succeed always
191 }
192
193 // module fucns for the specific module type
194 EAPI void
195 obj_hook(Evas_Object *obj)
196 {
197   
198 }
199
200 EAPI void
201 obj_unhook(Evas_Object *obj)
202 {
203    
204 }
205
206 EAPI void
207 obj_longpress(Evas_Object *obj)
208 {
209                         
210                         Widget_Data *wd = elm_widget_data_get(obj);
211                         Evas_Object *top;
212                         const Eina_List *l;
213                         const Elm_Entry_Context_Menu_Item *it;
214                         const char *context_menu_orientation;
215
216                         if (wd->ctxpopup) evas_object_del(wd->ctxpopup);
217                        else elm_widget_scroll_freeze_push(obj);
218                         top = elm_widget_top_get(obj);
219                         if(top)
220                                 wd->ctxpopup = elm_ctxpopup_add(top);
221                         elm_object_style_set(wd->ctxpopup,"entry");
222                         elm_ctxpopup_scroller_disabled_set(wd->ctxpopup, EINA_TRUE);
223                         context_menu_orientation = edje_object_data_get
224                         (wd->ent, "context_menu_orientation");
225                         if ((context_menu_orientation) &&
226                         (!strcmp(context_menu_orientation, "horizontal")))
227                                 elm_ctxpopup_horizontal_set(wd->ctxpopup, EINA_TRUE);
228
229                         elm_widget_sub_object_add(obj, wd->ctxpopup);
230                         if (!wd->selmode)
231                                 {       
232                                         if (!wd->password)
233                                                 elm_ctxpopup_label_add(wd->ctxpopup, "Select",_select, obj );
234                                         if (1) // need way to detect if someone has a selection
235                                                 {
236                                                         if (wd->editable)
237                                                                 elm_ctxpopup_label_add(wd->ctxpopup, "Paste",   _paste, obj );
238                                                 }
239                         //              elm_ctxpopup_label_add(wd->ctxpopup, "Selectall",_select_all, obj );
240                                 }
241                         else
242                                 {
243                                           if (!wd->password)
244                                                 {
245                                                         if (wd->have_selection)
246                                                                 {
247                                                                         elm_ctxpopup_label_add(wd->ctxpopup, "Copy",_copy, obj );
248                                                                         if (wd->editable)
249                                                                                 elm_ctxpopup_label_add(wd->ctxpopup, "Cut",_cut, obj );                                                 
250                                                                 }
251                                                         else
252                                                                 {
253                                                                         _cancel(obj,wd->ctxpopup,NULL);                                                 
254                                                                         if (1) // need way to detect if someone has a selection
255                                                                                 {
256                                                                                         if (wd->editable)
257                                                                                                 elm_ctxpopup_label_add(wd->ctxpopup, "Paste",   _paste, obj );
258                                                                                 }
259                                                                         elm_ctxpopup_label_add(wd->ctxpopup, "Select",_select, obj );
260                                                                 }
261                                                 }
262                                 }
263                                 EINA_LIST_FOREACH(wd->items, l, it)
264                                 {
265                                         elm_ctxpopup_label_add(wd->ctxpopup, it->label,_item_clicked, it );
266                                 }
267                         if (wd->ctxpopup)
268                                 {
269                                         _ctxpopup_position(obj);
270                                         evas_object_show(wd->ctxpopup);           
271                                 }
272                         wd->longpress_timer = NULL;
273         }
274
275 EAPI void
276 obj_mouseup(Evas_Object *obj)
277 {
278         Widget_Data *wd = elm_widget_data_get(obj);
279    if (wd->longpress_timer)
280      {          
281                 ecore_timer_del(wd->longpress_timer);
282                 wd->longpress_timer = NULL;
283                 if (wd->have_selection )
284                         {                               
285                                 _cancel(obj,wd->ctxpopup,NULL);
286                         }
287      }     
288    else
289    {
290                 if (wd->have_selection )
291                         {
292                                 obj_longpress( obj );
293                         }
294    }
295 }
296
297