1 #include "e.h"
2 
3 #define DEFAULT_LAYER E_LAYER_CLIENT_ABOVE
4 #define E_BRYCE_TYPE 0xE31338
5 
6 static unsigned int bryce_version = 2;
7 
8 typedef struct Bryce
9 {
10    E_Object *e_obj_inherit;
11    Eina_Stringshare *name;
12 
13    Evas_Object *bryce;
14    Evas_Object *events;
15    Evas_Object *layout;
16    Evas_Object *site;
17    Evas_Object *scroller;
18    Evas_Object *autohide_event;
19    Eina_List *zone_obstacles;
20    Eina_List *spacers;
21 
22    Evas_Object *parent; //comp_object is not an elm widget
23    Eina_Stringshare *style;
24    int size;
25    int x, y;
26    int last_w, last_h;
27    int autohide_size;
28    E_Layer layer;
29    unsigned int zone;
30    E_Gadget_Site_Orient orient;
31    E_Gadget_Site_Anchor anchor;
32 
33    Ecore_Job *calc_job;
34    Ecore_Timer *save_timer;
35    Ecore_Timer *autohide_timer;
36    unsigned int autohide_blocked;
37    Eina_List *popups;
38    void *event_info;
39    unsigned int last_timestamp;
40 
41    E_Menu *menu;
42 
43    /* config: do not bitfield! */
44    Eina_Bool autosize;
45    Eina_Bool autohide;
46    unsigned int version;
47 
48    Eina_Bool hidden E_BITFIELD;
49    Eina_Bool animating E_BITFIELD;
50    Eina_Bool mouse_in E_BITFIELD;
51    Eina_Bool noshadow E_BITFIELD;
52    Eina_Bool size_changed E_BITFIELD;
53    Eina_Bool editing E_BITFIELD;
54 } Bryce;
55 
56 typedef struct Bryces
57 {
58    Eina_List *bryces;
59 } Bryces;
60 
61 static E_Config_DD *edd_bryces;
62 static E_Config_DD *edd_bryce;
63 static Bryces *bryces;
64 static E_Action *resize_act;
65 static Eina_List *handlers;
66 
67 
68 static void _bryce_menu(Bryce *b, Evas_Object *g);
69 
70 #define BRYCE_GET(obj) \
71    Bryce *b; \
72    b = evas_object_data_get((obj), "__bryce"); \
73    if (!b) abort()
74 
75 static void
_bryce_obstacle_del(void * obs)76 _bryce_obstacle_del(void *obs)
77 {
78    Bryce *b = e_object_data_get(obs);
79 
80    b->zone_obstacles = eina_list_remove(b->zone_obstacles, obs);
81 }
82 
83 static void
_bryce_autohide_end(void * data,E_Efx_Map_Data * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED)84 _bryce_autohide_end(void *data, E_Efx_Map_Data *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED)
85 {
86    Bryce *b = data;
87 
88    b->animating = 0;
89 }
90 
91 static void
_bryce_autohide_coords(Bryce * b,int * x,int * y)92 _bryce_autohide_coords(Bryce *b, int *x, int *y)
93 {
94    int ox, oy, ow, oh;
95    E_Gadget_Site_Anchor an;
96 
97    if (b->parent == e_comp->elm)
98      {
99         E_Zone *zone;
100 
101         zone = e_comp_zone_number_get(b->zone);
102         ox = zone->x, oy = zone->y, ow = zone->w, oh = zone->h;
103      }
104    else
105      evas_object_geometry_get(b->parent, &ox, &oy, &ow, &oh);
106    an = e_gadget_site_anchor_get(b->site);
107 
108    if (b->orient == E_GADGET_SITE_ORIENT_HORIZONTAL)
109      {
110         *x = b->x;
111 
112         if (an & E_GADGET_SITE_ANCHOR_TOP)
113           *y = oy - lround(e_scale * b->size) + lround(e_scale * b->autohide_size);
114         if (an & E_GADGET_SITE_ANCHOR_BOTTOM)
115           *y = oy + oh - lround(e_scale * b->autohide_size);
116      }
117    else if (b->orient == E_GADGET_SITE_ORIENT_VERTICAL)
118      {
119         *y = b->y;
120 
121         if (an & E_GADGET_SITE_ANCHOR_LEFT)
122           *x = ox - lround(e_scale * b->size) + lround(e_scale * b->autohide_size);
123         if (an & E_GADGET_SITE_ANCHOR_RIGHT)
124           *x = ox + ow - lround(e_scale * b->autohide_size);
125      }
126 }
127 
128 static void
_bryce_position(Bryce * b,int w,int h,int * nx,int * ny)129 _bryce_position(Bryce *b, int w, int h, int *nx, int *ny)
130 {
131    int ox, oy, ow, oh;
132    int x, y;
133    E_Gadget_Site_Anchor an;
134 
135    if (b->parent == e_comp->elm)
136      {
137         E_Zone *zone;
138 
139         zone = e_comp_zone_number_get(b->zone);
140         ox = zone->x, oy = zone->y, ow = zone->w, oh = zone->h;
141         if (starting)
142           {
143              E_Zone *zone2;
144 
145              zone2 = e_comp_object_util_zone_get(b->bryce);
146              if (zone != zone2)
147                evas_object_move(b->bryce, ox, oy);
148           }
149      }
150    else
151      evas_object_geometry_get(b->parent, &ox, &oy, &ow, &oh);
152    x = ox + (ow - w) / 2;
153    x = E_CLAMP(x, ox, ox + ow / 2);
154    y = oy + (oh - h) / 2;
155    y = E_CLAMP(y, oy, oy + oh / 2);
156    an = e_gadget_site_anchor_get(b->site);
157    if (an & E_GADGET_SITE_ANCHOR_LEFT)
158      x = ox;
159    if (an & E_GADGET_SITE_ANCHOR_TOP)
160      y = oy;
161    if (b->orient == E_GADGET_SITE_ORIENT_HORIZONTAL)
162      {
163         if (an & E_GADGET_SITE_ANCHOR_RIGHT)
164           x = ox + ow - w;
165         if (an & E_GADGET_SITE_ANCHOR_BOTTOM)
166           y = oy + oh - lround(e_scale * b->size);
167         if (!b->autosize)
168           x = ox;
169      }
170    else if (b->orient == E_GADGET_SITE_ORIENT_VERTICAL)
171      {
172         if (an & E_GADGET_SITE_ANCHOR_RIGHT)
173           x = ox + ow - lround(e_scale * b->size);
174         if (an & E_GADGET_SITE_ANCHOR_BOTTOM)
175           y = oy + oh - h;
176         if (!b->autosize)
177           y = oy;
178      }
179    b->x = x, b->y = y;
180    if (b->animating)
181      {
182         if (b->hidden)
183           {
184              _bryce_autohide_coords(b, &x, &y);
185              e_efx_move(b->bryce, E_EFX_EFFECT_SPEED_LINEAR, E_EFX_POINT(x, y), 0.5, _bryce_autohide_end, b);
186           }
187         else
188           e_efx_move(b->bryce, E_EFX_EFFECT_SPEED_LINEAR, E_EFX_POINT(x, y), 0.5, _bryce_autohide_end, b);
189      }
190    else if (b->hidden)
191      _bryce_autohide_coords(b, &x, &y);
192 
193    if (nx && ny)
194      *nx = x, *ny = y;
195    else
196      evas_object_move(b->bryce, x, y);
197 }
198 
199 static void
_bryce_autosize(Bryce * b)200 _bryce_autosize(Bryce *b)
201 {
202    int lw, lh, sw, sh, maxw, maxh, x, y, w, h;
203 
204    E_FREE_FUNC(b->calc_job, ecore_job_del);
205    if (!b->autosize)
206      {
207         if (b->parent == e_comp->elm)
208           {
209              w = e_comp_zone_number_get(b->zone)->w;
210              if (b->orient == E_GADGET_SITE_ORIENT_VERTICAL)
211                e_zone_useful_geometry_get(e_comp_zone_number_get(b->zone), NULL, NULL, NULL, &h);
212              else
213                h = e_comp_zone_number_get(b->zone)->h;
214           }
215         else
216           evas_object_geometry_get(b->parent, NULL, NULL, &w, &h);
217         if (b->size_changed)
218           elm_object_content_unset(b->scroller);
219         _bryce_position(b, w, h, &x, &y);
220         evas_object_move(b->bryce, x, y);
221         if (b->orient == E_GADGET_SITE_ORIENT_HORIZONTAL)
222           e_efx_resize(b->bryce, E_EFX_EFFECT_SPEED_LINEAR, E_EFX_POINT(x, y), w, lround(b->size * e_scale), 0.1, NULL, NULL);
223         else if (b->orient == E_GADGET_SITE_ORIENT_VERTICAL)
224           e_efx_resize(b->bryce, E_EFX_EFFECT_SPEED_LINEAR, E_EFX_POINT(x, y), lround(b->size * e_scale), h, 0.1, NULL, NULL);
225         evas_object_smart_need_recalculate_set(b->site, 1);
226         evas_object_size_hint_min_set(b->site, -1, -1);
227         if (b->size_changed)
228           elm_object_content_set(b->scroller, b->site);
229         b->size_changed = 0;
230         return;
231      }
232    if (b->parent == e_comp->elm) //screen-based bryce
233      {
234         E_Zone *zone;
235 
236         zone = e_comp_zone_number_get(b->zone);
237         if (zone)
238           {
239              maxw = zone->w;
240              if (b->orient == E_GADGET_SITE_ORIENT_VERTICAL)
241                e_zone_useful_geometry_get(e_comp_zone_number_get(b->zone), NULL, NULL, NULL, &maxh);
242              else
243                maxh = zone->h;
244           }
245         else return;
246      }
247    else
248      evas_object_geometry_get(b->parent, NULL, NULL, &maxw, &maxh);
249    do
250      {
251         if (b->size_changed)
252           {
253              evas_object_geometry_get(b->bryce, NULL, NULL, &w, &h);
254              elm_object_content_unset(b->scroller);
255              if (b->orient == E_GADGET_SITE_ORIENT_HORIZONTAL)
256                {
257                   if (!h) h = 1;
258                   evas_object_resize(b->bryce, w * lround(b->size * e_scale) / h, lround(b->size * e_scale));
259                   evas_object_resize(b->site, w * lround(b->size * e_scale) / h, lround(b->size * e_scale));
260                }
261              else if (b->orient == E_GADGET_SITE_ORIENT_VERTICAL)
262                {
263                   if (!w) w = 1;
264                   evas_object_resize(b->bryce, lround(b->size * e_scale), h * lround(b->size * e_scale) / w);
265                   evas_object_resize(b->site, lround(b->size * e_scale), h * lround(b->size * e_scale) / w);
266                }
267              evas_object_smart_need_recalculate_set(b->site, 1);
268              evas_object_size_hint_min_set(b->site, -1, -1);
269              evas_object_smart_calculate(b->site);
270              elm_object_content_set(b->scroller, b->site);
271           }
272         evas_object_size_hint_min_get(b->site, &sw, &sh);
273         if ((!sw) && (!sh)) b->size_changed = 1;
274      }
275    while ((!sw) && (!sh));
276    edje_object_size_min_calc(elm_layout_edje_get(b->layout), &lw, &lh);
277    _bryce_position(b, lw + sw, lh + sh, &x, &y);
278    if (b->orient == E_GADGET_SITE_ORIENT_HORIZONTAL)
279      w = MIN(MAX(lw + sw, lround(b->size * e_scale)), maxw), h = lround(b->size * e_scale);
280    else if (b->orient == E_GADGET_SITE_ORIENT_VERTICAL)
281      w = lround(b->size * e_scale), h = MIN(MAX(lh + sh, lround(b->size * e_scale)), maxh);
282    evas_object_move(b->bryce, x, y);
283    e_efx_resize(b->bryce, E_EFX_EFFECT_SPEED_LINEAR, E_EFX_POINT(x, y), w, h, 0.1, NULL, NULL);
284    b->size_changed = 0;
285 }
286 
287 static Eina_Bool
_bryce_autohide_timeout(Bryce * b)288 _bryce_autohide_timeout(Bryce *b)
289 {
290    int x = 0, y = 0;
291 
292    b->autohide_timer = NULL;
293    b->hidden = b->animating = 1;
294    _bryce_autohide_coords(b, &x, &y);
295    e_efx_move(b->bryce, E_EFX_EFFECT_SPEED_LINEAR, E_EFX_POINT(x, y), 0.5, _bryce_autohide_end, b);
296    return EINA_FALSE;
297 }
298 
299 static void
_bryce_autohide_moveresize(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)300 _bryce_autohide_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
301 {
302    Bryce *b = data;
303    int x, y, w, h;
304 
305    evas_object_geometry_get(obj, &x, &y, &w, &h);
306    evas_object_geometry_set(b->autohide_event, x, y, w, h);
307 }
308 
309 static void
_bryce_autohide_show(Bryce * b)310 _bryce_autohide_show(Bryce *b)
311 {
312    E_FREE_FUNC(b->autohide_timer, ecore_timer_del);
313    if (b->animating && (!b->hidden)) return;
314    e_efx_move(b->bryce, E_EFX_EFFECT_SPEED_LINEAR, E_EFX_POINT(b->x, b->y), 0.5, _bryce_autohide_end, b);
315    b->animating = 1;
316    b->hidden = 0;
317 }
318 
319 static void
_bryce_autohide_hide(Bryce * b)320 _bryce_autohide_hide(Bryce *b)
321 {
322    if (b->autohide_blocked) return;
323    if (b->autohide_timer)
324      ecore_timer_loop_reset(b->autohide_timer);
325    else
326      b->autohide_timer = ecore_timer_loop_add(1.0, (Ecore_Task_Cb)_bryce_autohide_timeout, b);
327 }
328 
329 static void
_bryce_autohide_mouse_out(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)330 _bryce_autohide_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
331 {
332    Bryce *b = data;
333 
334    _bryce_autohide_hide(b);
335    b->mouse_in = 0;
336 }
337 
338 static void
_bryce_autohide_mouse_in(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)339 _bryce_autohide_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
340 {
341    Bryce *b = data;
342 
343    b->mouse_in = 1;
344    _bryce_autohide_show(b);
345 }
346 
347 static void
_bryce_autohide_setup(Bryce * b)348 _bryce_autohide_setup(Bryce *b)
349 {
350    int x, y, w, h;
351 
352    if (!b->autohide) return;
353    b->autohide_event = evas_object_rectangle_add(evas_object_evas_get(b->bryce));
354    evas_object_geometry_get(b->bryce, &x, &y, &w, &h);
355    evas_object_geometry_set(b->autohide_event, x, y, w, h);
356    evas_object_color_set(b->autohide_event, 0, 0, 0, 0);
357    evas_object_repeat_events_set(b->autohide_event, 1);
358    evas_object_layer_set(b->autohide_event, b->layer + 1);
359    evas_object_show(b->autohide_event);
360    evas_object_event_callback_add(b->autohide_event, EVAS_CALLBACK_MOUSE_IN, _bryce_autohide_mouse_in, b);
361    evas_object_event_callback_add(b->autohide_event, EVAS_CALLBACK_MOUSE_OUT, _bryce_autohide_mouse_out, b);
362    evas_object_event_callback_add(b->bryce, EVAS_CALLBACK_MOVE, _bryce_autohide_moveresize, b);
363    evas_object_event_callback_add(b->bryce, EVAS_CALLBACK_RESIZE, _bryce_autohide_moveresize, b);
364    ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
365    if (!E_INSIDE(x, y, b->x, b->y, w, h))
366      _bryce_autohide_hide(b);
367 }
368 
369 static void
_bryce_style(Evas_Object * site,Eina_Stringshare * name,Evas_Object * g)370 _bryce_style(Evas_Object *site, Eina_Stringshare *name, Evas_Object *g)
371 {
372    Evas_Object *ly, *prev;
373    char buf[1024];
374 
375    BRYCE_GET(site);
376 
377    ly = elm_layout_add(b->site);
378    snprintf(buf, sizeof(buf), "e/bryce/%s/%s", b->style ?: "default", name ?: "plain");
379    if (!e_theme_edje_object_set(ly, NULL, buf))
380      {
381         evas_object_del(ly);
382         return;
383      }
384    if (b->orient == E_GADGET_SITE_ORIENT_HORIZONTAL)
385      elm_layout_signal_emit(ly, "e,state,orient,horizontal", "e");
386    else
387      elm_layout_signal_emit(ly, "e,state,orient,vertical", "e");
388    edje_object_message_signal_process(elm_layout_edje_get(ly));
389    prev = e_gadget_util_layout_style_init(g, ly);
390    elm_object_part_content_set(ly, "e.swallow.content", g);
391    evas_object_smart_callback_call(g, "gadget_reparent", ly);
392    evas_object_del(prev);
393 }
394 
395 static void
_bryce_site_hints(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)396 _bryce_site_hints(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
397 {
398    Bryce *b = data;
399    int w, h;
400 
401    evas_object_size_hint_min_get(obj, &w, &h);
402    if ((w < 0) || (h < 0)) return;
403    if (b->autosize && (!b->calc_job))
404      b->calc_job = ecore_job_add((Ecore_Cb)_bryce_autosize, b);
405 }
406 
407 static E_Comp_Object_Type
_bryce_shadow_type(const Bryce * b)408 _bryce_shadow_type(const Bryce *b)
409 {
410    if ((b->layer == E_LAYER_DESKTOP_TOP) || b->noshadow)
411      return E_COMP_OBJECT_TYPE_NONE;
412    return E_COMP_OBJECT_TYPE_POPUP;
413 }
414 
415 static void
_bryce_restack(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)416 _bryce_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
417 {
418    Bryce *b = data;
419    E_Layer layer;
420 
421    layer = evas_object_layer_get(obj);
422    if (layer > DEFAULT_LAYER) return;
423    b->layer = layer;
424    if ((!b->noshadow) && (layer != b->layer))
425      e_comp_object_util_type_set(b->bryce, _bryce_shadow_type(b));
426 }
427 
428 static Eina_Bool
_bryce_moveresize_save(void * data)429 _bryce_moveresize_save(void *data)
430 {
431    Bryce *b = data;
432    int w, h;
433    int size;
434 
435    b->save_timer = NULL;
436    evas_object_geometry_get(b->bryce, NULL, NULL, &w, &h);
437    if (b->orient == E_GADGET_SITE_ORIENT_HORIZONTAL)
438      size = h;
439    else
440      size = w;
441    size = lround(size / e_scale);
442    if (b->size == size) return EINA_FALSE;
443    e_config_save_queue();
444    b->size = size;
445    return EINA_FALSE;
446 }
447 
448 static void
_bryce_zone_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)449 _bryce_zone_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
450 {
451    Bryce *b = data;
452    e_object_del(E_OBJECT(b->e_obj_inherit));
453 }
454 
455 static void
_bryce_zone_moveresize(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)456 _bryce_zone_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
457 {
458    Bryce *b = data;
459    if (!b->calc_job)
460      b->calc_job = ecore_job_add((Ecore_Cb)_bryce_autosize, b);
461 }
462 
463 static void
_bryce_zone_setup(Bryce * b)464 _bryce_zone_setup(Bryce *b)
465 {
466    Evas_Object *zone_clip;
467 
468    zone_clip = evas_object_clip_get(b->bryce);
469    if (zone_clip)
470      {
471         evas_object_event_callback_del_full(zone_clip, EVAS_CALLBACK_DEL, _bryce_zone_del, b);
472         evas_object_event_callback_del_full(zone_clip, EVAS_CALLBACK_MOVE, _bryce_zone_moveresize, b);
473         evas_object_event_callback_del_full(zone_clip, EVAS_CALLBACK_RESIZE, _bryce_zone_moveresize, b);
474      }
475    zone_clip = e_comp_zone_number_get(b->zone)->bg_clip_object;
476    evas_object_clip_set(b->bryce, zone_clip);
477    evas_object_event_callback_add(zone_clip, EVAS_CALLBACK_DEL, _bryce_zone_del, b);
478    evas_object_event_callback_add(zone_clip, EVAS_CALLBACK_MOVE, _bryce_zone_moveresize, b);
479    evas_object_event_callback_add(zone_clip, EVAS_CALLBACK_RESIZE, _bryce_zone_moveresize, b);
480 }
481 
482 static void
_bryce_rename(Bryce * b,int num)483 _bryce_rename(Bryce *b, int num)
484 {
485    char buf[1024], buf2[1024], *name, *p;
486 
487    name = strdup(b->name);
488    if (b->version >= 2)
489      {
490         p = strrchr(name, '_');
491         p[0] = 0;
492      }
493    snprintf(buf, sizeof(buf), "__bryce%s", name);
494    snprintf(buf2, sizeof(buf2), "__bryce%s_%d", name, num);
495    e_gadget_site_rename(buf, buf2);
496    if (b->version >= 2)
497      {
498         snprintf(buf, sizeof(buf), "%s_%u", name, num);
499         eina_stringshare_replace(&b->name, buf);
500      }
501    free(name);
502 }
503 
504 static void
_bryce_moveresize(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)505 _bryce_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
506 {
507    Bryce *b = data;
508    int x, y, w, h;
509    E_Zone *zone;
510    int size;
511 
512    evas_object_geometry_get(obj, &x, &y, &w, &h);
513    evas_object_geometry_set(b->events, x, y, w, h);
514    if (b->autohide)
515      {
516         E_FREE_LIST(b->zone_obstacles, e_object_del);
517         return;
518      }
519    if (b->orient == E_GADGET_SITE_ORIENT_HORIZONTAL)
520      size = h;
521    else
522      size = w;
523    if (((b->orient == E_GADGET_SITE_ORIENT_VERTICAL) && (w != b->last_w)) ||
524        ((b->orient == E_GADGET_SITE_ORIENT_HORIZONTAL) && (h != b->last_h)))
525      {
526         evas_object_smart_need_recalculate_set(b->site, 1);
527         evas_object_size_hint_min_set(b->site, -1, -1);
528      }
529    b->last_w = w, b->last_h = h;
530 
531    if (size && (b->size != size))
532      {
533         if (b->save_timer)
534           ecore_timer_loop_reset(b->save_timer);
535         else
536           b->save_timer = ecore_timer_loop_add(0.5, _bryce_moveresize_save, b);
537      }
538 
539    if (starting) return;
540    zone = e_comp_object_util_zone_get(obj);
541    if (zone)
542      {
543         Eina_Bool vertical = b->orient == E_GADGET_SITE_ORIENT_VERTICAL;
544         if (b->zone_obstacles)
545           {
546              Eina_List *l;
547              E_Zone_Obstacle *obs;
548 
549              EINA_LIST_FOREACH(b->zone_obstacles, l, obs)
550                e_zone_obstacle_modify(obs, &(Eina_Rectangle){b->x, b->y, w, h}, vertical);
551           }
552         else
553           {
554              void *obs;
555 
556              obs = e_zone_obstacle_add(e_comp_object_util_zone_get(obj), NULL,
557                     &(Eina_Rectangle){b->x, b->y, w, h}, vertical);
558              e_object_data_set(obs, b);
559              E_OBJECT_DEL_SET(obs, _bryce_obstacle_del);
560              b->zone_obstacles = eina_list_append(b->zone_obstacles, obs);
561           }
562      }
563    else
564      {
565         /* determine "closest" zone:
566          * calculate size of rect between bryce and zone
567          * smallest rect = closest zone
568          */
569         Eina_List *l;
570         E_Zone *lz;
571         size = 0;
572 
573         E_FREE_LIST(b->zone_obstacles, e_object_del);
574         EINA_LIST_FOREACH(e_comp->zones, l, lz)
575           {
576              int cw, ch;
577 
578              if (x < lz->x)
579                cw = lz->x + lz->w - x;
580              else
581                cw = x + w - lz->x;
582              if (y < lz->y)
583                ch = lz->y + lz->h - y;
584              else
585                ch = y + h - lz->y;
586              if (size >= cw * ch) continue;
587              size = cw * ch;
588              zone = lz;
589           }
590      }
591    if (!zone) return;
592    if (b->zone == zone->num) return;
593    e_config_save_queue();
594    _bryce_rename(b, zone->num);
595    b->zone = zone->num;
596    _bryce_zone_setup(b);
597    _bryce_autosize(b);
598 }
599 
600 static void
_bryce_mouse_wheel(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)601 _bryce_mouse_wheel(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
602 {
603    Bryce *b = data;
604    Evas_Event_Mouse_Wheel *ev = event_info;
605 
606    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
607    if (e_bindings_wheel_evas_event_handle(E_BINDING_CONTEXT_ANY, b->e_obj_inherit, ev))
608      ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
609 }
610 
611 static void
_bryce_popup_hide(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)612 _bryce_popup_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
613 {
614    Bryce *b = data;
615 
616    b->autohide_blocked--;
617    b->popups = eina_list_remove(b->popups, obj);
618    if (!b->autohide) return;
619    if (!b->mouse_in)
620      _bryce_autohide_hide(b);
621 }
622 
623 static void
_bryce_popup(Bryce * b,Evas_Object * popup)624 _bryce_popup(Bryce *b, Evas_Object *popup)
625 {
626    evas_object_event_callback_add(popup, EVAS_CALLBACK_HIDE, _bryce_popup_hide, b);
627    b->autohide_blocked++;
628    b->popups = eina_list_append(b->popups, popup);
629    if (b->autohide)
630      _bryce_autohide_show(b);
631 }
632 
633 static void
_bryce_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)634 _bryce_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
635 {
636    Bryce *b = data;
637    Evas_Object *p;
638    Evas_Object *zone_clip;
639    void *obs;
640 
641    if (b->menu)
642      {
643         e_menu_deactivate(b->menu);
644         e_object_del(E_OBJECT(b->menu));
645         b->menu = NULL;
646      }
647    EINA_LIST_FREE(b->zone_obstacles, obs)
648      {
649         E_OBJECT_DEL_SET(obs, NULL);
650         e_object_del(obs);
651      }
652    evas_object_del(b->autohide_event);
653    E_FREE_FUNC(b->events, evas_object_del);
654    E_FREE_FUNC(b->calc_job, ecore_job_del);
655    E_FREE_FUNC(b->autohide_timer, ecore_timer_del);
656    ecore_timer_del(b->save_timer);
657    EINA_LIST_FREE(b->popups, p)
658      evas_object_event_callback_del(p, EVAS_CALLBACK_HIDE, _bryce_popup_hide);
659    zone_clip = evas_object_clip_get(b->bryce);
660    if (zone_clip)
661      {
662         evas_object_event_callback_del_full(zone_clip, EVAS_CALLBACK_DEL, _bryce_zone_del, b);
663         evas_object_event_callback_del_full(zone_clip, EVAS_CALLBACK_MOVE, _bryce_zone_moveresize, b);
664         evas_object_event_callback_del_full(zone_clip, EVAS_CALLBACK_RESIZE, _bryce_zone_moveresize, b);
665      }
666    E_FREE(b->e_obj_inherit);
667    b->bryce = NULL;
668    b->site = NULL;
669 }
670 
671 static void
_bryce_object_free(E_Object * eobj)672 _bryce_object_free(E_Object *eobj)
673 {
674    Bryce *b = e_object_data_get(eobj);
675    evas_object_hide(b->bryce);
676    evas_object_del(b->bryce);
677 }
678 
679 static void
_bryce_style_menu(void * data,Evas_Object * obj EINA_UNUSED,void * event_info)680 _bryce_style_menu(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
681 {
682    Bryce *b = data;
683    char buf[1024];
684 
685    snprintf(buf, sizeof(buf), "e/bryce/%s", b->style ?: "default");
686    e_object_data_set(event_info, e_theme_collection_items_find(NULL, buf));
687 }
688 
689 static void
_bryce_gadgets_menu_close(void * data,Evas_Object * obj)690 _bryce_gadgets_menu_close(void *data, Evas_Object *obj)
691 {
692    Bryce *b = data;
693 
694    b->autohide_blocked--;
695    b->editing = 0;
696    evas_object_layer_set(b->bryce, b->layer);
697    evas_object_hide(obj);
698    evas_object_del(obj);
699    if (b->autohide && (!b->mouse_in))
700      _bryce_autohide_hide(b);
701 }
702 
703 static void
_bryce_gadgets_menu(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)704 _bryce_gadgets_menu(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
705 {
706    Bryce *b = data;
707    Evas_Object *comp_object;
708 
709    b->autohide_blocked++;
710    b->editing = 1;
711    comp_object = e_gadget_site_edit(b->site);
712    evas_object_layer_set(b->bryce, E_LAYER_POPUP);
713    e_comp_object_util_autoclose(comp_object, _bryce_gadgets_menu_close, e_comp_object_util_autoclose_on_escape, b);
714 }
715 
716 static void
_bryce_autosize_menu(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)717 _bryce_autosize_menu(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
718 {
719    Bryce *b = data;
720 
721    e_bryce_autosize_set(b->bryce, !b->autosize);
722 }
723 
724 static void
_bryce_autohide_menu(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)725 _bryce_autohide_menu(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
726 {
727    Bryce *b = data;
728 
729    e_bryce_autohide_set(b->bryce, !b->autohide);
730 }
731 
732 static void
_bryce_remove_menu(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)733 _bryce_remove_menu(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
734 {
735    Bryce *b = data;
736    bryces->bryces = eina_list_remove(bryces->bryces, data);
737    e_gadget_site_del(b->site);
738    eina_stringshare_del(b->name);
739    eina_stringshare_del(b->style);
740    evas_object_hide(b->bryce);
741    evas_object_del(b->bryce);
742    e_config_save_queue();
743 }
744 
745 static void
_bryce_wizard_menu(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)746 _bryce_wizard_menu(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
747 {
748    Bryce *b = data;
749    Evas_Object *editor;
750 
751    editor = e_bryce_edit(b->bryce);
752    _bryce_popup(b, editor);
753 }
754 
755 static void
_bryce_gadget_settings_menu(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)756 _bryce_gadget_settings_menu(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
757 {
758    Evas_Object *g = data;
759    e_gadget_configure(g);
760 }
761 
762 static void
_bryce_gadget_remove_menu(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)763 _bryce_gadget_remove_menu(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
764 {
765    Evas_Object *g = data;
766    e_gadget_del(g);
767    e_config_save_queue();
768 }
769 
770 static void
_bryce_menu_post_cb(void * data,E_Menu * m)771 _bryce_menu_post_cb(void *data, E_Menu *m)
772 {
773    Bryce *b = data;
774    if (b->menu != m) return;
775    b->menu = NULL;
776 }
777 
778 static void
_bryce_menu_populate(Bryce * b,E_Menu * m,Evas_Object * g)779 _bryce_menu_populate(Bryce *b, E_Menu *m, Evas_Object *g)
780 {
781    E_Menu_Item *mi;
782    const char *s = NULL;
783 
784    if (g) s = e_gadget_type_get(g);
785    if (s) e_menu_title_set(m, e_gadget_type_get(g));
786    else e_menu_title_set(m, _("Gadget Bar"));
787 
788    if (g)
789      {
790         mi = e_menu_item_new(m);
791         e_menu_item_label_set(mi, _("Settings"));
792         e_util_menu_item_theme_icon_set(mi, "preferences-system");
793         e_menu_item_callback_set(mi, _bryce_gadget_settings_menu, g);
794 
795         mi = e_menu_item_new(m);
796         e_menu_item_label_set(mi, _("Delete"));
797         e_util_menu_item_theme_icon_set(mi, "list-remove");
798         e_menu_item_callback_set(mi, _bryce_gadget_remove_menu, g);
799 
800         e_gadget_menu_populate(g, m);
801 
802         mi = e_menu_item_new(m);
803         e_menu_item_separator_set(mi, 1);
804      }
805 
806    mi = e_menu_item_new(m);
807    e_menu_item_label_set(mi, _("Autosize"));
808    e_menu_item_check_set(mi, 1);
809    e_menu_item_toggle_set(mi, b->autosize);
810    e_menu_item_callback_set(mi, _bryce_autosize_menu, b);
811 
812    mi = e_menu_item_new(m);
813    e_menu_item_label_set(mi, _("Autohide"));
814    e_menu_item_check_set(mi, 1);
815    e_menu_item_toggle_set(mi, b->autohide);
816    e_menu_item_callback_set(mi, _bryce_autohide_menu, b);
817 
818    mi = e_menu_item_new(m);
819    e_menu_item_label_set(mi, _("Bar Settings"));
820    e_menu_item_callback_set(mi, _bryce_wizard_menu, b);
821 
822    mi = e_menu_item_new(m);
823    e_menu_item_label_set(mi, _("Add Gadget"));
824    e_menu_item_callback_set(mi, _bryce_gadgets_menu, b);
825 
826    mi = e_menu_item_new(m);
827    e_menu_item_label_set(mi, _("Delete Bar"));
828    e_util_menu_item_theme_icon_set(mi, "list-remove");
829    e_menu_item_callback_set(mi, _bryce_remove_menu, b);
830 
831    if (b->menu)
832      {
833         e_menu_deactivate(b->menu);
834         e_object_del(E_OBJECT(b->menu));
835      }
836    b->menu = m;
837    e_menu_post_deactivate_callback_set(m, _bryce_menu_post_cb, b);
838 }
839 
840 static void
_bryce_owner_menu(void * data,Evas_Object * obj EINA_UNUSED,void * event_info)841 _bryce_owner_menu(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
842 {
843    Bryce *b = data;
844    E_Menu_Item *mi = event_info;
845    E_Menu *subm;
846 
847    e_menu_item_label_set(mi, _("Gadget Bar"));
848 
849    subm = e_menu_new();
850    e_menu_hold_mode_set(subm, EINA_FALSE);
851    e_menu_item_submenu_set(mi, subm);
852    e_object_unref(E_OBJECT(subm));
853 
854    _bryce_menu_populate(b, subm, NULL);
855 }
856 
857 static void
_bryce_gadget_popup(void * data,Evas_Object * obj EINA_UNUSED,void * event_info)858 _bryce_gadget_popup(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
859 {
860    _bryce_popup(data, event_info);
861 }
862 
863 static void
_bryce_gadget_locked(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)864 _bryce_gadget_locked(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
865 {
866    Bryce *b = data;
867 
868    b->autohide_blocked++;
869    if (b->autohide)
870      _bryce_autohide_show(b);
871 }
872 
873 static void
_bryce_gadget_unlocked(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)874 _bryce_gadget_unlocked(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
875 {
876    Bryce *b = data;
877 
878    b->autohide_blocked--;
879    if (b->autohide && (!b->mouse_in))
880      _bryce_autohide_hide(b);
881 }
882 
883 static void
_bryce_site_anchor(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)884 _bryce_site_anchor(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
885 {
886    Bryce *b = data;
887 
888    e_bryce_orient(b->bryce, e_gadget_site_orient_get(obj), e_gadget_site_anchor_get(obj));
889 }
890 
891 static void
_bryce_gadget_size_request(void * data,Evas_Object * obj EINA_UNUSED,void * event_info)892 _bryce_gadget_size_request(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
893 {
894    Evas_Coord_Size *size = event_info;
895    Bryce *b = data;
896 
897    edje_object_part_geometry_get(elm_layout_edje_get(b->layout), "e.swallow.content", NULL, NULL, &size->w, &size->h);
898 }
899 
900 static void
_bryce_context(Evas_Object * site,Evas_Object * g,unsigned int timestamp)901 _bryce_context(Evas_Object *site, Evas_Object *g, unsigned int timestamp)
902 {
903    Bryce *b = evas_object_data_get(site, "__bryce");
904    if (b)
905      {
906         b->last_timestamp = timestamp;
907         _bryce_menu(b, g);
908      }
909 }
910 
911 static void
_bryce_context_cancel(Evas_Object * site,Evas_Object * g EINA_UNUSED,unsigned int timestamp)912 _bryce_context_cancel(Evas_Object *site, Evas_Object *g EINA_UNUSED, unsigned int timestamp)
913 {
914    Bryce *b = evas_object_data_get(site, "__bryce");
915    if (b)
916      {
917         b->last_timestamp = timestamp;
918         if (b->menu)
919           {
920              e_menu_deactivate(b->menu);
921              e_object_del(E_OBJECT(b->menu));
922              b->menu = NULL;
923           }
924      }
925 }
926 
927 static void
_bryce_orient(Bryce * b)928 _bryce_orient(Bryce *b)
929 {
930    char buf[1024];
931 
932    evas_object_del(b->site);
933 
934    snprintf(buf, sizeof(buf), "__bryce%s", b->name);
935    b->site = e_gadget_site_add(b->orient, buf);
936    E_EXPAND(b->site);
937    E_FILL(b->site);
938    evas_object_data_set(b->site, "__bryce", b);
939    elm_object_content_set(b->scroller, b->site);
940    e_gadget_site_owner_setup(b->site, b->anchor, _bryce_style, _bryce_context, _bryce_context_cancel);
941    if (b->orient == E_GADGET_SITE_ORIENT_HORIZONTAL)
942      {
943         elm_layout_signal_emit(b->layout, "e,state,orient,horizontal", "e");
944         elm_layout_signal_emit(b->scroller, "e,state,orient,horizontal", "e");
945         elm_scroller_policy_set(b->scroller, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
946      }
947    else
948      {
949         elm_layout_signal_emit(b->layout, "e,state,orient,vertical", "e");
950         elm_layout_signal_emit(b->scroller, "e,state,orient,vertical", "e");
951         elm_scroller_policy_set(b->scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
952      }
953    evas_object_event_callback_add(b->site, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _bryce_site_hints, b);
954    evas_object_smart_callback_add(b->site, "gadget_site_anchor", _bryce_site_anchor, b);
955    evas_object_smart_callback_add(b->site, "gadget_site_style_menu", _bryce_style_menu, b);
956    evas_object_smart_callback_add(b->site, "gadget_site_owner_menu", _bryce_owner_menu, b);
957    evas_object_smart_callback_add(b->site, "gadget_site_popup", _bryce_gadget_popup, b);
958    evas_object_smart_callback_add(b->site, "gadget_site_locked", _bryce_gadget_locked, b);
959    evas_object_smart_callback_add(b->site, "gadget_site_unlocked", _bryce_gadget_unlocked, b);
960    evas_object_smart_callback_add(b->site, "gadget_site_parent_size_request", _bryce_gadget_size_request, b);
961 }
962 
963 static void
_bryce_style_apply(Bryce * b)964 _bryce_style_apply(Bryce *b)
965 {
966    char buf[1024];
967    Eina_Bool noshadow;
968 
969    snprintf(buf, sizeof(buf), "e/bryce/%s/base", b->style ?: "default");
970    e_theme_edje_object_set(b->layout, NULL, buf);
971    noshadow = b->noshadow;
972    b->noshadow = !!elm_layout_data_get(b->layout, "noshadow");
973    if (b->bryce && (noshadow != b->noshadow))
974      e_comp_object_util_type_set(b->bryce, _bryce_shadow_type(b));
975 }
976 
977 static void
_bryce_create(Bryce * b,Evas_Object * parent)978 _bryce_create(Bryce *b, Evas_Object *parent)
979 {
980    Evas_Object *ly, *bryce, *scr;
981 
982    b->e_obj_inherit = E_OBJECT_ALLOC(E_Object, E_BRYCE_TYPE, _bryce_object_free);
983    b->events = evas_object_rectangle_add(e_comp->evas);
984    evas_object_repeat_events_set(b->events, EINA_TRUE);
985    evas_object_color_set(b->events, 0, 0, 0, 0);
986    evas_object_name_set(b->events, "b->events");
987    evas_object_show(b->events);
988    e_object_data_set(b->e_obj_inherit, b);
989    b->layout = ly = elm_layout_add(parent);
990    _bryce_style_apply(b);
991 
992    b->scroller = scr = elm_scroller_add(ly);
993    elm_scroller_bounce_set(scr, 0, 0);
994    elm_object_style_set(scr, "bryce");
995    _bryce_orient(b);
996    elm_object_part_content_set(ly, "e.swallow.content", scr);
997    evas_object_show(ly);
998    b->bryce = bryce = e_comp_object_util_add(ly, _bryce_shadow_type(b));
999 //   evas_object_repeat_events_set(evas_object_smart_parent_get(ly), 1);
1000    evas_object_smart_member_add(b->events, bryce);
1001    evas_object_raise(b->events);
1002    evas_object_data_set(bryce, "comp_skip", (void*)1);
1003    evas_object_layer_set(bryce, b->layer);
1004    evas_object_lower(bryce);
1005 
1006    b->parent = parent;
1007    {
1008       const char *str;
1009 
1010       str = elm_layout_data_get(ly, "hidden_state_size");
1011       if (str && str[0])
1012         b->autohide_size = strtol(str, NULL, 10);
1013    }
1014    evas_object_data_set(bryce, "__bryce", b);
1015    evas_object_event_callback_add(bryce, EVAS_CALLBACK_DEL, _bryce_del, b);
1016    evas_object_event_callback_add(bryce, EVAS_CALLBACK_RESTACK, _bryce_restack, b);
1017    evas_object_event_callback_add(bryce, EVAS_CALLBACK_MOVE, _bryce_moveresize, b);
1018    evas_object_event_callback_add(bryce, EVAS_CALLBACK_RESIZE, _bryce_moveresize, b);
1019    evas_object_event_callback_add(b->events, EVAS_CALLBACK_MOUSE_WHEEL, _bryce_mouse_wheel, b);
1020 
1021   _bryce_zone_setup(b);
1022    _bryce_autohide_setup(b);
1023    _bryce_autosize(b);
1024 }
1025 
1026 static Eina_Bool
_bryce_act_resize(E_Object * obj,const char * params,E_Binding_Event_Wheel * ev)1027 _bryce_act_resize(E_Object *obj, const char *params, E_Binding_Event_Wheel *ev)
1028 {
1029    Bryce *b;
1030    int size, step = 4;
1031    char buf[64];
1032 
1033    if (obj->type != E_BRYCE_TYPE) return EINA_FALSE;
1034    if (params && params[0])
1035      {
1036         step = strtol(params, NULL, 10);
1037         step = MAX(step, 4);
1038      }
1039    b = e_object_data_get(obj);
1040    size = b->size;
1041    if (ev->z < 0)//up
1042      b->size += step;
1043    else
1044      b->size -= step;
1045    b->size = E_CLAMP(b->size, 20, 256);
1046    if (dblequal(e_scale, 1.0))
1047      snprintf(buf, sizeof(buf), "%dpx", b->size);
1048    else
1049      snprintf(buf, sizeof(buf), "%dpx (%ldpx scaled)", b->size, lround(b->size * e_scale));
1050    elm_object_part_text_set(b->layout, "e.text", buf);
1051    elm_object_signal_emit(b->layout, "e,action,resize", "e");
1052    e_config_save_queue();
1053    if (size == b->size) return EINA_TRUE;
1054    b->size_changed = 1;
1055    if (!b->calc_job)
1056      b->calc_job = ecore_job_add((Ecore_Cb)_bryce_autosize, b);
1057    return EINA_TRUE;
1058 }
1059 
1060 static void
_bryce_menu(Bryce * b,Evas_Object * g)1061 _bryce_menu(Bryce *b, Evas_Object *g)
1062 {
1063    E_Menu *m;
1064    int x = 0, y = 0, w = 1, h = 1;
1065 
1066    m = e_menu_new();
1067    e_menu_hold_mode_set(m, EINA_FALSE);
1068    _bryce_menu_populate(b, m, g);
1069    if (g)
1070      evas_object_geometry_get(g, &x, &y, &w, &h);
1071    else
1072      evas_pointer_canvas_xy_get(e_comp->evas, &x, &y);
1073    e_menu_activate_mouse(m, e_zone_current_get(), x, y, w, h,
1074                          E_MENU_POP_DIRECTION_AUTO, b->last_timestamp);
1075    _bryce_popup(b, m->comp_object);
1076 }
1077 
1078 static Eina_Bool
_bryce_zone_useful_geometry_changed(void * d EINA_UNUSED,int t EINA_UNUSED,E_Event_Zone_Move_Resize * ev)1079 _bryce_zone_useful_geometry_changed(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Zone_Move_Resize *ev)
1080 {
1081    Eina_List *l;
1082    Bryce *b;
1083 
1084    EINA_LIST_FOREACH(bryces->bryces, l, b)
1085      {
1086         if (b->bryce && (b->zone == ev->zone->num) &&
1087             (b->orient == E_GADGET_SITE_ORIENT_VERTICAL))
1088           _bryce_autosize(b);
1089      }
1090    return ECORE_CALLBACK_RENEW;
1091 }
1092 
1093 static void
_bryce_comp_resize(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1094 _bryce_comp_resize(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1095 {
1096    Eina_List *l;
1097    Bryce *b;
1098 
1099    EINA_LIST_FOREACH(bryces->bryces, l, b)
1100      {
1101         if (e_comp_zone_number_get(b->zone))
1102           {
1103              if (b->bryce) continue;
1104              _bryce_create(b, e_comp->elm);
1105              evas_object_show(b->bryce);
1106           }
1107      }
1108 }
1109 
1110 E_API Evas_Object *
e_bryce_add(Evas_Object * parent,const char * name,E_Gadget_Site_Orient orient,E_Gadget_Site_Anchor an)1111 e_bryce_add(Evas_Object *parent, const char *name, E_Gadget_Site_Orient orient, E_Gadget_Site_Anchor an)
1112 {
1113    Bryce *b;
1114    const char *z;
1115 
1116    b = E_NEW(Bryce, 1);
1117    b->size = 48;
1118    b->name = eina_stringshare_add(name);
1119    z = strrchr(name, '_');
1120    b->zone = strtoul(z + 1, NULL, 10);
1121    b->anchor = an;
1122    b->orient = orient;
1123    b->layer = DEFAULT_LAYER;
1124    b->version = bryce_version;
1125    _bryce_create(b, parent);
1126    bryces->bryces = eina_list_append(bryces->bryces, b);
1127    e_config_save_queue();
1128    return b->bryce;
1129 }
1130 
1131 E_API void
e_bryce_orient(Evas_Object * bryce,E_Gadget_Site_Orient orient,E_Gadget_Site_Anchor an)1132 e_bryce_orient(Evas_Object *bryce, E_Gadget_Site_Orient orient, E_Gadget_Site_Anchor an)
1133 {
1134    const char *loc = NULL, *loc2 = NULL;
1135    char buf[1024], buf2[1024];
1136 
1137    BRYCE_GET(bryce);
1138    if ((b->orient == orient) && (b->anchor == an)) return;
1139    if (an & E_GADGET_SITE_ANCHOR_TOP)
1140      loc = "top";
1141    else if (an & E_GADGET_SITE_ANCHOR_BOTTOM)
1142      loc = "bottom";
1143    else if (an & E_GADGET_SITE_ANCHOR_LEFT)
1144      loc = "left";
1145    else if (an & E_GADGET_SITE_ANCHOR_RIGHT)
1146      loc = "right";
1147    if (an & E_GADGET_SITE_ANCHOR_RIGHT)
1148      loc2 = "right";
1149    else if (an & E_GADGET_SITE_ANCHOR_LEFT)
1150      loc2 = "left";
1151    else if (an & E_GADGET_SITE_ANCHOR_TOP)
1152      loc2 = "top";
1153    else if (an & E_GADGET_SITE_ANCHOR_BOTTOM)
1154      loc2 = "bottom";
1155 
1156    snprintf(buf, sizeof(buf), "__bryce%s", b->name);
1157    snprintf(buf2, sizeof(buf2), "__brycebryce_%s_%s_%d", loc, loc2, b->zone);
1158    e_gadget_site_rename(buf, buf2);
1159    b->orient = orient;
1160    b->anchor = an;
1161    snprintf(buf2, sizeof(buf2), "bryce_%s_%s_%d", loc, loc2, b->zone);
1162    eina_stringshare_replace(&b->name, buf2);
1163    _bryce_orient(b);
1164    _bryce_autosize(b);
1165 }
1166 
1167 E_API Evas_Object *
e_bryce_site_get(Evas_Object * bryce)1168 e_bryce_site_get(Evas_Object *bryce)
1169 {
1170    BRYCE_GET(bryce);
1171 
1172    return b->site;
1173 }
1174 
1175 E_API Eina_Bool
e_bryce_autosize_get(Evas_Object * bryce)1176 e_bryce_autosize_get(Evas_Object *bryce)
1177 {
1178    BRYCE_GET(bryce);
1179    return b->autosize;
1180 }
1181 
1182 E_API void
e_bryce_autosize_set(Evas_Object * bryce,Eina_Bool set)1183 e_bryce_autosize_set(Evas_Object *bryce, Eina_Bool set)
1184 {
1185    BRYCE_GET(bryce);
1186    set = !!set;
1187 
1188    if (b->autosize == set) return;
1189    b->autosize = set;
1190    if (set)
1191      {
1192         while (b->spacers)
1193           e_gadget_del(eina_list_data_get(b->spacers));
1194      }
1195    e_config_save_queue();
1196    _bryce_autosize(b);
1197 }
1198 
1199 E_API Eina_Bool
e_bryce_autohide_get(Evas_Object * bryce)1200 e_bryce_autohide_get(Evas_Object *bryce)
1201 {
1202    BRYCE_GET(bryce);
1203    return b->autohide;
1204 }
1205 
1206 E_API void
e_bryce_autohide_set(Evas_Object * bryce,Eina_Bool set)1207 e_bryce_autohide_set(Evas_Object *bryce, Eina_Bool set)
1208 {
1209    BRYCE_GET(bryce);
1210    set = !!set;
1211 
1212    if (b->autohide == set) return;
1213    b->autohide = set;
1214 
1215    if (set)
1216      _bryce_autohide_setup(b);
1217    else
1218      {
1219         E_FREE_FUNC(b->autohide_event, evas_object_del);
1220         evas_object_event_callback_del_full(bryce, EVAS_CALLBACK_MOVE, _bryce_autohide_moveresize, b);
1221         evas_object_event_callback_del_full(bryce, EVAS_CALLBACK_RESIZE, _bryce_autohide_moveresize, b);
1222         if (!b->hidden) return;
1223         e_efx_move(b->bryce, E_EFX_EFFECT_SPEED_LINEAR, E_EFX_POINT(b->x, b->y), 0.5, _bryce_autohide_end, b);
1224         b->animating = 1;
1225         b->hidden = 0;
1226      }
1227    e_config_save_queue();
1228 }
1229 
1230 E_API Eina_List *
e_bryce_list(Evas_Object * parent)1231 e_bryce_list(Evas_Object *parent)
1232 {
1233    Eina_List *l, *ret = NULL;
1234    Bryce *b;
1235 
1236    if (!parent) parent = e_comp->elm;
1237    EINA_LIST_FOREACH(bryces->bryces, l, b)
1238      {
1239         if (!b->bryce) continue;
1240         if (parent == b->parent)
1241           ret = eina_list_append(ret, b->bryce);
1242      }
1243    return ret;
1244 }
1245 
1246 E_API Eina_Bool
e_bryce_exists(Evas_Object * parent,Evas_Object * bryce,E_Gadget_Site_Orient orient,E_Gadget_Site_Anchor an)1247 e_bryce_exists(Evas_Object *parent, Evas_Object *bryce, E_Gadget_Site_Orient orient, E_Gadget_Site_Anchor an)
1248 {
1249    Eina_List *l;
1250    Bryce *b;
1251    int zone = -1;
1252 
1253    if (!parent) parent = e_comp->elm;
1254    if (parent == e_comp->elm)
1255      {
1256         E_Shelf *es;
1257         E_Zone *z;
1258 
1259         z = e_zone_current_get();
1260         zone = z->num;
1261         /* FIXME: remove shelf block once shelves are dead */
1262         l = e_shelf_list_all();
1263         EINA_LIST_FREE(l, es)
1264           {
1265              if (es->zone != z) continue;
1266              switch (es->cfg->orient)
1267                {
1268 #define ORIENT_CHECK(ORIENT, ANCHOR1, ANCHOR2) \
1269   if ((orient == E_GADGET_SITE_ORIENT_##ORIENT) && \
1270     ((an == (E_GADGET_SITE_ANCHOR_##ANCHOR1)) || \
1271       ((an & E_GADGET_SITE_ANCHOR_##ANCHOR2) && (!es->cfg->fit_along)))) \
1272         return EINA_TRUE; \
1273   break
1274                 default: break;
1275                 case E_GADCON_ORIENT_LEFT:
1276                   ORIENT_CHECK(VERTICAL, LEFT, LEFT);
1277                 case E_GADCON_ORIENT_RIGHT:
1278                   ORIENT_CHECK(VERTICAL, RIGHT, RIGHT);
1279                 case E_GADCON_ORIENT_TOP:
1280                   ORIENT_CHECK(HORIZONTAL, TOP, TOP);
1281                 case E_GADCON_ORIENT_BOTTOM:
1282                   ORIENT_CHECK(HORIZONTAL, BOTTOM, BOTTOM);
1283                 case E_GADCON_ORIENT_CORNER_TL:
1284                   ORIENT_CHECK(HORIZONTAL, TOP | E_GADGET_SITE_ANCHOR_LEFT, TOP);
1285                 case E_GADCON_ORIENT_CORNER_TR:
1286                   ORIENT_CHECK(HORIZONTAL, TOP | E_GADGET_SITE_ANCHOR_RIGHT, TOP);
1287                 case E_GADCON_ORIENT_CORNER_BL:
1288                   ORIENT_CHECK(HORIZONTAL, BOTTOM | E_GADGET_SITE_ANCHOR_LEFT, BOTTOM);
1289                 case E_GADCON_ORIENT_CORNER_BR:
1290                   ORIENT_CHECK(HORIZONTAL, BOTTOM | E_GADGET_SITE_ANCHOR_RIGHT, BOTTOM);
1291                 case E_GADCON_ORIENT_CORNER_LT:
1292                   ORIENT_CHECK(VERTICAL, LEFT | E_GADGET_SITE_ANCHOR_TOP, LEFT);
1293                 case E_GADCON_ORIENT_CORNER_RT:
1294                   ORIENT_CHECK(VERTICAL, RIGHT | E_GADGET_SITE_ANCHOR_TOP, RIGHT);
1295                 case E_GADCON_ORIENT_CORNER_LB:
1296                   ORIENT_CHECK(VERTICAL, LEFT | E_GADGET_SITE_ANCHOR_BOTTOM, LEFT);
1297                 case E_GADCON_ORIENT_CORNER_RB:
1298                   ORIENT_CHECK(VERTICAL, RIGHT | E_GADGET_SITE_ANCHOR_BOTTOM, RIGHT);
1299 #undef ORIENT_CHECK
1300                }
1301           }
1302           /* end FIXME */
1303      }
1304    EINA_LIST_FOREACH(bryces->bryces, l, b)
1305      {
1306         if (!b->bryce) continue;
1307         if (b->bryce == bryce) return EINA_FALSE;
1308         if (parent != b->parent) continue;
1309         if (b->orient != orient) continue;
1310         if ((zone >= 0) && ((int)b->zone != zone)) continue;
1311         if ((b->anchor & an) == an) return EINA_TRUE;
1312         if (b->autosize) continue;
1313         if (b->orient == E_GADGET_SITE_ORIENT_HORIZONTAL)
1314           {
1315              if ((b->anchor & E_GADGET_SITE_ANCHOR_BOTTOM) && (an & E_GADGET_SITE_ANCHOR_BOTTOM))
1316                return EINA_TRUE;
1317              if ((b->anchor & E_GADGET_SITE_ANCHOR_TOP) && (an & E_GADGET_SITE_ANCHOR_TOP))
1318                return EINA_TRUE;
1319           }
1320         else
1321           {
1322              if ((b->anchor & E_GADGET_SITE_ANCHOR_LEFT) && (an & E_GADGET_SITE_ANCHOR_LEFT))
1323                return EINA_TRUE;
1324              if ((b->anchor & E_GADGET_SITE_ANCHOR_RIGHT) && (an & E_GADGET_SITE_ANCHOR_RIGHT))
1325                return EINA_TRUE;
1326           }
1327      }
1328    return EINA_FALSE;
1329 }
1330 
1331 E_API void
e_bryce_style_set(Evas_Object * bryce,const char * style)1332 e_bryce_style_set(Evas_Object *bryce, const char *style)
1333 {
1334    BRYCE_GET(bryce);
1335 
1336    eina_stringshare_replace(&b->style, style);
1337    _bryce_style_apply(b);
1338    e_config_save_queue();
1339    evas_object_smart_callback_call(b->site, "gadget_site_style", NULL);
1340 }
1341 
1342 /* FIXME */
1343 EINTERN void
e_bryce_save(void)1344 e_bryce_save(void)
1345 {
1346    e_config_domain_save("e_bryces", edd_bryces, bryces);
1347 }
1348 
1349 static void
bryce_spacer_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1350 bryce_spacer_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1351 {
1352    Bryce *b = data;
1353 
1354    b->spacers = eina_list_remove(b->spacers, obj);
1355 }
1356 
1357 static Evas_Object *
bryce_spacer_create(Evas_Object * parent,int * id,E_Gadget_Site_Orient orient)1358 bryce_spacer_create(Evas_Object *parent, int *id, E_Gadget_Site_Orient orient)
1359 {
1360    Bryce *b;
1361    Eina_List *l;
1362    Evas_Object *r;
1363 
1364    if (!orient) return NULL;
1365 
1366    /* only allow on bryces */
1367    EINA_LIST_FOREACH(bryces->bryces, l, b)
1368      {
1369         if (b->editing || (parent == b->site)) break;
1370      }
1371    if (!b) return NULL;
1372    if (b->autosize) return NULL;
1373    r = evas_object_rectangle_add(e_comp->evas);
1374    evas_object_event_callback_add(r, EVAS_CALLBACK_DEL, bryce_spacer_del, b);
1375    b->spacers = eina_list_append(b->spacers, r);
1376    E_EXPAND(r);
1377    E_FILL(r);
1378    /* FIXME: this should be better for demo gadgets... */
1379    if (*id < 0)
1380      {
1381         evas_object_size_hint_aspect_set(r, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
1382         evas_object_color_set(r, 255, 0, 0, 255);
1383      }
1384    else
1385      evas_object_color_set(r, 0, 0, 0, 0);
1386    return r;
1387 }
1388 
1389 EINTERN void
e_bryce_init(void)1390 e_bryce_init(void)
1391 {
1392    resize_act = e_action_add("bryce_resize");
1393    e_action_predef_name_set(_("Bryces"), _("Resize Gadget Bar"), "bryce_resize", NULL, "syntax: step, example: 4", 1);
1394    resize_act->func.go_wheel = _bryce_act_resize;
1395 
1396    edd_bryce = E_CONFIG_DD_NEW("Bryce", Bryce);
1397    E_CONFIG_VAL(edd_bryce, Bryce, name, STR);
1398    E_CONFIG_VAL(edd_bryce, Bryce, style, STR);
1399    E_CONFIG_VAL(edd_bryce, Bryce, zone, UINT);
1400    E_CONFIG_VAL(edd_bryce, Bryce, size, INT);
1401    E_CONFIG_VAL(edd_bryce, Bryce, layer, UINT);
1402    E_CONFIG_VAL(edd_bryce, Bryce, autosize, UCHAR);
1403    E_CONFIG_VAL(edd_bryce, Bryce, autohide, UCHAR);
1404    E_CONFIG_VAL(edd_bryce, Bryce, orient, UINT);
1405    E_CONFIG_VAL(edd_bryce, Bryce, anchor, UINT);
1406    E_CONFIG_VAL(edd_bryce, Bryce, version, UINT);
1407 
1408    edd_bryces = E_CONFIG_DD_NEW("Bryces", Bryces);
1409    E_CONFIG_LIST(edd_bryces, Bryces, bryces, edd_bryce);
1410    bryces = e_config_domain_load("e_bryces", edd_bryces);
1411 
1412    if (bryces)
1413      {
1414         Eina_List *l;
1415         Bryce *b;
1416 
1417         EINA_LIST_FOREACH(bryces->bryces, l, b)
1418           {
1419              if (b->version < 2)
1420                {
1421                   /* I broke this the first time by forgetting the __bryce prefix :(
1422                    */
1423                   _bryce_rename(b, b->zone);
1424                   if (b->version < 1)
1425                     {
1426                        char buf[1024];
1427 
1428                        snprintf(buf, sizeof(buf), "%s_%u", b->name, b->zone);
1429                        eina_stringshare_replace(&b->name, buf);
1430                     }
1431                }
1432              b->version = bryce_version;
1433              if (!e_comp_zone_number_get(b->zone)) continue;
1434              b->layer = E_CLAMP(b->layer, E_LAYER_DESKTOP_TOP, E_LAYER_CLIENT_ABOVE);
1435              _bryce_create(b, e_comp->elm);
1436              evas_object_show(b->bryce);
1437           }
1438      }
1439    else
1440      bryces = E_NEW(Bryces, 1);
1441 
1442    evas_object_event_callback_add(e_comp->canvas->resize_object, EVAS_CALLBACK_RESIZE, _bryce_comp_resize, NULL);
1443    E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_USEFUL_GEOMETRY_CHANGED, _bryce_zone_useful_geometry_changed, NULL);
1444    e_gadget_type_add("Spacer Bar", bryce_spacer_create, NULL);
1445 }
1446 
1447 EINTERN void
e_bryce_shutdown(void)1448 e_bryce_shutdown(void)
1449 {
1450    Bryce *b;
1451 
1452    E_CONFIG_DD_FREE(edd_bryce);
1453    E_CONFIG_DD_FREE(edd_bryces);
1454    EINA_LIST_FREE(bryces->bryces, b)
1455      {
1456         E_Zone *zone;
1457         void *obs;
1458 
1459         EINA_LIST_FREE(b->zone_obstacles, obs)
1460           {
1461              E_OBJECT_DEL_SET(obs, NULL);
1462              e_object_del(obs);
1463           }
1464         evas_object_event_callback_del(b->bryce, EVAS_CALLBACK_DEL, _bryce_del);
1465         EINA_LIST_FREE(b->popups, obs)
1466           evas_object_event_callback_del(obs, EVAS_CALLBACK_HIDE, _bryce_popup_hide);
1467         evas_object_hide(b->bryce);
1468         evas_object_del(b->bryce);
1469         evas_object_del(b->autohide_event);
1470         eina_stringshare_del(b->name);
1471         eina_stringshare_del(b->style);
1472         ecore_job_del(b->calc_job);
1473         ecore_timer_del(b->save_timer);
1474         ecore_timer_del(b->autohide_timer);
1475         zone = e_comp_zone_number_get(b->zone);
1476         if (zone)
1477           {
1478              evas_object_event_callback_del(zone->bg_clip_object, EVAS_CALLBACK_DEL, _bryce_zone_del);
1479              evas_object_event_callback_del(zone->bg_clip_object, EVAS_CALLBACK_MOVE, _bryce_zone_moveresize);
1480              evas_object_event_callback_del(zone->bg_clip_object, EVAS_CALLBACK_RESIZE, _bryce_zone_moveresize);
1481           }
1482         free(b->e_obj_inherit);
1483         free(b);
1484      }
1485    E_FREE_LIST(handlers, ecore_event_handler_del);
1486    E_FREE(bryces);
1487    e_gadget_type_del("Spacer Bar");
1488 }
1489