update for beta release
[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->id;
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->id;
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              w = gcc->min.w;
1710           }
1711         else
1712           {
1713              h = gcc->min.h;
1714           }
1715      }
1716    if (gcc->o_base)
1717      e_box_pack_options_set(gcc->o_base,
1718                             1, 1, /* fill */
1719                             1, 1, /* expand */
1720                             0.5, 0.5, /* align */
1721                             w, h, /* min */
1722                             w, h /* max */
1723                            );
1724 }
1725
1726 static Eina_Bool
1727 _e_gadcon_cb_client_scroll_timer(void *data)
1728 {
1729    E_Gadcon_Client *gcc;
1730    double d, v;
1731
1732    gcc = data;
1733    d = gcc->scroll_wanted - gcc->scroll_pos;
1734    if (d < 0) d = -d;
1735    if (d < 0.001)
1736      {
1737         gcc->scroll_pos =  gcc->scroll_wanted;
1738         gcc->scroll_timer = NULL;
1739         return ECORE_CALLBACK_CANCEL;
1740      }
1741    v = 0.05;
1742    gcc->scroll_pos = (gcc->scroll_pos * (1.0 - v)) + (gcc->scroll_wanted * v);
1743    return ECORE_CALLBACK_RENEW;
1744 }
1745
1746 static Eina_Bool
1747 _e_gadcon_cb_client_scroll_animator(void *data)
1748 {
1749    E_Gadcon_Client *gcc;
1750
1751    gcc = data;
1752    if (e_box_orientation_get(gcc->o_box))
1753      e_box_align_set(gcc->o_box, 1.0 - gcc->scroll_pos, 0.5);
1754    else
1755      e_box_align_set(gcc->o_box, 0.5, 1.0 - gcc->scroll_pos);
1756    if (!gcc->scroll_timer)
1757      {
1758         gcc->scroll_animator = NULL;
1759         return ECORE_CALLBACK_CANCEL;
1760      }
1761
1762    if (gcc->scroll_cb.func)
1763      gcc->scroll_cb.func(gcc->scroll_cb.data);
1764
1765    return ECORE_CALLBACK_RENEW;
1766 }
1767
1768 static void
1769 _e_gadcon_cb_client_frame_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1770 {
1771    Evas_Event_Mouse_Move *ev;
1772    E_Gadcon_Client *gcc;
1773    Evas_Coord x, y;
1774
1775    ev = event_info;
1776    gcc = data;
1777    evas_object_geometry_get(gcc->o_box, &x, &y, NULL, NULL);
1778    e_gadcon_client_autoscroll_update(gcc, ev->cur.output.x - x, 
1779                                      ev->cur.output.y - y);
1780 }
1781
1782 static void
1783 _e_gadcon_cb_client_frame_moveresize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1784 {
1785    E_Gadcon_Client *gcc;
1786
1787    gcc = data;
1788    _e_gadcon_moveresize_handle(gcc);
1789 }
1790     
1791 static void
1792 _e_gadcon_client_save(E_Gadcon_Client *gcc)
1793 {
1794    gcc->cf->geom.pos = gcc->config.pos;
1795    gcc->cf->geom.size = gcc->config.size;
1796    gcc->cf->geom.res = gcc->config.res;
1797    gcc->cf->geom.pos_x = gcc->config.pos_x;
1798    gcc->cf->geom.pos_y = gcc->config.pos_y;
1799    gcc->cf->geom.size_w = gcc->config.size_w;
1800    gcc->cf->geom.size_h = gcc->config.size_h;
1801    gcc->cf->state_info.seq = gcc->state_info.seq;
1802    gcc->cf->state_info.flags = gcc->state_info.flags;
1803    gcc->cf->autoscroll = gcc->autoscroll;
1804    if (gcc->cf->style) eina_stringshare_del(gcc->cf->style);
1805    gcc->cf->style = NULL;
1806    if (gcc->style)
1807      gcc->cf->style = eina_stringshare_add(gcc->style);
1808 /*   gcc->cf->resizable = gcc->resizable;*/
1809    gcc->cf->resizable = 0;
1810    e_config_save_queue();
1811 }
1812
1813 static void
1814 _e_gadcon_client_drag_begin(E_Gadcon_Client *gcc, int x, int y)
1815 {
1816    E_Drag *drag;
1817    Evas_Object *o = NULL;
1818    Evas_Coord w = 0, h = 0;
1819    const char *drag_types[] = { "enlightenment/gadcon_client" };
1820
1821    if ((drag_gcc) || (!gcc->gadcon->zone) || (!gcc->gadcon->zone->container))
1822      return;
1823
1824    drag_gcc = gcc;
1825
1826    e_object_ref(E_OBJECT(gcc));
1827    /* Remove this config from the current gadcon */
1828    gcc->gadcon->cf->clients = 
1829      eina_list_remove(gcc->gadcon->cf->clients, gcc->cf);
1830    gcc->state_info.state = E_LAYOUT_ITEM_STATE_NONE;
1831    gcc->state_info.resist = 0;
1832
1833    if (!e_drop_inside(gcc->gadcon->drop_handler, x, y))
1834      e_gadcon_client_hide(gcc);
1835
1836    ecore_x_pointer_xy_get(gcc->gadcon->zone->container->win, &x, &y);
1837    
1838    drag = e_drag_new(gcc->gadcon->zone->container, x, y,
1839                      drag_types, 1, gcc, -1, NULL, 
1840                      _e_gadcon_cb_drag_finished);
1841    if (drag) 
1842      {
1843         o = gcc->client_class->func.icon((E_Gadcon_Client_Class *)gcc->client_class, 
1844                                          e_drag_evas_get(drag));
1845         evas_object_geometry_get(o, NULL, NULL, &w, &h);
1846         if (!o)
1847           {
1848              /* FIXME: fallback icon for drag */
1849              o = evas_object_rectangle_add(e_drag_evas_get(drag));
1850              evas_object_color_set(o, 255, 255, 255, 100);
1851           }
1852         if (w < 10)
1853           w = h = 50;
1854         e_drag_object_set(drag, o);
1855         e_drag_resize(drag, w, h);
1856         e_drag_start(drag, x + w/2, y + h/2);
1857      }
1858 }
1859
1860 static void
1861 _e_gadcon_client_inject(E_Gadcon *gc, E_Gadcon_Client *gcc, int x, int y)
1862 {
1863    Eina_List *l;
1864    E_Gadcon_Client *gcc2;
1865    Evas_Coord cx, cy, cw, ch;
1866    int seq = 1;
1867
1868    /* Check if the gadcon client is in place */
1869    if (!gcc->hidden)
1870      {
1871         if (gcc->o_frame)
1872           evas_object_geometry_get(gcc->o_frame, &cx, &cy, &cw, &ch);
1873         else if (gcc->o_base)
1874           evas_object_geometry_get(gcc->o_base, &cx, &cy, &cw, &ch);
1875         else return; /* make clang happy */
1876
1877         if (E_INSIDE(x, y, cx, cy, cw, ch)) return;
1878      }
1879
1880    /* If x, y is not inside any gadcon client, seq will be 0 and it's position
1881     * will later be used for placement. */
1882    gcc->state_info.seq = 0;
1883    EINA_LIST_FOREACH(gc->clients, l, gcc2)
1884      {
1885         if (gcc == gcc2) continue;
1886         if (gcc2->hidden) continue;
1887         if (gcc2->o_frame)
1888           evas_object_geometry_get(gcc2->o_frame, &cx, &cy, &cw, &ch);
1889         else if (gcc2->o_base)
1890           evas_object_geometry_get(gcc2->o_base, &cx, &cy, &cw, &ch);
1891         else return; /* make clang happy */
1892         if (e_gadcon_layout_orientation_get(gc->o_container))
1893           {
1894              if (E_INSIDE(x, y, cx, cy, cw / 2, ch))
1895                {
1896                   gcc->state_info.seq = seq++;
1897                   gcc2->state_info.seq = seq++;
1898                }
1899              else if (E_INSIDE(x, y, cx + cw / 2, cy, cw / 2, ch))
1900                {
1901                   gcc2->state_info.seq = seq++;
1902                   gcc->state_info.seq = seq++;
1903                }
1904              else
1905                gcc2->state_info.seq = seq++;
1906           }
1907         else
1908           {
1909              if (E_INSIDE(x, y, cx, cy, cw, ch / 2))
1910                {
1911                   gcc->state_info.seq = seq++;
1912                   gcc2->state_info.seq = seq++;
1913                }
1914              else if (E_INSIDE(x, y, cx, cy + ch / 2, cw, ch / 2))
1915                {
1916                   gcc2->state_info.seq = seq++;
1917                   gcc->state_info.seq = seq++;
1918                }
1919              else
1920                gcc2->state_info.seq = seq++;
1921           }
1922      }
1923 }
1924
1925 static void
1926 _e_gadcon_cb_min_size_request(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1927 {
1928    E_Gadcon *gc;
1929
1930    gc = data;
1931    if (gc->min_size_request.func)
1932      {
1933         Evas_Coord w = 0, h = 0;
1934
1935         e_gadcon_layout_min_size_get(gc->o_container, &w, &h);
1936         gc->min_size_request.func(gc->min_size_request.data, gc, w, h);
1937      }
1938 }
1939
1940 static void
1941 _e_gadcon_cb_size_request(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1942 {
1943    E_Gadcon *gc;
1944
1945    gc = data;
1946    if (gc->resize_request.func)
1947      {
1948         Evas_Coord w = 0, h = 0;
1949
1950         e_gadcon_layout_asked_size_get(gc->o_container, &w, &h);
1951         gc->resize_request.func(gc->resize_request.data, gc, w, h);
1952      }
1953 }
1954
1955 static void
1956 _e_gadcon_cb_moveresize(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1957 {
1958    E_Gadcon *gc;
1959    Evas_Coord x, y, w, h;
1960
1961    gc = data;
1962    evas_object_geometry_get(gc->o_container, &x, &y, &w, &h);
1963    if (gc->drop_handler) 
1964      e_drop_handler_geometry_set(gc->drop_handler, x, y, w, h);
1965 }
1966
1967 static void
1968 _e_gadcon_cb_client_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1969 {
1970    Evas_Event_Mouse_Down *ev;
1971    E_Gadcon_Client *gcc;
1972
1973    gcc = data;
1974    ev = event_info;
1975    if (ev->button == 3)
1976      {
1977         E_Zone *zone;
1978         E_Menu *mn;
1979         E_Menu_Item *mi;
1980         int cx, cy;
1981
1982         zone = e_util_zone_current_get(e_manager_current_get());
1983
1984         e_gadcon_locked_set(gcc->gadcon, 1);
1985         mn = e_menu_new();
1986         e_menu_post_deactivate_callback_set(mn, _e_gadcon_client_cb_menu_post,
1987                                             gcc);
1988         gcc->menu = mn;
1989
1990         mi = e_menu_item_new(mn);
1991         e_menu_item_label_set(mi, _("Stop moving"));
1992         e_util_menu_item_theme_icon_set(mi, "enlightenment/edit");
1993         e_menu_item_callback_set(mi, _e_gadcon_client_cb_menu_edit, gcc);
1994
1995         if (gcc->gadcon->menu_attach.func)
1996           {
1997              mi = e_menu_item_new(mn);
1998              e_menu_item_separator_set(mi, 1);
1999
2000              gcc->gadcon->menu_attach.func(gcc->gadcon->menu_attach.data, 
2001                                            gcc, mn);
2002           }
2003
2004         if (gcc->gadcon->toolbar)
2005           ecore_x_pointer_xy_get(zone->container->win, &cx, &cy);
2006         else 
2007           {
2008              e_gadcon_canvas_zone_geometry_get(gcc->gadcon, &cx, &cy, NULL, NULL);
2009              cx = cx + ev->output.x;
2010              cy = cy + ev->output.y;
2011           }
2012         e_menu_activate_mouse(mn, zone, cx, cy, 1, 1, 
2013                               E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
2014      }
2015 }
2016
2017 static void
2018 _e_gadcon_cb_client_mouse_in(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2019 {
2020    E_Gadcon_Client *gcc;
2021
2022    gcc = data;
2023    edje_object_signal_emit(gcc->o_control, "e,state,focused", "e");
2024 }
2025
2026 static void
2027 _e_gadcon_cb_client_mouse_out(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2028 {
2029    E_Gadcon_Client *gcc;
2030
2031    gcc = data;
2032    edje_object_signal_emit(gcc->o_control, "e,state,unfocused", "e");
2033 }
2034
2035 static void
2036 _e_gadcon_cb_client_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2037 {
2038    E_Gadcon_Client *gcc;
2039    Evas_Coord x, y;
2040
2041    gcc = data;
2042    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
2043    if (gcc->o_control) evas_object_move(gcc->o_control, x, y);
2044    if (gcc->o_event) evas_object_move(gcc->o_event, x, y);
2045 }
2046
2047 static void
2048 _e_gadcon_cb_client_resize(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2049 {
2050    E_Gadcon_Client *gcc;
2051    Evas_Coord w, h;
2052
2053    gcc = data;
2054    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
2055    if (gcc->o_control) evas_object_resize(gcc->o_control, w, h);
2056    if (gcc->o_event) evas_object_resize(gcc->o_event, w, h);
2057 }
2058
2059 static void
2060 _e_gadcon_client_move_start(E_Gadcon_Client *gcc)
2061 {
2062    int x, y, gcx, gcy, gy ,gx;
2063    
2064    evas_object_raise(gcc->o_event);
2065    evas_object_stack_below(gcc->o_control, gcc->o_event);
2066    gcc->moving = 1;
2067    if (gcc->gadcon->toolbar)
2068      evas_pointer_canvas_xy_get(gcc->gadcon->evas, &gcc->dx, &gcc->dy);
2069    else
2070      {
2071         ecore_x_pointer_xy_get(gcc->gadcon->zone->container->win, &gcc->dx, &gcc->dy);
2072         e_gadcon_canvas_zone_geometry_get(gcc->gadcon, &gcx, &gcy, NULL, NULL);
2073         evas_object_geometry_get(gcc->gadcon->o_container, &gx, &gy, NULL, NULL);
2074         gcc->dx -= (gcx + gx);
2075         gcc->dy -= (gcy + gy);
2076      }
2077    
2078    if (gcc->o_frame)
2079      evas_object_geometry_get(gcc->o_frame, &x, &y, NULL, NULL);
2080    else if (gcc->o_base)
2081      evas_object_geometry_get(gcc->o_base, &x, &y, NULL, NULL);
2082    else
2083      return;
2084
2085    /* using drag pos to calc offset between pointer and gcc pos */
2086    gcc->drag.x = (x - gcc->dx);
2087    gcc->drag.y = (y - gcc->dy);
2088
2089    gcc->state_info.resist = 0;
2090 }
2091
2092 static void
2093 _e_gadcon_client_move_stop(E_Gadcon_Client *gcc)
2094 {
2095    gcc->moving = 0;
2096    gcc->state_info.state = E_LAYOUT_ITEM_STATE_NONE;
2097    gcc->state_info.resist = 0;
2098    _e_gadcon_layout_smart_sync_clients(gcc->gadcon);
2099 }
2100
2101 static void
2102 _e_gadcon_client_move_go(E_Gadcon_Client *gcc)
2103 {
2104    Evas_Coord x, y, w, h;
2105    int cx, cy;
2106    int gx, gy, gw, gh;
2107    int gcx = 0, gcy = 0;
2108    int changes = 0;
2109    
2110    if (!gcc->moving) return;
2111    /* we need to get output not canvas because things like systray
2112       can reparent another window so we get no position here */
2113    /* maybe we should better grab mouse while move resize is active...*/
2114    //evas_pointer_canvas_xy_get(gcc->gadcon->evas, &cx, &cy);
2115    if (gcc->gadcon->toolbar)
2116      evas_pointer_canvas_xy_get(gcc->gadcon->evas, &cx, &cy);
2117    else
2118      {
2119         ecore_x_pointer_xy_get(gcc->gadcon->zone->container->win, &cx, &cy);
2120         e_gadcon_canvas_zone_geometry_get(gcc->gadcon, &gcx, &gcy, NULL, NULL);
2121      }
2122    
2123    evas_object_geometry_get(gcc->gadcon->o_container, &gx, &gy, &gw, &gh);
2124
2125    cx -= (gx + gcx);
2126    cy -= (gy + gcy);
2127    
2128    x = cx - gcc->dx;
2129    y = cy - gcc->dy; 
2130    
2131    gcc->state_info.flags = E_GADCON_LAYOUT_ITEM_LOCK_POSITION | E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
2132    _e_gadcon_client_current_position_sync(gcc);
2133
2134    if (gcc->o_frame)
2135      evas_object_geometry_get(gcc->o_frame, NULL, NULL, &w, &h);
2136    else if (gcc->o_base)
2137      evas_object_geometry_get(gcc->o_base, NULL, NULL, &w, &h);
2138    else
2139      return; /* make clang happy */
2140
2141    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2142      { 
2143         if (cy + e_config->drag_resist < 0 || cy - e_config->drag_resist > gh)
2144           {
2145              _e_gadcon_client_drag_begin(gcc, cx, cy);
2146              return;
2147           }
2148
2149         if (x > 0 && (cx + gcc->drag.x > gcc->config.pos))
2150           {
2151              if (gcc->state_info.state != E_LAYOUT_ITEM_STATE_POS_INC)
2152                gcc->state_info.resist = 0;
2153              gcc->state_info.state = E_LAYOUT_ITEM_STATE_POS_INC;
2154              changes = 1;
2155           }
2156         else if (x < 0 && (cx + gcc->drag.x < gcc->config.pos))
2157           {
2158              if (gcc->state_info.state != E_LAYOUT_ITEM_STATE_POS_DEC)
2159                gcc->state_info.resist = 0; 
2160              gcc->state_info.state = E_LAYOUT_ITEM_STATE_POS_DEC;
2161              changes = 1;
2162           }
2163
2164         if (changes)
2165           {
2166              if (gcc->o_frame)
2167                e_gadcon_layout_pack_request_set(gcc->o_frame, cx + gcc->drag.x, w);
2168              else if (gcc->o_base)
2169                e_gadcon_layout_pack_request_set(gcc->o_base, cx + gcc->drag.x, w);
2170
2171              gcc->config.size = w;
2172              evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2173              gcc->config.res = w;
2174           }
2175      }
2176    else
2177      {
2178         if (cx + e_config->drag_resist < 0 || cx - e_config->drag_resist > gw)
2179           {
2180              _e_gadcon_client_drag_begin(gcc, cx, cy);
2181              return;
2182           }
2183
2184         if (y > 0 && (cy + gcc->drag.y > gcc->config.pos))
2185           {
2186              if (gcc->state_info.state != E_LAYOUT_ITEM_STATE_POS_INC)
2187                gcc->state_info.resist = 0;
2188              gcc->state_info.state = E_LAYOUT_ITEM_STATE_POS_INC;
2189              changes = 1;
2190           }
2191         else if (y < 0 && (cy + gcc->drag.y < gcc->config.pos))
2192           {
2193              if (gcc->state_info.state != E_LAYOUT_ITEM_STATE_POS_DEC)
2194                gcc->state_info.resist = 0;
2195              gcc->state_info.state = E_LAYOUT_ITEM_STATE_POS_DEC;
2196              changes = 1;
2197           }
2198
2199         if (changes)
2200           {
2201              if (gcc->o_frame)
2202                e_gadcon_layout_pack_request_set(gcc->o_frame, cy + gcc->drag.y, h);
2203              else if (gcc->o_base)
2204                e_gadcon_layout_pack_request_set(gcc->o_base, cy + gcc->drag.y, h);
2205
2206              gcc->config.size = h;
2207              evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2208              gcc->config.res = h;
2209           }
2210
2211      }
2212    
2213    gcc->dx += x;
2214    gcc->dy += y;
2215 }
2216
2217 static void
2218 _e_gadcon_cb_signal_move_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2219 {
2220    _e_gadcon_client_move_start(data);
2221 }
2222
2223 static void
2224 _e_gadcon_cb_signal_move_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2225 {
2226    _e_gadcon_client_move_stop(data);
2227 }
2228
2229 static void
2230 _e_gadcon_cb_signal_move_go(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2231 {
2232    _e_gadcon_client_move_go(data);
2233 }
2234
2235 static void
2236 _e_gadcon_client_resize_start(E_Gadcon_Client *gcc)
2237 {
2238    evas_object_raise(gcc->o_event);
2239    evas_object_stack_below(gcc->o_control, gcc->o_event);
2240    gcc->resizing = 1;
2241    evas_pointer_canvas_xy_get(gcc->gadcon->evas, &gcc->dx, &gcc->dy);
2242 }
2243
2244 static void
2245 _e_gadconclient_resize_stop(E_Gadcon_Client *gcc)
2246 {
2247    gcc->resizing = 0;
2248    gcc->state_info.state = E_LAYOUT_ITEM_STATE_NONE;
2249    _e_gadcon_layout_smart_sync_clients(gcc->gadcon);
2250    _e_gadcon_client_save(gcc);
2251 }
2252
2253 static void
2254 _e_gadcon_cb_signal_resize_left_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2255 {
2256    _e_gadcon_client_resize_start(data);
2257 }
2258
2259 static void
2260 _e_gadcon_cb_signal_resize_left_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2261 {
2262    _e_gadconclient_resize_stop(data);
2263 }
2264
2265 static void
2266 _e_gadcon_cb_signal_resize_left_go(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2267 {
2268    E_Gadcon_Client *gcc;
2269    Evas_Coord x, y, w, h;
2270
2271    gcc = data;
2272    if (!gcc->resizing) return;
2273    evas_pointer_canvas_xy_get(gcc->gadcon->evas, &x, &y);
2274    x = x - gcc->dx;
2275    y = y - gcc->dy;
2276
2277    gcc->state_info.flags = E_GADCON_LAYOUT_ITEM_LOCK_POSITION | 
2278      E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
2279
2280    if (gcc->o_frame)
2281      evas_object_geometry_get(gcc->o_frame, NULL, NULL, &w, &h);
2282    else if (gcc->o_base)
2283      evas_object_geometry_get(gcc->o_base, NULL, NULL, &w, &h);
2284    else return; /* make clang happy */
2285
2286    _e_gadcon_client_current_position_sync(gcc);
2287
2288    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2289      {
2290         if (x > 0)
2291           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC;
2292         else if (x < 0)
2293           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC;
2294      }
2295    else
2296      {
2297         if (y > 0)
2298           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC;
2299         else if (y < 0)
2300           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC;
2301      }
2302
2303    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2304      {
2305         if (gcc->o_frame) 
2306           e_gadcon_layout_pack_request_set(gcc->o_frame, gcc->config.pos + x, w - x);
2307         else if (gcc->o_base)
2308           e_gadcon_layout_pack_request_set(gcc->o_base, gcc->config.pos + x, w - x);
2309         evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2310         gcc->config.res = w;
2311      }
2312    else
2313      {
2314         if (gcc->o_frame)
2315           e_gadcon_layout_pack_request_set(gcc->o_frame, gcc->config.pos + y, h - y);
2316         else if (gcc->o_base)
2317           e_gadcon_layout_pack_request_set(gcc->o_base, gcc->config.pos + y, h - y);
2318         evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2319         gcc->config.res = h;
2320      }
2321    gcc->dx += x;
2322    gcc->dy += y;
2323 }
2324
2325 static void
2326 _e_gadcon_cb_signal_resize_right_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2327 {
2328    _e_gadcon_client_resize_start(data);
2329 }
2330
2331 static void
2332 _e_gadcon_cb_signal_resize_right_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2333 {
2334    _e_gadconclient_resize_stop(data);
2335 }
2336
2337 static void
2338 _e_gadcon_cb_signal_resize_right_go(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
2339 {
2340    E_Gadcon_Client *gcc;
2341    Evas_Coord x, y, w, h;
2342
2343    gcc = data;
2344    if (!gcc->resizing) return;
2345    evas_pointer_canvas_xy_get(gcc->gadcon->evas, &x, &y);
2346    x = x - gcc->dx;
2347    y = y - gcc->dy;
2348
2349    gcc->state_info.flags = E_GADCON_LAYOUT_ITEM_LOCK_POSITION | 
2350      E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
2351
2352    if (gcc->o_frame)
2353      evas_object_geometry_get(gcc->o_frame, NULL, NULL, &w, &h);
2354    else if (gcc->o_base)
2355      evas_object_geometry_get(gcc->o_base, NULL, NULL, &w, &h);
2356    else return; /* make clang happy */
2357
2358    _e_gadcon_client_current_position_sync(gcc);
2359
2360    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2361      {
2362         if (x > 0)
2363           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC;
2364         else if (x < 0)
2365           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MAX_END_DEC;
2366      }
2367    else
2368      {
2369         if (y > 0)
2370           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC;
2371         else if (y < 0)
2372           gcc->state_info.state = E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC;
2373      }
2374
2375    if (e_gadcon_layout_orientation_get(gcc->gadcon->o_container))
2376      {
2377         if (gcc->o_frame)
2378           e_gadcon_layout_pack_request_set(gcc->o_frame, gcc->config.pos, w + x);
2379         else if (gcc->o_base)
2380           e_gadcon_layout_pack_request_set(gcc->o_base, gcc->config.pos, w + x);
2381         evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2382         gcc->config.res = w;
2383      }
2384    else
2385      {
2386         if (gcc->o_frame)
2387           e_gadcon_layout_pack_request_set(gcc->o_frame, gcc->config.pos, h + y);
2388         else if (gcc->o_base)
2389           e_gadcon_layout_pack_request_set(gcc->o_base, gcc->config.pos, h + y);
2390         evas_object_geometry_get(gcc->gadcon->o_container, NULL, NULL, &w, &h);
2391         gcc->config.res = h;
2392      }
2393    gcc->dx += x;
2394    gcc->dy += y;
2395 }
2396
2397 static void
2398 _e_gadcon_cb_drag_finished(E_Drag *drag, int dropped)
2399 {
2400    E_Gadcon_Client *gcc;
2401
2402    gcc = drag->data;
2403    if (!dropped)
2404      {
2405         /* free client config */
2406         e_gadcon_client_config_del(NULL, gcc->cf);
2407         /* delete the gadcon client */
2408         /* TODO: Clean up module config too? */
2409         e_object_del(E_OBJECT(gcc));
2410      }
2411    else if (new_gcc)
2412      {
2413         /* dropped on new gadcon, delete this one as it is no longer in use */
2414         e_object_del(E_OBJECT(gcc));
2415      }
2416    e_object_unref(E_OBJECT(gcc));
2417    new_gcc = NULL;
2418    drag_gcc = NULL;
2419 }
2420
2421 static void
2422 _e_gadcon_cb_dnd_enter(void *data, const char *type __UNUSED__, void *event)
2423 {
2424    E_Event_Dnd_Enter *ev;
2425    E_Gadcon *gc;
2426    E_Gadcon_Client *gcc;
2427
2428    ev = event;
2429    gc = data;
2430    e_gadcon_layout_freeze(gc->o_container);
2431    gcc = drag_gcc;
2432
2433    if (gcc->gadcon == gc)
2434      {
2435         /* We have re-entered the gadcon we left, revive gadcon client */
2436         Evas_Coord dx, dy;
2437         Evas_Object *o;
2438
2439         if (e_gadcon_layout_orientation_get(gc->o_container))
2440           gcc->config.pos = ev->x - gcc->config.size / 2;
2441         else
2442           gcc->config.pos = ev->y - gcc->config.size / 2;
2443         gcc->state_info.prev_pos = gcc->config.pos;
2444
2445         evas_object_geometry_get(gc->o_container, &dx, &dy, NULL, NULL);
2446         _e_gadcon_client_inject(gc, gcc, ev->x + dx, ev->y + dy);
2447         e_gadcon_client_show(gcc);
2448
2449         o = gcc->o_frame ? gcc->o_frame : gcc->o_base;
2450         if (o)
2451           {
2452              if (e_gadcon_layout_orientation_get(gc->o_container))
2453                e_gadcon_layout_pack_request_set(o, gcc->config.pos, gcc->config.size);
2454              else
2455                e_gadcon_layout_pack_request_set(o, gcc->config.pos, gcc->config.size);
2456           }
2457         gcc->state_info.resist = 1;
2458      }
2459    else if (ev->data)
2460      {
2461         /* Create a new gadcon to show where the gadcon will end up */
2462         E_Gadcon_Client_Class *cc;
2463
2464         gcc = ev->data;
2465         cc = eina_hash_find(providers, gcc->name);
2466         if (cc)
2467           {
2468              if (!gcc->style)
2469                {
2470                   new_gcc = cc->func.init(gc, gcc->name, gcc->cf->id,
2471                                           cc->default_style);
2472                }
2473              else
2474                new_gcc = cc->func.init(gc, gcc->name, gcc->cf->id,
2475                                        gcc->style);
2476
2477              if (new_gcc)
2478                {
2479                   new_gcc->cf = gcc->cf;
2480                   new_gcc->client_class = cc;
2481                   new_gcc->config.pos = gcc->config.pos;
2482                   new_gcc->config.size = gcc->config.size;
2483                   new_gcc->config.res = gcc->config.res;
2484                   new_gcc->state_info.seq = gcc->state_info.seq;
2485                   new_gcc->state_info.flags = gcc->state_info.flags;
2486                   if (new_gcc->o_frame)
2487                     e_gadcon_layout_pack_options_set(new_gcc->o_frame, new_gcc);
2488                   else if (new_gcc->o_base)
2489                     e_gadcon_layout_pack_options_set(new_gcc->o_base, new_gcc);
2490
2491                   e_gadcon_client_autoscroll_set(new_gcc, gcc->autoscroll);
2492 /*                e_gadcon_client_resizable_set(new_gcc, gcc->resizable);*/
2493                   if (new_gcc->client_class->func.orient)
2494                     new_gcc->client_class->func.orient(new_gcc, gc->orient);
2495                   new_gcc->state_info.resist = 1;
2496                   if (gc->instant_edit)
2497                     e_gadcon_client_util_menu_attach(new_gcc);
2498                }
2499           }
2500      }
2501    else
2502      {
2503         /* TODO: Create a placeholder to show where the gadcon will end up */
2504      }
2505    e_gadcon_layout_thaw(gc->o_container);
2506 }
2507
2508 static void
2509 _e_gadcon_cb_dnd_move(void *data, const char *type __UNUSED__, void *event)
2510 {
2511    E_Event_Dnd_Move *ev;
2512    E_Gadcon *gc;
2513    E_Gadcon_Client *gcc = NULL;
2514
2515    ev = event;
2516    gc = data;
2517
2518    /* If we move in the same gadcon as the client originates */
2519    if (drag_gcc->gadcon == gc) gcc = drag_gcc;
2520    /* If we move in the newly entered gadcon */
2521    else if (new_gcc->gadcon == gc) gcc = new_gcc;
2522    if (gcc)
2523      {
2524         Evas_Coord dx, dy;
2525         Evas_Object *o;
2526
2527         if (gcc->state_info.resist > 0)
2528           {
2529              gcc->state_info.resist--;
2530              return;
2531           }
2532         e_gadcon_layout_freeze(gc->o_container);
2533
2534         if (e_gadcon_layout_orientation_get(gc->o_container))
2535           gcc->config.pos = ev->x - gcc->config.size / 2;
2536         else
2537           gcc->config.pos = ev->y - gcc->config.size / 2;
2538         gcc->state_info.prev_pos = gcc->config.pos;
2539
2540         evas_object_geometry_get(gc->o_container, &dx, &dy, NULL, NULL);
2541         _e_gadcon_client_inject(gc, gcc, ev->x + dx, ev->y + dy);
2542
2543         o = gcc->o_frame ? gcc->o_frame : gcc->o_base;
2544         if (o)
2545           {
2546              if (e_gadcon_layout_orientation_get(gc->o_container))
2547                e_gadcon_layout_pack_request_set(o, gcc->config.pos, 
2548                                                 gcc->config.size);
2549              else
2550                e_gadcon_layout_pack_request_set(o, gcc->config.pos, 
2551                                                 gcc->config.size);
2552           }
2553         e_gadcon_layout_thaw(gc->o_container);
2554      }
2555 }
2556
2557 static void
2558 _e_gadcon_cb_dnd_leave(void *data, const char *type __UNUSED__, void *event __UNUSED__)
2559 {
2560    E_Gadcon *gc;
2561
2562    gc = data;
2563    /* If we exit the starting container hide the gadcon visual */
2564    if (drag_gcc->gadcon == gc) e_gadcon_client_hide(drag_gcc);
2565
2566    /* Delete temporary object */
2567    if (new_gcc)
2568      {
2569         e_object_del(E_OBJECT(new_gcc));
2570         new_gcc = NULL;
2571      }
2572 }
2573
2574 static void
2575 _e_gadcon_cb_drop(void *data, const char *type __UNUSED__, void *event __UNUSED__)
2576 {
2577    E_Gadcon *gc;
2578    E_Gadcon_Client *gcc = NULL;
2579
2580    gc = data;
2581    if (drag_gcc->gadcon == gc) gcc = drag_gcc;
2582    else if ((new_gcc) && (new_gcc->gadcon == gc)) gcc = new_gcc;
2583    else return;  /* make clang happy */
2584
2585    gc->cf->clients = eina_list_append(gc->cf->clients, gcc->cf);
2586
2587    if (gc->editing) e_gadcon_client_edit_begin(gcc);
2588    e_config_save_queue();
2589 }
2590
2591 static int
2592 _e_gadcon_client_class_feature_check(const E_Gadcon_Client_Class *cc, const char *name, void *feature)
2593 {
2594    if (!feature)
2595      {
2596         e_util_dialog_show("Insufficent gadcon support",
2597                            "Module %s needs to support %s",
2598                            cc->name, name);
2599         return 0;
2600      }
2601    return 1;
2602 }
2603
2604 static void 
2605 _e_gadcon_client_cb_menu_post(void *data, E_Menu *m __UNUSED__)
2606 {
2607    E_Gadcon_Client *gcc;
2608
2609    if (!(gcc = data)) return;
2610    if (gcc->gadcon) e_gadcon_locked_set(gcc->gadcon, 0);
2611    if (!gcc->menu) return;
2612    e_object_del(E_OBJECT(gcc->menu));
2613    gcc->menu = NULL;
2614 }
2615
2616 static Eina_Bool
2617 _e_gadcon_client_cb_instant_edit_timer(void *data)
2618 {
2619    E_Gadcon_Client *gcc;
2620
2621    gcc = data;
2622    e_gadcon_client_edit_begin(gcc);
2623    _e_gadcon_client_move_start(gcc);
2624    gcc->instant_edit_timer = NULL;
2625    return ECORE_CALLBACK_CANCEL;
2626 }
2627
2628 static void
2629 _e_gadcon_client_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
2630 {
2631    Evas_Event_Mouse_Down *ev;
2632    E_Gadcon_Client *gcc;
2633
2634    ev = event_info;
2635    gcc = data;
2636    if (gcc->menu) return;
2637    if (ev->button == 3)
2638      {
2639         E_Menu *m;
2640         E_Zone *zone;
2641         int cx, cy, cw, ch;
2642
2643         e_gadcon_locked_set(gcc->gadcon, 1);
2644         m = e_menu_new();
2645
2646         m = e_gadcon_client_util_menu_items_append(gcc, m, 0);
2647         e_menu_post_deactivate_callback_set(m, _e_gadcon_client_cb_menu_post,
2648                                             gcc);
2649         gcc->menu = m;
2650
2651         e_gadcon_canvas_zone_geometry_get(gcc->gadcon, &cx, &cy, &cw, &ch);
2652         zone = gcc->gadcon->zone;
2653         if (!zone) zone = e_util_zone_current_get(e_manager_current_get());
2654         e_menu_activate_mouse(m, zone, 
2655                               cx + ev->output.x, 
2656                               cy + ev->output.y, 1, 1,
2657                               E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
2658      }
2659    else if (ev->button == 1)
2660      {
2661         if ((!gcc->o_control) && (gcc->gadcon->instant_edit))
2662           {
2663              if (gcc->instant_edit_timer) 
2664                ecore_timer_del(gcc->instant_edit_timer);
2665              gcc->instant_edit_timer = 
2666                ecore_timer_add(1.0, _e_gadcon_client_cb_instant_edit_timer, 
2667                                gcc);
2668           }
2669      }
2670 }
2671
2672 static void
2673 _e_gadcon_client_cb_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
2674 {
2675    Evas_Event_Mouse_Up *ev;
2676    E_Gadcon_Client *gcc;
2677
2678    ev = event_info;
2679    gcc = data;
2680    if ((ev->button == 1) && (gcc->gadcon->instant_edit))
2681      {
2682         if (gcc->instant_edit_timer)
2683           {
2684              ecore_timer_del(gcc->instant_edit_timer);
2685              gcc->instant_edit_timer = NULL;
2686           }
2687         if (gcc->o_control)
2688           {
2689              _e_gadcon_client_move_stop(gcc);
2690              e_gadcon_client_edit_end(gcc);
2691           }
2692      }
2693 }
2694
2695 static void
2696 _e_gadcon_client_cb_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2697 {
2698    E_Gadcon_Client *gcc;
2699
2700    gcc = data;
2701    if ((gcc->gadcon->instant_edit))
2702      {
2703         if (gcc->o_control) _e_gadcon_client_move_go(gcc);
2704      }
2705 }
2706
2707 static void
2708 _e_gadcon_client_cb_menu_style_plain(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
2709 {
2710    E_Gadcon_Client *gcc;
2711    E_Gadcon *gc;
2712
2713    gcc = data;
2714    gc = gcc->gadcon;
2715    if (gcc->style) eina_stringshare_del(gcc->style);
2716    gcc->style = eina_stringshare_add(E_GADCON_CLIENT_STYLE_PLAIN);
2717    _e_gadcon_client_save(gcc);
2718    e_gadcon_unpopulate(gc);
2719    e_gadcon_populate(gc);
2720 }
2721
2722 static void
2723 _e_gadcon_client_cb_menu_style_inset(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
2724 {
2725    E_Gadcon_Client *gcc;
2726    E_Gadcon *gc;
2727
2728    gcc = data;
2729    gc = gcc->gadcon;
2730    if (gcc->style) eina_stringshare_del(gcc->style);
2731    gcc->style = eina_stringshare_add(E_GADCON_CLIENT_STYLE_INSET);
2732    _e_gadcon_client_save(gcc);
2733    e_gadcon_unpopulate(gc);
2734    e_gadcon_populate(gc);
2735 }
2736
2737 static void
2738 _e_gadcon_client_cb_menu_autoscroll(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
2739 {
2740    E_Gadcon_Client *gcc;
2741
2742    gcc = data;
2743    e_gadcon_layout_freeze(gcc->gadcon->o_container);
2744    if (gcc->autoscroll) gcc->autoscroll = 0;
2745    else gcc->autoscroll = 1; 
2746    e_gadcon_client_autoscroll_set(gcc, gcc->autoscroll);
2747    _e_gadcon_client_save(gcc);
2748    e_gadcon_layout_thaw(gcc->gadcon->o_container);
2749 }
2750 /*
2751 static void
2752 _e_gadcon_client_cb_menu_resizable(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
2753 {
2754    E_Gadcon_Client *gcc;
2755
2756    gcc = data;
2757    e_gadcon_layout_freeze(gcc->gadcon->o_container);
2758    if (gcc->resizable) gcc->resizable = 0;
2759    else gcc->resizable = 1;
2760    e_gadcon_client_resizable_set(gcc, gcc->resizable);
2761    _e_gadcon_client_save(gcc);
2762    e_gadcon_layout_thaw(gcc->gadcon->o_container);
2763 }
2764 */
2765 static void
2766 _e_gadcon_client_cb_menu_edit(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
2767 {
2768    E_Gadcon_Client *gcc;
2769
2770    gcc = data;
2771    if (gcc->o_control)
2772      e_gadcon_client_edit_end(gcc);
2773    else
2774      e_gadcon_client_edit_begin(gcc);
2775 }
2776
2777 static void
2778 _e_gadcon_client_cb_menu_remove(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
2779 {
2780    E_Gadcon *gc;
2781    E_Gadcon_Client *gcc;
2782
2783    gcc = data;
2784    gc = gcc->gadcon;
2785
2786    e_gadcon_client_config_del(gc->cf, gcc->cf);
2787    e_gadcon_unpopulate(gc);
2788    e_gadcon_populate(gc);
2789    e_config_save_queue();
2790 }
2791
2792 static void 
2793 _e_gadcon_client_cb_menu_pre(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi) 
2794 {
2795    E_Gadcon_Client *gcc;
2796
2797    if (!(gcc = data)) return;
2798    if (gcc->client_class->func.icon) 
2799      {
2800         Evas_Object *ic;
2801         
2802         // e menu ASSUMES... EXPECTS the icon to be an.... e_icon! make it so.
2803         ic = gcc->client_class->func.icon
2804            ((E_Gadcon_Client_Class *)gcc->client_class, 
2805                mi->menu->evas);
2806         mi->icon_object = e_icon_add(mi->menu->evas);
2807         e_icon_object_set(mi->icon_object, ic);
2808      }
2809    else
2810       e_util_menu_item_theme_icon_set(mi, "preferences-gadget"); // FIXME: Needs icon in theme
2811 }
2812
2813 static void
2814 _e_gadcon_client_del_hook(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2815 {
2816    E_Gadcon_Client *gcc;
2817
2818    gcc = data;
2819    gcc->o_base = NULL;
2820    if (gcc->o_frame)
2821      {
2822         evas_object_del(gcc->o_frame);
2823         gcc->o_frame = NULL;
2824      }
2825    e_object_del(E_OBJECT(gcc));
2826 }
2827
2828 /* a smart object JUST for gadcon */
2829
2830 typedef struct _E_Gadcon_Layout_Item  E_Gadcon_Layout_Item;
2831
2832 struct _E_Smart_Data
2833
2834    Evas_Coord x, y, w, h;
2835    Evas_Object *obj, *clip;
2836    unsigned char horizontal : 1;
2837    unsigned char doing_config : 1;
2838    unsigned char redo_config : 1;
2839    Eina_List *items;
2840    int frozen;
2841    Evas_Coord minw, minh, req;
2842 }; 
2843
2844 struct _E_Gadcon_Layout_Item
2845 {
2846    E_Smart_Data *sd;
2847    struct 
2848      {
2849         int pos, size, size2, res, prev_pos, prev_size;
2850      } ask;
2851    int hookp;
2852    struct 
2853      {
2854         int w, h;
2855      } min, aspect, aspect_pad;
2856
2857    E_Gadcon_Client *gcc;
2858
2859    Evas_Coord x, y, w, h;
2860    Evas_Object *obj;
2861    unsigned char can_move : 1;
2862 };
2863
2864 /* local subsystem functions */
2865 static E_Gadcon_Layout_Item *_e_gadcon_layout_smart_adopt(E_Smart_Data *sd, Evas_Object *obj);
2866 static void _e_gadcon_layout_smart_disown(Evas_Object *obj);
2867 static void _e_gadcon_layout_smart_item_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
2868 static void _e_gadcon_layout_smart_reconfigure(E_Smart_Data *sd);
2869 static void _e_gadcon_layout_smart_init(void);
2870 static void _e_gadcon_layout_smart_add(Evas_Object *obj);
2871 static void _e_gadcon_layout_smart_del(Evas_Object *obj);
2872 static void _e_gadcon_layout_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
2873 static void _e_gadcon_layout_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
2874 static void _e_gadcon_layout_smart_show(Evas_Object *obj);
2875 static void _e_gadcon_layout_smart_hide(Evas_Object *obj);
2876 static void _e_gadcon_layout_smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
2877 static void _e_gadcon_layout_smart_clip_set(Evas_Object *obj, Evas_Object *clip);
2878 static void _e_gadcon_layout_smart_clip_unset(Evas_Object *obj);
2879 static void _e_gadcon_layout_smart_min_cur_size_calc(E_Smart_Data *sd, int *min, int *mino, int *cur);
2880 static void _e_gadcon_layout_smart_gadcons_width_adjust(E_Smart_Data *sd, int min, int cur);
2881 static int _e_gadcon_layout_smart_sort_by_sequence_number_cb(const void *d1, const void *d2);
2882 static int _e_gadcon_layout_smart_sort_by_position_cb(const void *d1, const void *d2);
2883
2884 /* local subsystem globals */
2885 static Evas_Smart *_e_smart = NULL;
2886
2887 /* externally accessible functions */
2888 static Evas_Object *
2889 e_gadcon_layout_add(Evas *evas)
2890 {   
2891    _e_gadcon_layout_smart_init();
2892    return evas_object_smart_add(evas, _e_smart);
2893 }
2894
2895 static void
2896 e_gadcon_layout_orientation_set(Evas_Object *obj, int horizontal)
2897 {
2898    E_Smart_Data *sd;
2899
2900    if (!obj) return;
2901    sd = evas_object_smart_data_get(obj);
2902    if (!sd) return;
2903    if (((sd->horizontal) && (horizontal)) || 
2904        ((!sd->horizontal) && (!horizontal))) return;
2905    sd->horizontal = horizontal;
2906    _e_gadcon_layout_smart_reconfigure(sd);
2907 }
2908
2909 static int
2910 e_gadcon_layout_orientation_get(Evas_Object *obj)
2911 {
2912    E_Smart_Data *sd;
2913
2914    if (!obj) return 0;
2915    sd = evas_object_smart_data_get(obj);
2916    if (!sd) return 0;
2917    return sd->horizontal;
2918 }
2919
2920 static void
2921 e_gadcon_layout_freeze(Evas_Object *obj)
2922 {
2923    E_Smart_Data *sd;
2924
2925    if (!obj) return;
2926    sd = evas_object_smart_data_get(obj);
2927    if (!sd) return;
2928    sd->frozen++;
2929 }
2930
2931 static void
2932 e_gadcon_layout_thaw(Evas_Object *obj)
2933 {
2934    E_Smart_Data *sd;
2935
2936    if (!obj) return;
2937    sd = evas_object_smart_data_get(obj);
2938    if (!sd) return;
2939    sd->frozen--;
2940    _e_gadcon_layout_smart_reconfigure(sd);
2941 }
2942
2943 static void
2944 e_gadcon_layout_min_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
2945 {
2946    E_Smart_Data *sd;
2947 /*   
2948    Eina_List *l;
2949    Evas_Object *obj;
2950    Evas_Coord tw = 0, th = 0;
2951  */
2952    if (!obj) return;
2953    sd = evas_object_smart_data_get(obj);
2954    if (!sd) return;
2955    if (sd->horizontal)
2956      {
2957         if (w) *w = sd->minw;
2958         if (h) *h = sd->minh;
2959      }
2960    else
2961      {
2962         if (w) *w = sd->minh;
2963         if (h) *h = sd->minw;
2964      }
2965    
2966 /*   
2967    EINA_LIST_FOREACH(sd->items, l, obj)
2968      {
2969         E_Gadcon_Layout_Item *bi;
2970         
2971         bi = evas_object_data_get(obj, "e_gadcon_layout_data");
2972         if (sd->horizontal)
2973           {
2974              tw += bi->min.w;
2975              if (bi->min.h > th) th = bi->min.h;
2976           }
2977         else
2978           {
2979              th += bi->min.h;
2980              if (bi->min.w > tw) tw = bi->min.w;
2981           }
2982      }
2983    if (w) *w = tw;
2984    if (h) *h = th;
2985  */
2986 }
2987
2988 static void
2989 e_gadcon_layout_asked_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
2990 {
2991    E_Smart_Data *sd;
2992    Evas_Coord tw = 0, th = 0;
2993
2994    if (!obj) return;
2995    sd = evas_object_smart_data_get(obj);
2996    if (!sd) return;
2997    if (sd->horizontal)
2998      tw = sd->req;
2999    else
3000      th = sd->req;
3001 /*   
3002    Evas_Object *obj;
3003    EINA_LIST_FOREACH(sd->items, l, obj)
3004      {
3005         E_Gadcon_Layout_Item *bi;
3006         
3007         bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3008         if (sd->horizontal)
3009           {
3010              tw += bi->ask.size;
3011           }
3012         else
3013           {
3014              th += bi->ask.size;
3015           }
3016      }
3017  */
3018    if (w) *w = tw;
3019    if (h) *h = th;
3020 }
3021
3022 static int
3023 e_gadcon_layout_pack(Evas_Object *obj, Evas_Object *child)
3024 {
3025    E_Smart_Data *sd;
3026
3027    if (!obj) return 0;
3028    sd = evas_object_smart_data_get(obj);
3029    if (!sd) return 0;
3030    _e_gadcon_layout_smart_adopt(sd, child);
3031    sd->items = eina_list_prepend(sd->items, child);
3032    _e_gadcon_layout_smart_reconfigure(sd);
3033    return 0;
3034 }
3035
3036 static void
3037 e_gadcon_layout_pack_size_set(Evas_Object *obj, int size)
3038 {
3039    /*
3040     * FIXME:
3041     * simplify this function until the is redone
3042     * _e_gadcon_layout_smart_gadcons_asked_position_set(E_Smart_Data *sd)
3043     */
3044    E_Gadcon_Layout_Item *bi;
3045    int pos;
3046
3047    if (!obj) return;
3048    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3049    if (!bi) return;
3050    pos = bi->ask.pos + (bi->ask.size / 2);
3051    if (pos < (bi->ask.res / 3))
3052      { 
3053         /* hooked to start */
3054         bi->ask.size = size;
3055      }
3056    else if (pos > ((2 * bi->ask.res) / 3))
3057      { 
3058         /* hooked to end */
3059         bi->ask.pos = (bi->ask.pos + bi->ask.size) - size;
3060         bi->ask.size = size;
3061      }
3062    else
3063      { 
3064         /* hooked to middle */
3065         if ((bi->ask.pos <= (bi->ask.res / 2)) &&
3066             ((bi->ask.pos + bi->ask.size) > (bi->ask.res / 2)))
3067           { 
3068              /* straddles middle */
3069              if (bi->ask.res > 2)
3070                bi->ask.pos = (bi->ask.res / 2) +
3071                (((bi->ask.pos + (bi->ask.size / 2) -
3072                   (bi->ask.res / 2)) *
3073                  (bi->ask.res / 2)) /
3074                 (bi->ask.res / 2)) - (bi->ask.size / 2);
3075              else
3076                bi->x = bi->ask.res / 2;
3077              bi->ask.size = size;
3078           }
3079         else
3080           { 
3081              if (pos < (bi->ask.res / 2))
3082                {
3083                   bi->ask.pos = (bi->ask.pos + bi->ask.size) - size;
3084                   bi->ask.size = size;
3085                }
3086              else
3087                bi->ask.size = size;
3088           }
3089         bi->ask.size = size;
3090      }
3091    _e_gadcon_layout_smart_reconfigure(bi->sd);
3092 }
3093
3094 /* called when a users moves/resizes the gadcon client explicitly */
3095 static void
3096 e_gadcon_layout_pack_request_set(Evas_Object *obj, int pos, int size)
3097 {
3098    E_Gadcon_Layout_Item *bi;
3099
3100    if (!obj) return;
3101    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3102    if (!bi) return;
3103
3104    bi->ask.res = bi->sd->w;
3105    if (pos < 0) pos = 0;
3106    if ((bi->ask.res - pos) < size) pos = bi->ask.res - size;
3107    bi->ask.size = size;
3108    bi->ask.pos = pos;
3109    _e_gadcon_layout_smart_reconfigure(bi->sd);
3110 }
3111
3112 /* called when restoring config from saved config */
3113 static void
3114 e_gadcon_layout_pack_options_set(Evas_Object *obj, E_Gadcon_Client *gcc)
3115 {
3116    int ok, seq;
3117    Eina_List *l;
3118    Evas_Object *item;
3119    E_Gadcon_Layout_Item *bi, *bi2;
3120
3121    if (!obj) return;
3122    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3123    if (!bi) return;
3124    bi->ask.res = gcc->config.res;
3125    bi->ask.size = gcc->config.size;
3126    bi->ask.pos = gcc->config.pos;
3127    bi->gcc = gcc;
3128
3129    ok = 0;
3130    if (!gcc->state_info.seq) ok = 1;
3131
3132    seq = 1;
3133    EINA_LIST_FOREACH(bi->sd->items, l, item)
3134      {
3135         bi2 = evas_object_data_get(item, "e_gadcon_layout_data");
3136         if (bi == bi2) continue;
3137         if (bi->gcc->state_info.seq == bi2->gcc->state_info.seq)
3138           ok = 1;
3139
3140         if (bi2->gcc->state_info.seq > seq)
3141           seq = bi2->gcc->state_info.seq;
3142      }
3143
3144    if (ok)
3145      { 
3146         gcc->state_info.seq = seq + 1; 
3147         gcc->state_info.want_save = 1;
3148         gcc->state_info.flags = E_GADCON_LAYOUT_ITEM_LOCK_NONE;
3149      }
3150    _e_gadcon_layout_smart_reconfigure(bi->sd); 
3151 }
3152
3153 static void
3154 e_gadcon_layout_pack_min_size_set(Evas_Object *obj, int w, int h)
3155 {
3156    E_Gadcon_Layout_Item *bi;
3157
3158    if (!obj) return;
3159    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3160    if (!bi) return;
3161    if (bi->sd->horizontal)
3162      {
3163         bi->min.w = w;
3164         bi->min.h = h;
3165      }
3166    else
3167      {
3168         bi->min.w = h;
3169         bi->min.h = w;
3170      }
3171    
3172    _e_gadcon_layout_smart_reconfigure(bi->sd);
3173 }
3174
3175 static void
3176 e_gadcon_layout_pack_aspect_set(Evas_Object *obj, int w, int h)
3177 {
3178    E_Gadcon_Layout_Item *bi;
3179
3180    if (!obj) return;
3181    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3182    if (!bi) return;
3183    if (bi->sd->horizontal)
3184      {
3185         bi->aspect.w = w;
3186         bi->aspect.h = h;
3187      }
3188    else
3189      {
3190         bi->aspect.w = h;
3191         bi->aspect.h = w;
3192      }
3193      
3194    _e_gadcon_layout_smart_reconfigure(bi->sd);
3195 }
3196
3197 static void
3198 e_gadcon_layout_pack_aspect_pad_set(Evas_Object *obj, int w, int h)
3199 {
3200    E_Gadcon_Layout_Item *bi;
3201
3202    if (!obj) return;
3203    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3204    if (!bi) return;
3205    if (bi->sd->horizontal)
3206      {
3207         bi->aspect_pad.w = w;
3208         bi->aspect_pad.h = h;
3209      }
3210    else
3211      {
3212         bi->aspect_pad.w = h;
3213         bi->aspect_pad.h = w;
3214      }   
3215 }
3216
3217 static void
3218 e_gadcon_layout_unpack(Evas_Object *obj)
3219 {
3220    E_Gadcon_Layout_Item *bi;
3221    E_Smart_Data *sd;
3222
3223    if (!obj) return;
3224    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3225    if (!bi) return;
3226    sd = bi->sd;
3227    if (!sd) return;
3228    sd->items = eina_list_remove(sd->items, obj);
3229    _e_gadcon_layout_smart_disown(obj);
3230    _e_gadcon_layout_smart_reconfigure(sd);
3231 }
3232
3233 /* local subsystem functions */
3234 static E_Gadcon_Layout_Item *
3235 _e_gadcon_layout_smart_adopt(E_Smart_Data *sd, Evas_Object *obj)
3236 {
3237    E_Gadcon_Layout_Item *bi;
3238
3239    if (!obj) return NULL;
3240    bi = E_NEW(E_Gadcon_Layout_Item, 1);
3241    if (!bi) return NULL;
3242    bi->sd = sd;
3243    bi->obj = obj;
3244    /* defaults */
3245    evas_object_clip_set(obj, sd->clip);
3246    evas_object_smart_member_add(obj, bi->sd->obj);
3247    evas_object_data_set(obj, "e_gadcon_layout_data", bi);
3248    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
3249                                   _e_gadcon_layout_smart_item_del_hook, NULL);
3250    if ((!evas_object_visible_get(sd->clip)) &&
3251        (evas_object_visible_get(sd->obj)))
3252      evas_object_show(sd->clip);
3253    return bi;
3254 }
3255
3256 static void
3257 _e_gadcon_layout_smart_disown(Evas_Object *obj)
3258 {
3259    E_Gadcon_Layout_Item *bi;
3260
3261    if (!obj) return;
3262    bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3263    if (!bi) return;
3264    if (!bi->sd->items)
3265      {
3266         if (evas_object_visible_get(bi->sd->clip))
3267           evas_object_hide(bi->sd->clip);
3268      }
3269    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL,
3270                                   _e_gadcon_layout_smart_item_del_hook);
3271    evas_object_smart_member_del(obj);
3272    evas_object_clip_unset(obj);
3273    evas_object_data_del(obj, "e_gadcon_layout_data");
3274    E_FREE(bi);
3275 }
3276
3277 static void
3278 _e_gadcon_layout_smart_item_del_hook(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
3279 {
3280    if (!obj) return;
3281    e_gadcon_layout_unpack(obj);
3282 }
3283
3284 static void
3285 _e_gadcon_layout_smart_reconfigure(E_Smart_Data *sd)
3286 {
3287    Evas_Coord xx, yy;
3288    Eina_List *l;
3289    Evas_Object *obj;
3290    int min, mino, cur;
3291    Eina_List *list = NULL;
3292    E_Gadcon_Layout_Item *bi;
3293    E_Layout_Item_Container *lc;
3294    int i, set_prev_pos = 0;
3295    static int recurse = 0;
3296
3297    if (sd->frozen) return;
3298    if (sd->doing_config)
3299      {
3300         sd->redo_config = 1;
3301         return;
3302      }
3303
3304    recurse++;
3305    min = mino = cur = 0;
3306
3307    _e_gadcon_layout_smart_min_cur_size_calc(sd, &min, &mino, &cur); 
3308
3309    if ((sd->minw != min) || (sd->minh != mino))
3310      {
3311         sd->minw = min;
3312         sd->minh = mino;
3313         evas_object_smart_callback_call(sd->obj, "min_size_request", NULL);
3314      }
3315
3316    if (sd->req != cur)
3317      {
3318         if (cur >= sd->minw)
3319           {
3320              sd->req = cur;
3321              evas_object_smart_callback_call(sd->obj, "size_request", NULL);
3322           }
3323         else
3324           {
3325              sd->req = sd->minw;     
3326           }
3327      }
3328    if (recurse == 1) _e_gadcon_layout_smart_gadcons_width_adjust(sd, min, cur);
3329
3330    if (sd->w <= sd->req)
3331      { 
3332         _e_gadcon_layout_smart_gadcon_position_shrinked_mode(sd);
3333         set_prev_pos = 0;
3334      }
3335    else
3336      { 
3337         _e_gadcon_layout_smart_gadcons_asked_position_set(sd);
3338
3339         list = _e_gadcon_layout_smart_gadcons_wrap(sd);
3340
3341         _e_gadcon_layout_smart_gadcons_position(sd, &list);
3342
3343         EINA_LIST_FREE(list, lc)
3344           LC_FREE(lc);
3345
3346         set_prev_pos = 1;
3347      }
3348
3349    sd->items = eina_list_sort(sd->items, eina_list_count(sd->items),
3350                               _e_gadcon_layout_smart_sort_by_position_cb);
3351    i = 1;
3352    EINA_LIST_FOREACH(sd->items, l, obj)
3353      {
3354         bi = evas_object_data_get(obj, "e_gadcon_layout_data"); 
3355         if (bi->gcc->gadcon->editing) bi->gcc->state_info.seq = i; 
3356
3357         if (set_prev_pos)
3358           {
3359             bi->ask.prev_pos = bi->x; 
3360             bi->ask.prev_size = bi->w;
3361           }
3362
3363         if ((bi->x == bi->ask.pos) &&
3364             (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION))
3365           bi->gcc->state_info.flags |= E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
3366
3367         if ((bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION) &&
3368             (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE))
3369           {
3370             if (bi->x != bi->ask.pos)
3371               bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
3372           }
3373         i++;
3374      } 
3375
3376    EINA_LIST_FOREACH(sd->items, l, obj)
3377      {
3378         E_Gadcon_Layout_Item *bi;
3379
3380         bi = evas_object_data_get(obj, "e_gadcon_layout_data");
3381         if (!bi) continue;
3382
3383         bi->h = sd->h;
3384         xx = sd->x + bi->x;
3385         yy = sd->y; // + ((sd->h - bi->h) / 2);
3386         
3387         if (sd->horizontal)
3388           {
3389              evas_object_move(obj, xx, yy);
3390              evas_object_resize(obj, bi->w, bi->h);
3391           }
3392         else
3393           {
3394              evas_object_move(obj, yy, xx);
3395              evas_object_resize(obj, bi->h, bi->w);
3396           }
3397      }
3398    sd->doing_config = 0;
3399    if (sd->redo_config)
3400      {
3401         _e_gadcon_layout_smart_reconfigure(sd);
3402         sd->redo_config = 0;
3403      }
3404
3405    if ((sd->minw != min) || (sd->minh != mino))
3406      {
3407         sd->minw = min;
3408         sd->minh = mino;
3409         evas_object_smart_callback_call(sd->obj, "min_size_request", NULL);
3410      }
3411
3412    if (sd->req != cur)
3413      {
3414           if (cur >= sd->minw)
3415           {
3416              sd->req = cur;
3417              evas_object_smart_callback_call(sd->obj, "size_request", NULL);
3418           }
3419      }
3420    recurse--;
3421 }
3422
3423 static void
3424 _e_gadcon_layout_smart_init(void)
3425 {
3426    if (_e_smart) return;
3427      {
3428         static const Evas_Smart_Class sc =
3429           {
3430              "e_gadcon_layout",
3431                EVAS_SMART_CLASS_VERSION,
3432                _e_gadcon_layout_smart_add,
3433                _e_gadcon_layout_smart_del,
3434                _e_gadcon_layout_smart_move,
3435                _e_gadcon_layout_smart_resize,
3436                _e_gadcon_layout_smart_show,
3437                _e_gadcon_layout_smart_hide,
3438                _e_gadcon_layout_smart_color_set,
3439                _e_gadcon_layout_smart_clip_set,
3440                _e_gadcon_layout_smart_clip_unset,
3441                NULL, NULL, NULL, NULL, NULL, NULL, NULL
3442           };
3443         _e_smart = evas_smart_class_new(&sc);
3444      }
3445 }
3446
3447 static void
3448 _e_gadcon_layout_smart_add(Evas_Object *obj)
3449 {
3450    E_Smart_Data *sd;
3451
3452    if (!obj) return;
3453    sd = calloc(1, sizeof(E_Smart_Data));
3454    if (!sd) return;
3455    sd->obj = obj;
3456    sd->x = 0;
3457    sd->y = 0;
3458    sd->w = 0;
3459    sd->h = 0;
3460    sd->clip = evas_object_rectangle_add(evas_object_evas_get(obj));
3461    sd->horizontal = 1;
3462    evas_object_smart_member_add(sd->clip, obj);
3463    evas_object_move(sd->clip, -100005, -100005);
3464    evas_object_resize(sd->clip, 200010, 200010);
3465    evas_object_color_set(sd->clip, 255, 255, 255, 255);
3466    evas_object_smart_data_set(obj, sd);
3467 }
3468    
3469 static void
3470 _e_gadcon_layout_smart_del(Evas_Object *obj)
3471 {
3472    E_Smart_Data *sd;
3473
3474    if (!obj) return;
3475    sd = evas_object_smart_data_get(obj);
3476    if (!sd) return;
3477    while (sd->items)
3478      {
3479         Evas_Object *child;
3480
3481         child = eina_list_data_get(sd->items);
3482         e_gadcon_layout_unpack(child);
3483      }
3484    evas_object_del(sd->clip);
3485    free(sd);
3486 }
3487
3488 static void
3489 _e_gadcon_layout_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
3490 {
3491    E_Smart_Data *sd;
3492
3493    if (!obj) return;
3494    sd = evas_object_smart_data_get(obj);
3495    if (!sd) return;
3496    if ((x == sd->x) && (y == sd->y)) return;
3497      {
3498         Eina_List *l;
3499         Evas_Object *item;
3500         Evas_Coord dx, dy;
3501
3502         if (sd->horizontal)
3503           {
3504              dx = x - sd->x;
3505              dy = y - sd->y;
3506           }
3507         else
3508           {
3509              dx = x - sd->y;
3510              dy = y - sd->x;
3511           }
3512         
3513         EINA_LIST_FOREACH(sd->items, l, item)
3514           {
3515              Evas_Coord ox, oy;
3516
3517              evas_object_geometry_get(item, &ox, &oy, NULL, NULL);
3518              evas_object_move(item, ox + dx, oy + dy);
3519           }
3520      }
3521
3522      if (sd->horizontal)
3523        {
3524           sd->x = x;
3525           sd->y = y;
3526        }
3527      else
3528        {
3529           sd->x = y;
3530           sd->y = x;
3531        }
3532 }
3533
3534 static void
3535 _e_gadcon_layout_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
3536 {
3537    E_Smart_Data *sd;
3538
3539    if (!obj) return;
3540    sd = evas_object_smart_data_get(obj);
3541    if (!sd) return;
3542    if ((w == sd->w) && (h == sd->h)) return;
3543    if (sd->horizontal)
3544      {  
3545         sd->w = w;
3546         sd->h = h;
3547      }
3548    else
3549      {
3550         sd->w = h;
3551         sd->h = w;
3552
3553      }
3554    
3555    _e_gadcon_layout_smart_reconfigure(sd);
3556 }
3557
3558 static void
3559 _e_gadcon_layout_smart_show(Evas_Object *obj)
3560 {
3561    E_Smart_Data *sd;
3562
3563    if (!obj) return;
3564    sd = evas_object_smart_data_get(obj);
3565    if (!sd) return;
3566    if (sd->items) evas_object_show(sd->clip);
3567 }
3568
3569 static void
3570 _e_gadcon_layout_smart_hide(Evas_Object *obj)
3571 {
3572    E_Smart_Data *sd;
3573
3574    if (!obj) return;
3575    sd = evas_object_smart_data_get(obj);
3576    if (!sd) return;
3577    evas_object_hide(sd->clip);
3578 }
3579
3580 static void
3581 _e_gadcon_layout_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
3582 {
3583    E_Smart_Data *sd;
3584
3585    if (!obj) return;
3586    sd = evas_object_smart_data_get(obj);
3587    if (!sd) return;   
3588    evas_object_color_set(sd->clip, r, g, b, a);
3589 }
3590
3591 static void
3592 _e_gadcon_layout_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
3593 {
3594    E_Smart_Data *sd;
3595
3596    if (!obj) return;
3597    sd = evas_object_smart_data_get(obj);
3598    if (!sd) return;
3599    evas_object_clip_set(sd->clip, clip);
3600 }
3601
3602 static void
3603 _e_gadcon_layout_smart_clip_unset(Evas_Object *obj)
3604 {
3605    E_Smart_Data *sd;
3606
3607    if (!obj) return;
3608    sd = evas_object_smart_data_get(obj);
3609    if (!sd) return;
3610    evas_object_clip_unset(sd->clip);
3611 }  
3612
3613 /*
3614  * @min - the minimum width required by all the gadcons
3615  * @cur - the current width required by all the gadcons
3616  * @mino - the smalest width/height among all the objects
3617  */
3618 static void
3619 _e_gadcon_layout_smart_min_cur_size_calc(E_Smart_Data *sd, int *min, int *mino, int *cur)
3620 {
3621    E_Gadcon_Layout_Item *bi;
3622    Eina_List *l;
3623    Evas_Object *item;
3624
3625    EINA_LIST_FOREACH(sd->items, l, item)
3626      {
3627         bi = evas_object_data_get(item, "e_gadcon_layout_data");
3628         bi->ask.size2 = bi->ask.size;
3629
3630         if ((bi->aspect.w > 0) && (bi->aspect.h > 0))
3631           {
3632              bi->ask.size2 =
3633                (((sd->h - bi->aspect_pad.h) * bi->aspect.w) / bi->aspect.h) + bi->aspect_pad.w;
3634              
3635              if (bi->ask.size2 > bi->min.w)
3636                {
3637                   *min += bi->ask.size2;
3638                   *cur += bi->ask.size2;
3639                }
3640              else
3641                {
3642                   *min += bi->min.w;
3643                   *cur += bi->min.w;
3644                }
3645           }
3646         else
3647           {
3648              bi->ask.size2 = bi->ask.size = bi->min.w;
3649              *min += bi->min.w;
3650              if (bi->min.h > *mino) *mino = bi->min.h;
3651              if (bi->ask.size < bi->min.w)
3652                *cur += bi->min.w;
3653              else
3654                *cur += bi->ask.size;
3655           }
3656      }
3657 }
3658
3659 static int 
3660 _e_gadcon_layout_smart_width_smart_sort_reverse_cb(const void *d1, const void *d2)
3661 {
3662    const E_Gadcon_Layout_Item *bi, *bi2;
3663
3664    bi = evas_object_data_get(d1, "e_gadcon_layout_data");
3665    bi2 = evas_object_data_get(d2, "e_gadcon_layout_data"); 
3666
3667    if (bi->ask.size2 > bi->min.w)
3668      {
3669         if (bi2->ask.size2 > bi2->min.w) 
3670           { 
3671              if (bi->ask.size2 < bi2->ask.size2)
3672                return 1;
3673              else
3674                return -1;
3675           }
3676         else
3677           {
3678              if (bi->ask.size2 == bi2->ask.size2)
3679                return -1;
3680              else
3681                { 
3682                   if (bi->ask.size2 < bi2->ask.size2)
3683                     return 1;
3684                   else
3685                     return -1;
3686                }
3687           }
3688      }
3689    else
3690      {
3691         if (bi2->ask.size2 > bi2->min.w)
3692           {
3693              if (bi->ask.size2 == bi2->ask.size2)
3694                return 1;
3695              else
3696                { 
3697                   if (bi->ask.size2 < bi2->ask.size2)
3698                     return 1;
3699                   else
3700                     return -1;
3701                }
3702           }
3703         else
3704           { 
3705              if (bi->ask.size2 < bi2->ask.size2)
3706                return 1;
3707              else if (bi->ask.size2 > bi2->ask.size2)
3708                return -1;
3709           }
3710      }
3711
3712    return 0;
3713 }
3714
3715 static void 
3716 _e_gadcon_layout_smart_gadcons_width_adjust(E_Smart_Data *sd, int min, int cur)
3717
3718    E_Gadcon_Layout_Item *bi = NULL;
3719    Eina_List *l, *l2;
3720    Evas_Object *item;
3721    int needed = 0;
3722    int need = 0;
3723    int max_size, autosize = 0;
3724
3725    if (sd->w < cur)
3726      {
3727         if (sd->w < min) max_size = min;
3728         else max_size = cur;
3729         need = max_size - sd->w;
3730      }
3731    else
3732      return;
3733    
3734    sd->items = eina_list_sort(sd->items, eina_list_count(sd->items), 
3735                               _e_gadcon_layout_smart_width_smart_sort_reverse_cb);
3736    EINA_LIST_FOREACH(sd->items, l, item)
3737      { 
3738         bi = evas_object_data_get(item, "e_gadcon_layout_data");
3739         if (bi->gcc->autoscroll) autosize += bi->ask.size2;
3740      } 
3741
3742    if (autosize < 1) autosize = 1;
3743    while (need > 0)
3744      { 
3745         needed = need;
3746         EINA_LIST_REVERSE_FOREACH(sd->items, l2, item)
3747           { 
3748              if (need <= 0) break;
3749              bi = evas_object_data_get(item, "e_gadcon_layout_data");
3750              if (bi->gcc->autoscroll)
3751                {
3752                   int reduce_by; 
3753                   
3754                   reduce_by = (need * bi->ask.size2) / autosize;
3755                   if (reduce_by < 1) reduce_by = 1;
3756                   if (bi->ask.size2 - reduce_by > 8)
3757                     {
3758                        bi->ask.size2 -= reduce_by;
3759                        need -= reduce_by ; 
3760                     }
3761                   else
3762                     {
3763                        need -= bi->ask.size2 - 8;
3764                        bi->ask.size2 = 8;
3765                     }
3766                }
3767           } 
3768         /* If the 'needed' size change didn't get modified (no gadget has autoscroll)
3769            then we must break or we end up in an infinite loop */
3770         if (need == needed) break;
3771      }
3772 }
3773
3774 static int 
3775 _e_gadcon_layout_smart_sort_by_sequence_number_cb(const void *d1, const void *d2)
3776 {
3777    const E_Gadcon_Layout_Item *bi, *bi2;
3778
3779    bi = evas_object_data_get(d1, "e_gadcon_layout_data");
3780    bi2 = evas_object_data_get(d2, "e_gadcon_layout_data");
3781
3782    if ((!bi->gcc->state_info.seq) && (!bi2->gcc->state_info.seq)) return 0;
3783    else if (!bi->gcc->state_info.seq) return 1;
3784    else if (!bi2->gcc->state_info.seq) return -1;
3785    return bi->gcc->state_info.seq - bi2->gcc->state_info.seq;
3786
3787
3788 static int
3789 _e_gadcon_layout_smart_sort_by_position_cb(const void *d1, const void *d2)
3790 {
3791    const E_Gadcon_Layout_Item *bi, *bi2;
3792
3793    bi = evas_object_data_get(d1, "e_gadcon_layout_data");
3794    bi2 = evas_object_data_get(d2, "e_gadcon_layout_data");
3795
3796    return (bi->x - bi2->x);
3797 }
3798
3799 static int
3800 _e_gadcon_layout_smart_containers_sort_cb(const void *d1, const void *d2)
3801 {
3802    const E_Layout_Item_Container *lc, *lc2;
3803
3804    lc = d1;
3805    lc2 = d2;
3806    if (lc->pos < lc2->pos) return -1;
3807    else if (lc->pos > lc2->pos) return 1;
3808    return 0;
3809 }
3810
3811 static int
3812 _e_gadcon_layout_smart_seq_sort_cb(const void *d1, const void *d2)
3813 {
3814    const E_Gadcon_Layout_Item *bi, *bi2;
3815
3816    bi = d1;
3817    bi2 = d2;
3818    return (bi->gcc->state_info.seq - bi2->gcc->state_info.seq);
3819 }
3820
3821 static void
3822 _e_gadcon_layout_smart_sync_clients(E_Gadcon *gc)
3823 {
3824    E_Gadcon_Client *gcc;
3825    Eina_List *l;
3826
3827    EINA_LIST_FOREACH(gc->clients, l, gcc)
3828      {
3829         _e_gadcon_client_save(gcc);
3830      }
3831 }
3832
3833 static void
3834 _e_gadcon_client_current_position_sync(E_Gadcon_Client *gcc)
3835 {
3836    E_Gadcon_Layout_Item *bi;
3837    Evas_Object *o;
3838
3839    o = gcc->o_frame ? gcc->o_frame : gcc->o_base;
3840    if (o)
3841      {
3842         bi = evas_object_data_get(o, "e_gadcon_layout_data");
3843         if (!bi) return;
3844      }
3845    else return; /* make clang happy */
3846
3847    gcc->state_info.prev_pos = gcc->config.pos;
3848    gcc->state_info.prev_size = gcc->config.size;
3849    gcc->config.pos = bi->x;
3850 }
3851
3852 static void
3853 _e_gadcon_layout_smart_gadcon_position_shrinked_mode(E_Smart_Data *sd)
3854
3855    Eina_List *l;
3856    Evas_Object *item;
3857    E_Gadcon_Layout_Item *bi, *bi2; 
3858    void *tp; 
3859    int pos = 0; 
3860
3861    sd->items = eina_list_sort(sd->items, eina_list_count(sd->items),
3862                               _e_gadcon_layout_smart_sort_by_sequence_number_cb); 
3863    EINA_LIST_FOREACH(sd->items, l, item)
3864      { 
3865         bi = evas_object_data_get(item, "e_gadcon_layout_data"); 
3866         if (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_POS_INC) 
3867           { 
3868              if (bi->gcc->state_info.resist <= E_LAYOUT_ITEM_DRAG_RESIST_LEVEL) 
3869                { 
3870                   bi->gcc->state_info.resist++; 
3871                   bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
3872                } 
3873              else
3874                { 
3875                   bi->gcc->state_info.resist = 0; 
3876                   if (eina_list_next(l)) 
3877                     { 
3878                        tp = eina_list_data_get(eina_list_next(l));
3879                        l->next->data = eina_list_data_get(l); 
3880                        l->data = tp; 
3881
3882                        bi2 = evas_object_data_get(tp, "e_gadcon_layout_data");
3883                        
3884                        if (bi2->x + bi2->w/2 > bi->ask.pos + bi->w)
3885                          {
3886                             bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
3887                             return;
3888                          }
3889                        
3890                        bi->gcc->config.pos = bi->ask.pos = bi2->ask.pos;
3891                        bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
3892                        bi->gcc->state_info.want_save = 1;
3893                        bi2->gcc->state_info.want_save = 1;
3894                        break;
3895                     }
3896                   else
3897                     bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
3898                } 
3899           } 
3900         else if (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_POS_DEC)
3901           { 
3902              if (bi->gcc->state_info.resist <= E_LAYOUT_ITEM_DRAG_RESIST_LEVEL)
3903                {
3904                   bi->gcc->state_info.resist++;
3905                   bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
3906                }
3907              else
3908                {
3909                   bi->gcc->state_info.resist = 0; 
3910                   if (eina_list_prev(l))
3911                     { 
3912                        E_Gadcon_Layout_Item *bi2;
3913                        void *tp;
3914
3915                        tp = eina_list_data_get(eina_list_prev(l));
3916                        l->prev->data = eina_list_data_get(l);
3917
3918                        l->data = tp; 
3919                        bi2 = evas_object_data_get(tp, "e_gadcon_layout_data");
3920
3921                        if (bi->ask.pos > bi2->x + bi2->w/2)
3922                          {
3923                             bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
3924                             return;
3925                          }
3926
3927                        bi->gcc->config.pos = bi->ask.pos = bi2->ask.pos;
3928                        bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
3929                        bi->gcc->state_info.want_save = 1;
3930                        bi2->gcc->state_info.want_save = 1;
3931                        break;
3932                     }
3933                   else
3934                     bi->gcc->config.pos = bi->ask.pos = bi->gcc->state_info.prev_pos;
3935                }
3936           }
3937         else if ((bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_SIZE_MIN_END_INC) ||
3938                  (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_SIZE_MAX_END_DEC) ||
3939                  (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_SIZE_MIN_END_DEC) ||
3940                  (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_SIZE_MAX_END_INC))
3941           { 
3942              if (bi->w < bi->min.w) 
3943                bi->gcc->config.size = bi->w = bi->min.w;
3944              else
3945                bi->gcc->config.size = bi->w;
3946
3947              bi->gcc->config.pos = bi->gcc->state_info.prev_pos;
3948           }     
3949      } 
3950
3951    EINA_LIST_FOREACH(sd->items, l, item)
3952      { 
3953         bi = evas_object_data_get(item, "e_gadcon_layout_data");
3954
3955         bi->x = pos;
3956         bi->w = bi->ask.size2; 
3957         bi->gcc->config.size = bi->w;
3958         pos = bi->x + bi->w;
3959      }
3960 }
3961
3962 static void
3963 _e_gadcon_layout_smart_gadcons_asked_position_set(E_Smart_Data *sd)
3964 {
3965    E_Gadcon_Layout_Item *bi;
3966    Eina_List *l;
3967    Evas_Object *item;
3968
3969 #if 0
3970    EINA_LIST_FOREACH(sd->items, l, item)
3971      {
3972         bi = evas_object_data_get(item, "e_gadcon_layout_data");
3973         if (!bi) continue;
3974         
3975         bi->x = bi->ask.pos;
3976         bi->w = bi->ask.size2;
3977      }
3978 #else
3979    int pos;
3980    EINA_LIST_FOREACH(sd->items, l, item)
3981      {
3982         bi = evas_object_data_get(item, "e_gadcon_layout_data");
3983         if (!bi) continue;
3984
3985         pos = bi->ask.pos + (bi->ask.size / 2);
3986         if (pos < (bi->ask.res / 3))
3987           { 
3988              /* hooked to start */
3989              bi->x = bi->ask.pos;
3990              bi->w = bi->ask.size2;
3991              bi->hookp = 0;
3992           }
3993         else if (pos > ((2 * bi->ask.res) / 3))
3994           { 
3995              /* hooked to end */
3996              bi->x = (bi->ask.pos - bi->ask.res) + sd->w;
3997              bi->w = bi->ask.size2;
3998              bi->hookp = bi->ask.res;
3999           }
4000         else
4001           { 
4002              /* hooked to middle */
4003              if ((bi->ask.pos <= (bi->ask.res / 2)) &&
4004                  ((bi->ask.pos + bi->ask.size2) > (bi->ask.res / 2)))
4005                { 
4006                   /* straddles middle */
4007                   if (bi->ask.res > 2)
4008                     bi->x = (sd->w / 2) + 
4009                       (((bi->ask.pos + (bi->ask.size2 / 2) - 
4010                          (bi->ask.res / 2)) * 
4011                         (bi->ask.res / 2)) /
4012                        (bi->ask.res / 2)) - (bi->ask.size2 / 2);
4013                   else
4014                     bi->x = sd->w / 2;
4015                   bi->w = bi->ask.size2;
4016                }
4017              else
4018                { 
4019                   /* either side of middle */
4020                   bi->x = (bi->ask.pos - (bi->ask.res / 2)) + (sd->w / 2);
4021                   bi->w = bi->ask.size2;
4022                }
4023              bi->hookp = bi->ask.res / 2;
4024           }
4025      }
4026 #endif
4027 }
4028
4029 /* 
4030  * The function returns a list of E_Gadcon_Layout_Item_Container
4031  */
4032 static Eina_List *
4033 _e_gadcon_layout_smart_gadcons_wrap(E_Smart_Data *sd)
4034 {
4035    Eina_List *l, *list = NULL;
4036    Evas_Object *item;
4037    E_Layout_Item_Container *lc;
4038    E_Gadcon_Layout_Item *bi;
4039
4040    
4041    EINA_LIST_FOREACH(sd->items, l, item)
4042      {
4043         bi = evas_object_data_get(item, "e_gadcon_layout_data");
4044         lc = E_NEW(E_Layout_Item_Container, 1);
4045         lc->state_info.min_seq = lc->state_info.max_seq = bi->gcc->state_info.seq;
4046         lc->sd = sd;
4047
4048         lc->pos = bi->x;
4049         lc->size = bi->w;
4050
4051         lc->prev_pos = bi->ask.prev_pos;
4052         lc->prev_size = bi->ask.prev_size;
4053
4054         E_LAYOUT_ITEM_CONTAINER_STATE_SET(lc->state, bi->gcc->state_info.state);
4055
4056         if ((bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION) &&
4057             (lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
4058           lc->state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
4059
4060         lc->items = eina_list_append(lc->items, bi);
4061         list = eina_list_append(list, lc);
4062      }
4063    return list;
4064 }
4065
4066 static void
4067 _e_gadcon_layout_smart_gadcons_position(E_Smart_Data *sd, Eina_List **list)
4068 {
4069    int ok, lc_moving_prev_pos;
4070    Eina_List *l, *l2, *l3;
4071    E_Layout_Item_Container *lc_moving = NULL, *lc_back = NULL, *lc, *lc3;
4072    E_Gadcon_Layout_Item *bi, *bi_moving = NULL;
4073
4074    if ((!list) || (!*list)) return;
4075
4076    EINA_LIST_FOREACH(*list, l, lc_moving)
4077      {
4078         if ((lc_moving->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
4079             (lc_moving->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED))
4080           {
4081              lc_back = E_NEW(E_Layout_Item_Container, 1);
4082              lc_back->pos = lc_moving->pos;
4083              lc_back->prev_pos = lc_moving->prev_pos;
4084              lc_back->size = lc_moving->size;
4085              lc_back->prev_size = lc_moving->prev_size;
4086              lc_back->state_info.min_seq = lc_moving->state_info.min_seq;
4087              lc_back->state_info.max_seq = lc_moving->state_info.max_seq;
4088              lc_back->sd = lc_moving->sd;
4089              EINA_LIST_FOREACH(lc_moving->items, l2, lc)
4090                lc_back->items = eina_list_append(lc_back->items, lc);
4091              lc_back->state = lc_moving->state;
4092              bi_moving = eina_list_data_get(lc_back->items);
4093              
4094              break;
4095           }
4096         lc_moving = NULL;
4097      }
4098
4099    if (!lc_moving)
4100      {
4101         _e_gadcon_layout_smart_gadcons_position_static(sd, list);
4102         return;
4103      } 
4104
4105    lc_moving_prev_pos = lc_moving->prev_pos;
4106    if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC) 
4107      { 
4108         _e_gadcon_layout_smart_restore_gadcons_position_before_move(sd, &lc_moving, lc_back, list); 
4109         EINA_LIST_FOREACH(*list, l, lc)
4110            if (lc == lc_moving) break;
4111
4112         ok = 0;
4113         if ((l) && eina_list_prev(l))
4114           {
4115              lc = eina_list_data_get(eina_list_prev(l));
4116
4117              if (lc_moving->pos < (lc->pos + lc->size))
4118                {
4119                   bi = eina_list_data_get(lc_moving->items);
4120                   if (bi->gcc->state_info.resist <= E_LAYOUT_ITEM_DRAG_RESIST_LEVEL)
4121                     {
4122                        if (lc_moving->prev_pos == (lc->pos + lc->size))
4123                          ok = 1;
4124                        bi->gcc->state_info.resist++;
4125                        lc_moving->pos = lc->pos + lc->size;
4126                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4127                     }
4128                   else
4129                     {
4130                        bi->gcc->state_info.resist = 0;
4131                        if (lc_moving->pos < lc->pos) 
4132                          { 
4133                             lc_moving->pos = (lc->pos + lc->size) - 1;
4134                             _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4135                          }
4136                        lc3 = _e_gadcon_layout_smart_containers_position_adjust(sd, lc, lc_moving);
4137                        if (lc3)
4138                          {
4139                             if (lc_moving->prev_pos == (lc->pos + lc->size))
4140                               ok = 1;
4141
4142                             l->data = lc3;
4143                             *list = eina_list_remove_list(*list, eina_list_prev(l));
4144                             LC_FREE(lc_moving);
4145                             LC_FREE(lc);
4146                             lc_moving = lc3;
4147                          }
4148                     }
4149                }
4150           }
4151         if (!ok) 
4152           { 
4153              int pos, prev_pos, stop;
4154
4155              EINA_LIST_FOREACH(*list, l, lc)
4156                 if (lc == lc_moving) break;
4157
4158              pos = lc_moving->pos + lc_moving->size;
4159              prev_pos = lc_moving_prev_pos;
4160              if ((l) && (eina_list_next(l)))
4161                { 
4162                   stop = 0;
4163                   EINA_LIST_FOREACH(eina_list_next(l), l2, lc)
4164                     {
4165                        if (stop) break;
4166                        if (lc->pos != prev_pos) break;
4167                        prev_pos = lc->pos + lc->size;
4168
4169                        EINA_LIST_FOREACH(lc->items, l3, bi)
4170                          {
4171                             if (bi->ask.pos <= pos)
4172                               {
4173                                 bi->x = pos;
4174                                 pos = (bi->x) + (bi->w);
4175                               }
4176                             else if (bi->ask.pos < bi->x)
4177                               {
4178                                 bi->x = bi->ask.pos;
4179                                 pos = (bi->x) + (bi->w);                                
4180                               }
4181                             else if (bi->ask.pos == bi->x)
4182                               {
4183                                  stop = 1;
4184                                  break;
4185                               }
4186                          }
4187                     }
4188                }
4189           }
4190      }
4191    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC)
4192      {
4193         _e_gadcon_layout_smart_restore_gadcons_position_before_move(sd, &lc_moving, lc_back, list); 
4194         EINA_LIST_FOREACH(*list, l, lc)
4195            if (lc == lc_moving) break;
4196
4197         ok = 0;
4198         if ((l) && eina_list_next(l))
4199           {
4200              lc = eina_list_data_get(eina_list_next(l));
4201
4202              if ((lc_moving->pos + lc_moving->size) > lc->pos)
4203                {
4204                   bi = eina_list_data_get(lc_moving->items);
4205                   if (bi->gcc->state_info.resist <= E_LAYOUT_ITEM_DRAG_RESIST_LEVEL)
4206                     {
4207                        if ((lc_moving->prev_pos + lc_moving->size) == lc->pos)
4208                          ok = 1;
4209                        bi->gcc->state_info.resist++;
4210                        lc_moving->pos = lc->pos - lc_moving->size;
4211                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4212                     } 
4213                   else
4214                     {
4215                        bi->gcc->state_info.resist = 0;
4216                        if ((lc_moving->pos + lc_moving->size) > lc->pos)
4217                          {
4218                             lc_moving->pos = (lc->pos - lc_moving->size) + 1;
4219                             _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4220                          }
4221                        lc3 = _e_gadcon_layout_smart_containers_position_adjust(sd, lc_moving, lc);
4222                        if (lc3)
4223                          {
4224                             if ((lc_moving->prev_pos + lc_moving->size) == lc->pos)
4225                               ok = 1;
4226
4227                             l->data = lc3;
4228                             *list = eina_list_remove_list(*list, eina_list_next(l));
4229                             LC_FREE(lc_moving);
4230                             LC_FREE(lc);
4231                             lc_moving = lc3;
4232                          }
4233                     }
4234                }
4235           }
4236
4237         if (!ok)
4238           {
4239              int pos, prev_pos, stop;
4240              
4241              EINA_LIST_FOREACH(*list, l, lc)
4242                 if (lc == lc_moving) break;
4243
4244              pos = lc_moving->pos;
4245              prev_pos = lc_moving_prev_pos;
4246
4247              if ((l) && eina_list_prev(l))
4248                {
4249                   stop = 0;
4250                   /* EINA_FUCK_REVERSE_FOREACH(eina_list_prev(l), l2, lc) */
4251                   for (l2 = l->prev; l2; l2 = l2->prev)
4252                     {
4253                        lc = l2->data;
4254                        
4255                        if (stop) break;
4256                        if ((lc->pos + lc->size) == prev_pos) break;
4257                        prev_pos = lc->pos;
4258
4259                        EINA_LIST_REVERSE_FOREACH(lc->items, l3, bi)
4260                          {
4261                             if ((bi->ask.pos + bi->w) >= pos)
4262                               {
4263                                  bi->x = pos - bi->w;
4264                                  pos = bi->x;
4265                               }
4266                             else if (bi->ask.pos > bi->x)
4267                               {
4268                                  bi->x = bi->ask.pos;
4269                                  pos = bi->x;
4270                               }
4271                             else if (bi->ask.pos == bi->x)
4272                               {
4273                                  stop = 1;
4274                                  break;
4275                               }
4276                          }
4277                     }
4278                }
4279           }
4280      } 
4281    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_DEC)
4282      { 
4283         _e_gadcon_layout_smart_restore_gadcons_position_before_move(sd, &lc_moving, lc_back, list); 
4284         EINA_LIST_FOREACH(*list, l, lc)
4285            if (lc == lc_moving) break;
4286
4287         if ((l) && eina_list_prev(l))
4288           {
4289              int new_pos = 0;
4290
4291              ok = 0;
4292              new_pos = lc_moving->pos;
4293              /* EINA_FUCK_REVERSE_FOREACH(eina_list_prev(l), l2, lc) */
4294              for (l2 = l->prev; l2; l2 = l2->prev)
4295                {
4296                   lc = l2->data;                  
4297                   if (new_pos >= (lc->pos + lc->size)) break;
4298
4299                   ok = 1;
4300                   new_pos -= lc->size;
4301                }
4302
4303              if (new_pos < 0)
4304                {
4305                   lc_moving->size += new_pos;
4306                   lc_moving->pos -= new_pos;
4307
4308                   bi = eina_list_data_get(lc_moving->items);
4309                   bi->w = lc_moving->size;
4310                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4311
4312                   new_pos = 0;
4313                }
4314
4315              if (ok)
4316                { 
4317                   if (!l2) l2 = *list; 
4318                   else l2 = eina_list_next(l2);
4319
4320                   EINA_LIST_FOREACH(l2, l2, lc)
4321                     { 
4322                        if (l2 == l) break;
4323                        lc->pos = new_pos; 
4324                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc); 
4325                        EINA_LIST_FOREACH(lc->items, l3, bi)
4326                          {
4327                             bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
4328                          }
4329                        new_pos += lc->size; 
4330                     }
4331                }
4332           }
4333         else if ((l) && (!eina_list_prev(l)))
4334           {
4335              if (lc_moving->pos <= 0)
4336                {
4337                   lc_moving->size = lc_moving->prev_size;
4338                   lc_moving->pos = 0;
4339
4340                   bi = eina_list_data_get(lc_moving->items);
4341                   bi->w = lc_moving->size;
4342
4343                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc_moving);
4344                }
4345           }
4346      }
4347    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_INC)
4348      {
4349         lc_moving->state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
4350         _e_gadcon_layout_smart_gadcons_position_static(sd, list);
4351         if (lc_back) LC_FREE(lc_back);
4352      }
4353    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_INC)
4354      {
4355         _e_gadcon_layout_smart_restore_gadcons_position_before_move(sd, &lc_moving, lc_back, list); 
4356         EINA_LIST_FOREACH(*list, l, lc)
4357            if (lc == lc_moving) break;
4358
4359         if ((l) && eina_list_next(l))
4360           {
4361              Eina_List *stop = NULL;
4362              int new_pos = 0;
4363
4364              ok = 0;
4365              new_pos = lc_moving->pos + lc_moving->size;
4366              EINA_LIST_FOREACH(eina_list_next(l), l2, lc)
4367                {
4368                   if (new_pos <= lc->pos)
4369                     {
4370                        stop = l2;
4371                        break;
4372                     }
4373
4374                   ok = 1;
4375                   /* new_pos += lc->size; */
4376                }
4377
4378              if (new_pos > sd->w)
4379                {
4380                   lc_moving->size -= (new_pos - sd->w);
4381                   bi = eina_list_data_get(lc_moving->items);
4382                   bi->w = lc_moving->size;
4383
4384                   new_pos = lc_moving->pos + lc_moving->size;
4385                }
4386
4387              if (ok)
4388                {
4389                   EINA_LIST_FOREACH(eina_list_next(l), l2, lc)
4390                     {
4391                        if (l2 == stop) break;
4392                        lc->pos = new_pos;
4393                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
4394                        EINA_LIST_FOREACH(lc->items, l3, bi)
4395                          {
4396                             bi->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
4397                          }
4398                        new_pos += lc->size;
4399                     }
4400                }
4401           }
4402         else if ((l) && (!eina_list_next(l)))
4403           {
4404              if ((lc_moving->pos + lc_moving->size) >= sd->w)
4405                {
4406                   lc_moving->size = lc_moving->prev_size;
4407                   bi = eina_list_data_get(lc_moving->items);
4408                   bi->w = lc_moving->size;
4409                }
4410           }
4411      }
4412    else if (lc_moving->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_DEC)
4413      {
4414         lc_moving->state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
4415         _e_gadcon_layout_smart_gadcons_position_static(sd, list);
4416         if (lc_back) LC_FREE(lc_back);
4417      }
4418
4419    if (bi_moving)
4420      {
4421         bi_moving->gcc->config.pos = bi_moving->ask.pos = bi_moving->x; 
4422         bi_moving->gcc->config.size = bi_moving->w;
4423      }
4424 }
4425
4426 static void
4427 _e_gadcon_layout_smart_gadcons_position_static(E_Smart_Data *sd, Eina_List **list)
4428 {
4429    int ok;
4430    Eina_List *l;
4431    E_Layout_Item_Container *lc, *lc2, *lc3;
4432
4433    *list = eina_list_sort(*list, eina_list_count(*list), _e_gadcon_layout_smart_containers_sort_cb);
4434
4435    __reposition_again:
4436    EINA_LIST_FOREACH(*list, l, lc)
4437      {
4438         if (!eina_list_next(l)) continue;
4439
4440         lc2 = eina_list_data_get(eina_list_next(l));
4441
4442         if (LC_OVERLAP(lc, lc2))
4443           {
4444              lc3 = _e_gadcon_layout_smart_containers_position_adjust(sd, lc, lc2);
4445              if (lc3)
4446                { 
4447                   l->data = lc3; 
4448                   *list = eina_list_remove_list(*list, eina_list_next(l)); 
4449                   LC_FREE(lc);
4450                   LC_FREE(lc2);
4451                   goto __reposition_again;
4452                }
4453           }
4454      }
4455
4456    ok = 1;
4457    EINA_LIST_FOREACH(*list, l, lc)
4458      {
4459         if (lc->pos < 0)
4460           {
4461              ok = 0;
4462              lc->pos = 0;
4463              _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
4464              continue;
4465           }
4466
4467         if (((lc->pos + lc->size) > sd->w) && (lc->size <= sd->w))
4468           {
4469              ok = 0;
4470              lc->pos = sd->w - lc->size;
4471              _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
4472           }
4473      }
4474    if (!ok)
4475      _e_gadcon_layout_smart_gadcons_position_static(sd, list);
4476 }
4477
4478 static E_Layout_Item_Container *
4479 _e_gadcon_layout_smart_containers_position_adjust(E_Smart_Data *sd, E_Layout_Item_Container *lc, E_Layout_Item_Container *lc2)
4480 {
4481    int create_new = 0;
4482    Eina_List *l;
4483    E_Layout_Item_Container *lc3 = NULL;
4484    E_Layout_Item_Container_State new_state;
4485    E_Gadcon_Layout_Item *bi, *bi2;
4486
4487    if ((lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
4488        (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
4489      {
4490         if (lc->state_info.max_seq <= lc2->state_info.min_seq)
4491           {
4492              lc2->pos = lc->pos + lc->size;
4493              _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
4494           }
4495         else if (lc->state_info.min_seq > lc2->state_info.max_seq)
4496           {
4497              lc->pos = lc2->pos + lc2->size;
4498              _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
4499           }
4500         else if (((lc->state_info.min_seq > lc2->state_info.min_seq) &&
4501                   (lc->state_info.min_seq < lc2->state_info.max_seq)) ||
4502                  ((lc2->state_info.min_seq > lc->state_info.min_seq) &&
4503                   (lc2->state_info.min_seq < lc->state_info.max_seq)))
4504           {
4505              _e_gadcon_layout_smart_containers_merge(sd, lc, lc2);
4506           } 
4507         create_new = 1; 
4508         new_state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;
4509      }
4510    else if ((lc->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
4511             (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
4512      {
4513         if (lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC)
4514           {
4515              int t;
4516
4517              bi = eina_list_data_get(lc->items);
4518              bi2 = eina_list_data_get(lc2->items);
4519
4520              bi->x = ((bi2->x) + (bi2->w)) - (bi->w);
4521              bi->gcc->config.pos = bi->ask.pos = bi->x;
4522              bi->gcc->config.size = bi->w;
4523              bi2->x = (bi->x) - (bi2->w);
4524
4525              bi2->gcc->state_info.flags &= ~E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE;
4526
4527              t = bi->gcc->state_info.seq;
4528              bi->gcc->state_info.seq = bi2->gcc->state_info.seq;
4529              bi2->gcc->state_info.seq = t;
4530
4531              _e_gadcon_layout_smart_containers_merge(sd, lc, lc2);
4532           }
4533         else if (lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED)
4534           {
4535              if (lc->state_info.max_seq < lc2->state_info.min_seq)
4536                {
4537                   lc2->pos = lc->pos + lc->size;
4538                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
4539                }
4540              else if (lc->state_info.min_seq > lc2->state_info.max_seq)
4541                {
4542                   lc2->pos = lc->pos - lc2->size;
4543                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
4544                } 
4545              else if (((lc->state_info.min_seq > lc2->state_info.min_seq) && 
4546                       (lc->state_info.min_seq < lc2->state_info.max_seq)) || 
4547                      ((lc2->state_info.min_seq > lc->state_info.min_seq) && 
4548                       (lc2->state_info.min_seq < lc->state_info.max_seq)))
4549                {
4550                   int shift = 0;
4551
4552                   _e_gadcon_layout_smart_containers_merge(sd, lc, lc2);
4553
4554                   EINA_LIST_FOREACH(lc->items, l, bi)
4555                     {
4556                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION)
4557                          {
4558                             shift = bi->ask.pos - bi->x;
4559                          }
4560
4561                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
4562                          break;
4563                     }
4564
4565                   if (shift)
4566                     {
4567                        EINA_LIST_FOREACH(lc->items, l, bi)
4568                          {
4569                             bi->x += shift;
4570                             
4571                             if (l == lc->items)
4572                               lc->pos = bi->x;
4573                          }
4574                     } 
4575                } 
4576           }
4577         create_new = 1; 
4578         new_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
4579      }
4580    else if ((lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
4581             (lc2->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
4582      {
4583         if (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED)
4584           {
4585              if (lc->state_info.max_seq < lc2->state_info.min_seq)
4586                {
4587                   lc->pos = lc2->pos - lc->size;
4588                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
4589                }
4590              else if (lc->state_info.min_seq > lc2->state_info.max_seq)
4591                {
4592                   lc->pos = lc2->pos + lc2->size;
4593                   _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
4594                }
4595              else if (((lc->state_info.min_seq > lc2->state_info.min_seq) && 
4596                       (lc->state_info.min_seq < lc2->state_info.max_seq)) || 
4597                      ((lc2->state_info.min_seq > lc->state_info.min_seq) && 
4598                       (lc2->state_info.min_seq < lc->state_info.max_seq)))
4599                {
4600                   int shift = 0;
4601
4602                   EINA_LIST_FOREACH(lc->items, l, bi)
4603                     {
4604                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION)
4605                          {
4606                             shift = bi->ask.pos - bi->x;
4607                          }
4608
4609                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
4610                          break;
4611                     }
4612
4613                   if (shift)
4614                     {
4615                        EINA_LIST_FOREACH(lc->items, l, bi)
4616                          {
4617                             bi->x += shift;
4618
4619                             if (l == lc->items)
4620                               lc->pos = bi->x;
4621                          }
4622                     }
4623                }
4624           }
4625         else if (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC)
4626           {
4627              int t;
4628
4629              bi = eina_list_data_get(eina_list_last(lc->items));
4630              bi2 = eina_list_data_get(lc2->items);
4631
4632              bi2->gcc->config.pos = bi2->ask.pos = (bi2->x) = (bi->x);
4633              bi2->gcc->config.size = bi2->w;
4634              bi->x = bi2->x + bi2->w;
4635
4636              t = bi->gcc->state_info.seq;
4637              bi->gcc->state_info.seq = bi2->gcc->state_info.seq;
4638              bi2->gcc->state_info.seq = t;
4639
4640              lc->items = eina_list_remove_list(lc->items, eina_list_last(lc->items));
4641              lc->items = eina_list_append(lc->items, bi2);
4642              lc->items = eina_list_append(lc->items, bi);
4643              lc2->items = eina_list_free(lc2->items);
4644              E_LAYOUT_ITEM_CONTAINER_SIZE_CHANGE_BY(lc, bi2, 1);
4645              lc2->pos = lc->pos + lc->size;
4646              lc2->size = 0;
4647           }
4648         create_new = 1;
4649         new_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
4650      }
4651    else if ((lc->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE) &&
4652             (lc2->state != E_LAYOUT_ITEM_CONTAINER_STATE_NONE))
4653      {
4654         if ((lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED) &&
4655             (lc2->state == E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED))
4656           {
4657              if (lc->state_info.max_seq < lc2->state_info.min_seq)
4658                {
4659                   int move_lc1 = 1;
4660                   int move_lc2 = 1;
4661
4662                   EINA_LIST_FOREACH(lc->items, l, bi)
4663                     {
4664                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
4665                          {
4666                             move_lc1 = 0;
4667                             break;
4668                          }
4669                     }
4670                   EINA_LIST_FOREACH(lc2->items, l, bi)
4671                     {
4672                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
4673                          {
4674                             move_lc2 = 0;
4675                             break;
4676                          }
4677                     }
4678
4679                   if ((move_lc1) && (!move_lc2))
4680                     {
4681                        lc->pos = lc2->pos - lc->size;
4682                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
4683                     }
4684                   else
4685                     {
4686                        lc2->pos = lc->pos + lc->size;
4687                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
4688                     }
4689                }
4690              else if (lc->state_info.min_seq > lc2->state_info.max_seq)
4691                {
4692                   int move_lc1 = 1;
4693                   int move_lc2 = 1;
4694
4695                   EINA_LIST_FOREACH(lc->items, l, bi)
4696                     {
4697                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
4698                          {
4699                             move_lc1 = 0;
4700                             break;
4701                          }
4702                     }
4703                   EINA_LIST_FOREACH(lc2->items, l, bi)
4704                     {
4705                        if (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE)
4706                          {
4707                             move_lc2 = 0;
4708                             break;
4709                          }
4710                     }
4711
4712                   if ((!move_lc1) && (move_lc2))
4713                     {
4714                        lc2->pos = lc->pos - lc2->size;
4715                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc2);
4716                     }
4717                   else
4718                     {
4719                        lc->pos = lc2->pos + lc2->size;
4720                        _e_gadcon_layout_smart_position_items_inside_container(sd, lc);
4721                     }
4722                }
4723              else if (((lc->state_info.min_seq > lc2->state_info.min_seq) && 
4724                       (lc->state_info.min_seq < lc2->state_info.max_seq)) || 
4725                      ((lc2->state_info.min_seq > lc->state_info.min_seq) && 
4726                       (lc2->state_info.min_seq < lc->state_info.max_seq)))
4727                {
4728                   int shift = 0;
4729
4730                   _e_gadcon_layout_smart_containers_merge(sd, lc, lc2);
4731
4732                   EINA_LIST_FOREACH(lc->items, l, bi)
4733                     {
4734                        if ((bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_POSITION) &&
4735                            (bi->gcc->state_info.flags & E_GADCON_LAYOUT_ITEM_LOCK_ABSOLUTE))
4736                          {
4737                             shift = bi->ask.pos - bi->x;
4738                             break;
4739                          }
4740                     }
4741
4742                   if (shift)
4743                     {
4744                        EINA_LIST_FOREACH(lc->items, l, bi)
4745                          {
4746                             bi->x += shift;
4747                             
4748                             if (l == lc->items)
4749                               lc->pos = bi->x;
4750                          }
4751                     }
4752                } 
4753              create_new = 1; 
4754              new_state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
4755           }
4756      }
4757
4758    if (create_new)
4759      {
4760         lc3 = E_NEW(E_Layout_Item_Container, 1);
4761         lc3->sd = sd;
4762         if (lc->pos < lc2->pos)
4763           {
4764              lc3->pos = lc->pos;
4765              EINA_LIST_FOREACH(lc->items, l, bi)
4766                 lc3->items = eina_list_append(lc3->items, bi);
4767              EINA_LIST_FOREACH(lc2->items, l, bi)
4768                 lc3->items = eina_list_append(lc3->items, bi);
4769
4770              lc3->state_info.min_seq = lc->state_info.min_seq;
4771              if (lc2->items)
4772                lc3->state_info.max_seq = lc2->state_info.max_seq;
4773              else
4774                lc3->state_info.max_seq = lc->state_info.max_seq;
4775           }
4776         else
4777           {
4778              lc3->pos = lc2->pos;
4779              EINA_LIST_FOREACH(lc2->items, l, bi)
4780                lc3->items = eina_list_append(lc3->items, bi);
4781              EINA_LIST_FOREACH(lc->items, l, bi)
4782                lc3->items = eina_list_append(lc3->items, bi);
4783
4784              lc3->state_info.min_seq = lc2->state_info.min_seq;
4785              if (lc->items)
4786                lc3->state_info.max_seq = lc->state_info.max_seq;
4787              else
4788                lc3->state_info.max_seq = lc2->state_info.max_seq;
4789           }
4790         lc3->size = lc->size + lc2->size;
4791         lc3->state = new_state;
4792      }
4793
4794    return lc3;
4795
4796
4797 static void
4798 _e_gadcon_layout_smart_position_items_inside_container(E_Smart_Data *sd __UNUSED__, E_Layout_Item_Container *lc)
4799 {
4800    int shift;
4801    Eina_List *l;
4802    E_Gadcon_Layout_Item *bi;
4803
4804    if (!lc->items) return;
4805
4806    bi = eina_list_data_get(lc->items);
4807    shift = lc->pos - bi->x;
4808    
4809    if (!shift) return;
4810
4811    EINA_LIST_FOREACH(lc->items, l, bi)
4812      {
4813         bi->x += shift;
4814         
4815         if ((bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_POS_DEC) ||
4816             (bi->gcc->state_info.state == E_LAYOUT_ITEM_STATE_POS_INC))
4817           {
4818              bi->gcc->config.pos = bi->ask.pos = bi->x;
4819           }
4820      }
4821
4822
4823 static void
4824 _e_gadcon_layout_smart_containers_merge(E_Smart_Data *sd __UNUSED__, E_Layout_Item_Container *lc, E_Layout_Item_Container *lc2)
4825 {
4826    int start = 0, size = 0, next = 0, min_seq = 0, max_seq = 0;
4827    Eina_List *l, *nl = NULL;
4828    E_Gadcon_Layout_Item *bi;
4829
4830    EINA_LIST_FOREACH(lc->items, l, bi)
4831      nl = eina_list_append(nl, bi);
4832    EINA_LIST_FOREACH(lc2->items, l, bi)
4833      nl = eina_list_append(nl, bi);
4834
4835    nl = eina_list_sort(nl, eina_list_count(nl), _e_gadcon_layout_smart_seq_sort_cb);
4836
4837    EINA_LIST_FOREACH(nl, l, bi)
4838      {
4839         if (l == nl)
4840           {
4841              min_seq = max_seq = bi->gcc->state_info.seq;
4842              start = bi->x;
4843              size = bi->w;
4844              next = bi->x + bi->w;
4845
4846              continue;
4847           }
4848
4849         max_seq = bi->gcc->state_info.seq;
4850
4851         bi->x = next;
4852         size += bi->w;
4853         next = bi->x + bi->w;
4854      }
4855
4856    lc->items = eina_list_free(lc->items);
4857    lc2->items = eina_list_free(lc->items);
4858    lc->items = nl;
4859    lc->pos = start;
4860    lc->size = size;
4861    lc->state_info.min_seq = min_seq;
4862    lc->state_info.max_seq = max_seq;
4863    lc2->pos = lc->pos + lc->size;
4864    lc2->size = 0;
4865
4866
4867 static void
4868 _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)
4869 {
4870    int ok;
4871    Eina_List *l, *l2, *l3;
4872    E_Gadcon_Layout_Item *bi, *bi2;
4873    E_Layout_Item_Container *lc, *lc2, *lc3;
4874
4875    (*lc_moving)->pos = (*lc_moving)->prev_pos;
4876    if (((*lc_moving)->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_INC) || 
4877        ((*lc_moving)->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MIN_END_DEC) || 
4878        ((*lc_moving)->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_INC) || 
4879        ((*lc_moving)->state == E_LAYOUT_ITEM_CONTAINER_STATE_SIZE_MAX_END_DEC))
4880      {
4881         (*lc_moving)->size = (*lc_moving)->prev_size;
4882         bi = eina_list_data_get((*lc_moving)->items);
4883
4884         bi->w = (*lc_moving)->prev_size;
4885      }
4886    _e_gadcon_layout_smart_position_items_inside_container(sd, (*lc_moving));
4887    (*lc_moving)->state = E_LAYOUT_ITEM_CONTAINER_STATE_POS_LOCKED;
4888    _e_gadcon_layout_smart_gadcons_position_static(sd, con_list);
4889
4890    lc2 = NULL;
4891    lc3 = NULL;
4892    ok = 0;
4893    EINA_LIST_FOREACH(*con_list, l, lc)
4894      {
4895         if (lc->state == E_LAYOUT_ITEM_CONTAINER_STATE_NONE) continue;
4896
4897         if (eina_list_count(lc->items) == 1)
4898           {
4899              bi = eina_list_data_get(lc->items);
4900              if (bi->gcc->state_info.state != E_LAYOUT_ITEM_STATE_NONE)
4901                {
4902                   LC_FREE(lc);
4903                   l->data = *lc_moving = lc_back;
4904                   _e_gadcon_layout_smart_position_items_inside_container(sd, (*lc_moving));
4905
4906                   if (((*lc_moving)->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC) &&
4907                       ((*lc_moving)->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC))
4908                     {
4909                        bi = eina_list_data_get((*lc_moving)->items);
4910                        bi->w = (*lc_moving)->size;
4911                     }
4912                }
4913           }
4914         else
4915           {
4916              EINA_LIST_FOREACH(lc->items, l2, bi)
4917                {
4918                   if (bi->gcc->state_info.state != E_LAYOUT_ITEM_STATE_NONE)
4919                     {
4920                        ok = 1;
4921                        if (l2 != lc->items)
4922                          {
4923                             lc2 = E_NEW(E_Layout_Item_Container, 1);
4924                             lc2->sd = sd;
4925                             lc2->state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;
4926                             EINA_LIST_FOREACH(lc->items, l3, bi2)
4927                               {
4928                                  if(l2 == l3) break;
4929                                  lc2->items = eina_list_append(lc2->items, bi2);
4930                                  if (l3 == lc->items)
4931                                    {
4932                                       lc2->state_info.min_seq = bi2->gcc->state_info.seq;
4933                                       lc2->pos = lc2->prev_pos = bi2->x;
4934                                    }
4935                                  lc2->state_info.max_seq = bi2->gcc->state_info.seq;
4936                                  E_LAYOUT_ITEM_CONTAINER_SIZE_CHANGE_BY(lc2, bi2, 1);
4937                               }
4938                          }
4939
4940                        if (eina_list_next(l2))
4941                          {
4942                             lc3 = E_NEW(E_Layout_Item_Container, 1);
4943                             lc3->sd = sd;
4944                             lc3->state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;
4945                             EINA_LIST_FOREACH(eina_list_next(l2), l3, bi2)
4946                               {
4947                                  lc3->items = eina_list_append(lc3->items, bi2);
4948                                  if (l3 == eina_list_next(l2))
4949                                    {
4950                                       lc3->state_info.min_seq = bi2->gcc->state_info.seq;
4951                                       lc3->pos = lc3->prev_pos = bi2->x;
4952                                    }
4953                                  lc3->state_info.max_seq = bi2->gcc->state_info.seq;
4954                                  E_LAYOUT_ITEM_CONTAINER_SIZE_CHANGE_BY(lc3, bi2, 1);
4955                               }
4956                          }
4957                        *lc_moving = lc_back;
4958                        _e_gadcon_layout_smart_position_items_inside_container(sd, *lc_moving); 
4959
4960                        if (((*lc_moving)->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_INC) && 
4961                            ((*lc_moving)->state != E_LAYOUT_ITEM_CONTAINER_STATE_POS_DEC)) 
4962                          { 
4963                             bi = eina_list_data_get((*lc_moving)->items); 
4964                             bi->w = (*lc_moving)->size; 
4965                          }
4966                        break;
4967                     }
4968                }
4969              if (ok)
4970                {
4971                   LC_FREE(lc);
4972                   if (lc2)
4973                     {
4974                        l->data = lc2;
4975                        *con_list = eina_list_append(*con_list, *lc_moving);
4976                        if (lc3)
4977                          *con_list = eina_list_append(*con_list, lc3);
4978                        *con_list = eina_list_sort(*con_list, eina_list_count(*con_list),
4979                                                   _e_gadcon_layout_smart_containers_sort_cb);
4980                     }
4981                   else
4982                     {
4983                        l->data = *lc_moving;
4984                        if (lc3)
4985                          {
4986                             *con_list = eina_list_append(*con_list, lc3);
4987                             *con_list = eina_list_sort(*con_list, eina_list_count(*con_list),
4988                                                        _e_gadcon_layout_smart_containers_sort_cb);
4989                          }
4990                     }
4991                   break;
4992                }
4993           }
4994      }
4995
4996    EINA_LIST_FOREACH(*con_list, l, lc)
4997      {
4998         if (lc == *lc_moving) continue;
4999         lc->state = E_LAYOUT_ITEM_CONTAINER_STATE_NONE;
5000      }
5001 }
5002
5003 static Eina_Bool
5004 _e_gadcon_custom_populate_idler(void *data __UNUSED__)
5005 {
5006    const E_Gadcon_Client_Class *cc;
5007    const Eina_List *l;
5008    E_Gadcon *gc;
5009
5010    EINA_LIST_FREE(custom_populate_requests, gc)
5011      {
5012         e_gadcon_layout_freeze(gc->o_container);
5013         EINA_LIST_FOREACH(providers_list, l, cc)
5014           {
5015              if (gc->populate_class.func)
5016                gc->populate_class.func(gc->populate_class.data, gc, cc);
5017              else
5018                e_gadcon_populate_class(gc, cc);
5019           }
5020         e_gadcon_layout_thaw(gc->o_container);
5021      }
5022
5023    custom_populate_idler = NULL;
5024    return ECORE_CALLBACK_CANCEL;
5025 }
5026
5027 static Eina_Bool
5028 _e_gadcon_provider_populate_idler(void *data __UNUSED__)
5029 {
5030    const E_Gadcon_Client_Class *cc;
5031    const Eina_List *l;
5032    E_Gadcon *gc;
5033
5034    EINA_LIST_FOREACH(gadcons, l, gc)
5035      e_gadcon_layout_freeze(gc->o_container);
5036
5037    EINA_LIST_FREE(populate_requests, cc)
5038      {
5039         EINA_LIST_FOREACH(gadcons, l, gc)
5040           {
5041              if (gc->populate_class.func)
5042                gc->populate_class.func(gc->populate_class.data, gc, cc);
5043              else
5044                e_gadcon_populate_class(gc, cc);
5045           }
5046      }
5047
5048    EINA_LIST_FOREACH(gadcons, l, gc)
5049      e_gadcon_layout_thaw(gc->o_container);
5050
5051    populate_idler = NULL;
5052    return ECORE_CALLBACK_CANCEL;
5053 }
5054
5055 static void
5056 _e_gadcon_provider_populate_request(const E_Gadcon_Client_Class *cc)
5057 {
5058    if (!populate_idler)
5059      populate_idler = ecore_idler_add(_e_gadcon_provider_populate_idler, NULL);
5060    if (!eina_list_data_find(populate_requests, cc))
5061      populate_requests = eina_list_append(populate_requests, cc);
5062 }
5063
5064 static void
5065 _e_gadcon_provider_populate_unrequest(const E_Gadcon_Client_Class *cc)
5066 {
5067    populate_requests = eina_list_remove(populate_requests, cc);
5068    if ((!populate_requests) && (populate_idler))
5069      {
5070         ecore_idler_del(populate_idler);
5071         populate_idler = NULL;
5072      }
5073 }
5074
5075 /* gadgets movement between different gadcons */
5076
5077 EAPI E_Gadcon_Location *
5078 e_gadcon_location_new(const char * name, 
5079                       E_Gadcon_Site site,
5080                       int (*add_func) (void *data, const E_Gadcon_Client_Class *cc),
5081                       void * add_data,
5082                       void (*remove_func) (void *data, E_Gadcon_Client *cc),
5083                       void * remove_data)
5084 {
5085    E_Gadcon_Location *loc;
5086
5087    loc  = E_NEW(E_Gadcon_Location, 1);
5088    loc->name = eina_stringshare_add(name);
5089    loc->site = site;
5090    loc->gadget_add.func = add_func; 
5091    loc->gadget_add.data = add_data; 
5092    loc->gadget_remove.func = remove_func; 
5093    loc->gadget_remove.data = remove_data; 
5094    loc->icon_name = NULL;
5095    return loc;
5096 }
5097
5098 EAPI void
5099 e_gadcon_location_set_icon_name(E_Gadcon_Location *loc, const char *name)
5100 {
5101    if (loc->icon_name) eina_stringshare_del(loc->icon_name);
5102    if (name)
5103      loc->icon_name = eina_stringshare_add(name);
5104    else
5105      loc->icon_name = NULL;
5106 }
5107
5108 EAPI void
5109 e_gadcon_location_free(E_Gadcon_Location *loc)
5110 {
5111    eina_stringshare_del(loc->name);
5112    if (loc->icon_name) eina_stringshare_del(loc->icon_name);
5113    free(loc);
5114 }
5115
5116 EAPI void
5117 e_gadcon_location_register(E_Gadcon_Location * loc)
5118 {
5119    gadcon_locations = eina_list_append(gadcon_locations, loc);
5120 }
5121
5122 EAPI void
5123 e_gadcon_location_unregister(E_Gadcon_Location * loc)
5124 {
5125    gadcon_locations = eina_list_remove(gadcon_locations, loc);
5126 }
5127
5128 static int
5129 _e_gadcon_location_change(E_Gadcon_Client * gcc, E_Gadcon_Location *src, E_Gadcon_Location *dst)
5130 {
5131    E_Gadcon_Client_Class *cc;
5132
5133    cc = eina_hash_find(providers, gcc->cf->name);
5134    if (!cc) return 0;
5135    if (!dst->gadget_add.func(dst->gadget_add.data, cc)) return 0;
5136    src->gadget_remove.func(src->gadget_remove.data, gcc);
5137    return 1;
5138 }
5139