Tizen 2.1 release
[platform/core/uifw/e17.git] / src / modules / conf_wallpaper2 / e_int_config_wallpaper.c
1 #include "e.h"
2 #include "e_mod_main.h"
3
4 // FIXME:
5 //   need choice after add (file, gradient, online source)
6 //   need delete select mode
7 //   need after select on delete an ok/cancel if file or "ok to remove whole online source" if online
8 //   need to make "exchange" wallpapers have a different look
9 //   bug: animated wp doesn't workon first show
10 //   need to be able to "type name to search/filter"
11
12 typedef struct _Info Info;
13 typedef struct _Smart_Data Smart_Data;
14 typedef struct _Item Item;
15
16 struct _Info
17 {
18    E_Win *win;
19    Evas_Object *bg, *preview, *mini, *button, *box, *sframe, *span;
20    char *bg_file;
21    int iw, ih;
22    Eina_List *dirs;
23    char *curdir;
24    Eina_Iterator *dir;
25    Ecore_Idler *idler;
26    int scans;
27    int con_num, zone_num, desk_x, desk_y;
28    int use_theme_bg;
29    int mode;
30 };
31
32 struct _Smart_Data
33 {
34    Eina_List *items;
35    Ecore_Idle_Enterer *idle_enter;
36    Ecore_Animator *animator;
37    Ecore_Timer *seltimer;
38    Info *info;
39    Evas_Coord x, y, w, h;
40    Evas_Coord cx, cy, cw, ch;
41    Evas_Coord sx, sy;
42    int id_num;
43    int sort_num;
44    double seltime;
45    double selmove;
46    Eina_Bool selin : 1;
47    Eina_Bool selout : 1;
48    Eina_Bool jump2hi : 1;
49 };
50
51 struct _Item
52 {
53    Evas_Object *obj;
54    Evas_Coord x, y, w, h;
55    const char *file;
56    char *sort_id;
57    Evas_Object *frame, *image;
58    Eina_Bool selected : 1;
59    Eina_Bool have_thumb : 1;
60    Eina_Bool do_thumb : 1;
61    Eina_Bool remote : 1;
62    Eina_Bool theme : 1;
63    Eina_Bool visible : 1;
64    Eina_Bool hilighted : 1;
65 };
66
67 static Info *global_info = NULL;
68
69 static void _e_smart_reconfigure(Evas_Object *obj);
70 static Eina_Bool _e_smart_reconfigure_do(void *data);
71 static void _thumb_gen(void *data, Evas_Object *obj, void *event_info);
72 static void _item_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
73 static void _item_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
74 static int _sort_cb(const void *d1, const void *d2);
75 static void _scan(Info *info);
76
77 static void
78 _pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
79 {
80    Smart_Data *sd = evas_object_smart_data_get(obj);
81
82    if (x > (sd->cw - sd->w)) x = sd->cw - sd->w;
83    if (y > (sd->ch - sd->h)) y = sd->ch - sd->h;
84    if (x < 0) x = 0;
85    if (y < 0) y = 0;
86    if ((sd->cx == x) && (sd->cy == y)) return;
87    sd->cx = x;
88    sd->cy = y;
89    _e_smart_reconfigure(obj);
90 }
91
92 static void
93 _pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
94 {
95    Smart_Data *sd = evas_object_smart_data_get(obj);
96
97    if (x) *x = sd->cx;
98    if (y) *y = sd->cy;
99 }
100
101 static void
102 _pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
103 {
104    Smart_Data *sd = evas_object_smart_data_get(obj);
105
106    if (x)
107      {
108         if (sd->w < sd->cw) *x = sd->cw - sd->w;
109         else *x = 0;
110      }
111    if (y)
112      {
113         if (sd->h < sd->ch) *y = sd->ch - sd->h;
114         else *y = 0;
115      }
116 }
117
118 static void
119 _pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
120 {
121    Smart_Data *sd = evas_object_smart_data_get(obj);
122
123    if (w) *w = sd->cw;
124    if (h) *h = sd->ch;
125 }
126
127 static Eina_Bool
128 _e_smart_reconfigure_do(void *data)
129 {
130    Evas_Object *obj = data;
131    Smart_Data *sd = evas_object_smart_data_get(obj);
132    Eina_List *l;
133    Item *it;
134    int iw, redo = 0, changed = 0;
135    static int recursion = 0;
136    Evas_Coord x, y, xx, yy, ww, hh, mw, mh, ox, oy, dd;
137    Evas_Coord vw, vh;
138    Evas *evas;
139
140    if (!sd) return ECORE_CALLBACK_CANCEL;
141    if (sd->cx > (sd->cw - sd->w)) sd->cx = sd->cw - sd->w;
142    if (sd->cy > (sd->ch - sd->h)) sd->cy = sd->ch - sd->h;
143    if (sd->cx < 0) sd->cx = 0;
144    if (sd->cy < 0) sd->cy = 0;
145
146    iw = sd->w / 4;
147    if (iw > (120 * e_scale)) iw = (120 * e_scale);
148    else
149      {
150         if (iw < (60 * e_scale)) iw = (sd->w / 3);
151         if (iw < (60 * e_scale)) iw = (sd->w / 2);
152         if (iw < (60 * e_scale)) iw = sd->w;
153      }
154    x = 0;
155    y = 0;
156    ww = iw;
157    hh = (sd->info->ih * iw) / (sd->info->iw);
158    mw = mh = 0;
159
160    evas = evas_object_evas_get(obj);
161    evas_output_viewport_get(evas, NULL, NULL, &vw, &vh);
162
163    EINA_LIST_FOREACH(sd->items, l, it)
164      {
165         if (x > (sd->w - ww))
166           {
167              x = 0;
168              y += hh;
169           }
170         it->x = x;
171         it->y = y;
172         it->w = ww;
173         it->h = hh;
174         if (it->selected)
175           {
176              sd->sx = it->x + (it->w / 2);
177              sd->sy = it->y + (it->h / 2);
178           }
179         if ((x + ww) > mw) mw = x + ww;
180         if ((y + hh) > mh) mh = y + hh;
181         x += ww;
182      }
183    if ((mw != sd->cw) || (mh != sd->ch))
184      {
185         sd->cw = mw;
186         sd->ch = mh;
187         if (sd->cx > (sd->cw - sd->w))
188           {
189              sd->cx = sd->cw - sd->w;
190              redo = 1;
191           }
192         if (sd->cy > (sd->ch - sd->h))
193           {
194              sd->cy = sd->ch - sd->h;
195              redo = 1;
196           }
197         if (sd->cx < 0)
198           {
199              sd->cx = 0;
200              redo = 1;
201           }
202         if (sd->cy < 0)
203           {
204              sd->cy = 0;
205              redo = 1;
206           }
207         if (redo)
208           {
209              recursion = 1;
210              _e_smart_reconfigure_do(obj);
211              recursion = 0;
212           }
213         changed = 1;
214      }
215
216    ox = 0;
217    if (sd->w > sd->cw) ox = (sd->w - sd->cw) / 2;
218    oy = 0;
219    if (sd->h > sd->ch) oy = (sd->h - sd->ch) / 2;
220
221    EINA_LIST_FOREACH(sd->items, l, it)
222      {
223         Evas_Coord dx, dy;
224
225         dx = dy = 0;
226         if ((sd->sx >= 0) && (sd->selmove > 0.0)
227
228 /*            &&
229             ((it->x + it->w) > sd->cx) &&
230             ((it->x) < (sd->cx + sd->w)) &&
231             ((it->y + it->h) > sd->cy) &&
232             ((it->y) < (sd->cy + sd->h))
233  */
234             )
235           {
236              double a, d;
237              int sum = 0;
238              char *p;
239
240              // -----0X0+++++
241              dx = (it->x + (it->w / 2)) - sd->sx;
242              dy = (it->y + (it->h / 2)) - sd->sy;
243              if (dx > 0)
244                {
245                   // |/
246                   // +--
247                   if (dy < 0)
248                     a = -atan(-(double)dy / (double)dx);
249                   // +--
250                   /* |\ */
251                   else
252                     a = atan((double)dy / (double)dx);
253                }
254              else if (dx == 0)
255                {
256                   //   |
257                   //   +
258                   if (dy < 0) a = -M_PI / 2;
259                   //   +
260                   //   |
261                   else a = M_PI / 2;
262                }
263              else
264                {
265                   //  \|
266                   // --+
267                   if (dy < 0)
268                     a = -M_PI + atan((double)dy / (double)dx);
269                   // --+
270                   //  /|
271                   else
272                     a = M_PI - atan(-(double)dy / (double)dx);
273                }
274              d = sqrt((double)(dx * dx) + (double)(dy * dy));
275
276              sum = 0;
277              if (it->file)
278                {
279                   for (p = (char *)it->file; *p; p++) sum += (int)(*p);
280                }
281              sum = (sum & 0xff) - 128;
282              a = a + ((double)sum / 1024.0);
283              xx = sd->sx - sd->cx + ox;
284              yy = sd->sy - sd->cy + oy;
285              if (xx < (sd->w / 2)) dx = sd->w - xx;
286              else dx = xx;
287              if (yy < (sd->h / 2)) dy = sd->h - yy;
288              else dy = yy;
289              dd = dx - d;
290              if (dy > dx) dd = dy - d;
291              if (dd < 0) dd = 0;
292              dy = sin(a) * sd->selmove * (dd * 0.9);
293              dx = cos(a) * sd->selmove * (dd * 0.9);
294           }
295         xx = sd->x - sd->cx + it->x + ox;
296         yy = sd->y - sd->cy + it->y + oy;
297         if (E_INTERSECTS(xx, yy, it->w, it->h, 0, 0, vw, vh))
298           {
299              if (!it->have_thumb)
300                {
301                   if (!it->do_thumb)
302                     {
303                        e_thumb_icon_begin(it->image);
304                        it->do_thumb = EINA_TRUE;
305                     }
306                }
307              else
308                {
309                   if (!it->frame)
310                     {
311                        it->frame = edje_object_add(evas);
312                        if (it->theme)
313                          e_theme_edje_object_set(it->frame, "base/theme/widgets",
314                                                  "e/conf/wallpaper/main/mini-theme");
315                        else if (it->remote)
316                          e_theme_edje_object_set(it->frame, "base/theme/widgets",
317                                                  "e/conf/wallpaper/main/mini-remote");
318                        else
319                          e_theme_edje_object_set(it->frame, "base/theme/widgets",
320                                                  "e/conf/wallpaper/main/mini");
321                        if (it->hilighted)
322                          {
323                             edje_object_signal_emit(it->frame, "e,state,selected", "e");
324                             evas_object_raise(it->frame);
325                          }
326                        evas_object_event_callback_add(it->frame, EVAS_CALLBACK_MOUSE_DOWN,
327                                                       _item_down, it);
328                        evas_object_event_callback_add(it->frame, EVAS_CALLBACK_MOUSE_UP,
329                                                       _item_up, it);
330
331                        evas_object_smart_member_add(it->frame, obj);
332                        evas_object_clip_set(it->frame, evas_object_clip_get(obj));
333                        it->image = e_thumb_icon_add(evas);
334                        edje_object_part_swallow(it->frame, "e.swallow.content", it->image);
335                        evas_object_smart_callback_add(it->image, "e_thumb_gen", _thumb_gen, it);
336                        if (it->theme)
337                          {
338                             const char *f;
339
340                             f = e_theme_edje_file_get("base/theme/backgrounds",
341                                                       "e/desktop/background");
342                             e_thumb_icon_file_set(it->image, f,
343                                                   "e/desktop/background");
344                          }
345                        else
346                          e_thumb_icon_file_set(it->image, it->file,
347                                                "e/desktop/background");
348                        e_thumb_icon_size_set(it->image, sd->info->iw,
349                                              sd->info->ih);
350                        evas_object_show(it->image);
351
352                        e_thumb_icon_begin(it->image);
353                     }
354                }
355              evas_object_move(it->frame, xx + dx, yy + dy);
356              evas_object_resize(it->frame, it->w, it->h);
357              evas_object_show(it->frame);
358              it->visible = EINA_TRUE;
359           }
360         else
361           {
362              if (it->have_thumb)
363                {
364                   if (it->do_thumb)
365                     {
366                        e_thumb_icon_end(it->image);
367                        it->do_thumb = EINA_FALSE;
368                     }
369                   evas_object_del(it->image);
370                   it->image = NULL;
371                   evas_object_del(it->frame);
372                   it->frame = NULL;
373                }
374              it->visible = EINA_FALSE;
375 /*
376              if (it->have_thumb)
377                {
378                   if (it->do_thumb)
379                     {
380                        e_thumb_icon_end(it->image);
381                        it->do_thumb = EINA_FALSE;
382                     }
383                   evas_object_del(it->image);
384                   it->have_thumb = EINA_FALSE;
385                   it->image = e_thumb_icon_add(evas);
386                   edje_object_part_swallow(it->frame, "e.swallow.content", it->image);
387                   evas_object_smart_callback_add(it->image, "e_thumb_gen", _thumb_gen, it);
388                   if (it->theme)
389                     {
390                        const char *f = e_theme_edje_file_get("base/theme/backgrounds",
391                                                              "e/desktop/background");
392                        e_thumb_icon_file_set(it->image, f, "e/desktop/background");
393                     }
394                   else
395                     e_thumb_icon_file_set(it->image, it->file, "e/desktop/background");
396                   e_thumb_icon_size_set(it->image, sd->info->iw, sd->info->ih);
397                   evas_object_show(it->image);
398                   edje_object_signal_emit(it->frame, "e,action,thumb,ungen", "e");
399                }
400              else
401                {
402                   if (it->sort_id)
403                     {
404                        if (it->do_thumb)
405                          {
406                             e_thumb_icon_end(it->image);
407                             it->do_thumb = 0;
408                          }
409                     }
410                }
411  */
412           }
413      }
414
415    if (changed)
416      evas_object_smart_callback_call(obj, "changed", NULL);
417    if (recursion == 0) sd->idle_enter = NULL;
418    return ECORE_CALLBACK_CANCEL;
419 }
420
421 static void
422 _e_smart_reconfigure(Evas_Object *obj)
423 {
424    Smart_Data *sd = evas_object_smart_data_get(obj);
425
426    if (sd->idle_enter) return;
427    sd->idle_enter = ecore_idle_enterer_before_add(_e_smart_reconfigure_do, obj);
428 }
429
430 static void
431 _e_smart_add(Evas_Object *obj)
432 {
433    Smart_Data *sd = calloc(1, sizeof(Smart_Data));
434
435    if (!sd) return;
436
437    sd->sx = sd->sy = -1;
438    evas_object_smart_data_set(obj, sd);
439 }
440
441 static void
442 _e_smart_del(Evas_Object *obj)
443 {
444    Smart_Data *sd = evas_object_smart_data_get(obj);
445    Item *it;
446
447    if (sd->seltimer)
448      ecore_timer_del(sd->seltimer);
449    if (sd->idle_enter)
450      ecore_idle_enterer_del(sd->idle_enter);
451    if (sd->animator)
452      ecore_animator_del(sd->animator);
453    // sd->info is just referenced
454    // sd->child_obj is unused
455    EINA_LIST_FREE(sd->items, it)
456      {
457         if (it->frame) evas_object_del(it->frame);
458         if (it->image) evas_object_del(it->image);
459         if (it->file) eina_stringshare_del(it->file);
460         free(it->sort_id);
461         free(it);
462      }
463    free(sd);
464    evas_object_smart_data_set(obj, NULL);
465 }
466
467 static void
468 _e_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
469 {
470    Smart_Data *sd = evas_object_smart_data_get(obj);
471
472    sd->x = x;
473    sd->y = y;
474    _e_smart_reconfigure(obj);
475 }
476
477 static void
478 _e_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
479 {
480    Smart_Data *sd = evas_object_smart_data_get(obj);
481
482    sd->w = w;
483    sd->h = h;
484    _e_smart_reconfigure(obj);
485    evas_object_smart_callback_call(obj, "changed", NULL);
486 }
487
488 static void
489 _e_smart_show(Evas_Object *obj __UNUSED__)
490 {
491 //   Smart_Data *sd = evas_object_smart_data_get(obj);
492 //   evas_object_show(sd->child_obj);
493 }
494
495 static void
496 _e_smart_hide(Evas_Object *obj __UNUSED__)
497 {
498 //   Smart_Data *sd = evas_object_smart_data_get(obj);
499 //   evas_object_hide(sd->child_obj);
500 }
501
502 static void
503 _e_smart_color_set(Evas_Object *obj __UNUSED__, int r __UNUSED__, int g __UNUSED__, int b __UNUSED__, int a __UNUSED__)
504 {
505 //   Smart_Data *sd = evas_object_smart_data_get(obj);
506 //   evas_object_color_set(sd->child_obj, r, g, b, a);
507 }
508
509 static void
510 _e_smart_clip_set(Evas_Object *obj __UNUSED__, Evas_Object * clip __UNUSED__)
511 {
512 //   Smart_Data *sd = evas_object_smart_data_get(obj);
513 //   evas_object_clip_set(sd->child_obj, clip);
514 }
515
516 static void
517 _e_smart_clip_unset(Evas_Object *obj __UNUSED__)
518 {
519 //   Smart_Data *sd = evas_object_smart_data_get(obj);
520 //   evas_object_clip_unset(sd->child_obj);
521 }
522
523 static Evas_Object *
524 _pan_add(Evas *evas)
525 {
526    static Evas_Smart *smart = NULL;
527    static const Evas_Smart_Class sc =
528      {
529         "wp_pan",
530           EVAS_SMART_CLASS_VERSION,
531           _e_smart_add,
532           _e_smart_del,
533           _e_smart_move,
534           _e_smart_resize,
535           _e_smart_show,
536           _e_smart_hide,
537           _e_smart_color_set,
538           _e_smart_clip_set,
539           _e_smart_clip_unset,
540           NULL,
541           NULL,
542           NULL,
543           NULL,
544           NULL,
545           NULL,
546           NULL
547      };
548    smart = evas_smart_class_new(&sc);
549    return evas_object_smart_add(evas, smart);
550 }
551
552 static void
553 _pan_info_set(Evas_Object *obj, Info *info)
554 {
555    Smart_Data *sd = evas_object_smart_data_get(obj);
556
557    sd->info = info;
558 }
559
560 static Eina_Bool
561 _sel_anim(void *data)
562 {
563    Evas_Object *obj = data;
564    Smart_Data *sd = evas_object_smart_data_get(obj);
565    double t = ecore_loop_time_get() - sd->seltime;
566    double len = 1.0;
567    double p = t / len;
568    double d;
569
570    if (p > 1.0) p = 1.0;
571    if (!sd->selin)
572      {
573         d = (p * 2) - 1.0;
574         if (d > 0.0)
575           {
576              d = 1.0 - d;
577              d = d * d * d;
578              d = 1.0 - d;
579           }
580         else
581           {
582              d = -1.0 - d;
583              d = d * d * d;
584              d = -1.0 - d;
585           }
586         d = (1.0 + d) / 2.0;
587         sd->selmove = d;
588      }
589    else
590      {
591         d = ((1.0 - p) * 2) - 1.0;
592         if (d > 0.0)
593           {
594              d = 1.0 - d;
595              d = d * d * d;
596              d = 1.0 - d;
597           }
598         else
599           {
600              d = -1.0 - d;
601              d = d * d * d;
602              d = -1.0 - d;
603           }
604         d = (1.0 + d) / 2.0;
605         sd->selmove = d;
606      }
607    _e_smart_reconfigure(obj);
608    if (p == 1.0)
609      {
610         if (sd->selout)
611           {
612              sd->selin = EINA_TRUE;
613              sd->selout = EINA_FALSE;
614              sd->seltime = ecore_loop_time_get();
615              return ECORE_CALLBACK_RENEW;
616           }
617         sd->selout = EINA_FALSE;
618         sd->selin = EINA_FALSE;
619         sd->animator = NULL;
620         return ECORE_CALLBACK_CANCEL;
621      }
622    return ECORE_CALLBACK_RENEW;
623 }
624
625 static Eina_Bool
626 _sel_timer(void *data)
627 {
628    Evas_Object *obj = data;
629    Smart_Data *sd = evas_object_smart_data_get(obj);
630
631    if (!sd->animator)
632      {
633         sd->seltime = ecore_time_get();
634         sd->animator = ecore_animator_add(_sel_anim, obj);
635         sd->selin = EINA_FALSE;
636      }
637    sd->seltimer = NULL;
638    return ECORE_CALLBACK_CANCEL;
639 }
640
641 static void
642 _pan_unhilight(Evas_Object *obj __UNUSED__, Item *it)
643 {
644 //   Smart_Data *sd = evas_object_smart_data_get(obj);
645    if (!it->hilighted) return;
646    it->hilighted = 0;
647    if (it->frame)
648      edje_object_signal_emit(it->frame, "e,state,unselected", "e");
649 }
650
651 static void
652 _pan_hilight(Evas_Object *obj __UNUSED__, Item *it)
653 {
654    Eina_List *l;
655    Item *it2;
656    Smart_Data *sd = evas_object_smart_data_get(obj);
657
658    if (it->hilighted) return;
659    EINA_LIST_FOREACH(sd->items, l, it2)
660      {
661         if (it2->hilighted)
662           {
663              _pan_unhilight(obj, it2);
664              break;
665           }
666      }
667    it->hilighted = 1;
668    if (it->frame)
669      {
670         edje_object_signal_emit(it->frame, "e,state,selected", "e");
671         evas_object_raise(it->frame);
672      }
673 }
674
675
676 static void
677 _pan_sel(Evas_Object *obj, Item *it)
678 {
679    Smart_Data *sd = evas_object_smart_data_get(obj);
680
681    if (sd->selmove > 0.0) return;
682    edje_object_signal_emit(it->frame, "e,state,selected", "e");
683    evas_object_raise(it->frame);
684    if (!it->selected)
685      {
686         Eina_List *l;
687         Item *it2;
688
689         EINA_LIST_FOREACH(sd->items, l, it2)
690           {
691              if (it2->selected) it2->selected = 0;
692           }
693         it->selected = EINA_TRUE;
694         if (sd->info->bg_file) free(sd->info->bg_file);
695         evas_object_hide(sd->info->mini);
696         if (it->file)
697           {
698              char *name = NULL, *p;
699
700              sd->info->use_theme_bg = 0;
701              sd->info->bg_file = strdup(it->file);
702              edje_object_file_set(sd->info->mini, sd->info->bg_file,
703                                   "e/desktop/background");
704              p = strrchr(sd->info->bg_file, '/');
705              if (p)
706                {
707                   p++;
708                   name = strdup(p);
709                   p = strrchr(name, '.');
710                   if (p) *p = 0;
711                }
712              edje_object_part_text_set(sd->info->bg, "e.text.filename", name);
713              if (name) free(name);
714           }
715         else
716           {
717              const char *f = e_theme_edje_file_get("base/theme/backgrounds",
718                                                    "e/desktop/background");
719
720              edje_object_file_set(sd->info->mini, f, "e/desktop/background");
721              sd->info->use_theme_bg = 1;
722              sd->info->bg_file = NULL;
723              edje_object_part_text_set(sd->info->bg, "e.text.filename",
724                                        _("Theme Wallpaper"));
725           }
726         evas_object_show(sd->info->mini);
727      }
728    if (sd->seltimer) ecore_timer_del(sd->seltimer);
729    sd->seltimer = ecore_timer_add(0.2, _sel_timer, obj);
730 }
731
732 static void
733 _pan_sel_up(Evas_Object *obj)
734 {
735    Smart_Data *sd = evas_object_smart_data_get(obj);
736
737    if (sd->selmove == 0.0) return;
738    if (!sd->animator)
739      {
740         sd->seltime = ecore_loop_time_get();
741         sd->animator = ecore_animator_add(_sel_anim, obj);
742         sd->selin = EINA_TRUE;
743      }
744    else
745      {
746         if (sd->selin) return;
747         sd->selout = EINA_TRUE;
748      }
749 }
750
751 static int
752 _sort_cb(const void *d1, const void *d2)
753 {
754    const Item *it1 = d1, *it2 = d2;
755
756    if ((!it1->sort_id) || (!it2->sort_id)) return 0;
757    return strcmp(it1->sort_id, it2->sort_id);
758 }
759
760 static void
761 _item_sort(Item *it)
762 {
763    Evas_Object *obj = it->obj;
764    Smart_Data *sd = evas_object_smart_data_get(obj);
765    int num, dosort = 0;
766
767    sd->id_num++;
768    sd->info->scans--;
769    num = eina_list_count(sd->items);
770 //   if (sd->sort_num < sd->id_num)
771 //     {
772 //        sd->sort_num = sd->id_num + 10;
773 //        dosort = 1;
774 //     }
775    if ((sd->id_num == num) || (dosort))
776      {
777         sd->items = eina_list_sort(sd->items, num, _sort_cb);
778         _e_smart_reconfigure_do(obj);
779          if (sd->jump2hi)
780           {
781              Eina_List *l;
782              Item *it2 = NULL;
783
784              EINA_LIST_FOREACH(sd->items, l, it2)
785                {
786                   if (it2->hilighted) break;
787                   it2 = NULL;
788                }
789              if (it2)
790                e_scrollframe_child_region_show(sd->info->sframe,
791                                                it2->x, it2->y, it2->w, it2->h);
792              sd->jump2hi = 1;
793           }
794      }
795    if (sd->info->scans == 0)
796      edje_object_signal_emit(sd->info->bg, "e,state,busy,off", "e");
797 }
798
799 static void
800 _thumb_gen(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
801 {
802    Item *it = data;
803
804    edje_object_signal_emit(it->frame, "e,action,thumb,gen", "e");
805    if (!it->sort_id)
806      {
807         const char *id = e_thumb_sort_id_get(it->image);
808
809         if (id)
810           {
811              it->sort_id = strdup(id);
812              _item_sort(it);
813           }
814      }
815    it->have_thumb = EINA_TRUE;
816    if (!it->visible)
817      {
818         if (it->do_thumb)
819           {
820              e_thumb_icon_end(it->image);
821              it->do_thumb = EINA_FALSE;
822           }
823         evas_object_del(it->image);
824         it->image = NULL;
825         evas_object_del(it->frame);
826         it->frame = NULL;
827      }
828 }
829
830 static void
831 _item_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
832 {
833 //   Evas_Event_Mouse_Down *ev = event_info;
834 //   Item *it = data;
835 //   _pan_sel(it->obj, it);
836 }
837
838 static void
839 _item_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
840 {
841    Evas_Event_Mouse_Up *ev = event_info;
842    Item *it = data;
843
844    if (ev->button == 1)
845      {
846         if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
847           {
848              _pan_hilight(it->obj, it);
849              _pan_sel(it->obj, it);
850              // FIXME: select image!!!
851           }
852      }
853 }
854
855 static void
856 _pan_file_add(Evas_Object *obj, const char *file, Eina_Bool remote, Eina_Bool theme)
857 {
858    Smart_Data *sd = evas_object_smart_data_get(obj);
859    Item *it = calloc(1, sizeof(Item));
860    Evas *evas;
861
862    if (!it) return;
863    evas = evas_object_evas_get(obj);
864    sd->items = eina_list_append(sd->items, it);
865    it->obj = obj;
866    it->remote = remote;
867    it->theme = theme;
868    it->file = eina_stringshare_add(file);
869    it->frame = edje_object_add(evas);
870    if (it->theme)
871      e_theme_edje_object_set(it->frame, "base/theme/widgets",
872                              "e/conf/wallpaper/main/mini-theme");
873    else if (it->remote)
874      e_theme_edje_object_set(it->frame, "base/theme/widgets",
875                              "e/conf/wallpaper/main/mini-remote");
876    else
877      e_theme_edje_object_set(it->frame, "base/theme/widgets",
878                              "e/conf/wallpaper/main/mini");
879    if (it->hilighted)
880      {
881         edje_object_signal_emit(it->frame, "e,state,selected", "e");
882         evas_object_raise(it->frame);
883      }
884    evas_object_event_callback_add(it->frame, EVAS_CALLBACK_MOUSE_DOWN,
885                                   _item_down, it);
886    evas_object_event_callback_add(it->frame, EVAS_CALLBACK_MOUSE_UP,
887                                   _item_up, it);
888
889    evas_object_smart_member_add(it->frame, obj);
890    evas_object_clip_set(it->frame, evas_object_clip_get(obj));
891    evas_object_show(it->frame);
892    it->image = e_thumb_icon_add(evas);
893    edje_object_part_swallow(it->frame, "e.swallow.content", it->image);
894    evas_object_smart_callback_add(it->image, "e_thumb_gen", _thumb_gen, it);
895    if (it->theme)
896      {
897         const char *f = e_theme_edje_file_get("base/theme/backgrounds",
898                                               "e/desktop/background");
899
900         e_thumb_icon_file_set(it->image, f, "e/desktop/background");
901      }
902    else
903      e_thumb_icon_file_set(it->image, it->file, "e/desktop/background");
904    e_thumb_icon_size_set(it->image, sd->info->iw, sd->info->ih);
905    evas_object_show(it->image);
906
907    e_thumb_icon_begin(it->image);
908    it->do_thumb = 1;
909 //   e_thumb_icon_begin(it->image);
910
911    if (it->theme)
912      {
913         if (sd->info->use_theme_bg)
914           {
915              _pan_hilight(it->obj, it);
916              edje_object_part_text_set(sd->info->bg, "e.text.filename",
917                                        _("Theme Wallpaper"));
918           }
919      }
920    else
921      {
922         if (sd->info->bg_file)
923           {
924              int match = 0;
925
926              if (!strcmp(sd->info->bg_file, it->file)) match = 1;
927              if (!match)
928                {
929                   const char *p1, *p2;
930
931                   p1 = ecore_file_file_get(sd->info->bg_file);
932                   p2 = ecore_file_file_get(it->file);
933                   if (!strcmp(p1, p2)) match = 1;
934                }
935              if (match)
936                {
937                   char *name = NULL, *p;
938
939                   sd->jump2hi = 1;
940                   _pan_hilight(it->obj, it);
941                   p = strrchr(sd->info->bg_file, '/');
942                   if (p)
943                     {
944                        p++;
945                        name = strdup(p);
946                        p = strrchr(name, '.');
947                        if (p) *p = 0;
948                     }
949                   edje_object_part_text_set(sd->info->bg, "e.text.filename", name);
950                   if (name) free(name);
951                }
952           }
953      }
954    _e_smart_reconfigure(obj);
955 }
956
957 ////////
958
959 static void
960 _resize(E_Win *wn)
961 {
962    Info *info = wn->data;
963
964    evas_object_resize(info->bg, wn->w, wn->h);
965 }
966
967 static void
968 _delete(E_Win *wn __UNUSED__)
969 {
970    wp_conf_hide();
971 }
972
973 static void
974 _bg_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
975 {
976    Info *info = data;
977
978    _pan_sel_up(info->span);
979 }
980
981 static void
982 _apply(void *data, void *data2 __UNUSED__)
983 {
984    Info *info = data;
985
986    if (info->mode == 0)
987      {
988         /* all desktops */
989         while (e_config->desktop_backgrounds)
990           {
991              E_Config_Desktop_Background *cfbg;
992
993              cfbg = e_config->desktop_backgrounds->data;
994              e_bg_del(cfbg->container, cfbg->zone, cfbg->desk_x, cfbg->desk_y);
995           }
996         if ((info->use_theme_bg) || (!info->bg_file))
997           e_bg_default_set(NULL);
998         else
999           e_bg_default_set(info->bg_file);
1000      }
1001    else if (info->mode == 1)
1002      {
1003         /* specific desk */
1004         e_bg_del(info->con_num, info->zone_num, info->desk_x, info->desk_y);
1005         e_bg_add(info->con_num, info->zone_num, info->desk_x, info->desk_y,
1006                  info->bg_file);
1007      }
1008    else
1009      {
1010         Eina_List *dlist = NULL, *l;
1011         E_Config_Desktop_Background *cfbg;
1012
1013         /* this screen */
1014         EINA_LIST_FOREACH(e_config->desktop_backgrounds, l, cfbg)
1015           {
1016              if (cfbg->zone == info->zone_num)
1017                dlist = eina_list_append(dlist, cfbg);
1018           }
1019         EINA_LIST_FREE(dlist, cfbg)
1020           e_bg_del(cfbg->container, cfbg->zone, cfbg->desk_x, cfbg->desk_y);
1021         e_bg_add(info->con_num, info->zone_num, -1, -1, info->bg_file);
1022      }
1023    e_bg_update();
1024    e_config_save_queue();
1025 }
1026
1027 static void
1028 _close(void *data __UNUSED__, void *data2 __UNUSED__)
1029 {
1030    wp_conf_hide();
1031 }
1032
1033 static void
1034 _ok(void *data, void *data2 __UNUSED__)
1035 {
1036   _apply(data, data2);
1037   wp_conf_hide();
1038 }
1039
1040 static void
1041 _wp_add(void *data, void *data2 __UNUSED__)
1042 {
1043    Info *info = data;
1044
1045    edje_object_signal_emit(info->bg, "e,action,panel,hide", "e");
1046 }
1047
1048 static void
1049 _wp_delete(void *data, void *data2 __UNUSED__)
1050 {
1051    Info *info = data;
1052
1053    edje_object_signal_emit(info->bg, "e,action,panel,hide", "e");
1054 }
1055
1056 static void
1057 _wp_changed(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1058 {
1059    Info *info = data;
1060
1061    edje_object_signal_emit(info->bg, "e,action,panel,hide", "e");
1062 }
1063
1064 static Eina_Bool
1065 _idler(void *data)
1066 {
1067    Eina_File_Direct_Info *st;
1068    Info *info = data;
1069
1070    if (!info->dir)
1071      {
1072         info->idler = NULL;
1073         return ECORE_CALLBACK_CANCEL;
1074      }
1075    if (!eina_iterator_next(info->dir, (void**) &st))
1076      {
1077         free(info->curdir);
1078         info->curdir = NULL;
1079         eina_iterator_free(info->dir);
1080         info->dir = NULL;
1081         info->idler = NULL;
1082         _scan(info);
1083         return ECORE_CALLBACK_CANCEL;
1084      }
1085    if ((st->path[st->name_start]) == '.')
1086      return ECORE_CALLBACK_RENEW;
1087    if (st->type == EINA_FILE_DIR)
1088      {
1089         info->dirs = eina_list_append(info->dirs, strdup(st->path));
1090         return ECORE_CALLBACK_RENEW;
1091      }
1092    info->scans++;
1093    _pan_file_add(info->span, st->path, 0, 0);
1094
1095    e_util_wakeup();
1096    return ECORE_CALLBACK_RENEW;
1097 }
1098
1099 static void
1100 _scan(Info *info)
1101 {
1102    if (info->dirs)
1103      {
1104         if (info->scans <= 0)
1105           {
1106              info->scans = 0;
1107              edje_object_signal_emit(info->bg, "e,state,busy,on", "e");
1108              edje_object_part_text_set(info->bg, "e.text.busy_label",
1109                                        _("Loading files..."));
1110           }
1111         if (info->curdir) free(info->curdir);
1112         info->curdir = info->dirs->data;
1113         info->dirs = eina_list_remove_list(info->dirs, info->dirs);
1114         if (!info->dir) info->dir = eina_file_stat_ls(info->curdir);
1115         info->idler = ecore_idler_add(_idler, info);
1116      }
1117 }
1118
1119 Info *
1120 wp_browser_new(E_Container *con)
1121 {
1122    Info *info;
1123    E_Win *win;
1124    E_Zone *zone;
1125    E_Desk *desk;
1126    const E_Config_Desktop_Background *cfbg;
1127    Evas_Coord mw, mh;
1128    Evas_Object *o, *o2, *ob;
1129    E_Radio_Group *rg;
1130    char buf[PATH_MAX];
1131
1132    info = calloc(1, sizeof(Info));
1133    if (!info) return NULL;
1134
1135    zone = e_util_zone_current_get(con->manager);
1136    desk = e_desk_current_get(zone);
1137    info->con_num = con->num;
1138    info->zone_num = zone->num;
1139    info->desk_x = desk->x;
1140    info->desk_y = desk->y;
1141    info->mode = 0;
1142    cfbg = e_bg_config_get(con->num, zone->num, desk->x, desk->y);
1143    if (cfbg)
1144      {
1145         if ((cfbg->container >= 0) && (cfbg->zone >= 0))
1146           {
1147              if ((cfbg->desk_x >= 0) && (cfbg->desk_y >= 0))
1148                info->mode = 1;
1149              else
1150                info->mode = 2;
1151           }
1152         info->bg_file = strdup(cfbg->file);
1153      }
1154    if ((!info->bg_file) && (e_config->desktop_default_background))
1155      info->bg_file = strdup(e_config->desktop_default_background);
1156    else
1157      info->use_theme_bg = 1;
1158
1159    info->iw = (120 * e_scale);
1160    info->ih = (zone->h * info->iw) / (zone->w);
1161
1162    win = e_win_new(con);
1163    if (!win)
1164      {
1165         free(info);
1166         info = NULL;
1167         return NULL;
1168      }
1169    info->win = win;
1170    win->data = info;
1171
1172    e_user_dir_concat_static(buf, "backgrounds");
1173    info->dirs = eina_list_append(info->dirs, strdup(buf));
1174    e_prefix_data_concat_static(buf, "data/backgrounds");
1175    info->dirs = eina_list_append(info->dirs, strdup(buf));
1176
1177    e_win_title_set(win, _("Wallpaper Settings"));
1178    e_win_name_class_set(win, "E", "_config::appearance/wallpaper2");
1179    e_win_resize_callback_set(win, _resize);
1180    e_win_delete_callback_set(win, _delete);
1181
1182    // bg + container
1183    info->bg = edje_object_add(info->win->evas);
1184    e_theme_edje_object_set(info->bg, "base/theme/widgets",
1185                            "e/conf/wallpaper/main/window");
1186    edje_object_signal_callback_add(info->bg, "e,action,click", "e",
1187                                    _bg_clicked, info);
1188
1189    info->box = e_widget_list_add(info->win->evas, 1, 1);
1190
1191    // ok button
1192    info->button = e_widget_button_add(info->win->evas, _("OK"), NULL,
1193                                       _ok, info, NULL);
1194    evas_object_show(info->button);
1195    e_widget_list_object_append(info->box, info->button, 1, 0, 0.5);
1196
1197    // apply button
1198    info->button = e_widget_button_add(info->win->evas, _("Apply"), NULL,
1199                                       _apply, info, NULL);
1200    evas_object_show(info->button);
1201    e_widget_list_object_append(info->box, info->button, 1, 0, 0.5);
1202
1203    // close button
1204    info->button = e_widget_button_add(info->win->evas, _("Close"), NULL,
1205                                       _close, info, NULL);
1206    evas_object_show(info->button);
1207    e_widget_list_object_append(info->box, info->button, 1, 0, 0.5);
1208
1209    e_widget_size_min_get(info->box, &mw, &mh);
1210    edje_extern_object_min_size_set(info->box, mw, mh);
1211    edje_object_part_swallow(info->bg, "e.swallow.buttons", info->box);
1212    evas_object_show(info->box);
1213
1214    // preview
1215    info->preview = e_livethumb_add(info->win->evas);
1216    e_livethumb_vsize_set(info->preview, zone->w, zone->h);
1217    edje_extern_object_aspect_set(info->preview, EDJE_ASPECT_CONTROL_NEITHER,
1218                                  zone->w, zone->h);
1219    edje_object_part_swallow(info->bg, "e.swallow.preview", info->preview);
1220    evas_object_show(info->preview);
1221
1222    info->mini = edje_object_add(e_livethumb_evas_get(info->preview));
1223    e_livethumb_thumb_set(info->preview, info->mini);
1224    evas_object_show(info->mini);
1225    if (info->bg_file)
1226      edje_object_file_set(info->mini, info->bg_file, "e/desktop/background");
1227    else
1228      {
1229         const char *f = e_theme_edje_file_get("base/theme/backgrounds",
1230                                               "e/desktop/background");
1231
1232         edje_object_file_set(info->mini, f, "e/desktop/background");
1233      }
1234
1235    // scrolled thumbs
1236    info->span = _pan_add(info->win->evas);
1237    _pan_info_set(info->span, info);
1238
1239    // the scrollframe holding the scrolled thumbs
1240    info->sframe = e_scrollframe_add(info->win->evas);
1241    e_scrollframe_custom_theme_set(info->sframe, "base/theme/widgets",
1242                                   "e/conf/wallpaper/main/scrollframe");
1243    e_scrollframe_extern_pan_set(info->sframe, info->span,
1244                                 _pan_set, _pan_get, _pan_max_get,
1245                                 _pan_child_size_get);
1246    edje_object_part_swallow(info->bg, "e.swallow.list", info->sframe);
1247    evas_object_show(info->sframe);
1248    evas_object_show(info->span);
1249
1250    ob = e_widget_list_add(info->win->evas, 0, 1);
1251
1252    o = e_widget_list_add(info->win->evas, 1, 0);
1253
1254    rg = e_widget_radio_group_new(&(info->mode));
1255    o2 = e_widget_radio_add(info->win->evas, _("All Desktops"), 0, rg);
1256    evas_object_smart_callback_add(o2, "changed", _wp_changed, info);
1257    e_widget_list_object_append(o, o2, 1, 0, 0.5);
1258    e_widget_disabled_set(o2, (e_util_container_desk_count_get(con) < 2));
1259    evas_object_show(o2);
1260
1261    o2 = e_widget_radio_add(info->win->evas, _("This Desktop"), 1, rg);
1262    evas_object_smart_callback_add(o2, "changed", _wp_changed, info);
1263    e_widget_list_object_append(o, o2, 1, 0, 0.5);
1264    evas_object_show(o2);
1265
1266    o2 = e_widget_radio_add(info->win->evas, _("This Screen"), 2, rg);
1267    evas_object_smart_callback_add(o2, "changed", _wp_changed, info);
1268    e_widget_list_object_append(o, o2, 1, 0, 0.5);
1269    if (!(e_util_container_zone_number_get(0, 1) ||
1270          (e_util_container_zone_number_get(1, 0))))
1271      e_widget_disabled_set(o2, EINA_TRUE);
1272    evas_object_show(o2);
1273
1274    e_widget_list_object_append(ob, o, 1, 0, 0.5);
1275    evas_object_show(o);
1276
1277    o = e_widget_list_add(info->win->evas, 1, 0);
1278
1279    o2 =  e_widget_button_add(info->win->evas, _("Add"), NULL,
1280                              _wp_add, info, NULL);
1281    e_widget_list_object_append(o, o2, 1, 0, 0.5);
1282    evas_object_show(o2);
1283
1284    o2 =  e_widget_button_add(info->win->evas, _("Delete"), NULL,
1285                              _wp_delete, info, NULL);
1286    e_widget_list_object_append(o, o2, 1, 0, 0.5);
1287    evas_object_show(o2);
1288
1289    e_widget_list_object_append(ob, o, 1, 0, 0.5);
1290    evas_object_show(o);
1291
1292    e_widget_size_min_get(ob, &mw, &mh);
1293    edje_extern_object_min_size_set(ob, mw, mh);
1294    edje_object_part_swallow(info->bg, "e.swallow.extras", ob);
1295    evas_object_show(ob);
1296
1297    // min size calc
1298    edje_object_size_min_calc(info->bg, &mw, &mh);
1299    e_win_size_min_set(win, mw, mh);
1300    if ((zone->w / 4) > mw) mw = (zone->w / 4);
1301    if ((zone->h / 4) > mh) mh = (zone->h / 4);
1302    e_win_resize(win, mw, mh);
1303    e_win_centered_set(win, 1);
1304    e_win_show(win);
1305    e_win_border_icon_set(win, "preferences-desktop-wallpaper");
1306
1307    evas_object_resize(info->bg, info->win->w, info->win->h);
1308    evas_object_show(info->bg);
1309
1310    // add theme bg
1311    _pan_file_add(info->span, NULL, 0, 1);
1312
1313    _scan(info);
1314    return info;
1315 }
1316
1317 void
1318 wp_broser_free(Info *info)
1319 {
1320    char *s;
1321
1322    if (!info) return;
1323    e_object_del(E_OBJECT(info->win));
1324    if (info->dir) eina_iterator_free(info->dir);
1325    free(info->bg_file);
1326    free(info->curdir);
1327    EINA_LIST_FREE(info->dirs, s)
1328      free(s);
1329    if (info->idler) ecore_idler_del(info->idler);
1330    // del other stuff
1331    free(info);
1332    info = NULL;
1333 }
1334
1335 E_Config_Dialog *
1336 wp_conf_show(E_Container *con, const char *params __UNUSED__)
1337 {
1338    if (global_info)
1339      {
1340         e_win_show(global_info->win);
1341         e_win_raise(global_info->win);
1342      }
1343    global_info = wp_browser_new(con);
1344
1345    return NULL;
1346 }
1347
1348 void
1349 wp_conf_hide(void)
1350 {
1351    if (global_info)
1352      {
1353         wp_broser_free(global_info);
1354         global_info = NULL;
1355      }
1356 }