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