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