okra pushed a commit to branch master.

http://git.enlightenment.org/apps/ephoto.git/commit/?id=e18e24a8a4a8af1af8897d2e7339c8da0959301c

commit e18e24a8a4a8af1af8897d2e7339c8da0959301c
Author: Stephen okra Houston <[email protected]>
Date:   Thu May 26 17:46:43 2016 -0500

    Ephoto: More changes to the edjey overlay style!
    
    Vist the following site for a video and screenshots:
    http://smhouston.us/ephoto-gets-edjey/
---
 data/images/grid.png                       |  Bin 0 -> 563 bytes
 data/images/single.png                     |  Bin 0 -> 539 bytes
 data/themes/crop.edc                       |  437 ----------
 data/themes/ephoto.edc                     |  792 ++++++++++++++++++
 data/themes/{ => images}/sel_border.png    |  Bin
 data/themes/{ => images}/sel_corner1.png   |  Bin
 data/themes/{ => images}/sel_corner3.png   |  Bin
 data/themes/{ => images}/sel_corner5.png   |  Bin
 data/themes/{ => images}/sel_corner7.png   |  Bin
 data/themes/images/shadow.png              |  Bin 0 -> 1263 bytes
 data/themes/images/shadow_circle_horiz.png |  Bin 0 -> 609 bytes
 data/themes/images/shadow_circle_vert.png  |  Bin 0 -> 777 bytes
 data/themes/images/tile.png                |  Bin 0 -> 204 bytes
 src/bin/ephoto_directory_browser.c         | 1200 ++++++++++++++++++++++++++++
 14 files changed, 1992 insertions(+), 437 deletions(-)

diff --git a/data/images/grid.png b/data/images/grid.png
new file mode 100644
index 0000000..4fa3d86
Binary files /dev/null and b/data/images/grid.png differ
diff --git a/data/images/single.png b/data/images/single.png
new file mode 100644
index 0000000..d9f71a0
Binary files /dev/null and b/data/images/single.png differ
diff --git a/data/themes/crop.edc b/data/themes/crop.edc
deleted file mode 100644
index a6bc21d..0000000
--- a/data/themes/crop.edc
+++ /dev/null
@@ -1,437 +0,0 @@
-
-#define FIXED_SIZE(_W, _H) \
-   min: _W _H; max: _W _H;
-
-images {
-   image: "sel_border.png" COMP;
-   image: "sel_corner1.png" COMP;
-   image: "sel_corner3.png" COMP;
-   image: "sel_corner5.png" COMP;
-   image: "sel_corner7.png" COMP;
-}
-
-collections {
-   group { name: "ephoto,image,cropper,base";
-      script {
-         public message(Msg_Type:type, id, ...) {
-            if ((type == MSG_INT_SET) && (id == 1)) {
-               new movetype, cox, coy, pox, poy, ix, iy, iw, ih, cx, cy, cw, 
ch;
-
-               movetype = getarg(2);
-               cox = getarg(3);
-               coy = getarg(4);
- 
-               get_geometry(PART:"ephoto.swallow.image", ix, iy, iw, ih);
-               get_geometry(PART:"ephoto.swallow.cropper", cx, cy, cw, ch);
-               
-               custom_state(PART:"ephoto.swallow.cropper", "default", 0.0);
-               if (movetype == 0) {
-                  new ppox, ppoy;
-                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
-                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
-                  if (cx+cox < ix)
-                    cox = ix-cx;
-                  if (cx+cw+cox > ix+iw)
-                    cox = (ix+iw)-(cx+cw);
-                  if (cy+coy < iy)
-                    coy = iy-cy;
-                  if (cy+ch+coy > iy+ih)
-                    coy = (iy+ih)-(cy+ch);
-                  pox += cox;
-                  poy += coy;
-                  ppox += cox;
-                  ppoy += coy;
-                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
-                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
-               }
-               if (movetype == 1 || movetype == 2 || movetype == 8) {
-                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
-                  if (cx+cox < ix)
-                    cox = ix-cx;
-                  if (cy+coy < iy)
-                    coy = iy-cy;
-                  if (cw-cox < 20)
-                     return;
-                  if (ch-coy < 20)
-                     return;
-                  cox += pox;
-                  coy += poy;
-                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, cox, coy);
-               }
-               if (movetype == 3) {
-                  new ppox, ppoy;
-                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
-                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
-                  if (cx+cw+cox > ix+iw)
-                    cox = (ix+iw)-(cx+cw);
-                  if (cy+coy < iy)
-                    coy = iy-cy;
-                  if (cw+cox < 20)
-                     return;
-                  if (ch-coy < 20)
-                     return;
-                  poy += coy;
-                  ppox += cox;
-                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
-                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
-               }
-               if (movetype == 4 || movetype == 5 || movetype == 6) {
-                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, pox, poy);
-                  if (cx+cw+cox > ix+iw)
-                    cox = (ix+iw)-(cx+cw);
-                  if (cy+ch+coy > iy+ih)
-                    coy = (iy+ih)-(cy+ch);
-                  if (cw+cox < 20)
-                     return;
-                  if (ch+coy < 20)
-                     return;
-                  cox += pox;
-                  coy += poy;
-                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, cox, coy);
-               }
-               if (movetype == 7) {
-                  new ppox, ppoy;
-                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
-                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
-                  if (cx+cox < ix)
-                    cox = ix-cx;
-                  if (cy+ch+coy > iy+ih)
-                    coy = (iy+ih)-(cy+ch);
-                  if (cw-cox < 20)
-                     return;
-                  if (ch+coy < 20)
-                     return;
-                  pox += cox;
-                  ppoy += coy;
-                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
-                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
-               }
-               if (movetype == 9) {
-                  new ppox, ppoy;
-                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
-                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
-                  if (cx < ix)
-                    cox = ix-cx;
-                  if (cx+cw > ix+iw)
-                    cox = (ix+iw)-(cx+cw);
-                  if (cy < iy)
-                    coy = iy-cy;
-                  if (cy+ch > iy+ih)
-                    coy = (iy+ih)-(cy+ch);
-                  pox += cox;
-                  ppox += cox;
-                  poy += coy;
-                  ppoy += coy;
-                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
-                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
-               }
-               if (movetype == 10) {
-                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, 0, 0);
-                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, 0, 0);
-               }
-               if (movetype == 11) {
-                  new buf[32];
-                  snprintf(buf, sizeof(buf), "%dx%d", cox, coy);
-                  set_text(PART:"ephoto.cropper.size", buf);
-               }
-               set_state(PART:"ephoto.swallow.cropper", "custom", 0.0);
-               if (movetype != 0) {
-                 emit("cropper,changed", "ephoto.swallow.cropper");
-               }
-            }
-         }
-      }
-      parts {
-         part { name: "clipper";
-            type: RECT;
-            description { state: "default" 0.0;
-            }
-         }
-         part { name: "ephoto.swallow.image";
-            type: SWALLOW;
-            scale: 1;
-            mouse_events: 0;
-            clip_to: "clipper";
-            description { state: "default" 0.0;
-            }
-         }
-         part { name: "ephoto.swallow.cropper";
-            type: SWALLOW;
-            scale: 1;
-            mouse_events: 1;
-            clip_to: "clipper";
-            description { state: "default" 0.0;
-               min: 20 20;
-               rel1.to: "ephoto.swallow.image";
-               rel1.relative: 0.2 0.2;
-               rel2.to: "ephoto.swallow.image";
-               rel2.relative: 0.8 0.8;
-            }
-         }
-         part { name: "ephoto.cropper.size";
-            type: TEXT;
-            effect: GLOW;
-            scale: 1;
-            mouse_events: 0;
-            clip_to: "clipper";
-            description { state: "default" 0.0;
-               color: 255 255 255 255;
-               rel1.to: "ephoto.swallow.cropper";
-               rel2.to: "ephoto.swallow.cropper";
-               text {
-                  text: "";
-                  font: FN;
-                  size: 12;
-                  align: 0.5 1.0;
-               }
-            }
-         }
-         part { name: "shader_top";
-            type: RECT;
-            scale: 1;
-            mouse_events: 0;
-            clip_to: "clipper";
-            description { state: "default" 0.0;
-               color: 0 0 0 150;
-               rel1.to: "clipper";
-               rel1.relative: 0.0 0.0;
-               rel2.to: "ephoto.swallow.cropper";
-               rel2.relative: 1.0 0.0;
-            }
-         }
-         part { name: "shader_left";
-            type: RECT;
-            scale: 1;
-            mouse_events: 0;
-            clip_to: "clipper";
-            description { state: "default" 0.0;
-               color: 0 0 0 150;
-               rel1.to: "shader_top";
-               rel1.relative: 0.0 1.0;
-               rel2.to: "ephoto.swallow.cropper";
-               rel2.relative: 0.0 1.0;
-            }
-         }
-         part { name: "shader_bottom";
-            type: RECT;
-            scale: 1;
-            mouse_events: 0;
-            clip_to: "clipper";
-            description { state: "default" 0.0;
-               color: 0 0 0 150;
-               rel1.to: "shader_left";
-               rel1.relative: 0.0 1.0;
-               rel2.to: "clipper";
-               rel2.relative: 1.0 1.0;
-            }
-         }
-         part { name: "shader_right";
-            type: RECT;
-            scale: 1;
-            mouse_events: 0;
-            clip_to: "clipper";
-            description { state: "default" 0.0;
-               color: 0 0 0 150;
-               rel1.to: "shader_top";
-               rel1.relative: 1.0 0.0;
-               rel2.to: "shader_bottom";
-               rel2.relative: 1.0 0.0;
-            }
-         }
-      }
-   }
-   group { name: "ephoto,image,cropper";
-      parts {
-         part { name: "cropper"; type: IMAGE;
-            repeat_events: 1;
-            description { state: "default" 0.0;
-               color: 255 255 255 200;
-               image {
-                  normal: "sel_border.png";
-                  border: 3 3 3 3;
-                  middle: NONE;
-               }
-            }
-            part { name: "dragger"; type: RECT;
-               repeat_events: 1;
-               description { state: "default" 0.0;
-                  color: 255 255 255 0;
-                  rel1 {
-                     to: "handle1";
-                     relative: 1.0 1.0;
-                  }
-                  rel2 {
-                     to: "handle5";
-                     relative: 0.0 0.0;
-                  }
-               }
-            }
-            part { name: "handle1"; type: IMAGE;
-               repeat_events: 1;
-               description { state: "default" 0.0;
-                  FIXED_SIZE(22, 22)
-                  rel1.offset: 1 1;
-                  align: 0.0 0.0;
-                  color: 255 255 255 0;
-                  image.normal: "sel_corner1.png";
-               }
-               description { state: "visible" 0.0;
-                  inherit: "default" 0.0;
-                  color: 255 255 255 200;
-               }
-            }
-            part { name: "handle2"; type: RECT;
-               repeat_events: 1;
-               description { state: "default" 0.0;
-                  color: 255 255 255 0;
-                  rel1 {
-                     to: "handle1";
-                     relative: 1.0 0.0;
-                     offset: 3 2;
-                  }
-                  rel2 {
-                     to: "handle3";
-                     relative: 0.0 1.0;
-                     offset: -4 -2;
-                  }
-               }
-               description { state: "visible" 0.0;
-                  inherit: "default" 0.0;
-                  color: 255 255 255 80;
-               }
-            }
-            part { name: "handle3"; type: IMAGE;
-               repeat_events: 1;
-               description { state: "default" 0.0;
-                  FIXED_SIZE(22, 22)
-                  rel1.offset: 0 1;
-                  rel2.offset: -2 -1;
-                  align: 1.0 0.0;
-                  color: 255 255 255 0;
-                  image.normal: "sel_corner3.png";
-               }
-               description { state: "visible" 0.0;
-                  inherit: "default" 0.0;
-                  color: 255 255 255 200;
-               }
-            }
-            part { name: "handle4"; type: RECT;
-               repeat_events: 1;
-               description { state: "default" 0.0;
-                  color: 255 255 255 0;
-                  rel1 {
-                     to: "handle3";
-                     relative: 0.0 1.0;
-                     offset: 1 3;
-                  }
-                  rel2 {
-                     to: "handle5";
-                     relative: 1.0 0.0;
-                     offset: -3 -4;
-                  }
-               }
-               description { state: "visible" 0.0;
-                  inherit: "default" 0.0;
-                  color: 255 255 255 80;
-               }
-            }
-            part { name: "handle5"; type: IMAGE;
-               repeat_events: 1;
-               description { state: "default" 0.0;
-                  FIXED_SIZE(22, 22)
-                  rel2.offset: -2 -2;
-                  align: 1.0 1.0;
-                  color: 255 255 255 0;
-                  image.normal: "sel_corner5.png";
-               }
-               description { state: "visible" 0.0;
-                  inherit: "default" 0.0;
-                  color: 255 255 255 200;
-               }
-            }
-            part { name: "handle6"; type: RECT;
-               repeat_events: 1;
-               description { state: "default" 0.0;
-                  rel1 {
-                     to: "handle7";
-                     relative: 1.0 0.0;
-                     offset: 3 1;
-                  }
-                  rel2 {
-                     to: "handle5";
-                     relative: 0.0 1.0;
-                     offset: -4 -3;
-                  }
-                  color: 255 255 255 0;
-               }
-               description { state: "visible" 0.0;
-                  inherit: "default" 0.0;
-                  color: 255 255 255 80;
-               }
-            }
-            part { name: "handle7"; type: IMAGE;
-               repeat_events: 1;
-               description { state: "default" 0.0;
-                  FIXED_SIZE(22, 22)
-                  rel1.offset: 1 0;
-                  rel2.offset: -1 -2;
-                  align: 0.0 1.0;
-                  color: 255 255 255 0;
-                  image.normal: "sel_corner7.png";
-               }
-               description { state: "visible" 0.0;
-                  inherit: "default" 0.0;
-                  color: 255 255 255 200;
-               }
-            }
-            part { name: "handle8"; type: RECT;
-               repeat_events: 1;
-               description { state: "default" 0.0;
-                  rel1 {
-                     to: "handle1";
-                     relative: 0.0 1.0;
-                     offset: 2 3;
-                  }
-                  rel2 {
-                     to: "handle7";
-                     relative: 1.0 0.0;
-                     offset: -2 -4;
-                  }
-                  color: 255 255 255 0;
-               }
-               description { state: "visible" 0.0;
-                  inherit: "default" 0.0;
-                  color: 255 255 255 80;
-               }
-            }
-            program {
-               signal: "mouse,in"; source: "cropper";
-               action: STATE_SET "visible" 0.0;
-               transition: LINEAR 0.3 ;
-               targets: "handle1" "handle3" "handle5" "handle7";
-            }
-            program {
-               signal: "mouse,out"; source: "cropper";
-               action: STATE_SET "default" 0.0;
-               transition: LINEAR 0.3 ;
-               targets: "handle1" "handle3" "handle5" "handle7";
-            }
-#define SHOW_HIDE_LATERALS(_NAME_)                 \
-            program { signal: "mouse,in"; source: _NAME_;   \
-                      action: STATE_SET "visible" 0.0;      \
-                      transition: LINEAR 0.3 ;       \
-                      target: _NAME_; }                     \
-            program { signal: "mouse,out"; source: _NAME_;  \
-                      action: STATE_SET "default" 0.0;      \
-                      transition: LINEAR 0.3 ;       \
-                      target: _NAME_; }
-            SHOW_HIDE_LATERALS("handle2")
-            SHOW_HIDE_LATERALS("handle4")
-            SHOW_HIDE_LATERALS("handle6")
-            SHOW_HIDE_LATERALS("handle8")
-#undef SHOW_HIDE_LATERALS
-         }
-      }
-   }
-}
-
diff --git a/data/themes/ephoto.edc b/data/themes/ephoto.edc
new file mode 100644
index 0000000..a03af5e
--- /dev/null
+++ b/data/themes/ephoto.edc
@@ -0,0 +1,792 @@
+#define FIXED_SIZE(_W, _H) \
+   min: _W _H; max: _W _H;
+
+collections {
+   images {
+      image: "images/shadow_circle_horiz.png" COMP;
+      image: "images/shadow_circle_vert.png" COMP;
+      image: "images/tile.png" COMP;
+      image: "images/shadow.png" COMP;
+      image: "images/sel_border.png" COMP;
+      image: "images/sel_corner1.png" COMP;
+      image: "images/sel_corner3.png" COMP;
+      image: "images/sel_corner5.png" COMP;
+      image: "images/sel_corner7.png" COMP;
+   }
+   group { name: "ephoto,main,layout";
+      script {
+         public offseth = 0;
+         public offsetv = 0;
+         public custom = 0 ;
+         public custom_folders = 0;
+         public message(Msg_Type:type, id, ...) {
+            if ((type == MSG_INT_SET) && (id == 1)) {
+               new hoffset = getarg(2);
+               new voffset = getarg(3);
+               new hoff, voff, roneoff;
+
+               set_int(custom, 1);
+               hoffset *= -1;
+               voffset *= -1;
+
+               get_state_val(PART:"ephoto.swallow.controls", STATE_REL1_OFFSET,
+                   0, roneoff);
+               get_state_val(PART:"ephoto.swallow.controls", STATE_REL2_OFFSET,
+                   hoff, voff);
+
+               roneoff -= get_int(offsetv);
+               roneoff += voffset;
+               hoff -= get_int(offseth);
+               voff -= get_int(offsetv);
+               hoff += hoffset;
+               voff += voffset;
+               set_int(offseth, hoffset);
+               set_int(offsetv, voffset);
+
+               custom_state(PART:"ephoto.swallow.controls", "default", 0.0);
+               set_state_val(PART:"ephoto.swallow.controls", STATE_REL1_OFFSET,
+                   0, roneoff);
+               set_state_val(PART:"ephoto.swallow.controls", STATE_REL2_OFFSET,
+                   hoff, voff);
+               set_state(PART:"ephoto.swallow.controls", "custom", 0.0);
+            }
+            if ((type == MSG_INT_SET) && (id == 2)) {
+               new minw = getarg(2);
+               set_int(custom_folders, 1);
+               custom_state(PART:"ephoto.swallow.folders", "visible", 0.0);
+               set_state_val(PART:"ephoto.swallow.folders",
+                   STATE_MIN, minw, 0);
+            }
+         }
+      }
+      parts {
+         rect { name: "ephoto,main,clip";
+            scale: 1;
+            description { state: "default" 0.0;
+            }
+         }
+         image { name: "background_tile";
+            scale: 1;
+            clip_to: "ephoto,main,clip";
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               image.normal: "images/tile.png";
+               color: 210 210 210 255;
+               fill {
+                  size.relative: 0.0 0.0;
+                  size.offset: 32 32;
+               }     
+            }
+         }
+         swallow { name: "ephoto.swallow.main";
+            scale: 1;
+            mouse_events: 1;
+            clip_to: "ephoto,main,clip";
+            description { state: "default" 0.0;
+               rel2.to: "ephoto,editor";
+               rel2.relative: 0.0 1.0; 
+            }
+         }
+         rect { name: "ephoto,editor";
+            scale: 1;
+            clip_to: "ephoto,main,clip";
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               rel1.to: "ephoto.swallow.editor";
+               rel2.to: "ephoto.swallow.editor";
+               visible: 0;
+            }
+            description { state: "visible" 0.0;
+               inherit: default 0.0;
+               visible: 1;
+            }
+         }
+         image { name: "editor_shadow";
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               image.normal: "images/shadow_circle_vert.png";
+               min: 32 0;
+               color: 255 255 255 0;
+               visible: 0;
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               fixed: 1 1;
+               rel1.to: "ephoto,editor";
+               rel1.relative: 1.0 0.0;
+               rel2.to: "ephoto,editor";
+               color: 255 255 255 128;
+               visible: 1;
+            }
+         }
+         rect { name: "editor_base";
+            clip_to: "ephoto,editor";
+            scale: 1;
+            description { state: "default" 0.0;
+               color: 15 15 15 150;
+               rel1.to: "ephoto,editor";
+               rel2.to: "ephoto,editor";
+            }
+         }
+         swallow { name: "ephoto.swallow.editor";
+            scale: 1;
+            mouse_events: 1;
+            clip_to: "ephoto,editor";
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               rel1.to: "ephoto,main,clip";
+               rel1.relative: 1.0 0.0;
+               rel2.to: "ephoto,main,clip";
+               rel2.relative: 1.0 1.0;
+               visible: 0;
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               rel1.to: "ephoto,main,clip";
+               rel1.relative: 1.0 0.0;
+               rel2.to: "ephoto,main,clip";
+               rel2.relative: 1.0 1.0;
+               align: 1.0 0.0;
+               visible: 1;
+            }
+         }
+         rect { name: "ephoto,folders";
+            clip_to: "ephoto,main,clip";
+            scale: 1;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               min: 220 0;
+               rel1.to: "ephoto.swallow.folders";
+               rel2.to: "ephoto.swallow.folders";
+               visible: 0;
+            }
+            description { state: "visible" 0.0;
+               inherit: default 0.0;
+               rel1.to: "ephoto.swallow.folders";
+               rel2.to: "ephoto.swallow.folders";
+               visible: 1;
+            }
+         }
+         image { name: "folders_shadow";
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               image.normal: "images/shadow_circle_vert.png";
+               min: 32 0;
+               color: 255 255 255 0;
+               visible: 0;
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               fixed: 1 1;
+               rel1.to: "ephoto,folders";
+               rel1.relative: 1.0 0.0;
+               rel2.to: "ephoto,folders";
+               color: 255 255 255 128;
+               visible: 1;
+            }
+         }
+         rect { name: "folders_base";
+            clip_to: "ephoto,folders";
+            scale: 1;
+            description { state: "default" 0.0;
+               color: 15 15 15 150;
+               rel1.to: "ephoto,folders";
+               rel2.to: "ephoto,folders";
+            }
+         }
+         swallow { name: "ephoto.swallow.folders";
+            scale: 1;
+            mouse_events: 1;
+            clip_to: "ephoto,folders";
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               rel1.to: "ephoto,controls";
+               rel1.relative: 0.0 0.0;
+               rel2.to: "ephoto,controls";
+               rel2.relative: 0.0 0.0;
+               visible: 0;
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               rel1.to: "ephoto.swallow.main";
+               rel1.relative: 0.0 0.0;
+               rel2.to: "ephoto,controls";
+               rel2.relative: 0.0 0.0;
+               align: 0.0 0.0;
+               visible: 1;
+            }
+         }
+         rect { name: "ephoto,controls";
+            scale: 1;
+            clip_to: "ephoto,main,clip";
+            description { state: "default" 0.0;
+               fixed: 0 1;
+               rel1.to: "ephoto.swallow.controls";
+               rel2.to: "ephoto.swallow.controls";
+               color: 255 255 255 255;
+               visible: 1;
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 0;
+               visible: 0;
+            }
+         }
+         rect { name: "controls_base";
+            clip_to: "ephoto,controls";
+            scale: 1;
+            description { state: "default" 0.0;
+               color: 15 15 15 150;
+               rel1.to: "ephoto,controls";
+               rel2.to: "ephoto,controls";
+            }
+         }
+         image { name: "controls_shadow";
+            mouse_events: 0;
+            scale: 1;
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               rel1.to: "controls_base";
+               rel1.relative: 0.0 0.0;
+               rel2.to: "controls_base";
+               rel2.relative: 1.0 0.0;
+               image.normal: "images/shadow_circle_horiz.png";
+               min: 0 32;
+               color: 255 255 255 128;
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 0;
+               visible: 0;
+            }
+         }
+         swallow { name: "ephoto.swallow.controls";
+            scale: 1;
+            mouse_events: 1;
+            clip_to: "ephoto,controls";
+            description { state: "default" 0.0;
+               fixed: 1 1;
+               rel1.to: "ephoto.swallow.main";
+               rel2.to: "ephoto.swallow.main";
+               rel1.relative: 0.0 1.0;
+               rel1.offset: 0 -1;
+               rel2.offset: 0 -1;
+               align: 0.5 1.0;
+               color: 255 255 255 255;
+               visible: 1;
+            }
+            description { state: "hidden" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 0;
+               rel1.to: "ephoto.swallow.main";
+               rel1.relative: 0.0 1.0;
+               rel2.to: "ephoto.swallow.main";
+               rel2.relative: 1.0 2.0;
+               visible: 0;
+            }
+         }
+      }
+      programs {
+         program { signal: "ephoto,editor,hide";
+            source: "ephoto";
+            action: STATE_SET "default" 0.0;
+            target: "ephoto.swallow.editor";
+            target: "editor_shadow";
+            target: "ephoto,editor";
+         }
+         program { signal: "ephoto,editor,show";
+            source: "ephoto";
+            action: STATE_SET "visible" 0.0;
+            target: "ephoto.swallow.editor";
+            target: "editor_shadow";
+            target: "ephoto,editor";
+         }
+         program { signal: "ephoto,folders,hide";
+            source: "ephoto";
+            action: STATE_SET "default" 0.0;
+            target: "ephoto.swallow.folders";
+            target: "folders_shadow";
+            target: "ephoto,folders";
+         }
+         program { signal: "ephoto,folders,show";
+            source: "ephoto";
+            script {
+               if (get_int(custom_folders)) {
+                  set_state(PART:"ephoto.swallow.folders", "custom", 0.0);
+               }
+               else {
+                  set_state(PART:"ephoto.swallow.folders", "visible", 0.0);
+               }
+               set_state(PART:"folders_shadow", "visible", 0.0);
+               set_state(PART:"ephoto,folders", "visible", 0.0);
+            }
+         }
+         program { signal: "ephoto,controls,hide";
+            source: "ephoto";
+            action: STATE_SET "hidden" 0.0;
+            target: "ephoto.swallow.controls";
+            target: "controls_shadow";
+            target: "ephoto,controls";
+         }
+         program { signal: "ephoto,controls,show";
+            source: "ephoto";
+            script {
+               if (get_int(custom)) {
+                  set_state(PART:"ephoto.swallow.controls", "custom", 0.0);
+               }
+               else {
+                  set_state(PART:"ephoto.swallow.controls", "default", 0.0);
+               }
+               set_state(PART:"controls_shadow", "default", 0.0);
+               set_state(PART:"ephoto,controls", "default", 0.0);
+            }
+         }
+      }
+   }
+   group { "elm/label/base/info";
+      mouse_events: 0;
+      styles {
+         style { name: "info_style";
+            base: "font=Sans font_size=10 align=center valign=0.5 
color=#ffffff style=glow glow_color=#151515 glow_color2=#000000 wrap=mixed 
text_class=info color_class=text";
+         }
+      }
+      parts {
+         textblock { "elm.text";
+            scale: 1;
+            desc {
+               text {
+                  style: "info_style";
+                  min: 1 1;
+                  ellipsis: -1;
+               }
+            }
+         }
+      }
+   }
+   group { name: "ephoto,image,cropper,base";
+      script {
+         public message(Msg_Type:type, id, ...) {
+            if ((type == MSG_INT_SET) && (id == 1)) {
+               new movetype, cox, coy, pox, poy, ix, iy, iw, ih, cx, cy, cw, 
ch;
+
+               movetype = getarg(2);
+               cox = getarg(3);
+               coy = getarg(4);
+ 
+               get_geometry(PART:"ephoto.swallow.image", ix, iy, iw, ih);
+               get_geometry(PART:"ephoto.swallow.cropper", cx, cy, cw, ch);
+               
+               custom_state(PART:"ephoto.swallow.cropper", "default", 0.0);
+               if (movetype == 0) {
+                  new ppox, ppoy;
+                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
+                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
+                  if (cx+cox < ix)
+                    cox = ix-cx;
+                  if (cx+cw+cox > ix+iw)
+                    cox = (ix+iw)-(cx+cw);
+                  if (cy+coy < iy)
+                    coy = iy-cy;
+                  if (cy+ch+coy > iy+ih)
+                    coy = (iy+ih)-(cy+ch);
+                  pox += cox;
+                  poy += coy;
+                  ppox += cox;
+                  ppoy += coy;
+                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
+                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
+               }
+               if (movetype == 1 || movetype == 2 || movetype == 8) {
+                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
+                  if (cx+cox < ix)
+                    cox = ix-cx;
+                  if (cy+coy < iy)
+                    coy = iy-cy;
+                  if (cw-cox < 20)
+                     return;
+                  if (ch-coy < 20)
+                     return;
+                  cox += pox;
+                  coy += poy;
+                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, cox, coy);
+               }
+               if (movetype == 3) {
+                  new ppox, ppoy;
+                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
+                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
+                  if (cx+cw+cox > ix+iw)
+                    cox = (ix+iw)-(cx+cw);
+                  if (cy+coy < iy)
+                    coy = iy-cy;
+                  if (cw+cox < 20)
+                     return;
+                  if (ch-coy < 20)
+                     return;
+                  poy += coy;
+                  ppox += cox;
+                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
+                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
+               }
+               if (movetype == 4 || movetype == 5 || movetype == 6) {
+                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, pox, poy);
+                  if (cx+cw+cox > ix+iw)
+                    cox = (ix+iw)-(cx+cw);
+                  if (cy+ch+coy > iy+ih)
+                    coy = (iy+ih)-(cy+ch);
+                  if (cw+cox < 20)
+                     return;
+                  if (ch+coy < 20)
+                     return;
+                  cox += pox;
+                  coy += poy;
+                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, cox, coy);
+               }
+               if (movetype == 7) {
+                  new ppox, ppoy;
+                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
+                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
+                  if (cx+cox < ix)
+                    cox = ix-cx;
+                  if (cy+ch+coy > iy+ih)
+                    coy = (iy+ih)-(cy+ch);
+                  if (cw-cox < 20)
+                     return;
+                  if (ch+coy < 20)
+                     return;
+                  pox += cox;
+                  ppoy += coy;
+                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
+                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
+               }
+               if (movetype == 9) {
+                  new ppox, ppoy;
+                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
+                  get_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
+                  if (cx < ix)
+                    cox = ix-cx;
+                  if (cx+cw > ix+iw)
+                    cox = (ix+iw)-(cx+cw);
+                  if (cy < iy)
+                    coy = iy-cy;
+                  if (cy+ch > iy+ih)
+                    coy = (iy+ih)-(cy+ch);
+                  pox += cox;
+                  ppox += cox;
+                  poy += coy;
+                  ppoy += coy;
+                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, pox, poy);
+                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, ppox, ppoy);
+               }
+               if (movetype == 10) {
+                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL1_OFFSET, 0, 0);
+                  set_state_val(PART:"ephoto.swallow.cropper", 
STATE_REL2_OFFSET, 0, 0);
+               }
+               if (movetype == 11) {
+                  new buf[32];
+                  snprintf(buf, sizeof(buf), "%dx%d", cox, coy);
+                  set_text(PART:"ephoto.cropper.size", buf);
+               }
+               set_state(PART:"ephoto.swallow.cropper", "custom", 0.0);
+               if (movetype != 0) {
+                 emit("cropper,changed", "ephoto.swallow.cropper");
+               }
+            }
+         }
+      }
+      parts {
+         rect { name: "clipper";
+            description { state: "default" 0.0;
+            }
+         }
+         swallow { name: "ephoto.swallow.image";
+            scale: 1;
+            mouse_events: 0;
+            clip_to: "clipper";
+            description { state: "default" 0.0;
+            }
+         }
+         swallow { name: "ephoto.swallow.cropper";
+            scale: 1;
+            mouse_events: 1;
+            clip_to: "clipper";
+            description { state: "default" 0.0;
+               min: 20 20;
+               rel1.to: "ephoto.swallow.image";
+               rel1.relative: 0.2 0.2;
+               rel2.to: "ephoto.swallow.image";
+               rel2.relative: 0.8 0.8;
+            }
+         }
+         text { name: "ephoto.cropper.size";
+            effect: GLOW;
+            scale: 1;
+            mouse_events: 0;
+            clip_to: "clipper";
+            description { state: "default" 0.0;
+               color: 255 255 255 255;
+               rel1.to: "ephoto.swallow.cropper";
+               rel2.to: "ephoto.swallow.cropper";
+               text {
+                  text: "";
+                  font: FN;
+                  size: 12;
+                  align: 0.5 1.0;
+               }
+            }
+         }
+         rect { name: "shader_top";
+            scale: 1;
+            mouse_events: 0;
+            clip_to: "clipper";
+            description { state: "default" 0.0;
+               color: 0 0 0 150;
+               rel1.to: "clipper";
+               rel1.relative: 0.0 0.0;
+               rel2.to: "ephoto.swallow.cropper";
+               rel2.relative: 1.0 0.0;
+            }
+         }
+         rect { name: "shader_left";
+
+            scale: 1;
+            mouse_events: 0;
+            clip_to: "clipper";
+            description { state: "default" 0.0;
+               color: 0 0 0 150;
+               rel1.to: "shader_top";
+               rel1.relative: 0.0 1.0;
+               rel2.to: "ephoto.swallow.cropper";
+               rel2.relative: 0.0 1.0;
+            }
+         }
+         rect { name: "shader_bottom";
+            scale: 1;
+            mouse_events: 0;
+            clip_to: "clipper";
+            description { state: "default" 0.0;
+               color: 0 0 0 150;
+               rel1.to: "shader_left";
+               rel1.relative: 0.0 1.0;
+               rel2.to: "clipper";
+               rel2.relative: 1.0 1.0;
+            }
+         }
+         rect { name: "shader_right";
+            scale: 1;
+            mouse_events: 0;
+            clip_to: "clipper";
+            description { state: "default" 0.0;
+               color: 0 0 0 150;
+               rel1.to: "shader_top";
+               rel1.relative: 1.0 0.0;
+               rel2.to: "shader_bottom";
+               rel2.relative: 1.0 0.0;
+            }
+         }
+      }
+   }
+   group { name: "ephoto,image,cropper";
+      parts {
+         image { name: "cropper";
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 255 255 255 200;
+               image {
+                  normal: "images/sel_border.png";
+                  border: 3 3 3 3;
+                  middle: NONE;
+               }
+            }
+         }
+         rect { name: "dragger";
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+               rel1 {
+                  to: "handle1";
+                  relative: 1.0 1.0;
+               }
+               rel2 {
+                  to: "handle5";
+                  relative: 0.0 0.0;
+               }
+            }
+         }
+         image { name: "handle1";
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               FIXED_SIZE(22, 22)
+               rel1.offset: 1 1;
+               align: 0.0 0.0;
+               color: 255 255 255 0;
+               image.normal: "images/sel_corner1.png";
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 200;
+            }
+         }
+         rect { name: "handle2";
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+               rel1 {
+                  to: "handle1";
+                  relative: 1.0 0.0;
+                  offset: 3 2;
+               }
+               rel2 {
+                  to: "handle3";
+                  relative: 0.0 1.0;
+                  offset: -4 -2;
+               }
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 80;
+            }
+         }
+         image { name: "handle3";
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               FIXED_SIZE(22, 22)
+               rel1.offset: 0 1;
+               rel2.offset: -2 -1;
+               align: 1.0 0.0;
+               color: 255 255 255 0;
+               image.normal: "images/sel_corner3.png";
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 200;
+            }
+         }
+         rect { name: "handle4";
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               color: 255 255 255 0;
+               rel1 {
+                  to: "handle3";
+                  relative: 0.0 1.0;
+                  offset: 1 3;
+               }
+               rel2 {
+                  to: "handle5";
+                  relative: 1.0 0.0;
+                  offset: -3 -4;
+               }
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 80;
+            }
+         }
+         image { name: "handle5";
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               FIXED_SIZE(22, 22)
+               rel2.offset: -2 -2;
+               align: 1.0 1.0;
+               color: 255 255 255 0;
+               image.normal: "images/sel_corner5.png";
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 200;
+            }
+         }
+         rect { name: "handle6";
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               rel1 {
+                  to: "handle7";
+                  relative: 1.0 0.0;
+                  offset: 3 1;
+               }
+               rel2 {
+                  to: "handle5";
+                  relative: 0.0 1.0;
+                  offset: -4 -3;
+               }
+               color: 255 255 255 0;
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 80;
+            }
+         }
+         image { name: "handle7";
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               FIXED_SIZE(22, 22)
+               rel1.offset: 1 0;
+               rel2.offset: -1 -2;
+               align: 0.0 1.0;
+               color: 255 255 255 0;
+               image.normal: "images/sel_corner7.png";
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 200;
+            }
+         }
+         rect { name: "handle8";
+            repeat_events: 1;
+            description { state: "default" 0.0;
+               rel1 {
+                  to: "handle1";
+                  relative: 0.0 1.0;
+                  offset: 2 3;
+               }
+               rel2 {
+                  to: "handle7";
+                  relative: 1.0 0.0;
+                  offset: -2 -4;
+               }
+               color: 255 255 255 0;
+            }
+            description { state: "visible" 0.0;
+               inherit: "default" 0.0;
+               color: 255 255 255 80;
+            }
+         }
+      }
+      programs {
+         program {
+            signal: "mouse,in"; source: "cropper";
+            action: STATE_SET "visible" 0.0;
+            transition: LINEAR 0.3 ;
+            targets: "handle1" "handle3" "handle5" "handle7";
+         }
+         program {
+            signal: "mouse,out"; source: "cropper";
+            action: STATE_SET "default" 0.0;
+            transition: LINEAR 0.3 ;
+            targets: "handle1" "handle3" "handle5" "handle7";
+         }
+#define SHOW_HIDE_LATERALS(_NAME_)                 \
+         program {        \
+            signal: "mouse,in"; source: _NAME_;   \
+             action: STATE_SET "visible" 0.0;      \
+             transition: LINEAR 0.3 ;       \
+             target: _NAME_;                \
+         }        \
+         program {        \
+            signal: "mouse,out"; source: _NAME_;  \
+            action: STATE_SET "default" 0.0;      \
+            transition: LINEAR 0.3 ;       \
+            target: _NAME_;                \
+         }
+         SHOW_HIDE_LATERALS("handle2")
+         SHOW_HIDE_LATERALS("handle4")
+         SHOW_HIDE_LATERALS("handle6")
+         SHOW_HIDE_LATERALS("handle8")
+#undef SHOW_HIDE_LATERALS
+      }
+   }
+}
+
diff --git a/data/themes/sel_border.png b/data/themes/images/sel_border.png
similarity index 100%
rename from data/themes/sel_border.png
rename to data/themes/images/sel_border.png
diff --git a/data/themes/sel_corner1.png b/data/themes/images/sel_corner1.png
similarity index 100%
rename from data/themes/sel_corner1.png
rename to data/themes/images/sel_corner1.png
diff --git a/data/themes/sel_corner3.png b/data/themes/images/sel_corner3.png
similarity index 100%
rename from data/themes/sel_corner3.png
rename to data/themes/images/sel_corner3.png
diff --git a/data/themes/sel_corner5.png b/data/themes/images/sel_corner5.png
similarity index 100%
rename from data/themes/sel_corner5.png
rename to data/themes/images/sel_corner5.png
diff --git a/data/themes/sel_corner7.png b/data/themes/images/sel_corner7.png
similarity index 100%
rename from data/themes/sel_corner7.png
rename to data/themes/images/sel_corner7.png
diff --git a/data/themes/images/shadow.png b/data/themes/images/shadow.png
new file mode 100644
index 0000000..9d1e0a6
Binary files /dev/null and b/data/themes/images/shadow.png differ
diff --git a/data/themes/images/shadow_circle_horiz.png 
b/data/themes/images/shadow_circle_horiz.png
new file mode 100644
index 0000000..f5fcc5c
Binary files /dev/null and b/data/themes/images/shadow_circle_horiz.png differ
diff --git a/data/themes/images/shadow_circle_vert.png 
b/data/themes/images/shadow_circle_vert.png
new file mode 100644
index 0000000..f06b622
Binary files /dev/null and b/data/themes/images/shadow_circle_vert.png differ
diff --git a/data/themes/images/tile.png b/data/themes/images/tile.png
new file mode 100644
index 0000000..219cc80
Binary files /dev/null and b/data/themes/images/tile.png differ
diff --git a/src/bin/ephoto_directory_browser.c 
b/src/bin/ephoto_directory_browser.c
new file mode 100644
index 0000000..7295193
--- /dev/null
+++ b/src/bin/ephoto_directory_browser.c
@@ -0,0 +1,1200 @@
+#include "ephoto.h"
+
+#define FILESEP             "file://"
+#define FILESEP_LEN         sizeof(FILESEP) - 1
+
+#define TODO_ITEM_MIN_BATCH 5
+
+#define ANIM_TIME           0.2
+
+typedef struct _Ephoto_Directory_Browser Ephoto_Directory_Browser;
+
+struct _Ephoto_Directory_Browser
+{
+   Ephoto *ephoto;
+   Evas_Object *main;
+   Evas_Object *fsel;
+   Evas_Object *fsel_back;
+   Evas_Object *leftbox;
+   Elm_Object_Item *dir_current;
+   Elm_Object_Item *last_sel;
+   Eio_File *ls;
+   Eina_Bool dirs_only;
+   Eina_Bool thumbs_only;
+   Ecore_File_Monitor *monitor;
+   Eina_List *handlers;
+   Eina_List *todo_items;
+   Ecore_Job *change_dir_job;
+   Ecore_Timer *click_timer;
+   Eina_Bool dragging;
+   Eina_Bool processing;
+   Eina_Bool initializing;
+   struct
+   {
+      Ecore_Animator *todo_items;
+      int count;
+      int processed;
+   } animator;
+   Eina_Bool main_deleted:1;
+   const char *back_directory;
+};
+
+static Elm_Genlist_Item_Class _ephoto_dir_class;
+
+static char * _drag_data_extract(char **drag_data);
+
+static void _fsel_mouse_up_cb(void *data, Evas *e EINA_UNUSED,
+    Evas_Object *obj EINA_UNUSED, void *event_info);
+
+/*File Pane Callbacks*/
+static void
+_menu_dismissed_cb(void *data, Evas_Object *obj,
+    void *event_info EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+
+   db->ephoto->menu_blocking = EINA_FALSE;
+   evas_object_del(obj);
+   elm_object_focus_set(db->main, EINA_TRUE);
+}
+
+static void
+_menu_empty_cb(void *data, Evas_Object *obj EINA_UNUSED,
+    void *event_info EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+   Eina_List *paths = NULL;
+   Elm_Object_Item *item;
+   Ephoto_Entry *file;
+   
+   item = elm_genlist_first_item_get(db->fsel);
+   while (item)
+     {
+        file = elm_object_item_data_get(item);
+        paths = eina_list_append(paths, strdup(file->path));
+        item = elm_genlist_item_next_get(item);
+     }
+   if (eina_list_count(paths) <= 0)
+     return;
+   ephoto_file_empty_trash(db->ephoto, paths);
+}
+
+static Eina_Bool
+_drop_dropcb(void *data EINA_UNUSED, Evas_Object *obj, Elm_Object_Item *it,
+    Elm_Selection_Data *ev, int xposret EINA_UNUSED, int yposret EINA_UNUSED)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(it, EINA_TRUE);
+
+   Ephoto_Entry *entry = elm_object_item_data_get(it);
+   const char *path = entry->path;
+   Eina_List *files = NULL;
+   Ephoto_Directory_Browser *db = evas_object_data_get(obj, 
"directory_browser");
+
+   if (!ev->data)
+      return EINA_FALSE;
+   if (ev->len <= 0)
+      return EINA_FALSE;
+   if (!path)
+      return EINA_FALSE;
+
+   char *dd = strdup(ev->data);
+
+   if (!dd)
+      return EINA_FALSE;
+
+   char *s = _drag_data_extract(&dd);
+
+   while (s)
+     {
+       files = eina_list_append(files, s);
+       s = _drag_data_extract(&dd);
+     }
+   free(dd);
+
+   if (db->ephoto->config->move_drop)
+     ephoto_file_move(db->ephoto, files, path);
+   else
+     ephoto_file_copy(db->ephoto, files, path);
+   if (db->dir_current)
+     elm_genlist_item_selected_set(db->dir_current, EINA_TRUE);
+   return EINA_TRUE;
+}
+
+static Elm_Object_Item *
+_drop_item_getcb(Evas_Object *obj, Evas_Coord x, Evas_Coord y,
+    int *xposret EINA_UNUSED, int *yposret)
+{
+   Elm_Object_Item *gli;
+
+   gli = elm_genlist_at_xy_item_get(obj, x, y, yposret);
+
+   return gli;
+}
+
+static void
+_drop_enter(void *data, Evas_Object *obj EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+
+   if (db->dragging)
+     elm_object_cursor_set(db->main, ELM_CURSOR_TARGET);
+}
+
+static void
+_drop_leave(void *data, Evas_Object *obj EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+
+   if (db->dragging)
+     {
+        elm_object_cursor_set(db->main, ELM_CURSOR_HAND2);
+        if (db->dir_current)
+          elm_genlist_item_selected_set(db->dir_current, EINA_TRUE);
+     }
+}
+
+static void
+_drop_pos(void *data EINA_UNUSED, Evas_Object *cont EINA_UNUSED,
+    Elm_Object_Item *it EINA_UNUSED, Evas_Coord x EINA_UNUSED,
+    Evas_Coord y EINA_UNUSED, int xposret EINA_UNUSED,
+    int yposret EINA_UNUSED, Elm_Xdnd_Action action EINA_UNUSED)
+{
+   elm_genlist_item_selected_set(it, EINA_TRUE);
+}
+
+static char *
+_drag_data_extract(char **drag_data)
+{
+   char *uri = NULL;
+
+   if (!drag_data)
+      return uri;
+
+   char *p = *drag_data;
+
+   if (!p)
+      return uri;
+   char *s = strstr(p, FILESEP);
+
+   if (s)
+      p += FILESEP_LEN;
+   s = strchr(p, '\n');
+   uri = p;
+   if (s)
+     {
+       if (s - p > 0)
+         {
+            char *s1 = s - 1;
+
+            if (s1[0] == '\r')
+               s1[0] = '\0';
+            else
+              {
+                 char *s2 = s + 1;
+
+                 if (s2[0] == '\r')
+                   {
+                      s[0] = '\0';
+                      s++;
+                   }
+                  else
+                    s[0] = '\0';
+              }
+         }
+        else
+          s[0] = '\0';
+       s++;
+     }
+   else
+     p = NULL;
+   *drag_data = s;
+
+   return uri;
+}
+
+static int
+_entry_cmp(const void *pa, const void *pb)
+{
+   const Ephoto_Entry *a, *b;
+
+   a = elm_object_item_data_get(pa);
+   b = elm_object_item_data_get(pb);
+
+   return strcasecmp(a->basename, b->basename);
+}
+
+static void
+_on_list_expand_req(void *data, Evas_Object *obj EINA_UNUSED,
+    void *event_info)
+{
+   Ephoto_Directory_Browser *db = data;
+   Elm_Object_Item *it = event_info;
+
+   if (db->initializing)
+     return;
+
+   ecore_job_del(db->change_dir_job);
+   db->change_dir_job = NULL;
+   ecore_timer_del(db->click_timer);
+   db->click_timer = NULL;
+   elm_genlist_item_expanded_set(it, EINA_TRUE);
+}
+
+static void
+_on_list_contract_req(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
+    void *event_info)
+{
+   Ephoto_Directory_Browser *db = data;
+   Elm_Object_Item *it = event_info;
+
+   if (db->initializing)
+     return;
+
+   ecore_job_del(db->change_dir_job);
+   db->change_dir_job = NULL;
+   ecore_timer_del(db->click_timer);
+   db->click_timer = NULL;
+   elm_genlist_item_expanded_set(it, EINA_FALSE);
+}
+
+static void
+_on_list_expanded(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Ephoto_Directory_Browser *db = data;
+   Elm_Object_Item *it = event_info;
+   Ephoto_Entry *entry;
+   const char *path;
+
+   if (db->initializing)
+     return;
+
+   entry = elm_object_item_data_get(it);
+   path = entry->path;
+   db->dirs_only = 0;
+   if (!strcmp(path, db->ephoto->config->directory))
+     db->dirs_only = 1;
+   else
+     db->dirs_only = 0;
+   db->thumbs_only = 0;
+   ephoto_directory_set(db->ephoto, path, it, db->dirs_only, db->thumbs_only);
+   ephoto_title_set(db->ephoto, db->ephoto->config->directory);
+}
+
+static void
+_on_list_contracted(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Ephoto_Directory_Browser *db = data;
+   Elm_Object_Item *it = event_info;
+   Ephoto_Entry *entry;
+   const char *path;
+
+   if (db->initializing)
+     return;
+
+   entry = elm_object_item_data_get(it);
+   path = entry->path;
+   elm_genlist_item_subitems_clear(it);
+   if (!strcmp(path, db->ephoto->config->directory))
+     return;
+   db->thumbs_only = 1;
+   db->dirs_only = 0;
+   ephoto_directory_set(db->ephoto, path, NULL,
+       db->dirs_only, db->thumbs_only);
+   ephoto_title_set(db->ephoto,
+       db->ephoto->config->directory);
+}
+
+static void
+_dir_job(void *data)
+{
+   Elm_Object_Item *it = data;
+   Ephoto_Directory_Browser *db = evas_object_data_get(it, 
"directory_browser");
+   Ephoto_Entry *entry;
+   const char *path;
+
+   entry = elm_object_item_data_get(it);
+   path = entry->path;
+   db->change_dir_job = NULL;
+   db->thumbs_only = 1;
+   db->dirs_only = 0;
+   ephoto_directory_set(db->ephoto, path, NULL,
+       db->dirs_only, db->thumbs_only);
+   ephoto_title_set(db->ephoto, db->ephoto->config->directory);
+}
+
+static void
+_wait_job(void *data)
+{
+   Elm_Object_Item *it = data;
+   Ephoto_Directory_Browser *db = evas_object_data_get(it, 
"directory_browser");
+
+   if (db->change_dir_job)
+     ecore_job_del(db->change_dir_job);
+   db->change_dir_job = ecore_job_add(_dir_job, it);
+}
+
+static void
+_on_list_selected(void *data, Evas_Object *obj EINA_UNUSED,
+    void *event_info)
+{
+   Ephoto_Directory_Browser *db = data;
+   Elm_Object_Item *it = event_info;
+
+   evas_object_data_set(it, "directory_browser", db);
+   if (!db->dragging)
+     {
+        db->dir_current = it;
+
+        ecore_job_add(_wait_job, it);
+     }
+}
+
+static char *
+_dir_item_text_get(void *data, Evas_Object *obj EINA_UNUSED,
+    const char *part EINA_UNUSED)
+{
+   Ephoto_Entry *e = data;
+
+   return strdup(e->label);
+}
+
+static Evas_Object *
+_dir_item_icon_get(void *data EINA_UNUSED, Evas_Object *obj,
+    const char *part)
+{
+   if (!strcmp(part, "elm.swallow.end"))
+      return NULL;
+   Evas_Object *ic = elm_icon_add(obj);
+
+   elm_icon_order_lookup_set(ic, ELM_ICON_LOOKUP_FDO_THEME);
+   elm_icon_standard_set(ic, "folder");
+   return ic;
+}
+
+static void
+_dir_item_del(void *data, Evas_Object *obj EINA_UNUSED)
+{
+   Ephoto_Entry *e = data;
+
+   if (!e->no_delete)
+     ephoto_entry_free(e->ephoto, e);
+}
+
+static Eina_Bool
+_check_for_subdirs(Ephoto_Entry *entry)
+{
+   Eina_Iterator *ls = eina_file_direct_ls(entry->path);
+   Eina_File_Direct_Info *info;
+
+   if (!ls)
+     return EINA_FALSE;
+   EINA_ITERATOR_FOREACH(ls, info)
+     {
+        if (info->type == EINA_FILE_DIR)
+          {
+             eina_iterator_free(ls);
+             return EINA_TRUE;
+          }
+     }
+   eina_iterator_free(ls);
+   return EINA_FALSE;
+}
+
+static void
+_trash_back(void *data, Evas_Object *obj EINA_UNUSED,
+    void *event_info EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+
+   elm_box_clear(db->leftbox);
+   db->fsel = db->fsel_back;
+   elm_box_pack_end(db->leftbox, db->fsel);
+   evas_object_show(db->fsel);
+   db->fsel_back = NULL;
+
+   db->thumbs_only = 1;
+   db->dirs_only = 0;
+   ephoto_directory_set(db->ephoto, db->back_directory, NULL,
+       db->dirs_only, db->thumbs_only);
+   ephoto_title_set(db->ephoto, db->back_directory);
+}
+
+static void
+_dir_go_trash(void *data, Evas_Object *obj EINA_UNUSED,
+    void *event_info EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+   char path[PATH_MAX];
+   Evas_Object *ic, *but;
+
+   db->fsel_back = db->fsel;
+   evas_object_hide(db->fsel_back);
+   elm_box_unpack(db->leftbox, db->fsel_back);
+
+   ic = elm_icon_add(db->leftbox);
+   evas_object_size_hint_min_set(ic, 20*elm_config_scale_get(),
+       20*elm_config_scale_get());
+   elm_icon_order_lookup_set(ic, ELM_ICON_LOOKUP_FDO_THEME);
+   elm_icon_standard_set(ic, "go-previous");
+   evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_BOTH, 1, 1);
+   
+   but = elm_button_add(db->leftbox);
+   elm_object_text_set(but, _("Back"));
+   elm_object_part_content_set(but, "icon", ic);
+   evas_object_size_hint_weight_set(but, EVAS_HINT_EXPAND, 0.0);
+   evas_object_size_hint_fill_set(but, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_smart_callback_add(but, "clicked", _trash_back, db);
+   elm_box_pack_end(db->leftbox, but);
+   evas_object_show(but);
+
+   db->fsel = elm_genlist_add(db->leftbox);
+   elm_genlist_homogeneous_set(db->fsel, EINA_FALSE);
+   elm_genlist_select_mode_set(db->fsel, ELM_OBJECT_SELECT_MODE_ALWAYS);
+   evas_object_size_hint_weight_set(db->fsel, EVAS_HINT_EXPAND,
+       EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(db->fsel, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_smart_callback_add(db->fsel, "expand,request",
+       _on_list_expand_req, db);
+   evas_object_smart_callback_add(db->fsel, "contract,request",
+       _on_list_contract_req, db);
+   evas_object_smart_callback_add(db->fsel, "expanded", _on_list_expanded, db);
+   evas_object_smart_callback_add(db->fsel, "contracted", _on_list_contracted,
+       db);
+   evas_object_event_callback_add(db->fsel, EVAS_CALLBACK_MOUSE_UP,
+       _fsel_mouse_up_cb, db);
+   evas_object_data_set(db->fsel, "directory_browser", db);
+   evas_object_size_hint_min_set(db->fsel, (int)round(195 * 
elm_config_scale_get()), 0);
+   elm_box_pack_end(db->leftbox, db->fsel);
+   evas_object_show(db->fsel);
+
+   eina_stringshare_replace(&db->back_directory,
+       db->ephoto->config->directory);
+   snprintf(path, PATH_MAX, "%s/.config/ephoto/trash", getenv("HOME"));
+   if (!ecore_file_exists(path))
+      ecore_file_mkpath(path);
+   db->thumbs_only = 0;
+   db->dirs_only = 0;
+   ephoto_directory_set(db->ephoto, path, NULL,
+       db->dirs_only, db->thumbs_only);
+   ephoto_title_set(db->ephoto, _("Trash"));
+   ephoto_directory_browser_top_dir_set(db->ephoto, 
db->ephoto->config->directory);
+}
+
+static Eina_Bool
+_click_timer_cb(void *data)
+{
+   Elm_Object_Item *item = data;
+   Ephoto_Directory_Browser *db = evas_object_data_get(item, 
"directory_browser");
+
+   _on_list_selected(db, NULL, item);
+   db->click_timer = NULL;
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_fsel_menu_new_dir_cb(void *data, Evas_Object *obj EINA_UNUSED,
+    void *event_info EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+   Elm_Object_Item *item = elm_genlist_selected_item_get(db->fsel);
+   Ephoto_Entry *entry;
+   const char *path;
+
+   if (item)
+     {
+        entry = elm_object_item_data_get(item);
+        path = entry->path;
+     }
+   else
+     path = db->ephoto->config->directory;
+   if (!path)
+     return;
+   ephoto_file_new_dir(db->ephoto, path);
+}
+
+static void
+_fsel_menu_paste_cb(void *data, Evas_Object *obj EINA_UNUSED,
+    void *event_info EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+   Elm_Object_Item *item = elm_genlist_selected_item_get(db->fsel);
+
+   ephoto_thumb_browser_paste(db->ephoto, item);
+}
+
+static void
+_fsel_menu_rename_cb(void *data, Evas_Object *obj EINA_UNUSED,
+    void *event_info EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+   Elm_Object_Item *item = elm_genlist_selected_item_get(db->fsel);
+   Ephoto_Entry *entry;
+   const char *path;
+
+   if (!item)
+     return;
+   entry = elm_object_item_data_get(item);
+   path = entry->path;
+   if (!path)
+     return;
+   ephoto_file_rename(db->ephoto, path);
+}
+
+static void
+_fsel_menu_delete_cb(void *data, Evas_Object *obj EINA_UNUSED,
+    void *event_info EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+   Elm_Object_Item *item = elm_genlist_selected_item_get(db->fsel);
+   Ephoto_Entry *entry;
+   Eina_List *files = NULL;
+   const char *path;
+
+   if (!item)
+     return;
+   entry = elm_object_item_data_get(item);
+   path = entry->path;
+   if (!path)
+     return;
+   files = eina_list_append(files, path);
+   ephoto_file_delete(db->ephoto, files, EINA_FILE_DIR);
+}
+
+static void
+_fsel_mouse_up_cb(void *data, Evas *e EINA_UNUSED,
+    Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Ephoto_Directory_Browser *db = data;
+   Evas_Object *menu;
+   Elm_Object_Item *item, *menu_it;
+   Evas_Event_Mouse_Up *info = event_info;
+   char trash[PATH_MAX];
+   Evas_Coord x, y;
+
+   evas_pointer_canvas_xy_get(evas_object_evas_get(db->fsel), &x, &y);
+   item = elm_genlist_at_xy_item_get(db->fsel, x, y, 0);
+
+   if (info->button == 1 && item)
+     {
+        if (info->flags == EVAS_BUTTON_DOUBLE_CLICK)
+          {
+             if (elm_genlist_item_type_get(item) == ELM_GENLIST_ITEM_TREE)
+               {
+                  if (db->click_timer)
+                    {
+                       ecore_timer_del(db->click_timer);
+                       db->click_timer = NULL;
+                       elm_genlist_item_expanded_set(item,
+                           !elm_genlist_item_expanded_get(item));
+                    }
+               }
+          }
+        else
+          {
+             evas_object_data_set(item, "directory_browser", db);
+             if (elm_genlist_item_type_get(item) == ELM_GENLIST_ITEM_TREE)
+               db->click_timer = ecore_timer_add(.3, _click_timer_cb, item);
+             else
+               _on_list_selected(db, NULL, item);
+          }
+     }
+   else if (!item)
+     {
+        Elm_Object_Item *it;
+
+        it = elm_genlist_selected_item_get(db->fsel);
+        if (it)
+          elm_genlist_item_selected_set(it, EINA_FALSE);
+        ephoto_directory_set(db->ephoto, db->ephoto->top_directory, NULL, 0, 
1);
+     }
+
+   if (info->button != 3)
+      return;
+
+   snprintf(trash, PATH_MAX, "%s/.config/ephoto/trash", getenv("HOME"));
+
+   if (item)
+      elm_genlist_item_selected_set(item, EINA_TRUE);
+
+   db->ephoto->menu_blocking = EINA_TRUE;
+
+   menu = elm_menu_add(db->ephoto->win);
+   elm_menu_move(menu, x, y);
+
+   menu_it = elm_menu_item_add(menu, NULL, "document-properties", _("Edit"),
+       NULL, NULL);
+   if (strcmp(db->ephoto->config->directory, trash))
+     {
+        elm_menu_item_add(menu, menu_it, "folder-new", _("New Folder"),
+              _fsel_menu_new_dir_cb, db);
+     }
+   if (item)
+     {
+        evas_object_data_set(item, "directory_browser", db);
+        elm_menu_item_add(menu, menu_it, "edit", _("Rename"),
+            _fsel_menu_rename_cb, item);
+       elm_menu_item_add(menu, menu_it, "edit-paste", _("Paste"),
+           _fsel_menu_paste_cb, db);
+     }
+   else if (!strcmp(db->ephoto->config->directory, trash) &&
+     elm_genlist_first_item_get(db->fsel))
+     {
+        elm_menu_item_add(menu, menu_it, "edit-delete", _("Empty Trash"),
+            _menu_empty_cb, db);
+     }
+   if (strcmp(db->ephoto->config->directory, trash) && item)
+     {
+        elm_menu_item_add(menu, menu_it, "edit-delete", _("Delete"),
+             _fsel_menu_delete_cb, db);
+        elm_menu_item_separator_add(menu, NULL);
+        menu_it = elm_menu_item_add(menu, NULL, "user-trash", _("Trash"),
+            _dir_go_trash, db);
+     }
+   evas_object_smart_callback_add(menu, "dismissed", _menu_dismissed_cb,
+            db);
+   evas_object_show(menu);
+}
+
+static void
+_ephoto_directory_view_add(Ephoto_Directory_Browser *db)
+{
+   Edje_Message_Int_Set *msg;
+
+   msg = alloca(sizeof(Edje_Message_Int_Set) + (1 * sizeof(int)));
+   msg->count = 1;
+   msg->val[0] = (int)round(220 * elm_config_scale_get());
+   edje_object_message_send(elm_layout_edje_get(db->ephoto->layout),
+       EDJE_MESSAGE_INT_SET, 2, msg);
+
+   db->leftbox = elm_box_add(db->main);
+   elm_box_horizontal_set(db->leftbox, EINA_FALSE);
+   elm_box_homogeneous_set(db->leftbox, EINA_FALSE);
+   elm_box_padding_set(db->leftbox, 0, -5);
+   evas_object_size_hint_weight_set(db->leftbox, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(db->leftbox,
+       EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(db->main, db->leftbox);
+   evas_object_show(db->leftbox);
+
+   db->fsel = elm_genlist_add(db->leftbox);
+   elm_genlist_homogeneous_set(db->fsel, EINA_FALSE);
+   elm_genlist_select_mode_set(db->fsel, ELM_OBJECT_SELECT_MODE_ALWAYS);
+   evas_object_size_hint_weight_set(db->fsel, EVAS_HINT_EXPAND,
+       EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(db->fsel, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_smart_callback_add(db->fsel, "expand,request",
+       _on_list_expand_req, db);
+   evas_object_smart_callback_add(db->fsel, "contract,request",
+       _on_list_contract_req, db);
+   evas_object_smart_callback_add(db->fsel, "expanded", _on_list_expanded, db);
+   evas_object_smart_callback_add(db->fsel, "contracted", _on_list_contracted,
+       db);
+   evas_object_event_callback_add(db->fsel, EVAS_CALLBACK_MOUSE_UP,
+       _fsel_mouse_up_cb, db);
+   evas_object_data_set(db->fsel, "directory_browser", db);
+   evas_object_size_hint_min_set(db->fsel, (int)round(195 * 
elm_config_scale_get()), 0);
+   elm_box_pack_end(db->leftbox, db->fsel);
+   evas_object_show(db->fsel);
+
+   elm_drop_item_container_add(db->fsel, ELM_SEL_FORMAT_TARGETS,
+       _drop_item_getcb, _drop_enter, db, _drop_leave, db, _drop_pos, db,
+       _drop_dropcb, NULL);
+}
+
+/*Ephoto Populating Functions*/
+static void
+_todo_items_free(Ephoto_Directory_Browser *db)
+{
+   eina_list_free(db->todo_items);
+   db->todo_items = NULL;
+}
+
+static void
+_monitor_cb(void *data, Ecore_File_Monitor *em EINA_UNUSED,
+    Ecore_File_Event event, const char *path)
+{
+   Elm_Object_Item *item;
+   Ephoto_Entry *entry = data;
+   Ephoto_Entry *e;
+   char file[PATH_MAX], dir[PATH_MAX];
+   const Elm_Genlist_Item_Class *ic;
+   char buf[PATH_MAX];
+
+   if (!entry)
+     return;
+
+   snprintf(file, PATH_MAX, "%s", path);
+   snprintf(dir, PATH_MAX, "%s", ecore_file_dir_get(file));
+
+   if (strcmp(entry->path, dir))
+     return;
+   if (event == ECORE_FILE_EVENT_CREATED_DIRECTORY)
+     {
+        if (!ecore_file_is_dir(path))
+          return;
+        if (ephoto_entry_exists(entry->ephoto, path))
+          return;
+ 
+        if (elm_genlist_item_type_get(entry->item) == ELM_GENLIST_ITEM_TREE &&
+            elm_genlist_item_expanded_get(entry->item) == EINA_TRUE)
+          {
+             ic = &_ephoto_dir_class;
+             snprintf(buf, PATH_MAX, "%s", path);
+             e = ephoto_entry_new(entry->ephoto, path, basename(buf),
+                 EINA_FILE_DIR);
+             e->genlist = entry->genlist;
+             e->parent = entry->item;
+             e->item =
+                 elm_genlist_item_sorted_insert(entry->genlist, ic, e,
+                 e->parent, ELM_GENLIST_ITEM_NONE, _entry_cmp, NULL, NULL);
+             if (e->item)
+               e->monitor = ecore_file_monitor_add(e->path, _monitor_cb, e);
+          }
+        if (elm_genlist_item_type_get(entry->item) == ELM_GENLIST_ITEM_NONE)
+          {
+             Elm_Object_Item *parent;
+
+             ic = &_ephoto_dir_class;
+             parent =
+                 elm_genlist_item_insert_before(entry->genlist, ic, entry,
+                     entry->parent, entry->item, ELM_GENLIST_ITEM_TREE, NULL, 
NULL);
+             entry->no_delete = EINA_TRUE;
+             if (entry->monitor)
+               ecore_file_monitor_del(entry->monitor);
+             elm_object_item_del(entry->item);
+             entry->item = parent;
+             entry->no_delete = EINA_FALSE;
+             entry->monitor = ecore_file_monitor_add(entry->path, _monitor_cb, 
entry);
+          }
+        return;
+     }
+   else if (event == ECORE_FILE_EVENT_DELETED_DIRECTORY)
+     {
+        item = elm_genlist_first_item_get(entry->genlist);
+        while (item)
+          {
+             e = elm_object_item_data_get(item);
+             if (!strcmp(e->path, path))
+               {
+                  elm_object_item_del(e->item);
+                  //if (!strcmp(e->path, e->ephoto->config->directory))
+                  break;
+               }
+             item = elm_genlist_item_next_get(item);
+          }
+        if (elm_genlist_item_type_get(entry->item) == ELM_GENLIST_ITEM_TREE &&
+            _check_for_subdirs(entry) == EINA_FALSE)
+          {
+             Elm_Object_Item *parent;
+
+             ic = &_ephoto_dir_class;
+             parent =
+                 elm_genlist_item_insert_before(entry->genlist, ic, entry,
+                 entry->parent, entry->item, ELM_GENLIST_ITEM_NONE, NULL, 
NULL);
+             entry->no_delete = EINA_TRUE;
+             elm_object_item_del(entry->item);
+             entry->item = parent;
+             entry->no_delete = EINA_FALSE;
+          }
+        if (!ecore_file_exists(entry->ephoto->config->directory))
+          {
+             ephoto_directory_set(entry->ephoto, entry->path, entry->parent, 
0, 1);
+             ephoto_title_set(entry->ephoto, entry->path);
+          }
+        return;
+     }
+   else if (event == ECORE_FILE_EVENT_MODIFIED)
+     {
+        if (!ecore_file_is_dir(path))
+          return;
+        if ((elm_genlist_item_expanded_get(entry->item) == EINA_TRUE))
+          {
+             item = elm_genlist_first_item_get(entry->genlist);
+             while (item)
+               {
+                  e = elm_object_item_data_get(item);
+                  if (!strcmp(e->path, path))
+                    {
+                       elm_genlist_item_update(e->item);
+                       break;
+                    }
+                  item = elm_genlist_item_next_get(item);
+               }
+          }
+        return;
+     }
+}
+
+static void
+_top_monitor_cb(void *data, Ecore_File_Monitor *em EINA_UNUSED,
+    Ecore_File_Event event, const char *path)
+{
+   Elm_Object_Item *item;
+   Ephoto_Directory_Browser *db = data;
+   Ephoto_Entry *e;
+   const Elm_Genlist_Item_Class *ic;
+   char buf[PATH_MAX], file[PATH_MAX], dir[PATH_MAX];
+
+   if (!db)
+     return;
+   snprintf(file, PATH_MAX, "%s", path);
+   snprintf(dir, PATH_MAX, "%s", ecore_file_dir_get(file));
+
+   if (strcmp(db->ephoto->top_directory, dir))
+     return;
+   if (event == ECORE_FILE_EVENT_CREATED_DIRECTORY)
+     {
+       if (!ecore_file_is_dir(path))
+         return; 
+        if (ephoto_entry_exists(db->ephoto, path))
+          return;
+        snprintf(buf, PATH_MAX, "%s", path);
+        e = ephoto_entry_new(db->ephoto, path, basename(buf),
+            EINA_FILE_DIR);
+        e->genlist = db->fsel;
+        ic = &_ephoto_dir_class;
+        e->item =
+            elm_genlist_item_append(db->fsel, ic, e,
+            NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+        if (e->item)
+          e->monitor = ecore_file_monitor_add(e->path, _monitor_cb, e);
+        return;
+     }
+   else if (event == ECORE_FILE_EVENT_DELETED_DIRECTORY)
+     {
+        item = elm_genlist_first_item_get(db->fsel);
+        while (item)
+          {
+             e = elm_object_item_data_get(item);
+             if (!strcmp(e->path, path))
+               {
+                  if (!strcmp(path, db->ephoto->config->directory))
+                    elm_genlist_item_expanded_set(e->parent, EINA_TRUE);
+                  else
+                    elm_object_item_del(e->item);
+                  break;
+               }
+             item = elm_genlist_item_next_get(item);
+          }
+        return;
+     }
+   else if (event == ECORE_FILE_EVENT_MODIFIED)
+     {
+        if (!ecore_file_is_dir(path))
+          return;
+        item = elm_genlist_first_item_get(db->fsel);
+        while (item)
+          {
+             e = elm_object_item_data_get(item);
+             if (!strcmp(e->path, path))
+               {
+                  elm_genlist_item_update(e->item);
+                  break;
+               }
+             item = elm_genlist_item_next_get(item);
+          }
+        return;
+     }
+}
+
+static Eina_Bool
+_todo_items_process(void *data)
+{
+   Ephoto_Directory_Browser *db = data;
+   Ephoto_Entry *entry;
+   int i = 0;
+
+   if ((!db->ls) && (db->animator.processed == db->animator.count))
+     {
+        if (db->animator.count == 0)
+          return EINA_TRUE;
+        db->animator.todo_items = NULL;
+        db->processing = 0;
+       return EINA_FALSE;
+     }
+   if ((db->ls) && (eina_list_count(db->todo_items) < TODO_ITEM_MIN_BATCH))
+      return EINA_TRUE;
+
+   db->animator.todo_items = NULL;
+   db->processing = 1;
+   EINA_LIST_FREE(db->todo_items, entry)
+   {
+      i++;
+      if (i > TODO_ITEM_MIN_BATCH)
+        return EINA_TRUE;
+      if (entry->is_dir && !entry->item)
+        {
+          const Elm_Genlist_Item_Class *ic;
+
+          ic = &_ephoto_dir_class;
+          if (_check_for_subdirs(entry))
+             entry->item =
+                 elm_genlist_item_sorted_insert(db->fsel, ic, entry,
+                 entry->parent, ELM_GENLIST_ITEM_TREE, _entry_cmp, NULL, NULL);
+           else
+             entry->item =
+                 elm_genlist_item_sorted_insert(db->fsel, ic, entry,
+                 entry->parent, ELM_GENLIST_ITEM_NONE, _entry_cmp, NULL, NULL);
+          if (!entry->item)
+            {
+               ephoto_entry_free(db->ephoto, entry);
+            }
+           else
+             {
+               entry->monitor = ecore_file_monitor_add(entry->path, 
_monitor_cb, entry);
+               entry->genlist = db->fsel;
+             }
+        }
+      db->animator.processed++;
+   }
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_ephoto_dir_populate_start(void *data, int type EINA_UNUSED,
+    void *event EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+
+   evas_object_smart_callback_call(db->main, "changed,directory", NULL);
+
+   db->animator.processed = 0;
+   db->animator.count = 0;
+   _todo_items_free(db);
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_ephoto_dir_populate_end(void *data, int type EINA_UNUSED,
+    void *event EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+
+   db->ls = NULL;
+   if (db->main_deleted)
+     {
+       free(db);
+       return ECORE_CALLBACK_PASS_ON;
+     }
+   db->dirs_only = 0;
+   db->thumbs_only = 0;
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_ephoto_dir_populate_error(void *data, int type EINA_UNUSED,
+    void *event EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+
+   db->dirs_only = 0;
+   db->thumbs_only = 0;
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_ephoto_dir_entry_create(void *data, int type EINA_UNUSED, void *event)
+{
+   Ephoto_Directory_Browser *db = data;
+   Ephoto_Event_Entry_Create *ev = event;
+   Ephoto_Entry *e;
+
+   e = ev->entry;
+   if (e->is_dir)
+     {
+       db->todo_items = eina_list_append(db->todo_items, e);
+       db->animator.count++;
+     }
+   if (!db->animator.todo_items)
+      db->animator.todo_items = ecore_animator_add(_todo_items_process, db);
+
+   return ECORE_CALLBACK_PASS_ON;
+}
+
+/*Ephoto Directory Browser Main Callbacks*/
+static void
+_ephoto_main_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
+    void *event_info EINA_UNUSED)
+{
+   Ephoto_Directory_Browser *db = data;
+   Ecore_Event_Handler *handler;
+
+   _todo_items_free(db);
+   EINA_LIST_FREE(db->handlers, handler) ecore_event_handler_del(handler);
+   if (db->animator.todo_items)
+     {
+       ecore_animator_del(db->animator.todo_items);
+       db->animator.todo_items = NULL;
+     }
+   if (db->ls)
+     {
+       db->main_deleted = EINA_TRUE;
+       eio_file_cancel(db->ls);
+       return;
+     }
+   if (db->monitor)
+     ecore_file_monitor_del(db->monitor);
+   free(db);
+}
+
+void
+ephoto_directory_browser_top_dir_set(Ephoto *ephoto, const char *dir)
+{
+   Ephoto_Directory_Browser *db =
+       evas_object_data_get(ephoto->dir_browser, "directory_browser");
+
+   if (db->monitor)
+     ecore_file_monitor_del(db->monitor);
+   if (ephoto->top_directory)
+     eina_stringshare_replace(&ephoto->top_directory, dir);
+   else
+     ephoto->top_directory = eina_stringshare_add(dir);
+   db->monitor = ecore_file_monitor_add(dir, _top_monitor_cb, db);
+}
+
+void
+ephoto_directory_browser_initialize_structure(Ephoto *ephoto)
+{
+   Ephoto_Directory_Browser *db =
+       evas_object_data_get(ephoto->dir_browser, "directory_browser");
+   Eina_List *dirs = NULL, *l;
+   Elm_Object_Item *next = NULL, *cur = NULL;
+   char path[PATH_MAX], *dir;
+
+   db->initializing = EINA_TRUE;
+   snprintf(path, PATH_MAX, "%s", ephoto->config->directory);
+   dirs = eina_list_prepend(dirs, strdup(path));
+   dir = strdup(path);
+   while (strcmp(dir, "/"))
+     {
+        if (dir)
+          {
+             free(dir);
+             dir = NULL;
+          }
+        dir = ecore_file_dir_get(path);
+        dirs = eina_list_prepend(dirs, strdup(dir));
+        memset(path, 0x00, sizeof(path));
+        snprintf(path, PATH_MAX, "%s", dir);
+     }
+   if (dir)
+     {
+        free(dir);
+        dir = NULL;
+     }
+   EINA_LIST_FOREACH(dirs, l, dir)
+     {
+        Eina_Iterator *it;
+        Eina_File_Direct_Info *finfo;
+        const char *n = eina_list_data_get(eina_list_next(l));
+
+        it = eina_file_direct_ls(dir);
+         EINA_ITERATOR_FOREACH(it, finfo)
+          {
+             cur = next;
+             if (finfo->type == EINA_FILE_DIR && 
+                 strncmp(finfo->path + finfo->name_start, ".", 1))
+               {
+                  Ephoto_Entry *entry = ephoto_entry_new(db->ephoto, 
finfo->path,
+                      finfo->path+finfo->name_start, finfo->type);
+                  entry->parent = cur;
+                  if (entry->is_dir && !entry->item)
+                    {
+                       const Elm_Genlist_Item_Class *ic;
+                       ic = &_ephoto_dir_class;
+                       if (_check_for_subdirs(entry))
+                         entry->item =
+                             elm_genlist_item_sorted_insert(db->fsel, ic, 
entry,
+                             entry->parent, ELM_GENLIST_ITEM_TREE, _entry_cmp, 
NULL, NULL);
+                       else
+                         entry->item =
+                             elm_genlist_item_sorted_insert(db->fsel, ic, 
entry,
+                             entry->parent, ELM_GENLIST_ITEM_NONE, _entry_cmp, 
NULL, NULL);
+                       if (!entry->item)
+                         {
+                            ephoto_entry_free(db->ephoto, entry);
+                         }
+                       else
+                         {
+                            entry->monitor = 
ecore_file_monitor_add(entry->path, _monitor_cb, entry);
+                            entry->genlist = db->fsel;
+                         }
+                       if (n)
+                         {
+                            if (!strcmp(n, entry->path))
+                              {
+                                 next = entry->item;
+                                 elm_genlist_item_expanded_set(next, 
EINA_TRUE);
+                              }
+                         }
+                    }
+               }
+          }
+        free(dir);  
+     }
+   ephoto_directory_set(db->ephoto, db->ephoto->config->directory, next, 
EINA_FALSE, EINA_TRUE);
+   ephoto_directory_browser_top_dir_set(db->ephoto, "/");
+   db->initializing = EINA_FALSE;
+}
+
+Evas_Object *
+ephoto_directory_browser_add(Ephoto *ephoto, Evas_Object *parent)
+{
+   Evas_Object *box = elm_box_add(parent);
+   Ephoto_Directory_Browser *db;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(box, NULL);
+
+   db = calloc(1, sizeof(Ephoto_Directory_Browser));
+   EINA_SAFETY_ON_NULL_GOTO(db, error);
+
+   _ephoto_dir_class.item_style = "tree_effect";
+   _ephoto_dir_class.func.text_get = _dir_item_text_get;
+   _ephoto_dir_class.func.content_get = _dir_item_icon_get;
+   _ephoto_dir_class.func.state_get = NULL;
+   _ephoto_dir_class.func.del = _dir_item_del;
+
+   db->ephoto = ephoto;
+   db->dir_current = NULL;
+   db->main = box;
+
+   elm_box_horizontal_set(db->main, EINA_FALSE);
+   evas_object_size_hint_weight_set(db->main, EVAS_HINT_EXPAND,
+       EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(db->main, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_event_callback_add(db->main, EVAS_CALLBACK_DEL,
+       _ephoto_main_del, db);
+   evas_object_size_hint_min_set(db->main, (int)round(195 * 
elm_config_scale_get()), 0);
+   evas_object_data_set(db->main, "directory_browser", db);
+
+   _ephoto_directory_view_add(db);
+
+   db->handlers =
+       eina_list_append(db->handlers,
+       ecore_event_handler_add(EPHOTO_EVENT_POPULATE_START,
+          _ephoto_dir_populate_start, db));
+
+   db->handlers =
+       eina_list_append(db->handlers,
+       ecore_event_handler_add(EPHOTO_EVENT_POPULATE_END,
+          _ephoto_dir_populate_end, db));
+
+   db->handlers =
+       eina_list_append(db->handlers,
+       ecore_event_handler_add(EPHOTO_EVENT_POPULATE_ERROR,
+          _ephoto_dir_populate_error, db));
+
+   db->handlers =
+       eina_list_append(db->handlers,
+       ecore_event_handler_add(EPHOTO_EVENT_ENTRY_CREATE,
+          _ephoto_dir_entry_create, db));
+
+   return db->main;
+
+  error:
+   evas_object_del(db->main);
+   return NULL;
+}

-- 


Reply via email to