1 #include "e.h"
2 
3 /*
4  * TODO: gadcon client ordering on drop
5  */
6 
7 #define E_LAYOUT_ITEM_DRAG_RESIST_LEVEL 10
8 static void                     _e_gadcon_event_populate(E_Gadcon *gc);
9 static Eina_Bool                _e_gadcon_client_populate(E_Gadcon *gc, const E_Gadcon_Client_Class *cc, E_Config_Gadcon_Client *cf_gcc);
10 static void                     _e_gadcon_client_unpopulate(E_Gadcon_Client *gcc);
11 static void                     _e_gadcon_free(E_Gadcon *gc);
12 static void                     _e_gadcon_client_free(E_Gadcon_Client *gcc);
13 
14 static void                     _e_gadcon_moveresize_handle(E_Gadcon_Client *gcc);
15 static Eina_Bool                _e_gadcon_cb_client_scroll_timer(void *data);
16 static void                     _e_gadcon_client_scroll_state_update(E_Gadcon_Client *gcc);
17 static Eina_Bool                _e_gadcon_cb_client_scroll_animator(void *data);
18 static void                     _e_gadcon_cb_client_frame_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
19 static void                     _e_gadcon_cb_client_frame_moveresize(void *data, Evas *e, Evas_Object *obj, void *event_info);
20 static void                     _e_gadcon_client_save(E_Gadcon_Client *gcc);
21 static void                     _e_gadcon_client_drag_begin(E_Gadcon_Client *gcc, int x, int y);
22 static void                     _e_gadcon_client_inject(E_Gadcon *gc, E_Gadcon_Client *gcc, int x, int y);
23 
24 static void                     _e_gadcon_cb_min_size_request(void *data, Evas_Object *obj, void *event_info);
25 static void                     _e_gadcon_cb_size_request(void *data, Evas_Object *obj, void *event_info);
26 static void                     _e_gadcon_cb_hide(void *data, Evas *evas, Evas_Object *obj, void *event_info);
27 static void                     _e_gadcon_cb_show(void *data, Evas *evas, Evas_Object *obj, void *event_info);
28 static void                     _e_gadcon_cb_moveresize(void *data, Evas *evas, Evas_Object *obj, void *event_info);
29 static void                     _e_gadcon_parent_resize_cb(E_Gadcon *gc, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED);
30 static void                     _e_gadcon_cb_client_mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
31 static void                     _e_gadcon_cb_client_mouse_in(void *data, Evas *evas, Evas_Object *obj, void *event_info);
32 static void                     _e_gadcon_cb_client_mouse_out(void *data, Evas *evas, Evas_Object *obj, void *event_info);
33 static void                     _e_gadcon_cb_client_move(void *data, Evas *evas, Evas_Object *obj, void *event_info);
34 static void                     _e_gadcon_cb_client_resize(void *data, Evas *evas, Evas_Object *obj, void *event_info);
35 
36 static void                     _e_gadcon_client_move_start(E_Gadcon_Client *gcc);
37 static void                     _e_gadcon_client_move_stop(E_Gadcon_Client *gcc);
38 static void                     _e_gadcon_client_move_go(E_Gadcon_Client *gcc);
39 
40 static void                     _e_gadcon_cb_signal_move_start(void *data, Evas_Object *obj, const char *emission, const char *source);
41 static void                     _e_gadcon_cb_signal_move_stop(void *data, Evas_Object *obj, const char *emission, const char *source);
42 static void                     _e_gadcon_cb_signal_move_go(void *data, Evas_Object *obj, const char *emission, const char *source);
43 static void                     _e_gadcon_cb_signal_resize_left_start(void *data, Evas_Object *obj, const char *emission, const char *source);
44 static void                     _e_gadcon_cb_signal_resize_left_stop(void *data, Evas_Object *obj, const char *emission, const char *source);
45 static void                     _e_gadcon_cb_signal_resize_left_go(void *data, Evas_Object *obj, const char *emission, const char *source);
46 static void                     _e_gadcon_cb_signal_resize_right_start(void *data, Evas_Object *obj, const char *emission, const char *source);
47 static void                     _e_gadcon_cb_signal_resize_right_stop(void *data, Evas_Object *obj, const char *emission, const char *source);
48 static void                     _e_gadcon_cb_signal_resize_right_go(void *data, Evas_Object *obj, const char *emission, const char *source);
49 static void                     _e_gadcon_cb_dnd_enter(void *data, const char *type, void *event);
50 static void                     _e_gadcon_cb_dnd_move(void *data, const char *type, void *event);
51 static void                     _e_gadcon_cb_dnd_leave(void *data, const char *type, void *event);
52 static void                     _e_gadcon_cb_dnd_drop(void *data, const char *type, void *event);
53 
54 static int                      _e_gadcon_client_class_feature_check(const E_Gadcon_Client_Class *cc, const char *name, void *feature);
55 static void                     _e_gadcon_client_cb_menu_post(void *data, E_Menu *m);
56 static void                     _e_gadcon_client_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
57 static void                     _e_gadcon_client_cb_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
58 static void                     _e_gadcon_client_cb_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
59 static void                     _e_gadcon_client_cb_menu_style_plain(void *data, E_Menu *m, E_Menu_Item *mi);
60 static void                     _e_gadcon_client_cb_menu_style_inset(void *data, E_Menu *m, E_Menu_Item *mi);
61 static void                     _e_gadcon_client_cb_menu_autoscroll(void *data, E_Menu *m, E_Menu_Item *mi);
62 /*static void _e_gadcon_client_cb_menu_resizable(void *data, E_Menu *m, E_Menu_Item *mi);*/
63 static void                     _e_gadcon_client_cb_menu_edit(void *data, E_Menu *m, E_Menu_Item *mi);
64 static void                     _e_gadcon_client_cb_menu_remove(void *data, E_Menu *m, E_Menu_Item *mi);
65 static void                     _e_gadcon_client_cb_menu_pre(void *data, E_Menu *m, E_Menu_Item *mi);
66 static void                     _e_gadcon_client_delfn(void *d, void *o);
67 static void                     _e_gadcon_client_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
68 static void                     _e_gadcon_client_event_free(void *d, void *e);
69 static Evas_Object             *e_gadcon_layout_add(Evas *evas);
70 static void                     e_gadcon_layout_orientation_set(Evas_Object *obj, int horizontal);
71 static int                      e_gadcon_layout_orientation_get(Evas_Object *obj);
72 static void                     e_gadcon_layout_freeze(Evas_Object *obj);
73 static void                     e_gadcon_layout_thaw(Evas_Object *obj);
74 static void                     e_gadcon_layout_min_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
75 static void                     e_gadcon_layout_asked_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
76 static int                      e_gadcon_layout_pack(Evas_Object *obj, Evas_Object *child);
77 static void                     e_gadcon_layout_pack_size_set(Evas_Object *obj, int size);
78 static void                     e_gadcon_layout_pack_request_set(Evas_Object *obj, int pos, int size);
79 static void                     e_gadcon_layout_pack_options_set(Evas_Object *obj, E_Gadcon_Client *gcc);
80 static void                     e_gadcon_layout_pack_min_size_set(Evas_Object *obj, int w, int h);
81 static void                     e_gadcon_layout_pack_aspect_set(Evas_Object *obj, int w, int h);
82 static void                     e_gadcon_layout_pack_aspect_pad_set(Evas_Object *obj, int w, int h);
83 static void                     e_gadcon_layout_unpack(Evas_Object *obj);
84 static void                     _e_gadcon_provider_populate_request(E_Gadcon *gc, const E_Gadcon_Client_Class *cc);
85 static void                     _e_gadcon_provider_populate_unrequest(const E_Gadcon_Client_Class *cc);
86 static void                     _e_gadcon_provider_populate_job(void *data);
87 static void                     _e_gadcon_event_populate_free(void *data EINA_UNUSED, void *event);
88 static void                     _e_gadcon_custom_populate_job(void *data);
89 
90 static int                      _e_gadcon_location_change(E_Gadcon_Client *gcc, E_Gadcon_Location *src, E_Gadcon_Location *dst);
91 
92 typedef struct _E_Smart_Data            E_Smart_Data;
93 typedef struct _E_Layout_Item_Container E_Layout_Item_Container;
94 
95 static void                     _e_gadcon_client_current_position_sync(E_Gadcon_Client *gcc);
96 static void                     _e_gadcon_layout_smart_sync_clients(E_Gadcon *gc);
97 static void                     _e_gadcon_layout_smart_gadcon_position_shrinked_mode(E_Smart_Data *sd);
98 static void                     _e_gadcon_layout_smart_gadcons_asked_position_set(E_Smart_Data *sd);
99 static Eina_List               *_e_gadcon_layout_smart_gadcons_wrap(E_Smart_Data *sd);
100 static void                     _e_gadcon_layout_smart_gadcons_position(E_Smart_Data *sd, Eina_List **list);
101 static void                     _e_gadcon_layout_smart_gadcons_position_static(E_Smart_Data *sd, Eina_List **list);
102 static E_Layout_Item_Container *_e_gadcon_layout_smart_containers_position_adjust(E_Smart_Data *sd, E_Layout_Item_Container *lc, E_Layout_Item_Container *lc2);
103 static void                     _e_gadcon_layout_smart_position_items_inside_container(E_Smart_Data *sd, E_Layout_Item_Container *lc);
104 static void                     _e_gadcon_layout_smart_containers_merge(E_Smart_Data *sd, E_Layout_Item_Container *lc, E_Layout_Item_Container *lc2);
105 static void                     _e_gadcon_layout_smart_restore_gadcons_position_before_move(E_Smart_Data *sd, E_Layout_Item_Container **lc_moving, E_Layout_Item_Container *lc_back, Eina_List **con_list);
106 
107 typedef enum _E_Gadcon_Layout_Item_State
108 {
109    E_LAYOUT_ITEM_STATE_NONE,
110    E_LAYOUT_ITEM_STATE_POS_INC,
111    E_LAYOUT_ITEM_STATE_POS_DEC,
112    E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC,
113    E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC,
114    E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC,
115    E_LAYOUT_ITEM_STATE_SIZE_MAX_END_DEC,
116 } E_Gadcon_Layout_Item_State;
117 
118 typedef enum _E_Gadcon_Layout_Item_Flags
119 {
120    E_GADCON_LAYOUT_ITEM_LOCK_NONE = 0x00000000,
121    E_GADCON_LAYOUT_ITEM_LOCK_POSITION = 0x00000001,
122    E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE = 0x00000002
123 } E_Gadcon_Layout_Item_Flags;
124 
125 typedef enum _E_Layout_Item_Container_State
126 {
127    E_LAYOUT_ITEM_CONTAINER_STATE_NONE,
128    E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC,
129    E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC,
130    E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_INC,
131    E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_DEC,
132    E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_INC,
133    E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_DEC,
134    E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED
135 } E_Layout_Item_Container_State;
136 
137 struct _E_Layout_Item_Container
138 {
139    int                           pos, size, prev_pos, prev_size;
140 
141    struct
142    {
143       int min_seq, max_seq;
144    } state_info;
145 
146    E_Smart_Data                 *sd;
147    Eina_List                    *items;
148 
149    E_Layout_Item_Container_State state;
150 };
151 
152 #define LC_FREE(__lc)             \
153   if (__lc->items)                \
154     eina_list_free(__lc->items);  \
155   E_FREE(__lc)
156 
157 #define E_LAYOUT_ITEM_CONTAINER_STATE_SET(__con_state, __bi_state) \
158   if (__bi_state == E_LAYOUT_ITEM_STATE_NONE)                      \
159     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;              \
160   else if (__bi_state == E_LAYOUT_ITEM_STATE_POS_INC)              \
161     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC;           \
162   else if (__bi_state == E_LAYOUT_ITEM_STATE_POS_DEC)              \
163     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC;           \
164   else if (__bi_state == E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC)     \
165     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_INC;  \
166   else if (__bi_state == E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC)     \
167     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_DEC;  \
168   else if (__bi_state == E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC)     \
169     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_INC;  \
170   else if (__bi_state == E_LAYOUT_ITEM_STATE_SIZE_MAX_END_DEC)     \
171     __con_state = E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_DEC
172 
173 #define LC_OVERLAP(__lc, __lc2)                                                        \
174   ((((__lc2)->pos >= (__lc)->pos) && ((__lc2)->pos < ((__lc)->pos + (__lc)->size))) || \
175    (((__lc)->pos >= (__lc2)->pos) && ((__lc)->pos < ((__lc2)->pos + (__lc2)->size))))
176 
177 #define E_LAYOUT_ITEM_CONTAINER_SIZE_CHANGE_BY(__lc, __bi, __increase) \
178   {                                                                    \
179      if (__increase)                                                   \
180        __lc->size += __bi->w;                                          \
181      else                                                              \
182        __lc->size -= __bi->w;                                          \
183   }
184 
185 /********************/
186 E_API int E_EVENT_GADCON_CLIENT_CLASS_ADD = -1;
187 E_API int E_EVENT_GADCON_CLIENT_CLASS_DEL = -1;
188 E_API int E_EVENT_GADCON_CLIENT_ADD = -1;
189 E_API int E_EVENT_GADCON_CLIENT_DEL = -1;
190 E_API int E_EVENT_GADCON_POPULATE = -1;
191 
192 static Eina_Hash *providers = NULL;
193 static Eina_List *providers_list = NULL;
194 static Eina_List *gadcons = NULL;
195 static Eina_List *dummies = NULL;
196 static Ecore_Job *populate_job = NULL;
197 static Eina_List *custom_populate_requests = NULL;
198 static Ecore_Job *custom_populate_job = NULL;
199 static Eina_List *gadcon_locations = NULL;
200 static Ecore_Event_Handler *_module_init_end_handler = NULL;
201 static Eina_Bool _modules_loaded = EINA_FALSE;
202 
203 static inline void
_eina_list_free(Eina_List * l)204 _eina_list_free(Eina_List *l)
205 {
206    eina_list_free(l);
207 }
208 
209 static int
_e_gadcon_provider_list_sort_cb(E_Gadcon_Client_Class * a,E_Gadcon_Client_Class * b)210 _e_gadcon_provider_list_sort_cb(E_Gadcon_Client_Class *a, E_Gadcon_Client_Class *b)
211 {
212    return strcasecmp(a->name, b->name);
213 }
214 
215 static Eina_Bool
_module_init_end_cb(void * d EINA_UNUSED,int type EINA_UNUSED,void * ev EINA_UNUSED)216 _module_init_end_cb(void *d EINA_UNUSED, int type EINA_UNUSED, void *ev EINA_UNUSED)
217 {
218    _modules_loaded = EINA_TRUE;
219    return ECORE_CALLBACK_RENEW;
220 }
221 
222 /* externally accessible functions */
223 EINTERN int
e_gadcon_init(void)224 e_gadcon_init(void)
225 {
226    E_EVENT_GADCON_CLIENT_CLASS_ADD = ecore_event_type_new();
227    E_EVENT_GADCON_CLIENT_CLASS_DEL = ecore_event_type_new();
228    E_EVENT_GADCON_CLIENT_ADD = ecore_event_type_new();
229    E_EVENT_GADCON_CLIENT_DEL = ecore_event_type_new();
230    E_EVENT_GADCON_POPULATE = ecore_event_type_new();
231    _module_init_end_handler = ecore_event_handler_add(E_EVENT_MODULE_INIT_END, _module_init_end_cb, NULL);
232    return 1;
233 }
234 
235 EINTERN int
e_gadcon_shutdown(void)236 e_gadcon_shutdown(void)
237 {
238    if (populate_job)
239      {
240         ecore_job_del(populate_job);
241         populate_job = NULL;
242      }
243    custom_populate_requests = eina_list_free(custom_populate_requests);
244    if (custom_populate_job)
245      {
246         ecore_job_del(custom_populate_job);
247         custom_populate_job = NULL;
248      }
249    _modules_loaded = EINA_FALSE;
250    if (_module_init_end_handler)
251      ecore_event_handler_del(_module_init_end_handler);
252    _module_init_end_handler = NULL;
253    E_LIST_FOREACH(gadcons, e_gadcon_unpopulate);
254 
255    return 1;
256 }
257 
258 /**
259  * Registers a new gadget class in e
260  *
261  * @param cc version of gadcon, name and callbacks to use
262  * for handling creation and destroying a gadget
263  */
264 E_API void
e_gadcon_provider_register(const E_Gadcon_Client_Class * cc)265 e_gadcon_provider_register(const E_Gadcon_Client_Class *cc)
266 {
267    E_Gadcon *gc;
268    Eina_List *l, *ll, *lll;
269    E_Config_Gadcon_Client *cf_gcc;
270 
271    EINA_SAFETY_ON_NULL_RETURN(cc->name);
272    if (!providers) providers = eina_hash_string_superfast_new(NULL);
273    eina_hash_direct_add(providers, cc->name, cc);
274    EINA_LIST_FOREACH(gadcons, l, gc)
275      {
276         e_gadcon_layout_freeze(gc->o_container);
277         if (gc->awaiting_classes)
278           {
279              ll = eina_hash_find(gc->awaiting_classes, cc->name);
280              EINA_LIST_FOREACH(ll, lll, cf_gcc)
281                _e_gadcon_client_populate(gc, cc, cf_gcc);
282           }
283         e_gadcon_layout_thaw(gc->o_container);
284      }
285    providers_list = eina_list_sorted_insert(providers_list, (Eina_Compare_Cb)_e_gadcon_provider_list_sort_cb, cc);
286    {
287       E_Event_Gadcon_Client_Class_Add *ev;
288       ev = E_NEW(E_Event_Gadcon_Client_Class_Add, 1);
289       ev->cc = cc;
290       ecore_event_add(E_EVENT_GADCON_CLIENT_CLASS_ADD, ev, NULL, NULL);
291    }
292 }
293 
294 /**
295  * unregisters a gadget class in e
296  *
297  * @param cc the gadget class that was used to register the gadget
298  */
299 E_API void
e_gadcon_provider_unregister(const E_Gadcon_Client_Class * cc)300 e_gadcon_provider_unregister(const E_Gadcon_Client_Class *cc)
301 {
302    Eina_List *l, *ll, *dlist = NULL;
303    E_Gadcon *gc;
304    E_Gadcon_Client *gcc;
305 
306    _e_gadcon_provider_populate_unrequest(cc);
307 
308    EINA_LIST_FOREACH(gadcons, l, gc)
309      {
310         EINA_LIST_FOREACH(gc->clients, ll, gcc)
311           {
312              if (gcc->client_class == cc)
313                dlist = eina_list_append(dlist, gcc);
314           }
315         gc->populated_classes = eina_list_remove(gc->populated_classes, cc);
316      }
317    EINA_LIST_FREE(dlist, gcc)
318      {
319         e_gadcon_client_queue(gcc->gadcon, gcc->cf);
320         gcc->hidden = 0;
321         e_gadcon_client_hide(gcc);
322         e_object_del(E_OBJECT(gcc));
323      }
324 
325    eina_hash_del(providers, cc->name, cc);
326    providers_list = eina_list_remove(providers_list, cc);
327    {
328       E_Event_Gadcon_Client_Class_Add *ev;
329       ev = E_NEW(E_Event_Gadcon_Client_Class_Add, 1);
330       ev->cc = cc;
331       ecore_event_add(E_EVENT_GADCON_CLIENT_CLASS_DEL, ev, NULL, NULL);
332    }
333 }
334 
335 E_API void
e_gadcon_client_queue(E_Gadcon * gc,E_Config_Gadcon_Client * cf_gcc)336 e_gadcon_client_queue(E_Gadcon *gc, E_Config_Gadcon_Client *cf_gcc)
337 {
338    Eina_List *l;
339    if (!gc->awaiting_classes)
340      gc->awaiting_classes = eina_hash_string_superfast_new((Eina_Free_Cb)_eina_list_free);
341    l = eina_hash_find(gc->awaiting_classes, cf_gcc->name);
342    if (eina_list_data_find(l, cf_gcc)) return;
343    l = eina_list_append(l, cf_gcc);
344    eina_hash_set(gc->awaiting_classes, cf_gcc->name, l);
345 }
346 
347 E_API Eina_List *
e_gadcon_provider_list(void)348 e_gadcon_provider_list(void)
349 {
350    return providers_list;
351 }
352 
353 E_API void
e_gadcon_custom_new(E_Gadcon * gc)354 e_gadcon_custom_new(E_Gadcon *gc)
355 {
356    E_OBJECT_CHECK(gc);
357    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
358 
359    gadcons = eina_list_append(gadcons, gc);
360 
361    if (!custom_populate_job)
362      {
363         custom_populate_job =
364           ecore_job_add(_e_gadcon_custom_populate_job, NULL);
365      }
366    if (!eina_list_data_find(custom_populate_requests, gc))
367      custom_populate_requests = eina_list_append(custom_populate_requests, gc);
368    gc->custom = EINA_TRUE;
369 }
370 
371 E_API void
e_gadcon_custom_del(E_Gadcon * gc)372 e_gadcon_custom_del(E_Gadcon *gc)
373 {
374    E_OBJECT_CHECK(gc);
375    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
376 
377    if (eina_list_data_find(custom_populate_requests, gc))
378      custom_populate_requests = eina_list_remove(custom_populate_requests, gc);
379 
380    gadcons = eina_list_remove(gadcons, gc);
381 }
382 
383 E_API void
e_gadcon_custom_populate_request(E_Gadcon * gc)384 e_gadcon_custom_populate_request(E_Gadcon *gc)
385 {
386    E_OBJECT_CHECK(gc);
387    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
388 
389    if (!gc->custom) return;
390    if (!custom_populate_job)
391      {
392         custom_populate_job =
393           ecore_job_add(_e_gadcon_custom_populate_job, NULL);
394      }
395    if (!eina_list_data_find(custom_populate_requests, gc))
396      custom_populate_requests = eina_list_append(custom_populate_requests, gc);
397 }
398 
399 E_API E_Gadcon *
e_gadcon_dummy_new(int id)400 e_gadcon_dummy_new(int id)
401 {
402    E_Gadcon *gc;
403 
404    gc = E_OBJECT_ALLOC(E_Gadcon, E_GADCON_DUMMY_TYPE, _e_gadcon_free);
405    if (!gc) return NULL;
406 
407    gc->id = id;
408    gc->layout_policy = E_GADCON_LAYOUT_POLICY_PANEL;
409    gc->location = NULL;
410    gc->dummy = 1;
411 
412    gc->orient = E_GADCON_ORIENT_HORIZ;
413    dummies = eina_list_append(dummies, gc);
414    return gc;
415 }
416 
417 E_API void
e_gadcon_config_del(E_Gadcon * gc)418 e_gadcon_config_del(E_Gadcon *gc)
419 {
420    E_OBJECT_CHECK(gc);
421    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
422    gc->cfg_delete = 1;
423 }
424 
425 E_API void
e_gadcon_drop_handler_add(E_Gadcon * gc,E_Gadcon_DND_Cb enter,E_Gadcon_DND_Cb leave,E_Gadcon_DND_Cb move,E_Gadcon_DND_Cb drop,int x,int y,int w,int h)426 e_gadcon_drop_handler_add(E_Gadcon *gc, E_Gadcon_DND_Cb enter, E_Gadcon_DND_Cb leave, E_Gadcon_DND_Cb move, E_Gadcon_DND_Cb drop, int x, int y, int w, int h)
427 {
428    const char *drop_types[] = { "enlightenment/gadcon_client" };
429 
430    E_OBJECT_CHECK(gc);
431    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
432    if (gc->drop_handler) return;
433    gc->drop_handler =
434      e_drop_handler_add(E_OBJECT(gc), NULL, gc,
435                         _e_gadcon_cb_dnd_enter, _e_gadcon_cb_dnd_move,
436                         _e_gadcon_cb_dnd_leave, _e_gadcon_cb_dnd_drop,
437                         drop_types, 1, x, y, w, h);
438    gc->dnd_enter_cb = enter;
439    gc->dnd_leave_cb = leave;
440    gc->dnd_move_cb = move;
441    gc->dnd_drop_cb = drop;
442 }
443 
444 E_API E_Gadcon *
e_gadcon_swallowed_new(const char * name,int id,Evas_Object * obj,const char * swallow_name)445 e_gadcon_swallowed_new(const char *name, int id, Evas_Object *obj, const char *swallow_name)
446 {
447    E_Gadcon *gc;
448    E_Config_Gadcon *cf_gc;
449    Eina_List *l;
450    Evas_Coord x, y, w, h;
451 
452    gc = E_OBJECT_ALLOC(E_Gadcon, E_GADCON_TYPE, _e_gadcon_free);
453    if (!gc) return NULL;
454 
455    gc->name = eina_stringshare_add(name);
456    gc->id = id;
457    gc->layout_policy = E_GADCON_LAYOUT_POLICY_PANEL;
458    gc->location = NULL;
459 
460    gc->edje.o_parent = obj;
461    gc->edje.swallow_name = eina_stringshare_add(swallow_name);
462 
463    gc->orient = E_GADCON_ORIENT_HORIZ;
464    gc->evas = evas_object_evas_get(obj);
465    gc->o_container = e_gadcon_layout_add(gc->evas);
466    evas_object_geometry_get(gc->o_container, &x, &y, &w, &h);
467    e_gadcon_drop_handler_add(gc, NULL, NULL, NULL, NULL, x, y, w, h);
468    evas_object_event_callback_add(gc->o_container, EVAS_CALLBACK_MOVE,
469                                   _e_gadcon_cb_moveresize, gc);
470    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
471                                   (Evas_Object_Event_Cb)_e_gadcon_parent_resize_cb, gc);
472    evas_object_event_callback_add(gc->o_container, EVAS_CALLBACK_RESIZE,
473                                   _e_gadcon_cb_moveresize, gc);
474    evas_object_event_callback_add(gc->o_container, EVAS_CALLBACK_SHOW,
475                                   _e_gadcon_cb_show, gc);
476    evas_object_event_callback_add(gc->o_container, EVAS_CALLBACK_HIDE,
477                                   _e_gadcon_cb_hide, gc);
478    evas_object_smart_callback_add(gc->o_container, "size_request",
479                                   _e_gadcon_cb_size_request, gc);
480    evas_object_smart_callback_add(gc->o_container, "min_size_request",
481                                   _e_gadcon_cb_min_size_request, gc);
482    evas_object_show(gc->o_container);
483    edje_object_part_swallow(gc->edje.o_parent, gc->edje.swallow_name,
484                             gc->o_container);
485    gadcons = eina_list_append(gadcons, gc);
486 
487    EINA_LIST_FOREACH(e_config->gadcons, l, cf_gc)
488      {
489         if ((!strcmp(cf_gc->name, gc->name)) && (cf_gc->id == gc->id))
490           {
491              gc->cf = cf_gc;
492              break;
493           }
494      }
495    if (!gc->cf)
496      {
497         gc->cf = E_NEW(E_Config_Gadcon, 1);
498         gc->cf->name = eina_stringshare_add(gc->name);
499         gc->cf->id = gc->id;
500         e_config->gadcons = eina_list_append(e_config->gadcons, gc->cf);
501         e_config_save_queue();
502      }
503    return gc;
504 }
505 
506 E_API void
e_gadcon_swallowed_min_size_set(E_Gadcon * gc,Evas_Coord w,Evas_Coord h)507 e_gadcon_swallowed_min_size_set(E_Gadcon *gc, Evas_Coord w, Evas_Coord h)
508 {
509    E_OBJECT_CHECK(gc);
510    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
511    if (gc->edje.o_parent)
512      {
513         evas_object_size_hint_min_set(gc->o_container, w, h);
514         edje_object_part_swallow(gc->edje.o_parent, gc->edje.swallow_name,
515                                  gc->o_container);
516      }
517 }
518 
519 E_API void
e_gadcon_min_size_request_callback_set(E_Gadcon * gc,void (* func)(void * data,E_Gadcon * gc,Evas_Coord w,Evas_Coord h),void * data)520 e_gadcon_min_size_request_callback_set(E_Gadcon *gc, void (*func)(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h), void *data)
521 {
522    E_OBJECT_CHECK(gc);
523    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
524    gc->min_size_request.func = func;
525    gc->min_size_request.data = data;
526 }
527 
528 E_API void
e_gadcon_size_request_callback_set(E_Gadcon * gc,void (* func)(void * data,E_Gadcon * gc,Evas_Coord w,Evas_Coord h),void * data)529 e_gadcon_size_request_callback_set(E_Gadcon *gc, void (*func)(void *data, E_Gadcon *gc, Evas_Coord w, Evas_Coord h), void *data)
530 {
531    E_OBJECT_CHECK(gc);
532    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
533    gc->resize_request.func = func;
534    gc->resize_request.data = data;
535 }
536 
537 E_API void
e_gadcon_frame_request_callback_set(E_Gadcon * gc,Evas_Object * (* func)(void * data,E_Gadcon_Client * gcc,const char * style),void * data)538 e_gadcon_frame_request_callback_set(E_Gadcon *gc, Evas_Object *(*func)(void *data, E_Gadcon_Client * gcc, const char *style), void *data)
539 {
540    E_OBJECT_CHECK(gc);
541    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
542    gc->frame_request.func = func;
543    gc->frame_request.data = data;
544 }
545 
546 E_API void
e_gadcon_populate_callback_set(E_Gadcon * gc,void (* func)(void * data,E_Gadcon * gc,const E_Gadcon_Client_Class * cc),void * data)547 e_gadcon_populate_callback_set(E_Gadcon *gc, void (*func)(void *data, E_Gadcon *gc, const E_Gadcon_Client_Class *cc), void *data)
548 {
549    E_OBJECT_CHECK(gc);
550    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
551    gc->populate_class.func = func;
552    gc->populate_class.data = data;
553 }
554 
555 E_API void
e_gadcon_layout_policy_set(E_Gadcon * gc,E_Gadcon_Layout_Policy layout_policy)556 e_gadcon_layout_policy_set(E_Gadcon *gc, E_Gadcon_Layout_Policy layout_policy)
557 {
558    E_OBJECT_CHECK(gc);
559    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
560    if (gc->layout_policy == layout_policy) return;
561    gc->layout_policy = layout_policy;
562    /* FIXME: delete container obj, re-pack all clients */
563 }
564 
565 E_API Eina_Bool
e_gadcon_populate(E_Gadcon * gc)566 e_gadcon_populate(E_Gadcon *gc)
567 {
568    Eina_List *l;
569    E_Config_Gadcon_Client *cf_gcc;
570    E_Gadcon_Client_Class *cc;
571    int x = 0;
572 
573    E_OBJECT_CHECK_RETURN(gc, EINA_FALSE);
574    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, EINA_FALSE);
575    e_gadcon_layout_freeze(gc->o_container);
576    EINA_LIST_FOREACH(gc->cf->clients, l, cf_gcc)
577      {
578         if (!cf_gcc->name) continue;
579         cc = eina_hash_find(providers, cf_gcc->name);
580         if (cc)
581           {
582              if (!eina_list_data_find(gc->populated_classes, cc))
583                {
584                   _e_gadcon_provider_populate_request(gc, cc);
585                   cc = NULL;
586                }
587           }
588         if (cc)
589           _e_gadcon_client_populate(gc, cc, cf_gcc);
590         else
591           e_gadcon_client_queue(gc, cf_gcc);
592      }
593    if (!gc->toolbar)
594      {
595         EINA_LIST_FREE(gc->populate_requests, cc)
596           {
597              char buf[256];
598 
599              e_main_ts(cc->name);
600              if (gc->populate_class.func)
601                gc->populate_class.func(gc->populate_class.data, gc, cc);
602              else
603                e_gadcon_populate_class(gc, cc);
604              if (!eina_list_data_find(gc->populated_classes, cc))
605                {
606                   gc->populated_classes = eina_list_append(gc->populated_classes, cc);
607                   if (gc->cf)
608                     {
609                        Eina_List *ll;
610 
611                        if (!gc->awaiting_classes) continue;
612                        ll = eina_hash_set(gc->awaiting_classes, cc->name, NULL);
613                        EINA_LIST_FREE(ll, cf_gcc)
614                          _e_gadcon_client_populate(gc, cc, cf_gcc);
615                     }
616                }
617              snprintf(buf, sizeof(buf), "%s Done", cc->name);
618              e_main_ts(buf);
619              x++;
620           }
621         if (x && _modules_loaded) _e_gadcon_event_populate(gc);
622           e_gadcon_layout_thaw(gc->o_container);
623      }
624    else
625      {
626         e_gadcon_layout_thaw(gc->o_container);
627         if (gc->populated_classes && (!gc->populate_requests))
628           _e_gadcon_event_populate(gc);
629      }
630    return EINA_TRUE;
631 }
632 
633 E_API void
e_gadcon_unpopulate(E_Gadcon * gc)634 e_gadcon_unpopulate(E_Gadcon *gc)
635 {
636    E_Gadcon_Client *gcc;
637 
638    E_OBJECT_CHECK(gc);
639    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
640    /* Be careful, e_object_del does remove gcc from gc->clients */
641    if (gc->o_container) e_gadcon_layout_freeze(gc->o_container);
642    while (gc->clients)
643      {
644         gcc = eina_list_data_get(gc->clients);
645         _e_gadcon_client_unpopulate(gcc);
646         /* FIXME: this seems to happen under some rare and as-yet
647          * undetermined circumstances in gadman
648          */
649         if (gcc != eina_list_data_get(gc->clients)) continue;
650         CRI("DANGLING GADCON CLIENT %p! THIS IS A BUG!!!", gcc);
651         e_object_unref(E_OBJECT(gcc));
652      }
653    if (gc->awaiting_classes)
654      eina_hash_free(gc->awaiting_classes);
655    gc->awaiting_classes = NULL;
656    if (gc->o_container && (!stopping) && (!e_object_is_del(E_OBJECT(gc))))
657      e_gadcon_layout_thaw(gc->o_container);
658 }
659 
660 E_API void
e_gadcon_repopulate(E_Gadcon * gc)661 e_gadcon_repopulate(E_Gadcon *gc)
662 {
663    E_OBJECT_CHECK(gc);
664    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
665    if (gc->o_container) e_gadcon_layout_freeze(gc->o_container);
666    e_gadcon_unpopulate(gc);
667    e_gadcon_populate(gc);
668    if (gc->o_container) e_gadcon_layout_thaw(gc->o_container);
669 }
670 
671 E_API void
e_gadcon_populate_class(E_Gadcon * gc,const E_Gadcon_Client_Class * cc)672 e_gadcon_populate_class(E_Gadcon *gc, const E_Gadcon_Client_Class *cc)
673 {
674    Eina_List *l;
675    E_Config_Gadcon_Client *cf_gcc;
676 
677    E_OBJECT_CHECK(gc);
678    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
679    e_gadcon_layout_freeze(gc->o_container);
680    EINA_LIST_FOREACH(gc->cf->clients, l, cf_gcc)
681      {
682         if (cf_gcc->name && (!strcmp(cf_gcc->name, cc->name)) &&
683             (cf_gcc->id) && (cf_gcc->style))
684           _e_gadcon_client_populate(gc, cc, cf_gcc);
685      }
686    e_gadcon_layout_thaw(gc->o_container);
687 }
688 
689 E_API void
e_gadcon_orient(E_Gadcon * gc,E_Gadcon_Orient orient)690 e_gadcon_orient(E_Gadcon *gc, E_Gadcon_Orient orient)
691 {
692    Eina_List *l;
693    E_Gadcon_Client *gcc;
694    int horiz = 0;
695 
696    E_OBJECT_CHECK(gc);
697    E_OBJECT_IF_NOT_TYPE(gc, E_GADCON_DUMMY_TYPE)
698      {
699         E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
700      }
701    if (gc->orient == orient) return;
702    gc->orient = orient;
703    if (gc->dummy) return;
704    e_gadcon_layout_freeze(gc->o_container);
705    switch (gc->orient)
706      {
707       case E_GADCON_ORIENT_FLOAT:
708       case E_GADCON_ORIENT_HORIZ:
709       case E_GADCON_ORIENT_TOP:
710       case E_GADCON_ORIENT_BOTTOM:
711       case E_GADCON_ORIENT_CORNER_TL:
712       case E_GADCON_ORIENT_CORNER_TR:
713       case E_GADCON_ORIENT_CORNER_BL:
714       case E_GADCON_ORIENT_CORNER_BR:
715         horiz = 1;
716         break;
717 
718       case E_GADCON_ORIENT_VERT:
719       case E_GADCON_ORIENT_LEFT:
720       case E_GADCON_ORIENT_RIGHT:
721       case E_GADCON_ORIENT_CORNER_LT:
722       case E_GADCON_ORIENT_CORNER_RT:
723       case E_GADCON_ORIENT_CORNER_LB:
724       case E_GADCON_ORIENT_CORNER_RB:
725         horiz = 0;
726         break;
727 
728       default:
729         break;
730      }
731    e_gadcon_layout_orientation_set(gc->o_container, horiz);
732    EINA_LIST_FOREACH(gc->clients, l, gcc)
733      {
734         elm_box_horizontal_set(gcc->o_box, horiz);
735         if (gcc->client_class->func.orient)
736           gcc->client_class->func.orient(gcc, gc->orient);
737      }
738    e_gadcon_layout_thaw(gc->o_container);
739 }
740 
741 E_API void
e_gadcon_edit_begin(E_Gadcon * gc)742 e_gadcon_edit_begin(E_Gadcon *gc)
743 {
744    Eina_List *l;
745    E_Gadcon_Client *gcc;
746 
747    E_OBJECT_CHECK(gc);
748    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
749    e_gadcon_layout_freeze(gc->o_container);
750    e_gadcon_locked_set(gc, 1);
751    gc->editing = 1;
752    EINA_LIST_FOREACH(gc->clients, l, gcc)
753      e_gadcon_client_edit_begin(gcc);
754    e_gadcon_layout_thaw(gc->o_container);
755 }
756 
757 E_API void
e_gadcon_edit_end(E_Gadcon * gc)758 e_gadcon_edit_end(E_Gadcon *gc)
759 {
760    Eina_List *l;
761    E_Gadcon_Client *gcc;
762 
763    E_OBJECT_CHECK(gc);
764    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
765    e_gadcon_layout_freeze(gc->o_container);
766    gc->editing = 0;
767    EINA_LIST_FOREACH(gc->clients, l, gcc)
768      e_gadcon_client_edit_end(gcc);
769    e_gadcon_layout_thaw(gc->o_container);
770    e_gadcon_locked_set(gc, 0);
771 }
772 
773 E_API void
e_gadcon_all_edit_begin(void)774 e_gadcon_all_edit_begin(void)
775 {
776    Eina_List *l;
777    E_Gadcon *gc;
778 
779    EINA_LIST_FOREACH(gadcons, l, gc)
780      e_gadcon_edit_begin(gc);
781 }
782 
783 E_API void
e_gadcon_all_edit_end(void)784 e_gadcon_all_edit_end(void)
785 {
786    Eina_List *l;
787    E_Gadcon *gc;
788 
789    EINA_LIST_FOREACH(gadcons, l, gc)
790      e_gadcon_edit_end(gc);
791 }
792 
793 E_API void
e_gadcon_zone_set(E_Gadcon * gc,E_Zone * zone)794 e_gadcon_zone_set(E_Gadcon *gc, E_Zone *zone)
795 {
796    E_OBJECT_CHECK(gc);
797    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
798    gc->zone = zone;
799    if (gc->cf) gc->cf->zone = zone->num;
800 }
801 
802 E_API E_Zone *
e_gadcon_zone_get(E_Gadcon * gc)803 e_gadcon_zone_get(E_Gadcon *gc)
804 {
805    E_OBJECT_CHECK_RETURN(gc, NULL);
806    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, NULL);
807    if (gc->zone) return gc->zone;
808    if (!gc->toolbar) return NULL;
809    return e_win_client_get(gc->toolbar->fwin)->zone;
810 }
811 
812 E_API void
e_gadcon_ecore_evas_set(E_Gadcon * gc,Ecore_Evas * ee)813 e_gadcon_ecore_evas_set(E_Gadcon *gc, Ecore_Evas *ee)
814 {
815    E_OBJECT_CHECK(gc);
816    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
817    gc->ecore_evas = ee;
818 }
819 
820 E_API int
e_gadcon_canvas_zone_geometry_get(E_Gadcon * gc,int * x,int * y,int * w,int * h)821 e_gadcon_canvas_zone_geometry_get(E_Gadcon *gc, int *x, int *y, int *w, int *h)
822 {
823    E_OBJECT_CHECK_RETURN(gc, 0);
824    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, 0);
825    if (!gc->ecore_evas) return 0;
826    ecore_evas_geometry_get(gc->ecore_evas, x, y, w, h);
827    *x = 0;
828    *y = 0;
829 // so much relies on this down here to have been broken... ie return comp-relative coords.
830 //   if (gc->zone)
831 //     {
832 //	if (x) *x = *x - gc->zone->x;
833 //	if (y) *y = *y - gc->zone->y;
834 //     }
835    return 1;
836 }
837 
838 E_API void
e_gadcon_util_menu_attach_func_set(E_Gadcon * gc,void (* func)(void * data,E_Gadcon_Client * gcc,E_Menu * menu),void * data)839 e_gadcon_util_menu_attach_func_set(E_Gadcon *gc, void (*func)(void *data, E_Gadcon_Client *gcc, E_Menu *menu), void *data)
840 {
841    E_OBJECT_CHECK(gc);
842    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
843    gc->menu_attach.func = func;
844    gc->menu_attach.data = data;
845 }
846 
847 E_API void
e_gadcon_util_lock_func_set(E_Gadcon * gc,void (* func)(void * data,int lock),void * data)848 e_gadcon_util_lock_func_set(E_Gadcon *gc, void (*func)(void *data, int lock), void *data)
849 {
850    E_OBJECT_CHECK(gc);
851    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
852    gc->locked_set.func = func;
853    gc->locked_set.data = data;
854 }
855 
856 E_API void
e_gadcon_util_urgent_show_func_set(E_Gadcon * gc,void (* func)(void * data),void * data)857 e_gadcon_util_urgent_show_func_set(E_Gadcon *gc, void (*func)(void *data), void *data)
858 {
859    E_OBJECT_CHECK(gc);
860    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
861    gc->urgent_show.func = func;
862    gc->urgent_show.data = data;
863 }
864 
865 E_API void
e_gadcon_dnd_window_set(E_Gadcon * gc,Ecore_X_Window win)866 e_gadcon_dnd_window_set(E_Gadcon *gc, Ecore_X_Window win)
867 {
868    E_OBJECT_CHECK(gc);
869    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
870    gc->dnd_win = win;
871 }
872 
873 E_API Ecore_X_Window
e_gadcon_dnd_window_get(E_Gadcon * gc)874 e_gadcon_dnd_window_get(E_Gadcon *gc)
875 {
876    E_OBJECT_CHECK_RETURN(gc, 0);
877    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, 0);
878    return gc->dnd_win;
879 }
880 
881 E_API void
e_gadcon_xdnd_window_set(E_Gadcon * gc,Ecore_X_Window win)882 e_gadcon_xdnd_window_set(E_Gadcon *gc, Ecore_X_Window win)
883 {
884    E_OBJECT_CHECK(gc);
885    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
886    gc->xdnd_win = win;
887 }
888 
889 E_API Ecore_X_Window
e_gadcon_xdnd_window_get(E_Gadcon * gc)890 e_gadcon_xdnd_window_get(E_Gadcon *gc)
891 {
892    E_OBJECT_CHECK_RETURN(gc, 0);
893    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, 0);
894    return gc->xdnd_win;
895 }
896 
897 E_API void
e_gadcon_name_set(E_Gadcon * gc,const char * name)898 e_gadcon_name_set(E_Gadcon *gc, const char *name)
899 {
900    if (!gc) return;
901    if (!name) return;
902    if (gc->name == name) return;
903    eina_stringshare_replace(&gc->name, name);
904    eina_stringshare_replace(&gc->cf->name, name);
905 }
906 
907 E_API void
e_gadcon_shelf_set(E_Gadcon * gc,E_Shelf * shelf)908 e_gadcon_shelf_set(E_Gadcon *gc, E_Shelf *shelf)
909 {
910    E_OBJECT_CHECK(gc);
911    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
912    gc->shelf = shelf;
913 }
914 
915 E_API E_Shelf *
e_gadcon_shelf_get(E_Gadcon * gc)916 e_gadcon_shelf_get(E_Gadcon *gc)
917 {
918    E_OBJECT_CHECK_RETURN(gc, NULL);
919    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, NULL);
920    return gc->shelf;
921 }
922 
923 E_API void
e_gadcon_toolbar_set(E_Gadcon * gc,E_Toolbar * toolbar)924 e_gadcon_toolbar_set(E_Gadcon *gc, E_Toolbar *toolbar)
925 {
926    E_OBJECT_CHECK(gc);
927    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
928    gc->toolbar = toolbar;
929 }
930 
931 E_API E_Toolbar *
e_gadcon_toolbar_get(E_Gadcon * gc)932 e_gadcon_toolbar_get(E_Gadcon *gc)
933 {
934    E_OBJECT_CHECK_RETURN(gc, NULL);
935    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, NULL);
936    return gc->toolbar;
937 }
938 
939 E_API E_Config_Gadcon_Client *
e_gadcon_client_config_new(E_Gadcon * gc,const char * name)940 e_gadcon_client_config_new(E_Gadcon *gc, const char *name)
941 {
942    E_Gadcon_Client_Class *cc;
943    E_Config_Gadcon_Client *cf_gcc;
944 
945    E_OBJECT_CHECK_RETURN(gc, NULL);
946    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, NULL);
947    if (!name) return NULL;
948    cc = eina_hash_find(providers, name);
949    if (!cc) return NULL;
950    if (!_e_gadcon_client_class_feature_check(cc, "id_new", cc->func.id_new))
951      return NULL;
952 
953    cf_gcc = E_NEW(E_Config_Gadcon_Client, 1);
954    if (!cf_gcc) return NULL;
955    cf_gcc->id = eina_stringshare_add(cc->func.id_new(cc));
956    if (!cf_gcc->id)
957      {
958         free(cf_gcc);
959         return NULL;
960      }
961    cf_gcc->name = eina_stringshare_add(name);
962    if (gc->zone)
963      cf_gcc->geom.res = gc->zone->w;
964    else if (gc->o_container)
965      {
966         int w, h;
967         evas_object_geometry_get(gc->o_container, NULL, NULL, &w, &h);
968         switch (gc->orient)
969           {
970            case E_GADCON_ORIENT_VERT:
971            case E_GADCON_ORIENT_LEFT:
972            case E_GADCON_ORIENT_RIGHT:
973            case E_GADCON_ORIENT_CORNER_LT:
974            case E_GADCON_ORIENT_CORNER_RT:
975            case E_GADCON_ORIENT_CORNER_LB:
976            case E_GADCON_ORIENT_CORNER_RB:
977              cf_gcc->geom.res = h;
978              break;
979 
980            default:
981              cf_gcc->geom.res = w;
982           }
983      }
984    else
985      cf_gcc->geom.res = 800;
986    cf_gcc->geom.size = 80;
987    cf_gcc->geom.pos = cf_gcc->geom.res - cf_gcc->geom.size;
988    cf_gcc->style = NULL;
989    cf_gcc->autoscroll = 0;
990    cf_gcc->resizable = 0;
991    gc->cf->clients = eina_list_append(gc->cf->clients, cf_gcc);
992    e_config_save_queue();
993    return cf_gcc;
994 }
995 
996 E_API void
e_gadcon_client_config_del(E_Config_Gadcon * cf_gc,E_Config_Gadcon_Client * cf_gcc)997 e_gadcon_client_config_del(E_Config_Gadcon *cf_gc, E_Config_Gadcon_Client *cf_gcc)
998 {
999    E_Gadcon *gc;
1000    Eina_List *l, *ll;
1001 
1002    if (!cf_gcc) return;
1003    EINA_LIST_FOREACH(gadcons, l, gc)
1004      {
1005         if (!gc->awaiting_classes) continue;
1006         ll = eina_hash_find(gc->awaiting_classes, cf_gcc->name);
1007         eina_hash_set(gc->awaiting_classes, cf_gcc->name, eina_list_remove(ll, cf_gcc));
1008      }
1009 
1010    eina_stringshare_del(cf_gcc->name);
1011    eina_stringshare_del(cf_gcc->id);
1012    eina_stringshare_del(cf_gcc->style);
1013    if (cf_gc) cf_gc->clients = eina_list_remove(cf_gc->clients, cf_gcc);
1014    free(cf_gcc);
1015 }
1016 
1017 E_API E_Gadcon_Client *
e_gadcon_client_find(E_Gadcon * gc,E_Config_Gadcon_Client * cf_gcc)1018 e_gadcon_client_find(E_Gadcon *gc, E_Config_Gadcon_Client *cf_gcc)
1019 {
1020    E_Gadcon_Client *gcc;
1021    Eina_List *l, *ll;
1022 
1023    if (!cf_gcc) return NULL;
1024    if (gc)
1025      {
1026         EINA_LIST_FOREACH(gc->clients, ll, gcc)
1027           if (gcc->cf == cf_gcc) return gcc;
1028         return NULL;
1029      }
1030    EINA_LIST_FOREACH(gadcons, l, gc)
1031      EINA_LIST_FOREACH(gc->clients, ll, gcc)
1032        if (gcc->cf == cf_gcc) return gcc;
1033    return NULL;
1034 }
1035 
1036 static void
_e_gadcon_client_box_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1037 _e_gadcon_client_box_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1038 {
1039    E_Gadcon_Client *gcc = data;
1040    gcc->o_box = NULL;
1041 }
1042 
1043 static void
_e_gadcon_client_box_hints_changed(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1044 _e_gadcon_client_box_hints_changed(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1045 {
1046    E_Gadcon_Client *gcc = data;
1047    if (gcc->autoscroll)
1048      _e_gadcon_client_scroll_state_update(gcc);
1049    evas_object_size_hint_min_set(obj, 0, 0);
1050 }
1051 
1052 static void
_e_gadcon_client_frame_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1053 _e_gadcon_client_frame_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1054 {
1055    E_Gadcon_Client *gcc = data;
1056    gcc->o_frame = NULL;
1057 }
1058 
1059 E_API void
e_gadcon_drag_finished_cb(E_Drag * drag,int dropped)1060 e_gadcon_drag_finished_cb(E_Drag *drag, int dropped)
1061 {
1062    E_Gadcon_Client *gcc;
1063 
1064    gcc = drag->data;
1065    gcc->drag.drag = NULL;
1066    if (!dropped)
1067      {
1068         /* free client config */
1069         e_gadcon_client_config_del(NULL, gcc->cf);
1070         gcc->cf = NULL;
1071         /* delete the gadcon client */
1072         /* TODO: Clean up module config too? */
1073         e_object_del(E_OBJECT(gcc));
1074      }
1075    e_gadcon_client_drag_set(NULL);
1076    gcc->gadcon->new_gcc = NULL;
1077    e_object_unref(E_OBJECT(gcc));
1078 }
1079 
1080 /**
1081  * Creates a new gadget
1082  *
1083  * @param gc gadcon pointer
1084  * @param name to use for gadget
1085  * @param id assigned to gadget
1086  * @param style to for gadget
1087  * @param base_obj the evas object that will show up in the shelf or gadget module
1088  * @return returns pointer to created gadget, on failure returns null
1089  */
1090 E_API E_Gadcon_Client *
e_gadcon_client_new(E_Gadcon * gc,const char * name,const char * id EINA_UNUSED,const char * style,Evas_Object * base_obj)1091 e_gadcon_client_new(E_Gadcon *gc, const char *name, const char *id EINA_UNUSED, const char *style, Evas_Object *base_obj)
1092 {
1093    E_Gadcon_Client *gcc;
1094 
1095    E_OBJECT_CHECK_RETURN(gc, NULL);
1096    E_OBJECT_TYPE_CHECK_RETURN(gc, E_GADCON_TYPE, NULL);
1097    gcc = E_OBJECT_ALLOC(E_Gadcon_Client, E_GADCON_CLIENT_TYPE,
1098                         _e_gadcon_client_free);
1099    if (!gcc) return NULL;
1100    e_object_delfn_add(E_OBJECT(gcc), _e_gadcon_client_delfn, NULL);
1101    gcc->name = eina_stringshare_add(name);
1102    gcc->gadcon = gc;
1103    gcc->o_base = base_obj;
1104    if (gc->clients)
1105      gcc->id = E_GADCON_CLIENT(eina_list_last_data_get(gc->clients))->id + 1;
1106    gc->clients = eina_list_append(gc->clients, gcc);
1107    /* This must only be unique during runtime */
1108    if (gcc->o_base)
1109      evas_object_event_callback_add(gcc->o_base, EVAS_CALLBACK_DEL,
1110                                     _e_gadcon_client_del_hook, gcc);
1111    if ((gc->frame_request.func) && (style))
1112      {
1113         gcc->o_frame = gc->frame_request.func(gc->frame_request.data, gcc, style);
1114         gcc->style = eina_stringshare_add(style);
1115         if (gcc->o_frame)
1116           {
1117              edje_object_size_min_calc(gcc->o_frame, &(gcc->pad.w), &(gcc->pad.h));
1118              gcc->o_box = elm_box_add(e_win_evas_object_win_get(gcc->gadcon->o_container));
1119              evas_object_event_callback_add(gcc->o_box, EVAS_CALLBACK_DEL, _e_gadcon_client_box_del, gcc);
1120              evas_object_event_callback_add(gcc->o_box, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _e_gadcon_client_box_hints_changed, gcc);
1121              switch (gcc->gadcon->orient)
1122                {
1123                 case E_GADCON_ORIENT_FLOAT:
1124                 case E_GADCON_ORIENT_HORIZ:
1125                 case E_GADCON_ORIENT_TOP:
1126                 case E_GADCON_ORIENT_BOTTOM:
1127                 case E_GADCON_ORIENT_CORNER_TL:
1128                 case E_GADCON_ORIENT_CORNER_TR:
1129                 case E_GADCON_ORIENT_CORNER_BL:
1130                 case E_GADCON_ORIENT_CORNER_BR:
1131                   elm_box_horizontal_set(gcc->o_box, 1);
1132                   break;
1133 
1134                 case E_GADCON_ORIENT_VERT:
1135                 case E_GADCON_ORIENT_LEFT:
1136                 case E_GADCON_ORIENT_RIGHT:
1137                 case E_GADCON_ORIENT_CORNER_LT:
1138                 case E_GADCON_ORIENT_CORNER_RT:
1139                 case E_GADCON_ORIENT_CORNER_LB:
1140                 case E_GADCON_ORIENT_CORNER_RB:
1141                   elm_box_horizontal_set(gcc->o_box, 0);
1142                   break;
1143 
1144                 default:
1145                   break;
1146                }
1147              evas_object_event_callback_add(gcc->o_box, EVAS_CALLBACK_MOVE,
1148                                             _e_gadcon_cb_client_frame_moveresize, gcc);
1149              evas_object_event_callback_add(gcc->o_box, EVAS_CALLBACK_RESIZE,
1150                                             _e_gadcon_cb_client_frame_moveresize, gcc);
1151              evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_MOUSE_MOVE,
1152                                             _e_gadcon_cb_client_frame_mouse_move, gcc);
1153              if (gcc->o_base)
1154                {
1155                   E_EXPAND(gcc->o_base);
1156                   elm_box_pack_end(gcc->o_box, gcc->o_base);
1157                }
1158              edje_object_part_swallow(gcc->o_frame, gc->edje.swallow_name, gcc->o_box);
1159              evas_object_show(gcc->o_box);
1160              evas_object_show(gcc->o_frame);
1161           }
1162      }
1163    if (gcc->o_frame)
1164      {
1165         e_gadcon_layout_pack(gc->o_container, gcc->o_frame);
1166         evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_DEL, _e_gadcon_client_frame_del, gcc);
1167      }
1168    else if (gcc->o_base)
1169      e_gadcon_layout_pack(gc->o_container, gcc->o_base);
1170    if (gcc->o_base) evas_object_show(gcc->o_base);
1171    {
1172       E_Event_Gadcon_Client_Add *ev;
1173 
1174       ev = E_NEW(E_Event_Gadcon_Client_Add, 1);
1175       ev->gcc = gcc;
1176       e_object_ref(E_OBJECT(gcc));
1177       ecore_event_add(E_EVENT_GADCON_CLIENT_ADD, ev, _e_gadcon_client_event_free, NULL);
1178    }
1179    return gcc;
1180 }
1181 
1182 E_API void
e_gadcon_client_edit_begin(E_Gadcon_Client * gcc)1183 e_gadcon_client_edit_begin(E_Gadcon_Client *gcc)
1184 {
1185    Evas_Coord x, y, w, h;
1186    Evas_Object *base;
1187    int layer;
1188 
1189    E_OBJECT_CHECK(gcc);
1190    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1191    if (gcc->o_control) return;
1192 
1193    base = gcc->o_frame ?: gcc->o_base;
1194    if (!base) return;
1195    layer = evas_object_layer_get(base) + 1;
1196    evas_object_geometry_get(base, &x, &y, &w, &h);
1197 
1198    gcc->o_control = edje_object_add(gcc->gadcon->evas);
1199    /* FIXME: should probably be in gadget theme or something */
1200    evas_object_layer_set(gcc->o_control, layer);
1201    e_gadcon_locked_set(gcc->gadcon, 1);
1202    gcc->gadcon->editing = 1;
1203 
1204    evas_object_move(gcc->o_control, x, y);
1205    evas_object_resize(gcc->o_control, w, h);
1206    e_theme_edje_object_set(gcc->o_control, "base/theme/gadman",
1207                            "e/gadman/control");
1208 
1209    if ((gcc->autoscroll) /* || (gcc->resizable)*/)
1210      {
1211         if (elm_box_horizontal_get(gcc->o_box))
1212           edje_object_signal_emit(gcc->o_control, "e,state,hsize,on", "e");
1213         else
1214           edje_object_signal_emit(gcc->o_control, "e,state,vsize,on", "e");
1215      }
1216    else
1217      {
1218         edje_object_signal_emit(gcc->o_control, "e,state,hsize,off", "e");
1219         edje_object_signal_emit(gcc->o_control, "e,state,vsize,off", "e");
1220      }
1221    edje_object_signal_emit(gcc->o_control, "e,state,move,on", "e");
1222 
1223    gcc->o_event = evas_object_rectangle_add(gcc->gadcon->evas);
1224    evas_object_color_set(gcc->o_event, 0, 0, 0, 0);
1225    evas_object_repeat_events_set(gcc->o_event, 1);
1226    evas_object_layer_set(gcc->o_event, layer);
1227    evas_object_move(gcc->o_event, x, y);
1228    evas_object_resize(gcc->o_event, w, h);
1229 
1230    edje_object_signal_callback_add(gcc->o_control, "e,action,move,start", "",
1231                                    _e_gadcon_cb_signal_move_start, gcc);
1232    edje_object_signal_callback_add(gcc->o_control, "e,action,move,stop", "",
1233                                    _e_gadcon_cb_signal_move_stop, gcc);
1234    edje_object_signal_callback_add(gcc->o_control, "e,action,move,go", "",
1235                                    _e_gadcon_cb_signal_move_go, gcc);
1236    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,left,start", "",
1237                                    _e_gadcon_cb_signal_resize_left_start, gcc);
1238    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,left,stop", "",
1239                                    _e_gadcon_cb_signal_resize_left_stop, gcc);
1240    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,left,go", "",
1241                                    _e_gadcon_cb_signal_resize_left_go, gcc);
1242    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,right,start", "",
1243                                    _e_gadcon_cb_signal_resize_right_start, gcc);
1244    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,right,stop", "",
1245                                    _e_gadcon_cb_signal_resize_right_stop, gcc);
1246    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,right,go", "",
1247                                    _e_gadcon_cb_signal_resize_right_go, gcc);
1248    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,up,start", "",
1249                                    _e_gadcon_cb_signal_resize_left_start, gcc);
1250    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,up,stop", "",
1251                                    _e_gadcon_cb_signal_resize_left_stop, gcc);
1252    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,up,go", "",
1253                                    _e_gadcon_cb_signal_resize_left_go, gcc);
1254    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,down,start", "",
1255                                    _e_gadcon_cb_signal_resize_right_start, gcc);
1256    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,down,stop", "",
1257                                    _e_gadcon_cb_signal_resize_right_stop, gcc);
1258    edje_object_signal_callback_add(gcc->o_control, "e,action,resize,down,go", "",
1259                                    _e_gadcon_cb_signal_resize_right_go, gcc);
1260 
1261    evas_object_event_callback_add(gcc->o_event, EVAS_CALLBACK_MOUSE_DOWN,
1262                                   _e_gadcon_cb_client_mouse_down, gcc);
1263    evas_object_event_callback_add(gcc->o_event, EVAS_CALLBACK_MOUSE_IN,
1264                                   _e_gadcon_cb_client_mouse_in, gcc);
1265    evas_object_event_callback_add(gcc->o_event, EVAS_CALLBACK_MOUSE_OUT,
1266                                   _e_gadcon_cb_client_mouse_out, gcc);
1267 
1268    evas_object_event_callback_add(base, EVAS_CALLBACK_MOVE,
1269                                   _e_gadcon_cb_client_move, gcc);
1270    evas_object_event_callback_add(base, EVAS_CALLBACK_RESIZE,
1271                                   _e_gadcon_cb_client_resize, gcc);
1272 
1273    evas_object_show(gcc->o_event);
1274    evas_object_show(gcc->o_control);
1275 }
1276 
1277 E_API void
e_gadcon_client_edit_end(E_Gadcon_Client * gcc)1278 e_gadcon_client_edit_end(E_Gadcon_Client *gcc)
1279 {
1280    Eina_List *l = NULL;
1281    E_Gadcon_Client *client = NULL;
1282 
1283    E_OBJECT_CHECK(gcc);
1284    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1285 
1286    if (gcc->o_frame)
1287      {
1288         evas_object_event_callback_del(gcc->o_frame, EVAS_CALLBACK_MOVE,
1289                                        _e_gadcon_cb_client_move);
1290         evas_object_event_callback_del(gcc->o_frame, EVAS_CALLBACK_RESIZE,
1291                                        _e_gadcon_cb_client_resize);
1292      }
1293    else if (gcc->o_base)
1294      {
1295         evas_object_event_callback_del(gcc->o_base, EVAS_CALLBACK_MOVE,
1296                                        _e_gadcon_cb_client_move);
1297         evas_object_event_callback_del(gcc->o_base, EVAS_CALLBACK_RESIZE,
1298                                        _e_gadcon_cb_client_resize);
1299      }
1300 
1301    if (gcc->moving)
1302      {
1303         gcc->moving = 0;
1304         if (gcc->cf) _e_gadcon_client_save(gcc);
1305      }
1306    if (gcc->o_event) evas_object_del(gcc->o_event);
1307    gcc->o_event = NULL;
1308    if (gcc->o_control) evas_object_del(gcc->o_control);
1309    gcc->o_control = NULL;
1310 
1311    e_gadcon_locked_set(gcc->gadcon, 0);
1312    EINA_LIST_FOREACH(gcc->gadcon->clients, l, client)
1313      {
1314         if (!client) continue;
1315         if (client->o_control) return;
1316      }
1317    gcc->gadcon->editing = 0;
1318 }
1319 
1320 E_API void
e_gadcon_client_show(E_Gadcon_Client * gcc)1321 e_gadcon_client_show(E_Gadcon_Client *gcc)
1322 {
1323    E_OBJECT_CHECK(gcc);
1324    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1325 
1326    if (!gcc->hidden) return;
1327    if (gcc->o_box) evas_object_show(gcc->o_box);
1328    if (gcc->o_frame) evas_object_show(gcc->o_frame);
1329    if (gcc->o_base) evas_object_show(gcc->o_base);
1330    if (gcc->o_control) evas_object_show(gcc->o_control);
1331    if (gcc->o_event) evas_object_show(gcc->o_event);
1332    if (gcc->o_frame)
1333      {
1334         e_gadcon_layout_pack(gcc->gadcon->o_container, gcc->o_frame);
1335         e_gadcon_layout_pack_options_set(gcc->o_frame, gcc);
1336      }
1337    else if (gcc->o_base)
1338      {
1339         e_gadcon_layout_pack(gcc->gadcon->o_container, gcc->o_base);
1340         e_gadcon_layout_pack_options_set(gcc->o_base, gcc);
1341      }
1342    gcc->hidden = 0;
1343 }
1344 
1345 E_API void
e_gadcon_client_hide(E_Gadcon_Client * gcc)1346 e_gadcon_client_hide(E_Gadcon_Client *gcc)
1347 {
1348    E_OBJECT_CHECK(gcc);
1349    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1350 
1351    if (gcc->hidden) return;
1352    if (gcc->o_box) evas_object_hide(gcc->o_box);
1353    if (gcc->o_frame) evas_object_hide(gcc->o_frame);
1354    if (gcc->o_base) evas_object_hide(gcc->o_base);
1355    if (gcc->o_control) evas_object_hide(gcc->o_control);
1356    if (gcc->o_event) evas_object_hide(gcc->o_event);
1357    if (gcc->o_frame)
1358      e_gadcon_layout_unpack(gcc->o_frame);
1359    else if (gcc->o_base)
1360      e_gadcon_layout_unpack(gcc->o_base);
1361    gcc->hidden = 1;
1362 }
1363 
1364 E_API void
e_gadcon_client_size_request(E_Gadcon_Client * gcc,Evas_Coord w,Evas_Coord h)1365 e_gadcon_client_size_request(E_Gadcon_Client *gcc, Evas_Coord w, Evas_Coord h)
1366 {
1367    E_OBJECT_CHECK(gcc);
1368    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1369    switch (gcc->gadcon->orient)
1370      {
1371       case E_GADCON_ORIENT_HORIZ:
1372       case E_GADCON_ORIENT_TOP:
1373       case E_GADCON_ORIENT_BOTTOM:
1374         if (gcc->o_frame)
1375           e_gadcon_layout_pack_size_set(gcc->o_frame, w + gcc->pad.w);
1376         else if (gcc->o_base)
1377           e_gadcon_layout_pack_size_set(gcc->o_base, w);
1378         break;
1379 
1380       case E_GADCON_ORIENT_VERT:
1381       case E_GADCON_ORIENT_LEFT:
1382       case E_GADCON_ORIENT_RIGHT:
1383         if (gcc->o_frame)
1384           e_gadcon_layout_pack_size_set(gcc->o_frame, h + gcc->pad.h);
1385         else if (gcc->o_base)
1386           e_gadcon_layout_pack_size_set(gcc->o_base, h);
1387         break;
1388 
1389       case E_GADCON_ORIENT_FLOAT:
1390       case E_GADCON_ORIENT_CORNER_TL:
1391       case E_GADCON_ORIENT_CORNER_TR:
1392       case E_GADCON_ORIENT_CORNER_BL:
1393       case E_GADCON_ORIENT_CORNER_BR:
1394       case E_GADCON_ORIENT_CORNER_LT:
1395       case E_GADCON_ORIENT_CORNER_RT:
1396       case E_GADCON_ORIENT_CORNER_LB:
1397       case E_GADCON_ORIENT_CORNER_RB:
1398       default:
1399         break;
1400      }
1401 }
1402 
1403 E_API void
e_gadcon_client_min_size_set(E_Gadcon_Client * gcc,Evas_Coord w,Evas_Coord h)1404 e_gadcon_client_min_size_set(E_Gadcon_Client *gcc, Evas_Coord w, Evas_Coord h)
1405 {
1406    E_OBJECT_CHECK(gcc);
1407    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1408    gcc->min.w = w;
1409    gcc->min.h = h;
1410 /*   if (!gcc->resizable)*/
1411    {
1412       if (gcc->o_frame)
1413         e_gadcon_layout_pack_min_size_set(gcc->o_frame, w + gcc->pad.w,
1414                                           h + gcc->pad.h);
1415       else if (gcc->o_base)
1416         e_gadcon_layout_pack_min_size_set(gcc->o_base, w, h);
1417    }
1418    _e_gadcon_moveresize_handle(gcc);
1419 }
1420 
1421 E_API void
e_gadcon_client_aspect_set(E_Gadcon_Client * gcc,int w,int h)1422 e_gadcon_client_aspect_set(E_Gadcon_Client *gcc, int w, int h)
1423 {
1424    E_OBJECT_CHECK(gcc);
1425    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1426    gcc->aspect.w = w;
1427    gcc->aspect.h = h;
1428 //   if ((!gcc->autoscroll)/* && (!gcc->resizable)*/)
1429    {
1430       if (gcc->o_frame)
1431         {
1432            e_gadcon_layout_pack_aspect_pad_set(gcc->o_frame, gcc->pad.w,
1433                                                gcc->pad.h);
1434            e_gadcon_layout_pack_aspect_set(gcc->o_frame, w, h);
1435         }
1436       else if (gcc->o_base)
1437         e_gadcon_layout_pack_aspect_set(gcc->o_base, w, h);
1438    }
1439    _e_gadcon_moveresize_handle(gcc);
1440 }
1441 
1442 E_API void
e_gadcon_client_autoscroll_toggle_disabled_set(E_Gadcon_Client * gcc,Eina_Bool disable)1443 e_gadcon_client_autoscroll_toggle_disabled_set(E_Gadcon_Client *gcc, Eina_Bool disable)
1444 {
1445    disable = !!disable;
1446    if (gcc->autoscroll_disabled == disable) return;
1447    gcc->autoscroll_disabled = disable;
1448    if (disable) e_gadcon_client_autoscroll_set(gcc, 1);
1449 }
1450 
1451 E_API void
e_gadcon_client_autoscroll_set(E_Gadcon_Client * gcc,int autoscroll)1452 e_gadcon_client_autoscroll_set(E_Gadcon_Client *gcc, int autoscroll)
1453 {
1454    E_OBJECT_CHECK(gcc);
1455    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1456 
1457    if (gcc->autoscroll_disabled && (!autoscroll))
1458      {
1459         e_util_dialog_show(_("Gadget error"), _("%s does not support disabling autoscrolling"), gcc->name);
1460         return;
1461      }
1462    gcc->autoscroll = autoscroll;
1463    gcc->autoscroll_set = 1;
1464 /*
1465    if (gcc->autoscroll)
1466      {
1467         if (gcc->o_frame)
1468           {
1469              e_gadcon_layout_pack_aspect_pad_set(gcc->o_frame, gcc->pad.w,
1470                                                  gcc->pad.h);
1471              e_gadcon_layout_pack_aspect_set(gcc->o_frame, 0, 0);
1472              e_gadcon_layout_pack_min_size_set(gcc->o_frame, 0, 0);
1473           }
1474         else if (gcc->o_base)
1475           {
1476              e_gadcon_layout_pack_aspect_set(gcc->o_base, 0, 0);
1477              e_gadcon_layout_pack_min_size_set(gcc->o_base, 0, 0);
1478           }
1479      }
1480    else
1481  */
1482    {
1483       if (gcc->o_frame)
1484         {
1485            e_gadcon_layout_pack_aspect_pad_set(gcc->o_frame, gcc->pad.w,
1486                                                gcc->pad.h);
1487            e_gadcon_layout_pack_aspect_set(gcc->o_frame, gcc->aspect.w,
1488                                            gcc->aspect.h);
1489            e_gadcon_layout_pack_min_size_set(gcc->o_frame, gcc->min.w,
1490                                              gcc->min.h);
1491         }
1492       else if (gcc->o_base)
1493         {
1494            e_gadcon_layout_pack_min_size_set(gcc->o_base, gcc->min.w,
1495                                              gcc->min.h);
1496            e_gadcon_layout_pack_aspect_set(gcc->o_base, gcc->aspect.w,
1497                                            gcc->aspect.h);
1498         }
1499    }
1500    if (gcc->autoscroll)
1501      _e_gadcon_client_scroll_state_update(gcc);
1502 }
1503 
1504 E_API void
e_gadcon_client_resizable_set(E_Gadcon_Client * gcc EINA_UNUSED,int resizable EINA_UNUSED)1505 e_gadcon_client_resizable_set(E_Gadcon_Client *gcc EINA_UNUSED, int resizable EINA_UNUSED)
1506 {
1507    E_OBJECT_CHECK(gcc);
1508    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1509 /*
1510    gcc->resizable = resizable;
1511    if (gcc->resizable)
1512      {
1513         if (gcc->o_frame)
1514           {
1515              e_gadcon_layout_pack_aspect_pad_set(gcc->o_frame, gcc->pad.w,
1516                                                  gcc->pad.h);
1517              e_gadcon_layout_pack_aspect_set(gcc->o_frame, 0, 0);
1518              e_gadcon_layout_pack_min_size_set(gcc->o_frame, 0, 0);
1519           }
1520         else if (gcc->o_base)
1521           {
1522              e_gadcon_layout_pack_min_size_set(gcc->o_base, 0, 0);
1523              e_gadcon_layout_pack_aspect_set(gcc->o_base, 0, 0);
1524           }
1525      }
1526    else
1527      {
1528         if (gcc->o_frame)
1529           {
1530              e_gadcon_layout_pack_aspect_pad_set(gcc->o_frame, gcc->pad.w,
1531                                                  gcc->pad.h);
1532              e_gadcon_layout_pack_aspect_set(gcc->o_frame, gcc->aspect.w,
1533                                              gcc->aspect.h);
1534              e_gadcon_layout_pack_min_size_set(gcc->o_frame, gcc->min.w,
1535                                                gcc->min.h);
1536           }
1537         else if (gcc->o_base)
1538           {
1539              e_gadcon_layout_pack_min_size_set(gcc->o_base, gcc->min.w,
1540                                                gcc->min.h);
1541              e_gadcon_layout_pack_aspect_set(gcc->o_base, gcc->aspect.w,
1542                                              gcc->aspect.h);
1543           }
1544      }
1545  */
1546 }
1547 
1548 E_API int
e_gadcon_client_geometry_get(E_Gadcon_Client * gcc,int * x,int * y,int * w,int * h)1549 e_gadcon_client_geometry_get(E_Gadcon_Client *gcc, int *x, int *y, int *w, int *h)
1550 {
1551    int gx = 0, gy = 0;
1552 
1553    E_OBJECT_CHECK_RETURN(gcc, 0);
1554    E_OBJECT_TYPE_CHECK_RETURN(gcc, E_GADCON_CLIENT_TYPE, 0);
1555    if (!e_gadcon_canvas_zone_geometry_get(gcc->gadcon, &gx, &gy, NULL, NULL))
1556      return 0;
1557    if (gcc->o_base) evas_object_geometry_get(gcc->o_base, x, y, w, h);
1558    if (x) *x += gx;
1559    if (y) *y += gy;
1560    return 1;
1561 }
1562 
1563 E_API int
e_gadcon_client_viewport_geometry_get(E_Gadcon_Client * gcc,int * x,int * y,int * w,int * h)1564 e_gadcon_client_viewport_geometry_get(E_Gadcon_Client *gcc, int *x, int *y, int *w, int *h)
1565 {
1566    E_OBJECT_CHECK_RETURN(gcc, 0);
1567    E_OBJECT_TYPE_CHECK_RETURN(gcc, E_GADCON_CLIENT_TYPE, 0);
1568 
1569    if (gcc->o_box) evas_object_geometry_get(gcc->o_base, x, y, w, h);
1570    else if (gcc->o_base)
1571      evas_object_geometry_get(gcc->o_base, x, y, w, h);
1572    else
1573      {
1574         if (x) *x = 0;
1575         if (y) *y = 0;
1576         if (w) *w = 0;
1577         if (h) *h = 0;
1578      }
1579    return 1;
1580 }
1581 
1582 E_API E_Zone *
e_gadcon_client_zone_get(E_Gadcon_Client * gcc)1583 e_gadcon_client_zone_get(E_Gadcon_Client *gcc)
1584 {
1585    E_OBJECT_CHECK_RETURN(gcc, NULL);
1586    E_OBJECT_TYPE_CHECK_RETURN(gcc, E_GADCON_CLIENT_TYPE, NULL);
1587    return e_gadcon_zone_get(gcc->gadcon);
1588 }
1589 
1590 static Eina_Bool
_e_gadcon_client_populate(E_Gadcon * gc,const E_Gadcon_Client_Class * cc,E_Config_Gadcon_Client * cf_gcc)1591 _e_gadcon_client_populate(E_Gadcon *gc, const E_Gadcon_Client_Class *cc, E_Config_Gadcon_Client *cf_gcc)
1592 {
1593    E_Gadcon_Client *gcc;
1594 
1595    if (!eina_list_data_find(gc->populated_classes, cc))
1596      {
1597         _e_gadcon_provider_populate_request(gc, cc);
1598         return EINA_TRUE;
1599      }
1600 
1601    if ((!cf_gcc->id) &&
1602        (_e_gadcon_client_class_feature_check(cc, "id_new", cc->func.id_new)))
1603      cf_gcc->id = eina_stringshare_add(cc->func.id_new(cc));
1604 
1605    if (!cf_gcc->style)
1606      gcc = cc->func.init(gc, cf_gcc->name, cf_gcc->id,
1607                          cc->default_style);
1608    else
1609      gcc = cc->func.init(gc, cf_gcc->name, cf_gcc->id,
1610                          cf_gcc->style);
1611 
1612    if (!gcc) return EINA_FALSE;
1613    gcc->cf = cf_gcc;
1614    gcc->client_class = cc;
1615    gcc->config.pos = cf_gcc->geom.pos;
1616    gcc->config.size = cf_gcc->geom.size;
1617    gcc->config.res = cf_gcc->geom.res;
1618    gcc->state_info.seq = cf_gcc->state_info.seq;
1619    gcc->state_info.flags = cf_gcc->state_info.flags;
1620    gcc->config.pos_x = gcc->cf->geom.pos_x;
1621    gcc->config.pos_y = gcc->cf->geom.pos_y;
1622    gcc->config.size_w = gcc->cf->geom.size_w;
1623    gcc->config.size_h = gcc->cf->geom.size_h;
1624    gcc->cf->resizable = 0;
1625 
1626    eina_stringshare_replace(&gcc->style, cf_gcc->style);
1627    if (gcc->o_frame)
1628      e_gadcon_layout_pack_options_set(gcc->o_frame, gcc);
1629    else if (gcc->o_base)
1630      e_gadcon_layout_pack_options_set(gcc->o_base, gcc);
1631 
1632    if (!gcc->autoscroll_set)
1633      e_gadcon_client_autoscroll_set(gcc, cf_gcc->autoscroll);
1634    //		  e_gadcon_client_resizable_set(gcc, cf_gcc->resizable);
1635    if (gcc->client_class->func.orient)
1636      gcc->client_class->func.orient(gcc, gc->orient);
1637 
1638    e_config_save_queue();
1639    if (gc->editing) e_gadcon_client_edit_begin(gcc);
1640    if (gc->instant_edit)
1641      e_gadcon_client_util_menu_attach(gcc);
1642    return EINA_TRUE;
1643 }
1644 
1645 static void
_e_gadcon_client_unpopulate(E_Gadcon_Client * gcc)1646 _e_gadcon_client_unpopulate(E_Gadcon_Client *gcc)
1647 {
1648    if (gcc->menu)
1649      {
1650         if (gcc->gadcon->shelf && (gcc->menu == gcc->gadcon->shelf->menu)) gcc->gadcon->shelf->menu = NULL;
1651         e_menu_post_deactivate_callback_set(gcc->menu, NULL, NULL);
1652         e_menu_deactivate(gcc->menu);
1653         e_object_del(E_OBJECT(gcc->menu));
1654         gcc->menu = NULL;
1655      }
1656    e_object_del(E_OBJECT(gcc));
1657 }
1658 
1659 static void
_e_gadcon_client_change_gadcon(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi)1660 _e_gadcon_client_change_gadcon(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi)
1661 {
1662    E_Gadcon_Location *src, *dst;
1663    E_Gadcon_Client *gcc;
1664 
1665    gcc = data;
1666    src = gcc->gadcon->location;
1667    dst = e_object_data_get(E_OBJECT(mi));
1668    _e_gadcon_location_change(gcc, src, dst);
1669 }
1670 
1671 static void
_e_gadcon_add_locations_menu_for_site(E_Menu * m,E_Gadcon_Client * gcc,E_Gadcon_Site site,int * count)1672 _e_gadcon_add_locations_menu_for_site(E_Menu *m, E_Gadcon_Client *gcc, E_Gadcon_Site site, int *count)
1673 {
1674    E_Menu_Item *mi;
1675    const Eina_List *l;
1676    E_Gadcon_Location *loc;
1677    int k = *count;
1678 
1679    EINA_LIST_FOREACH(gadcon_locations, l, loc)
1680      {
1681         if (loc->site == site)
1682           {
1683              if (loc == gcc->gadcon->location) continue;
1684              if (k)
1685                {
1686                   k = 0;
1687                   mi = e_menu_item_new(m);
1688                   e_menu_item_separator_set(mi, 1);
1689                   (*count) = 0;
1690                }
1691              mi = e_menu_item_new(m);
1692              e_menu_item_label_set(mi, loc->name);
1693              e_object_data_set(E_OBJECT(mi), loc);
1694              e_menu_item_callback_set(mi, _e_gadcon_client_change_gadcon, gcc);
1695              if (loc->icon_name)
1696                e_util_menu_item_theme_icon_set(mi, loc->icon_name);
1697              (*count)++;
1698           }
1699      }
1700 }
1701 
1702 static void
_e_gadcon_gadget_move_to_pre_cb(void * data,E_Menu * m)1703 _e_gadcon_gadget_move_to_pre_cb(void *data, E_Menu *m)
1704 {
1705    E_Gadcon_Client *gcc;
1706    int n = 0;
1707 
1708    gcc = data;
1709    e_menu_pre_activate_callback_set(m, NULL, NULL);
1710 
1711    if (!gcc->client_class->func.is_site || gcc->client_class->func.is_site(E_GADCON_SITE_SHELF))
1712      _e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_SHELF, &n);
1713    if (!gcc->client_class->func.is_site || gcc->client_class->func.is_site(E_GADCON_SITE_DESKTOP))
1714      _e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_DESKTOP, &n);
1715    if (!gcc->client_class->func.is_site || gcc->client_class->func.is_site(E_GADCON_SITE_TOOLBAR))
1716      _e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_TOOLBAR, &n);
1717    //if (!gcc->client_class->func.is_site || gcc->client_class->func.is_site(E_GADCON_SITE_EFM_TOOLBAR))
1718      //_e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_EFM_TOOLBAR, &n);
1719    _e_gadcon_add_locations_menu_for_site(m, gcc, E_GADCON_SITE_UNKNOWN, &n);
1720 }
1721 
1722 E_API void
e_gadcon_client_add_location_menu(E_Gadcon_Client * gcc,E_Menu * menu)1723 e_gadcon_client_add_location_menu(E_Gadcon_Client *gcc, E_Menu *menu)
1724 {
1725    E_Menu *mn;
1726    E_Menu_Item *mi;
1727 
1728    E_OBJECT_CHECK(gcc);
1729    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1730 
1731    if (gcc->gadcon->location)
1732      {
1733         mn = e_menu_new();
1734         mi = e_menu_item_new(menu);
1735         e_menu_item_label_set(mi, _("Move to"));
1736         e_util_menu_item_theme_icon_set(mi, "preferences-look");
1737         e_menu_item_submenu_set(mi, mn);
1738         e_menu_pre_activate_callback_set(mn, _e_gadcon_gadget_move_to_pre_cb, gcc);
1739         e_object_unref(E_OBJECT(mn));
1740      }
1741 }
1742 
1743 E_API E_Menu *
e_gadcon_client_menu_set(E_Gadcon_Client * gcc,E_Menu * m)1744 e_gadcon_client_menu_set(E_Gadcon_Client *gcc, E_Menu *m)
1745 {
1746    E_Menu *ret;
1747 
1748    E_OBJECT_CHECK_RETURN(gcc, NULL);
1749    E_OBJECT_TYPE_CHECK_RETURN(gcc, E_GADCON_CLIENT_TYPE, NULL);
1750 
1751    ret = gcc->menu;
1752    if (ret)
1753      e_menu_post_deactivate_callback_set(ret, NULL, NULL);
1754    gcc->menu = m;
1755    if (gcc->gadcon->shelf) gcc->gadcon->shelf->menu = m;
1756    if (m)
1757      e_menu_post_deactivate_callback_set(m, _e_gadcon_client_cb_menu_post, gcc);
1758    return ret;
1759 }
1760 
1761 E_API E_Menu *
e_gadcon_client_util_menu_items_append(E_Gadcon_Client * gcc,E_Menu * menu_gadget,int flags EINA_UNUSED)1762 e_gadcon_client_util_menu_items_append(E_Gadcon_Client *gcc, E_Menu *menu_gadget, int flags EINA_UNUSED)
1763 {
1764    E_Menu *mo, *menu_main = NULL;
1765    E_Menu_Item *mi;
1766    char buf[256];
1767 
1768    E_OBJECT_CHECK_RETURN(gcc, NULL);
1769    E_OBJECT_TYPE_CHECK_RETURN(gcc, E_GADCON_CLIENT_TYPE, NULL);
1770 
1771    if (e_config->menu_gadcon_client_toplevel)
1772      menu_main = menu_gadget;
1773    else
1774      menu_main = e_menu_new();
1775    e_menu_post_deactivate_callback_set(menu_main, _e_gadcon_client_cb_menu_post, gcc);
1776    gcc->menu = menu_main;
1777 
1778    if (gcc->gadcon->shelf)
1779      {
1780         if (e_menu_item_nth(menu_gadget, 0))
1781           {
1782              mi = e_menu_item_new(menu_gadget);
1783              e_menu_item_separator_set(mi, 1);
1784           }
1785 /*
1786         if (!gcc->o_control)
1787           {
1788              mi = e_menu_item_new(menu_gadget);
1789              e_menu_item_label_set(mi, _("Move"));
1790              e_util_menu_item_theme_icon_set(mi, "transform-scale");
1791              e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_edit, gcc);
1792           }
1793         mi = e_menu_item_new(menu_gadget);
1794         e_menu_item_label_set(mi, _("Resizable"));
1795         e_util_menu_item_theme_icon_set(mi, "transform-scale");
1796         e_menu_item_check_set(mi, 1);
1797         if (gcc->resizable) e_menu_item_toggle_set(mi, 1);
1798         e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_resizable, gcc);
1799  */
1800         if (!gcc->autoscroll_disabled)
1801           {
1802              mi = e_menu_item_new(menu_gadget);
1803              e_menu_item_label_set(mi, _("Automatically scroll contents"));
1804              e_util_menu_item_theme_icon_set(mi, "transform-move");
1805              e_menu_item_check_set(mi, 1);
1806              if (gcc->autoscroll) e_menu_item_toggle_set(mi, 1);
1807              e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_autoscroll, gcc);
1808           }
1809 
1810         if (gcc->gadcon->shelf)
1811           {
1812              mo = e_menu_new();
1813              gcc->gadcon->shelf->menu = menu_main;
1814 
1815              mi = e_menu_item_new(mo);
1816              e_menu_item_label_set(mi, _("Plain"));
1817              e_util_menu_item_theme_icon_set(mi, "enlightenment/plain");
1818              e_menu_item_radio_group_set(mi, 1);
1819              e_menu_item_radio_set(mi, 1);
1820              if (!e_util_strcmp(gcc->style, E_GADCON_CLIENT_STYLE_PLAIN))
1821                e_menu_item_toggle_set(mi, 1);
1822              else if ((!gcc->style) &&
1823                       (!e_util_strcmp(gcc->client_class->default_style, E_GADCON_CLIENT_STYLE_PLAIN)))
1824                e_menu_item_toggle_set(mi, 1);
1825              e_menu_item_disabled_set(mi, mi->toggle);
1826              e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_style_plain, gcc);
1827 
1828              mi = e_menu_item_new(mo);
1829              e_menu_item_label_set(mi, _("Inset"));
1830              e_util_menu_item_theme_icon_set(mi, "enlightenment/inset");
1831              e_menu_item_radio_group_set(mi, 1);
1832              e_menu_item_radio_set(mi, 1);
1833              if (!e_util_strcmp(gcc->style, E_GADCON_CLIENT_STYLE_INSET))
1834                e_menu_item_toggle_set(mi, 1);
1835              else if ((!gcc->style) &&
1836                       (!e_util_strcmp(gcc->client_class->default_style, E_GADCON_CLIENT_STYLE_INSET)))
1837                e_menu_item_toggle_set(mi, 1);
1838              e_menu_item_disabled_set(mi, mi->toggle);
1839              e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_style_inset, gcc);
1840 
1841              mi = e_menu_item_new(menu_gadget);
1842              e_menu_item_label_set(mi, _("Look"));
1843              e_util_menu_item_theme_icon_set(mi, "preferences-look");
1844              e_menu_item_submenu_set(mi, mo);
1845              e_object_unref(E_OBJECT(mo));
1846           }
1847 
1848         mi = e_menu_item_new(menu_gadget);
1849         e_menu_item_separator_set(mi, 1);
1850 
1851         e_gadcon_client_add_location_menu(gcc, menu_gadget);
1852 
1853         mi = e_menu_item_new(menu_gadget);
1854         e_menu_item_label_set(mi, _("Remove"));
1855         e_util_menu_item_theme_icon_set(mi, "list-remove");
1856         e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_remove, gcc);
1857      }
1858 
1859    if ((!e_config->menu_gadcon_client_toplevel) && (!gcc->gadcon->toolbar))
1860      {
1861         mi = e_menu_item_new(menu_main);
1862         if (gcc->client_class->func.label)
1863           snprintf(buf, sizeof(buf), "%s",
1864                    gcc->client_class->func.label((E_Gadcon_Client_Class *)gcc->client_class));
1865         else
1866           snprintf(buf, sizeof(buf), "%s", gcc->name);
1867 
1868         e_menu_item_label_set(mi, _(buf));
1869         e_menu_item_realize_callback_set(mi, _e_gadcon_client_cb_menu_pre, gcc);
1870         e_menu_item_submenu_set(mi, menu_gadget);
1871         e_object_unref(E_OBJECT(menu_gadget));
1872      }
1873 
1874    if (gcc->gadcon->menu_attach.func)
1875      {
1876         if ((gcc->gadcon->shelf) || (gcc->gadcon->toolbar))
1877           {
1878              if (e_config->menu_gadcon_client_toplevel)
1879                {
1880                   mi = e_menu_item_new(menu_main);
1881                   e_menu_item_separator_set(mi, 1);
1882                }
1883              gcc->gadcon->menu_attach.func(gcc->gadcon->menu_attach.data, gcc, menu_main);
1884           }
1885         else
1886           gcc->gadcon->menu_attach.func(gcc->gadcon->menu_attach.data, gcc, menu_gadget);
1887      }
1888 
1889    return menu_main;
1890 }
1891 
1892 E_API void
e_gadcon_client_util_menu_attach(E_Gadcon_Client * gcc)1893 e_gadcon_client_util_menu_attach(E_Gadcon_Client *gcc)
1894 {
1895    E_OBJECT_CHECK(gcc);
1896    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1897    if (gcc->o_frame)
1898      {
1899         evas_object_event_callback_del_full(gcc->o_frame, EVAS_CALLBACK_MOUSE_DOWN,
1900                                             _e_gadcon_client_cb_mouse_down, gcc);
1901         evas_object_event_callback_del_full(gcc->o_frame, EVAS_CALLBACK_MOUSE_UP,
1902                                             _e_gadcon_client_cb_mouse_up, gcc);
1903         evas_object_event_callback_del_full(gcc->o_frame, EVAS_CALLBACK_MOUSE_MOVE,
1904                                             _e_gadcon_client_cb_mouse_move, gcc);
1905         evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_MOUSE_DOWN,
1906                                        _e_gadcon_client_cb_mouse_down, gcc);
1907         evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_MOUSE_UP,
1908                                        _e_gadcon_client_cb_mouse_up, gcc);
1909         evas_object_event_callback_add(gcc->o_frame, EVAS_CALLBACK_MOUSE_MOVE,
1910                                        _e_gadcon_client_cb_mouse_move, gcc);
1911      }
1912    else if (gcc->o_base)
1913      {
1914         evas_object_event_callback_del_full(gcc->o_base, EVAS_CALLBACK_MOUSE_DOWN,
1915                                             _e_gadcon_client_cb_mouse_down, gcc);
1916         evas_object_event_callback_del_full(gcc->o_base, EVAS_CALLBACK_MOUSE_UP,
1917                                             _e_gadcon_client_cb_mouse_up, gcc);
1918         evas_object_event_callback_del_full(gcc->o_base, EVAS_CALLBACK_MOUSE_MOVE,
1919                                             _e_gadcon_client_cb_mouse_move, gcc);
1920         evas_object_event_callback_add(gcc->o_base, EVAS_CALLBACK_MOUSE_DOWN,
1921                                        _e_gadcon_client_cb_mouse_down, gcc);
1922         evas_object_event_callback_add(gcc->o_base, EVAS_CALLBACK_MOUSE_UP,
1923                                        _e_gadcon_client_cb_mouse_up, gcc);
1924         evas_object_event_callback_add(gcc->o_base, EVAS_CALLBACK_MOUSE_MOVE,
1925                                        _e_gadcon_client_cb_mouse_move, gcc);
1926      }
1927 }
1928 
1929 E_API void
e_gadcon_locked_set(E_Gadcon * gc,int lock)1930 e_gadcon_locked_set(E_Gadcon *gc, int lock)
1931 {
1932    E_OBJECT_CHECK(gc);
1933    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
1934    if (gc->locked_set.func)
1935      gc->locked_set.func(gc->locked_set.data, lock);
1936 }
1937 
1938 E_API void
e_gadcon_urgent_show(E_Gadcon * gc)1939 e_gadcon_urgent_show(E_Gadcon *gc)
1940 {
1941    E_OBJECT_CHECK(gc);
1942    E_OBJECT_TYPE_CHECK(gc, E_GADCON_TYPE);
1943    if (gc->urgent_show.func)
1944      gc->urgent_show.func(gc->urgent_show.data);
1945 }
1946 
1947 /*
1948  * NOTE: x & y are relative to the o_box of the gadcon.
1949  */
1950 E_API void
e_gadcon_client_autoscroll_update(E_Gadcon_Client * gcc,Evas_Coord x,Evas_Coord y)1951 e_gadcon_client_autoscroll_update(E_Gadcon_Client *gcc, Evas_Coord x, Evas_Coord y)
1952 {
1953    E_OBJECT_CHECK(gcc);
1954    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1955 
1956    if (gcc->autoscroll)
1957      {
1958         Evas_Coord w, h;
1959         double d;
1960 
1961         /* TODO: When using gadman there is no o_box! */
1962         evas_object_geometry_get(gcc->o_box, NULL, NULL, &w, &h);
1963         if (elm_box_horizontal_get(gcc->o_box))
1964           {
1965              if (w > 1) d = (double)x / (double)(w - 1);
1966              else d = 0;
1967           }
1968         else
1969           {
1970              if (h > 1) d = (double)y / (double)(h - 1);
1971              else d = 0;
1972           }
1973         if (d < 0.0) d = 0.0;
1974         else if (d > 1.0)
1975           d = 1.0;
1976         if (!gcc->scroll_timer)
1977           gcc->scroll_timer =
1978             ecore_timer_loop_add(0.01, _e_gadcon_cb_client_scroll_timer, gcc);
1979         if (!gcc->scroll_animator)
1980           gcc->scroll_animator =
1981             ecore_animator_add(_e_gadcon_cb_client_scroll_animator, gcc);
1982         gcc->scroll_wanted = d;
1983      }
1984 }
1985 
1986 E_API void
e_gadcon_client_autoscroll_cb_set(E_Gadcon_Client * gcc,void (* func)(void * data),void * data)1987 e_gadcon_client_autoscroll_cb_set(E_Gadcon_Client *gcc, void (*func)(void *data), void *data)
1988 {
1989    E_OBJECT_CHECK(gcc);
1990    E_OBJECT_TYPE_CHECK(gcc, E_GADCON_CLIENT_TYPE);
1991    gcc->scroll_cb.func = func;
1992    gcc->scroll_cb.data = data;
1993 }
1994 
1995 E_API Eina_Bool
e_gadcon_site_is_shelf(E_Gadcon_Site site)1996 e_gadcon_site_is_shelf(E_Gadcon_Site site)
1997 {
1998    return site == E_GADCON_SITE_SHELF;
1999 }
2000 
2001 E_API Eina_Bool
e_gadcon_site_is_desktop(E_Gadcon_Site site)2002 e_gadcon_site_is_desktop(E_Gadcon_Site site)
2003 {
2004    return site == E_GADCON_SITE_DESKTOP;
2005 }
2006 
2007 E_API Eina_Bool
e_gadcon_site_is_efm_toolbar(E_Gadcon_Site site)2008 e_gadcon_site_is_efm_toolbar(E_Gadcon_Site site)
2009 {
2010    return site == E_GADCON_SITE_EFM_TOOLBAR;
2011 }
2012 
2013 E_API Eina_Bool
e_gadcon_site_is_any_toolbar(E_Gadcon_Site site)2014 e_gadcon_site_is_any_toolbar(E_Gadcon_Site site)
2015 {
2016    switch (site)
2017      {
2018       // there should be all toolbar sities identifiers
2019       case E_GADCON_SITE_TOOLBAR:
2020       case E_GADCON_SITE_EFM_TOOLBAR:
2021         return EINA_TRUE;
2022 
2023       default:
2024         return EINA_FALSE;
2025      }
2026    return EINA_FALSE;
2027 }
2028 
2029 E_API Eina_Bool
e_gadcon_site_is_not_toolbar(E_Gadcon_Site site)2030 e_gadcon_site_is_not_toolbar(E_Gadcon_Site site)
2031 {
2032    switch (site)
2033      {
2034       // there should be all toolbar sities identifiers
2035       case E_GADCON_SITE_TOOLBAR:
2036       case E_GADCON_SITE_EFM_TOOLBAR:
2037         return EINA_FALSE;
2038 
2039       default:
2040         return EINA_TRUE;
2041      }
2042    return EINA_TRUE;
2043 }
2044 
2045 E_API void
e_gadcon_client_drag_set(E_Gadcon_Client * gcc)2046 e_gadcon_client_drag_set(E_Gadcon_Client *gcc)
2047 {
2048    Eina_List *l;
2049    E_Gadcon *gc;
2050 
2051    EINA_LIST_FOREACH(gadcons, l, gc)
2052      gc->drag_gcc = gcc;
2053 }
2054 
2055 /* local subsystem functions */
2056 static void
_e_gadcon_free(E_Gadcon * gc)2057 _e_gadcon_free(E_Gadcon *gc)
2058 {
2059    if (gc->dummy)
2060      dummies = eina_list_remove(dummies, gc);
2061    else
2062      {
2063         e_gadcon_unpopulate(gc);
2064         gadcons = eina_list_remove(gadcons, gc);
2065      }
2066    eina_list_free(gc->populated_classes);
2067    if (custom_populate_requests)
2068      custom_populate_requests = eina_list_remove(custom_populate_requests, gc);
2069    if (gc->o_container) evas_object_del(gc->o_container);
2070    eina_stringshare_del(gc->name);
2071    eina_stringshare_del(gc->edje.swallow_name);
2072    if (gc->edje.o_parent)
2073      evas_object_event_callback_del_full(gc->edje.o_parent, EVAS_CALLBACK_RESIZE,
2074                                    (Evas_Object_Event_Cb)_e_gadcon_parent_resize_cb, gc);
2075    if (gc->config_dialog) e_object_del(E_OBJECT(gc->config_dialog));
2076    if (gc->drop_handler) e_drop_handler_del(gc->drop_handler);
2077    if (gc->cfg_delete)
2078      {
2079         eina_stringshare_del(gc->cf->name);
2080         e_config->gadcons = eina_list_remove(e_config->gadcons, gc->cf);
2081         free(gc->cf);
2082         e_config_save_queue();
2083      }
2084    free(gc);
2085 }
2086 
2087 static void
_e_gadcon_client_event_free(void * d EINA_UNUSED,void * e)2088 _e_gadcon_client_event_free(void *d EINA_UNUSED, void *e)
2089 {
2090    E_Event_Gadcon_Client_Del *ev = e;
2091 
2092    e_object_unref(E_OBJECT(ev->gcc));
2093    free(ev);
2094 }
2095 
2096 static void
_e_gadcon_event_populate(E_Gadcon * gc)2097 _e_gadcon_event_populate(E_Gadcon *gc)
2098 {
2099    E_Event_Gadcon_Populate *ev;
2100 
2101    ev = E_NEW(E_Event_Gadcon_Populate, 1);
2102    e_object_ref(E_OBJECT(gc));
2103    ev->gc = gc;
2104    ecore_event_add(E_EVENT_GADCON_POPULATE, ev, _e_gadcon_event_populate_free, NULL);
2105 }
2106 
2107 static void
_e_gadcon_client_delfn(void * d EINA_UNUSED,void * o)2108 _e_gadcon_client_delfn(void *d EINA_UNUSED, void *o)
2109 {
2110    E_Gadcon_Client *gcc = o;
2111    E_Event_Gadcon_Client_Add *ev;
2112 
2113    if (gcc->instant_edit_timer)
2114      {
2115         ecore_timer_del(gcc->instant_edit_timer);
2116         gcc->instant_edit_timer = NULL;
2117      }
2118    if (gcc->o_base)
2119      evas_object_event_callback_del(gcc->o_base, EVAS_CALLBACK_DEL,
2120                                     _e_gadcon_client_del_hook);
2121    if (gcc->menu)
2122      {
2123         if (gcc->gadcon->shelf && (gcc->menu == gcc->gadcon->shelf->menu)) gcc->gadcon->shelf->menu = NULL;
2124         e_menu_post_deactivate_callback_set(gcc->menu, NULL, NULL);
2125         e_menu_deactivate(gcc->menu);
2126         e_object_del(E_OBJECT(gcc->menu));
2127         gcc->menu = NULL;
2128      }
2129    e_gadcon_client_edit_end(gcc);
2130    gcc->client_class->func.shutdown(gcc);
2131    if ((gcc->client_class->func.id_del) && (gcc->cf))
2132      gcc->client_class->func.id_del((E_Gadcon_Client_Class *)gcc->client_class,
2133                                     gcc->cf->id);
2134    if (gcc->drag.drag)
2135      e_object_del(E_OBJECT(gcc->drag.drag));
2136    gcc->gadcon->clients = eina_list_remove(gcc->gadcon->clients, gcc);
2137    E_FREE_FUNC(gcc->scroll_timer, ecore_timer_del);
2138    E_FREE_FUNC(gcc->scroll_animator, ecore_animator_del);
2139    E_FREE_FUNC(gcc->o_box, evas_object_del);
2140    E_FREE_FUNC(gcc->o_frame, evas_object_del);
2141    e_object_ref(E_OBJECT(gcc));
2142    ev = E_NEW(E_Event_Gadcon_Client_Del, 1);
2143    ev->gcc = gcc;
2144    ecore_event_add(E_EVENT_GADCON_CLIENT_DEL, ev, _e_gadcon_client_event_free, NULL);
2145 }
2146 
2147 static void
_e_gadcon_client_free(E_Gadcon_Client * gcc)2148 _e_gadcon_client_free(E_Gadcon_Client *gcc)
2149 {
2150    if (gcc->o_box) evas_object_del(gcc->o_box);
2151    if (gcc->o_frame) evas_object_del(gcc->o_frame);
2152    eina_stringshare_del(gcc->name);
2153    eina_stringshare_del(gcc->style);
2154    if (gcc->menu)
2155      {
2156         e_menu_deactivate(gcc->menu);
2157         e_object_del(E_OBJECT(gcc->menu));
2158      }
2159    free(gcc);
2160 }
2161 
2162 static void
_e_gadcon_moveresize_handle(E_Gadcon_Client * gcc)2163 _e_gadcon_moveresize_handle(E_Gadcon_Client *gcc)
2164 {
2165    int w, h, mw, mh;
2166 
2167    if (!gcc->o_base) return;
2168    evas_object_geometry_get(gcc->o_box, NULL, NULL, &w, &h);
2169    if (gcc->gadcon->edje.o_parent)
2170      evas_object_geometry_get(gcc->gadcon->edje.o_parent, NULL, NULL, &mw, &mh);
2171    else
2172      mw = w, mh = h;
2173    w = MIN(w, mw);
2174    h = MIN(h, mh);
2175 /*
2176    if (gcc->resizable)
2177      {
2178         if (elm_box_horizontal_get(gcc->o_box))
2179           {
2180              if ((gcc->aspect.w > 0) && (gcc->aspect.h > 0))
2181                w = (h * gcc->aspect.w) / gcc->aspect.h;
2182           }
2183         else
2184           {
2185              if ((gcc->aspect.w > 0) && (gcc->aspect.h > 0))
2186                h = (w * gcc->aspect.h) / gcc->aspect.w;
2187           }
2188      }
2189  */
2190    if (gcc->autoscroll)
2191      {
2192         if (elm_box_horizontal_get(gcc->o_box))
2193           {
2194              if ((gcc->aspect.w > 0) && (gcc->aspect.h > 0))
2195                {
2196                   w = (h * gcc->aspect.w) / gcc->aspect.h; // ZZZZ
2197 //                  w = gcc->min.w;
2198                }
2199              else
2200                {
2201                   w = gcc->min.w;
2202                }
2203           }
2204         else
2205           {
2206              if ((gcc->aspect.w > 0) && (gcc->aspect.h > 0))
2207                {
2208                   h = (w * gcc->aspect.h) / gcc->aspect.w; // ZZZZ
2209 //                  h = gcc->min.h;
2210                }
2211              else
2212                {
2213                   h = gcc->min.h;
2214                }
2215           }
2216      }
2217    evas_object_size_hint_min_set(gcc->o_base, w, h);
2218    evas_object_size_hint_max_set(gcc->o_base, mw, mh);
2219    _e_gadcon_client_scroll_state_update(gcc);
2220 }
2221 
2222 static void
_e_gadcon_parent_resize_cb(E_Gadcon * gc,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2223 _e_gadcon_parent_resize_cb(E_Gadcon *gc, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2224 {
2225    Eina_List *l;
2226    E_Gadcon_Client *gcc;
2227 
2228    EINA_LIST_FOREACH(gc->clients, l, gcc)
2229      _e_gadcon_moveresize_handle(gcc);
2230 }
2231 
2232 static Eina_Bool
_e_gadcon_cb_client_scroll_timer(void * data)2233 _e_gadcon_cb_client_scroll_timer(void *data)
2234 {
2235    E_Gadcon_Client *gcc;
2236    double d, v;
2237 
2238    gcc = data;
2239    d = gcc->scroll_wanted - gcc->scroll_pos;
2240    if (d < 0) d = -d;
2241    if (d < 0.001)
2242      {
2243         gcc->scroll_pos = gcc->scroll_wanted;
2244         gcc->scroll_timer = NULL;
2245         return ECORE_CALLBACK_CANCEL;
2246      }
2247    v = 0.05;
2248    gcc->scroll_pos = (gcc->scroll_pos * (1.0 - v)) + (gcc->scroll_wanted * v);
2249    return ECORE_CALLBACK_RENEW;
2250 }
2251 
2252 static void
_e_gadcon_client_scroll_state_update(E_Gadcon_Client * gcc)2253 _e_gadcon_client_scroll_state_update(E_Gadcon_Client *gcc)
2254 {
2255    Evas_Coord box_w, box_h, base_w, base_h;
2256 
2257    if (gcc->o_frame)
2258      {
2259         evas_object_geometry_get(gcc->o_box, NULL, NULL, &box_w, &box_h);
2260         evas_object_geometry_get(gcc->o_base, NULL, NULL, &base_w, &base_h);
2261 
2262         if (((elm_box_horizontal_get(gcc->o_box)) && (box_w >= base_w)) ||
2263             ((!elm_box_horizontal_get(gcc->o_box)) && (box_h >= base_h)))
2264           {
2265              if (gcc->pscrollstate != 0)
2266                {
2267                   edje_object_signal_emit(gcc->o_frame, "e,state,scroll,none", "e");
2268                   gcc->pscrollstate = 0;
2269                }
2270           }
2271         else if (gcc->scroll_pos <= 0.01)
2272           {
2273              if (gcc->pscrollstate != 1)
2274                {
2275                   edje_object_signal_emit(gcc->o_frame, "e,state,scroll,begin", "e");
2276                   gcc->pscrollstate = 1;
2277                }
2278           }
2279         else if (gcc->scroll_pos >= 0.99)
2280           {
2281              if (gcc->pscrollstate != 3)
2282                {
2283                   edje_object_signal_emit(gcc->o_frame, "e,state,scroll,end", "e");
2284                   gcc->pscrollstate = 3;
2285                }
2286           }
2287         else
2288           {
2289              if (gcc->pscrollstate != 2)
2290                {
2291                   edje_object_signal_emit(gcc->o_frame, "e,state,scroll,middle", "e");
2292                   gcc->pscrollstate = 2;
2293                }
2294           }
2295      }
2296 }
2297 
2298 static Eina_Bool
_e_gadcon_cb_client_scroll_animator(void * data)2299 _e_gadcon_cb_client_scroll_animator(void *data)
2300 {
2301    E_Gadcon_Client *gcc;
2302 
2303    gcc = data;
2304    if (elm_box_horizontal_get(gcc->o_box))
2305      elm_box_align_set(gcc->o_box, 1.0 - gcc->scroll_pos, 0.5);
2306    else
2307      elm_box_align_set(gcc->o_box, 0.5, 1.0 - gcc->scroll_pos);
2308    if (!gcc->scroll_timer)
2309      {
2310         gcc->scroll_animator = NULL;
2311         return ECORE_CALLBACK_CANCEL;
2312      }
2313 
2314    _e_gadcon_client_scroll_state_update(gcc);
2315 
2316    if (gcc->scroll_cb.func)
2317      gcc->scroll_cb.func(gcc->scroll_cb.data);
2318 
2319    return ECORE_CALLBACK_RENEW;
2320 }
2321 
2322 static void
_e_gadcon_cb_client_frame_mouse_move(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)2323 _e_gadcon_cb_client_frame_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
2324 {
2325    Evas_Event_Mouse_Move *ev;
2326    E_Gadcon_Client *gcc;
2327    Evas_Coord x, y;
2328 
2329    ev = event_info;
2330    gcc = data;
2331    evas_object_geometry_get(gcc->o_box, &x, &y, NULL, NULL);
2332    e_gadcon_client_autoscroll_update(gcc, ev->cur.output.x - x,
2333                                      ev->cur.output.y - y);
2334 }
2335 
2336 static void
_e_gadcon_cb_client_frame_moveresize(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2337 _e_gadcon_cb_client_frame_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2338 {
2339    E_Gadcon_Client *gcc;
2340 
2341    gcc = data;
2342    _e_gadcon_moveresize_handle(gcc);
2343 }
2344 
2345 static void
_e_gadcon_client_save(E_Gadcon_Client * gcc)2346 _e_gadcon_client_save(E_Gadcon_Client *gcc)
2347 {
2348    gcc->cf->geom.pos = gcc->config.pos;
2349    gcc->cf->geom.size = gcc->config.size;
2350    gcc->cf->geom.res = gcc->config.res;
2351    gcc->cf->geom.pos_x = gcc->config.pos_x;
2352    gcc->cf->geom.pos_y = gcc->config.pos_y;
2353    gcc->cf->geom.size_w = gcc->config.size_w;
2354    gcc->cf->geom.size_h = gcc->config.size_h;
2355    gcc->cf->state_info.seq = gcc->state_info.seq;
2356    gcc->cf->state_info.flags = gcc->state_info.flags;
2357    gcc->cf->autoscroll = gcc->autoscroll;
2358    eina_stringshare_replace(&gcc->cf->style, gcc->style);
2359 /*   gcc->cf->resizable = gcc->resizable;*/
2360    gcc->cf->resizable = 0;
2361    e_config_save_queue();
2362 }
2363 
2364 static void
_e_gadcon_client_drag_begin(E_Gadcon_Client * gcc,int x,int y)2365 _e_gadcon_client_drag_begin(E_Gadcon_Client *gcc, int x, int y)
2366 {
2367    E_Drag *drag;
2368    Evas_Object *o = NULL;
2369    Evas_Coord w = 0, h = 0;
2370    E_Zone *zone;
2371    const char *drag_types[] = { "enlightenment/gadcon_client" };
2372 
2373    zone = e_gadcon_zone_get(gcc->gadcon);
2374    if (gcc->gadcon->drag_gcc) return;
2375    if (!zone) return;
2376 
2377    if (!e_util_strcmp(gcc->client_class->name, "systray"))
2378      return;
2379 
2380    e_gadcon_client_drag_set(gcc);
2381 
2382    e_object_ref(E_OBJECT(gcc));
2383    /* Remove this config from the current gadcon */
2384    gcc->gadcon->cf->clients =
2385      eina_list_remove(gcc->gadcon->cf->clients, gcc->cf);
2386    gcc->state_info.state = E_LAYOUT_ITEM_STATE_NONE;
2387    gcc->state_info.resist = 0;
2388 
2389    if (!e_drop_inside(gcc->gadcon->drop_handler, x, y))
2390      e_gadcon_client_hide(gcc);
2391 
2392    ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
2393 
2394    gcc->drag.drag = drag = e_drag_new(x, y,
2395                                       drag_types, 1, gcc, -1, NULL,
2396                                       e_gadcon_drag_finished_cb);
2397    if (!drag) return;
2398    drag->button_mask = evas_pointer_button_down_mask_get(e_comp->evas);
2399 
2400    o = gcc->client_class->func.icon((E_Gadcon_Client_Class *)gcc->client_class,
2401                                     e_drag_evas_get(drag));
2402    if (o)
2403      evas_object_geometry_get(o, NULL, NULL, &w, &h);
2404    else
2405      {
2406         /* FIXME: fallback icon for drag */
2407         o = evas_object_rectangle_add(e_drag_evas_get(drag));
2408         evas_object_color_set(o, 255, 255, 255, 100);
2409      }
2410    if (w < 10)
2411      w = h = 50;
2412    e_drag_object_set(drag, o);
2413    e_drag_resize(drag, w, h);
2414    e_drag_start(drag, x + w / 2, y + h / 2);
2415    e_drag_hide(drag);
2416 }
2417 
2418 static void
_e_gadcon_client_inject(E_Gadcon * gc,E_Gadcon_Client * gcc,int x,int y)2419 _e_gadcon_client_inject(E_Gadcon *gc, E_Gadcon_Client *gcc, int x, int y)
2420 {
2421    Eina_List *l;
2422    E_Gadcon_Client *gcc2;
2423    Evas_Coord cx = 0, cy = 0, cw = 0, ch = 0;
2424    int i;
2425 
2426    /* Check if the gadcon client is in place */
2427    if (!gcc->hidden)
2428      {
2429         if (gcc->o_frame)
2430           evas_object_geometry_get(gcc->o_frame, &cx, &cy, &cw, &ch);
2431         else if (gcc->o_base)
2432           evas_object_geometry_get(gcc->o_base, &cx, &cy, &cw, &ch);
2433         else return;  /* make clang happy */
2434 
2435         if (E_INSIDE(x, y, cx, cy, cw, ch)) return;
2436      }
2437 
2438    /* If x, y is not inside any gadcon client, seq will be 0 and it's position
2439     * will later be used for placement. */
2440    gcc->state_info.seq = 0;
2441    for (i = 0; i < 2; i++)
2442      {
2443         /* two passes:
2444          * - find sequence position to inject
2445          * - update other gadget sequences
2446          */
2447         EINA_LIST_FOREACH(gc->clients, l, gcc2)
2448           {
2449              if (gcc == gcc2) continue;
2450              if (i == 1)
2451                {
2452                   /* on second pass, increment all sequence numbers which are
2453                    * >= the injected gadget's sequence to get ordering right
2454                    */
2455                   if (gcc2->state_info.seq >= gcc->state_info.seq)
2456                     gcc2->state_info.seq++;
2457                   continue;
2458                }
2459              if (gcc2->hidden) continue;
2460              if (gcc2->o_frame)
2461                evas_object_geometry_get(gcc2->o_frame, &cx, &cy, &cw, &ch);
2462              else if (gcc2->o_base)
2463                evas_object_geometry_get(gcc2->o_base, &cx, &cy, &cw, &ch);
2464              else return;  /* make clang happy */
2465              if (e_gadcon_layout_orientation_get(gc->o_container))
2466                {
2467                   /* inside left half of gadget */
2468                   if (E_INSIDE(x, y, cx, cy, cw / 2, ch))
2469                     {
2470                        /* place before */
2471                        gcc->state_info.seq = gcc2->state_info.seq;
2472                        break;
2473                     }
2474                   /* inside right half of gadget */
2475                   else if (E_INSIDE(x, y, cx + cw / 2, cy, cw / 2, ch))
2476                     {
2477                        /* place after */
2478                        gcc->state_info.seq = gcc2->state_info.seq + 1;
2479                        break;
2480                     }
2481                }
2482              else
2483                {
2484                   /* top half of gadget */
2485                   if (E_INSIDE(x, y, cx, cy, cw, ch / 2))
2486                     {
2487                        /* place before */
2488                        gcc->state_info.seq = gcc2->state_info.seq;
2489                        break;
2490                     }
2491                   /* bottom half of gadget */
2492                   else if (E_INSIDE(x, y, cx, cy + ch / 2, cw, ch / 2))
2493                     {
2494                        /* place after */
2495                        gcc->state_info.seq = gcc2->state_info.seq + 1;
2496                        break;
2497                     }
2498                }
2499           }
2500      }
2501 }
2502 
2503 static void
_e_gadcon_cb_min_size_request(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2504 _e_gadcon_cb_min_size_request(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2505 {
2506    E_Gadcon *gc;
2507 
2508    gc = data;
2509    if (gc->min_size_request.func)
2510      {
2511         Evas_Coord w = 0, h = 0;
2512 
2513         e_gadcon_layout_min_size_get(gc->o_container, &w, &h);
2514         gc->min_size_request.func(gc->min_size_request.data, gc, w, h);
2515      }
2516 }
2517 
2518 static void
_e_gadcon_cb_size_request(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2519 _e_gadcon_cb_size_request(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2520 {
2521    E_Gadcon *gc;
2522 
2523    gc = data;
2524    if (gc->resize_request.func)
2525      {
2526         Evas_Coord w = 0, h = 0;
2527 
2528         e_gadcon_layout_asked_size_get(gc->o_container, &w, &h);
2529         gc->resize_request.func(gc->resize_request.data, gc, w, h);
2530      }
2531 }
2532 
2533 static void
_e_gadcon_cb_show(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2534 _e_gadcon_cb_show(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2535 {
2536    E_Gadcon *gc = data;
2537    Eina_List *l;
2538    E_Gadcon_Client *gcc;
2539 
2540    EINA_LIST_FOREACH(gc->clients, l, gcc)
2541      evas_object_show(gcc->o_base ?: gcc->o_frame);
2542 }
2543 
2544 static void
_e_gadcon_cb_hide(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2545 _e_gadcon_cb_hide(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2546 {
2547    E_Gadcon *gc = data;
2548    Eina_List *l;
2549    E_Gadcon_Client *gcc;
2550 
2551    EINA_LIST_FOREACH(gc->clients, l, gcc)
2552      evas_object_hide(gcc->o_base ?: gcc->o_frame);
2553 }
2554 
2555 static void
_e_gadcon_cb_moveresize(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2556 _e_gadcon_cb_moveresize(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2557 {
2558    E_Gadcon *gc;
2559    Evas_Coord x, y, w, h;
2560 
2561    gc = data;
2562    evas_object_geometry_get(gc->o_container, &x, &y, &w, &h);
2563    if (gc->drop_handler)
2564      e_drop_handler_geometry_set(gc->drop_handler, x, y, w, h);
2565 }
2566 
2567 static void
_e_gadcon_cb_client_mouse_down(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)2568 _e_gadcon_cb_client_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
2569 {
2570    Evas_Event_Mouse_Down *ev;
2571    E_Gadcon_Client *gcc;
2572 
2573    gcc = data;
2574    ev = event_info;
2575    if (ev->button == 3)
2576      {
2577         E_Zone *zone;
2578         E_Menu *mn;
2579         E_Menu_Item *mi;
2580         int cx, cy;
2581 
2582         zone = e_zone_current_get();
2583 
2584         e_gadcon_locked_set(gcc->gadcon, 1);
2585         mn = e_menu_new();
2586         e_menu_post_deactivate_callback_set(mn, _e_gadcon_client_cb_menu_post,
2587                                             gcc);
2588         gcc->menu = mn;
2589 
2590         mi = e_menu_item_new(mn);
2591         e_menu_item_label_set(mi, _("Stop moving"));
2592         e_util_menu_item_theme_icon_set(mi, "enlightenment/edit");
2593         e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_edit, gcc);
2594 
2595         if (gcc->gadcon->menu_attach.func)
2596           {
2597              mi = e_menu_item_new(mn);
2598              e_menu_item_separator_set(mi, 1);
2599 
2600              gcc->gadcon->menu_attach.func(gcc->gadcon->menu_attach.data,
2601                                            gcc, mn);
2602              if (gcc->gadcon->shelf) e_shelf_locked_set(gcc->gadcon->shelf, 0);
2603           }
2604 
2605         if (gcc->gadcon->toolbar)
2606           ecore_evas_pointer_xy_get(e_comp->ee, &cx, &cy);
2607         else
2608           {
2609              e_gadcon_canvas_zone_geometry_get(gcc->gadcon, &cx, &cy, NULL, NULL);
2610              cx = cx + ev->output.x;
2611              cy = cy + ev->output.y;
2612           }
2613         e_menu_activate_mouse(mn, zone, cx, cy, 1, 1,
2614                               E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
2615      }
2616 }
2617 
2618 static void
_e_gadcon_cb_client_mouse_in(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2619 _e_gadcon_cb_client_mouse_in(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2620 {
2621    E_Gadcon_Client *gcc;
2622 
2623    gcc = data;
2624    edje_object_signal_emit(gcc->o_control, "e,state,focused", "e");
2625 }
2626 
2627 static void
_e_gadcon_cb_client_mouse_out(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2628 _e_gadcon_cb_client_mouse_out(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2629 {
2630    E_Gadcon_Client *gcc;
2631 
2632    gcc = data;
2633    edje_object_signal_emit(gcc->o_control, "e,state,unfocused", "e");
2634 }
2635 
2636 static void
_e_gadcon_cb_client_move(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2637 _e_gadcon_cb_client_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2638 {
2639    E_Gadcon_Client *gcc;
2640    Evas_Coord x, y;
2641 
2642    gcc = data;
2643    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
2644    if (gcc->o_control) evas_object_move(gcc->o_control, x, y);
2645    if (gcc->o_event) evas_object_move(gcc->o_event, x, y);
2646 }
2647 
2648 static void
_e_gadcon_cb_client_resize(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2649 _e_gadcon_cb_client_resize(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2650 {
2651    E_Gadcon_Client *gcc;
2652    Evas_Coord w, h;
2653 
2654    gcc = data;
2655    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
2656    if (gcc->o_control) evas_object_resize(gcc->o_control, w, h);
2657    if (gcc->o_event) evas_object_resize(gcc->o_event, w, h);
2658    _e_gadcon_client_scroll_state_update(gcc);
2659 }
2660 
2661 static void
_e_gadcon_client_move_start(E_Gadcon_Client * gcc)2662 _e_gadcon_client_move_start(E_Gadcon_Client *gcc)
2663 {
2664    int x, y, gy, gx;
2665 
2666    evas_object_raise(gcc->o_event);
2667    evas_object_stack_below(gcc->o_control, gcc->o_event);
2668    gcc->moving = 1;
2669    evas_object_geometry_get(gcc->gadcon->o_container, &gx, &gy, NULL, NULL);
2670    if (gcc->gadcon->toolbar)
2671      evas_pointer_canvas_xy_get(gcc->gadcon->evas, &gcc->dx, &gcc->dy);
2672    else
2673      {
2674         ecore_evas_pointer_xy_get(e_comp->ee, &gcc->dx, &gcc->dy);
2675         gcc->dx -= gx;
2676         gcc->dy -= gy;
2677      }
2678 
2679    if (gcc->o_frame)
2680      evas_object_geometry_get(gcc->o_frame, &x, &y, NULL, NULL);
2681    else if (gcc->o_base)
2682      evas_object_geometry_get(gcc->o_base, &x, &y, NULL, NULL);
2683    else
2684      return;
2685 
2686    /* using drag pos to calc offset between pointer and gcc pos */
2687    gcc->drag.x = x - (gcc->dx + gx);
2688    gcc->drag.y = y - (gcc->dy + gy);
2689 
2690    gcc->state_info.resist = 0;
2691 }
2692 
2693 static void
_e_gadcon_client_move_stop(E_Gadcon_Client * gcc)2694 _e_gadcon_client_move_stop(E_Gadcon_Client *gcc)
2695 {
2696    gcc->moving = 0;
2697    gcc->state_info.state = E_LAYOUT_ITEM_STATE_NONE;
2698    gcc->state_info.resist = 0;
2699    _e_gadcon_layout_smart_sync_clients(gcc->gadcon);
2700 }
2701 
2702 static void
_e_gadcon_client_move_go(E_Gadcon_Client * gcc)2703 _e_gadcon_client_move_go(E_Gadcon_Client *gcc)
2704 {
2705    Evas_Coord x, y, w, h;
2706    int cx, cy;
2707    int gx, gy, gw, gh;
2708    int changes = 0;
2709 
2710    if (!gcc->moving) return;
2711    /* we need to get output not canvas because things like systray
2712       can reparent another window so we get no position here */
2713    /* maybe we should better grab mouse while move resize is active...*/
2714    //evas_pointer_canvas_xy_get(gcc->gadcon->evas, &cx, &cy);
2715    if (gcc->gadcon->toolbar)
2716      evas_pointer_canvas_xy_get(gcc->gadcon->evas, &cx, &cy);
2717    else
2718      ecore_evas_pointer_xy_get(e_comp->ee, &cx, &cy);
2719 
2720    evas_object_geometry_get(gcc->gadcon->o_container, &gx, &gy, &gw, &gh);
2721 
2722    cx -= gx;
2723    cy -= gy;
2724 
2725    x = cx - gcc->dx;
2726    y = cy - gcc->dy;
2727 
2728    gcc->state_info.flags = E_GADCON_LAYOUT_ITEM_LOCK_POSITION | E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
2729    _e_gadcon_client_current_position_sync(gcc);
2730 
2731    if ((cy + e_config->drag_resist < 0 || cy - e_config->drag_resist >= gh) ||
2732        (cx + e_config->drag_resist < 0 || cx - e_config->drag_resist > gw))
2733      {
2734         _e_gadcon_client_drag_begin(gcc, cx, cy);
2735         return;
2736      }
2737 
2738    if (gcc->o_frame)
2739      evas_object_geometry_get(gcc->o_frame, NULL, NULL, &w, &h);
2740    else if (gcc->o_base)
2741      evas_object_geometry_get(gcc->o_base, NULL, NULL, &w, &h);
2742    else
2743      return;  /* make clang happy */
2744 
2745    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2746      {
2747         /* DRAG RIGHT */
2748         if (x > 0 && (cx + gcc->drag.x > gcc->config.pos))
2749           {
2750              if (gcc->state_info.state != E_LAYOUT_ITEM_STATE_POS_INC)
2751                gcc->state_info.resist = 0;
2752              gcc->state_info.state = E_LAYOUT_ITEM_STATE_POS_INC;
2753              changes = 1;
2754           }
2755         /* DRAG LEFT */
2756         else if (x < 0 && (cx + gcc->drag.x < gcc->config.pos))
2757           {
2758              if (gcc->state_info.state != E_LAYOUT_ITEM_STATE_POS_DEC)
2759                gcc->state_info.resist = 0;
2760              gcc->state_info.state = E_LAYOUT_ITEM_STATE_POS_DEC;
2761              changes = 1;
2762           }
2763 
2764         if (changes)
2765           {
2766              if (gcc->o_frame)
2767                e_gadcon_layout_pack_request_set(gcc->o_frame, cx + gcc->drag.x, w);
2768              else if (gcc->o_base)
2769                e_gadcon_layout_pack_request_set(gcc->o_base, cx + gcc->drag.x, w);
2770 
2771              gcc->config.size = w;
2772              evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2773              gcc->config.res = w;
2774           }
2775      }
2776    else
2777      {
2778         /* DRAG DOWN */
2779         if (y > 0 && (cy + gcc->drag.y > gcc->config.pos))
2780           {
2781              if (gcc->state_info.state != E_LAYOUT_ITEM_STATE_POS_INC)
2782                gcc->state_info.resist = 0;
2783              gcc->state_info.state = E_LAYOUT_ITEM_STATE_POS_INC;
2784              changes = 1;
2785           }
2786         /* DRAG UP */
2787         else if (y < 0 && (cy + gcc->drag.y < gcc->config.pos))
2788           {
2789              if (gcc->state_info.state != E_LAYOUT_ITEM_STATE_POS_DEC)
2790                gcc->state_info.resist = 0;
2791              gcc->state_info.state = E_LAYOUT_ITEM_STATE_POS_DEC;
2792              changes = 1;
2793           }
2794 
2795         if (changes)
2796           {
2797              if (gcc->o_frame)
2798                e_gadcon_layout_pack_request_set(gcc->o_frame, cy + gcc->drag.y, h);
2799              else if (gcc->o_base)
2800                e_gadcon_layout_pack_request_set(gcc->o_base, cy + gcc->drag.y, h);
2801 
2802              gcc->config.size = h;
2803              evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2804              gcc->config.res = h;
2805           }
2806      }
2807 
2808    gcc->dx += x;
2809    gcc->dy += y;
2810 }
2811 
2812 static void
_e_gadcon_cb_signal_move_start(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2813 _e_gadcon_cb_signal_move_start(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
2814 {
2815    _e_gadcon_client_move_start(data);
2816 }
2817 
2818 static void
_e_gadcon_cb_signal_move_stop(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2819 _e_gadcon_cb_signal_move_stop(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
2820 {
2821    _e_gadcon_client_move_stop(data);
2822 }
2823 
2824 static void
_e_gadcon_cb_signal_move_go(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2825 _e_gadcon_cb_signal_move_go(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
2826 {
2827    _e_gadcon_client_move_go(data);
2828 }
2829 
2830 static void
_e_gadcon_client_resize_start(E_Gadcon_Client * gcc)2831 _e_gadcon_client_resize_start(E_Gadcon_Client *gcc)
2832 {
2833    evas_object_raise(gcc->o_event);
2834    evas_object_stack_below(gcc->o_control, gcc->o_event);
2835    gcc->resizing = 1;
2836    evas_pointer_canvas_xy_get(gcc->gadcon->evas, &gcc->dx, &gcc->dy);
2837 }
2838 
2839 static void
_e_gadconclient_resize_stop(E_Gadcon_Client * gcc)2840 _e_gadconclient_resize_stop(E_Gadcon_Client *gcc)
2841 {
2842    gcc->resizing = 0;
2843    gcc->state_info.state = E_LAYOUT_ITEM_STATE_NONE;
2844    _e_gadcon_layout_smart_sync_clients(gcc->gadcon);
2845    _e_gadcon_client_save(gcc);
2846 }
2847 
2848 static void
_e_gadcon_cb_signal_resize_left_start(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2849 _e_gadcon_cb_signal_resize_left_start(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
2850 {
2851    _e_gadcon_client_resize_start(data);
2852 }
2853 
2854 static void
_e_gadcon_cb_signal_resize_left_stop(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2855 _e_gadcon_cb_signal_resize_left_stop(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
2856 {
2857    _e_gadconclient_resize_stop(data);
2858 }
2859 
2860 static void
_e_gadcon_cb_signal_resize_left_go(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2861 _e_gadcon_cb_signal_resize_left_go(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
2862 {
2863    E_Gadcon_Client *gcc;
2864    Evas_Coord x, y, w, h;
2865 
2866    gcc = data;
2867    if (!gcc->resizing) return;
2868    evas_pointer_canvas_xy_get(gcc->gadcon->evas, &x, &y);
2869    x = x - gcc->dx;
2870    y = y - gcc->dy;
2871 
2872    gcc->state_info.flags = E_GADCON_LAYOUT_ITEM_LOCK_POSITION |
2873      E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
2874 
2875    if (gcc->o_frame)
2876      evas_object_geometry_get(gcc->o_frame, NULL, NULL, &w, &h);
2877    else if (gcc->o_base)
2878      evas_object_geometry_get(gcc->o_base, NULL, NULL, &w, &h);
2879    else return;  /* make clang happy */
2880 
2881    _e_gadcon_client_current_position_sync(gcc);
2882 
2883    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2884      {
2885         if (x > 0)
2886           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC;
2887         else if (x < 0)
2888           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC;
2889      }
2890    else
2891      {
2892         if (y > 0)
2893           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC;
2894         else if (y < 0)
2895           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC;
2896      }
2897 
2898    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2899      {
2900         if (gcc->o_frame)
2901           e_gadcon_layout_pack_request_set(gcc->o_frame, gcc->config.pos + x, w - x);
2902         else if (gcc->o_base)
2903           e_gadcon_layout_pack_request_set(gcc->o_base, gcc->config.pos + x, w - x);
2904         evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2905         gcc->config.res = w;
2906      }
2907    else
2908      {
2909         if (gcc->o_frame)
2910           e_gadcon_layout_pack_request_set(gcc->o_frame, gcc->config.pos + y, h - y);
2911         else if (gcc->o_base)
2912           e_gadcon_layout_pack_request_set(gcc->o_base, gcc->config.pos + y, h - y);
2913         evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2914         gcc->config.res = h;
2915      }
2916    gcc->dx += x;
2917    gcc->dy += y;
2918 }
2919 
2920 static void
_e_gadcon_cb_signal_resize_right_start(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2921 _e_gadcon_cb_signal_resize_right_start(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
2922 {
2923    _e_gadcon_client_resize_start(data);
2924 }
2925 
2926 static void
_e_gadcon_cb_signal_resize_right_stop(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2927 _e_gadcon_cb_signal_resize_right_stop(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
2928 {
2929    _e_gadconclient_resize_stop(data);
2930 }
2931 
2932 static void
_e_gadcon_cb_signal_resize_right_go(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)2933 _e_gadcon_cb_signal_resize_right_go(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
2934 {
2935    E_Gadcon_Client *gcc;
2936    Evas_Coord x, y, w, h;
2937 
2938    gcc = data;
2939    if (!gcc->resizing) return;
2940    evas_pointer_canvas_xy_get(gcc->gadcon->evas, &x, &y);
2941    x = x - gcc->dx;
2942    y = y - gcc->dy;
2943 
2944    gcc->state_info.flags = E_GADCON_LAYOUT_ITEM_LOCK_POSITION |
2945      E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
2946 
2947    if (gcc->o_frame)
2948      evas_object_geometry_get(gcc->o_frame, NULL, NULL, &w, &h);
2949    else if (gcc->o_base)
2950      evas_object_geometry_get(gcc->o_base, NULL, NULL, &w, &h);
2951    else return;  /* make clang happy */
2952 
2953    _e_gadcon_client_current_position_sync(gcc);
2954 
2955    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2956      {
2957         if (x > 0)
2958           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC;
2959         else if (x < 0)
2960           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MAX_END_DEC;
2961      }
2962    else
2963      {
2964         if (y > 0)
2965           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC;
2966         else if (y < 0)
2967           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC;
2968      }
2969 
2970    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2971      {
2972         if (gcc->o_frame)
2973           e_gadcon_layout_pack_request_set(gcc->o_frame, gcc->config.pos, w + x);
2974         else if (gcc->o_base)
2975           e_gadcon_layout_pack_request_set(gcc->o_base, gcc->config.pos, w + x);
2976         evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2977         gcc->config.res = w;
2978      }
2979    else
2980      {
2981         if (gcc->o_frame)
2982           e_gadcon_layout_pack_request_set(gcc->o_frame, gcc->config.pos, h + y);
2983         else if (gcc->o_base)
2984           e_gadcon_layout_pack_request_set(gcc->o_base, gcc->config.pos, h + y);
2985         evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2986         gcc->config.res = h;
2987      }
2988    gcc->dx += x;
2989    gcc->dy += y;
2990 }
2991 
2992 static void
_e_gadcon_cb_dnd_enter(void * data,const char * type EINA_UNUSED,void * event)2993 _e_gadcon_cb_dnd_enter(void *data, const char *type EINA_UNUSED, void *event)
2994 {
2995    E_Event_Dnd_Enter *ev;
2996    E_Gadcon *gc;
2997    E_Gadcon_Client *gcc;
2998 
2999    ev = event;
3000    gc = data;
3001    //INF("DND ENTER");
3002    gcc = gc->drag_gcc;
3003    if (!gcc) return;  // dnd from efm or something
3004    if ((!gcc->hidden) && (gcc->gadcon == gc))
3005      {
3006         if (gc->dnd_enter_cb) gc->dnd_enter_cb(gc, gc->drag_gcc);
3007         e_drag_hide(gc->drag_gcc->drag.drag);
3008         return;
3009      }
3010    if (gcc->gadcon != gc)
3011      e_gadcon_client_hide(gc->drag_gcc);
3012    else if (e_gadcon_site_is_desktop(gcc->gadcon->location->site))
3013      {
3014         e_gadcon_client_show(gc->drag_gcc);
3015         e_drag_hide(gc->drag_gcc->drag.drag);
3016         if (gc->dnd_enter_cb) gc->dnd_enter_cb(gc, gc->drag_gcc);
3017         return;
3018      }
3019    e_gadcon_layout_freeze(gc->o_container);
3020 
3021    if (gc->new_gcc)
3022      {
3023         e_object_del(E_OBJECT(gc->new_gcc));
3024         gc->new_gcc = NULL;
3025      }
3026 
3027    while (ev->data)
3028      {
3029         /* Create a new gadcon to show where the gadcon will end up */
3030         E_Gadcon_Client_Class *cc;
3031 
3032         gcc = ev->data;
3033         cc = eina_hash_find(providers, gcc->name);
3034         if (!cc) break;
3035         if (!gcc->style)
3036           gc->new_gcc = cc->func.init(gc, gcc->name, gcc->cf->id,
3037                                       cc->default_style);
3038         else
3039           gc->new_gcc = cc->func.init(gc, gcc->name, gcc->cf->id,
3040                                       gcc->style);
3041 
3042         if (!gc->new_gcc) break;
3043         gc->new_gcc->cf = gcc->cf;
3044         gc->new_gcc->client_class = cc;
3045         gc->new_gcc->config.pos = gcc->config.pos;
3046         gc->new_gcc->config.size = gcc->config.size;
3047         gc->new_gcc->config.res = gcc->config.res;
3048         gc->new_gcc->state_info.seq = gcc->state_info.seq;
3049         gc->new_gcc->state_info.flags = gcc->state_info.flags;
3050         gc->new_gcc->config.pos_x = gcc->config.pos_x;
3051         gc->new_gcc->config.pos_y = gcc->config.pos_y;
3052         gc->new_gcc->config.size_w = gcc->config.size_w;
3053         gc->new_gcc->config.size_h = gcc->config.size_h;
3054         if (gc->new_gcc->client_class->func.orient)
3055           {
3056              if (gc->orient == E_GADCON_ORIENT_FLOAT)
3057                {
3058                   gc->new_gcc->client_class->func.orient(gc->new_gcc, gcc->gadcon->orient);
3059                   gc->new_gcc->cf->orient = gcc->gadcon->orient;
3060                }
3061              else
3062                {
3063                   gc->new_gcc->client_class->func.orient(gc->new_gcc, gc->orient);
3064                   gc->new_gcc->cf->orient = gc->orient;
3065                }
3066           }
3067         if (gc->new_gcc->o_frame)
3068           e_gadcon_layout_pack_options_set(gc->new_gcc->o_frame, gc->new_gcc);
3069         else if (gc->new_gcc->o_base)
3070           {
3071              e_gadcon_layout_pack_options_set(gc->new_gcc->o_base, gc->new_gcc);
3072              if (!gc->o_container)
3073                {
3074                   int w, h, gw, gh;
3075 
3076                   w = gc->zone->w;
3077                   h = gc->zone->h;
3078                   if ((!EINA_DBL_NONZERO(gc->new_gcc->config.pos_x)) && (!EINA_DBL_NONZERO(gc->new_gcc->config.pos_y)))
3079                     {
3080                        gc->new_gcc->config.pos_x = (double)ev->x / (double)w;
3081                        gc->new_gcc->config.pos_y = (double)ev->y / (double)h;
3082                     }
3083                   if ((!EINA_DBL_NONZERO(gc->new_gcc->config.size_w)) && (!EINA_DBL_NONZERO(gc->new_gcc->config.size_h)))
3084                     {
3085                        evas_object_geometry_get(gcc->o_frame ? : gcc->o_base, NULL, NULL, &gw, &gh);
3086                        gc->new_gcc->config.size_w = (double)gw / (double)w;
3087                        gc->new_gcc->config.size_h = (double)gh / (double)h;
3088                     }
3089                   else
3090                     {
3091                        gw = gc->new_gcc->config.size_w * w;
3092                        gh = gc->new_gcc->config.size_h * h;
3093                     }
3094                   evas_object_resize(gc->new_gcc->o_base, gw, gh);
3095                   evas_object_move(gc->new_gcc->o_base, ev->x, ev->y);
3096                }
3097           }
3098 
3099         e_drag_hide(gc->drag_gcc->drag.drag);
3100         e_gadcon_client_edit_begin(gc->new_gcc);
3101         e_gadcon_client_autoscroll_set(gc->new_gcc, gcc->autoscroll);
3102 /*		  e_gadcon_client_resizable_set(gc->new_gcc, gcc->resizable);*/
3103         gc->new_gcc->state_info.resist = 1;
3104         if (gc->instant_edit)
3105           e_gadcon_client_util_menu_attach(gc->new_gcc);
3106         break;
3107      }
3108    e_gadcon_layout_thaw(gc->o_container);
3109    if (gc->dnd_enter_cb) gc->dnd_enter_cb(gc, gc->drag_gcc);
3110 }
3111 
3112 static void
_e_gadcon_cb_dnd_move(void * data,const char * type EINA_UNUSED,void * event)3113 _e_gadcon_cb_dnd_move(void *data, const char *type EINA_UNUSED, void *event)
3114 {
3115    E_Event_Dnd_Move *ev;
3116    E_Gadcon *gc;
3117    E_Gadcon_Client *gcc = NULL;
3118    int dx = 0, dy = 0;
3119    Evas_Object *o;
3120 
3121    ev = event;
3122    gc = data;
3123    //INF("DND (%d,%d)", ev->x, ev->y);
3124    gcc = gc->new_gcc ? : gc->drag_gcc;
3125    if (!gcc) return;
3126 
3127    if (gcc->state_info.resist > 0)
3128      {
3129         gcc->state_info.resist--;
3130         return;
3131      }
3132    e_gadcon_layout_freeze(gc->o_container);
3133 
3134    if (e_gadcon_layout_orientation_get(gc->o_container))
3135      gcc->config.pos = ev->x - gcc->config.size / 2;
3136    else
3137      gcc->config.pos = ev->y - gcc->config.size / 2;
3138    if (!gcc->gadcon->o_container)
3139      {
3140         int w, h;
3141         w = gc->zone->w;
3142         h = gc->zone->h;
3143         gcc->config.pos_x = (double)ev->x / (double)w;
3144         gcc->config.pos_y = (double)ev->y / (double)h;
3145         if (gcc->o_frame) evas_object_move(gcc->o_frame, ev->x, ev->y);
3146         else if (gcc->o_base)
3147           evas_object_move(gcc->o_base, ev->x, ev->y);
3148      }
3149    _e_gadcon_client_inject(gc, gcc, ev->x + dx, ev->y + dy);
3150 
3151    o = gcc->o_frame ? gcc->o_frame : gcc->o_base;
3152    if (o)
3153      e_gadcon_layout_pack_request_set(o, gcc->config.pos,
3154                                       gcc->config.size);
3155    e_gadcon_layout_thaw(gc->o_container);
3156    if (gc->dnd_move_cb) gc->dnd_move_cb(gc, gcc);
3157 }
3158 
3159 static void
_e_gadcon_cb_dnd_leave(void * data,const char * type EINA_UNUSED,void * event EINA_UNUSED)3160 _e_gadcon_cb_dnd_leave(void *data, const char *type EINA_UNUSED, void *event EINA_UNUSED)
3161 {
3162    E_Gadcon *gc;
3163 
3164    gc = data;
3165    //INF("DND LEAVE");
3166 
3167    /* If we exit the starting container hide the gadcon visual */
3168    if (gc->drag_gcc->gadcon == gc) e_gadcon_client_hide(gc->drag_gcc);
3169 
3170    /* Delete temporary object */
3171    if (!gc->new_gcc)
3172      {
3173         if (gc->dnd_leave_cb) gc->dnd_leave_cb(gc, gc->drag_gcc);
3174         return;
3175      }
3176 
3177    //INF("DELETING new_gcc");
3178    e_object_del(E_OBJECT(gc->new_gcc));
3179    gc->new_gcc = NULL;
3180    e_drag_show(gc->drag_gcc->drag.drag);
3181    if (gc->dnd_leave_cb) gc->dnd_leave_cb(gc, gc->drag_gcc);
3182 }
3183 
3184 static void
_e_gadcon_cb_dnd_drop(void * data,const char * type EINA_UNUSED,void * event EINA_UNUSED)3185 _e_gadcon_cb_dnd_drop(void *data, const char *type EINA_UNUSED, void *event EINA_UNUSED)
3186 {
3187    E_Gadcon *gc;
3188    E_Gadcon_Client *gcc = NULL;
3189 
3190    gc = data;
3191    //INF("DND DROP");
3192    gc->cf->clients = eina_list_append(gc->cf->clients, gc->drag_gcc->cf);
3193    if (!gc->new_gcc)
3194      {
3195         /* using drag_gcc, so do things a bit differently
3196          * this only happens with gadman dnd, broken on shelves
3197          */
3198         _e_gadcon_client_save(gc->drag_gcc);
3199         e_gadcon_client_show(gc->drag_gcc);
3200         if (gc->dnd_drop_cb) gc->dnd_drop_cb(gc, gc->drag_gcc);
3201         return;
3202      }
3203 
3204    gcc = gc->new_gcc;
3205 
3206    if (!gc->o_container)
3207      {
3208         /* FIXME: gadman sucks and should probably use a regular gadcon layout, but it doesn't
3209          * so we need to repop here
3210          */
3211         gcc->cf = gc->drag_gcc->cf;
3212         _e_gadcon_client_save(gc->new_gcc);
3213         e_object_del(E_OBJECT(gc->new_gcc));
3214         gc->new_gcc = NULL;
3215         /* this little hack prevents the dead gcc from overwriting our config */
3216         gc->drag_gcc->moving = 0;
3217         e_gadcon_custom_populate_request(gc);
3218         e_config_save_queue();
3219         if (gc->dnd_drop_cb) gc->dnd_drop_cb(gc, gc->drag_gcc);
3220         goto cleanup;
3221      }
3222    if (gc->editing) e_gadcon_client_edit_begin(gc->new_gcc);
3223    gc->new_gcc = NULL;
3224    e_config_save_queue();
3225    if (gc->dnd_drop_cb) gc->dnd_drop_cb(gc, gc->drag_gcc);
3226 
3227 cleanup:
3228    /* still has refcount from drag */
3229    e_object_del(E_OBJECT(gc->drag_gcc));
3230    gc->drag_gcc = NULL;
3231 }
3232 
3233 static int
_e_gadcon_client_class_feature_check(const E_Gadcon_Client_Class * cc,const char * name,void * feature)3234 _e_gadcon_client_class_feature_check(const E_Gadcon_Client_Class *cc, const char *name, void *feature)
3235 {
3236    if (!feature)
3237      {
3238         e_util_dialog_show(_("Insufficient gadcon support"),
3239                            _("Module %s needs to support %s"),
3240                            cc->name, name);
3241         return 0;
3242      }
3243    return 1;
3244 }
3245 
3246 static void
_e_gadcon_client_cb_menu_post(void * data,E_Menu * m)3247 _e_gadcon_client_cb_menu_post(void *data, E_Menu *m)
3248 {
3249    E_Gadcon_Client *gcc;
3250 
3251    if (!(gcc = data)) return;
3252    if (gcc->gadcon) e_gadcon_locked_set(gcc->gadcon, 0);
3253    if (gcc->menu != m)
3254      {
3255         e_object_del(E_OBJECT(m));
3256         return;
3257      }
3258    if (gcc->gadcon && gcc->gadcon->shelf && (gcc->menu == gcc->gadcon->shelf->menu)) gcc->gadcon->shelf->menu = NULL;
3259    e_object_del(E_OBJECT(gcc->menu));
3260    gcc->menu = NULL;
3261 }
3262 
3263 static Eina_Bool
_e_gadcon_client_cb_instant_edit_timer(void * data)3264 _e_gadcon_client_cb_instant_edit_timer(void *data)
3265 {
3266    E_Gadcon_Client *gcc;
3267 
3268    gcc = data;
3269    e_gadcon_client_edit_begin(gcc);
3270    _e_gadcon_client_move_start(gcc);
3271    gcc->instant_edit_timer = NULL;
3272    return ECORE_CALLBACK_CANCEL;
3273 }
3274 
3275 static void
_e_gadcon_client_cb_mouse_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)3276 _e_gadcon_client_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
3277 {
3278    Evas_Event_Mouse_Down *ev;
3279    E_Gadcon_Client *gcc;
3280 
3281    ev = event_info;
3282    gcc = data;
3283    if (gcc->menu) return;
3284    if (ev->button == 3)
3285      {
3286         E_Menu *m;
3287         E_Zone *zone;
3288         int cx, cy, cw, ch;
3289 
3290         e_gadcon_locked_set(gcc->gadcon, 1);
3291         m = e_menu_new();
3292 
3293         m = e_gadcon_client_util_menu_items_append(gcc, m, 0);
3294         e_menu_post_deactivate_callback_set(m, _e_gadcon_client_cb_menu_post,
3295                                             gcc);
3296         gcc->menu = m;
3297         if (gcc->gadcon->shelf) gcc->gadcon->shelf->menu = m;
3298 
3299         e_gadcon_canvas_zone_geometry_get(gcc->gadcon, &cx, &cy, &cw, &ch);
3300         zone = gcc->gadcon->zone;
3301         if (!zone) zone = e_zone_current_get();
3302         e_menu_activate_mouse(m, zone,
3303                               cx + ev->output.x,
3304                               cy + ev->output.y, 1, 1,
3305                               E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
3306      }
3307    else if (ev->button == 2)
3308      {
3309         if (gcc->instant_edit_timer)
3310           ecore_timer_del(gcc->instant_edit_timer);
3311         gcc->instant_edit_timer = NULL;
3312         e_gadcon_client_edit_begin(gcc);
3313         _e_gadcon_client_move_start(gcc);
3314      }
3315    else if (ev->button == 1)
3316      {
3317         if ((!gcc->o_control) && (gcc->gadcon->instant_edit))
3318           {
3319              if (gcc->instant_edit_timer)
3320                ecore_timer_del(gcc->instant_edit_timer);
3321              gcc->instant_edit_timer =
3322                ecore_timer_loop_add(1.0, _e_gadcon_client_cb_instant_edit_timer,
3323                                gcc);
3324           }
3325      }
3326 }
3327 
3328 static void
_e_gadcon_client_cb_mouse_up(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)3329 _e_gadcon_client_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
3330 {
3331    Evas_Event_Mouse_Up *ev;
3332    E_Gadcon_Client *gcc;
3333 
3334    ev = event_info;
3335    gcc = data;
3336    if ((ev->button == 1) && (gcc->gadcon->instant_edit))
3337      {
3338         if (gcc->instant_edit_timer)
3339           {
3340              ecore_timer_del(gcc->instant_edit_timer);
3341              gcc->instant_edit_timer = NULL;
3342           }
3343         if (gcc->o_control)
3344           {
3345              _e_gadcon_client_move_stop(gcc);
3346              e_gadcon_client_edit_end(gcc);
3347           }
3348      }
3349    else if (ev->button == 2)
3350      {
3351         if (gcc->o_control)
3352           {
3353              _e_gadcon_client_move_stop(gcc);
3354              e_gadcon_client_edit_end(gcc);
3355           }
3356      }
3357 }
3358 
3359 static void
_e_gadcon_client_cb_mouse_move(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)3360 _e_gadcon_client_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
3361 {
3362    E_Gadcon_Client *gcc;
3363 
3364    gcc = data;
3365    if ((gcc->gadcon->instant_edit))
3366      {
3367         if (gcc->o_control) _e_gadcon_client_move_go(gcc);
3368      }
3369 }
3370 
3371 static void
_e_gadcon_client_cb_menu_style_plain(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)3372 _e_gadcon_client_cb_menu_style_plain(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
3373 {
3374    E_Gadcon_Client *gcc;
3375    E_Gadcon *gc;
3376 
3377    gcc = data;
3378    gc = gcc->gadcon;
3379    eina_stringshare_replace(&gcc->style, E_GADCON_CLIENT_STYLE_PLAIN);
3380    _e_gadcon_client_save(gcc);
3381    e_gadcon_unpopulate(gc);
3382    e_gadcon_populate(gc);
3383 }
3384 
3385 static void
_e_gadcon_client_cb_menu_style_inset(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)3386 _e_gadcon_client_cb_menu_style_inset(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
3387 {
3388    E_Gadcon_Client *gcc;
3389    E_Gadcon *gc;
3390 
3391    gcc = data;
3392    gc = gcc->gadcon;
3393    eina_stringshare_replace(&gcc->style, E_GADCON_CLIENT_STYLE_INSET);
3394    _e_gadcon_client_save(gcc);
3395    e_gadcon_unpopulate(gc);
3396    e_gadcon_populate(gc);
3397 }
3398 
3399 static void
_e_gadcon_client_cb_menu_autoscroll(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)3400 _e_gadcon_client_cb_menu_autoscroll(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
3401 {
3402    E_Gadcon_Client *gcc;
3403 
3404    gcc = data;
3405    e_gadcon_layout_freeze(gcc->gadcon->o_container);
3406    if (gcc->autoscroll) gcc->autoscroll = 0;
3407    else gcc->autoscroll = 1;
3408    e_gadcon_client_autoscroll_set(gcc, gcc->autoscroll);
3409    _e_gadcon_client_save(gcc);
3410    e_gadcon_layout_thaw(gcc->gadcon->o_container);
3411    if (gcc->autoscroll)
3412      _e_gadcon_client_scroll_state_update(gcc);
3413 }
3414 
3415 /*
3416    static void
3417    _e_gadcon_client_cb_menu_resizable(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
3418    {
3419    E_Gadcon_Client *gcc;
3420 
3421    gcc = data;
3422    e_gadcon_layout_freeze(gcc->gadcon->o_container);
3423    if (gcc->resizable) gcc->resizable = 0;
3424    else gcc->resizable = 1;
3425    e_gadcon_client_resizable_set(gcc, gcc->resizable);
3426    _e_gadcon_client_save(gcc);
3427    e_gadcon_layout_thaw(gcc->gadcon->o_container);
3428    }
3429  */
3430 static void
_e_gadcon_client_cb_menu_edit(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)3431 _e_gadcon_client_cb_menu_edit(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
3432 {
3433    E_Gadcon_Client *gcc;
3434 
3435    gcc = data;
3436    if (gcc->o_control)
3437      e_gadcon_client_edit_end(gcc);
3438    else
3439      e_gadcon_client_edit_begin(gcc);
3440 }
3441 
3442 static void
_e_gadcon_client_cb_menu_remove(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)3443 _e_gadcon_client_cb_menu_remove(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
3444 {
3445    E_Gadcon *gc;
3446    E_Gadcon_Client *gcc;
3447 
3448    gcc = data;
3449    gc = gcc->gadcon;
3450 
3451    e_gadcon_client_config_del(gc->cf, gcc->cf);
3452    gcc->cf = NULL;
3453    e_object_del(E_OBJECT(gcc));
3454    if (!gc->custom)
3455      {
3456         e_gadcon_unpopulate(gc);
3457         e_gadcon_populate(gc);
3458      }
3459    e_config_save_queue();
3460 }
3461 
3462 static void
_e_gadcon_client_cb_menu_pre(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi)3463 _e_gadcon_client_cb_menu_pre(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi)
3464 {
3465    E_Gadcon_Client *gcc;
3466 
3467    if (!(gcc = data)) return;
3468    if (gcc->client_class->func.icon)
3469      {
3470         // e menu ASSUMES... EXPECTS the icon to be an.... e_icon!
3471         // if it's not, spankies for whoever wrote the icon callback!
3472         mi->icon_object =
3473           gcc->client_class->func.icon((E_Gadcon_Client_Class *)gcc->client_class,
3474                                        mi->menu->evas);
3475      }
3476    else
3477      e_util_menu_item_theme_icon_set(mi, "preferences-gadget");  // FIXME: Needs icon in theme
3478 }
3479 
3480 static void
_e_gadcon_client_del_hook(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)3481 _e_gadcon_client_del_hook(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
3482 {
3483    E_Gadcon_Client *gcc;
3484 
3485    gcc = data;
3486    gcc->o_base = NULL;
3487    e_object_del(E_OBJECT(gcc));
3488 }
3489 
3490 /* a smart object JUST for gadcon */
3491 
3492 typedef struct _E_Gadcon_Layout_Item E_Gadcon_Layout_Item;
3493 
3494 struct _E_Smart_Data
3495 {
3496    Evas_Coord    x, y, w, h;
3497    Evas_Object  *obj, *clip;
3498    Eina_List    *items;
3499    Ecore_Job    *job;
3500    int           frozen;
3501    Evas_Coord    minw, minh, req;
3502    unsigned char horizontal E_BITFIELD;
3503    unsigned char doing_config E_BITFIELD;
3504    unsigned char redo_config E_BITFIELD;
3505 };
3506 
3507 struct _E_Gadcon_Layout_Item
3508 {
3509    E_Smart_Data    *sd;
3510    struct
3511    {
3512       int pos, size, size2, res, prev_pos, prev_size;
3513    } ask;
3514    int              hookp;
3515    struct
3516    {
3517       int w, h;
3518    } min, aspect, aspect_pad;
3519 
3520    E_Gadcon_Client *gcc;
3521 
3522    Evas_Coord       x, y, w, h;
3523    Evas_Object     *obj;
3524    unsigned char    can_move E_BITFIELD;
3525 };
3526 
3527 /* local subsystem functions */
3528 static E_Gadcon_Layout_Item *_e_gadcon_layout_smart_adopt(E_Smart_Data *sd, Evas_Object *obj);
3529 static void                  _e_gadcon_layout_smart_disown(Evas_Object *obj);
3530 static void                  _e_gadcon_layout_smart_item_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
3531 static void                  _e_gadcon_layout_smart_reconfigure(E_Smart_Data *sd);
3532 static void                  _e_gadcon_layout_smart_init(void);
3533 static void                  _e_gadcon_layout_smart_add(Evas_Object *obj);
3534 static void                  _e_gadcon_layout_smart_del(Evas_Object *obj);
3535 static void                  _e_gadcon_layout_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
3536 static void                  _e_gadcon_layout_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
3537 static void                  _e_gadcon_layout_smart_show(Evas_Object *obj);
3538 static void                  _e_gadcon_layout_smart_hide(Evas_Object *obj);
3539 static void                  _e_gadcon_layout_smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
3540 static void                  _e_gadcon_layout_smart_clip_set(Evas_Object *obj, Evas_Object *clip);
3541 static void                  _e_gadcon_layout_smart_clip_unset(Evas_Object *obj);
3542 static void                  _e_gadcon_layout_smart_min_cur_size_calc(E_Smart_Data *sd, int *min, int *mino, int *cur);
3543 static void                  _e_gadcon_layout_smart_gadcons_width_adjust(E_Smart_Data *sd, int min, int cur);
3544 static int                   _e_gadcon_layout_smart_sort_by_sequence_number_cb(const void *d1, const void *d2);
3545 static int                   _e_gadcon_layout_smart_sort_by_position_cb(const void *d1, const void *d2);
3546 
3547 /* local subsystem globals */
3548 static Evas_Smart *_e_smart = NULL;
3549 
3550 /* externally accessible functions */
3551 static Evas_Object *
e_gadcon_layout_add(Evas * evas)3552 e_gadcon_layout_add(Evas *evas)
3553 {
3554    _e_gadcon_layout_smart_init();
3555    return evas_object_smart_add(evas, _e_smart);
3556 }
3557 
3558 static void
e_gadcon_layout_orientation_set(Evas_Object * obj,int horizontal)3559 e_gadcon_layout_orientation_set(Evas_Object *obj, int horizontal)
3560 {
3561    E_Smart_Data *sd;
3562 
3563    if (!obj) return;
3564    sd = evas_object_smart_data_get(obj);
3565    if (!sd) return;
3566    if (((sd->horizontal) && (horizontal)) ||
3567        ((!sd->horizontal) && (!horizontal))) return;
3568    sd->horizontal = horizontal;
3569    _e_gadcon_layout_smart_reconfigure(sd);
3570 }
3571 
3572 static int
e_gadcon_layout_orientation_get(Evas_Object * obj)3573 e_gadcon_layout_orientation_get(Evas_Object *obj)
3574 {
3575    E_Smart_Data *sd;
3576 
3577    if (!obj) return 0;
3578    sd = evas_object_smart_data_get(obj);
3579    if (!sd) return 0;
3580    return sd->horizontal;
3581 }
3582 
3583 static void
e_gadcon_layout_freeze(Evas_Object * obj)3584 e_gadcon_layout_freeze(Evas_Object *obj)
3585 {
3586    E_Smart_Data *sd;
3587 
3588    if (!obj) return;
3589    sd = evas_object_smart_data_get(obj);
3590    if (!sd) return;
3591    sd->frozen++;
3592 }
3593 
3594 static void
e_gadcon_layout_thaw(Evas_Object * obj)3595 e_gadcon_layout_thaw(Evas_Object *obj)
3596 {
3597    E_Smart_Data *sd;
3598 
3599    if (!obj) return;
3600    sd = evas_object_smart_data_get(obj);
3601    if (!sd) return;
3602    sd->frozen--;
3603    _e_gadcon_layout_smart_reconfigure(sd);
3604 }
3605 
3606 static void
e_gadcon_layout_min_size_get(Evas_Object * obj,Evas_Coord * w,Evas_Coord * h)3607 e_gadcon_layout_min_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
3608 {
3609    E_Smart_Data *sd;
3610 /*
3611    Eina_List *l;
3612    Evas_Object *obj;
3613    Evas_Coord tw = 0, th = 0;
3614  */
3615    if (!obj) return;
3616    sd = evas_object_smart_data_get(obj);
3617    if (!sd) return;
3618    if (sd->horizontal)
3619      {
3620         if (w) *w = sd->minw;
3621         if (h) *h = sd->minh;
3622      }
3623    else
3624      {
3625         if (w) *w = sd->minh;
3626         if (h) *h = sd->minw;
3627      }
3628 
3629 /*
3630    EINA_LIST_FOREACH(sd->items, l, obj)
3631      {
3632         E_Gadcon_Layout_Item *bi;
3633 
3634         bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3635         if (sd->horizontal)
3636           {
3637              tw += bi->min.w;
3638              if (bi->min.h > th) th = bi->min.h;
3639           }
3640         else
3641           {
3642              th += bi->min.h;
3643              if (bi->min.w > tw) tw = bi->min.w;
3644           }
3645      }
3646    if (w) *w = tw;
3647    if (h) *h = th;
3648  */
3649 }
3650 
3651 static void
e_gadcon_layout_asked_size_get(Evas_Object * obj,Evas_Coord * w,Evas_Coord * h)3652 e_gadcon_layout_asked_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
3653 {
3654    E_Smart_Data *sd;
3655    Evas_Coord tw = 0, th = 0;
3656 
3657    if (!obj) return;
3658    sd = evas_object_smart_data_get(obj);
3659    if (!sd) return;
3660    if (sd->horizontal)
3661      tw = sd->req;
3662    else
3663      th = sd->req;
3664 /*
3665    Evas_Object *obj;
3666    EINA_LIST_FOREACH(sd->items, l, obj)
3667      {
3668         E_Gadcon_Layout_Item *bi;
3669 
3670         bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3671         if (sd->horizontal)
3672           {
3673              tw += bi->ask.size;
3674           }
3675         else
3676           {
3677              th += bi->ask.size;
3678           }
3679      }
3680  */
3681    if (w) *w = tw;
3682    if (h) *h = th;
3683 }
3684 
3685 static int
e_gadcon_layout_pack(Evas_Object * obj,Evas_Object * child)3686 e_gadcon_layout_pack(Evas_Object *obj, Evas_Object *child)
3687 {
3688    E_Smart_Data *sd;
3689 
3690    if (!obj) return 0;
3691    sd = evas_object_smart_data_get(obj);
3692    if (!sd) return 0;
3693    _e_gadcon_layout_smart_adopt(sd, child);
3694    sd->items = eina_list_prepend(sd->items, child);
3695    _e_gadcon_layout_smart_reconfigure(sd);
3696    return 0;
3697 }
3698 
3699 static void
e_gadcon_layout_pack_size_set(Evas_Object * obj,int size)3700 e_gadcon_layout_pack_size_set(Evas_Object *obj, int size)
3701 {
3702    /*
3703     * FIXME:
3704     * simplify this function until the is redone
3705     * _e_gadcon_layout_smart_gadcons_asked_position_set(E_Smart_Data *sd)
3706     */
3707    E_Gadcon_Layout_Item *bi;
3708    int pos;
3709 
3710    if (!obj) return;
3711    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3712    if (!bi) return;
3713    pos = bi->ask.pos + (bi->ask.size / 2);
3714    if (pos < (bi->ask.res / 3))
3715      {
3716         /* hooked to start */
3717         bi->ask.size = size;
3718      }
3719    else if (pos > ((2 * bi->ask.res) / 3))
3720      {
3721         /* hooked to end */
3722         bi->ask.pos = (bi->ask.pos + bi->ask.size) - size;
3723         bi->ask.size = size;
3724      }
3725    else
3726      {
3727         /* hooked to middle */
3728         if ((bi->ask.pos <= (bi->ask.res / 2)) &&
3729             ((bi->ask.pos + bi->ask.size) > (bi->ask.res / 2)))
3730           {
3731              /* straddles middle */
3732              if (bi->ask.res > 2)
3733                bi->ask.pos = (bi->ask.res / 2) +
3734                  (((bi->ask.pos + (bi->ask.size / 2) -
3735                     (bi->ask.res / 2)) *
3736                    (bi->ask.res / 2)) /
3737                   (bi->ask.res / 2)) - (bi->ask.size / 2);
3738              else
3739                bi->x = bi->ask.res / 2;
3740              bi->ask.size = size;
3741           }
3742         else
3743           {
3744              if (pos < (bi->ask.res / 2))
3745                {
3746                   bi->ask.pos = (bi->ask.pos + bi->ask.size) - size;
3747                   bi->ask.size = size;
3748                }
3749              else
3750                bi->ask.size = size;
3751           }
3752         bi->ask.size = size;
3753      }
3754    _e_gadcon_layout_smart_reconfigure(bi->sd);
3755 }
3756 
3757 /* called when a users moves/resizes the gadcon client explicitly */
3758 static void
e_gadcon_layout_pack_request_set(Evas_Object * obj,int pos,int size)3759 e_gadcon_layout_pack_request_set(Evas_Object *obj, int pos, int size)
3760 {
3761    E_Gadcon_Layout_Item *bi;
3762 
3763    if (!obj) return;
3764    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3765    if (!bi) return;
3766 
3767    bi->ask.res = bi->sd->w;
3768    if (pos < 0) pos = 0;
3769    if ((bi->ask.res - pos) < size) pos = bi->ask.res - size;
3770    bi->ask.size = size;
3771    bi->ask.pos = pos;
3772    _e_gadcon_layout_smart_reconfigure(bi->sd);
3773 }
3774 
3775 /* called when restoring config from saved config */
3776 static void
e_gadcon_layout_pack_options_set(Evas_Object * obj,E_Gadcon_Client * gcc)3777 e_gadcon_layout_pack_options_set(Evas_Object *obj, E_Gadcon_Client *gcc)
3778 {
3779    int ok, seq;
3780    Eina_List *l;
3781    Evas_Object *item;
3782    E_Gadcon_Layout_Item *bi, *bi2;
3783 
3784    if (!obj) return;
3785    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3786    if (!bi) return;
3787    bi->ask.res = gcc->config.res;
3788    bi->ask.size = gcc->config.size;
3789    bi->ask.pos = gcc->config.pos;
3790    bi->gcc = gcc;
3791 
3792    ok = 0;
3793    if (!gcc->state_info.seq) ok = 1;
3794 
3795    seq = 1;
3796    EINA_LIST_FOREACH(bi->sd->items, l, item)
3797      {
3798         bi2 = evas_object_data_get(item, "e_gadcon_layout_data");
3799         if (bi == bi2) continue;
3800         if (bi->gcc->id == bi2->gcc->id) continue;
3801         if (bi->gcc->state_info.seq == bi2->gcc->state_info.seq)
3802           ok = 1;
3803 
3804         if (bi2->gcc->state_info.seq > seq)
3805           seq = bi2->gcc->state_info.seq;
3806      }
3807 
3808    if (ok)
3809      {
3810         gcc->state_info.seq = seq + 1;
3811         gcc->state_info.want_save = 1;
3812         gcc->state_info.flags = E_GADCON_LAYOUT_ITEM_LOCK_NONE;
3813      }
3814    _e_gadcon_layout_smart_reconfigure(bi->sd);
3815 }
3816 
3817 static void
e_gadcon_layout_pack_min_size_set(Evas_Object * obj,int w,int h)3818 e_gadcon_layout_pack_min_size_set(Evas_Object *obj, int w, int h)
3819 {
3820    E_Gadcon_Layout_Item *bi;
3821 
3822    if (!obj) return;
3823    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3824    if (!bi)
3825      {
3826         evas_object_size_hint_min_set(obj, w, h);
3827         evas_object_size_hint_min_set(obj, w, h);
3828         return;
3829      }
3830    if (bi->sd->horizontal)
3831      {
3832         bi->min.w = w;
3833         bi->min.h = h;
3834      }
3835    else
3836      {
3837         bi->min.w = h;
3838         bi->min.h = w;
3839      }
3840 
3841    _e_gadcon_layout_smart_reconfigure(bi->sd);
3842 }
3843 
3844 static void
e_gadcon_layout_pack_aspect_set(Evas_Object * obj,int w,int h)3845 e_gadcon_layout_pack_aspect_set(Evas_Object *obj, int w, int h)
3846 {
3847    E_Gadcon_Layout_Item *bi;
3848 
3849    if (!obj) return;
3850    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3851    if (!bi)
3852      {
3853         evas_object_size_hint_aspect_set(obj, EVAS_ASPECT_CONTROL_BOTH, w, h);
3854         return;
3855      }
3856    if (bi->sd->horizontal)
3857      {
3858         bi->aspect.w = w;
3859         bi->aspect.h = h;
3860      }
3861    else
3862      {
3863         bi->aspect.w = h;
3864         bi->aspect.h = w;
3865      }
3866 
3867    _e_gadcon_layout_smart_reconfigure(bi->sd);
3868 }
3869 
3870 static void
e_gadcon_layout_pack_aspect_pad_set(Evas_Object * obj,int w,int h)3871 e_gadcon_layout_pack_aspect_pad_set(Evas_Object *obj, int w, int h)
3872 {
3873    E_Gadcon_Layout_Item *bi;
3874 
3875    if (!obj) return;
3876    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3877    if (!bi) return;
3878    if (bi->sd->horizontal)
3879      {
3880         bi->aspect_pad.w = w;
3881         bi->aspect_pad.h = h;
3882      }
3883    else
3884      {
3885         bi->aspect_pad.w = h;
3886         bi->aspect_pad.h = w;
3887      }
3888 }
3889 
3890 static void
e_gadcon_layout_unpack(Evas_Object * obj)3891 e_gadcon_layout_unpack(Evas_Object *obj)
3892 {
3893    E_Gadcon_Layout_Item *bi;
3894    E_Smart_Data *sd;
3895 
3896    if (!obj) return;
3897    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3898    if (!bi) return;
3899    sd = bi->sd;
3900    if (!sd) return;
3901    sd->items = eina_list_remove(sd->items, obj);
3902    _e_gadcon_layout_smart_disown(obj);
3903    if (!stopping)
3904      _e_gadcon_layout_smart_reconfigure(sd);
3905 }
3906 
3907 /* local subsystem functions */
3908 static E_Gadcon_Layout_Item *
_e_gadcon_layout_smart_adopt(E_Smart_Data * sd,Evas_Object * obj)3909 _e_gadcon_layout_smart_adopt(E_Smart_Data *sd, Evas_Object *obj)
3910 {
3911    E_Gadcon_Layout_Item *bi;
3912 
3913    if (!obj) return NULL;
3914    bi = E_NEW(E_Gadcon_Layout_Item, 1);
3915    if (!bi) return NULL;
3916    bi->sd = sd;
3917    bi->obj = obj;
3918    /* defaults */
3919    evas_object_clip_set(obj, sd->clip);
3920    evas_object_smart_member_add(obj, bi->sd->obj);
3921    evas_object_data_set(obj, "e_gadcon_layout_data", bi);
3922    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
3923                                   _e_gadcon_layout_smart_item_del_hook, NULL);
3924    if ((!evas_object_visible_get(sd->clip)) &&
3925        (evas_object_visible_get(sd->obj)))
3926      evas_object_show(sd->clip);
3927    return bi;
3928 }
3929 
3930 static void
_e_gadcon_layout_smart_disown(Evas_Object * obj)3931 _e_gadcon_layout_smart_disown(Evas_Object *obj)
3932 {
3933    E_Gadcon_Layout_Item *bi;
3934 
3935    if (!obj) return;
3936    bi = evas_object_data_del(obj, "e_gadcon_layout_data");
3937    if (!bi) return;
3938    if (!bi->sd->items)
3939      {
3940         if (evas_object_visible_get(bi->sd->clip))
3941           evas_object_hide(bi->sd->clip);
3942      }
3943    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
3944                                   _e_gadcon_layout_smart_item_del_hook);
3945    evas_object_smart_member_del(obj);
3946    evas_object_clip_unset(obj);
3947    free(bi);
3948 }
3949 
3950 static void
_e_gadcon_layout_smart_item_del_hook(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)3951 _e_gadcon_layout_smart_item_del_hook(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
3952 {
3953    if (!obj) return;
3954    e_gadcon_layout_unpack(obj);
3955 }
3956 
3957 static void
_e_gadcon_layout_smart_reconfigure(E_Smart_Data * sd)3958 _e_gadcon_layout_smart_reconfigure(E_Smart_Data *sd)
3959 {
3960    Evas_Coord xx, yy;
3961    Eina_List *l;
3962    Evas_Object *obj;
3963    int min, mino, cur;
3964    Eina_List *list = NULL;
3965    E_Gadcon_Layout_Item *bi;
3966    E_Layout_Item_Container *lc;
3967    int i, set_prev_pos = 0;
3968    static int recurse = 0;
3969 
3970    if (sd->frozen) return;
3971    if (sd->doing_config)
3972      {
3973         sd->redo_config = 1;
3974         return;
3975      }
3976 
3977    recurse++;
3978    min = mino = cur = 0;
3979 
3980    _e_gadcon_layout_smart_min_cur_size_calc(sd, &min, &mino, &cur);
3981 
3982    if ((sd->minw != min) || (sd->minh != mino))
3983      {
3984         sd->minw = min;
3985         sd->minh = mino;
3986         evas_object_smart_callback_call(sd->obj, "min_size_request", NULL);
3987      }
3988 
3989    if (sd->req != cur)
3990      {
3991         if (cur >= sd->minw)
3992           {
3993              sd->req = cur;
3994              evas_object_smart_callback_call(sd->obj, "size_request", NULL);
3995           }
3996         else
3997           {
3998              sd->req = sd->minw;
3999           }
4000      }
4001    if (recurse == 1) _e_gadcon_layout_smart_gadcons_width_adjust(sd, min, cur);
4002 
4003    if (sd->w <= sd->req)
4004      {
4005         _e_gadcon_layout_smart_gadcon_position_shrinked_mode(sd);
4006         set_prev_pos = 0;
4007      }
4008    else
4009      {
4010         _e_gadcon_layout_smart_gadcons_asked_position_set(sd);
4011 
4012         list = _e_gadcon_layout_smart_gadcons_wrap(sd);
4013 
4014         _e_gadcon_layout_smart_gadcons_position(sd, &list);
4015 
4016         EINA_LIST_FREE(list, lc)
4017           LC_FREE(lc);
4018 
4019         set_prev_pos = 1;
4020      }
4021 
4022    sd->items = eina_list_sort(sd->items, eina_list_count(sd->items),
4023                               _e_gadcon_layout_smart_sort_by_position_cb);
4024    i = 1;
4025    EINA_LIST_FOREACH(sd->items, l, obj)
4026      {
4027         bi = evas_object_data_get(obj, "e_gadcon_layout_data");
4028         if (bi->gcc->gadcon->editing) bi->gcc->state_info.seq = i;
4029 
4030         if (set_prev_pos)
4031           {
4032              bi->ask.prev_pos = bi->x;
4033              bi->ask.prev_size = bi->w;
4034           }
4035 
4036         if ((bi->x == bi->ask.pos) &&
4037             (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION))
4038           bi->gcc->state_info.flags |= E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
4039 
4040         if ((bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION) &&
4041             (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE))
4042           {
4043              if (bi->x != bi->ask.pos)
4044                bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
4045           }
4046         i++;
4047      }
4048 
4049    EINA_LIST_FOREACH(sd->items, l, obj)
4050      {
4051         bi = evas_object_data_get(obj, "e_gadcon_layout_data");
4052         if (!bi) continue;
4053 
4054         bi->h = sd->h;
4055         xx = sd->x + bi->x;
4056         yy = sd->y; // + ((sd->h - bi->h) / 2);
4057 
4058         if (sd->horizontal)
4059           {
4060              evas_object_move(obj, xx, yy);
4061              evas_object_resize(obj, bi->w, bi->h);
4062           }
4063         else
4064           {
4065              evas_object_move(obj, yy, xx);
4066              evas_object_resize(obj, bi->h, bi->w);
4067           }
4068         if ((recurse == 1) && bi->gcc->state_info.want_save)
4069           {
4070              _e_gadcon_client_save(bi->gcc);
4071              bi->gcc->state_info.want_save = 0;
4072           }
4073      }
4074    sd->doing_config = 0;
4075    if (sd->redo_config)
4076      {
4077         _e_gadcon_layout_smart_reconfigure(sd);
4078         sd->redo_config = 0;
4079      }
4080 
4081    if ((sd->minw != min) || (sd->minh != mino))
4082      {
4083         sd->minw = min;
4084         sd->minh = mino;
4085         evas_object_smart_callback_call(sd->obj, "min_size_request", NULL);
4086      }
4087 
4088    if (sd->req != cur)
4089      {
4090         if (cur >= sd->minw)
4091           {
4092              sd->req = cur;
4093              evas_object_smart_callback_call(sd->obj, "size_request", NULL);
4094           }
4095      }
4096    recurse--;
4097 }
4098 
4099 static void
_e_gadcon_layout_smart_init(void)4100 _e_gadcon_layout_smart_init(void)
4101 {
4102    if (_e_smart) return;
4103    {
4104       static const Evas_Smart_Class sc =
4105       {
4106          "e_gadcon_layout",
4107          EVAS_SMART_CLASS_VERSION,
4108          _e_gadcon_layout_smart_add,
4109          _e_gadcon_layout_smart_del,
4110          _e_gadcon_layout_smart_move,
4111          _e_gadcon_layout_smart_resize,
4112          _e_gadcon_layout_smart_show,
4113          _e_gadcon_layout_smart_hide,
4114          _e_gadcon_layout_smart_color_set,
4115          _e_gadcon_layout_smart_clip_set,
4116          _e_gadcon_layout_smart_clip_unset,
4117          NULL, NULL, NULL, NULL, NULL, NULL, NULL
4118       };
4119       _e_smart = evas_smart_class_new(&sc);
4120    }
4121 }
4122 
4123 static void
_e_gadcon_layout_smart_add(Evas_Object * obj)4124 _e_gadcon_layout_smart_add(Evas_Object *obj)
4125 {
4126    E_Smart_Data *sd;
4127 
4128    if (!obj) return;
4129    sd = calloc(1, sizeof(E_Smart_Data));
4130    if (!sd) return;
4131    sd->obj = obj;
4132    sd->x = 0;
4133    sd->y = 0;
4134    sd->w = 0;
4135    sd->h = 0;
4136    sd->clip = evas_object_rectangle_add(evas_object_evas_get(obj));
4137    sd->horizontal = 1;
4138    evas_object_smart_member_add(sd->clip, obj);
4139    evas_object_move(sd->clip, -100005, -100005);
4140    evas_object_resize(sd->clip, 200010, 200010);
4141    evas_object_color_set(sd->clip, 255, 255, 255, 255);
4142    evas_object_smart_data_set(obj, sd);
4143 }
4144 
4145 static void
_e_gadcon_layout_smart_del(Evas_Object * obj)4146 _e_gadcon_layout_smart_del(Evas_Object *obj)
4147 {
4148    E_Smart_Data *sd;
4149 
4150    if (!obj) return;
4151    sd = evas_object_smart_data_get(obj);
4152    if (!sd) return;
4153    while (sd->items)
4154      {
4155         Evas_Object *child;
4156 
4157         child = eina_list_data_get(sd->items);
4158         e_gadcon_layout_unpack(child);
4159      }
4160    if (sd->job) ecore_job_del(sd->job);
4161    sd->job = NULL;
4162    evas_object_del(sd->clip);
4163    free(sd);
4164    evas_object_smart_data_set(obj, NULL);
4165 }
4166 
4167 static void
_e_gadcon_layout_smart_move(Evas_Object * obj,Evas_Coord x,Evas_Coord y)4168 _e_gadcon_layout_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
4169 {
4170    E_Smart_Data *sd;
4171 
4172    if (!obj) return;
4173    sd = evas_object_smart_data_get(obj);
4174    if (!sd) return;
4175    if ((x == sd->x) && (y == sd->y)) return;
4176    {
4177       Eina_List *l;
4178       Evas_Object *item;
4179       Evas_Coord dx, dy;
4180 
4181       if (sd->horizontal)
4182         {
4183            dx = x - sd->x;
4184            dy = y - sd->y;
4185         }
4186       else
4187         {
4188            dx = x - sd->y;
4189            dy = y - sd->x;
4190         }
4191 
4192       EINA_LIST_FOREACH(sd->items, l, item)
4193         {
4194            Evas_Coord ox, oy;
4195 
4196            evas_object_geometry_get(item, &ox, &oy, NULL, NULL);
4197            evas_object_move(item, ox + dx, oy + dy);
4198         }
4199    }
4200 
4201    if (sd->horizontal)
4202      {
4203         sd->x = x;
4204         sd->y = y;
4205      }
4206    else
4207      {
4208         sd->x = y;
4209         sd->y = x;
4210      }
4211 }
4212 
4213 static void
_resize_job_cb(void * data)4214 _resize_job_cb(void *data)
4215 {
4216    E_Smart_Data *sd = evas_object_smart_data_get(data);
4217    if (!sd) return;
4218    sd->job = NULL;
4219    _e_gadcon_layout_smart_reconfigure(sd);
4220 }
4221 
4222 static void
_e_gadcon_layout_smart_resize(Evas_Object * obj,Evas_Coord w,Evas_Coord h)4223 _e_gadcon_layout_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
4224 {
4225    E_Smart_Data *sd;
4226 
4227    if (!obj) return;
4228    sd = evas_object_smart_data_get(obj);
4229    if (!sd) return;
4230    if ((w == sd->w) && (h == sd->h)) return;
4231    if (sd->horizontal)
4232      {
4233         sd->w = w;
4234         sd->h = h;
4235      }
4236    else
4237      {
4238         sd->w = h;
4239         sd->h = w;
4240      }
4241 
4242    if (sd->job) ecore_job_del(sd->job);
4243    sd->job = ecore_job_add(_resize_job_cb, obj);
4244 // done in job...
4245 //   _e_gadcon_layout_smart_reconfigure(sd);
4246 }
4247 
4248 static void
_e_gadcon_layout_smart_show(Evas_Object * obj)4249 _e_gadcon_layout_smart_show(Evas_Object *obj)
4250 {
4251    E_Smart_Data *sd;
4252 
4253    if (!obj) return;
4254    sd = evas_object_smart_data_get(obj);
4255    if (!sd) return;
4256    if (sd->items) evas_object_show(sd->clip);
4257 }
4258 
4259 static void
_e_gadcon_layout_smart_hide(Evas_Object * obj)4260 _e_gadcon_layout_smart_hide(Evas_Object *obj)
4261 {
4262    E_Smart_Data *sd;
4263 
4264    if (!obj) return;
4265    sd = evas_object_smart_data_get(obj);
4266    if (!sd) return;
4267    evas_object_hide(sd->clip);
4268 }
4269 
4270 static void
_e_gadcon_layout_smart_color_set(Evas_Object * obj,int r,int g,int b,int a)4271 _e_gadcon_layout_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
4272 {
4273    E_Smart_Data *sd;
4274 
4275    if (!obj) return;
4276    sd = evas_object_smart_data_get(obj);
4277    if (!sd) return;
4278    evas_object_color_set(sd->clip, r, g, b, a);
4279 }
4280 
4281 static void
_e_gadcon_layout_smart_clip_set(Evas_Object * obj,Evas_Object * clip)4282 _e_gadcon_layout_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
4283 {
4284    E_Smart_Data *sd;
4285 
4286    if (!obj) return;
4287    sd = evas_object_smart_data_get(obj);
4288    if (!sd) return;
4289    evas_object_clip_set(sd->clip, clip);
4290 }
4291 
4292 static void
_e_gadcon_layout_smart_clip_unset(Evas_Object * obj)4293 _e_gadcon_layout_smart_clip_unset(Evas_Object *obj)
4294 {
4295    E_Smart_Data *sd;
4296 
4297    if (!obj) return;
4298    sd = evas_object_smart_data_get(obj);
4299    if (!sd) return;
4300    evas_object_clip_unset(sd->clip);
4301 }
4302 
4303 /*
4304  * @min - the minimum width required by all the gadcons
4305  * @cur - the current width required by all the gadcons
4306  * @mino - the smalest width/height among all the objects
4307  */
4308 static void
_e_gadcon_layout_smart_min_cur_size_calc(E_Smart_Data * sd,int * min,int * mino,int * cur)4309 _e_gadcon_layout_smart_min_cur_size_calc(E_Smart_Data *sd, int *min, int *mino, int *cur)
4310 {
4311    E_Gadcon_Layout_Item *bi;
4312    Eina_List *l;
4313    Evas_Object *item;
4314 
4315    EINA_LIST_FOREACH(sd->items, l, item)
4316      {
4317         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4318         bi->ask.size2 = bi->ask.size;
4319 
4320         if ((bi->aspect.w > 0) && (bi->aspect.h > 0))
4321           {
4322              bi->ask.size2 =
4323                (((sd->h - bi->aspect_pad.h) * bi->aspect.w) / bi->aspect.h) + bi->aspect_pad.w;
4324 
4325              if (bi->ask.size2 > bi->min.w)
4326                {
4327                   *min += bi->ask.size2;
4328                   *cur += bi->ask.size2;
4329                }
4330              else
4331                {
4332                   *min += bi->min.w;
4333                   *cur += bi->min.w;
4334                }
4335           }
4336         else
4337           {
4338              bi->ask.size2 = bi->ask.size = bi->min.w;
4339              *min += bi->min.w;
4340              if (bi->min.h > *mino) *mino = bi->min.h;
4341              if (bi->ask.size < bi->min.w)
4342                *cur += bi->min.w;
4343              else
4344                *cur += bi->ask.size;
4345           }
4346      }
4347 }
4348 
4349 static int
_e_gadcon_layout_smart_width_smart_sort_reverse_cb(const void * d1,const void * d2)4350 _e_gadcon_layout_smart_width_smart_sort_reverse_cb(const void *d1, const void *d2)
4351 {
4352    const E_Gadcon_Layout_Item *bi, *bi2;
4353 
4354    bi = evas_object_data_get(d1, "e_gadcon_layout_data");
4355    bi2 = evas_object_data_get(d2, "e_gadcon_layout_data");
4356 
4357    if (bi->ask.size2 > bi->min.w)
4358      {
4359         if (bi2->ask.size2 > bi2->min.w)
4360           {
4361              if (bi->ask.size2 < bi2->ask.size2)
4362                return 1;
4363              else
4364                return -1;
4365           }
4366         else
4367           {
4368              if (bi->ask.size2 == bi2->ask.size2)
4369                return -1;
4370              else
4371                {
4372                   if (bi->ask.size2 < bi2->ask.size2)
4373                     return 1;
4374                   else
4375                     return -1;
4376                }
4377           }
4378      }
4379    else
4380      {
4381         if (bi2->ask.size2 > bi2->min.w)
4382           {
4383              if (bi->ask.size2 == bi2->ask.size2)
4384                return 1;
4385              else
4386                {
4387                   if (bi->ask.size2 < bi2->ask.size2)
4388                     return 1;
4389                   else
4390                     return -1;
4391                }
4392           }
4393         else
4394           {
4395              if (bi->ask.size2 < bi2->ask.size2)
4396                return 1;
4397              else if (bi->ask.size2 > bi2->ask.size2)
4398                return -1;
4399           }
4400      }
4401 
4402    return 0;
4403 }
4404 
4405 static void
_e_gadcon_layout_smart_gadcons_width_adjust(E_Smart_Data * sd,int min,int cur)4406 _e_gadcon_layout_smart_gadcons_width_adjust(E_Smart_Data *sd, int min, int cur)
4407 {
4408    E_Gadcon_Layout_Item *bi = NULL;
4409    Eina_List *l, *l2;
4410    Evas_Object *item;
4411    int needed = 0;
4412    int need = 0;
4413    int max_size, autosize = 0;
4414 
4415    if (sd->w < cur)
4416      {
4417         if (sd->w < min) max_size = min;
4418         else max_size = cur;
4419         need = max_size - sd->w;
4420      }
4421    else
4422      return;
4423 
4424    sd->items = eina_list_sort(sd->items, eina_list_count(sd->items),
4425                               _e_gadcon_layout_smart_width_smart_sort_reverse_cb);
4426    EINA_LIST_FOREACH(sd->items, l, item)
4427      {
4428         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4429         if (bi->gcc->autoscroll) autosize += bi->ask.size2;
4430      }
4431 
4432    if (autosize < 1) autosize = 1;
4433    while (need > 0)
4434      {
4435         needed = need;
4436         EINA_LIST_REVERSE_FOREACH(sd->items, l2, item)
4437           {
4438              if (need <= 0) break;
4439              bi = evas_object_data_get(item, "e_gadcon_layout_data");
4440              if (bi->gcc->autoscroll)
4441                {
4442                   int reduce_by;
4443 
4444                   reduce_by = (need * bi->ask.size2) / autosize;
4445                   if (reduce_by < 1) reduce_by = 1;
4446                   if (bi->ask.size2 - reduce_by > 8)
4447                     {
4448                        bi->ask.size2 -= reduce_by;
4449                        need -= reduce_by;
4450                     }
4451                   else
4452                     {
4453                        need -= bi->ask.size2 - 8;
4454                        bi->ask.size2 = 8;
4455                     }
4456                }
4457           }
4458         /* If the 'needed' size change didn't get modified (no gadget has autoscroll)
4459            then we must break or we end up in an infinite loop */
4460         if (need == needed) break;
4461      }
4462 }
4463 
4464 static int
_e_gadcon_layout_smart_sort_by_sequence_number_cb(const void * d1,const void * d2)4465 _e_gadcon_layout_smart_sort_by_sequence_number_cb(const void *d1, const void *d2)
4466 {
4467    const E_Gadcon_Layout_Item *bi, *bi2;
4468 
4469    bi = evas_object_data_get(d1, "e_gadcon_layout_data");
4470    bi2 = evas_object_data_get(d2, "e_gadcon_layout_data");
4471 
4472    if ((!bi->gcc->state_info.seq) && (!bi2->gcc->state_info.seq)) return 0;
4473    else if (!bi->gcc->state_info.seq)
4474      return 1;
4475    else if (!bi2->gcc->state_info.seq)
4476      return -1;
4477    return bi->gcc->state_info.seq - bi2->gcc->state_info.seq;
4478 }
4479 
4480 static int
_e_gadcon_layout_smart_sort_by_position_cb(const void * d1,const void * d2)4481 _e_gadcon_layout_smart_sort_by_position_cb(const void *d1, const void *d2)
4482 {
4483    const E_Gadcon_Layout_Item *bi, *bi2;
4484 
4485    bi = evas_object_data_get(d1, "e_gadcon_layout_data");
4486    bi2 = evas_object_data_get(d2, "e_gadcon_layout_data");
4487 
4488    return bi->x - bi2->x;
4489 }
4490 
4491 static int
_e_gadcon_layout_smart_containers_sort_cb(const void * d1,const void * d2)4492 _e_gadcon_layout_smart_containers_sort_cb(const void *d1, const void *d2)
4493 {
4494    const E_Layout_Item_Container *lc, *lc2;
4495 
4496    lc = d1;
4497    lc2 = d2;
4498    if (lc->pos < lc2->pos) return -1;
4499    else if (lc->pos > lc2->pos)
4500      return 1;
4501    return 0;
4502 }
4503 
4504 static int
_e_gadcon_layout_smart_seq_sort_cb(const void * d1,const void * d2)4505 _e_gadcon_layout_smart_seq_sort_cb(const void *d1, const void *d2)
4506 {
4507    const E_Gadcon_Layout_Item *bi, *bi2;
4508 
4509    bi = d1;
4510    bi2 = d2;
4511    return bi->gcc->state_info.seq - bi2->gcc->state_info.seq;
4512 }
4513 
4514 static void
_e_gadcon_layout_smart_sync_clients(E_Gadcon * gc)4515 _e_gadcon_layout_smart_sync_clients(E_Gadcon *gc)
4516 {
4517    E_Gadcon_Client *gcc;
4518    Eina_List *l;
4519 
4520    EINA_LIST_FOREACH(gc->clients, l, gcc)
4521      {
4522         _e_gadcon_client_save(gcc);
4523      }
4524 }
4525 
4526 static void
_e_gadcon_client_current_position_sync(E_Gadcon_Client * gcc)4527 _e_gadcon_client_current_position_sync(E_Gadcon_Client *gcc)
4528 {
4529    E_Gadcon_Layout_Item *bi;
4530    Evas_Object *o;
4531 
4532    o = gcc->o_frame ? gcc->o_frame : gcc->o_base;
4533    if (o)
4534      {
4535         bi = evas_object_data_get(o, "e_gadcon_layout_data");
4536         if (!bi) return;
4537      }
4538    else return;  /* make clang happy */
4539 
4540    gcc->state_info.prev_pos = gcc->config.pos;
4541    gcc->state_info.prev_size = gcc->config.size;
4542    gcc->config.pos = bi->x;
4543 }
4544 
4545 static void
_e_gadcon_layout_smart_gadcon_position_shrinked_mode(E_Smart_Data * sd)4546 _e_gadcon_layout_smart_gadcon_position_shrinked_mode(E_Smart_Data *sd)
4547 {
4548    Eina_List *l;
4549    Evas_Object *item;
4550    E_Gadcon_Layout_Item *bi, *bi2;
4551    void *tp;
4552    int pos = 0;
4553 
4554    sd->items = eina_list_sort(sd->items, eina_list_count(sd->items),
4555                               _e_gadcon_layout_smart_sort_by_sequence_number_cb);
4556    EINA_LIST_FOREACH(sd->items, l, item)
4557      {
4558         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4559         if (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_POS_INC)
4560           {
4561              if (bi->gcc->state_info.resist <= E_LAYOUT_ITEM_DRAG_RESIST_LEVEL)
4562                {
4563                   bi->gcc->state_info.resist++;
4564                   bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
4565                }
4566              else
4567                {
4568                   bi->gcc->state_info.resist = 0;
4569                   if (eina_list_next(l))
4570                     {
4571                        tp = eina_list_data_get(eina_list_next(l));
4572                        l->next->data = eina_list_data_get(l);
4573                        l->data = tp;
4574 
4575                        bi2 = evas_object_data_get(tp, "e_gadcon_layout_data");
4576 
4577                        if (bi2->x + bi2->w / 2 > bi->ask.pos + bi->w)
4578                          {
4579                             bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
4580                             return;
4581                          }
4582 
4583                        bi->gcc->config.pos = bi->ask.pos = bi2->ask.pos;
4584                        bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
4585                        bi->gcc->state_info.want_save = 1;
4586                        bi2->gcc->state_info.want_save = 1;
4587                        break;
4588                     }
4589                   else
4590                     bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
4591                }
4592           }
4593         else if (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_POS_DEC)
4594           {
4595              if (bi->gcc->state_info.resist <= E_LAYOUT_ITEM_DRAG_RESIST_LEVEL)
4596                {
4597                   bi->gcc->state_info.resist++;
4598                   bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
4599                }
4600              else
4601                {
4602                   bi->gcc->state_info.resist = 0;
4603                   if (eina_list_prev(l))
4604                     {
4605                        tp = eina_list_data_get(eina_list_prev(l));
4606                        l->prev->data = eina_list_data_get(l);
4607 
4608                        l->data = tp;
4609                        bi2 = evas_object_data_get(tp, "e_gadcon_layout_data");
4610 
4611                        if (bi->ask.pos > bi2->x + bi2->w / 2)
4612                          {
4613                             bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
4614                             return;
4615                          }
4616 
4617                        bi->gcc->config.pos = bi->ask.pos = bi2->ask.pos;
4618                        bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
4619                        bi->gcc->state_info.want_save = 1;
4620                        bi2->gcc->state_info.want_save = 1;
4621                        break;
4622                     }
4623                   else
4624                     bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
4625                }
4626           }
4627         else if ((bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC) ||
4628                  (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_SIZE_MAX_END_DEC) ||
4629                  (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC) ||
4630                  (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC))
4631           {
4632              if (bi->w < bi->min.w)
4633                bi->gcc->config.size = bi->w = bi->min.w;
4634              else
4635                bi->gcc->config.size = bi->w;
4636 
4637              bi->gcc->config.pos = bi->gcc->state_info.prev_pos;
4638           }
4639      }
4640 
4641    EINA_LIST_FOREACH(sd->items, l, item)
4642      {
4643         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4644 
4645         bi->x = pos;
4646         bi->w = bi->ask.size2;
4647         bi->gcc->config.size = bi->w;
4648         pos = bi->x + bi->w;
4649      }
4650 }
4651 
4652 static void
_e_gadcon_layout_smart_gadcons_asked_position_set(E_Smart_Data * sd)4653 _e_gadcon_layout_smart_gadcons_asked_position_set(E_Smart_Data *sd)
4654 {
4655    E_Gadcon_Layout_Item *bi;
4656    Eina_List *l;
4657    Evas_Object *item;
4658 
4659 #if 0
4660    EINA_LIST_FOREACH(sd->items, l, item)
4661      {
4662         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4663         if (!bi) continue;
4664 
4665         bi->x = bi->ask.pos;
4666         bi->w = bi->ask.size2;
4667      }
4668 #else
4669    int pos;
4670    EINA_LIST_FOREACH(sd->items, l, item)
4671      {
4672         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4673         if (!bi) continue;
4674 
4675         pos = bi->ask.pos + (bi->ask.size / 2);
4676         if (pos < (bi->ask.res / 3))
4677           {
4678              /* hooked to start */
4679              bi->x = bi->ask.pos;
4680              bi->w = bi->ask.size2;
4681              bi->hookp = 0;
4682           }
4683         else if (pos > ((2 * bi->ask.res) / 3))
4684           {
4685              /* hooked to end */
4686              bi->x = (bi->ask.pos - bi->ask.res) + sd->w;
4687              bi->w = bi->ask.size2;
4688              bi->hookp = bi->ask.res;
4689           }
4690         else
4691           {
4692              /* hooked to middle */
4693              if ((bi->ask.pos <= (bi->ask.res / 2)) &&
4694                  ((bi->ask.pos + bi->ask.size2) > (bi->ask.res / 2)))
4695                {
4696                   /* straddles middle */
4697                   if (bi->ask.res > 2)
4698                     bi->x = (sd->w / 2) +
4699                       (((bi->ask.pos + (bi->ask.size2 / 2) -
4700                          (bi->ask.res / 2)) *
4701                         (bi->ask.res / 2)) /
4702                        (bi->ask.res / 2)) - (bi->ask.size2 / 2);
4703                   else
4704                     bi->x = sd->w / 2;
4705                   bi->w = bi->ask.size2;
4706                }
4707              else
4708                {
4709                   /* either side of middle */
4710                   bi->x = (bi->ask.pos - (bi->ask.res / 2)) + (sd->w / 2);
4711                   bi->w = bi->ask.size2;
4712                }
4713              bi->hookp = bi->ask.res / 2;
4714           }
4715      }
4716 #endif
4717 }
4718 
4719 /*
4720  * The function returns a list of E_Gadcon_Layout_Item_Container
4721  */
4722 static Eina_List *
_e_gadcon_layout_smart_gadcons_wrap(E_Smart_Data * sd)4723 _e_gadcon_layout_smart_gadcons_wrap(E_Smart_Data *sd)
4724 {
4725    Eina_List *l, *list = NULL;
4726    Evas_Object *item;
4727    E_Layout_Item_Container *lc;
4728    E_Gadcon_Layout_Item *bi;
4729 
4730    EINA_LIST_FOREACH(sd->items, l, item)
4731      {
4732         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4733         lc = E_NEW(E_Layout_Item_Container, 1);
4734         lc->state_info.min_seq = lc->state_info.max_seq = bi->gcc->state_info.seq;
4735         lc->sd = sd;
4736 
4737         lc->pos = bi->x;
4738         lc->size = bi->w;
4739 
4740         lc->prev_pos = bi->ask.prev_pos;
4741         lc->prev_size = bi->ask.prev_size;
4742 
4743         E_LAYOUT_ITEM_CONTAINER_STATE_SET(lc->state, bi->gcc->state_info.state);
4744 
4745         if ((bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION) &&
4746             (lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
4747           lc->state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
4748 
4749         lc->items = eina_list_append(lc->items, bi);
4750         list = eina_list_append(list, lc);
4751      }
4752    return list;
4753 }
4754 
4755 static void
_e_gadcon_layout_smart_gadcons_position(E_Smart_Data * sd,Eina_List ** list)4756 _e_gadcon_layout_smart_gadcons_position(E_Smart_Data *sd, Eina_List **list)
4757 {
4758    int ok, lc_moving_prev_pos;
4759    Eina_List *l, *l2, *l3;
4760    E_Layout_Item_Container *lc_moving = NULL, *lc_back = NULL, *lc, *lc3;
4761    E_Gadcon_Layout_Item *bi, *bi_moving = NULL;
4762 
4763    if ((!list) || (!*list)) return;
4764 
4765    EINA_LIST_FOREACH(*list, l, lc_moving)
4766      {
4767         if ((lc_moving->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
4768             (lc_moving->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED))
4769           {
4770              lc_back = E_NEW(E_Layout_Item_Container, 1);
4771              lc_back->pos = lc_moving->pos;
4772              lc_back->prev_pos = lc_moving->prev_pos;
4773              lc_back->size = lc_moving->size;
4774              lc_back->prev_size = lc_moving->prev_size;
4775              lc_back->state_info.min_seq = lc_moving->state_info.min_seq;
4776              lc_back->state_info.max_seq = lc_moving->state_info.max_seq;
4777              lc_back->sd = lc_moving->sd;
4778              EINA_LIST_FOREACH(lc_moving->items, l2, lc)
4779                lc_back->items = eina_list_append(lc_back->items, lc);
4780              lc_back->state = lc_moving->state;
4781              bi_moving = eina_list_data_get(lc_back->items);
4782 
4783              break;
4784           }
4785         lc_moving = NULL;
4786      }
4787 
4788    if (!lc_moving)
4789      {
4790         if (lc_back) LC_FREE(lc_back);
4791         _e_gadcon_layout_smart_gadcons_position_static(sd, list);
4792         return;
4793      }
4794 
4795    lc_moving_prev_pos = lc_moving->prev_pos;
4796    if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC)
4797      {
4798         _e_gadcon_layout_smart_restore_gadcons_position_before_move(sd, &lc_moving, lc_back, list);
4799         EINA_LIST_FOREACH(*list, l, lc)
4800           if (lc == lc_moving) break;
4801 
4802         ok = 0;
4803         if ((l) && eina_list_prev(l))
4804           {
4805              lc = eina_list_data_get(eina_list_prev(l));
4806 
4807              if (lc_moving->pos < (lc->pos + lc->size))
4808                {
4809                   bi = eina_list_data_get(lc_moving->items);
4810                   if (bi->gcc->state_info.resist <= E_LAYOUT_ITEM_DRAG_RESIST_LEVEL)
4811                     {
4812                        if (lc_moving->prev_pos == (lc->pos + lc->size))
4813                          ok = 1;
4814                        bi->gcc->state_info.resist++;
4815                        lc_moving->pos = lc->pos + lc->size;
4816                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4817                     }
4818                   else
4819                     {
4820                        bi->gcc->state_info.resist = 0;
4821                        if (lc_moving->pos < lc->pos)
4822                          {
4823                             lc_moving->pos = (lc->pos + lc->size) - 1;
4824                             _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4825                          }
4826                        lc3 = _e_gadcon_layout_smart_containers_position_adjust(sd, lc, lc_moving);
4827                        if (lc3)
4828                          {
4829                             if (lc_moving->prev_pos == (lc->pos + lc->size))
4830                               ok = 1;
4831 
4832                             l->data = lc3;
4833                             *list = eina_list_remove_list(*list, eina_list_prev(l));
4834                             LC_FREE(lc_moving);
4835                             LC_FREE(lc);
4836                             lc_moving = lc3;
4837                          }
4838                     }
4839                }
4840           }
4841         if (!ok)
4842           {
4843              int pos, prev_pos, stop;
4844 
4845              EINA_LIST_FOREACH(*list, l, lc)
4846                if (lc == lc_moving) break;
4847 
4848              pos = lc_moving->pos + lc_moving->size;
4849              prev_pos = lc_moving_prev_pos;
4850              if ((l) && (eina_list_next(l)))
4851                {
4852                   stop = 0;
4853                   EINA_LIST_FOREACH(eina_list_next(l), l2, lc)
4854                     {
4855                        if (stop) break;
4856                        if (lc->pos != prev_pos) break;
4857                        prev_pos = lc->pos + lc->size;
4858 
4859                        EINA_LIST_FOREACH(lc->items, l3, bi)
4860                          {
4861                             if (bi->ask.pos <= pos)
4862                               {
4863                                  bi->x = pos;
4864                                  pos = (bi->x) + (bi->w);
4865                               }
4866                             else if (bi->ask.pos < bi->x)
4867                               {
4868                                  bi->x = bi->ask.pos;
4869                                  pos = (bi->x) + (bi->w);
4870                               }
4871                             else if (bi->ask.pos == bi->x)
4872                               {
4873                                  stop = 1;
4874                                  break;
4875                               }
4876                          }
4877                     }
4878                }
4879           }
4880      }
4881    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC)
4882      {
4883         _e_gadcon_layout_smart_restore_gadcons_position_before_move(sd, &lc_moving, lc_back, list);
4884         EINA_LIST_FOREACH(*list, l, lc)
4885           if (lc == lc_moving) break;
4886 
4887         ok = 0;
4888         if ((l) && eina_list_next(l))
4889           {
4890              lc = eina_list_data_get(eina_list_next(l));
4891 
4892              if ((lc_moving->pos + lc_moving->size) > lc->pos)
4893                {
4894                   bi = eina_list_data_get(lc_moving->items);
4895                   if (bi->gcc->state_info.resist <= E_LAYOUT_ITEM_DRAG_RESIST_LEVEL)
4896                     {
4897                        if ((lc_moving->prev_pos + lc_moving->size) == lc->pos)
4898                          ok = 1;
4899                        bi->gcc->state_info.resist++;
4900                        lc_moving->pos = lc->pos - lc_moving->size;
4901                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4902                     }
4903                   else
4904                     {
4905                        bi->gcc->state_info.resist = 0;
4906                        if ((lc_moving->pos + lc_moving->size) > lc->pos)
4907                          {
4908                             lc_moving->pos = (lc->pos - lc_moving->size) + 1;
4909                             _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4910                          }
4911                        lc3 = _e_gadcon_layout_smart_containers_position_adjust(sd, lc_moving, lc);
4912                        if (lc3)
4913                          {
4914                             if ((lc_moving->prev_pos + lc_moving->size) == lc->pos)
4915                               ok = 1;
4916 
4917                             l->data = lc3;
4918                             *list = eina_list_remove_list(*list, eina_list_next(l));
4919                             LC_FREE(lc_moving);
4920                             LC_FREE(lc);
4921                             lc_moving = lc3;
4922                          }
4923                     }
4924                }
4925           }
4926 
4927         if (!ok)
4928           {
4929              int pos, prev_pos, stop;
4930 
4931              EINA_LIST_FOREACH(*list, l, lc)
4932                if (lc == lc_moving) break;
4933 
4934              pos = lc_moving->pos;
4935              prev_pos = lc_moving_prev_pos;
4936 
4937              if ((l) && eina_list_prev(l))
4938                {
4939                   stop = 0;
4940                   /* EINA_FUCK_REVERSE_FOREACH(eina_list_prev(l), l2, lc) */
4941                   for (l2 = l->prev; l2; l2 = l2->prev)
4942                     {
4943                        lc = l2->data;
4944 
4945                        if (stop) break;
4946                        if ((lc->pos + lc->size) == prev_pos) break;
4947                        prev_pos = lc->pos;
4948 
4949                        EINA_LIST_REVERSE_FOREACH(lc->items, l3, bi)
4950                          {
4951                             if ((bi->ask.pos + bi->w) >= pos)
4952                               {
4953                                  bi->x = pos - bi->w;
4954                                  pos = bi->x;
4955                               }
4956                             else if (bi->ask.pos > bi->x)
4957                               {
4958                                  bi->x = bi->ask.pos;
4959                                  pos = bi->x;
4960                               }
4961                             else if (bi->ask.pos == bi->x)
4962                               {
4963                                  stop = 1;
4964                                  break;
4965                               }
4966                          }
4967                     }
4968                }
4969           }
4970      }
4971    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_DEC)
4972      {
4973         _e_gadcon_layout_smart_restore_gadcons_position_before_move(sd, &lc_moving, lc_back, list);
4974         EINA_LIST_FOREACH(*list, l, lc)
4975           if (lc == lc_moving) break;
4976 
4977         if ((l) && eina_list_prev(l))
4978           {
4979              int new_pos = 0;
4980 
4981              ok = 0;
4982              new_pos = lc_moving->pos;
4983              /* EINA_FUCK_REVERSE_FOREACH(eina_list_prev(l), l2, lc) */
4984              for (l2 = l->prev; l2; l2 = l2->prev)
4985                {
4986                   lc = l2->data;
4987                   if (new_pos >= (lc->pos + lc->size)) break;
4988 
4989                   ok = 1;
4990                   new_pos -= lc->size;
4991                }
4992 
4993              if (new_pos < 0)
4994                {
4995                   lc_moving->size += new_pos;
4996                   lc_moving->pos -= new_pos;
4997 
4998                   bi = eina_list_data_get(lc_moving->items);
4999                   bi->w = lc_moving->size;
5000                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
5001 
5002                   new_pos = 0;
5003                }
5004 
5005              if (ok)
5006                {
5007                   if (!l2) l2 = *list;
5008                   else l2 = eina_list_next(l2);
5009 
5010                   EINA_LIST_FOREACH(l2, l2, lc)
5011                     {
5012                        if (l2 == l) break;
5013                        lc->pos = new_pos;
5014                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5015                        EINA_LIST_FOREACH(lc->items, l3, bi)
5016                          {
5017                             bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
5018                          }
5019                        new_pos += lc->size;
5020                     }
5021                }
5022           }
5023         else if ((l) && (!eina_list_prev(l)))
5024           {
5025              if (lc_moving->pos <= 0)
5026                {
5027                   lc_moving->size = lc_moving->prev_size;
5028                   lc_moving->pos = 0;
5029 
5030                   bi = eina_list_data_get(lc_moving->items);
5031                   bi->w = lc_moving->size;
5032 
5033                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
5034                }
5035           }
5036      }
5037    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_INC)
5038      {
5039         lc_moving->state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
5040         _e_gadcon_layout_smart_gadcons_position_static(sd, list);
5041         if (lc_back) LC_FREE(lc_back);
5042      }
5043    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_INC)
5044      {
5045         _e_gadcon_layout_smart_restore_gadcons_position_before_move(sd, &lc_moving, lc_back, list);
5046         EINA_LIST_FOREACH(*list, l, lc)
5047           if (lc == lc_moving) break;
5048 
5049         if ((l) && eina_list_next(l))
5050           {
5051              Eina_List *stop = NULL;
5052              int new_pos = 0;
5053 
5054              ok = 0;
5055              new_pos = lc_moving->pos + lc_moving->size;
5056              EINA_LIST_FOREACH(eina_list_next(l), l2, lc)
5057                {
5058                   if (new_pos <= lc->pos)
5059                     {
5060                        stop = l2;
5061                        break;
5062                     }
5063 
5064                   ok = 1;
5065                   /* new_pos += lc->size; */
5066                }
5067 
5068              if (new_pos > sd->w)
5069                {
5070                   lc_moving->size -= (new_pos - sd->w);
5071                   bi = eina_list_data_get(lc_moving->items);
5072                   bi->w = lc_moving->size;
5073 
5074                   new_pos = lc_moving->pos + lc_moving->size;
5075                }
5076 
5077              if (ok)
5078                {
5079                   EINA_LIST_FOREACH(eina_list_next(l), l2, lc)
5080                     {
5081                        if (l2 == stop) break;
5082                        lc->pos = new_pos;
5083                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5084                        EINA_LIST_FOREACH(lc->items, l3, bi)
5085                          {
5086                             bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
5087                          }
5088                        new_pos += lc->size;
5089                     }
5090                }
5091           }
5092         else if ((l) && (!eina_list_next(l)))
5093           {
5094              if ((lc_moving->pos + lc_moving->size) >= sd->w)
5095                {
5096                   lc_moving->size = lc_moving->prev_size;
5097                   bi = eina_list_data_get(lc_moving->items);
5098                   bi->w = lc_moving->size;
5099                }
5100           }
5101      }
5102    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_DEC)
5103      {
5104         lc_moving->state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
5105         _e_gadcon_layout_smart_gadcons_position_static(sd, list);
5106         if (lc_back) LC_FREE(lc_back);
5107      }
5108 
5109    if (bi_moving)
5110      {
5111         bi_moving->gcc->config.pos = bi_moving->ask.pos = bi_moving->x;
5112         bi_moving->gcc->config.size = bi_moving->w;
5113      }
5114 }
5115 
5116 static void
_e_gadcon_layout_smart_gadcons_position_static(E_Smart_Data * sd,Eina_List ** list)5117 _e_gadcon_layout_smart_gadcons_position_static(E_Smart_Data *sd, Eina_List **list)
5118 {
5119    int ok;
5120    Eina_List *l;
5121    E_Layout_Item_Container *lc, *lc2, *lc3;
5122 
5123    *list = eina_list_sort(*list, eina_list_count(*list), _e_gadcon_layout_smart_containers_sort_cb);
5124 
5125 __reposition_again:
5126    EINA_LIST_FOREACH(*list, l, lc)
5127      {
5128         if (!eina_list_next(l)) continue;
5129 
5130         lc2 = eina_list_data_get(eina_list_next(l));
5131 
5132         if (LC_OVERLAP(lc, lc2))
5133           {
5134              lc3 = _e_gadcon_layout_smart_containers_position_adjust(sd, lc, lc2);
5135              if (lc3)
5136                {
5137                   l->data = lc3;
5138                   *list = eina_list_remove_list(*list, eina_list_next(l));
5139                   LC_FREE(lc);
5140                   LC_FREE(lc2);
5141                   goto __reposition_again;
5142                }
5143           }
5144      }
5145 
5146    ok = 1;
5147    EINA_LIST_FOREACH(*list, l, lc)
5148      {
5149         if (lc->pos < 0)
5150           {
5151              ok = 0;
5152              lc->pos = 0;
5153              _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5154              continue;
5155           }
5156 
5157         if (((lc->pos + lc->size) > sd->w) && (lc->size <= sd->w))
5158           {
5159              ok = 0;
5160              lc->pos = sd->w - lc->size;
5161              _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5162           }
5163      }
5164    if (!ok)
5165      _e_gadcon_layout_smart_gadcons_position_static(sd, list);
5166 }
5167 
5168 static E_Layout_Item_Container *
_e_gadcon_layout_smart_containers_position_adjust(E_Smart_Data * sd,E_Layout_Item_Container * lc,E_Layout_Item_Container * lc2)5169 _e_gadcon_layout_smart_containers_position_adjust(E_Smart_Data *sd, E_Layout_Item_Container *lc, E_Layout_Item_Container *lc2)
5170 {
5171    int create_new = 0;
5172    Eina_List *l;
5173    E_Layout_Item_Container *lc3 = NULL;
5174    E_Layout_Item_Container_State new_state;
5175    E_Gadcon_Layout_Item *bi, *bi2;
5176 
5177    if ((lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
5178        (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
5179      {
5180         if (lc->state_info.max_seq <= lc2->state_info.min_seq)
5181           {
5182              lc2->pos = lc->pos + lc->size;
5183              _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
5184           }
5185         else if (lc->state_info.min_seq > lc2->state_info.max_seq)
5186           {
5187              lc->pos = lc2->pos + lc2->size;
5188              _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5189           }
5190         else if (((lc->state_info.min_seq > lc2->state_info.min_seq) &&
5191                   (lc->state_info.min_seq < lc2->state_info.max_seq)) ||
5192                  ((lc2->state_info.min_seq > lc->state_info.min_seq) &&
5193                   (lc2->state_info.min_seq < lc->state_info.max_seq)))
5194           {
5195              _e_gadcon_layout_smart_containers_merge(sd, lc, lc2);
5196           }
5197         create_new = 1;
5198         new_state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;
5199      }
5200    else if ((lc->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
5201             (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
5202      {
5203         if (lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC)
5204           {
5205              int t;
5206 
5207              bi = eina_list_data_get(lc->items);
5208              bi2 = eina_list_data_get(lc2->items);
5209 
5210              bi->x = ((bi2->x) + (bi2->w)) - (bi->w);
5211              bi->gcc->config.pos = bi->ask.pos = bi->x;
5212              bi->gcc->config.size = bi->w;
5213              bi2->x = (bi->x) - (bi2->w);
5214 
5215              bi2->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
5216 
5217              t = bi->gcc->state_info.seq;
5218              bi->gcc->state_info.seq = bi2->gcc->state_info.seq;
5219              bi2->gcc->state_info.seq = t;
5220 
5221              _e_gadcon_layout_smart_containers_merge(sd, lc, lc2);
5222           }
5223         else if (lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED)
5224           {
5225              if (lc->state_info.max_seq < lc2->state_info.min_seq)
5226                {
5227                   lc2->pos = lc->pos + lc->size;
5228                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
5229                }
5230              else if (lc->state_info.min_seq > lc2->state_info.max_seq)
5231                {
5232                   lc2->pos = lc->pos - lc2->size;
5233                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
5234                }
5235              else if (((lc->state_info.min_seq > lc2->state_info.min_seq) &&
5236                        (lc->state_info.min_seq < lc2->state_info.max_seq)) ||
5237                       ((lc2->state_info.min_seq > lc->state_info.min_seq) &&
5238                        (lc2->state_info.min_seq < lc->state_info.max_seq)))
5239                {
5240                   int shift = 0;
5241 
5242                   _e_gadcon_layout_smart_containers_merge(sd, lc, lc2);
5243 
5244                   EINA_LIST_FOREACH(lc->items, l, bi)
5245                     {
5246                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION)
5247                          {
5248                             shift = bi->ask.pos - bi->x;
5249                          }
5250 
5251                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
5252                          break;
5253                     }
5254 
5255                   if (shift)
5256                     {
5257                        EINA_LIST_FOREACH(lc->items, l, bi)
5258                          {
5259                             bi->x += shift;
5260 
5261                             if (l == lc->items)
5262                               lc->pos = bi->x;
5263                          }
5264                     }
5265                }
5266           }
5267         create_new = 1;
5268         new_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
5269      }
5270    else if ((lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
5271             (lc2->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
5272      {
5273         if (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED)
5274           {
5275              if (lc->state_info.max_seq < lc2->state_info.min_seq)
5276                {
5277                   lc->pos = lc2->pos - lc->size;
5278                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5279                }
5280              else if (lc->state_info.min_seq > lc2->state_info.max_seq)
5281                {
5282                   lc->pos = lc2->pos + lc2->size;
5283                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5284                }
5285              else if (((lc->state_info.min_seq > lc2->state_info.min_seq) &&
5286                        (lc->state_info.min_seq < lc2->state_info.max_seq)) ||
5287                       ((lc2->state_info.min_seq > lc->state_info.min_seq) &&
5288                        (lc2->state_info.min_seq < lc->state_info.max_seq)))
5289                {
5290                   int shift = 0;
5291 
5292                   EINA_LIST_FOREACH(lc->items, l, bi)
5293                     {
5294                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION)
5295                          {
5296                             shift = bi->ask.pos - bi->x;
5297                          }
5298 
5299                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
5300                          break;
5301                     }
5302 
5303                   if (shift)
5304                     {
5305                        EINA_LIST_FOREACH(lc->items, l, bi)
5306                          {
5307                             bi->x += shift;
5308 
5309                             if (l == lc->items)
5310                               lc->pos = bi->x;
5311                          }
5312                     }
5313                }
5314           }
5315         else if (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC)
5316           {
5317              int t;
5318 
5319              bi = eina_list_last_data_get(lc->items);
5320              bi2 = eina_list_data_get(lc2->items);
5321 
5322              bi2->gcc->config.pos = bi2->ask.pos = (bi2->x) = (bi->x);
5323              bi2->gcc->config.size = bi2->w;
5324              bi->x = bi2->x + bi2->w;
5325 
5326              t = bi->gcc->state_info.seq;
5327              bi->gcc->state_info.seq = bi2->gcc->state_info.seq;
5328              bi2->gcc->state_info.seq = t;
5329 
5330              lc->items = eina_list_remove_list(lc->items, eina_list_last(lc->items));
5331              lc->items = eina_list_append(lc->items, bi2);
5332              lc->items = eina_list_append(lc->items, bi);
5333              lc2->items = eina_list_free(lc2->items);
5334              E_LAYOUT_ITEM_CONTAINER_SIZE_CHANGE_BY(lc, bi2, 1);
5335              lc2->pos = lc->pos + lc->size;
5336              lc2->size = 0;
5337           }
5338         create_new = 1;
5339         new_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
5340      }
5341    else if ((lc->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
5342             (lc2->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
5343      {
5344         if ((lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED) &&
5345             (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED))
5346           {
5347              if (lc->state_info.max_seq < lc2->state_info.min_seq)
5348                {
5349                   int move_lc1 = 1;
5350                   int move_lc2 = 1;
5351 
5352                   EINA_LIST_FOREACH(lc->items, l, bi)
5353                     {
5354                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
5355                          {
5356                             move_lc1 = 0;
5357                             break;
5358                          }
5359                     }
5360                   EINA_LIST_FOREACH(lc2->items, l, bi)
5361                     {
5362                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
5363                          {
5364                             move_lc2 = 0;
5365                             break;
5366                          }
5367                     }
5368 
5369                   if ((move_lc1) && (!move_lc2))
5370                     {
5371                        lc->pos = lc2->pos - lc->size;
5372                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5373                     }
5374                   else
5375                     {
5376                        lc2->pos = lc->pos + lc->size;
5377                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
5378                     }
5379                }
5380              else if (lc->state_info.min_seq > lc2->state_info.max_seq)
5381                {
5382                   int move_lc1 = 1;
5383                   int move_lc2 = 1;
5384 
5385                   EINA_LIST_FOREACH(lc->items, l, bi)
5386                     {
5387                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
5388                          {
5389                             move_lc1 = 0;
5390                             break;
5391                          }
5392                     }
5393                   EINA_LIST_FOREACH(lc2->items, l, bi)
5394                     {
5395                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
5396                          {
5397                             move_lc2 = 0;
5398                             break;
5399                          }
5400                     }
5401 
5402                   if ((!move_lc1) && (move_lc2))
5403                     {
5404                        lc2->pos = lc->pos - lc2->size;
5405                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
5406                     }
5407                   else
5408                     {
5409                        lc->pos = lc2->pos + lc2->size;
5410                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
5411                     }
5412                }
5413              else if (((lc->state_info.min_seq > lc2->state_info.min_seq) &&
5414                        (lc->state_info.min_seq < lc2->state_info.max_seq)) ||
5415                       ((lc2->state_info.min_seq > lc->state_info.min_seq) &&
5416                        (lc2->state_info.min_seq < lc->state_info.max_seq)))
5417                {
5418                   int shift = 0;
5419 
5420                   _e_gadcon_layout_smart_containers_merge(sd, lc, lc2);
5421 
5422                   EINA_LIST_FOREACH(lc->items, l, bi)
5423                     {
5424                        if ((bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION) &&
5425                            (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE))
5426                          {
5427                             shift = bi->ask.pos - bi->x;
5428                             break;
5429                          }
5430                     }
5431 
5432                   if (shift)
5433                     {
5434                        EINA_LIST_FOREACH(lc->items, l, bi)
5435                          {
5436                             bi->x += shift;
5437 
5438                             if (l == lc->items)
5439                               lc->pos = bi->x;
5440                          }
5441                     }
5442                }
5443              create_new = 1;
5444              new_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
5445           }
5446      }
5447 
5448    if (create_new)
5449      {
5450         lc3 = E_NEW(E_Layout_Item_Container, 1);
5451         lc3->sd = sd;
5452         if (lc->pos < lc2->pos)
5453           {
5454              lc3->pos = lc->pos;
5455              EINA_LIST_FOREACH(lc->items, l, bi)
5456                lc3->items = eina_list_append(lc3->items, bi);
5457              EINA_LIST_FOREACH(lc2->items, l, bi)
5458                lc3->items = eina_list_append(lc3->items, bi);
5459 
5460              lc3->state_info.min_seq = lc->state_info.min_seq;
5461              if (lc2->items)
5462                lc3->state_info.max_seq = lc2->state_info.max_seq;
5463              else
5464                lc3->state_info.max_seq = lc->state_info.max_seq;
5465           }
5466         else
5467           {
5468              lc3->pos = lc2->pos;
5469              EINA_LIST_FOREACH(lc2->items, l, bi)
5470                lc3->items = eina_list_append(lc3->items, bi);
5471              EINA_LIST_FOREACH(lc->items, l, bi)
5472                lc3->items = eina_list_append(lc3->items, bi);
5473 
5474              lc3->state_info.min_seq = lc2->state_info.min_seq;
5475              if (lc->items)
5476                lc3->state_info.max_seq = lc->state_info.max_seq;
5477              else
5478                lc3->state_info.max_seq = lc2->state_info.max_seq;
5479           }
5480         lc3->size = lc->size + lc2->size;
5481         lc3->state = new_state;
5482      }
5483 
5484    return lc3;
5485 }
5486 
5487 static void
_e_gadcon_layout_smart_position_items_inside_container(E_Smart_Data * sd EINA_UNUSED,E_Layout_Item_Container * lc)5488 _e_gadcon_layout_smart_position_items_inside_container(E_Smart_Data *sd EINA_UNUSED, E_Layout_Item_Container *lc)
5489 {
5490    int shift;
5491    Eina_List *l;
5492    E_Gadcon_Layout_Item *bi;
5493 
5494    if (!lc->items) return;
5495 
5496    bi = eina_list_data_get(lc->items);
5497    shift = lc->pos - bi->x;
5498 
5499    if (!shift) return;
5500 
5501    EINA_LIST_FOREACH(lc->items, l, bi)
5502      {
5503         bi->x += shift;
5504 
5505         if ((bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_POS_DEC) ||
5506             (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_POS_INC))
5507           {
5508              bi->gcc->config.pos = bi->ask.pos = bi->x;
5509           }
5510      }
5511 }
5512 
5513 static void
_e_gadcon_layout_smart_containers_merge(E_Smart_Data * sd EINA_UNUSED,E_Layout_Item_Container * lc,E_Layout_Item_Container * lc2)5514 _e_gadcon_layout_smart_containers_merge(E_Smart_Data *sd EINA_UNUSED, E_Layout_Item_Container *lc, E_Layout_Item_Container *lc2)
5515 {
5516    int start = 0, size = 0, next = 0, min_seq = 0, max_seq = 0;
5517    Eina_List *l, *nl = NULL;
5518    E_Gadcon_Layout_Item *bi;
5519 
5520    EINA_LIST_FOREACH(lc->items, l, bi)
5521      nl = eina_list_append(nl, bi);
5522    EINA_LIST_FOREACH(lc2->items, l, bi)
5523      nl = eina_list_append(nl, bi);
5524 
5525    nl = eina_list_sort(nl, eina_list_count(nl), _e_gadcon_layout_smart_seq_sort_cb);
5526 
5527    EINA_LIST_FOREACH(nl, l, bi)
5528      {
5529         if (l == nl)
5530           {
5531              min_seq = max_seq = bi->gcc->state_info.seq;
5532              start = bi->x;
5533              size = bi->w;
5534              next = bi->x + bi->w;
5535 
5536              continue;
5537           }
5538 
5539         max_seq = bi->gcc->state_info.seq;
5540 
5541         bi->x = next;
5542         size += bi->w;
5543         next = bi->x + bi->w;
5544      }
5545 
5546    lc->items = eina_list_free(lc->items);
5547    lc2->items = eina_list_free(lc->items);
5548    lc->items = nl;
5549    lc->pos = start;
5550    lc->size = size;
5551    lc->state_info.min_seq = min_seq;
5552    lc->state_info.max_seq = max_seq;
5553    lc2->pos = lc->pos + lc->size;
5554    lc2->size = 0;
5555 }
5556 
5557 static void
_e_gadcon_layout_smart_restore_gadcons_position_before_move(E_Smart_Data * sd,E_Layout_Item_Container ** lc_moving,E_Layout_Item_Container * lc_back,Eina_List ** con_list)5558 _e_gadcon_layout_smart_restore_gadcons_position_before_move(E_Smart_Data *sd, E_Layout_Item_Container **lc_moving, E_Layout_Item_Container *lc_back, Eina_List **con_list)
5559 {
5560    int ok;
5561    Eina_List *l, *l2, *l3;
5562    E_Gadcon_Layout_Item *bi, *bi2;
5563    E_Layout_Item_Container *lc, *lc2, *lc3;
5564 
5565    (*lc_moving)->pos = (*lc_moving)->prev_pos;
5566    if (((*lc_moving)->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_INC) ||
5567        ((*lc_moving)->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_DEC) ||
5568        ((*lc_moving)->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_INC) ||
5569        ((*lc_moving)->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_DEC))
5570      {
5571         (*lc_moving)->size = (*lc_moving)->prev_size;
5572         bi = eina_list_data_get((*lc_moving)->items);
5573 
5574         bi->w = (*lc_moving)->prev_size;
5575      }
5576    _e_gadcon_layout_smart_position_items_inside_container(sd, (*lc_moving));
5577    (*lc_moving)->state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
5578    _e_gadcon_layout_smart_gadcons_position_static(sd, con_list);
5579 
5580    lc2 = NULL;
5581    lc3 = NULL;
5582    ok = 0;
5583    EINA_LIST_FOREACH(*con_list, l, lc)
5584      {
5585         if (lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE) continue;
5586 
5587         if (eina_list_count(lc->items) == 1)
5588           {
5589              bi = eina_list_data_get(lc->items);
5590              if (bi->gcc->state_info.state != E_LAYOUT_ITEM_STATE_NONE)
5591                {
5592                   LC_FREE(lc);
5593                   l->data = *lc_moving = lc_back;
5594                   _e_gadcon_layout_smart_position_items_inside_container(sd, (*lc_moving));
5595 
5596                   if (((*lc_moving)->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC) &&
5597                       ((*lc_moving)->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC))
5598                     {
5599                        bi = eina_list_data_get((*lc_moving)->items);
5600                        bi->w = (*lc_moving)->size;
5601                     }
5602                }
5603           }
5604         else
5605           {
5606              EINA_LIST_FOREACH(lc->items, l2, bi)
5607                {
5608                   if (bi->gcc->state_info.state != E_LAYOUT_ITEM_STATE_NONE)
5609                     {
5610                        ok = 1;
5611                        if (l2 != lc->items)
5612                          {
5613                             lc2 = E_NEW(E_Layout_Item_Container, 1);
5614                             lc2->sd = sd;
5615                             lc2->state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;
5616                             EINA_LIST_FOREACH(lc->items, l3, bi2)
5617                               {
5618                                  if (l2 == l3) break;
5619                                  lc2->items = eina_list_append(lc2->items, bi2);
5620                                  if (l3 == lc->items)
5621                                    {
5622                                       lc2->state_info.min_seq = bi2->gcc->state_info.seq;
5623                                       lc2->pos = lc2->prev_pos = bi2->x;
5624                                    }
5625                                  lc2->state_info.max_seq = bi2->gcc->state_info.seq;
5626                                  E_LAYOUT_ITEM_CONTAINER_SIZE_CHANGE_BY(lc2, bi2, 1);
5627                               }
5628                          }
5629 
5630                        if (eina_list_next(l2))
5631                          {
5632                             lc3 = E_NEW(E_Layout_Item_Container, 1);
5633                             lc3->sd = sd;
5634                             lc3->state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;
5635                             EINA_LIST_FOREACH(eina_list_next(l2), l3, bi2)
5636                               {
5637                                  lc3->items = eina_list_append(lc3->items, bi2);
5638                                  if (l3 == eina_list_next(l2))
5639                                    {
5640                                       lc3->state_info.min_seq = bi2->gcc->state_info.seq;
5641                                       lc3->pos = lc3->prev_pos = bi2->x;
5642                                    }
5643                                  lc3->state_info.max_seq = bi2->gcc->state_info.seq;
5644                                  E_LAYOUT_ITEM_CONTAINER_SIZE_CHANGE_BY(lc3, bi2, 1);
5645                               }
5646                          }
5647                        *lc_moving = lc_back;
5648                        _e_gadcon_layout_smart_position_items_inside_container(sd, *lc_moving);
5649 
5650                        if (((*lc_moving)->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC) &&
5651                            ((*lc_moving)->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC))
5652                          {
5653                             bi = eina_list_data_get((*lc_moving)->items);
5654                             bi->w = (*lc_moving)->size;
5655                          }
5656                        break;
5657                     }
5658                }
5659              if (ok)
5660                {
5661                   LC_FREE(lc);
5662                   if (lc2)
5663                     {
5664                        l->data = lc2;
5665                        *con_list = eina_list_append(*con_list, *lc_moving);
5666                        if (lc3)
5667                          *con_list = eina_list_append(*con_list, lc3);
5668                        *con_list = eina_list_sort(*con_list, eina_list_count(*con_list),
5669                                                   _e_gadcon_layout_smart_containers_sort_cb);
5670                     }
5671                   else
5672                     {
5673                        l->data = *lc_moving;
5674                        if (lc3)
5675                          {
5676                             *con_list = eina_list_append(*con_list, lc3);
5677                             *con_list = eina_list_sort(*con_list, eina_list_count(*con_list),
5678                                                        _e_gadcon_layout_smart_containers_sort_cb);
5679                          }
5680                     }
5681                   break;
5682                }
5683           }
5684      }
5685 
5686    EINA_LIST_FOREACH(*con_list, l, lc)
5687      {
5688         if (lc == *lc_moving) continue;
5689         lc->state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;
5690      }
5691 }
5692 
5693 static void
_e_gadcon_event_populate_free(void * data EINA_UNUSED,void * event)5694 _e_gadcon_event_populate_free(void *data EINA_UNUSED, void *event)
5695 {
5696    E_Event_Gadcon_Populate *ev = event;
5697 
5698    e_object_unref(E_OBJECT(ev->gc));
5699    free(ev);
5700 }
5701 
5702 static void
_e_gadcon_custom_populate_job(void * data EINA_UNUSED)5703 _e_gadcon_custom_populate_job(void *data EINA_UNUSED)
5704 {
5705    const E_Gadcon_Client_Class *cc;
5706    E_Config_Gadcon_Client *cf_gcc;
5707    Eina_List *l, *ll;
5708    E_Gadcon *gc;
5709 
5710 #ifndef E_RELEASE_BUILD
5711    static Eina_Bool first = EINA_TRUE;
5712    if (first)
5713      e_main_ts("gadcon custom populate idler start");
5714 #endif
5715    EINA_LIST_FREE(custom_populate_requests, gc)
5716      {
5717         if (!gc->cf) continue;
5718         e_gadcon_layout_freeze(gc->o_container);
5719         EINA_LIST_FOREACH_SAFE(gc->cf->clients, l, ll, cf_gcc)
5720           {
5721              if ((!cf_gcc->name) || (!cf_gcc->name[0]) || (!cf_gcc->id) || (!cf_gcc->id[0]))
5722                {
5723                   e_gadcon_client_config_del(gc->cf, cf_gcc);
5724                   continue;
5725                }
5726              cc = eina_hash_find(providers, cf_gcc->name);
5727              if (!cc) continue;
5728              if (gc->populate_class.func)
5729                gc->populate_class.func(gc->populate_class.data, gc, cc);
5730              else
5731                e_gadcon_populate_class(gc, cc);
5732           }
5733         e_gadcon_layout_thaw(gc->o_container);
5734         _e_gadcon_event_populate(gc);
5735      }
5736 
5737 #ifndef E_RELEASE_BUILD
5738    if (first)
5739      e_main_ts("gadcon custom populate idler end");
5740 #endif
5741    if (!custom_populate_requests)
5742      {
5743         custom_populate_job = NULL;
5744 #ifndef E_RELEASE_BUILD
5745         first = EINA_FALSE;
5746 #endif
5747      }
5748 }
5749 
5750 static void
_e_gadcon_provider_populate_job(void * data EINA_UNUSED)5751 _e_gadcon_provider_populate_job(void *data EINA_UNUSED)
5752 {
5753    E_Gadcon_Client_Class *cc;
5754    Eina_List *l;
5755    E_Gadcon *gc;
5756 
5757 #ifndef E_RELEASE_BUILD
5758    static Eina_Bool first = EINA_TRUE;
5759    if (first)
5760      e_main_ts("gadcon populate idler start");
5761 #endif
5762    EINA_LIST_FOREACH(gadcons, l, gc)
5763      {
5764         int x = 0;
5765         Eina_Bool freeze = EINA_FALSE;
5766         if (gc->populate_requests)
5767           {
5768              freeze = EINA_TRUE;
5769              e_gadcon_layout_freeze(gc->o_container);
5770           }
5771         EINA_LIST_FREE(gc->populate_requests, cc)
5772           {
5773 #ifndef E_RELEASE_BUILD
5774              if (first) e_main_ts(cc->name);
5775 #endif
5776              if (gc->populate_class.func)
5777                gc->populate_class.func(gc->populate_class.data, gc, cc);
5778              else
5779                e_gadcon_populate_class(gc, cc);
5780              if (!eina_list_data_find(gc->populated_classes, cc))
5781                {
5782                   gc->populated_classes = eina_list_append(gc->populated_classes, cc);
5783                   if (gc->cf)
5784                     {
5785                        Eina_List *ll;
5786                        E_Config_Gadcon_Client *cf_gcc;
5787 
5788                        if (!gc->awaiting_classes) continue;
5789                        ll = eina_hash_set(gc->awaiting_classes, cc->name, NULL);
5790                        EINA_LIST_FREE(ll, cf_gcc)
5791                          _e_gadcon_client_populate(gc, cc, cf_gcc);
5792                     }
5793                }
5794              x++;
5795           }
5796         if (freeze) e_gadcon_layout_thaw(gc->o_container);
5797         if (x && _modules_loaded) _e_gadcon_event_populate(gc);
5798      }
5799 //out:
5800 #ifndef E_RELEASE_BUILD
5801    if (first)
5802      e_main_ts("gadcon populate idler end");
5803 #endif
5804 
5805    populate_job = NULL;
5806 #ifndef E_RELEASE_BUILD
5807    first = EINA_FALSE;
5808 #endif
5809 }
5810 
5811 static void
_e_gadcon_provider_populate_request(E_Gadcon * gc,const E_Gadcon_Client_Class * cc)5812 _e_gadcon_provider_populate_request(E_Gadcon *gc, const E_Gadcon_Client_Class *cc)
5813 {
5814    if (eina_list_data_find(gc->populate_requests, cc)) return;
5815    gc->populate_requests = eina_list_append(gc->populate_requests, cc);
5816    if (populate_job) ecore_job_del(populate_job);
5817    populate_job = ecore_job_add(_e_gadcon_provider_populate_job, NULL);
5818 }
5819 
5820 static void
_e_gadcon_provider_populate_unrequest(const E_Gadcon_Client_Class * cc)5821 _e_gadcon_provider_populate_unrequest(const E_Gadcon_Client_Class *cc)
5822 {
5823    E_Gadcon *gc;
5824    Eina_List *l;
5825    unsigned int more = 0;
5826    EINA_LIST_FOREACH(gadcons, l, gc)
5827      {
5828         gc->populate_requests = eina_list_remove(gc->populate_requests, cc);
5829         more += eina_list_count(gc->populate_requests);
5830      }
5831    if ((!more) && (populate_job))
5832      {
5833         ecore_job_del(populate_job);
5834         populate_job = NULL;
5835      }
5836 }
5837 
5838 /* gadgets movement between different gadcons */
5839 
5840 E_API E_Gadcon_Location *
e_gadcon_location_new(const char * name,E_Gadcon_Site site,int (* add_func)(void * data,E_Gadcon_Client * gcc,const E_Gadcon_Client_Class * cc),void * add_data,void (* remove_func)(void * data,E_Gadcon_Client * cc),void * remove_data)5841 e_gadcon_location_new(const char *name,
5842                       E_Gadcon_Site site,
5843                       int (*add_func)(void *data, E_Gadcon_Client *gcc, const E_Gadcon_Client_Class *cc),
5844                       void *add_data,
5845                       void (*remove_func)(void *data, E_Gadcon_Client *cc),
5846                       void *remove_data)
5847 {
5848    E_Gadcon_Location *loc;
5849 
5850    loc = E_NEW(E_Gadcon_Location, 1);
5851    loc->name = eina_stringshare_add(name);
5852    loc->site = site;
5853    loc->gadget_add.func = add_func;
5854    loc->gadget_add.data = add_data;
5855    loc->gadget_remove.func = remove_func;
5856    loc->gadget_remove.data = remove_data;
5857    loc->icon_name = NULL;
5858    return loc;
5859 }
5860 
5861 E_API void
e_gadcon_location_set_icon_name(E_Gadcon_Location * loc,const char * name)5862 e_gadcon_location_set_icon_name(E_Gadcon_Location *loc, const char *name)
5863 {
5864    if (loc->icon_name) eina_stringshare_del(loc->icon_name);
5865    if (name)
5866      loc->icon_name = eina_stringshare_add(name);
5867    else
5868      loc->icon_name = NULL;
5869 }
5870 
5871 E_API void
e_gadcon_location_free(E_Gadcon_Location * loc)5872 e_gadcon_location_free(E_Gadcon_Location *loc)
5873 {
5874    eina_stringshare_del(loc->name);
5875    if (loc->icon_name) eina_stringshare_del(loc->icon_name);
5876    free(loc);
5877 }
5878 
5879 E_API void
e_gadcon_location_register(E_Gadcon_Location * loc)5880 e_gadcon_location_register(E_Gadcon_Location *loc)
5881 {
5882    gadcon_locations = eina_list_append(gadcon_locations, loc);
5883 }
5884 
5885 E_API void
e_gadcon_location_unregister(E_Gadcon_Location * loc)5886 e_gadcon_location_unregister(E_Gadcon_Location *loc)
5887 {
5888    gadcon_locations = eina_list_remove(gadcon_locations, loc);
5889 }
5890 
5891 static int
_e_gadcon_location_change(E_Gadcon_Client * gcc,E_Gadcon_Location * src,E_Gadcon_Location * dst)5892 _e_gadcon_location_change(E_Gadcon_Client *gcc, E_Gadcon_Location *src, E_Gadcon_Location *dst)
5893 {
5894    E_Gadcon_Client_Class *cc;
5895 
5896    cc = eina_hash_find(providers, gcc->cf->name);
5897    if (!cc) return 0;
5898    if (!dst->gadget_add.func(dst->gadget_add.data, gcc, cc)) return 0;
5899    gcc->cf = NULL;
5900    src->gadget_remove.func(src->gadget_remove.data, gcc);
5901    return 1;
5902 }
5903 
5904 E_API Eina_Bool
e_gadcon_client_visible_get(const E_Gadcon_Client * gcc,const E_Desk * desk)5905 e_gadcon_client_visible_get(const E_Gadcon_Client *gcc, const E_Desk *desk)
5906 {
5907    const Eina_List *l;
5908    E_Zone *zone;
5909 
5910    if (!gcc->gadcon) return EINA_FALSE;
5911    switch (gcc->gadcon->location->site)
5912      {
5913       case E_GADCON_SITE_DESKTOP:
5914         return EINA_TRUE; // FIXME for when gadman allows per-desk gadgets
5915       case E_GADCON_SITE_SHELF:
5916         if (desk) return e_shelf_desk_visible(gcc->gadcon->shelf, desk);
5917         EINA_LIST_FOREACH(e_comp->zones, l, zone)
5918           if (e_shelf_desk_visible(gcc->gadcon->shelf, e_desk_current_get(zone)))
5919             return EINA_TRUE;
5920         break;
5921       case E_GADCON_SITE_TOOLBAR:
5922       case E_GADCON_SITE_EFM_TOOLBAR:
5923         if (desk) return (e_win_client_get(gcc->gadcon->toolbar->fwin)->desk == desk);
5924         EINA_LIST_FOREACH(e_comp->zones, l, zone)
5925           if (e_win_client_get(gcc->gadcon->toolbar->fwin)->desk == e_desk_current_get(zone)) return EINA_TRUE;
5926       default:
5927         break;
5928      }
5929    return EINA_FALSE;
5930 }
5931