1cfc0f26371ad758b2c5f29063b789b9c56c454e
[framework/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    DIR *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 void _e_smart_reconfigure(Evas_Object *obj);
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 *evas;
138
139    if (!sd) return ECORE_CALLBACK_CANCEL;
140    if (sd->cx > (sd->cw - sd->w)) sd->cx = sd->cw - sd->w;
141    if (sd->cy > (sd->ch - sd->h)) sd->cy = sd->ch - sd->h;
142    if (sd->cx < 0) sd->cx = 0;
143    if (sd->cy < 0) sd->cy = 0;
144
145    iw = sd->w / 4;
146    if (iw > (120 * e_scale)) iw = (120 * e_scale);
147    else
148      {
149         if (iw < (60 * e_scale)) iw = (sd->w / 3);
150         if (iw < (60 * e_scale)) iw = (sd->w / 2);
151         if (iw < (60 * e_scale)) iw = sd->w;
152      }
153    x = 0;
154    y = 0;
155    ww = iw;
156    hh = (sd->info->ih * iw) / (sd->info->iw);
157    mw = mh = 0;
158
159    evas = evas_object_evas_get(obj);
160    EINA_LIST_FOREACH(sd->items, l, it)
161      {
162         xx = sd->x - sd->cx + x;
163         if (x > (sd->w - ww))
164           {
165              x = 0;
166              y += hh;
167              xx = sd->x - sd->cx + x;
168           }
169         yy = sd->y - sd->cy + y;
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, vw, vh;
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         evas_output_viewport_get(evas, NULL, NULL, &vw, &vh);
298         if (E_INTERSECTS(xx, yy, it->w, it->h, 0, 0, vw, vh))
299           {
300              if (!it->have_thumb)
301                {
302                   if (!it->do_thumb)
303                     {
304                        e_thumb_icon_begin(it->image);
305                        it->do_thumb = EINA_TRUE;
306                     }
307                }
308              else
309                {
310                   if (!it->frame)
311                     {
312                        it->frame = edje_object_add(evas);
313                        if (it->theme)
314                          e_theme_edje_object_set(it->frame, "base/theme/widgets",
315                                                  "e/conf/wallpaper/main/mini-theme");
316                        else if (it->remote)
317                          e_theme_edje_object_set(it->frame, "base/theme/widgets",
318                                                  "e/conf/wallpaper/main/mini-remote");
319                        else
320                          e_theme_edje_object_set(it->frame, "base/theme/widgets",
321                                                  "e/conf/wallpaper/main/mini");
322                        if (it->hilighted)
323                          {
324                             edje_object_signal_emit(it->frame, "e,state,selected", "e");
325                             evas_object_raise(it->frame);
326                          }
327                        evas_object_event_callback_add(it->frame, EVAS_CALLBACK_MOUSE_DOWN,
328                                                       _item_down, it);
329                        evas_object_event_callback_add(it->frame, EVAS_CALLBACK_MOUSE_UP,
330                                                       _item_up, it);
331
332                        evas_object_smart_member_add(it->frame, obj);
333                        evas_object_clip_set(it->frame, evas_object_clip_get(obj));
334                        it->image = e_thumb_icon_add(evas);
335                        edje_object_part_swallow(it->frame, "e.swallow.content", it->image);
336                        evas_object_smart_callback_add(it->image, "e_thumb_gen", _thumb_gen, it);
337                        if (it->theme)
338                          {
339                             const char *f;
340
341                             f = e_theme_edje_file_get("base/theme/backgrounds",
342                                                       "e/desktop/background");
343                             e_thumb_icon_file_set(it->image, f, 
344                                                   "e/desktop/background");
345                          }
346                        else
347                          e_thumb_icon_file_set(it->image, it->file, 
348                                                "e/desktop/background");
349                        e_thumb_icon_size_set(it->image, sd->info->iw, 
350                                              sd->info->ih);
351                        evas_object_show(it->image);
352
353                        e_thumb_icon_begin(it->image);
354                     }
355                }
356              evas_object_move(it->frame, xx + dx, yy + dy);
357              evas_object_resize(it->frame, it->w, it->h);
358              evas_object_show(it->frame);
359              it->visible = EINA_TRUE;
360           }
361         else
362           {
363              if (it->have_thumb)
364                {
365                   if (it->do_thumb)
366                     {
367                        e_thumb_icon_end(it->image);
368                        it->do_thumb = EINA_FALSE;
369                     }
370                   evas_object_del(it->image);
371                   it->image = NULL;
372                   evas_object_del(it->frame);
373                   it->frame = NULL;
374                }
375              it->visible = EINA_FALSE;
376 /*             
377              if (it->have_thumb)
378                {
379                   if (it->do_thumb)
380                     {
381                        e_thumb_icon_end(it->image);
382                        it->do_thumb = EINA_FALSE;
383                     }
384                   evas_object_del(it->image);
385                   it->have_thumb = EINA_FALSE;
386                   it->image = e_thumb_icon_add(evas);
387                   edje_object_part_swallow(it->frame, "e.swallow.content", it->image);
388                   evas_object_smart_callback_add(it->image, "e_thumb_gen", _thumb_gen, it);
389                   if (it->theme)
390                     {
391                        const char *f = e_theme_edje_file_get("base/theme/backgrounds",
392                                                              "e/desktop/background");
393                        e_thumb_icon_file_set(it->image, f, "e/desktop/background");
394                     }
395                   else
396                     e_thumb_icon_file_set(it->image, it->file, "e/desktop/background");
397                   e_thumb_icon_size_set(it->image, sd->info->iw, sd->info->ih);
398                   evas_object_show(it->image);
399                   edje_object_signal_emit(it->frame, "e,action,thumb,ungen", "e");
400                }
401              else
402                {
403                   if (it->sort_id)
404                     {
405                        if (it->do_thumb)
406                          {
407                             e_thumb_icon_end(it->image);
408                             it->do_thumb = 0;
409                          }
410                     }
411                }
412  */
413           }
414      }
415
416    if (changed)
417      evas_object_smart_callback_call(obj, "changed", NULL);
418    if (recursion == 0) sd->idle_enter = NULL;
419    return ECORE_CALLBACK_CANCEL;
420 }
421
422 static void
423 _e_smart_reconfigure(Evas_Object *obj)
424 {
425    Smart_Data *sd = evas_object_smart_data_get(obj);
426
427    if (sd->idle_enter) return;
428    sd->idle_enter = ecore_idle_enterer_before_add(_e_smart_reconfigure_do, obj);
429 }
430
431 static void
432 _e_smart_add(Evas_Object *obj)
433 {
434    Smart_Data *sd = calloc(1, sizeof(Smart_Data));
435
436    if (!sd) return;
437
438    sd->sx = sd->sy = -1;
439    evas_object_smart_data_set(obj, sd);
440 }
441
442 static void
443 _e_smart_del(Evas_Object *obj)
444 {
445    Smart_Data *sd = evas_object_smart_data_get(obj);
446    Item *it;
447
448    if (sd->seltimer)
449      ecore_timer_del(sd->seltimer);
450    if (sd->idle_enter)
451      ecore_idle_enterer_del(sd->idle_enter);
452    if (sd->animator)
453      ecore_animator_del(sd->animator);
454    // sd->info is just referenced
455    // sd->child_obj is unused
456    EINA_LIST_FREE(sd->items, it)
457      {
458         if (it->frame) evas_object_del(it->frame);
459         if (it->image) evas_object_del(it->image);
460         if (it->file) eina_stringshare_del(it->file);
461         free(it->sort_id);
462         free(it);
463      }
464    free(sd);
465    evas_object_smart_data_set(obj, NULL);
466 }
467
468 static void
469 _e_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
470 {
471    Smart_Data *sd = evas_object_smart_data_get(obj);
472
473    sd->x = x;
474    sd->y = y;
475    _e_smart_reconfigure(obj);
476 }
477
478 static void
479 _e_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
480 {
481    Smart_Data *sd = evas_object_smart_data_get(obj);
482
483    sd->w = w;
484    sd->h = h;
485    _e_smart_reconfigure(obj);
486    evas_object_smart_callback_call(obj, "changed", NULL);
487 }
488
489 static void
490 _e_smart_show(Evas_Object *obj __UNUSED__)
491 {
492 //   Smart_Data *sd = evas_object_smart_data_get(obj);
493 //   evas_object_show(sd->child_obj);
494 }
495
496 static void
497 _e_smart_hide(Evas_Object *obj __UNUSED__)
498 {
499 //   Smart_Data *sd = evas_object_smart_data_get(obj);
500 //   evas_object_hide(sd->child_obj);
501 }
502
503 static void
504 _e_smart_color_set(Evas_Object *obj __UNUSED__, int r __UNUSED__, int g __UNUSED__, int b __UNUSED__, int a __UNUSED__)
505 {
506 //   Smart_Data *sd = evas_object_smart_data_get(obj);
507 //   evas_object_color_set(sd->child_obj, r, g, b, a);
508 }
509
510 static void
511 _e_smart_clip_set(Evas_Object *obj __UNUSED__, Evas_Object * clip __UNUSED__)
512 {
513 //   Smart_Data *sd = evas_object_smart_data_get(obj);
514 //   evas_object_clip_set(sd->child_obj, clip);
515 }
516
517 static void
518 _e_smart_clip_unset(Evas_Object *obj __UNUSED__)
519 {
520 //   Smart_Data *sd = evas_object_smart_data_get(obj);
521 //   evas_object_clip_unset(sd->child_obj);
522 }
523
524 static Evas_Object *
525 _pan_add(Evas *evas)
526 {
527    static Evas_Smart *smart = NULL;
528    static const Evas_Smart_Class sc =
529      {
530         "wp_pan",
531           EVAS_SMART_CLASS_VERSION,
532           _e_smart_add,
533           _e_smart_del,
534           _e_smart_move,
535           _e_smart_resize,
536           _e_smart_show,
537           _e_smart_hide,
538           _e_smart_color_set,
539           _e_smart_clip_set,
540           _e_smart_clip_unset,
541           NULL,
542           NULL,
543           NULL,
544           NULL, 
545           NULL, 
546           NULL, 
547           NULL
548      };
549    smart = evas_smart_class_new(&sc);
550    return evas_object_smart_add(evas, smart);
551 }
552
553 static void
554 _pan_info_set(Evas_Object *obj, Info *info)
555 {
556    Smart_Data *sd = evas_object_smart_data_get(obj);
557
558    sd->info = info;
559 }
560
561 static Eina_Bool
562 _sel_anim(void *data)
563 {
564    Evas_Object *obj = data;
565    Smart_Data *sd = evas_object_smart_data_get(obj);
566    double t = ecore_loop_time_get() - sd->seltime;
567    double len = 1.0;
568    double p = t / len;
569    double d;
570
571    if (p > 1.0) p = 1.0;
572    if (!sd->selin)
573      {
574         d = (p * 2) - 1.0;
575         if (d > 0.0)
576           {
577              d = 1.0 - d;
578              d = d * d * d;
579              d = 1.0 - d;
580           }
581         else
582           {
583              d = -1.0 - d;
584              d = d * d * d;
585              d = -1.0 - d;
586           }
587         d = (1.0 + d) / 2.0;
588         sd->selmove = d;
589      }
590    else
591      {
592         d = ((1.0 - p) * 2) - 1.0;
593         if (d > 0.0)
594           {
595              d = 1.0 - d;
596              d = d * d * d;
597              d = 1.0 - d;
598           }
599         else
600           {
601              d = -1.0 - d;
602              d = d * d * d;
603              d = -1.0 - d;
604           }
605         d = (1.0 + d) / 2.0;
606         sd->selmove = d;
607      }
608    _e_smart_reconfigure(obj);
609    if (p == 1.0)
610      {
611         if (sd->selout)
612           {
613              sd->selin = EINA_TRUE;
614              sd->selout = EINA_FALSE;
615              sd->seltime = ecore_loop_time_get();
616              return ECORE_CALLBACK_RENEW;
617           }
618         sd->selout = EINA_FALSE;
619         sd->selin = EINA_FALSE;
620         sd->animator = NULL;
621         return ECORE_CALLBACK_CANCEL;
622      }
623    return ECORE_CALLBACK_RENEW;
624 }
625
626 static Eina_Bool
627 _sel_timer(void *data)
628 {
629    Evas_Object *obj = data;
630    Smart_Data *sd = evas_object_smart_data_get(obj);
631
632    if (!sd->animator)
633      {
634         sd->seltime = ecore_time_get();
635         sd->animator = ecore_animator_add(_sel_anim, obj);
636         sd->selin = EINA_FALSE;
637      }
638    sd->seltimer = NULL;
639    return ECORE_CALLBACK_CANCEL;
640 }
641
642 static void
643 _pan_unhilight(Evas_Object *obj __UNUSED__, Item *it)
644 {
645 //   Smart_Data *sd = evas_object_smart_data_get(obj);
646    if (!it->hilighted) return;
647    it->hilighted = 0;
648    if (it->frame)
649      edje_object_signal_emit(it->frame, "e,state,unselected", "e");
650 }
651
652 static void
653 _pan_hilight(Evas_Object *obj __UNUSED__, Item *it)
654 {
655    Eina_List *l;
656    Item *it2;
657    Smart_Data *sd = evas_object_smart_data_get(obj);
658
659    if (it->hilighted) return;
660    EINA_LIST_FOREACH(sd->items, l, it2)
661      {
662         if (it2->hilighted)
663           {
664              _pan_unhilight(obj, it2);
665              break;
666           }
667      }
668    it->hilighted = 1;
669    if (it->frame)
670      {
671         edje_object_signal_emit(it->frame, "e,state,selected", "e");
672         evas_object_raise(it->frame);
673      }
674 }
675
676
677 static void
678 _pan_sel(Evas_Object *obj, Item *it)
679 {
680    Smart_Data *sd = evas_object_smart_data_get(obj);
681
682    if (sd->selmove > 0.0) return;
683    edje_object_signal_emit(it->frame, "e,state,selected", "e");
684    evas_object_raise(it->frame); 
685    if (!it->selected)
686      {
687         Eina_List *l;
688         Item *it2;
689
690         EINA_LIST_FOREACH(sd->items, l, it2)
691           {
692              if (it2->selected) it2->selected = 0;
693           }
694         it->selected = EINA_TRUE;
695         if (sd->info->bg_file) free(sd->info->bg_file);
696         evas_object_hide(sd->info->mini);
697         if (it->file)
698           {
699              char *name = NULL, *p;
700
701              sd->info->use_theme_bg = 0;
702              sd->info->bg_file = strdup(it->file);
703              edje_object_file_set(sd->info->mini, sd->info->bg_file,
704                                   "e/desktop/background");
705              p = strrchr(sd->info->bg_file, '/');
706              if (p)
707                {
708                   p++;
709                   name = strdup(p);
710                   p = strrchr(name, '.');
711                   if (p) *p = 0;
712                }
713              edje_object_part_text_set(sd->info->bg, "e.text.filename", name);
714              if (name) free(name);
715           }
716         else
717           {
718              const char *f = e_theme_edje_file_get("base/theme/backgrounds",
719                                                    "e/desktop/background");
720
721              edje_object_file_set(sd->info->mini, f, "e/desktop/background");
722              sd->info->use_theme_bg = 1;
723              sd->info->bg_file = NULL;
724              edje_object_part_text_set(sd->info->bg, "e.text.filename", 
725                                        _("Theme Wallpaper"));
726           }
727         evas_object_show(sd->info->mini);
728      }
729    if (sd->seltimer) ecore_timer_del(sd->seltimer);
730    sd->seltimer = ecore_timer_add(0.2, _sel_timer, obj);
731 }
732
733 static void
734 _pan_sel_up(Evas_Object *obj)
735 {
736    Smart_Data *sd = evas_object_smart_data_get(obj);
737
738    if (sd->selmove == 0.0) return;
739    if (!sd->animator)
740      {
741         sd->seltime = ecore_loop_time_get();
742         sd->animator = ecore_animator_add(_sel_anim, obj);
743         sd->selin = EINA_TRUE;
744      }
745    else
746      {
747         if (sd->selin) return;
748         sd->selout = EINA_TRUE;
749      }
750 }
751
752 static int
753 _sort_cb(const void *d1, const void *d2)
754 {
755    const Item *it1 = d1, *it2 = d2;
756
757    if ((!it1->sort_id) || (!it2->sort_id)) return 0;
758    return strcmp(it1->sort_id, it2->sort_id);
759 }
760
761 static void
762 _item_sort(Item *it)
763 {
764    Evas_Object *obj = it->obj;
765    Smart_Data *sd = evas_object_smart_data_get(obj);
766    int num, dosort = 0;
767
768    sd->id_num++;
769    sd->info->scans--;
770    num = eina_list_count(sd->items);
771 //   if (sd->sort_num < sd->id_num)
772 //     {
773 //        sd->sort_num = sd->id_num + 10;
774 //        dosort = 1;
775 //     }
776    if ((sd->id_num == num) || (dosort))
777      {
778         sd->items = eina_list_sort(sd->items, num, _sort_cb);
779         _e_smart_reconfigure_do(obj);
780          if (sd->jump2hi)
781           {
782              Eina_List *l;
783              Item *it2 = NULL;
784
785              EINA_LIST_FOREACH(sd->items, l, it2)
786                {
787                   if (it2->hilighted) break;
788                   it2 = NULL;
789                }
790              if (it2)
791                e_scrollframe_child_region_show(sd->info->sframe,
792                                                it2->x, it2->y, it2->w, it2->h);
793              sd->jump2hi = 1;
794           }
795      }
796    if (sd->info->scans == 0)
797      edje_object_signal_emit(sd->info->bg, "e,state,busy,off", "e");
798 }
799
800 static void
801 _thumb_gen(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
802 {
803    Item *it = data;
804
805    edje_object_signal_emit(it->frame, "e,action,thumb,gen", "e");
806    if (!it->sort_id)
807      {
808         const char *id = e_thumb_sort_id_get(it->image);
809
810         if (id)
811           {
812              it->sort_id = strdup(id);
813              _item_sort(it);
814           }
815      }
816    it->have_thumb = EINA_TRUE;
817    if (!it->visible)
818      {
819         if (it->do_thumb)
820           {
821              e_thumb_icon_end(it->image);
822              it->do_thumb = EINA_FALSE;
823           }
824         evas_object_del(it->image);
825         it->image = NULL;
826         evas_object_del(it->frame);
827         it->frame = NULL;
828      }
829 }
830
831 static void         
832 _item_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
833 {
834 //   Evas_Event_Mouse_Down *ev = event_info;
835 //   Item *it = data;
836 //   _pan_sel(it->obj, it);
837 }
838     
839 static void         
840 _item_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
841 {
842    Evas_Event_Mouse_Up *ev = event_info;
843    Item *it = data;
844
845    if (ev->button == 1)
846      {
847         if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
848           {
849              _pan_hilight(it->obj, it);
850              _pan_sel(it->obj, it);
851              // FIXME: select image!!!
852           }
853      }
854 }
855     
856 static void
857 _pan_file_add(Evas_Object *obj, const char *file, Eina_Bool remote, Eina_Bool theme)
858 {
859    Smart_Data *sd = evas_object_smart_data_get(obj);
860    Item *it = calloc(1, sizeof(Item));
861    Evas *evas;
862
863    if (!it) return;
864    evas = evas_object_evas_get(obj);
865    sd->items = eina_list_append(sd->items, it);
866    it->obj = obj;
867    it->remote = remote;
868    it->theme = theme;
869    it->file = eina_stringshare_add(file);
870    it->frame = edje_object_add(evas);
871    if (it->theme)
872      e_theme_edje_object_set(it->frame, "base/theme/widgets",
873                              "e/conf/wallpaper/main/mini-theme");
874    else if (it->remote)
875      e_theme_edje_object_set(it->frame, "base/theme/widgets",
876                              "e/conf/wallpaper/main/mini-remote");
877    else
878      e_theme_edje_object_set(it->frame, "base/theme/widgets",
879                              "e/conf/wallpaper/main/mini");
880    if (it->hilighted)
881      {
882         edje_object_signal_emit(it->frame, "e,state,selected", "e");
883         evas_object_raise(it->frame);
884      }
885    evas_object_event_callback_add(it->frame, EVAS_CALLBACK_MOUSE_DOWN,
886                                   _item_down, it);
887    evas_object_event_callback_add(it->frame, EVAS_CALLBACK_MOUSE_UP,
888                                   _item_up, it);
889
890    evas_object_smart_member_add(it->frame, obj);
891    evas_object_clip_set(it->frame, evas_object_clip_get(obj));
892    evas_object_show(it->frame);
893    it->image = e_thumb_icon_add(evas);
894    edje_object_part_swallow(it->frame, "e.swallow.content", it->image);
895    evas_object_smart_callback_add(it->image, "e_thumb_gen", _thumb_gen, it);
896    if (it->theme)
897      {
898         const char *f = e_theme_edje_file_get("base/theme/backgrounds",
899                                               "e/desktop/background");
900
901         e_thumb_icon_file_set(it->image, f, "e/desktop/background");
902      }
903    else
904      e_thumb_icon_file_set(it->image, it->file, "e/desktop/background");
905    e_thumb_icon_size_set(it->image, sd->info->iw, sd->info->ih);
906    evas_object_show(it->image);
907
908    e_thumb_icon_begin(it->image);
909    it->do_thumb = 1;
910 //   e_thumb_icon_begin(it->image);
911
912    if (it->theme)
913      {
914         if (sd->info->use_theme_bg)
915           {
916              _pan_hilight(it->obj, it);
917              edje_object_part_text_set(sd->info->bg, "e.text.filename", 
918                                        _("Theme Wallpaper"));
919           }
920      }
921    else
922      {
923         if (sd->info->bg_file)
924           {
925              int match = 0;
926
927              if (!strcmp(sd->info->bg_file, it->file)) match = 1;
928              if (!match)
929                {
930                   const char *p1, *p2;
931
932                   p1 = ecore_file_file_get(sd->info->bg_file);
933                   p2 = ecore_file_file_get(it->file);
934                   if (!strcmp(p1, p2)) match = 1;
935                }
936              if (match)
937                {
938                   char *name = NULL, *p;
939
940                   sd->jump2hi = 1;
941                   _pan_hilight(it->obj, it);
942                   p = strrchr(sd->info->bg_file, '/');
943                   if (p)
944                     {
945                        p++;
946                        name = strdup(p);
947                        p = strrchr(name, '.');
948                        if (p) *p = 0;
949                     }
950                   edje_object_part_text_set(sd->info->bg, "e.text.filename", name);
951                   if (name) free(name);
952                }
953           }
954      }
955    _e_smart_reconfigure(obj);
956 }
957
958 ////////
959
960 static void
961 _resize(E_Win *wn)
962 {
963    Info *info = wn->data;
964
965    evas_object_resize(info->bg, wn->w, wn->h);
966 }
967
968 static void
969 _delete(E_Win *wn __UNUSED__)
970 {
971    wp_conf_hide();
972 }
973
974 static void
975 _bg_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
976 {
977    Info *info = data;
978
979    _pan_sel_up(info->span);
980 }
981
982 static void
983 _ok(void *data, void *data2 __UNUSED__)
984 {
985    Info *info = data;
986
987    if (info->mode == 0)
988      {
989         /* all desktops */
990         while (e_config->desktop_backgrounds)
991           {
992              E_Config_Desktop_Background *cfbg;
993
994              cfbg = e_config->desktop_backgrounds->data;
995              e_bg_del(cfbg->container, cfbg->zone, cfbg->desk_x, cfbg->desk_y);
996           }
997         if ((info->use_theme_bg) || (!info->bg_file))
998           e_bg_default_set(NULL);
999         else
1000           e_bg_default_set(info->bg_file);
1001      }
1002    else if (info->mode == 1)
1003      {
1004         /* specific desk */
1005         e_bg_del(info->con_num, info->zone_num, info->desk_x, info->desk_y);
1006         e_bg_add(info->con_num, info->zone_num, info->desk_x, info->desk_y, 
1007                  info->bg_file);
1008      }
1009    else
1010      {
1011         Eina_List *dlist = NULL, *l;
1012         E_Config_Desktop_Background *cfbg;
1013
1014         /* this screen */
1015         EINA_LIST_FOREACH(e_config->desktop_backgrounds, l, cfbg)
1016           {
1017              if (cfbg->zone == info->zone_num)
1018                dlist = eina_list_append(dlist, cfbg);
1019           }
1020         EINA_LIST_FREE(dlist, cfbg)
1021           e_bg_del(cfbg->container, cfbg->zone, cfbg->desk_x, cfbg->desk_y);
1022         e_bg_add(info->con_num, info->zone_num, -1, -1, info->bg_file);
1023      }
1024    e_bg_update();
1025    e_config_save_queue();
1026    wp_conf_hide();
1027 }
1028
1029 static void
1030 _wp_add(void *data, void *data2 __UNUSED__)
1031 {
1032    Info *info = data;
1033
1034    edje_object_signal_emit(info->bg, "e,action,panel,hide", "e");
1035 }
1036
1037 static void
1038 _wp_delete(void *data, void *data2 __UNUSED__)
1039 {
1040    Info *info = data;
1041
1042    edje_object_signal_emit(info->bg, "e,action,panel,hide", "e");
1043 }
1044
1045 static void
1046 _wp_changed(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1047 {
1048    Info *info = data;
1049
1050    edje_object_signal_emit(info->bg, "e,action,panel,hide", "e");
1051 }
1052
1053 static Eina_Bool
1054 _idler(void *data)
1055 {
1056    struct dirent *dp;
1057    char buf[PATH_MAX];
1058    Info *info = data;
1059
1060    if (!info->dir)
1061      {
1062         info->idler = NULL;
1063         return ECORE_CALLBACK_CANCEL;
1064      }
1065    dp = readdir(info->dir);
1066    if (!dp)
1067      {
1068         free(info->curdir);
1069         info->curdir = NULL;
1070         closedir(info->dir);
1071         info->dir = NULL;
1072         info->idler = NULL;
1073         _scan(info);
1074         return ECORE_CALLBACK_CANCEL;
1075      }
1076    if ((!strcmp(dp->d_name, ".")) || (!strcmp(dp->d_name, "..")))
1077      return ECORE_CALLBACK_RENEW;
1078    if (dp->d_name[0] == '.')
1079      return ECORE_CALLBACK_RENEW;
1080    snprintf(buf, sizeof(buf), "%s/%s", info->curdir, dp->d_name);
1081    if (ecore_file_is_dir(buf))
1082      {
1083         info->dirs = eina_list_append(info->dirs, strdup(buf));
1084         return ECORE_CALLBACK_RENEW;
1085      }
1086    info->scans++;
1087    _pan_file_add(info->span, buf, 0, 0);
1088
1089    e_util_wakeup();
1090    return ECORE_CALLBACK_RENEW;
1091 }
1092
1093 static void
1094 _scan(Info *info)
1095 {
1096    if (info->dirs)
1097      {
1098         if (info->scans <= 0)
1099           {
1100              info->scans = 0;
1101              edje_object_signal_emit(info->bg, "e,state,busy,on", "e");
1102              edje_object_part_text_set(info->bg, "e.text.busy_label", 
1103                                        _("Loading files..."));
1104           }
1105         if (info->curdir) free(info->curdir);
1106         info->curdir = info->dirs->data;
1107         info->dirs = eina_list_remove_list(info->dirs, info->dirs);
1108         if (!info->dir) info->dir = opendir(info->curdir);
1109         info->idler = ecore_idler_add(_idler, info);
1110      }
1111 }
1112
1113 Info *
1114 wp_browser_new(E_Container *con)
1115 {
1116    Info *info;
1117    E_Win *win;
1118    E_Zone *zone;
1119    E_Desk *desk;
1120    const E_Config_Desktop_Background *cfbg;
1121    Evas_Coord mw, mh;
1122    Evas_Object *o, *o2, *ob;
1123    E_Radio_Group *rg;
1124    char buf[PATH_MAX];   
1125
1126    info = calloc(1, sizeof(Info));
1127    if (!info) return NULL;
1128
1129    zone = e_util_zone_current_get(con->manager);
1130    desk = e_desk_current_get(zone);
1131    info->con_num = con->num;
1132    info->zone_num = zone->id;
1133    info->desk_x = desk->x;
1134    info->desk_y = desk->y;
1135    info->mode = 0;
1136    cfbg = e_bg_config_get(con->num, zone->id, desk->x, desk->y);
1137    if (cfbg)
1138      {
1139         if ((cfbg->container >= 0) && (cfbg->zone >= 0))
1140           {
1141              if ((cfbg->desk_x >= 0) && (cfbg->desk_y >= 0))
1142                info->mode = 1;
1143              else
1144                info->mode = 2;
1145           }
1146         info->bg_file = strdup(cfbg->file);
1147      }
1148    if ((!info->bg_file) && (e_config->desktop_default_background))
1149      info->bg_file = strdup(e_config->desktop_default_background);
1150    else
1151      info->use_theme_bg = 1;
1152
1153    info->iw = (120 * e_scale);
1154    info->ih = (zone->h * info->iw) / (zone->w);
1155
1156    win = e_win_new(con);
1157    if (!win)
1158      {
1159         free(info);
1160         info = NULL;
1161         return NULL;
1162      }
1163    info->win = win;
1164    win->data = info;
1165
1166    e_user_dir_concat_static(buf, "backgrounds");
1167    info->dirs = eina_list_append(info->dirs, strdup(buf));
1168    e_prefix_data_concat_static(buf, "data/backgrounds");
1169    info->dirs = eina_list_append(info->dirs, strdup(buf));
1170
1171    e_win_title_set(win, _("Wallpaper Settings"));
1172    e_win_name_class_set(win, "E", "_config::appearance/wallpaper2");
1173    e_win_resize_callback_set(win, _resize);
1174    e_win_delete_callback_set(win, _delete);
1175
1176    // bg + container
1177    info->bg = edje_object_add(info->win->evas);
1178    e_theme_edje_object_set(info->bg, "base/theme/widgets",
1179                            "e/conf/wallpaper/main/window");
1180    edje_object_signal_callback_add(info->bg, "e,action,click", "e",
1181                                    _bg_clicked, info);
1182
1183    // ok button
1184    info->box = e_widget_list_add(info->win->evas, 1, 1);
1185
1186    info->button = e_widget_button_add(info->win->evas, _("OK"), NULL, 
1187                                       _ok, info, NULL);
1188    evas_object_show(info->button);
1189    e_widget_list_object_append(info->box, info->button, 1, 0, 0.5);
1190
1191    e_widget_size_min_get(info->box, &mw, &mh);
1192    edje_extern_object_min_size_set(info->box, mw, mh);
1193    edje_object_part_swallow(info->bg, "e.swallow.buttons", info->box);
1194    evas_object_show(info->box);
1195
1196    // preview
1197    info->preview = e_livethumb_add(info->win->evas);
1198    e_livethumb_vsize_set(info->preview, zone->w, zone->h);
1199    edje_extern_object_aspect_set(info->preview, EDJE_ASPECT_CONTROL_NEITHER, 
1200                                  zone->w, zone->h);
1201    edje_object_part_swallow(info->bg, "e.swallow.preview", info->preview);
1202    evas_object_show(info->preview);
1203
1204    info->mini = edje_object_add(e_livethumb_evas_get(info->preview));
1205    e_livethumb_thumb_set(info->preview, info->mini);
1206    evas_object_show(info->mini);
1207    if (info->bg_file)
1208      edje_object_file_set(info->mini, info->bg_file, "e/desktop/background");
1209    else
1210      {
1211         const char *f = e_theme_edje_file_get("base/theme/backgrounds",
1212                                               "e/desktop/background");
1213
1214         edje_object_file_set(info->mini, f, "e/desktop/background");
1215      }
1216
1217    // scrolled thumbs
1218    info->span = _pan_add(info->win->evas);
1219    _pan_info_set(info->span, info);
1220
1221    // the scrollframe holding the scrolled thumbs
1222    info->sframe = e_scrollframe_add(info->win->evas);
1223    e_scrollframe_custom_theme_set(info->sframe, "base/theme/widgets",
1224                                   "e/conf/wallpaper/main/scrollframe");
1225    e_scrollframe_extern_pan_set(info->sframe, info->span,
1226                                 _pan_set, _pan_get, _pan_max_get, 
1227                                 _pan_child_size_get);
1228    edje_object_part_swallow(info->bg, "e.swallow.list", info->sframe);
1229    evas_object_show(info->sframe);
1230    evas_object_show(info->span);
1231
1232    ob = e_widget_list_add(info->win->evas, 0, 1);
1233
1234    o = e_widget_list_add(info->win->evas, 1, 0);
1235
1236    rg = e_widget_radio_group_new(&(info->mode));
1237    o2 = e_widget_radio_add(info->win->evas, _("All Desktops"), 0, rg);
1238    evas_object_smart_callback_add(o2, "changed", _wp_changed, info);
1239    e_widget_list_object_append(o, o2, 1, 0, 0.5);
1240    e_widget_disabled_set(o2, (e_util_container_desk_count_get(con) < 2));
1241    evas_object_show(o2);
1242
1243    o2 = e_widget_radio_add(info->win->evas, _("This Desktop"), 1, rg);
1244    evas_object_smart_callback_add(o2, "changed", _wp_changed, info);
1245    e_widget_list_object_append(o, o2, 1, 0, 0.5);
1246    evas_object_show(o2);
1247
1248    o2 = e_widget_radio_add(info->win->evas, _("This Screen"), 2, rg);
1249    evas_object_smart_callback_add(o2, "changed", _wp_changed, info);
1250    e_widget_list_object_append(o, o2, 1, 0, 0.5);
1251    if (!(e_util_container_zone_number_get(0, 1) || 
1252          (e_util_container_zone_number_get(1, 0))))
1253      e_widget_disabled_set(o2, EINA_TRUE);
1254    evas_object_show(o2);
1255
1256    e_widget_list_object_append(ob, o, 1, 0, 0.5);
1257    evas_object_show(o);
1258
1259    o = e_widget_list_add(info->win->evas, 1, 0);
1260
1261    o2 =  e_widget_button_add(info->win->evas, _("Add"), NULL, 
1262                              _wp_add, info, NULL);
1263    e_widget_list_object_append(o, o2, 1, 0, 0.5);
1264    evas_object_show(o2);
1265
1266    o2 =  e_widget_button_add(info->win->evas, _("Delete"), NULL, 
1267                              _wp_delete, info, NULL);
1268    e_widget_list_object_append(o, o2, 1, 0, 0.5);
1269    evas_object_show(o2);
1270
1271    e_widget_list_object_append(ob, o, 1, 0, 0.5);
1272    evas_object_show(o);
1273
1274    e_widget_size_min_get(ob, &mw, &mh);
1275    edje_extern_object_min_size_set(ob, mw, mh);
1276    edje_object_part_swallow(info->bg, "e.swallow.extras", ob);
1277    evas_object_show(ob);
1278
1279    // min size calc
1280    edje_object_size_min_calc(info->bg, &mw, &mh);
1281    e_win_size_min_set(win, mw, mh);
1282    if ((zone->w / 4) > mw) mw = (zone->w / 4);
1283    if ((zone->h / 4) > mh) mh = (zone->h / 4);
1284    e_win_resize(win, mw, mh);
1285    e_win_centered_set(win, 1);
1286    e_win_show(win);
1287    e_win_border_icon_set(win, "preferences-desktop-wallpaper");
1288
1289    evas_object_resize(info->bg, info->win->w, info->win->h);
1290    evas_object_show(info->bg);
1291
1292    // add theme bg
1293    _pan_file_add(info->span, NULL, 0, 1);
1294
1295    _scan(info);
1296    return info;
1297 }
1298
1299 void
1300 wp_broser_free(Info *info)
1301 {
1302    char *s;
1303
1304    if (!info) return;
1305    e_object_del(E_OBJECT(info->win));
1306    if (info->dir) closedir(info->dir);
1307    free(info->bg_file);
1308    free(info->curdir);
1309    EINA_LIST_FREE(info->dirs, s) 
1310      free(s);
1311    if (info->idler) ecore_idler_del(info->idler);
1312    // del other stuff
1313    free(info);
1314    info = NULL;
1315 }
1316
1317 E_Config_Dialog *
1318 wp_conf_show(E_Container *con, const char *params __UNUSED__)
1319 {
1320    if (global_info)
1321      {
1322         e_win_show(global_info->win);
1323         e_win_raise(global_info->win);
1324      }
1325    global_info = wp_browser_new(con);
1326
1327    return NULL;
1328 }
1329
1330 void
1331 wp_conf_hide(void)
1332 {
1333    if (global_info)
1334      {
1335         wp_broser_free(global_info);
1336         global_info = NULL;
1337      }
1338 }