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